Skip to content

Commit 19975c9

Browse files
committed
WIP:delete inactive sessions
Signed-off-by: shitrerohit <[email protected]>
1 parent a6b69fd commit 19975c9

File tree

5 files changed

+149
-82
lines changed

5 files changed

+149
-82
lines changed

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

Lines changed: 96 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export class UserController {
6262
private readonly userService: UserService,
6363
private readonly commonService: CommonService,
6464
private readonly awsService: AwsService
65-
) { }
65+
) {}
6666

6767
/**
6868
*
@@ -105,9 +105,9 @@ export class UserController {
105105
return res.status(HttpStatus.OK).json(finalResponse);
106106
}
107107

108-
/**
108+
/**
109109
* Get public profile details of a user by username.
110-
*
110+
*
111111
* @param username The username of the user.
112112
* @returns Public profile information.
113113
*/
@@ -134,7 +134,6 @@ export class UserController {
134134
return res.status(HttpStatus.OK).json(finalResponse);
135135
}
136136

137-
138137
/**
139138
* Retrieves the profile details of the currently logged-in user.
140139
*
@@ -149,7 +148,7 @@ export class UserController {
149148
@ApiBearerAuth()
150149
async getProfile(@User() reqUser: user, @Res() res: Response): Promise<Response> {
151150
const userData = await this.userService.getProfile(reqUser.id);
152-
151+
153152
const finalResponse: IResponse = {
154153
statusCode: HttpStatus.OK,
155154
message: ResponseMessages.user.success.fetchProfile,
@@ -159,9 +158,9 @@ export class UserController {
159158
return res.status(HttpStatus.OK).json(finalResponse);
160159
}
161160

162-
/**
161+
/**
163162
* Retrieves all platform settings.
164-
*
163+
*
165164
* @returns The platform settings.
166165
*/
167166
@Get('/platform-settings')
@@ -185,11 +184,11 @@ export class UserController {
185184
}
186185

