File

src/auth/auth.controller.ts

Prefix

auth

Index

Methods

Methods

Public Async changePass
changePass()
Decorators :
@Post('pass/change')
Returns : unknown
Public Async confirmCode
confirmCode(undefined: CodesDto, resp: FastifyReply)
Decorators :
@Get('/confirm/:code')
@Public()
Parameters :
Name Type Optional
CodesDto No
resp FastifyReply No
Returns : unknown
Public Async disable2fa
disable2fa(req: FastifyRequest, twofactorDto: TwoFactorDisableDto)
Decorators :
@Post('/2fa/disable')
Parameters :
Name Type Optional
req FastifyRequest No
twofactorDto TwoFactorDisableDto No
Returns : unknown
Public Async discordCb
discordCb(query: literal type)
Decorators :
@Get('/callback/discord')
@Public()
Parameters :
Name Type Optional
query literal type No
Returns : unknown
Public Async enable2fa
enable2fa(req: FastifyRequest, twofactorDto: TwoFactorEnableDto)
Decorators :
@Post('/2fa/enable')
Parameters :
Name Type Optional
req FastifyRequest No
twofactorDto TwoFactorEnableDto No
Returns : unknown
Public Async githubCb
githubCb(query: literal type)
Decorators :
@Get('/callback/github')
@Public()
Parameters :
Name Type Optional
query literal type No
Returns : unknown
Public Async init2fa
init2fa(req: FastifyRequest)
Decorators :
@Get('/2fa/init')
Parameters :
Name Type Optional
req FastifyRequest No
Returns : unknown
Public Async initResetPass
initResetPass(dto: InitResetPassDto)
Decorators :
@Public()
@Post('/reset/pass')
Parameters :
Name Type Optional
dto InitResetPassDto No
Returns : unknown
Public Async login
login(loginDto: LoginDto, request: FastifyRequest)
Decorators :
@RateLimit({for: 'Fastify', keyPrefix: 'login', points: 4, duration: 10, blockDuration: 60, errorMessage: 'You can only login 4 times every 10 seconds. Try again in 1 minute.'})
@Post('login')
@Captcha()
@Public()
Parameters :
Name Type Optional
loginDto LoginDto No
request FastifyRequest No
Returns : unknown
Public Async loginVia2fa
loginVia2fa(twofactorDto: TwoFactorLoginDto, request: FastifyRequest)
Decorators :
@Post('/2fa/login')
@Public()
Parameters :
Name Type Optional
twofactorDto TwoFactorLoginDto No
request FastifyRequest No
Returns : unknown
Public Async resendConfEmail
resendConfEmail(undefined: InitResetPassDto)
Decorators :
@RateLimit({for: 'Fastify', keyPrefix: 'resend-verification', points: 2, duration: 300, errorMessage: 'You can only resend two verification emails every 5 minutes.'})
@Public()
@Post('/confirmation/resend')
Parameters :
Name Type Optional
InitResetPassDto No
Returns : unknown
Public Async resetPas
resetPas(dto: ResetPassDto)
Decorators :
@Public()
@Post('/reset/pass/set')
Parameters :
Name Type Optional
dto ResetPassDto No
Returns : unknown
Public Async setOauthPass
setOauthPass(dto: SetOauthPassDto, request: FastifyRequest)
Decorators :
@Post('/oauth/setpass')
@Public()
Parameters :
Name Type Optional
dto SetOauthPassDto No
request FastifyRequest No
Returns : unknown
import {
  Body,
  Controller,
  Post,
  ValidationPipe,
  Param,
  Get,
  Inject,
  forwardRef,
  Req,
  Logger,
  Query,
  UnauthorizedException,
  Res,
} from '@nestjs/common';
import { AuthService } from './auth.service';
import LoginDto from './dto/login.dto';
import { Public } from '../common/decorators/public.decorator';
import { Captcha } from '../common/decorators/captcha.decorator';
import { CodesService } from '../codes/codes.service';
import { InvalidCodeException } from '../exceptions/invalid-code.exception';
import { UtilsService } from '../utils/utils.service';
import { UsersService } from '../users/users.service';
import { FastifyReply, FastifyRequest } from 'fastify';
import {
  TwoFactorDisableDto,
  TwoFactorEnableDto,
  TwoFactorLoginDto,
} from './dto/2fa.dto';
import { InvalidDataException } from '../exceptions/invalid-data.exception';
import { CodesDto } from './dto/codes.dto';
import { DiscordService } from './discord/discord.service';
import { GenericRespEnum } from '../utils/enums/responses.enum';
import { SetOauthPassDto } from './dto/setpass.dto';
import { InitResetPassDto, ResetPassDto } from './dto/resetpass.dto';
import { GithubService } from './github/github.service';
import { OauthCode } from '../../types';
import { RateLimit } from 'nestjs-rate-limiter';

