From 0d02e6503baff5b97e2d093eb1752d32a4094597 Mon Sep 17 00:00:00 2001 From: Anand Chowdhary Date: Sat, 9 Jan 2021 18:55:15 +0530 Subject: [PATCH] :recycle: Update approved subnet, session, webhook modules --- .../approved-subnets.controller.ts | 7 +++- .../approved-subnets.service.ts | 29 ++++++++------- src/modules/sessions/sessions.controller.ts | 29 ++++++++++----- src/modules/sessions/sessions.service.ts | 37 +++++++++++++------ src/modules/webhooks/webhooks.controller.ts | 15 ++++++-- src/modules/webhooks/webhooks.service.ts | 25 +++++++------ 6 files changed, 90 insertions(+), 52 deletions(-) diff --git a/src/modules/approved-subnets/approved-subnets.controller.ts b/src/modules/approved-subnets/approved-subnets.controller.ts index e815aece6..3c314847b 100644 --- a/src/modules/approved-subnets/approved-subnets.controller.ts +++ b/src/modules/approved-subnets/approved-subnets.controller.ts @@ -19,6 +19,7 @@ import { ApprovedSubnetsService } from './approved-subnets.service'; export class ApprovedSubnetController { constructor(private approvedSubnetsService: ApprovedSubnetsService) {} + /** Get approved subnets for a user */ @Get() @Scopes('user-{userId}:read-approved-subnet-*') async getAll( @@ -38,21 +39,23 @@ export class ApprovedSubnetController { }); } + /** Get an approved subnet for a user */ @Get(':id') @Scopes('user-{userId}:read-approved-subnet-{id}') async get( @Param('userId', ParseIntPipe) userId: number, @Param('id', ParseIntPipe) id: number, ): Promise> { - return this.approvedSubnetsService.getApprovedSubnet(userId, Number(id)); + return this.approvedSubnetsService.getApprovedSubnet(userId, id); } + /** Delete an approved subnet for a user */ @Delete(':id') @Scopes('user-{userId}:delete-approved-subnet-{id}') async remove( @Param('userId', ParseIntPipe) userId: number, @Param('id', ParseIntPipe) id: number, ): Promise> { - return this.approvedSubnetsService.deleteApprovedSubnet(userId, Number(id)); + return this.approvedSubnetsService.deleteApprovedSubnet(userId, id); } } diff --git a/src/modules/approved-subnets/approved-subnets.service.ts b/src/modules/approved-subnets/approved-subnets.service.ts index e723f22bb..d1ac06cb1 100644 --- a/src/modules/approved-subnets/approved-subnets.service.ts +++ b/src/modules/approved-subnets/approved-subnets.service.ts @@ -8,7 +8,6 @@ import type { Prisma } from '@prisma/client'; import { ApprovedSubnet } from '@prisma/client'; import { compare, hash } from 'bcrypt'; import anonymize from 'ip-anonymize'; -import { Configuration } from '../../config/configuration.interface'; import { APPROVED_SUBNET_NOT_FOUND, UNAUTHORIZED_RESOURCE, @@ -36,16 +35,20 @@ export class ApprovedSubnetsService { }, ): Promise[]> { const { skip, take, cursor, where, orderBy } = params; - const ApprovedSubnet = await this.prisma.approvedSubnet.findMany({ - skip, - take, - cursor, - where: { ...where, user: { id: userId } }, - orderBy, - }); - return ApprovedSubnet.map((user) => - this.prisma.expose(user), - ); + try { + const ApprovedSubnet = await this.prisma.approvedSubnet.findMany({ + skip, + take, + cursor, + where: { ...where, user: { id: userId } }, + orderBy, + }); + return ApprovedSubnet.map((user) => + this.prisma.expose(user), + ); + } catch (error) { + return []; + } } async getApprovedSubnet( @@ -82,9 +85,7 @@ export class ApprovedSubnetsService { async approveNewSubnet(userId: number, ipAddress: string) { const subnet = await hash( anonymize(ipAddress), - this.configService.get( - 'security.saltRounds', - ) ?? 10, + this.configService.get('security.saltRounds') ?? 10, ); const location = await this.geolocationService.getLocation(ipAddress); const approved = await this.prisma.approvedSubnet.create({ diff --git a/src/modules/sessions/sessions.controller.ts b/src/modules/sessions/sessions.controller.ts index f8b08e272..bb5b1041f 100644 --- a/src/modules/sessions/sessions.controller.ts +++ b/src/modules/sessions/sessions.controller.ts @@ -5,6 +5,7 @@ import { Param, ParseIntPipe, Query, + Req, } from '@nestjs/common'; import { Session } from '@prisma/client'; import { CursorPipe } from '../../pipes/cursor.pipe'; @@ -12,6 +13,7 @@ import { OptionalIntPipe } from '../../pipes/optional-int.pipe'; import { OrderByPipe } from '../../pipes/order-by.pipe'; import { WherePipe } from '../../pipes/where.pipe'; import { Expose } from '../../providers/prisma/prisma.interface'; +import { UserRequest } from '../auth/auth.interface'; import { Scopes } from '../auth/scope.decorator'; import { SessionsService } from './sessions.service'; @@ -19,9 +21,11 @@ import { SessionsService } from './sessions.service'; export class SessionController { constructor(private sessionsService: SessionsService) {} + /** Get sessions for a user */ @Get() @Scopes('user-{userId}:read-session-*') async getAll( + @Req() req: UserRequest, @Param('userId', ParseIntPipe) userId: number, @Query('skip', OptionalIntPipe) skip?: number, @Query('take', OptionalIntPipe) take?: number, @@ -29,30 +33,37 @@ export class SessionController { @Query('where', WherePipe) where?: Record, @Query('orderBy', OrderByPipe) orderBy?: Record, ): Promise[]> { - return this.sessionsService.getSessions(userId, { - skip, - take, - orderBy, - cursor, - where, - }); + return this.sessionsService.getSessions( + userId, + { + skip, + take, + orderBy, + cursor, + where, + }, + req.user?.sessionId, + ); } + /** Get a session for a user */ @Get(':id') @Scopes('user-{userId}:read-session-{id}') async get( + @Req() req: UserRequest, @Param('userId', ParseIntPipe) userId: number, @Param('id', ParseIntPipe) id: number, ): Promise> { - return this.sessionsService.getSession(userId, Number(id)); + return this.sessionsService.getSession(userId, id, req.user?.sessionId); } + /** Delete a session for a user */ @Delete(':id') @Scopes('user-{userId}:delete-session-{id}') async remove( @Param('userId', ParseIntPipe) userId: number, @Param('id', ParseIntPipe) id: number, ): Promise> { - return this.sessionsService.deleteSession(userId, Number(id)); + return this.sessionsService.deleteSession(userId, id); } } diff --git a/src/modules/sessions/sessions.service.ts b/src/modules/sessions/sessions.service.ts index 416c04cad..5da0e8379 100644 --- a/src/modules/sessions/sessions.service.ts +++ b/src/modules/sessions/sessions.service.ts @@ -15,6 +15,7 @@ import { PrismaService } from '../../providers/prisma/prisma.service'; @Injectable() export class SessionsService { constructor(private prisma: PrismaService) {} + async getSessions( userId: number, params: { @@ -24,19 +25,30 @@ export class SessionsService { where?: Prisma.SessionWhereInput; orderBy?: Prisma.SessionOrderByInput; }, - ): Promise[]> { + sessionId?: number, + ): Promise[]> { const { skip, take, cursor, where, orderBy } = params; - const sessions = await this.prisma.session.findMany({ - skip, - take, - cursor, - where: { ...where, user: { id: userId } }, - orderBy, - }); - return sessions.map((user) => this.prisma.expose(user)); + try { + const sessions = await this.prisma.session.findMany({ + skip, + take, + cursor, + where: { ...where, user: { id: userId } }, + orderBy, + }); + return sessions + .map((user) => this.prisma.expose(user)) + .map((i) => ({ ...i, isCurrentSession: sessionId === i.id })); + } catch (error) { + return []; + } } - async getSession(userId: number, id: number): Promise> { + async getSession( + userId: number, + id: number, + sessionId?: number, + ): Promise> { const session = await this.prisma.session.findUnique({ where: { id }, }); @@ -44,7 +56,10 @@ export class SessionsService { if (session.userId !== userId) throw new UnauthorizedException(UNAUTHORIZED_RESOURCE); if (!session) throw new NotFoundException(SESSION_NOT_FOUND); - return this.prisma.expose(session); + return { + ...this.prisma.expose(session), + isCurrentSession: sessionId === session.id, + }; } async deleteSession(userId: number, id: number): Promise> { diff --git a/src/modules/webhooks/webhooks.controller.ts b/src/modules/webhooks/webhooks.controller.ts index 1a2e5633b..c5aee2183 100644 --- a/src/modules/webhooks/webhooks.controller.ts +++ b/src/modules/webhooks/webhooks.controller.ts @@ -29,6 +29,7 @@ import { WebhooksService } from './webhooks.service'; export class WebhookController { constructor(private webhooksService: WebhooksService) {} + /** Create a webhook for a group */ @Post() @AuditLog('create-webhook') @Scopes('group-{groupId}:write-webhook-*') @@ -39,6 +40,7 @@ export class WebhookController { return this.webhooksService.createWebhook(groupId, data); } + /** Get webhooks for a group */ @Get() @Scopes('group-{groupId}:read-webhook-*') async getAll( @@ -58,21 +60,24 @@ export class WebhookController { }); } + /** Get webhook scopes for a group */ @Get('scopes') @Scopes('group-{groupId}:write-webhook-*') async scopes(): Promise> { return this.webhooksService.getWebhookScopes(); } + /** Get a webhook for a group */ @Get(':id') @Scopes('group-{groupId}:read-webhook-{id}') async get( @Param('groupId', ParseIntPipe) groupId: number, @Param('id', ParseIntPipe) id: number, ): Promise> { - return this.webhooksService.getWebhook(groupId, Number(id)); + return this.webhooksService.getWebhook(groupId, id); } + /** Update a webhook for a group */ @Patch(':id') @AuditLog('update-webhook') @Scopes('group-{groupId}:write-webhook-{id}') @@ -81,9 +86,10 @@ export class WebhookController { @Param('groupId', ParseIntPipe) groupId: number, @Param('id', ParseIntPipe) id: number, ): Promise> { - return this.webhooksService.updateWebhook(groupId, Number(id), data); + return this.webhooksService.updateWebhook(groupId, id, data); } + /** Replace a webhook for a group */ @Put(':id') @AuditLog('update-webhook') @Scopes('group-{groupId}:write-webhook-{id}') @@ -92,9 +98,10 @@ export class WebhookController { @Param('groupId', ParseIntPipe) groupId: number, @Param('id', ParseIntPipe) id: number, ): Promise> { - return this.webhooksService.updateWebhook(groupId, Number(id), data); + return this.webhooksService.updateWebhook(groupId, id, data); } + /** Delete a webhook for a group */ @Delete(':id') @AuditLog('delete-webhook') @Scopes('group-{groupId}:delete-webhook-{id}') @@ -102,6 +109,6 @@ export class WebhookController { @Param('groupId', ParseIntPipe) groupId: number, @Param('id', ParseIntPipe) id: number, ): Promise> { - return this.webhooksService.deleteWebhook(groupId, Number(id)); + return this.webhooksService.deleteWebhook(groupId, id); } } diff --git a/src/modules/webhooks/webhooks.service.ts b/src/modules/webhooks/webhooks.service.ts index 9eb3046be..b53127520 100644 --- a/src/modules/webhooks/webhooks.service.ts +++ b/src/modules/webhooks/webhooks.service.ts @@ -10,7 +10,6 @@ import { Webhook } from '@prisma/client'; import got from 'got'; import PQueue from 'p-queue'; import pRetry from 'p-retry'; -import { Configuration } from '../../config/configuration.interface'; import { UNAUTHORIZED_RESOURCE, WEBHOOK_NOT_FOUND, @@ -48,14 +47,18 @@ export class WebhooksService { }, ): Promise[]> { const { skip, take, cursor, where, orderBy } = params; - const webhooks = await this.prisma.webhook.findMany({ - skip, - take, - cursor, - where: { ...where, group: { id: groupId } }, - orderBy, - }); - return webhooks.map((group) => this.prisma.expose(group)); + try { + const webhooks = await this.prisma.webhook.findMany({ + skip, + take, + cursor, + where: { ...where, group: { id: groupId } }, + orderBy, + }); + return webhooks.map((group) => this.prisma.expose(group)); + } catch (error) { + return []; + } } async getWebhook(groupId: number, id: number): Promise> { @@ -156,9 +159,7 @@ export class WebhooksService { .add(() => pRetry(() => this.callWebhook(webhook, event), { retries: - this.configService.get( - 'webhooks.retries', - ) ?? 3, + this.configService.get('webhooks.retries') ?? 3, onFailedAttempt: (error) => { this.logger.error( `Triggering webhoook failed, retrying (${error.retriesLeft} attempts left)`,