From 2d8965c8341a3823f18e1d58935f67b62bb0693d Mon Sep 17 00:00:00 2001 From: Anand Chowdhary Date: Sun, 8 Nov 2020 18:08:07 +0530 Subject: [PATCH] :fire: Remove access token module --- src/app.module.ts | 2 - .../access-tokens/access-tokens.controller.ts | 104 ---------- .../access-tokens/access-tokens.dto.ts | 76 ------- .../access-tokens/access-tokens.module.ts | 12 -- .../access-tokens/access-tokens.service.ts | 195 ------------------ 5 files changed, 389 deletions(-) delete mode 100644 src/modules/access-tokens/access-tokens.controller.ts delete mode 100644 src/modules/access-tokens/access-tokens.dto.ts delete mode 100644 src/modules/access-tokens/access-tokens.module.ts delete mode 100644 src/modules/access-tokens/access-tokens.service.ts diff --git a/src/app.module.ts b/src/app.module.ts index 3177705a6..e2838da5f 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -12,7 +12,6 @@ import configuration from './config/configuration'; import { AuditLogger } from './interceptors/audit-log.interceptor'; import { JsonBodyMiddleware } from './middleware/json-body.middleware'; import { RawBodyMiddleware } from './middleware/raw-body.middleware'; -import { AccessTokensModule } from './modules/access-tokens/access-tokens.module'; import { ApiKeysModule } from './modules/api-keys/api-keys.module'; import { ApprovedSubnetsModule } from './modules/approved-subnets/approved-subnets.module'; import { AuditLogsModule } from './modules/audit-logs/audit-logs.module'; @@ -50,7 +49,6 @@ import { WebhooksModule } from './modules/webhooks/webhooks.module'; }), EmailModule, SessionsModule, - AccessTokensModule, EmailsModule, GroupsModule, MultiFactorAuthenticationModule, diff --git a/src/modules/access-tokens/access-tokens.controller.ts b/src/modules/access-tokens/access-tokens.controller.ts deleted file mode 100644 index f5d796603..000000000 --- a/src/modules/access-tokens/access-tokens.controller.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { - Body, - Controller, - Delete, - Get, - Param, - ParseIntPipe, - Patch, - Post, - Put, - Query, -} from '@nestjs/common'; -import { accessTokens } from '@prisma/client'; -import { Expose } from '../../modules/prisma/prisma.interface'; -import { CursorPipe } from '../../pipes/cursor.pipe'; -import { OptionalIntPipe } from '../../pipes/optional-int.pipe'; -import { OrderByPipe } from '../../pipes/order-by.pipe'; -import { WherePipe } from '../../pipes/where.pipe'; -import { Scopes } from '../auth/scope.decorator'; -import { - CreateAccessTokenDto, - ReplaceAccessTokenDto, - UpdateAccessTokenDto, -} from './access-tokens.dto'; -import { AccessTokensService } from './access-tokens.service'; - -@Controller('users/:userId/access-tokens') -export class AccessTokenController { - constructor(private accessTokensService: AccessTokensService) {} - - @Post() - @Scopes('user-{userId}:write-access-token-*') - async create( - @Param('userId', ParseIntPipe) userId: number, - @Body() data: CreateAccessTokenDto, - ): Promise> { - return this.accessTokensService.createAccessToken(userId, data); - } - - @Get() - @Scopes('user-{userId}:read-access-token-*') - async getAll( - @Param('userId', ParseIntPipe) userId: number, - @Query('skip', OptionalIntPipe) skip?: number, - @Query('take', OptionalIntPipe) take?: number, - @Query('cursor', CursorPipe) cursor?: Record, - @Query('where', WherePipe) where?: Record, - @Query('orderBy', OrderByPipe) orderBy?: Record, - ): Promise[]> { - return this.accessTokensService.getAccessTokens(userId, { - skip, - take, - orderBy, - cursor, - where, - }); - } - - @Get('scopes') - @Scopes('user-{userId}:read-access-token-{id}') - async scopes( - @Param('userId', ParseIntPipe) userId: number, - ): Promise> { - return this.accessTokensService.getAccessTokenScopes(userId); - } - - @Get(':id') - @Scopes('user-{userId}:read-access-token-{id}') - async get( - @Param('userId', ParseIntPipe) userId: number, - @Param('id', ParseIntPipe) id: number, - ): Promise> { - return this.accessTokensService.getAccessToken(userId, Number(id)); - } - - @Patch(':id') - @Scopes('user-{userId}:write-access-token-{id}') - async update( - @Body() data: UpdateAccessTokenDto, - @Param('userId', ParseIntPipe) userId: number, - @Param('id', ParseIntPipe) id: number, - ): Promise> { - return this.accessTokensService.updateAccessToken(userId, Number(id), data); - } - - @Put(':id') - @Scopes('user-{userId}:write-access-token-{id}') - async replace( - @Body() data: ReplaceAccessTokenDto, - @Param('userId', ParseIntPipe) userId: number, - @Param('id', ParseIntPipe) id: number, - ): Promise> { - return this.accessTokensService.updateAccessToken(userId, Number(id), data); - } - - @Delete(':id') - @Scopes('user-{userId}:delete-access-token-{id}') - async remove( - @Param('userId', ParseIntPipe) userId: number, - @Param('id', ParseIntPipe) id: number, - ): Promise> { - return this.accessTokensService.deleteAccessToken(userId, Number(id)); - } -} diff --git a/src/modules/access-tokens/access-tokens.dto.ts b/src/modules/access-tokens/access-tokens.dto.ts deleted file mode 100644 index 8b37f920e..000000000 --- a/src/modules/access-tokens/access-tokens.dto.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { IsArray, IsNotEmpty, IsOptional, IsString } from 'class-validator'; - -export class CreateAccessTokenDto { - @IsString() - @IsOptional() - description?: string; - - @IsString() - @IsOptional() - name?: string; - - @IsArray() - @IsString({ each: true }) - @IsOptional() - scopes?: string[]; - - @IsArray() - @IsString({ each: true }) - @IsOptional() - ipRestrictions?: string[]; - - @IsArray() - @IsString({ each: true }) - @IsOptional() - referrerRestrictions?: string[]; -} - -export class UpdateAccessTokenDto { - @IsString() - @IsOptional() - description?: string; - - @IsString() - @IsOptional() - name?: string; - - @IsArray() - @IsString({ each: true }) - @IsOptional() - scopes?: string[]; - - @IsArray() - @IsString({ each: true }) - @IsOptional() - ipRestrictions?: string[]; - - @IsArray() - @IsString({ each: true }) - @IsOptional() - referrerRestrictions?: string[]; -} - -export class ReplaceAccessTokenDto { - @IsString() - @IsNotEmpty() - description!: string; - - @IsString() - @IsNotEmpty() - name!: string; - - @IsArray() - @IsString({ each: true }) - @IsNotEmpty() - scopes!: string[]; - - @IsArray() - @IsString({ each: true }) - @IsNotEmpty() - ipRestrictions!: string[]; - - @IsArray() - @IsString({ each: true }) - @IsNotEmpty() - referrerRestrictions!: string[]; -} diff --git a/src/modules/access-tokens/access-tokens.module.ts b/src/modules/access-tokens/access-tokens.module.ts deleted file mode 100644 index 20500bde0..000000000 --- a/src/modules/access-tokens/access-tokens.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Module } from '@nestjs/common'; -import { PrismaModule } from '../prisma/prisma.module'; -import { TokensModule } from '../tokens/tokens.module'; -import { AccessTokenController } from './access-tokens.controller'; -import { AccessTokensService } from './access-tokens.service'; - -@Module({ - imports: [PrismaModule, TokensModule], - controllers: [AccessTokenController], - providers: [AccessTokensService], -}) -export class AccessTokensModule {} diff --git a/src/modules/access-tokens/access-tokens.service.ts b/src/modules/access-tokens/access-tokens.service.ts deleted file mode 100644 index 963fd2796..000000000 --- a/src/modules/access-tokens/access-tokens.service.ts +++ /dev/null @@ -1,195 +0,0 @@ -import { - HttpException, - HttpStatus, - Injectable, - UnauthorizedException, -} from '@nestjs/common'; -import { - accessTokens, - accessTokensCreateInput, - accessTokensOrderByInput, - accessTokensUpdateInput, - accessTokensWhereInput, - accessTokensWhereUniqueInput, -} from '@prisma/client'; -import { Expose } from '../../modules/prisma/prisma.interface'; -import { PrismaService } from '../prisma/prisma.service'; -import { TokensService } from '../tokens/tokens.service'; - -@Injectable() -export class AccessTokensService { - constructor( - private prisma: PrismaService, - private tokensService: TokensService, - ) {} - - async createAccessToken( - userId: number, - data: Omit, 'user'>, - ): Promise { - const accessToken = this.tokensService.generateUuid(); - return this.prisma.accessTokens.create({ - data: { ...data, accessToken, user: { connect: { id: userId } } }, - }); - } - - async getAccessTokens( - userId: number, - params: { - skip?: number; - take?: number; - cursor?: accessTokensWhereUniqueInput; - where?: accessTokensWhereInput; - orderBy?: accessTokensOrderByInput; - }, - ): Promise[]> { - const { skip, take, cursor, where, orderBy } = params; - const accessTokens = await this.prisma.accessTokens.findMany({ - skip, - take, - cursor, - where: { ...where, user: { id: userId } }, - orderBy, - }); - return accessTokens.map((user) => this.prisma.expose(user)); - } - - async getAccessToken( - userId: number, - id: number, - ): Promise> { - const accessToken = await this.prisma.accessTokens.findOne({ - where: { id }, - }); - if (!accessToken) - throw new HttpException('AccessToken not found', HttpStatus.NOT_FOUND); - if (accessToken.userId !== userId) throw new UnauthorizedException(); - return this.prisma.expose(accessToken); - } - - async updateAccessToken( - userId: number, - id: number, - data: accessTokensUpdateInput, - ): Promise> { - const testAccessToken = await this.prisma.accessTokens.findOne({ - where: { id }, - }); - if (!testAccessToken) - throw new HttpException('AccessToken not found', HttpStatus.NOT_FOUND); - if (testAccessToken.userId !== userId) throw new UnauthorizedException(); - const accessToken = await this.prisma.accessTokens.update({ - where: { id }, - data, - }); - return this.prisma.expose(accessToken); - } - - async replaceAccessToken( - userId: number, - id: number, - data: accessTokensCreateInput, - ): Promise> { - const testAccessToken = await this.prisma.accessTokens.findOne({ - where: { id }, - }); - if (!testAccessToken) - throw new HttpException('AccessToken not found', HttpStatus.NOT_FOUND); - if (testAccessToken.userId !== userId) throw new UnauthorizedException(); - const accessToken = await this.prisma.accessTokens.update({ - where: { id }, - data, - }); - return this.prisma.expose(accessToken); - } - - async deleteAccessToken( - userId: number, - id: number, - ): Promise> { - const testAccessToken = await this.prisma.accessTokens.findOne({ - where: { id }, - }); - if (!testAccessToken) - throw new HttpException('AccessToken not found', HttpStatus.NOT_FOUND); - if (testAccessToken.userId !== userId) throw new UnauthorizedException(); - const accessToken = await this.prisma.accessTokens.delete({ - where: { id }, - }); - return this.prisma.expose(accessToken); - } - - async getAccessTokenScopes(userId: number): Promise> { - const scopes: Record = {}; - scopes[`user-${userId}:read-info`] = 'Read user details'; - scopes[`user-${userId}:write-info`] = 'Update user details'; - scopes[`user-${userId}:delete`] = 'Delete user'; - - scopes[`user-${userId}:write-membership-*`] = 'Create new groups'; - scopes[`user-${userId}:read-membership-*`] = 'Read group memberships'; - for await (const membership of await this.prisma.memberships.findMany({ - where: { user: { id: userId } }, - select: { id: true, group: true }, - })) { - scopes[ - `user-${userId}:read-membership-${membership.id}` - ] = `Read membership: ${membership.group.name}`; - scopes[ - `user-${userId}:write-membership-${membership.id}` - ] = `Update membership: ${membership.group.name}`; - scopes[ - `user-${userId}:delete-membership-${membership.id}` - ] = `Delete membership: ${membership.group.name}`; - } - - scopes[`user-${userId}:write-email-*`] = 'Create and update emails'; - scopes[`user-${userId}:read-email-*`] = 'Read emails'; - for await (const email of await this.prisma.emails.findMany({ - where: { user: { id: userId } }, - select: { id: true, email: true }, - })) { - scopes[ - `user-${userId}:read-email-${email.id}` - ] = `Read email: ${email.email}`; - scopes[ - `user-${userId}:delete-email-${email.id}` - ] = `Delete email: ${email.email}`; - } - - scopes[`user-${userId}:read-session-*`] = 'Read sessions'; - for await (const session of await this.prisma.sessions.findMany({ - where: { user: { id: userId } }, - select: { id: true, browser: true }, - })) { - scopes[`user-${userId}:read-session-${session.id}`] = `Read session: ${ - session.browser ?? session.id - }`; - scopes[ - `user-${userId}:delete-session-${session.id}` - ] = `Delete session: ${session.browser ?? session.id}`; - } - - scopes[`user-${userId}:read-approved-subnet-*`] = 'Read approvedSubnets'; - for await (const subnet of await this.prisma.approvedSubnets.findMany({ - where: { user: { id: userId } }, - select: { id: true, subnet: true }, - })) { - scopes[ - `user-${userId}:read-approved-subnet-${subnet.id}` - ] = `Read subnet: ${subnet.subnet}`; - scopes[ - `user-${userId}:delete-approved-subnet-${subnet.id}` - ] = `Delete subnet: ${subnet.subnet}`; - } - - scopes[`user-${userId}:delete-mfa-*`] = - 'Disable multi-factor authentication'; - scopes[`user-${userId}:write-mfa-regenerate`] = - 'Regenerate MFA backup codes'; - scopes[`user-${userId}:write-mfa-totp`] = 'Enable TOTP-based MFA'; - scopes[`user-${userId}:write-mfa-sms`] = 'Enable SMS-based MFA'; - scopes[`user-${userId}:write-mfa-email`] = 'Enable email-based MFA'; - - return scopes; - } -}