mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 12:28:42 +00:00
feat(server): auto refresh session (#6613)
This commit is contained in:
@@ -36,7 +36,7 @@ export class AuthGuard implements CanActivate, OnModuleInit {
|
||||
}
|
||||
|
||||
async canActivate(context: ExecutionContext) {
|
||||
const { req } = getRequestResponseFromContext(context);
|
||||
const { req, res } = getRequestResponseFromContext(context);
|
||||
|
||||
// check cookie
|
||||
let sessionToken: string | undefined =
|
||||
@@ -51,7 +51,19 @@ export class AuthGuard implements CanActivate, OnModuleInit {
|
||||
req.headers[AuthService.authUserSeqHeaderName]
|
||||
);
|
||||
|
||||
const user = await this.auth.getUser(sessionToken, userSeq);
|
||||
const { user, expiresAt } = await this.auth.getUser(
|
||||
sessionToken,
|
||||
userSeq
|
||||
);
|
||||
if (res && user && expiresAt) {
|
||||
await this.auth.refreshUserSessionIfNeeded(
|
||||
req,
|
||||
res,
|
||||
sessionToken,
|
||||
user.id,
|
||||
expiresAt
|
||||
);
|
||||
}
|
||||
|
||||
if (user) {
|
||||
req.sid = sessionToken;
|
||||
|
||||
@@ -145,24 +145,27 @@ export class AuthService implements OnApplicationBootstrap {
|
||||
return sessionUser(user);
|
||||
}
|
||||
|
||||
async getUser(token: string, seq = 0): Promise<CurrentUser | null> {
|
||||
async getUser(
|
||||
token: string,
|
||||
seq = 0
|
||||
): Promise<{ user: CurrentUser | null; expiresAt: Date | null }> {
|
||||
const session = await this.getSession(token);
|
||||
|
||||
// no such session
|
||||
if (!session) {
|
||||
return null;
|
||||
return { user: null, expiresAt: null };
|
||||
}
|
||||
|
||||
const userSession = session.userSessions.at(seq);
|
||||
|
||||
// no such user session
|
||||
if (!userSession) {
|
||||
return null;
|
||||
return { user: null, expiresAt: null };
|
||||
}
|
||||
|
||||
// user session expired
|
||||
if (userSession.expiresAt && userSession.expiresAt <= new Date()) {
|
||||
return null;
|
||||
return { user: null, expiresAt: null };
|
||||
}
|
||||
|
||||
const user = await this.db.user.findUnique({
|
||||
@@ -170,10 +173,10 @@ export class AuthService implements OnApplicationBootstrap {
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
return null;
|
||||
return { user: null, expiresAt: null };
|
||||
}
|
||||
|
||||
return sessionUser(user);
|
||||
return { user: sessionUser(user), expiresAt: userSession.expiresAt };
|
||||
}
|
||||
|
||||
async getUserList(token: string) {
|
||||
@@ -269,6 +272,43 @@ export class AuthService implements OnApplicationBootstrap {
|
||||
});
|
||||
}
|
||||
|
||||
async refreshUserSessionIfNeeded(
|
||||
_req: Request,
|
||||
res: Response,
|
||||
sessionId: string,
|
||||
userId: string,
|
||||
expiresAt: Date,
|
||||
ttr = this.config.auth.session.ttr
|
||||
): Promise<boolean> {
|
||||
if (expiresAt && expiresAt.getTime() - Date.now() > ttr * 1000) {
|
||||
// no need to refresh
|
||||
return false;
|
||||
}
|
||||
|
||||
const newExpiresAt = new Date(
|
||||
Date.now() + this.config.auth.session.ttl * 1000
|
||||
);
|
||||
|
||||
await this.db.userSession.update({
|
||||
where: {
|
||||
sessionId_userId: {
|
||||
sessionId,
|
||||
userId,
|
||||
},
|
||||
},
|
||||
data: {
|
||||
expiresAt: newExpiresAt,
|
||||
},
|
||||
});
|
||||
|
||||
res.cookie(AuthService.sessionCookieName, sessionId, {
|
||||
expires: newExpiresAt,
|
||||
...this.cookieOptions,
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async createUserSession(
|
||||
user: { id: string },
|
||||
existingSession?: string,
|
||||
|
||||
@@ -240,6 +240,13 @@ export interface AFFiNEConfig {
|
||||
* @default 15 days
|
||||
*/
|
||||
ttl: number;
|
||||
|
||||
/**
|
||||
* Application auth time to refresh in seconds
|
||||
*
|
||||
* @default 7 days
|
||||
*/
|
||||
ttr: number;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -153,6 +153,7 @@ export const getDefaultAFFiNEConfig: () => AFFiNEConfig = () => {
|
||||
},
|
||||
session: {
|
||||
ttl: 15 * ONE_DAY_IN_SEC,
|
||||
ttr: 7 * ONE_DAY_IN_SEC,
|
||||
},
|
||||
accessToken: {
|
||||
ttl: 7 * ONE_DAY_IN_SEC,
|
||||
|
||||
Reference in New Issue
Block a user