Browse Source

implemented SqliteClientService

Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
sqlite
Stephan Richter 2 months ago
parent
commit
f0213512ad
  1. 2
      de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/ClientService.java
  2. 28
      de.srsoftware.oidc.api/src/test/java/de/srsoftware/oidc/api/ClientServiceTest.java
  3. 2
      de.srsoftware.oidc.app/src/main/java/de/srsoftware/oidc/app/Application.java
  4. 2
      de.srsoftware.oidc.backend/src/main/java/de/srsoftware/oidc/backend/ClientController.java
  5. 4
      de.srsoftware.oidc.datastore.file/src/main/java/de/srsoftware/oidc/datastore/file/FileStore.java
  6. 26
      de.srsoftware.oidc.datastore.file/src/test/java/de/srsoftware/oidc/datastore/file/FileStoreClientServiceTest.java
  7. 158
      de.srsoftware.oidc.datastore.sqlite/src/main/java/de/srsoftware/oidc/datastore/sqlite/SqliteClientService.java
  8. 26
      de.srsoftware.oidc.datastore.sqlite/src/test/java/de/srsoftware/oidc/datastore/sqlite/SqlteClientServiceTest.java

2
de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/ClientService.java

@ -8,6 +8,6 @@ import java.util.Optional; @@ -8,6 +8,6 @@ import java.util.Optional;
public interface ClientService {
Optional<Client> getClient(String clientId);
List<Client> listClients();
ClientService remove(Client client);
ClientService remove(String clientId);
ClientService save(Client client);
}

28
de.srsoftware.oidc.datastore.file/src/test/java/de/srsoftware/oidc/datastore/file/ClientServiceTest.java → de.srsoftware.oidc.api/src/test/java/de/srsoftware/oidc/api/ClientServiceTest.java

