From b5c850d178974c3a4ad2460994e0474d035b3640 Mon Sep 17 00:00:00 2001 From: Igor Propisnov Date: Fri, 31 May 2024 08:19:26 +0200 Subject: [PATCH] tidy up --- .../repositories/session.repository.ts | 55 ++++++++++++++++++- .../auth-module/services/auth.service.ts | 2 +- .../auth-module/services/session.service.ts | 48 +++------------- 3 files changed, 64 insertions(+), 41 deletions(-) diff --git a/backend/src/modules/auth-module/repositories/session.repository.ts b/backend/src/modules/auth-module/repositories/session.repository.ts index 9cb7bb3..d2de7ee 100644 --- a/backend/src/modules/auth-module/repositories/session.repository.ts +++ b/backend/src/modules/auth-module/repositories/session.repository.ts @@ -1,7 +1,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { Response } from 'express'; import { Session } from 'src/entities'; -import { Repository } from 'typeorm'; +import { LessThan, Repository } from 'typeorm'; import { v4 as uuidv4 } from 'uuid'; @Injectable() @@ -30,6 +31,21 @@ export class SessionRepository { return session; } + public async findSessionBySessionId(sessionId: string): Promise { + return await this.sessionRepository.findOne({ + where: { sessionId: sessionId }, + relations: ['userCredentials'], + }); + } + + public attachSessionToResponse(response: Response, sessionId: string): void { + response.cookie('session_id', sessionId, { + httpOnly: true, + secure: true, + sameSite: 'strict', + }); + } + public async validateSessionUserAgent( sessionId: string, currentUserAgent: string @@ -45,4 +61,41 @@ export class SessionRepository { return session.userAgent === currentUserAgent; } + + public async checkSessionLimit(userId: string): Promise { + const userSessions = await this.sessionRepository + .createQueryBuilder('session') + .leftJoinAndSelect('session.userCredentials', 'userCredentials') + .where('userCredentials.id = :userId', { userId }) + .orderBy('session.expiresAt', 'ASC') + .getMany(); + + if (userSessions.length >= 5) { + await this.sessionRepository.delete(userSessions[0].id); + } + } + + public async invalidateAllSessionsForUser(userId: string): Promise { + await this.sessionRepository.delete({ userCredentials: userId }); + } + + public async extendSessionExpiration(sessionId: string): Promise { + const session = await this.sessionRepository.findOne({ + where: { sessionId }, + }); + + if (session) { + session.expiresAt = new Date( + session.expiresAt.setMinutes(session.expiresAt.getMinutes() + 30) + ); + await this.sessionRepository.save(session); + } + } + + // TODO Add cron job to clear expired sessions + public async clearExpiredSessions(): Promise { + const now = new Date(); + + await this.sessionRepository.delete({ expiresAt: LessThan(now) }); + } } diff --git a/backend/src/modules/auth-module/services/auth.service.ts b/backend/src/modules/auth-module/services/auth.service.ts index 595c986..cea61c0 100644 --- a/backend/src/modules/auth-module/services/auth.service.ts +++ b/backend/src/modules/auth-module/services/auth.service.ts @@ -88,7 +88,7 @@ export class AuthService { this.sessionService.attachSessionToResponse(response, sesseionId.sessionId); - return this.generateAndPersistTokens(user.id, user.email); + return this.generateAndPersistTokens(user.id, user.email, true); } public async logout(userId: string): Promise { diff --git a/backend/src/modules/auth-module/services/session.service.ts b/backend/src/modules/auth-module/services/session.service.ts index fae9da1..623c976 100644 --- a/backend/src/modules/auth-module/services/session.service.ts +++ b/backend/src/modules/auth-module/services/session.service.ts @@ -2,7 +2,6 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Response } from 'express'; import { Session } from 'src/entities'; -import { LessThan, Repository } from 'typeorm'; import { SessionRepository } from '../repositories/session.repository'; @@ -10,76 +9,47 @@ import { SessionRepository } from '../repositories/session.repository'; export class SessionService { public constructor( @InjectRepository(Session) - private sessionRepository: Repository, - private readonly sessionRepository2: SessionRepository + private readonly sessionRepository: SessionRepository ) {} public async createSession( userId: string, userAgent: string ): Promise { - return this.sessionRepository2.createSession(userId, userAgent); + return await this.sessionRepository.createSession(userId, userAgent); } public async validateSessionUserAgent( sessionId: string, currentUserAgent: string ): Promise { - return this.sessionRepository2.validateSessionUserAgent( + return await this.sessionRepository.validateSessionUserAgent( sessionId, currentUserAgent ); } public async checkSessionLimit(userId: string): Promise { - const userSessions = await this.sessionRepository - .createQueryBuilder('session') - .leftJoinAndSelect('session.userCredentials', 'userCredentials') - .where('userCredentials.id = :userId', { userId }) - .orderBy('session.expiresAt', 'ASC') - .getMany(); - - if (userSessions.length >= 5) { - await this.sessionRepository.delete(userSessions[0].id); - } + await this.sessionRepository.checkSessionLimit(userId); } public async invalidateAllSessionsForUser(userId: string): Promise { - await this.sessionRepository.delete({ userCredentials: userId }); + await this.sessionRepository.invalidateAllSessionsForUser(userId); } - // TODO Add cron job to clear expired sessions public async clearExpiredSessions(): Promise { - const now = new Date(); - - await this.sessionRepository.delete({ expiresAt: LessThan(now) }); + await this.sessionRepository.clearExpiredSessions(); } public async extendSessionExpiration(sessionId: string): Promise { - const session = await this.sessionRepository.findOne({ - where: { sessionId }, - }); - - if (session) { - session.expiresAt = new Date( - session.expiresAt.setMinutes(session.expiresAt.getMinutes() + 30) - ); - await this.sessionRepository.save(session); - } + await this.sessionRepository.extendSessionExpiration(sessionId); } public async findSessionBySessionId(sessionId: string): Promise { - return this.sessionRepository.findOne({ - where: { sessionId: sessionId }, - relations: ['userCredentials'], - }); + return await this.sessionRepository.findSessionBySessionId(sessionId); } public attachSessionToResponse(response: Response, sessionId: string): void { - response.cookie('session_id', sessionId, { - httpOnly: true, - secure: true, - sameSite: 'strict', - }); + this.sessionRepository.attachSessionToResponse(response, sessionId); } }