Skip to content

Commit cfc3588

Browse files
committed
Session API: tied SessionToken to SessionStore
1 parent d4e2529 commit cfc3588

5 files changed

Lines changed: 65 additions & 75 deletions

File tree

jooby/src/main/java/io/jooby/SessionOptions.java

Lines changed: 5 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,8 @@
55
*/
66
package io.jooby;
77

8-
import io.jooby.internal.MemorySessionStore;
9-
import io.jooby.internal.MultipleSessionToken;
10-
import io.jooby.internal.SecretSessionToken;
11-
128
import javax.annotation.Nonnull;
139
import java.security.SecureRandom;
14-
import java.time.Duration;
1510
import java.util.Base64;
1611

1712
/**
@@ -25,47 +20,19 @@
2520
* @since 2.0.0
2621
*/
2722
public class SessionOptions {
28-
private static final Cookie DEFAULT_COOKIE = new Cookie("jooby.sid")
29-
.setMaxAge(Duration.ofSeconds(-1))
30-
.setHttpOnly(true)
31-
.setPath("/");
32-
3323
private static final int ID_SIZE = 30;
3424

3525
private static final SecureRandom secure = new SecureRandom();
3626

37-
private SessionStore store = new MemorySessionStore();
38-
39-
private final SessionToken sessionToken;
40-
41-
/**
42-
* Creates a session options.
43-
*
44-
* @param secret Secret key. Used to signed the cookie.
45-
* @param sessionToken session ID.
46-
*/
47-
public SessionOptions(@Nonnull String secret, @Nonnull SessionToken... sessionToken) {
48-
this.sessionToken = new SecretSessionToken(createSessionId(sessionToken), secret);
49-
}
27+
private final SessionStore store;
5028

51-
/**
52-
* Creates a session options.
53-
*
54-
* @param sessionToken session ID.
55-
*/
56-
public SessionOptions(@Nonnull SessionToken... sessionToken) {
57-
this.sessionToken = createSessionId(sessionToken);
29+
public SessionOptions(SessionStore store) {
30+
this.store = store;
5831
}
5932

60-
/**
61-
* Session token strategy (cookie or header).
62-
*
63-
* @return Session token strategy (cookie or header).
64-
*/
65-
public SessionToken getSessionToken() {
66-
return sessionToken;
33+
public SessionOptions() {
34+
this(SessionStore.memory());
6735
}
68-
6936
/**
7037
* Session store (defaults uses memory).
7138
*
@@ -75,17 +42,6 @@ public SessionToken getSessionToken() {
7542
return store;
7643
}
7744

78-
/**
79-
* Set session store.
80-
*
81-
* @param store Session store.
82-
* @return This options.
83-
*/
84-
public @Nonnull SessionOptions setStore(@Nonnull SessionStore store) {
85-
this.store = store;
86-
return this;
87-
}
88-
8945
/**
9046
* Generates a Session ID.
9147
*
@@ -96,14 +52,4 @@ public SessionToken getSessionToken() {
9652
secure.nextBytes(bytes);
9753
return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes);
9854
}
99-
100-
private static SessionToken createSessionId(@Nonnull SessionToken[] sessionId) {
101-
if (sessionId.length == 0) {
102-
return SessionToken.cookie(DEFAULT_COOKIE);
103-
} else if (sessionId.length == 1) {
104-
return sessionId[0];
105-
} else {
106-
return new MultipleSessionToken(sessionId);
107-
}
108-
}
10955
}

jooby/src/main/java/io/jooby/SessionStore.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@
55
*/
66
package io.jooby;
77

8+
import io.jooby.internal.MemorySessionStore;
9+
810
import javax.annotation.Nonnull;
911
import javax.annotation.Nullable;
12+
import java.time.Duration;
1013
import java.time.Instant;
1114

1215
/**
@@ -17,6 +20,13 @@
1720
*/
1821
public interface SessionStore {
1922

23+
Cookie SID = new Cookie("jooby.sid")
24+
.setMaxAge(Duration.ofSeconds(-1))
25+
.setHttpOnly(true)
26+
.setPath("/");
27+
28+
@Nonnull SessionToken getSessionToken();
29+
2030
/**
2131
* Creates a new session. This method must:
2232
*
@@ -56,4 +66,16 @@ public interface SessionStore {
5666
* @param session Session to save.
5767
*/
5868
void save(@Nonnull Context ctx);
69+
70+
static SessionStore memory() {
71+
return memory(SID);
72+
}
73+
74+
static SessionStore memory(Cookie cookie) {
75+
return memory(SessionToken.cookie(cookie));
76+
}
77+
78+
static SessionStore memory(SessionToken token) {
79+
return new MemorySessionStore(token);
80+
}
5981
}

jooby/src/main/java/io/jooby/internal/MemorySessionStore.java

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66
package io.jooby.internal;
77

88
import io.jooby.Context;
9+
import io.jooby.Router;
910
import io.jooby.Session;
1011
import io.jooby.SessionToken;
1112
import io.jooby.SessionOptions;
1213
import io.jooby.SessionStore;
1314

15+
import javax.annotation.Nonnull;
1416
import java.time.Instant;
1517
import java.util.Map;
1618
import java.util.concurrent.ConcurrentHashMap;
@@ -30,6 +32,16 @@ public SessionData(Instant creationTime, Instant lastAccessedTime, Map hash) {
3032

3133
private ConcurrentHashMap<String, SessionData> sessions = new ConcurrentHashMap<>();
3234

35+
private SessionToken token;
36+
37+
public MemorySessionStore(SessionToken token) {
38+
this.token = token;
39+
}
40+
41+
@Nonnull @Override public SessionToken getSessionToken() {
42+
return token;
43+
}
44+
3345
@Override public Session newSession(Context ctx) {
3446
SessionOptions options = sessionOptions(ctx);
3547
String sessionId = options.generateId();
@@ -38,13 +50,12 @@ public SessionData(Instant creationTime, Instant lastAccessedTime, Map hash) {
3850
.setCreationTime(now)
3951
.setLastAccessedTime(now)
4052
.setNew(true);
41-
options.getSessionToken().saveToken(ctx, sessionId);
53+
token.saveToken(ctx, sessionId);
4254
return session;
4355
}
4456

4557
@Override public Session findSession(Context ctx) {
46-
SessionOptions options = sessionOptions(ctx);
47-
String sessionId = options.getSessionToken().findToken(ctx);
58+
String sessionId = token.findToken(ctx);
4859
if (sessionId == null) {
4960
return null;
5061
}
@@ -53,7 +64,7 @@ public SessionData(Instant creationTime, Instant lastAccessedTime, Map hash) {
5364
Session session = Session.create(ctx, sessionId, data.hash);
5465
session.setLastAccessedTime(data.lastAccessedTime);
5566
session.setCreationTime(data.creationTime);
56-
options.getSessionToken().saveToken(ctx, sessionId);
67+
token.saveToken(ctx, sessionId);
5768
return session;
5869
}
5970
return null;
@@ -62,9 +73,7 @@ public SessionData(Instant creationTime, Instant lastAccessedTime, Map hash) {
6273
@Override public void deleteSession(Context ctx) {
6374
String sessionId = ctx.session().getId();
6475
sessions.remove(sessionId);
65-
SessionOptions options = sessionOptions(ctx);
66-
SessionToken store = options.getSessionToken();
67-
store.deleteToken(ctx, sessionId);
76+
token.deleteToken(ctx, sessionId);
6877
}
6978

7079
@Override public void save(Context ctx) {
@@ -79,6 +88,7 @@ public SessionData(Instant creationTime, Instant lastAccessedTime, Map hash) {
7988
}
8089

8190
private static SessionOptions sessionOptions(Context ctx) {
82-
return ctx.getRouter().getSessionOptions();
91+
Router router = ctx.getRouter();
92+
return router.getSessionOptions();
8393
}
8494
}

jooby/src/main/java/io/jooby/internal/SessionImpl.java

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
package io.jooby.internal;
77

88
import io.jooby.Context;
9+
import io.jooby.Router;
910
import io.jooby.Session;
1011
import io.jooby.SessionOptions;
12+
import io.jooby.SessionStore;
1113
import io.jooby.Value;
1214
import io.jooby.ValueNode;
1315

@@ -111,15 +113,24 @@ public SessionImpl(Context ctx, String id, Map<String, String> attributes) {
111113
@Override public void destroy() {
112114
ctx.getAttributes().remove(NAME);
113115
attributes.clear();
114-
SessionOptions options = ctx.getRouter().getSessionOptions();
115-
options.getSessionToken().deleteToken(ctx, id);
116-
options.getStore().deleteSession(ctx);
116+
SessionStore store = store(ctx);
117+
store.getSessionToken().deleteToken(ctx, id);
118+
store.deleteSession(ctx);
117119
}
118120

119121
private void updateState() {
120122
modify = true;
121123
lastAccessedTime = Instant.now();
122-
SessionOptions sessionOptions = ctx.getRouter().getSessionOptions();
123-
sessionOptions.getSessionToken().saveToken(ctx, id);
124+
store(ctx).getSessionToken().saveToken(ctx, id);
124125
}
126+
127+
private static SessionOptions options(Context ctx) {
128+
Router router = ctx.getRouter();
129+
return router.getSessionOptions();
130+
}
131+
132+
private static SessionStore store(Context ctx) {
133+
return options(ctx).getStore();
134+
}
135+
125136
}

tests/src/test/java/io/jooby/FeaturedTest.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1748,7 +1748,7 @@ public void sessionCookie() {
17481748
/**********************************************************************************************/
17491749
new JoobyRunner(app -> {
17501750
app.setSessionOptions(
1751-
new SessionOptions(SessionToken.cookie(new Cookie("my.sid").setMaxAge(1L)))
1751+
new SessionOptions(SessionStore.memory(new Cookie("my.sid").setMaxAge(1L)))
17521752
);
17531753
app.get("/session", ctx -> ctx.session().toMap());
17541754
app.get("/sessionMaxAge", ctx -> Optional.ofNullable(ctx.sessionOrNull()).isPresent());
@@ -1763,8 +1763,9 @@ public void sessionCookie() {
17631763

17641764
@Test
17651765
public void signSession() {
1766+
17661767
new JoobyRunner(app -> {
1767-
app.setSessionOptions(new SessionOptions("987654345!$009P"));
1768+
// app.setSessionOptions(new SessionOptions("987654345!$009P"));
17681769
app.get("/findSession", ctx -> Optional.ofNullable(ctx.sessionOrNull()).isPresent());
17691770
app.get("/getSession", ctx -> ctx.session().get("foo").value("none"));
17701771
app.get("/putSession", ctx -> ctx.session().put("foo", "bar").get("foo").value());
@@ -1825,7 +1826,7 @@ public void signSession() {
18251826
public void sessionHeader() {
18261827
new JoobyRunner(app -> {
18271828

1828-
app.setSessionOptions(new SessionOptions(SessionToken.header("jooby.sid")));
1829+
app.setSessionOptions(new SessionOptions(SessionStore.memory(SessionToken.header("jooby.sid"))));
18291830

18301831
app.get("/findSession", ctx -> Optional.ofNullable(ctx.sessionOrNull()).isPresent());
18311832
app.get("/getSession", ctx -> ctx.session().get("foo").value("none"));

0 commit comments

Comments
 (0)