Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"license": "BUSL-1.1",
"dependencies": {
"@aws-sdk/client-s3": "^3.637.0",
"@aws-sdk/client-sns": "^3.1049.0",
"@aws-sdk/client-textract": "^3.873.0",
"@aws-sdk/s3-request-presigner": "^3.828.0",
"@elasticemail/elasticemail-client": "^4.0.23",
Expand Down
343 changes: 185 additions & 158 deletions src/controllers/authentication.controller.ts
Original file line number Diff line number Diff line change
@@ -1,168 +1,195 @@
import { Body, Controller, Get, HttpCode, HttpStatus, Logger, Param, ParseIntPipe, Patch, Post, Res, Headers } from '@nestjs/common';
import { ApiBearerAuth, ApiHeader, ApiTags } from '@nestjs/swagger';
import { Response } from 'express';
import {
Body,
Controller,
Get,
HttpCode,
HttpStatus,
Logger,
Param,
ParseIntPipe,
Patch,
Post,
Res,
Headers,
} from "@nestjs/common";
import { ApiBearerAuth, ApiHeader, ApiTags } from "@nestjs/swagger";
import { Response } from "express";
import { ActiveUser } from "../decorators/active-user.decorator";
import { Public } from '../decorators/public.decorator';
import { Public } from "../decorators/public.decorator";
import { ChangePasswordDto } from "../dtos/change-password.dto";
import { ConfirmForgotPasswordDto } from '../dtos/confirm-forgot-password.dto';
import { CreateApiKeyDto } from '../dtos/create-api-key.dto';
import { UpdateApiKeyDto } from '../dtos/update-api-key.dto';
import { InitiateForgotPasswordDto } from '../dtos/initiate-forgot-password.dto';
import { RefreshTokenDto } from '../dtos/refresh-token.dto';
import { SsoExchangeDto } from '../dtos/sso-exchange.dto';
import { SignInDto } from '../dtos/sign-in.dto';
import { RegisterPrivateDto } from '../dtos/register-private.dto';
import { SignUpDto } from '../dtos/sign-up.dto';
import { ConfirmForgotPasswordDto } from "../dtos/confirm-forgot-password.dto";
import { CreateApiKeyDto } from "../dtos/create-api-key.dto";
import { UpdateApiKeyDto } from "../dtos/update-api-key.dto";
import { InitiateForgotPasswordDto } from "../dtos/initiate-forgot-password.dto";
import { RefreshTokenDto } from "../dtos/refresh-token.dto";
import { SsoExchangeDto } from "../dtos/sso-exchange.dto";
import { SignInDto } from "../dtos/sign-in.dto";
import { RegisterPrivateDto } from "../dtos/register-private.dto";
import { SignUpDto } from "../dtos/sign-up.dto";
import { ActiveUserData } from "../interfaces/active-user-data.interface";
import { ApiKeyService } from '../services/api-key.service';
import { AuthenticationService } from '../services/authentication.service';

import { ApiKeyService } from "../services/api-key.service";
import { AuthenticationService } from "../services/authentication.service";

// @Auth(AuthType.None)
@Controller('iam')
@Controller("iam")
@ApiTags("Solid Core")
// @UseGuards(ThrottlerGuard)
// @SkipThrottle({login: true, short: true, burst: true, sustained: true}) // disable all sets by default for this controller
export class AuthenticationController {
private readonly logger = new Logger(AuthenticationController.name);

constructor(
private readonly authService: AuthenticationService,
private readonly apiKeyService: ApiKeyService,
) { }

@Public()
// @SkipThrottle({ login: false, short: true, burst: true, sustained: true }) //Enable the login throttle only
@Post('register')
signUp(@Body() signUpDto: SignUpDto) {
return this.authService.signUp(signUpDto);
}

@ApiBearerAuth("jwt")
@Post('register-private')
signUpPrivate(@Body() signUpDto: RegisterPrivateDto, @ActiveUser() activeUser: ActiveUserData) {
return this.authService.signUp(signUpDto, activeUser);
}

@Public()
// @SkipThrottle({ login: false, short: true, burst: true, sustained: true }) //Enable the login throttle only
@HttpCode(HttpStatus.OK) // by default @Post does 201, we wanted 200 - hence using @HttpCode(HttpStatus.OK)
@Post('authenticate')
async signIn(
@Res({ passthrough: true }) response: Response,
@Body() signInDto: SignInDto
) {
// This means that we are passing the token back in plain text.
// This is less secure.
// console.log("signInDto in Signin Controller", signInDto);

return this.authService.signIn(signInDto);

// This means we are setting the token as a http only cookie.
// const accessToken = await this.authService.signIn(signInDto);
// response.cookie('accessToken', accessToken, {
// secure: true,
// httpOnly: true,
// sameSite: true,
// });
}

@Public()
// @SkipThrottle({ login: false, short: true, burst: true, sustained: true }) //Enable the login throttle only
@HttpCode(HttpStatus.OK) // changed since the default is 201
@Post('refresh-tokens')
refreshTokens(@Body() refreshTokenDto: RefreshTokenDto) {
return this.authService.refreshTokens(refreshTokenDto);
}

@Public()
// @SkipThrottle({ login: false, short: true, burst: true, sustained: true }) //Enable the login throttle only
@Post('initiate/forgot-password')
initiateForgotPassword(@Body() initiateForgotPasswordDto: InitiateForgotPasswordDto) {
return this.authService.initiateForgotPassword(initiateForgotPasswordDto);
}

@Public()
// @SkipThrottle({ login: false, short: true, burst: true, sustained: true }) //Enable the login throttle only
@Post('confirm/forgot-password')
confirmForgotPassword(@Body() confirmForgotPasswordDto: ConfirmForgotPasswordDto) {
return this.authService.confirmForgotPassword(confirmForgotPasswordDto);
}

@ApiBearerAuth("jwt")
@Post('change-password')
changePassword(@Body() changePasswordDto: ChangePasswordDto, @ActiveUser() activeUser: ActiveUserData) {
return this.authService.changePassword(changePasswordDto, activeUser);
}

@ApiBearerAuth("jwt")
@Get('me')
me(
@ActiveUser() activeUser: ActiveUserData
) {
return this.authService.me(activeUser);
}

@ApiBearerAuth("jwt")
@Post('logout')
@Public()
@HttpCode(HttpStatus.OK)
async logout(@Body('refreshToken') refreshToken: string) {
return this.authService.logout(refreshToken);
}

@ApiBearerAuth("jwt")
@Post('api-keys')
@HttpCode(HttpStatus.CREATED)
generateApiKey(
@Body() dto: CreateApiKeyDto,
@ActiveUser() activeUser: ActiveUserData,
) {
return this.apiKeyService.generate(activeUser.sub, dto);
}

@ApiBearerAuth("jwt")
@Post('api-keys/users/:userId')
@HttpCode(HttpStatus.CREATED)
generateApiKeyForUser(
@Param('userId', ParseIntPipe) userId: number,
@Body() dto: CreateApiKeyDto,
) {
return this.apiKeyService.generate(userId, dto);
}

@ApiBearerAuth("jwt")
@Patch('api-keys/:id')
@HttpCode(HttpStatus.OK)
updateApiKey(
@Param('id', ParseIntPipe) id: number,
@Body() dto: UpdateApiKeyDto,
@ActiveUser() activeUser: ActiveUserData,
) {
return this.apiKeyService.updateKey(id, activeUser.sub, dto);
}

@Public()
@ApiHeader({ name: 'solidx-api-key', required: true, description: 'API key for authenticating the request' })
@Get('api-keys/me')
async apiKeyMe(@Headers('solidx-api-key') apiKey: string) {
return this.apiKeyService.apiKeyMe(apiKey);
}

@Post('sso/code')
@HttpCode(HttpStatus.OK)
generateSsoCode(
@ActiveUser() activeUser: ActiveUserData,
@Headers('authorization') authorization: string,
) {
const rawAccessToken = authorization?.replace(/^Bearer\s+/i, '');
return this.authService.generateSsoCode(activeUser, rawAccessToken);
}

@Public()
@Post('sso/exchange')
@HttpCode(HttpStatus.OK)
exchangeSsoCode(@Body() ssoExchangeDto: SsoExchangeDto) {
return this.authService.exchangeSsoCode(ssoExchangeDto.code);
}
private readonly logger = new Logger(AuthenticationController.name);

constructor(
private readonly authService: AuthenticationService,
private readonly apiKeyService: ApiKeyService,
) {}

@Public()
// @SkipThrottle({ login: false, short: true, burst: true, sustained: true }) //Enable the login throttle only
@Post("register")
signUp(@Body() signUpDto: SignUpDto) {
return this.authService.signUp(signUpDto);
}

@ApiBearerAuth("jwt")
@Post("register-private")
signUpPrivate(
@Body() signUpDto: RegisterPrivateDto,
@ActiveUser() activeUser: ActiveUserData,
) {
return this.authService.signUp(signUpDto, activeUser);
}

@Public()
// @SkipThrottle({ login: false, short: true, burst: true, sustained: true }) //Enable the login throttle only
@HttpCode(HttpStatus.OK) // by default @Post does 201, we wanted 200 - hence using @HttpCode(HttpStatus.OK)
@Post("authenticate")
async signIn(
@Res({ passthrough: true }) response: Response,
@Body() signInDto: SignInDto,
) {
// This means that we are passing the token back in plain text.
// This is less secure.
// console.log("signInDto in Signin Controller", signInDto);

return this.authService.signIn(signInDto);

// This means we are setting the token as a http only cookie.
// const accessToken = await this.authService.signIn(signInDto);
// response.cookie('accessToken', accessToken, {
// secure: true,
// httpOnly: true,
// sameSite: true,
// });
}

@Public()
// @SkipThrottle({ login: false, short: true, burst: true, sustained: true }) //Enable the login throttle only
@HttpCode(HttpStatus.OK) // changed since the default is 201
@Post("refresh-tokens")
refreshTokens(@Body() refreshTokenDto: RefreshTokenDto) {
return this.authService.refreshTokens(refreshTokenDto);
}

@Public()
// @SkipThrottle({ login: false, short: true, burst: true, sustained: true }) //Enable the login throttle only
@Post("initiate/forgot-password")
initiateForgotPassword(
@Body() initiateForgotPasswordDto: InitiateForgotPasswordDto,
) {
return this.authService.initiateForgotPassword(initiateForgotPasswordDto);
}

@Public()
// @SkipThrottle({ login: false, short: true, burst: true, sustained: true }) //Enable the login throttle only
@Post("confirm/forgot-password")
confirmForgotPassword(
@Body() confirmForgotPasswordDto: ConfirmForgotPasswordDto,
) {
return this.authService.confirmForgotPassword(confirmForgotPasswordDto);
}

@ApiBearerAuth("jwt")
@Post("change-password")
changePassword(
@Body() changePasswordDto: ChangePasswordDto,
@ActiveUser() activeUser: ActiveUserData,
) {
return this.authService.changePassword(changePasswordDto, activeUser);
}

@ApiBearerAuth("jwt")
@Get("me")
me(@ActiveUser() activeUser: ActiveUserData) {
return this.authService.me(activeUser);
}

@ApiBearerAuth("jwt")
@Post("logout")
@Public()
@HttpCode(HttpStatus.OK)
async logout(
@Body("refreshToken") refreshToken: string,
@Body("deviceId") deviceId?: string,
) {
return this.authService.logout(refreshToken, deviceId);
}

@ApiBearerAuth("jwt")
@Post("api-keys")
@HttpCode(HttpStatus.CREATED)
generateApiKey(
@Body() dto: CreateApiKeyDto,
@ActiveUser() activeUser: ActiveUserData,
) {
return this.apiKeyService.generate(activeUser.sub, dto);
}

@ApiBearerAuth("jwt")
@Post("api-keys/users/:userId")
@HttpCode(HttpStatus.CREATED)
generateApiKeyForUser(
@Param("userId", ParseIntPipe) userId: number,
@Body() dto: CreateApiKeyDto,
) {
return this.apiKeyService.generate(userId, dto);
}

@ApiBearerAuth("jwt")
@Patch("api-keys/:id")
@HttpCode(HttpStatus.OK)
updateApiKey(
@Param("id", ParseIntPipe) id: number,
@Body() dto: UpdateApiKeyDto,
@ActiveUser() activeUser: ActiveUserData,
) {
return this.apiKeyService.updateKey(id, activeUser.sub, dto);
}

@Public()
@ApiHeader({
name: "solidx-api-key",
required: true,
description: "API key for authenticating the request",
})
@Get("api-keys/me")
async apiKeyMe(@Headers("solidx-api-key") apiKey: string) {
return this.apiKeyService.apiKeyMe(apiKey);
}

@Post("sso/code")
@HttpCode(HttpStatus.OK)
generateSsoCode(
@ActiveUser() activeUser: ActiveUserData,
@Headers("authorization") authorization: string,
) {
const rawAccessToken = authorization?.replace(/^Bearer\s+/i, "");
return this.authService.generateSsoCode(activeUser, rawAccessToken);
}

@Public()
@Post("sso/exchange")
@HttpCode(HttpStatus.OK)
exchangeSsoCode(@Body() ssoExchangeDto: SsoExchangeDto) {
return this.authService.exchangeSsoCode(ssoExchangeDto.code);
}
}
Loading