diff --git a/src/auth/auth.guard.ts b/src/auth/auth.guard.ts new file mode 100644 index 0000000..20201f9 --- /dev/null +++ b/src/auth/auth.guard.ts @@ -0,0 +1,81 @@ +import { Injectable, CanActivate, ExecutionContext, UnauthorizedException } from '@nestjs/common'; +import { Request } from 'express'; +import { CredentialsService } from "src/credentials/credentials.service"; +import { DrizzleService } from "src/drizzle/drizzle.service"; +import { UsersTable } from "src/schema"; +import { eq } from "drizzle-orm"; + +@Injectable() +export class UserGuard implements CanActivate { + constructor( + private readonly credentialService: CredentialsService, + private readonly databaseService: DrizzleService + ) {} + + async canActivate( + context: ExecutionContext, + ): Promise { + const request: Request = context.switchToHttp().getRequest(); + const authHeader = request.headers.authorization; + + if (!authHeader) + throw new UnauthorizedException('No authorization header found.'); + + const token = authHeader.split(' ')[1]; + const vToken = await this.credentialService.verifyAuthToken(token) + + const user = await this.databaseService.use() + .select() + .from(UsersTable) + .where(eq(UsersTable.uuid, vToken.payload.sub)) + + if (user.length !== 1) + throw new UnauthorizedException('No such user found.'); + + if (user[0].emailCode) + throw new UnauthorizedException('Email not verified.'); + + // Inject user ID into request body + request.body.sourceUserId = vToken.payload.sub; + + return true; + } +} + +@Injectable() +export class AdminGuard implements CanActivate { + constructor( + private readonly credentialService: CredentialsService, + private readonly databaseService: DrizzleService + ) {} + + async canActivate( + context: ExecutionContext, + ): Promise { + const request: Request = context.switchToHttp().getRequest(); + const authHeader = request.headers.authorization; + + if (!authHeader) + throw new UnauthorizedException('No authorization header found.'); + + const token = authHeader.split(' ')[1]; + const vToken = await this.credentialService.verifyAuthToken(token) + + const user = await this.databaseService.use() + .select() + .from(UsersTable) + .where(eq(UsersTable.uuid, vToken.payload.sub)) + + if (user.length !== 1) + throw new UnauthorizedException('No such user found.'); + + if (!user[0].isAdmin) { + throw new UnauthorizedException('Administrator only..'); + } + + // Inject user ID into request body + request.body.sourceUserId = vToken.payload.sub; + + return true; + } +} \ No newline at end of file