187186
/**
188-
* Fetch user activities.
189-
*
190-
* @param limit - Number of activities to fetch.
191-
* @returns A response containing user activity data.
192-
*/
187+
* Fetch user activities.
188+
*
189+
* @param limit - Number of activities to fetch.
190+
* @returns A response containing user activity data.
191+
*/
193192
@Get('/activity')
194193
@ApiOperation({
195194
summary: 'Fetch users activity',
@@ -214,12 +213,11 @@ export class UserController {
214213
return res.status(HttpStatus.OK).json(finalResponse);
215214
}
216215

217-
218-
/**
219-
* Fetch organization invitations.
220-
*
221-
* @returns A paginated list of organization invitations.
222-
*/
216+
/**
217+
* Fetch organization invitations.
218+
*
219+
* @returns A paginated list of organization invitations.
220+
*/
223221
@Get('/org-invitations')
224222
@ApiOperation({
225223
summary: 'organization invitations',
@@ -248,7 +246,7 @@ export class UserController {
248246
required: false
249247
})
250248
async invitations(
251-
@Query() getAllInvitationsDto: GetAllInvitationsDto,
249+
@Query() getAllInvitationsDto: GetAllInvitationsDto,
252250
@User() reqUser: user,
253251
@Res() res: Response
254252
): Promise<Response> {
@@ -271,14 +269,17 @@ export class UserController {
271269
return res.status(HttpStatus.OK).json(finalResponse);
272270
}
273271

274-
/**
275-
* Checks if a user is registered and verifies email existence.
276-
*
277-
* @param email The email address to check.
278-
* @returns Returns user registration and email verification status.
279-
*/
272+
/**
273+
* Checks if a user is registered and verifies email existence.
274+
*
275+
* @param email The email address to check.
276+
* @returns Returns user registration and email verification status.
277+
*/
280278
@Get('/:email')
281-
@ApiOperation({ summary: 'Check user registration and email verification status', description: 'Check if a user is already registered and if their email already exists.' })
279+
@ApiOperation({
280+
summary: 'Check user registration and email verification status',
281+
description: 'Check if a user is already registered and if their email already exists.'
282+
})
282283
async checkUserExist(@Param() emailParam: EmailValidator, @Res() res: Response): Promise<Response> {
283284
const userDetails = await this.userService.checkUserExist(emailParam.email);
284285

@@ -292,12 +293,12 @@ export class UserController {
292293
}
293294

294295
/**
295-
* Accept or reject an organization invitation.
296-
*
297-
* @param invitationId The ID of the organization invitation.
298-
* @body AcceptRejectInvitationDto
299-
* @returns The status of the organization invitation response.
300-
*/
296+
* Accept or reject an organization invitation.
297+
*
298+
* @param invitationId The ID of the organization invitation.
299+
* @body AcceptRejectInvitationDto
300+
* @returns The status of the organization invitation response.
301+
*/
301302
@Post('/org-invitations/:invitationId')
302303
@ApiOperation({
303304
summary: 'accept/reject organization invitation',
@@ -306,8 +307,17 @@ export class UserController {
306307
@UseGuards(AuthGuard('jwt'), UserAccessGuard)
307308
@ApiBearerAuth()
308309
async acceptRejectInvitaion(
309-
@Body() acceptRejectInvitation: AcceptRejectInvitationDto,
310-
@Param('invitationId', TrimStringParamPipe, new ParseUUIDPipe({exceptionFactory: (): Error => { throw new BadRequestException(`Invalid format for InvitationId`); }})) invitationId: string,
310+
@Body() acceptRejectInvitation: AcceptRejectInvitationDto,
311+
@Param(
312+
'invitationId',
313+
TrimStringParamPipe,
314+
new ParseUUIDPipe({
315+
exceptionFactory: (): Error => {
316+
throw new BadRequestException(`Invalid format for InvitationId`);
317+
}
318+
})
319+
)
320+
invitationId: string,
311321
@User() reqUser: user,
312322
@Res() res: Response
313323
): Promise<Response> {
@@ -320,13 +330,13 @@ export class UserController {
320330
};
321331
return res.status(HttpStatus.CREATED).json(finalResponse);
322332
}
323-
333+
324334
/**
325-
* Updates the user profile.
326-
*
327-
* @body UpdateUserProfileDto
328-
* @returns A response indicating the success of the update operation.
329-
*/
335+
* Updates the user profile.
336+
*
337+
* @body UpdateUserProfileDto
338+
* @returns A response indicating the success of the update operation.
339+
*/
330340
@Put('/')
331341
@ApiOperation({
332342
summary: 'Update user profile',
@@ -343,48 +353,48 @@ export class UserController {
343353
const userId = reqUser.id;
344354
updateUserProfileDto.id = userId;
345355
await this.userService.updateUserProfile(updateUserProfileDto);
346-
356+
347357
const finalResponse: IResponse = {
348358
statusCode: HttpStatus.OK,
349359
message: ResponseMessages.user.success.update
350360
};
351361
return res.status(HttpStatus.OK).json(finalResponse);
352362
}
353363

354-
/**
364+
/**
355365
* @body AddPasskeyDetailsDto
356366
* @returns User's profile update status
357367
*/
358-
359-
360-
@Put('/password/:email')
361-
@ApiOperation({ summary: 'Store user password details', description: 'Securely store and update the user’s password details.' })
362-
@ApiExcludeEndpoint()
363-
@ApiBearerAuth()
364-
@UseGuards(AuthGuard('jwt'), UserAccessGuard)
365-
366-
async addPasskey(
367-
@Body() userInfo: AddPasskeyDetailsDto,
368-
@User() reqUser: user,
369-
@Res() res: Response
370-
): Promise<Response> {
371-
372-
const userDetails = await this.userService.addPasskey(reqUser.email, userInfo);
373-
const finalResponse = {
374-
statusCode: HttpStatus.OK,
375-
message: ResponseMessages.user.success.update,
376-
data: userDetails
377-
};
378-
379-
return res.status(HttpStatus.OK).json(finalResponse);
380-
}
368+
369+
@Put('/password/:email')
370+
@ApiOperation({
371+
summary: 'Store user password details',
372+
description: 'Securely store and update the user’s password details.'
373+
})
374+
@ApiExcludeEndpoint()
375+
@ApiBearerAuth()
376+
@UseGuards(AuthGuard('jwt'), UserAccessGuard)
377+
async addPasskey(
378+
@Body() userInfo: AddPasskeyDetailsDto,
379+
@User() reqUser: user,
380+
@Res() res: Response
381+
): Promise<Response> {
382+
const userDetails = await this.userService.addPasskey(reqUser.email, userInfo);
383+
const finalResponse = {
384+
statusCode: HttpStatus.OK,
385+
message: ResponseMessages.user.success.update,
386+
data: userDetails
387+
};
388+
389+
return res.status(HttpStatus.OK).json(finalResponse);
390+
}
381391

382392
/**
383-
* Updates platform settings.
384-
* @body UpdatePlatformSettingsDto
385-
*
386-
* @returns Status of the update operation.
387-
*/
393+
* Updates platform settings.
394+
* @body UpdatePlatformSettingsDto
395+
*
396+
* @returns Status of the update operation.
397+
*/
388398
@Put('/platform-settings')
389399
@ApiOperation({
390400
summary: 'Update platform settings',
@@ -406,4 +416,19 @@ export class UserController {
406416

407417
return res.status(HttpStatus.OK).json(finalResponse);
408418
}
409-
}
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+
}
434+
}

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

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ import { NATSClient } from '@credebl/common/NATSClient';
1515

1616
@Injectable()
1717
export class UserService extends BaseService {
18-
constructor(@Inject('NATS_CLIENT') private readonly serviceProxy: ClientProxy, private readonly natsClient : NATSClient) {
18+
constructor(
19+
@Inject('NATS_CLIENT') private readonly serviceProxy: ClientProxy,
20+
private readonly natsClient: NATSClient
21+
) {
1922
super('User Service');
2023
}
2124

@@ -25,8 +28,8 @@ export class UserService extends BaseService {
2528
}
2629

2730
async getPublicProfile(username: string): Promise<object> {
28-
const payload = { username };
29-
return this.natsClient.sendNatsMessage(this.serviceProxy, 'get-user-public-profile', payload);
31+
const payload = { username };
32+
return this.natsClient.sendNatsMessage(this.serviceProxy, 'get-user-public-profile', payload);
3033
}
3134

3235
async updateUserProfile(updateUserProfileDto: UpdateUserProfileDto): Promise<user> {
@@ -43,24 +46,19 @@ export class UserService extends BaseService {
4346
const payload = { id };
4447
return this.natsClient.sendNatsMessage(this.serviceProxy, 'get-user-by-keycloak', payload);
4548
}
46-
49+
4750
async invitations(id: string, status: string, getAllInvitationsDto: GetAllInvitationsDto): Promise<IUserInvitations> {
4851
const { pageNumber, pageSize, search } = getAllInvitationsDto;
4952
const payload = { id, status, pageNumber, pageSize, search };
5053
return this.natsClient.sendNatsMessage(this.serviceProxy, 'get-org-invitations', payload);
5154
}
5255

53-
async acceptRejectInvitaion(
54-
acceptRejectInvitation: AcceptRejectInvitationDto,
55-
userId: string
56-
): Promise<string> {
56+
async acceptRejectInvitaion(acceptRejectInvitation: AcceptRejectInvitationDto, userId: string): Promise<string> {
5757
const payload = { acceptRejectInvitation, userId };
5858
return this.natsClient.sendNatsMessage(this.serviceProxy, 'accept-reject-invitations', payload);
5959
}
6060

61-
async get(
62-
paginationDto:PaginationDto
63-
): Promise<object> {
61+
async get(paginationDto: PaginationDto): Promise<object> {
6462
const { pageNumber, pageSize, search } = paginationDto;
6563
const payload = { pageNumber, pageSize, search };
6664
return this.natsClient.sendNatsMessage(this.serviceProxy, 'fetch-users', payload);
@@ -94,4 +92,8 @@ export class UserService extends BaseService {
9492
const payload = { email };
9593
return this.natsClient.sendNatsMessage(this.serviceProxy, 'get-user-info-by-user-email-keycloak', payload);
9694
}
95+
96+
async deleteInactiveSessions(): Promise<void> {
97+
return this.natsClient.sendNatsMessage(this.serviceProxy, 'delete-inactive-sessions', '');
98+
}
9799
}

apps/user/repositories/user.repository.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -987,4 +987,30 @@ export class UserRepository {
987987
throw error;
988988
}
989989
}
990+
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+
`;
1009+
this.logger.debug('Response::', response);
1010+
return response;
1011+
} catch (error) {
1012+
this.logger.error(`Error in deleting the in active sessions::${error.message}`);
1013+
throw error;
1014+
}
1015+
}
9901016
}

apps/user/src/user.controller.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,4 +269,9 @@ 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+
}
272277
}

apps/user/src/user.service.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,4 +1335,13 @@ export class UserService {
13351335
throw new RpcException(error.response ? error.response : error);
13361336
}
13371337
}
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+
}
13381347
}

0 commit comments

Comments
 (0)