Skip to content

Commit dc6eede

Browse files
authored
fix: JDBCApiKeyStore (membrane#1920)
* fix: JDBCApiKeyStore * fix: JDBCApiKeyStore * fix: JDBCApiKeyStore * fix: JDBCApiKeyStore * wip * add doc * add doc * wip
1 parent f42d4e0 commit dc6eede

File tree

1 file changed

+63
-18
lines changed

1 file changed

+63
-18
lines changed

core/src/main/java/com/predic8/membrane/core/interceptor/apikey/stores/JDBCApiKeyStore.java

Lines changed: 63 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
package com.predic8.membrane.core.interceptor.apikey.stores;
1616

17+
import com.predic8.membrane.annot.MCAttribute;
1718
import com.predic8.membrane.annot.MCChildElement;
1819
import com.predic8.membrane.annot.MCElement;
1920
import com.predic8.membrane.core.Router;
@@ -22,15 +23,30 @@
2223
import org.jetbrains.annotations.NotNull;
2324

2425
import java.sql.*;
25-
import java.util.ArrayList;
26-
import java.util.List;
27-
import java.util.Optional;
26+
import java.util.*;
2827

28+
/**
29+
* @description <p>JDBC database store for API keys and their associated scopes.</p>
30+
* @topic 3. Security and Validation
31+
*/
2932
@MCElement(name = "databaseApiKeyStore")
3033
public class JDBCApiKeyStore extends AbstractJdbcSupport implements ApiKeyStore {
3134

3235
private KeyTable keyTable;
3336
private ScopeTable scopeTable;
37+
private boolean autoCreate = true;
38+
39+
private static final String CREATE_SCOPE_TABLE = """
40+
CREATE TABLE %s (
41+
apikey VARCHAR(255) NOT NULL REFERENCES %s (apikey),
42+
scope VARCHAR(255) NOT NULL
43+
)
44+
""";
45+
private static final String CREATE_KEY_TABLE = """
46+
CREATE TABLE %s (
47+
apikey VARCHAR(255) NOT NULL PRIMARY KEY
48+
)
49+
""";
3450

3551
@Override
3652
public void init(Router router) {
@@ -74,46 +90,75 @@ private void checkApiKey(String apiKey) throws Exception {
7490
}
7591

7692
private void createTablesIfNotExist() {
93+
if (!autoCreate) {
94+
return;
95+
}
96+
7797
try (Connection connection = getDatasource().getConnection()) {
78-
if (tableExists(connection, keyTable.getName())) {
79-
connection.createStatement().executeUpdate(String.format("""
80-
CREATE TABLE %s (
81-
apikey VARCHAR(255) NOT NULL PRIMARY KEY
82-
)
83-
""", keyTable.getName()));
98+
if (!tableExists(connection, keyTable.getName())) {
99+
createKeyTable(connection);
84100
}
85-
if (tableExists(connection, scopeTable.getName())) {
86-
connection.createStatement().executeUpdate(String.format("""
87-
CREATE TABLE %s (
88-
apikey VARCHAR(255) NOT NULL REFERENCES %s (apikey),
89-
scope VARCHAR(255) NOT NULL
90-
)
91-
""", scopeTable.getName(), keyTable.getName()));
101+
if (!tableExists(connection, scopeTable.getName())) {
102+
createScopeTable(connection);
92103
}
93104
} catch (Exception e) {
94-
throw new ConfigurationException("Failed to create tables for API Keys %s and %s: ".formatted(keyTable.getName(),scopeTable.getName()), e);
105+
throw new ConfigurationException("Failed to create tables for API Keys %s and %s: ".formatted(keyTable.getName(), scopeTable.getName()), e);
95106
}
96107
}
97108

109+
private void createKeyTable(Connection connection) throws SQLException {
110+
connection.createStatement().executeUpdate(CREATE_KEY_TABLE.formatted(keyTable.getName()));
111+
}
112+
113+
private void createScopeTable(Connection connection) throws SQLException {
114+
connection.createStatement().executeUpdate(CREATE_SCOPE_TABLE.formatted(scopeTable.getName(), keyTable.getName()));
115+
}
116+
98117
private boolean tableExists(Connection connection, String tableName) throws SQLException {
99-
return !connection.getMetaData().getTables(null, null, tableName.toUpperCase(), null).next();
118+
try (ResultSet rs = connection.getMetaData().getTables(null, connection.getSchema(), "%", new String[]{"TABLE"})) {
119+
while (rs.next()) {
120+
if (tableName.equalsIgnoreCase(rs.getString("TABLE_NAME"))) {
121+
return true;
122+
}
123+
}
124+
}
125+
return false;
100126
}
101127

128+
/**
129+
* @descriptio Table with the scopes.
130+
*/
102131
@MCChildElement(order = 0)
103132
public void setKeyTable(KeyTable keyTable) {
104133
this.keyTable = keyTable;
105134
}
106135

136+
/**
137+
* @description The table mapping API keys to their scopes.
138+
*/
107139
@MCChildElement(order = 1)
108140
public void setScopeTable(ScopeTable scopeTable) {
109141
this.scopeTable = scopeTable;
110142
}
111143

144+
/**
145+
* @description Whether the required tables should be created automatically on startup.
146+
* @default true
147+
*/
148+
@MCAttribute
149+
public void setAutoCreate(boolean autoCreate) {
150+
this.autoCreate = autoCreate;
151+
}
152+
112153
public KeyTable getKeyTable() {
113154
return keyTable;
114155
}
115156

116157
public ScopeTable getScopeTable() {
117158
return scopeTable;
118159
}
160+
161+
public boolean isAutoCreate() {
162+
return autoCreate;
163+
}
119164
}

0 commit comments

Comments
 (0)