@ -1,34 +1,20 @@ @@ -1,34 +1,20 @@
/* © SRSoftware 2024 */
package de.srsoftware.oidc.datastore.file;
package de.srsoftware.oidc.api;
import static de.srsoftware.utils.Strings.uuid;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import de.srsoftware.oidc.api.ClientService;
import de.srsoftware.oidc.api.data.Client;
import java.io.File;
import java.io.IOException;
import java.util.Set;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class ClientServiceTest {
private static ClientService clientService;
private static final String NAME = "client-1";
private static final String URI = "uri-1";
private static final String URI2 = "uri-2";
@BeforeEach
public void setup() throws IOException {
var storage = new File("/tmp/" + UUID.randomUUID());
if (storage.exists()) storage.delete();
clientService = new FileStore(storage, null);
}
public abstract class ClientServiceTest {
private static final String NAME = "client-1";
private static final String URI = "uri-1";
private static final String URI2 = "uri-2";
protected ClientService clientService() {
return clientService;
}
protected abstract ClientService clientService();
@Test
public void testSaveAndList() {
@ -40,7 +26,7 @@ public class ClientServiceTest { @@ -40,7 +26,7 @@ public class ClientServiceTest {
var list = cs.save(client).listClients();
assertEquals(1, list.size());
assertTrue(list.contains(client));
cs.remove(client);
cs.remove(clientId);
assertTrue(cs.listClients().isEmpty());
}

2
de.srsoftware.oidc.app/src/main/java/de/srsoftware/oidc/app/Application.java

@ -84,7 +84,7 @@ public class Application { @@ -84,7 +84,7 @@ public class Application {
server.start();
}
private static ClientService setupClientService(Configuration config, Path defaultFile, FileStoreProvider fileStoreProvider) {
private static ClientService setupClientService(Configuration config, Path defaultFile, FileStoreProvider fileStoreProvider) throws SQLException {
var clientStore = new File(config.getOrDefault("client_store", defaultFile));
return switch (extension(clientStore)) {
case "db", "sqlite", "sqlite3" -> new SqliteClientService(connectionProvider.get(clientStore));

2
de.srsoftware.oidc.backend/src/main/java/de/srsoftware/oidc/backend/ClientController.java

@ -104,7 +104,7 @@ public class ClientController extends Controller { @@ -104,7 +104,7 @@ public class ClientController extends Controller {
if (!optUser.get().hasPermission(MANAGE_CLIENTS)) return badRequest(ex, "NOT ALLOWED");
var json = json(ex);
var id = json.getString(CLIENT_ID);
clients.getClient(id).ifPresent(clients::remove);
clients.remove(id);
return sendEmptyResponse(HTTP_OK, ex);
}

4
de.srsoftware.oidc.datastore.file/src/main/java/de/srsoftware/oidc/datastore/file/FileStore.java

@ -287,10 +287,10 @@ public class FileStore implements AuthorizationService, ClientService, SessionSe @@ -287,10 +287,10 @@ public class FileStore implements AuthorizationService, ClientService, SessionSe
}
@Override
public FileStore remove(Client client) {
public FileStore remove(String clientId) {
if (!json.has(CLIENTS)) return this;
var clients = json.getJSONObject(CLIENTS);
if (clients.has(client.id())) clients.remove(client.id());
if (clients.has(clientId)) clients.remove(clientId);
return save();
}

26
de.srsoftware.oidc.datastore.file/src/test/java/de/srsoftware/oidc/datastore/file/FileStoreClientServiceTest.java

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
/* © SRSoftware 2024 */
package de.srsoftware.oidc.datastore.file;
import de.srsoftware.oidc.api.ClientService;
import de.srsoftware.oidc.api.ClientServiceTest;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
public class FileStoreClientServiceTest extends ClientServiceTest {
private static ClientService clientService;
@BeforeEach
public void setup() throws IOException {
var storage = new File("/tmp/" + UUID.randomUUID());
if (storage.exists()) storage.delete();
clientService = new FileStore(storage, null);
}
@Override
protected ClientService clientService() {
return clientService;
}
}

158
de.srsoftware.oidc.datastore.sqlite/src/main/java/de/srsoftware/oidc/datastore/sqlite/SqliteClientService.java

@ -1,33 +1,173 @@ @@ -1,33 +1,173 @@
/* © SRSoftware 2024 */
package de.srsoftware.oidc.datastore.sqlite;
import static de.srsoftware.oidc.api.Constants.NAME;
import static de.srsoftware.oidc.api.Constants.SECRET;
import de.srsoftware.oidc.api.ClientService;
import de.srsoftware.oidc.api.data.Client;
import java.sql.Connection;
import java.util.List;
import java.util.Optional;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;
public class SqliteClientService extends SqliteStore implements ClientService {
private static final String STORE_VERSION = "client_store_version";
private static final String CREATE_STORE_VERSION = "INSERT INTO metainfo (key,value) VALUES ('" + STORE_VERSION + "','0')";
private static final String SELECT_STORE_VERSION = "SELECT * FROM metainfo WHERE key = '" + STORE_VERSION + "'";
private static final String SET_STORE_VERSION = "UPDATE metainfo SET value = ? WHERE key = '" + STORE_VERSION + "'";
private static final String CREATE_CLIENT_TABLE = "CREATE TABLE IF NOT EXISTS clients(id VARCHAR(255) NOT NULL PRIMARY KEY, name VARCHAR(255), secret VARCHAR(255));";
private static final String CREATE_REDIRECT_TABLE = "CREATE TABLE IF NOT EXISTS client_redirects(clientId VARCHAR(255), uri VARCHAR(255), PRIMARY KEY(clientId, uri));";
private static final String SAVE_CLIENT = "INSERT INTO clients (id, name, secret) VALUES (?,?,?) ON CONFLICT DO UPDATE SET name = ?, secret = ?;";
private static final String SAVE_REDIRECT = "INSERT OR IGNORE INTO client_redirects(clientId, uri) VALUES (?, ?)";
private static final String DROP_OTHER_REDIRECTS = "DELETE FROM client_redirects WHERE clientId = ? AND uri NOT IN";
private static final String SELECT_CLIENT = "SELECT * FROM clients WHERE id = ?";
private static final String SELECT_CLIENT_REDIRECTS = "SELECT uri FROM client_redirects WHERE clientId = ?";
private static final String LIST_CLIENT_REDIRECTS = "SELECT * FROM client_redirects";
private static final String LIST_CLIENTS = "SELECT * FROM clients";
private static final String DELETE_CLIENT = "DELETE FROM clients WHERE id = ?";
private static final String DELETE_CLIENT_REDIRECTS = "DELETE FROM client_redirects WHERE clientId = ?";
public SqliteClientService(Connection connection) throws SQLException {
super(connection);
}
private void createStoreTables() throws SQLException {
conn.prepareStatement(CREATE_CLIENT_TABLE).execute();
conn.prepareStatement(CREATE_REDIRECT_TABLE).execute();
}
@Override
protected void initTables() throws SQLException {
var rs = conn.prepareStatement(SELECT_STORE_VERSION).executeQuery();
int availableVersion = 1;
int currentVersion;
if (rs.next()) {
currentVersion = rs.getInt("value");
rs.close();
} else {
rs.close();
conn.prepareStatement(CREATE_STORE_VERSION).execute();
currentVersion = 0;
}
public class SqliteClientService implements ClientService {
public SqliteClientService(Connection connection) {
conn.setAutoCommit(false);
var stmt = conn.prepareStatement(SET_STORE_VERSION);
while (currentVersion < availableVersion) {
try {
switch (currentVersion) {
case 0:
createStoreTables();
break;
}
stmt.setInt(1, ++currentVersion);
stmt.execute();
conn.commit();
} catch (Exception e) {
conn.rollback();
LOG.log(System.Logger.Level.ERROR, "Failed to update at {} = {}", STORE_VERSION, currentVersion);
break;
}
}
conn.setAutoCommit(true);
}
@Override
public Optional<Client> getClient(String clientId) {
return Optional.empty();
Optional<Client> result = Optional.empty();
try {
var stmt = conn.prepareStatement(SELECT_CLIENT_REDIRECTS);
stmt.setString(1, clientId);
var rs = stmt.executeQuery();
var uris = new HashSet<String>();
while (rs.next()) uris.add(rs.getString("uri"));
rs.close();
stmt = conn.prepareStatement(SELECT_CLIENT);
stmt.setString(1, clientId);
rs = stmt.executeQuery();
if (rs.next()) {
var name = rs.getString(NAME);
var secret = rs.getString(SECRET);
result = Optional.of(new Client(clientId, name, secret, uris));
}
rs.close();
return result;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public List<Client> listClients() {
return List.of();
try {
var stmt = conn.prepareStatement(LIST_CLIENT_REDIRECTS);
var rs = stmt.executeQuery();
var redirects = new HashMap<String, Set<String>>();
while (rs.next()) {
var clientId = rs.getString("clientId");
var uri = rs.getString("uri");
var set = redirects.computeIfAbsent(clientId, k -> new HashSet<>());
set.add(uri);
}
rs.close();
stmt = conn.prepareStatement(LIST_CLIENTS);
rs = stmt.executeQuery();
var result = new ArrayList<Client>();
while (rs.next()) {
var id = rs.getString("id");
var name = rs.getString(NAME);
var secret = rs.getString(SECRET);
result.add(new Client(id, name, secret, redirects.get(id)));
}
rs.close();
return result;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public ClientService remove(Client client) {
return null;
public ClientService remove(String clientId) {
try {
var stmt = conn.prepareStatement(DELETE_CLIENT);
stmt.setString(1, clientId);
stmt.execute();
stmt = conn.prepareStatement(DELETE_CLIENT_REDIRECTS);
stmt.setString(1, clientId);
stmt.execute();
return this;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public ClientService save(Client client) {
return null;
try {
var stmt = conn.prepareStatement(SAVE_CLIENT);
stmt.setString(1, client.id());
stmt.setString(2, client.name());
stmt.setString(3, client.secret());
stmt.setString(4, client.name());
stmt.setString(5, client.secret());
stmt.execute();
stmt = conn.prepareStatement(SAVE_REDIRECT);
stmt.setString(1, client.id());
for (var redirect : client.redirectUris()) {
stmt.setString(2, redirect);
stmt.execute();
}
var where = "(" + client.redirectUris().stream().map(u -> "?").collect(Collectors.joining(", ")) + ")";
var sql = DROP_OTHER_REDIRECTS + where;
stmt = conn.prepareStatement(sql);
stmt.setString(1, client.id());
int i = 2;
for (var redirect : client.redirectUris()) stmt.setString(i++, redirect);
stmt.execute();
return this;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}

26
de.srsoftware.oidc.datastore.sqlite/src/test/java/de/srsoftware/oidc/datastore/sqlite/SqlteClientServiceTest.java

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
/* © SRSoftware 2024 */
package de.srsoftware.oidc.datastore.sqlite;
import static de.srsoftware.utils.Strings.uuid;
import de.srsoftware.oidc.api.ClientService;
import de.srsoftware.oidc.api.ClientServiceTest;
import java.io.File;
import java.sql.SQLException;
import org.junit.jupiter.api.BeforeEach;
public class SqlteClientServiceTest extends ClientServiceTest {
private ClientService clientService;
@Override
protected ClientService clientService() {
return clientService;
}
@BeforeEach
public void setup() throws SQLException {
var dbFile = new File("/tmp/" + uuid() + ".sqlite");
var conn = new ConnectionProvider().get(dbFile);
clientService = new SqliteClientService(conn);
}
}
Loading…
Cancel
Save