Skip to content

Commit 2c730a4

Browse files
authored
Merge pull request #4 from yayza/master
fix setting session TTL (ioredis)
2 parents 0639e64 + 2fe120e commit 2c730a4

File tree

3 files changed

+96
-54
lines changed

3 files changed

+96
-54
lines changed

src/lib/providers/ioredis.ts

+33-18
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,18 @@ export class IoRedisSessionStore {
2828
private readonly cookieOptions: CookieSerializeOptions;
2929

3030
constructor({
31-
redisClient,
32-
secret,
33-
cookieName = 'session',
34-
sessionPrefix = 'sk_ioredis_session',
35-
userSessionsPrefix = 'sk_ioredis_user_sessions',
36-
signed = true,
37-
useTTL = true,
38-
renewSessionBeforeExpire = false,
39-
renewBeforeSeconds = defaultRenewBeforeSeconds,
40-
serializer = JSON,
41-
cookiesOptions = {}
42-
}: ioRedisSessionOptions) {
31+
redisClient,
32+
secret,
33+
cookieName = 'session',
34+
sessionPrefix = 'sk_ioredis_session',
35+
userSessionsPrefix = 'sk_ioredis_user_sessions',
36+
signed = true,
37+
useTTL = true,
38+
renewSessionBeforeExpire = false,
39+
renewBeforeSeconds = defaultRenewBeforeSeconds,
40+
serializer = JSON,
41+
cookiesOptions = {}
42+
}: ioRedisSessionOptions) {
4343
if (!redisClient) {
4444
throw new Error('A pre-initiated redis client must be provided to the RedisStore');
4545
}
@@ -89,11 +89,13 @@ export class IoRedisSessionStore {
8989
console.log('Error in Set Session while serializing', er);
9090
return formattedReturn(null, true, 'Unable to stringify session data.');
9191
}
92+
93+
const prefixedSessionKey = getSessionKey(this.sessionPrefix, sessionKey);
9294
const redisPipeline = this.redisClient.pipeline();
93-
redisPipeline.set(getSessionKey(this.sessionPrefix, sessionKey), serializedSessionData);
94-
redisPipeline.sadd(getUserSessionKey(this.userSessionsPrefix, userId), getSessionKey(this.sessionPrefix, sessionKey));
95+
redisPipeline.set(prefixedSessionKey, serializedSessionData);
96+
redisPipeline.sadd(getUserSessionKey(this.userSessionsPrefix, userId), sessionKey);
9597
if (this.useTTL && this.ttlSeconds) {
96-
redisPipeline.expire(sessionKey, this.ttlSeconds);
98+
redisPipeline.expire(prefixedSessionKey, this.ttlSeconds);
9799
}
98100
await redisPipeline.exec();
99101
if (this.signedCookies) {
@@ -111,8 +113,10 @@ export class IoRedisSessionStore {
111113
} = await validateCookie(cookies, this.cookieName, this.secret, this.signedCookies);
112114
if (error) return formattedReturn(sessionId, error, message);
113115
const sessionData = await this.redisClient.get(getSessionKey(this.sessionPrefix, sessionId));
116+
114117
if (!sessionData)
115118
return formattedReturn(null, true, `Unable to find data for the provided key - ${sessionId}`);
119+
116120
let parsedSession;
117121
try {
118122
parsedSession = this.serializer.parse(sessionData);
@@ -158,7 +162,7 @@ export class IoRedisSessionStore {
158162
};
159163
// till here
160164

161-
deleteSession = async (cookies: Cookies) => {
165+
deleteSession = async (cookies: Cookies, userId = null) => {
162166
const {
163167
data: sessionId,
164168
error,
@@ -168,8 +172,19 @@ export class IoRedisSessionStore {
168172
console.log('Error in delSession method', message);
169173
return formattedReturn(sessionId, error, 'Unable to validate key while deleting');
170174
}
171-
const deleteData = await this.redisClient.del(getSessionKey(this.sessionPrefix, sessionId));
172-
if (!deleteData) return formattedReturn(null, true, `Key not found while deleting`);
175+
const prefixedSessionKey = getSessionKey(this.sessionPrefix, sessionId);
176+
const sessionData = await this.redisClient.get(prefixedSessionKey);
177+
if (!sessionData) return formattedReturn(sessionId, true, `Not a valid session key`);
178+
179+
if (userId) {
180+
const redisPipeline = this.redisClient.pipeline();
181+
redisPipeline.del(prefixedSessionKey);
182+
redisPipeline.srem(getUserSessionKey(this.userSessionsPrefix, userId), sessionId);
183+
await redisPipeline.exec()
184+
} else {
185+
await this.redisClient.del(prefixedSessionKey);
186+
}
187+
173188
await this.deleteCookie(cookies);
174189
return formattedReturn(sessionId, false, `Key successfully deleted`); // Returns unique key without prefix which is deleted from redis
175190
};

src/lib/providers/redis.ts

+30-18
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,18 @@ export class RedisSessionStore {
2828
private readonly cookieOptions: CookieSerializeOptions;
2929

3030
constructor({
31-
redisClient,
32-
secret,
33-
cookieName = 'session',
34-
sessionPrefix = 'sk_ioredis_session',
35-
userSessionsPrefix = 'sk_ioredis_user_sessions',
36-
signed = true,
37-
useTTL = true,
38-
renewSessionBeforeExpire = false,
39-
renewBeforeSeconds = defaultRenewBeforeSeconds,
40-
serializer = JSON,
41-
cookiesOptions = {}
42-
}: nodeRedisSessionOptions) {
31+
redisClient,
32+
secret,
33+
cookieName = 'session',
34+
sessionPrefix = 'sk_ioredis_session',
35+
userSessionsPrefix = 'sk_ioredis_user_sessions',
36+
signed = true,
37+
useTTL = true,
38+
renewSessionBeforeExpire = false,
39+
renewBeforeSeconds = defaultRenewBeforeSeconds,
40+
serializer = JSON,
41+
cookiesOptions = {}
42+
}: nodeRedisSessionOptions) {
4343
if (!redisClient) {
4444
throw new Error('A pre-initiated redis client must be provided to the RedisStore');
4545
}
@@ -89,12 +89,13 @@ export class RedisSessionStore {
8989
console.log('Error in Set Session while serializing', er);
9090
return formattedReturn(null, true, 'Unable to stringify session data.');
9191
}
92+
const prefixedSessionKey = getSessionKey(this.sessionPrefix, sessionKey);
9293
await Promise.all([
93-
this.redisClient.set(getSessionKey(this.sessionPrefix, sessionKey), serializedSessionData, serializedSessionData),
94-
this.redisClient.sAdd(getUserSessionKey(this.userSessionsPrefix, userId), getSessionKey(this.sessionPrefix, sessionKey))
94+
this.redisClient.set(prefixedSessionKey, serializedSessionData, serializedSessionData),
95+
this.redisClient.sAdd(getUserSessionKey(this.userSessionsPrefix, userId), sessionKey)
9596
]);
9697
if (this.useTTL && this.ttlSeconds) {
97-
await this.redisClient.expire(sessionKey, this.ttlSeconds);
98+
await this.redisClient.expire(prefixedSessionKey, this.ttlSeconds);
9899
}
99100
if (this.signedCookies) {
100101
sessionKey = await signSessionKey(sessionKey, this.secret);
@@ -158,7 +159,7 @@ export class RedisSessionStore {
158159
};
159160
// till here
160161

161-
deleteSession = async (cookies: Cookies) => {
162+
deleteSession = async (cookies: Cookies, userId = null) => {
162163
const {
163164
data: sessionId,
164165
error,
@@ -168,8 +169,19 @@ export class RedisSessionStore {
168169
console.log('Error in delSession method', message);
169170
return formattedReturn(sessionId, error, 'Unable to validate key while deleting');
170171
}
171-
const deleteData = await this.redisClient.del(getSessionKey(this.sessionPrefix, sessionId));
172-
if (!deleteData) return formattedReturn(null, true, `Key not found while deleting`);
172+
173+
const prefixedSessionKey = getSessionKey(this.sessionPrefix, sessionId);
174+
const sessionData = await this.redisClient.get(prefixedSessionKey);
175+
if (!sessionData) return formattedReturn(sessionId, true, `Not a valid session key`);
176+
177+
if (userId) {
178+
await Promise.all([
179+
this.redisClient.del(prefixedSessionKey),
180+
this.redisClient.sRem(getUserSessionKey(this.userSessionsPrefix, userId), sessionId)
181+
])
182+
} else {
183+
await this.redisClient.del( prefixedSessionKey );
184+
}
173185
await this.deleteCookie(cookies);
174186
return formattedReturn(sessionId, false, `Key successfully deleted`); // Returns unique key without prefix which is deleted from redis
175187
};

src/lib/providers/upstash.ts

+33-18
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,18 @@ export class upstashSessionStore {
3232
private readonly cookieOptions: CookieSerializeOptions;
3333

3434
constructor({
35-
redisClient,
36-
secret,
37-
cookieName = 'session',
38-
sessionPrefix = 'sk_ioredis_session',
39-
userSessionsPrefix = 'sk_ioredis_user_sessions',
40-
signed = true,
41-
useTTL = true,
42-
renewSessionBeforeExpire = false,
43-
renewBeforeSeconds = defaultRenewBeforeSeconds,
44-
serializer = JSON,
45-
cookiesOptions = {}
46-
}: upstashRedisSessionOptions) {
35+
redisClient,
36+
secret,
37+
cookieName = 'session',
38+
sessionPrefix = 'sk_ioredis_session',
39+
userSessionsPrefix = 'sk_ioredis_user_sessions',
40+
signed = true,
41+
useTTL = true,
42+
renewSessionBeforeExpire = false,
43+
renewBeforeSeconds = defaultRenewBeforeSeconds,
44+
serializer = JSON,
45+
cookiesOptions = {}
46+
}: upstashRedisSessionOptions) {
4747
if (!redisClient) {
4848
throw new Error('A pre-initiated redis client must be provided to the RedisStore');
4949
}
@@ -85,13 +85,16 @@ export class upstashSessionStore {
8585
console.log('Error in Set Session while serializing', er);
8686
return formattedReturn(null, true, 'Unable to stringify session data.');
8787
}
88+
const prefixedSessionKey = getSessionKey(this.sessionPrefix, sessionKey);
89+
8890
const redisPipeline = this.redisClient.pipeline();
89-
redisPipeline.set(getSessionKey(this.sessionPrefix, sessionKey), serializedSessionData);
90-
redisPipeline.sadd(getUserSessionKey(this.userSessionsPrefix, userId), getSessionKey(this.sessionPrefix, sessionKey));
91+
redisPipeline.set(prefixedSessionKey, serializedSessionData);
92+
redisPipeline.sadd(getUserSessionKey(this.userSessionsPrefix, userId), sessionKey);
9193
if (this.useTTL && this.ttlSeconds) {
92-
redisPipeline.expire(sessionKey, this.ttlSeconds);
94+
redisPipeline.expire(prefixedSessionKey, this.ttlSeconds);
9395
}
9496
await redisPipeline.exec();
97+
9598
if (this.signedCookies) {
9699
sessionKey = await signSessionKey(sessionKey, this.secret);
97100
}
@@ -154,7 +157,7 @@ export class upstashSessionStore {
154157
};
155158
// till here
156159

157-
deleteSession = async (cookies: Cookies) => {
160+
deleteSession = async (cookies: Cookies, userId = null) => {
158161
const {
159162
data: sessionId,
160163
error,
@@ -164,8 +167,20 @@ export class upstashSessionStore {
164167
console.log('Error in delSession method', message);
165168
return formattedReturn(sessionId, error, 'Unable to validate key while deleting');
166169
}
167-
const deleteData = await this.redisClient.del(getSessionKey(this.sessionPrefix, sessionId));
168-
if (!deleteData) return formattedReturn(null, true, `Key not found while deleting`);
170+
171+
const prefixedSessionKey = getSessionKey(this.sessionPrefix, sessionId);
172+
const sessionData = await this.redisClient.get(prefixedSessionKey);
173+
if (!sessionData) return formattedReturn(sessionId, true, `Not a valid session key`);
174+
175+
if (userId) {
176+
const redisPipeline = this.redisClient.pipeline();
177+
redisPipeline.del(prefixedSessionKey);
178+
redisPipeline.srem(getUserSessionKey(this.userSessionsPrefix, userId), sessionId);
179+
await redisPipeline.exec()
180+
} else {
181+
await this.redisClient.del(prefixedSessionKey);
182+
}
183+
169184
await this.deleteCookie(cookies);
170185
return formattedReturn(sessionId, false, `Key successfully deleted`); // Returns unique key without prefix which is deleted from redis
171186
};

0 commit comments

Comments
 (0)