Skip to content

Commit bd4cc44

Browse files
committed
Added delete inactive session functionality during login
Signed-off-by: shitrerohit <[email protected]>
1 parent 19975c9 commit bd4cc44

File tree

9 files changed

+38
-56
lines changed

9 files changed

+38
-56
lines changed

apps/api-gateway/src/user/user.controller.ts

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -416,19 +416,4 @@ export class UserController {
416416

417417
return res.status(HttpStatus.OK).json(finalResponse);
418418
}
419-
420-
@Post('/delete-inactive-sessions')
421-
@ApiOperation({
422-
summary: 'Update platform settings',
423-
description: 'Modify platform settings. Only accessible by platform admins.'
424-
})
425-
async deleteInactiveSessions(@Res() res: Response): Promise<Response> {
426-
await this.userService.deleteInactiveSessions();
427-
const finalResponse = {
428-
statusCode: HttpStatus.OK,
429-
message: ''
430-
};
431-
432-
return res.status(HttpStatus.OK).json(finalResponse);
433-
}
434419
}

apps/api-gateway/src/user/user.service.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,4 @@ export class UserService extends BaseService {
9292
const payload = { email };
9393
return this.natsClient.sendNatsMessage(this.serviceProxy, 'get-user-info-by-user-email-keycloak', payload);
9494
}
95-
96-
async deleteInactiveSessions(): Promise<void> {
97-
return this.natsClient.sendNatsMessage(this.serviceProxy, 'delete-inactive-sessions', '');
98-
}
9995
}