@Controller('auth')
export class AuthController {
  private readonly logger = new Logger(AuthController.name);
  constructor(
    private readonly authService: AuthService,
    private readonly codesService: CodesService,
    private readonly utilsService: UtilsService,
    @Inject(forwardRef(() => UsersService))
    private readonly usersService: UsersService,
    @Inject(forwardRef(() => DiscordService))
    private readonly discordService: DiscordService,
    private readonly githubService: GithubService,
  ) {}
  @RateLimit({
    for: 'Fastify',
    keyPrefix: 'login',
    points: 4,
    duration: 10,
    blockDuration: 60,
    errorMessage:
      'You can only login 4 times every 10 seconds. Try again in 1 minute.',
  })
  @Post('login')
  @Captcha()
  @Public()
  public async login(
    @Body(new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true }))
    loginDto: LoginDto,
    @Req() request: FastifyRequest,
  ) {
    const agent = request.headers['user-agent'];
    this.logger.debug('UA', agent);
    return await this.authService.validateUser(loginDto, agent);
  }
  @Post('pass/change')
  public async changePass() {
    return 'yo';
  }

  @Get('/confirm/:code')
  @Public()
  public async confirmCode(
    @Param(new ValidationPipe()) { code }: CodesDto,
    @Res() resp: FastifyReply,
  ) {
    const meta = await this.codesService.fetchCode(code);
    switch (meta.type) {
      case 'EMAIL_CONFIRM_INIT':
        await this.usersService.confirmUserEmail(meta.user, meta.code);
        return resp
          .status(301)
          .redirect('https://dash.file.glass/login?confirmed=true');
      case 'EMAIL_CONFIRM_UPDATE':
        await this.usersService.setFieldData(meta.user, 'email', meta.excess);
        const decrypted = this.utilsService.decrypt(meta.excess!);
        await this.usersService.setFieldData(
          meta.user,
          'email_hash',
          this.utilsService.sha(decrypted),
        );
        await this.codesService.setCodeUsed(meta.code);
        return resp
          .status(301)
          .redirect('https://dash.file.glass/login?changed=true');
      default:
        throw new InvalidCodeException(false);
    }
  }

  @Get('/2fa/init')
  public async init2fa(@Req() req: FastifyRequest) {
    return await this.authService.initiallyCreate2faToken(req.user);
  }

  @Post('/2fa/enable')
  public async enable2fa(
    @Req() req: FastifyRequest,
    @Body(new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true }))
    twofactorDto: TwoFactorEnableDto,
  ) {
    if (
      !(await this.authService.isPasswordCorrectForUser(
        req.user,
        twofactorDto.password,
      ))
    ) {
      throw new InvalidDataException('PASS');
    }

    if (await this.authService.is2faCodeValid(req.user, twofactorDto.code)) {
      await this.authService.toggle2fa(req.user, true);
      return GenericRespEnum.TWOFACTOR_ON;
    } else {
      throw new InvalidDataException('TWOFACTOR');
    }
  }

  @Post('/2fa/disable')
  public async disable2fa(
    @Req() req: FastifyRequest,
    @Body(new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true }))
    twofactorDto: TwoFactorDisableDto,
  ) {
    if (
      !(await this.authService.isPasswordCorrectForUser(
        req.user,
        twofactorDto.password,
      ))
    ) {
      throw new InvalidDataException('PASS');
    } else {
      await this.authService.toggle2fa(req.user, false);
      return GenericRespEnum.TWOFACTOR_OFF;
    }
  }

  @Post('/2fa/login')
  @Public()
  public async loginVia2fa(
    @Body(new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true }))
    twofactorDto: TwoFactorLoginDto,
    @Req() request: FastifyRequest,
  ) {
    const codeData = await this.codesService.fetchCode(twofactorDto.code);

    if (
      await this.authService.is2faCodeValid(codeData.user, twofactorDto.token)
    ) {
      await this.codesService.setCodeUsed(codeData.code);
      return await this.authService.forceLogUserIn(codeData.user);
    } else {
      throw new InvalidDataException('TWOFACTOR');
    }
  }

  @Get('/callback/discord')
  @Public()
  public async discordCb(@Query() query: { code: string }) {
    return await this.discordService.onAuth(query.code);
  }

  @Get('/callback/github')
  @Public()
  public async githubCb(@Query() query: { code: string }) {
    return await this.githubService.onAuth(query.code);
  }

  @Post('/oauth/setpass')
  @Public()
  public async setOauthPass(
    @Body(new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true }))
    dto: SetOauthPassDto,
    @Req() request: FastifyRequest,
  ) {
    const code = await this.codesService.fetchCode(dto.code);
    const [tok, tokType, userId, type] = JSON.parse(code.excess) as [
      string,
      string,
      string,
      OauthCode,
    ];
    this.logger.debug(
      'Fetched code:',
      code.code,
      'token',
      tok,
      'toktype',
      tokType,
    );
    if (dto.id !== userId) {
      throw new UnauthorizedException();
    }

    switch (type) {
      case 'discord':
        return await this.authService.handleDiscordOauthPassW(
          dto,
          userId,
          tok,
          tokType,
        );
      case 'github':
        return await this.authService.handleGithubOauthPassW(dto, userId, tok);
    }
  }

  @Public()
  @Post('/reset/pass')
  public async initResetPass(
    @Body(new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true }))
    dto: InitResetPassDto,
  ) {
    return await this.authService.initResetPass(dto);
  }

  @Public()
  @Post('/reset/pass/set')
  public async resetPas(
    @Body(new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true }))
    dto: ResetPassDto,
  ) {
    return await this.authService.resetPass(dto);
  }

  @RateLimit({
    for: 'Fastify',
    keyPrefix: 'resend-verification',
    points: 2,
    duration: 300,
    errorMessage:
      'You can only resend two verification emails every 5 minutes.',
  })
  @Public()
  @Post('/confirmation/resend')
  public async resendConfEmail(
    @Body(new ValidationPipe()) { email }: InitResetPassDto,
  ) {
    const user = await this.usersService.getUser(
      this.utilsService.sha(email),
      'email_hash',
    );

    if (user?.snowflake && user?.emailVerified === false) {
      const username = await this.usersService.getUsername(user.snowflake);
      await this.usersService.sendEmailConfirmation(
        email,
        user.snowflake,
        username,
      );
    }

    return GenericRespEnum.EMAIL_CONF_SENT;
  }
}

results matching ""

    No results matching ""