implemented SqliteSessionService
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
@@ -80,7 +80,7 @@ public abstract class SessionServiceTest {
|
||||
|
||||
sessionService().dropSession(session.id());
|
||||
var loaded = sessionService().retrieve(session.id());
|
||||
assertTrue(sessionService().retrieve(session.id()).isEmpty());
|
||||
assertTrue(loaded.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -16,13 +16,17 @@ import org.jose4j.jwk.PublicJsonWebKey;
|
||||
import org.jose4j.lang.JoseException;
|
||||
|
||||
public class SqliteKeyStore extends SqliteStore implements KeyStorage {
|
||||
private static final String SELECT_KEYSTORE_VERSION = "SELECT * FROM metainfo WHERE key = 'key_store_version'";
|
||||
private static final String SET_KEYSTORE_VERSION = "UPDATE metainfo SET value = ? WHERE key = 'key_store_version'";
|
||||
private static final String CREATE_KEYSTORE_TABLE = "CREATE TABLE IF NOT EXISTS keystore(key_id VARCHAR(255) PRIMARY KEY, json TEXT NOT NULL);";
|
||||
private static final String SAVE_KEY = "INSERT INTO keystore(key_id, json) values (?,?) ON CONFLICT(key_id) DO UPDATE SET json = ?";
|
||||
private static final String SELECT_KEY_IDS = "SELECT key_id FROM keystore";
|
||||
private static final String LOAD_KEY = "SELECT json FROM keystore WHERE key_id = ?";
|
||||
private static final String DROP_KEY = "DELETE FROM keystore WHERE key_id = ?";
|
||||
private static final String STORE_VERSION = "key_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 SET_KEYSTORE_VERSION = "UPDATE metainfo SET value = ? WHERE key = 'key_store_version'";
|
||||
private static final String CREATE_KEYSTORE_TABLE = "CREATE TABLE IF NOT EXISTS keystore(key_id VARCHAR(255) PRIMARY KEY, json TEXT NOT NULL);";
|
||||
private static final String SAVE_KEY = "INSERT INTO keystore(key_id, json) values (?,?) ON CONFLICT(key_id) DO UPDATE SET json = ?";
|
||||
private static final String SELECT_KEY_IDS = "SELECT key_id FROM keystore";
|
||||
private static final String LOAD_KEY = "SELECT json FROM keystore WHERE key_id = ?";
|
||||
private static final String DROP_KEY = "DELETE FROM keystore WHERE key_id = ?";
|
||||
|
||||
private HashMap<String, PublicJsonWebKey> loaded = new HashMap<>();
|
||||
|
||||
@@ -30,36 +34,7 @@ public class SqliteKeyStore extends SqliteStore implements KeyStorage {
|
||||
super(connection);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initTables() throws SQLException {
|
||||
var rs = conn.prepareStatement(SELECT_KEYSTORE_VERSION).executeQuery();
|
||||
int availableVersion = 1;
|
||||
int lastVersion = 1;
|
||||
if (rs.next()) {
|
||||
lastVersion = rs.getInt(1);
|
||||
}
|
||||
rs.close();
|
||||
conn.setAutoCommit(false);
|
||||
var stmt = conn.prepareStatement(SET_KEYSTORE_VERSION);
|
||||
for (int version = lastVersion; version <= availableVersion; version++) {
|
||||
try {
|
||||
switch (version) {
|
||||
case 1:
|
||||
createKeyStoreTables();
|
||||
}
|
||||
stmt.setInt(1, version);
|
||||
stmt.execute();
|
||||
conn.commit();
|
||||
} catch (Exception e) {
|
||||
conn.rollback();
|
||||
LOG.log(System.Logger.Level.ERROR, "Failed to update at keystore version = {0}", version);
|
||||
break;
|
||||
}
|
||||
}
|
||||
conn.setAutoCommit(true);
|
||||
}
|
||||
|
||||
private void createKeyStoreTables() throws SQLException {
|
||||
private void createStoreTables() throws SQLException {
|
||||
conn.prepareStatement(CREATE_KEYSTORE_TABLE).execute();
|
||||
}
|
||||
|
||||
@@ -75,6 +50,41 @@ public class SqliteKeyStore extends SqliteStore implements KeyStorage {
|
||||
return this;
|
||||
}
|
||||
|
||||
@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(1);
|
||||
rs.close();
|
||||
} else {
|
||||
rs.close();
|
||||
conn.prepareStatement(CREATE_STORE_VERSION).execute();
|
||||
currentVersion = 0;
|
||||
}
|
||||
|
||||
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 List<String> listKeys() {
|
||||
var result = new ArrayList<String>();
|
||||
|
||||
@@ -19,11 +19,43 @@ public class SqliteSessionService extends SqliteStore implements SessionService
|
||||
private static final String SET_STORE_VERSION = "UPDATE metainfo SET value = ? WHERE key = '" + STORE_VERSION + "'";
|
||||
|
||||
private static final String CREATE_SESSION_TABLE = "CREATE TABLE sessions (id VARCHAR(64) PRIMARY KEY, userId VARCHAR(64) NOT NULL, expiration LONG NOT NULL)";
|
||||
private static final String SAVE_SESSION = "INSERT INTO sessions (id, userId, expiration) VALUES (?,?,?) ON CONFLICT DO UPDATE SET expiration = ?;";
|
||||
private static final String DROP_SESSION = "DELETE FROM sessions WHERE id = ?";
|
||||
private static final String SELECT_SESSION = "SELECT * FROM sessions WHERE id = ?";
|
||||
|
||||
public SqliteSessionService(Connection connection) throws SQLException {
|
||||
super(connection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Session createSession(User user) {
|
||||
var now = Instant.now();
|
||||
var endOfSession = now.plus(user.sessionDuration()).truncatedTo(SECONDS);
|
||||
return save(new Session(user.uuid(), endOfSession, uuid()));
|
||||
}
|
||||
|
||||
private void createStoreTables() throws SQLException {
|
||||
conn.prepareStatement(CREATE_SESSION_TABLE).execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionService dropSession(String sessionId) {
|
||||
try {
|
||||
var stmt = conn.prepareStatement(DROP_SESSION);
|
||||
stmt.setString(1, sessionId);
|
||||
stmt.execute();
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Session extend(Session session, User user) {
|
||||
var endOfSession = Instant.now().plus(user.sessionDuration());
|
||||
return save(new Session(user.uuid(), endOfSession, session.id()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initTables() throws SQLException {
|
||||
var rs = conn.prepareStatement(SELECT_STORE_VERSION).executeQuery();
|
||||
@@ -59,33 +91,37 @@ public class SqliteSessionService extends SqliteStore implements SessionService
|
||||
conn.setAutoCommit(true);
|
||||
}
|
||||
|
||||
private void createStoreTables() throws SQLException {
|
||||
conn.prepareStatement(CREATE_SESSION_TABLE).execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Session createSession(User user) {
|
||||
var now = Instant.now();
|
||||
var endOfSession = now.plus(user.sessionDuration()).truncatedTo(SECONDS);
|
||||
return save(new Session(user.uuid(), endOfSession, uuid()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionService dropSession(String sessionId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Session extend(Session session, User user) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Session> retrieve(String sessionId) {
|
||||
return Optional.empty();
|
||||
try {
|
||||
var stmt = conn.prepareStatement(SELECT_SESSION);
|
||||
stmt.setString(1, sessionId);
|
||||
var rs = stmt.executeQuery();
|
||||
Optional<Session> result = Optional.empty();
|
||||
if (rs.next()) {
|
||||
var userID = rs.getString("userId");
|
||||
var expiration = Instant.ofEpochSecond(rs.getLong("expiration"));
|
||||
if (expiration.isAfter(Instant.now())) result = Optional.of(new Session(userID, expiration, sessionId));
|
||||
}
|
||||
rs.close();
|
||||
return result;
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Session save(Session session) {
|
||||
return session;
|
||||
try {
|
||||
var stmt = conn.prepareStatement(SAVE_SESSION);
|
||||
var expiration = session.expiration().getEpochSecond();
|
||||
stmt.setString(1, session.id());
|
||||
stmt.setString(2, session.userId());
|
||||
stmt.setLong(3, expiration);
|
||||
stmt.setLong(4, expiration);
|
||||
stmt.execute();
|
||||
return session;
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ public class SqliteUserService extends SqliteStore implements UserService {
|
||||
private static final String LOAD_PERMISSIONS = "SELECT permission FROM user_permissions WHERE uuid = ?";
|
||||
private static final String FIND_USER = "SELECT * FROM users WHERE uuid = ? OR username LIKE ? OR realname LIKE ? OR email = ? ORDER BY COALESCE(uuid, ?), username";
|
||||
private static final String LIST_USERS = "SELECT * FROM users";
|
||||
private static final String INSERT_USER = "INSERT INTO users (uuid,password,email,session_duration,username,realname) VALUES (?,?,?,?,?,?) ON CONFLICT DO UPDATE SET password = ?, email = ?, session_duration = ?, username = ?, realname = ?;";
|
||||
private static final String SAVE_USER = "INSERT INTO users (uuid,password,email,session_duration,username,realname) VALUES (?,?,?,?,?,?) ON CONFLICT DO UPDATE SET password = ?, email = ?, session_duration = ?, username = ?, realname = ?;";
|
||||
private static final String INSERT_PERMISSIONS = "INSERT INTO user_permissions (uuid, permission) VALUES (?,?)";
|
||||
private static final String DROP_PERMISSIONS = "DELETE FROM user_permissions WHERE uuid = ?";
|
||||
private static final String DROP_USER = "DELETE FROM users WHERE uuid = ?";
|
||||
@@ -53,6 +53,22 @@ public class SqliteUserService extends SqliteStore implements UserService {
|
||||
return token;
|
||||
}
|
||||
|
||||
private User addPermissions(User user) {
|
||||
try {
|
||||
var stmt = conn.prepareStatement(LOAD_PERMISSIONS);
|
||||
stmt.setString(1, user.uuid());
|
||||
var rs = stmt.executeQuery();
|
||||
while (rs.next()) try {
|
||||
user.add(Permission.valueOf(rs.getString("permission")));
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
}
|
||||
rs.close();
|
||||
return user;
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<User> consumeToken(String id) {
|
||||
var user = forToken(id);
|
||||
@@ -86,6 +102,25 @@ public class SqliteUserService extends SqliteStore implements UserService {
|
||||
stmt.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<User> find(String idOrEmail) {
|
||||
try {
|
||||
var result = new HashSet<User>();
|
||||
var stmt = conn.prepareStatement(FIND_USER); // TODO: implement test for this query
|
||||
stmt.setString(1, idOrEmail);
|
||||
stmt.setString(2, "%" + idOrEmail + "%");
|
||||
stmt.setString(3, "%" + idOrEmail + "%");
|
||||
stmt.setString(4, idOrEmail);
|
||||
stmt.setString(5, idOrEmail);
|
||||
var rs = stmt.executeQuery();
|
||||
while (rs.next()) result.add(userFrom(rs));
|
||||
rs.close();
|
||||
return result;
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<User> forToken(String id) {
|
||||
AccessToken token = accessTokens.get(id);
|
||||
@@ -158,35 +193,6 @@ public class SqliteUserService extends SqliteStore implements UserService {
|
||||
}
|
||||
}
|
||||
|
||||
private User userFrom(ResultSet rs) throws SQLException {
|
||||
var uuid = rs.getString("uuid");
|
||||
var pass = rs.getString("password");
|
||||
var user = rs.getString("username");
|
||||
var name = rs.getString("realname");
|
||||
var mail = rs.getString("email");
|
||||
var mins = rs.getLong("session_duration");
|
||||
return new User(user, pass, name, mail, uuid).sessionDuration(Duration.ofMinutes(mins));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<User> find(String idOrEmail) {
|
||||
try {
|
||||
var result = new HashSet<User>();
|
||||
var stmt = conn.prepareStatement(FIND_USER); // TODO: implement test for this query
|
||||
stmt.setString(1, idOrEmail);
|
||||
stmt.setString(2, "%" + idOrEmail + "%");
|
||||
stmt.setString(3, "%" + idOrEmail + "%");
|
||||
stmt.setString(4, idOrEmail);
|
||||
stmt.setString(5, idOrEmail);
|
||||
var rs = stmt.executeQuery();
|
||||
while (rs.next()) result.add(userFrom(rs));
|
||||
rs.close();
|
||||
return result;
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<User> load(String id) {
|
||||
try {
|
||||
@@ -202,22 +208,6 @@ public class SqliteUserService extends SqliteStore implements UserService {
|
||||
}
|
||||
}
|
||||
|
||||
private User addPermissions(User user) {
|
||||
try {
|
||||
var stmt = conn.prepareStatement(LOAD_PERMISSIONS);
|
||||
stmt.setString(1, user.uuid());
|
||||
var rs = stmt.executeQuery();
|
||||
while (rs.next()) try {
|
||||
user.add(Permission.valueOf(rs.getString("permission")));
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
}
|
||||
rs.close();
|
||||
return user;
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<User> load(String username, String password) {
|
||||
var candidates = find(username);
|
||||
@@ -236,7 +226,7 @@ public class SqliteUserService extends SqliteStore implements UserService {
|
||||
public SqliteUserService save(User user) {
|
||||
try {
|
||||
conn.setAutoCommit(false);
|
||||
var stmt = conn.prepareStatement(INSERT_USER);
|
||||
var stmt = conn.prepareStatement(SAVE_USER);
|
||||
stmt.setString(1, user.uuid());
|
||||
stmt.setString(2, user.hashedPassword());
|
||||
stmt.setString(3, user.email());
|
||||
@@ -270,4 +260,14 @@ public class SqliteUserService extends SqliteStore implements UserService {
|
||||
public SqliteUserService updatePassword(User user, String plaintextPassword) {
|
||||
return save(user.hashedPassword(hasher.hash(plaintextPassword, uuid())));
|
||||
}
|
||||
|
||||
private User userFrom(ResultSet rs) throws SQLException {
|
||||
var uuid = rs.getString("uuid");
|
||||
var pass = rs.getString("password");
|
||||
var user = rs.getString("username");
|
||||
var name = rs.getString("realname");
|
||||
var mail = rs.getString("email");
|
||||
var mins = rs.getLong("session_duration");
|
||||
return new User(user, pass, name, mail, uuid).sessionDuration(Duration.ofMinutes(mins));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user