apps/organization/src/organization.service.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ import { DeleteOrgInvitationsEmail } from '../templates/delete-organization-invi
6464
import { IOrgRoles } from 'libs/org-roles/interfaces/org-roles.interface';
6565
import { NATSClient } from '@credebl/common/NATSClient';
6666
import { UserRepository } from 'apps/user/repositories/user.repository';
67+
import * as jwt from 'jsonwebtoken';
68+
6769
@Injectable()
6870
export class OrganizationService {
6971
constructor(
@@ -708,17 +710,24 @@ export class OrganizationService {
708710
let addSessionDetails;
709711
// Fetch owner organization details for getting the user id
710712
const orgRoleDetails = await this.organizationRepository.getOrgAndOwnerUser(clientId);
713+
// called seprate method to delete exp session
714+
this.userRepository.deleteInactiveSessions(orgRoleDetails['user'].id);
715+
711716
// Fetch the total number of sessions for the requested user to check and restrict the creation of multiple sessions.
712717
const userSessionDetails = await this.userRepository.fetchUserSessions(orgRoleDetails['user'].id);
713718
if (Number(process.env.SESSIONS_LIMIT) <= userSessionDetails?.length) {
714719
throw new BadRequestException(ResponseMessages.user.error.sessionLimitReached);
715720
}
721+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
722+
const decodedToken: any = jwt.decode(authenticationResult?.access_token);
723+
const expiresAt = new Date(decodedToken.exp * 1000);
716724
// Session payload
717725
const sessionData = {
718726
sessionToken: authenticationResult?.access_token,
719727
userId: orgRoleDetails['user'].id,
720728
expires: authenticationResult?.expires_in,
721-
sessionType: SessionType.ORG_SESSION
729+
sessionType: SessionType.ORG_SESSION,
730+
expiresAt
722731
};
723732
// Note:
724733
// Fetch account details to check whether the requested user account exists

apps/user/interfaces/user.interface.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ export interface ISession {
191191
type?: string;
192192
accountId?: string;
193193
sessionType?: string;
194+
expiresAt?: Date;
194195
}
195196

196197
export interface IUpdateAccountDetails {

apps/user/repositories/user.repository.ts

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -678,7 +678,7 @@ export class UserRepository {
678678

679679
async createSession(tokenDetails: ISession): Promise<session> {
680680
try {
681-
const { sessionToken, userId, expires, refreshToken, accountId, sessionType } = tokenDetails;
681+
const { sessionToken, userId, expires, refreshToken, accountId, sessionType, expiresAt } = tokenDetails;
682682
const sessionResponse = await this.prisma.session.create({
683683
data: {
684684
id: tokenDetails.id,
@@ -687,7 +687,8 @@ export class UserRepository {
687687
userId,
688688
refreshToken,
689689
accountId,
690-
sessionType
690+
sessionType,
691+
expiresAt
691692
}
692693
});
693694
return sessionResponse;
@@ -988,24 +989,16 @@ export class UserRepository {
988989
}
989990
}
990991

991-
async deleteInactiveSessions(): Promise<number> {
992-
try {
993-
// await this.prisma.session.deleteMany({
994-
// where: {
995-
// AND: [
996-
// {
997-
// createdAt: {
998-
// lt: new Date(Date.now() - expires), // Current time minus expire interval
999-
// },
1000-
// },
1001-
// // You can add more conditions here
1002-
// ],
1003-
// },
1004-
// });
1005-
const response = await this.prisma.$executeRaw`
1006-
DELETE FROM "session"
1007-
WHERE ("createdAt" + make_interval(secs => "expires")) < NOW()
1008-
`;
992+
async deleteInactiveSessions(userId: string): Promise<Prisma.BatchPayload> {
993+
try {
994+
const response = await this.prisma.session.deleteMany({
995+
where: {
996+
expiresAt: {
997+
lt: new Date()
998+
},
999+
userId
1000+
}
1001+
});
10091002
this.logger.debug('Response::', response);
10101003
return response;
10111004
} catch (error) {

apps/user/src/user.controller.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -269,9 +269,4 @@ export class UserController {
269269
async logout(logoutUserDto: ISessions): Promise<string> {
270270
return this.userService.logout(logoutUserDto);
271271
}
272-
273-
@MessagePattern({ cmd: 'delete-inactive-sessions' })
274-
async deleteInActiveSessions(): Promise<string> {
275-
return this.userService.deleteInActiveSessions();
276-
}
277272
}

apps/user/src/user.service.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,8 @@ export class UserService {
459459
if (true === isPasskey && false === userData?.isFidoVerified) {
460460
throw new UnauthorizedException(ResponseMessages.user.error.registerFido);
461461
}
462+
// called seprate method to delete exp session
463+
this.userRepository.deleteInactiveSessions(userData?.id);
462464
const userSessionDetails = await this.userRepository.fetchUserSessions(userData?.id);
463465
if (Number(process.env.SESSIONS_LIMIT) <= userSessionDetails?.length) {
464466
throw new BadRequestException(ResponseMessages.user.error.sessionLimitReached);
@@ -474,13 +476,16 @@ export class UserService {
474476
}
475477
// eslint-disable-next-line @typescript-eslint/no-explicit-any
476478
const decodedToken: any = jwt.decode(tokenDetails?.access_token);
479+
const expiresAt = new Date(decodedToken.exp * 1000);
480+
477481
const sessionData = {
478482
id: decodedToken.sid,
479483
sessionToken: tokenDetails?.access_token,
480484
userId: userData?.id,
481485
expires: tokenDetails?.expires_in,
482486
refreshToken: tokenDetails?.refresh_token,
483-
sessionType: SessionType.USER_SESSION
487+
sessionType: SessionType.USER_SESSION,
488+
expiresAt
484489
};
485490

486491
const fetchAccountDetails = await this.userRepository.checkAccountDetails(userData?.id);
@@ -555,13 +560,17 @@ export class UserService {
555560
if (!deletePreviousSession) {
556561
throw new InternalServerErrorException(ResponseMessages.user.error.errorInDeleteSession);
557562
}
563+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
564+
const decodedToken: any = jwt.decode(tokenResponse?.access_token);
565+
const expiresAt = new Date(decodedToken.exp * 1000);
558566
const sessionData = {
559567
sessionToken: tokenResponse.access_token,
560568
userId: userByKeycloakId?.['id'],
561569
expires: tokenResponse.expires_in,
562570
refreshToken: tokenResponse.refresh_token,
563571
sessionType: SessionType.USER_SESSION,
564-
accountId: userAccountDetails.id
572+
accountId: userAccountDetails.id,
573+
expiresAt
565574
};
566575
const addSessionDetails = await this.userRepository.createSession(sessionData);
567576
if (!addSessionDetails) {
@@ -1335,13 +1344,4 @@ export class UserService {
13351344
throw new RpcException(error.response ? error.response : error);
13361345
}
13371346
}
1338-
1339-
async deleteInActiveSessions(): Promise<number> {
1340-
try {
1341-
return await this.userRepository.deleteInactiveSessions();
1342-
} catch (error) {
1343-
this.logger.error(`Error in deleting in-active sessions`);
1344-
throw new RpcException(error.response ? error.response : error);
1345-
}
1346-
}
13471347
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-- AlterTable
2+
ALTER TABLE "session" ADD COLUMN "expiresAt" TIMESTAMP(6);

libs/prisma-service/prisma/schema.prisma

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ model session {
6666
accountId String? @db.Uuid
6767
sessionType String?
6868
account account? @relation(fields: [accountId], references:[id])
69+
expiresAt DateTime? @db.Timestamp(6)
6970
}
7071

7172
model token {

0 commit comments

Comments
 (0)