decoupling sesson object from user object
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
@@ -187,6 +187,11 @@ public abstract class PathHandler implements HttpHandler {
|
|||||||
return sendContent(ex, HTTP_OK, o);
|
return sendContent(ex, HTTP_OK, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean serverError(HttpExchange ex, Object o) throws IOException {
|
||||||
|
sendContent(ex, HTTP_INTERNAL_ERROR, o);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public static String url(HttpExchange ex) {
|
public static String url(HttpExchange ex) {
|
||||||
return hostname(ex) + ex.getRequestURI();
|
return hostname(ex) + ex.getRequestURI();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import java.util.Optional;
|
|||||||
public interface SessionService {
|
public interface SessionService {
|
||||||
Session createSession(User user);
|
Session createSession(User user);
|
||||||
SessionService dropSession(String sessionId);
|
SessionService dropSession(String sessionId);
|
||||||
Session extend(Session session);
|
Session extend(Session session, User user);
|
||||||
Optional<Session> retrieve(String sessionId, UserService userService);
|
Optional<Session> retrieve(String sessionId);
|
||||||
SessionService setDuration(Duration duration);
|
SessionService setDuration(Duration duration);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,5 +3,5 @@ package de.srsoftware.oidc.api.data;
|
|||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
|
||||||
public record Session(User user, Instant expiration, String id) {
|
public record Session(String userId, Instant expiration, String id) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,11 +22,13 @@ public class ClientController extends Controller {
|
|||||||
private static final System.Logger LOG = System.getLogger(ClientController.class.getSimpleName());
|
private static final System.Logger LOG = System.getLogger(ClientController.class.getSimpleName());
|
||||||
private final AuthorizationService authorizations;
|
private final AuthorizationService authorizations;
|
||||||
private final ClientService clients;
|
private final ClientService clients;
|
||||||
|
private final UserService users;
|
||||||
|
|
||||||
public ClientController(AuthorizationService authorizationService, ClientService clientService, SessionService sessionService, UserService userService) {
|
public ClientController(AuthorizationService authorizationService, ClientService clientService, SessionService sessionService, UserService userService) {
|
||||||
super(sessionService, userService);
|
super(sessionService);
|
||||||
authorizations = authorizationService;
|
authorizations = authorizationService;
|
||||||
clients = clientService;
|
clients = clientService;
|
||||||
|
users = userService;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean authorizationError(HttpExchange ex, String errorCode, String description, String state) throws IOException {
|
private boolean authorizationError(HttpExchange ex, String errorCode, String description, String state) throws IOException {
|
||||||
@@ -38,7 +40,9 @@ public class ClientController extends Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean authorize(HttpExchange ex, Session session) throws IOException {
|
private boolean authorize(HttpExchange ex, Session session) throws IOException {
|
||||||
var user = session.user();
|
var optUser = users.load(session.userId());
|
||||||
|
if (optUser.isEmpty()) return invalidSessionUser(ex);
|
||||||
|
var user = optUser.get();
|
||||||
var json = json(ex);
|
var json = json(ex);
|
||||||
var state = json.has(STATE) ? json.getString(STATE) : null;
|
var state = json.has(STATE) ? json.getString(STATE) : null;
|
||||||
if (!json.has(CLIENT_ID)) return authorizationError(ex, INVALID_REQUEST, "Missing required parameter \"%s\"!".formatted(CLIENT_ID), state);
|
if (!json.has(CLIENT_ID)) return authorizationError(ex, INVALID_REQUEST, "Missing required parameter \"%s\"!".formatted(CLIENT_ID), state);
|
||||||
@@ -95,7 +99,9 @@ public class ClientController extends Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean deleteClient(HttpExchange ex, Session session) throws IOException {
|
private boolean deleteClient(HttpExchange ex, Session session) throws IOException {
|
||||||
if (!session.user().hasPermission(MANAGE_CLIENTS)) return badRequest(ex, "NOT ALLOWED");
|
var optUser = users.load(session.userId());
|
||||||
|
if (optUser.isEmpty()) return invalidSessionUser(ex);
|
||||||
|
if (!optUser.get().hasPermission(MANAGE_CLIENTS)) return badRequest(ex, "NOT ALLOWED");
|
||||||
var json = json(ex);
|
var json = json(ex);
|
||||||
var id = json.getString(CLIENT_ID);
|
var id = json.getString(CLIENT_ID);
|
||||||
clients.getClient(id).ifPresent(clients::remove);
|
clients.getClient(id).ifPresent(clients::remove);
|
||||||
@@ -110,7 +116,11 @@ public class ClientController extends Controller {
|
|||||||
|
|
||||||
// post-login paths
|
// post-login paths
|
||||||
var session = optSession.get();
|
var session = optSession.get();
|
||||||
sessions.extend(session);
|
var optUser = users.load(session.userId());
|
||||||
|
if (optUser.isEmpty()) return invalidSessionUser(ex);
|
||||||
|
var user = optUser.get();
|
||||||
|
sessions.extend(session, user);
|
||||||
|
|
||||||
switch (path) {
|
switch (path) {
|
||||||
case "/":
|
case "/":
|
||||||
return deleteClient(ex, session);
|
return deleteClient(ex, session);
|
||||||
@@ -126,7 +136,11 @@ public class ClientController extends Controller {
|
|||||||
|
|
||||||
// post-login paths
|
// post-login paths
|
||||||
var session = optSession.get();
|
var session = optSession.get();
|
||||||
sessions.extend(session);
|
var optUser = users.load(session.userId());
|
||||||
|
if (optUser.isEmpty()) return invalidSessionUser(ex);
|
||||||
|
var user = optUser.get();
|
||||||
|
sessions.extend(session, user);
|
||||||
|
|
||||||
switch (path) {
|
switch (path) {
|
||||||
case "/":
|
case "/":
|
||||||
return load(ex, session);
|
return load(ex, session);
|
||||||
@@ -141,8 +155,9 @@ public class ClientController extends Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean list(HttpExchange ex, Session session) throws IOException {
|
private boolean list(HttpExchange ex, Session session) throws IOException {
|
||||||
var user = session.user();
|
var optUser = users.load(session.userId());
|
||||||
if (!user.hasPermission(MANAGE_CLIENTS)) return sendEmptyResponse(HTTP_FORBIDDEN, ex);
|
if (optUser.isEmpty()) return invalidSessionUser(ex);
|
||||||
|
if (!optUser.get().hasPermission(MANAGE_CLIENTS)) return sendEmptyResponse(HTTP_FORBIDDEN, ex);
|
||||||
var json = new JSONObject();
|
var json = new JSONObject();
|
||||||
clients.listClients().forEach(client -> json.put(client.id(), Map.of("name", client.name(), "redirect_uris", client.redirectUris())));
|
clients.listClients().forEach(client -> json.put(client.id(), Map.of("name", client.name(), "redirect_uris", client.redirectUris())));
|
||||||
return sendContent(ex, json);
|
return sendContent(ex, json);
|
||||||
@@ -150,7 +165,9 @@ public class ClientController extends Controller {
|
|||||||
|
|
||||||
|
|
||||||
private boolean load(HttpExchange ex, Session session) throws IOException {
|
private boolean load(HttpExchange ex, Session session) throws IOException {
|
||||||
if (!session.user().hasPermission(MANAGE_CLIENTS)) return sendEmptyResponse(HTTP_FORBIDDEN, ex);
|
var optUser = users.load(session.userId());
|
||||||
|
if (optUser.isEmpty()) return invalidSessionUser(ex);
|
||||||
|
if (!optUser.get().hasPermission(MANAGE_CLIENTS)) return sendEmptyResponse(HTTP_FORBIDDEN, ex);
|
||||||
var json = json(ex);
|
var json = json(ex);
|
||||||
if (json.has(CLIENT_ID)) {
|
if (json.has(CLIENT_ID)) {
|
||||||
var clientID = json.getString(CLIENT_ID);
|
var clientID = json.getString(CLIENT_ID);
|
||||||
@@ -161,7 +178,9 @@ public class ClientController extends Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean save(HttpExchange ex, Session session) throws IOException {
|
private boolean save(HttpExchange ex, Session session) throws IOException {
|
||||||
if (!session.user().hasPermission(MANAGE_CLIENTS)) return badRequest(ex, "NOT ALLOWED");
|
var optUser = users.load(session.userId());
|
||||||
|
if (optUser.isEmpty()) return invalidSessionUser(ex);
|
||||||
|
if (!optUser.get().hasPermission(MANAGE_CLIENTS)) return badRequest(ex, "NOT ALLOWED");
|
||||||
var json = json(ex);
|
var json = json(ex);
|
||||||
var redirects = new HashSet<String>();
|
var redirects = new HashSet<String>();
|
||||||
for (Object o : json.getJSONArray(REDIRECT_URIS)) {
|
for (Object o : json.getJSONArray(REDIRECT_URIS)) {
|
||||||
|
|||||||
@@ -5,20 +5,22 @@ import com.sun.net.httpserver.HttpExchange;
|
|||||||
import de.srsoftware.http.PathHandler;
|
import de.srsoftware.http.PathHandler;
|
||||||
import de.srsoftware.http.SessionToken;
|
import de.srsoftware.http.SessionToken;
|
||||||
import de.srsoftware.oidc.api.SessionService;
|
import de.srsoftware.oidc.api.SessionService;
|
||||||
import de.srsoftware.oidc.api.UserService;
|
|
||||||
import de.srsoftware.oidc.api.data.Session;
|
import de.srsoftware.oidc.api.data.Session;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public abstract class Controller extends PathHandler {
|
public abstract class Controller extends PathHandler {
|
||||||
protected final SessionService sessions;
|
protected final SessionService sessions;
|
||||||
private final UserService users;
|
|
||||||
|
|
||||||
Controller(SessionService sessionService, UserService userService) {
|
Controller(SessionService sessionService) {
|
||||||
sessions = sessionService;
|
sessions = sessionService;
|
||||||
users = userService;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Optional<Session> getSession(HttpExchange ex) {
|
protected Optional<Session> getSession(HttpExchange ex) {
|
||||||
return SessionToken.from(ex).map(SessionToken::sessionId).flatMap(sessionId -> sessions.retrieve(sessionId, users));
|
return SessionToken.from(ex).map(SessionToken::sessionId).flatMap(sessionId -> sessions.retrieve(sessionId));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean invalidSessionUser(HttpExchange ex) throws IOException {
|
||||||
|
return serverError(ex, "Session object refers to missing user");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,11 +14,13 @@ import de.srsoftware.oidc.api.data.Session;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class EmailController extends Controller {
|
public class EmailController extends Controller {
|
||||||
private final MailConfig mailConfig;
|
private final MailConfig mailConfig;
|
||||||
|
private final UserService users;
|
||||||
|
|
||||||
public EmailController(MailConfig mailConfig, SessionService sessionService, UserService userService) {
|
public EmailController(MailConfig mailConfig, SessionService sessionService, UserService userService) {
|
||||||
super(sessionService, userService);
|
super(sessionService);
|
||||||
this.mailConfig = mailConfig;
|
this.mailConfig = mailConfig;
|
||||||
|
users = userService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -26,7 +28,11 @@ public class EmailController extends Controller {
|
|||||||
var optSession = getSession(ex);
|
var optSession = getSession(ex);
|
||||||
if (optSession.isEmpty()) return sendEmptyResponse(HTTP_UNAUTHORIZED, ex);
|
if (optSession.isEmpty()) return sendEmptyResponse(HTTP_UNAUTHORIZED, ex);
|
||||||
var session = optSession.get();
|
var session = optSession.get();
|
||||||
sessions.extend(session);
|
var optUser = users.load(session.userId());
|
||||||
|
if (optUser.isEmpty()) return invalidSessionUser(ex);
|
||||||
|
var user = optUser.get();
|
||||||
|
sessions.extend(session, user);
|
||||||
|
|
||||||
switch (path) {
|
switch (path) {
|
||||||
case "/settings":
|
case "/settings":
|
||||||
return provideSettings(ex, session);
|
return provideSettings(ex, session);
|
||||||
@@ -39,7 +45,10 @@ public class EmailController extends Controller {
|
|||||||
var optSession = getSession(ex);
|
var optSession = getSession(ex);
|
||||||
if (optSession.isEmpty()) return sendEmptyResponse(HTTP_UNAUTHORIZED, ex);
|
if (optSession.isEmpty()) return sendEmptyResponse(HTTP_UNAUTHORIZED, ex);
|
||||||
var session = optSession.get();
|
var session = optSession.get();
|
||||||
sessions.extend(session);
|
var optUser = users.load(session.userId());
|
||||||
|
if (optUser.isEmpty()) return invalidSessionUser(ex);
|
||||||
|
var user = optUser.get();
|
||||||
|
sessions.extend(session, user);
|
||||||
|
|
||||||
switch (path) {
|
switch (path) {
|
||||||
case "/settings":
|
case "/settings":
|
||||||
@@ -49,12 +58,16 @@ public class EmailController extends Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean provideSettings(HttpExchange ex, Session session) throws IOException {
|
private boolean provideSettings(HttpExchange ex, Session session) throws IOException {
|
||||||
if (!session.user().hasPermission(MANAGE_SMTP)) return sendEmptyResponse(HTTP_FORBIDDEN, ex);
|
var optUser = users.load(session.userId());
|
||||||
|
if (optUser.isEmpty()) return invalidSessionUser(ex);
|
||||||
|
if (!optUser.get().hasPermission(MANAGE_SMTP)) return sendEmptyResponse(HTTP_FORBIDDEN, ex);
|
||||||
return sendContent(ex, mailConfig.map());
|
return sendContent(ex, mailConfig.map());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean saveSettings(HttpExchange ex, Session session) throws IOException {
|
private boolean saveSettings(HttpExchange ex, Session session) throws IOException {
|
||||||
if (!session.user().hasPermission(MANAGE_SMTP)) return sendEmptyResponse(HTTP_FORBIDDEN, ex);
|
var optUser = users.load(session.userId());
|
||||||
|
if (optUser.isEmpty()) return invalidSessionUser(ex);
|
||||||
|
if (!optUser.get().hasPermission(MANAGE_SMTP)) return sendEmptyResponse(HTTP_FORBIDDEN, ex);
|
||||||
var data = json(ex);
|
var data = json(ex);
|
||||||
if (data.has(SMTP_HOST)) mailConfig.smtpHost(data.getString(SMTP_HOST));
|
if (data.has(SMTP_HOST)) mailConfig.smtpHost(data.getString(SMTP_HOST));
|
||||||
if (data.has(SMTP_PORT)) mailConfig.smtpPort(data.getInt(SMTP_PORT));
|
if (data.has(SMTP_PORT)) mailConfig.smtpPort(data.getInt(SMTP_PORT));
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public class UserController extends Controller {
|
|||||||
private final ResourceLoader resourceLoader;
|
private final ResourceLoader resourceLoader;
|
||||||
|
|
||||||
public UserController(MailConfig mailConfig, SessionService sessionService, UserService userService, ResourceLoader resourceLoader) {
|
public UserController(MailConfig mailConfig, SessionService sessionService, UserService userService, ResourceLoader resourceLoader) {
|
||||||
super(sessionService, userService);
|
super(sessionService);
|
||||||
users = userService;
|
users = userService;
|
||||||
this.mailConfig = mailConfig;
|
this.mailConfig = mailConfig;
|
||||||
this.resourceLoader = resourceLoader;
|
this.resourceLoader = resourceLoader;
|
||||||
@@ -51,9 +51,11 @@ public class UserController extends Controller {
|
|||||||
public boolean doDelete(String path, HttpExchange ex) throws IOException {
|
public boolean doDelete(String path, HttpExchange ex) throws IOException {
|
||||||
var optSession = getSession(ex);
|
var optSession = getSession(ex);
|
||||||
if (optSession.isEmpty()) return sendEmptyResponse(HTTP_UNAUTHORIZED, ex);
|
if (optSession.isEmpty()) return sendEmptyResponse(HTTP_UNAUTHORIZED, ex);
|
||||||
|
var session = optSession.get();
|
||||||
// post-login paths
|
var optUser = users.load(session.userId());
|
||||||
var user = sessions.extend(optSession.get()).user();
|
if (optUser.isEmpty()) return invalidSessionUser(ex);
|
||||||
|
var user = optUser.get();
|
||||||
|
sessions.extend(session, user);
|
||||||
|
|
||||||
switch (path) {
|
switch (path) {
|
||||||
case "/delete":
|
case "/delete":
|
||||||
@@ -88,10 +90,11 @@ public class UserController extends Controller {
|
|||||||
}
|
}
|
||||||
var optSession = getSession(ex);
|
var optSession = getSession(ex);
|
||||||
if (optSession.isEmpty()) return sendEmptyResponse(HTTP_UNAUTHORIZED, ex);
|
if (optSession.isEmpty()) return sendEmptyResponse(HTTP_UNAUTHORIZED, ex);
|
||||||
|
|
||||||
// post-login paths
|
|
||||||
var session = optSession.get();
|
var session = optSession.get();
|
||||||
sessions.extend(session);
|
var optUser = users.load(session.userId());
|
||||||
|
if (optUser.isEmpty()) return invalidSessionUser(ex);
|
||||||
|
var user = optUser.get();
|
||||||
|
sessions.extend(session, user);
|
||||||
|
|
||||||
switch (path) {
|
switch (path) {
|
||||||
case "/logout":
|
case "/logout":
|
||||||
@@ -112,15 +115,15 @@ public class UserController extends Controller {
|
|||||||
}
|
}
|
||||||
var optSession = getSession(ex);
|
var optSession = getSession(ex);
|
||||||
if (optSession.isEmpty()) return sendEmptyResponse(HTTP_UNAUTHORIZED, ex);
|
if (optSession.isEmpty()) return sendEmptyResponse(HTTP_UNAUTHORIZED, ex);
|
||||||
|
|
||||||
// post-login paths
|
|
||||||
var session = optSession.get();
|
var session = optSession.get();
|
||||||
sessions.extend(session);
|
var optUser = users.load(session.userId());
|
||||||
var user = session.user();
|
if (optUser.isEmpty()) return invalidSessionUser(ex);
|
||||||
|
var user = optUser.get();
|
||||||
|
sessions.extend(session, user);
|
||||||
|
|
||||||
switch (path) {
|
switch (path) {
|
||||||
case "/":
|
case "/":
|
||||||
return sendUserAndCookie(ex, session);
|
return sendUserAndCookie(ex, session, user);
|
||||||
case "/add":
|
case "/add":
|
||||||
return addUser(ex, user);
|
return addUser(ex, user);
|
||||||
case "/list":
|
case "/list":
|
||||||
@@ -192,7 +195,7 @@ public class UserController extends Controller {
|
|||||||
var password = body.has(PASSWORD) ? body.getString(PASSWORD) : null;
|
var password = body.has(PASSWORD) ? body.getString(PASSWORD) : null;
|
||||||
|
|
||||||
Optional<User> user = users.load(username, password);
|
Optional<User> user = users.load(username, password);
|
||||||
if (user.isPresent()) return sendUserAndCookie(ex, sessions.createSession(user.get()));
|
if (user.isPresent()) return sendUserAndCookie(ex, sessions.createSession(user.get()), user.get());
|
||||||
return sendEmptyResponse(HTTP_UNAUTHORIZED, ex);
|
return sendEmptyResponse(HTTP_UNAUTHORIZED, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,9 +265,9 @@ public class UserController extends Controller {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean sendUserAndCookie(HttpExchange ex, Session session) throws IOException {
|
private boolean sendUserAndCookie(HttpExchange ex, Session session, User user) throws IOException {
|
||||||
new SessionToken(session.id()).addTo(ex);
|
new SessionToken(session.id()).addTo(ex);
|
||||||
return sendContent(ex, session.user().map(false));
|
return sendContent(ex, user.map(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import java.time.Duration;
|
|||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public class FileStore implements AuthorizationService, ClientService, SessionService, UserService, MailConfig {
|
public class FileStore implements AuthorizationService, ClientService, SessionService, UserService, MailConfig {
|
||||||
@@ -75,12 +74,7 @@ public class FileStore implements AuthorizationService, ClientService, SessionSe
|
|||||||
|
|
||||||
var authorizations = json.getJSONObject(AUTHORIZATIONS);
|
var authorizations = json.getJSONObject(AUTHORIZATIONS);
|
||||||
var authorizationUsers = Set.copyOf(authorizations.keySet());
|
var authorizationUsers = Set.copyOf(authorizations.keySet());
|
||||||
var userIds = list().stream().map(User::uuid).collect(Collectors.toSet());
|
|
||||||
for (var userId : authorizationUsers) {
|
for (var userId : authorizationUsers) {
|
||||||
if (!userIds.contains(userId)) {
|
|
||||||
authorizations.remove(userId);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var clients = authorizations.getJSONObject(userId);
|
var clients = authorizations.getJSONObject(userId);
|
||||||
var clientIds = Set.copyOf(clients.keySet());
|
var clientIds = Set.copyOf(clients.keySet());
|
||||||
for (var clientId : clientIds) {
|
for (var clientId : clientIds) {
|
||||||
@@ -228,7 +222,7 @@ public class FileStore implements AuthorizationService, ClientService, SessionSe
|
|||||||
public Session createSession(User user) {
|
public Session createSession(User user) {
|
||||||
var now = Instant.now();
|
var now = Instant.now();
|
||||||
var endOfSession = now.plus(user.sessionDuration());
|
var endOfSession = now.plus(user.sessionDuration());
|
||||||
return save(new Session(user, endOfSession, uuid()));
|
return save(new Session(user.uuid(), endOfSession, uuid()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -239,10 +233,9 @@ public class FileStore implements AuthorizationService, ClientService, SessionSe
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Session extend(Session session) {
|
public Session extend(Session session, User user) {
|
||||||
var user = session.user();
|
|
||||||
var endOfSession = Instant.now().plus(user.sessionDuration());
|
var endOfSession = Instant.now().plus(user.sessionDuration());
|
||||||
return save(new Session(user, endOfSession, session.id()));
|
return save(new Session(user.uuid(), endOfSession, session.id()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private JSONObject sessions() {
|
private JSONObject sessions() {
|
||||||
@@ -250,14 +243,12 @@ public class FileStore implements AuthorizationService, ClientService, SessionSe
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Session> retrieve(String sessionId, UserService userService) {
|
public Optional<Session> retrieve(String sessionId) {
|
||||||
try {
|
try {
|
||||||
var session = sessions().getJSONObject(sessionId);
|
var session = sessions().getJSONObject(sessionId);
|
||||||
var userId = session.getString(USER);
|
var userId = session.getString(USER);
|
||||||
var expiration = Instant.ofEpochSecond(session.getLong(EXPIRATION));
|
var expiration = Instant.ofEpochSecond(session.getLong(EXPIRATION));
|
||||||
if (expiration.isAfter(Instant.now())) {
|
if (expiration.isAfter(Instant.now())) return Optional.of(new Session(userId, expiration, sessionId));
|
||||||
return userService.load(userId).map(user -> new Session(user, expiration, sessionId));
|
|
||||||
}
|
|
||||||
dropSession(sessionId);
|
dropSession(sessionId);
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
}
|
}
|
||||||
@@ -265,7 +256,7 @@ public class FileStore implements AuthorizationService, ClientService, SessionSe
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Session save(Session session) {
|
private Session save(Session session) {
|
||||||
sessions().put(session.id(), Map.of(USER, session.user().uuid(), EXPIRATION, session.expiration().getEpochSecond()));
|
sessions().put(session.id(), Map.of(USER, session.userId(), EXPIRATION, session.expiration().getEpochSecond()));
|
||||||
save();
|
save();
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,33 @@
|
|||||||
/* © SRSoftware 2024 */
|
/* © SRSoftware 2024 */
|
||||||
package de.srsoftware.oidc.datastore.file;
|
package de.srsoftware.oidc.datastore.file;
|
||||||
|
|
||||||
|
import static de.srsoftware.utils.Strings.uuid;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
import de.srsoftware.oidc.api.SessionService;
|
import de.srsoftware.oidc.api.SessionService;
|
||||||
|
import de.srsoftware.oidc.api.data.User;
|
||||||
import de.srsoftware.utils.PasswordHasher;
|
import de.srsoftware.utils.PasswordHasher;
|
||||||
import de.srsoftware.utils.UuidHasher;
|
import de.srsoftware.utils.UuidHasher;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class SessionServiceTest {
|
public class SessionServiceTest {
|
||||||
private PasswordHasher<String> hasher = null;
|
private PasswordHasher<String> hasher = null;
|
||||||
private File storage = new File("/tmp/" + UUID.randomUUID());
|
private File storage = new File("/tmp/" + UUID.randomUUID());
|
||||||
private SessionService sessionService;
|
private SessionService sessionService;
|
||||||
|
|
||||||
|
private static final String EMAIL = "arno@nym.de";
|
||||||
|
private static final String PASSWORD = "grunzwanzling";
|
||||||
|
private static final String REALNAME = "Arno Nym";
|
||||||
|
private static final String USERNAME = "arno";
|
||||||
|
|
||||||
protected PasswordHasher<String> hasher() {
|
protected PasswordHasher<String> hasher() {
|
||||||
if (hasher == null) try {
|
if (hasher == null) try {
|
||||||
hasher = new UuidHasher();
|
hasher = new UuidHasher();
|
||||||
@@ -30,4 +43,17 @@ public class SessionServiceTest {
|
|||||||
if (storage.exists()) storage.delete();
|
if (storage.exists()) storage.delete();
|
||||||
sessionService = new FileStore(storage, hasher());
|
sessionService = new FileStore(storage, hasher());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreate() {
|
||||||
|
var uuid = uuid();
|
||||||
|
var pass = hasher().hash(PASSWORD, uuid);
|
||||||
|
var user = new User(USERNAME, pass, REALNAME, EMAIL, uuid).sessionDuration(Duration.ofMinutes(5));
|
||||||
|
|
||||||
|
Instant now = Instant.now();
|
||||||
|
var session = sessionService.createSession(user);
|
||||||
|
var expiration = session.expiration();
|
||||||
|
assertTrue(expiration.isAfter(now.plus(5, ChronoUnit.MINUTES).minusSeconds(1)));
|
||||||
|
assertTrue(expiration.isBefore(now.plus(5, ChronoUnit.MINUTES).plusSeconds(1)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
package de.srsoftware.oidc.datastore.sqlite;
|
package de.srsoftware.oidc.datastore.sqlite;
|
||||||
|
|
||||||
import de.srsoftware.oidc.api.SessionService;
|
import de.srsoftware.oidc.api.SessionService;
|
||||||
import de.srsoftware.oidc.api.UserService;
|
|
||||||
import de.srsoftware.oidc.api.data.Session;
|
import de.srsoftware.oidc.api.data.Session;
|
||||||
import de.srsoftware.oidc.api.data.User;
|
import de.srsoftware.oidc.api.data.User;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
@@ -24,12 +23,12 @@ public class SqliteSessionService implements SessionService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Session extend(Session session) {
|
public Session extend(Session session, User user) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Session> retrieve(String sessionId, UserService users) {
|
public Optional<Session> retrieve(String sessionId) {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user