Skip to content

Commit

Permalink
refactor: users, auth and azure use cases (#1233)
Browse files Browse the repository at this point in the history
  • Loading branch information
nunocaseiro authored Mar 15, 2023
1 parent 579a451 commit 486c344
Show file tree
Hide file tree
Showing 81 changed files with 938 additions and 741 deletions.
16 changes: 16 additions & 0 deletions backend/src/libs/exceptions/deleteFailedBadRequestException.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { BadRequestException, HttpStatus } from '@nestjs/common';
import { DELETE_FAILED } from './messages';

export class DeleteFailedException extends BadRequestException {
private static defaultMessage = DELETE_FAILED;

constructor(message = DeleteFailedException.defaultMessage) {
super(
{
statusCode: HttpStatus.BAD_REQUEST,
message
},
message
);
}
}
16 changes: 16 additions & 0 deletions backend/src/libs/exceptions/insertFailedBadRequestException.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { BadRequestException, HttpStatus } from '@nestjs/common';
import { INSERT_FAILED } from './messages';

export class InsertFailedException extends BadRequestException {
private static defaultMessage = INSERT_FAILED;

constructor(message = InsertFailedException.defaultMessage) {
super(
{
statusCode: HttpStatus.BAD_REQUEST,
message
},
message
);
}
}
16 changes: 16 additions & 0 deletions backend/src/libs/exceptions/updateFailedBadRequestException.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { BadRequestException, HttpStatus } from '@nestjs/common';
import { UPDATE_FAILED } from './messages';

export class UpdateFailedException extends BadRequestException {
private static defaultMessage = UPDATE_FAILED;

constructor(message = UpdateFailedException.defaultMessage) {
super(
{
statusCode: HttpStatus.BAD_REQUEST,
message
},
message
);
}
}
10 changes: 10 additions & 0 deletions backend/src/libs/exceptions/userNotFoundException.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { NotFoundException } from '@nestjs/common';
import { USER_NOT_FOUND } from 'src/libs/exceptions/messages';

export class UserNotFoundException extends NotFoundException {
private static defaultMessage = USER_NOT_FOUND;

constructor(message = UserNotFoundException.defaultMessage) {
super(message);
}
}
3 changes: 3 additions & 0 deletions backend/src/libs/interfaces/use-case.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface UseCase<T, P> {
execute(props: T): Promise<P>;
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import { Inject, Injectable, InternalServerErrorException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { MailerService } from '@nestjs-modules/mailer';
import { CreateResetTokenAuthServiceInterface } from '../interfaces/services/create-reset-token.auth.service.interface';
import { TYPES } from 'src/modules/auth/interfaces/types';
import { Inject, Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { InsertFailedException } from 'src/libs/exceptions/insertFailedBadRequestException';
import { CreateResetPasswordTokenUseCaseInterface } from '../interfaces/applications/create-reset-token.use-case.interface';
import { TYPES } from '../interfaces/types';
import { ResetPasswordRepositoryInterface } from '../repository/reset-password.repository.interface';

@Injectable()
export default class CreateResetTokenAuthService implements CreateResetTokenAuthServiceInterface {
export class CreateResetPasswordTokenUseCase implements CreateResetPasswordTokenUseCaseInterface {
constructor(
private mailerService: MailerService,
private configService: ConfigService,
@Inject(TYPES.repository.ResetPasswordRepository)
private readonly resetPasswordRepository: ResetPasswordRepositoryInterface
) {}

async create(emailAddress: string) {
async execute(emailAddress: string) {
await this.resetPasswordRepository.startTransaction();
try {
const passwordModel = await this.resetPasswordRepository.findPassword(emailAddress);
Expand All @@ -25,7 +26,7 @@ export default class CreateResetTokenAuthService implements CreateResetTokenAuth
const { token } = await this.tokenGenerator(emailAddress, true);

if (!token) {
throw new InternalServerErrorException();
throw new InsertFailedException();
}

const res = await this.emailBody(token, emailAddress);
Expand Down

This file was deleted.

This file was deleted.

16 changes: 16 additions & 0 deletions backend/src/modules/auth/applications/refresh-token.use-case.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Inject, Injectable } from '@nestjs/common';
import { RefreshTokenUseCaseInterface } from '../interfaces/applications/refresh-token.use-case.interface';
import { TYPES } from '../interfaces/types';
import { GetTokenAuthServiceInterface } from '../interfaces/services/get-token.auth.service.interface';

@Injectable()
export default class RefreshTokenUseCase implements RefreshTokenUseCaseInterface {
constructor(
@Inject(TYPES.services.GetTokenAuthService)
private readonly getTokenService: GetTokenAuthServiceInterface
) {}

execute(userId: string) {
return this.getTokenService.getAccessToken(userId);
}
}
Original file line number Diff line number Diff line change
@@ -1,36 +1,25 @@
import { GetTokenAuthServiceInterface } from 'src/modules/auth/interfaces/services/get-token.auth.service.interface';
import { INSERT_FAILED } from 'src/libs/exceptions/messages';
import { BadRequestException, Inject, Injectable } from '@nestjs/common';
import { encrypt } from 'src/libs/utils/bcrypt';
import CreateUserDto from 'src/modules/users/dto/create.user.dto';
import { Inject, Injectable } from '@nestjs/common';
import { CreateUserServiceInterface } from 'src/modules/users/interfaces/services/create.user.service.interface';
import { TYPES } from 'src/modules/users/interfaces/types';
import * as AUTH_TYPES from 'src/modules/auth/interfaces/types';
import { RegisterAuthServiceInterface } from '../interfaces/services/register.auth.service.interface';
import CreateGuestUserDto from 'src/modules/users/dto/create.guest.user.dto';
import { RegisterGuestUserUseCaseInterface } from '../interfaces/applications/register-guest-user.use-case.interface';
import { InsertFailedException } from 'src/libs/exceptions/insertFailedBadRequestException';

@Injectable()
export default class RegisterAuthService implements RegisterAuthServiceInterface {
export default class RegisterGuestUserUseCase implements RegisterGuestUserUseCaseInterface {
constructor(
@Inject(TYPES.services.CreateUserService)
private createUserService: CreateUserServiceInterface,
@Inject(AUTH_TYPES.TYPES.services.GetTokenAuthService)
private getTokenAuthService: GetTokenAuthServiceInterface
) {}

public async register(registrationData: CreateUserDto) {
const hashedPassword = await encrypt(registrationData.password);

return this.createUserService.create({
...registrationData,
password: hashedPassword
});
}

public async createGuest(guestUserData: CreateGuestUserDto) {
public async execute(guestUserData: CreateGuestUserDto) {
const guestUserCreated = await this.createUserService.createGuest(guestUserData);

if (!guestUserCreated) throw new BadRequestException(INSERT_FAILED);
if (!guestUserCreated) throw new InsertFailedException();

const { accessToken } = await this.getTokenAuthService.getTokens(guestUserCreated._id);

Expand Down
35 changes: 35 additions & 0 deletions backend/src/modules/auth/applications/register-user.use-case.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { BadRequestException, Inject, Injectable } from '@nestjs/common';
import { encrypt } from 'src/libs/utils/bcrypt';
import CreateUserDto from 'src/modules/users/dto/create.user.dto';
import { CreateUserServiceInterface } from 'src/modules/users/interfaces/services/create.user.service.interface';
import { TYPES } from 'src/modules/users/interfaces/types';
import { RegisterUserUseCaseInterface } from '../interfaces/applications/register-user.use-case.interface';
import { uniqueViolation } from 'src/infrastructure/database/errors/unique.user';
import { EmailExistsException } from '../exceptions/emailExistsException';

@Injectable()
export default class RegisterUserUseCase implements RegisterUserUseCaseInterface {
constructor(
@Inject(TYPES.services.CreateUserService)
private createUserService: CreateUserServiceInterface
) {}

public async execute(registrationData: CreateUserDto) {
const hashedPassword = await encrypt(registrationData.password);

try {
const { _id, firstName, lastName, email } = await this.createUserService.create({
...registrationData,
password: hashedPassword
});

return { _id, firstName, lastName, email };
} catch (error) {
if (error.code === uniqueViolation) {
throw new EmailExistsException();
}

throw new BadRequestException(error.message);
}
}
}
22 changes: 0 additions & 22 deletions backend/src/modules/auth/applications/register.auth.application.ts

This file was deleted.

34 changes: 34 additions & 0 deletions backend/src/modules/auth/applications/reset-password.use-case.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Inject, Injectable } from '@nestjs/common';
import { TYPES } from 'src/modules/users/interfaces/types';
import { ResetPasswordUseCaseInterface } from '../interfaces/applications/reset-password.use-case.interface';
import { UpdateUserServiceInterface } from 'src/modules/users/interfaces/services/update.user.service.interface';
import { UPDATE_FAILED } from 'src/libs/exceptions/messages';
import { InvalidTokenException } from '../exceptions/invalidTokenException';
import { UpdateFailedException } from 'src/libs/exceptions/updateFailedBadRequestException';

@Injectable()
export default class ResetPasswordUseCase implements ResetPasswordUseCaseInterface {
constructor(
@Inject(TYPES.services.UpdateUserService)
private readonly updateUserService: UpdateUserServiceInterface
) {}

async execute(token: string, newPassword: string, newPasswordConf: string) {
const email = await this.updateUserService.checkEmailOfToken(token);

if (!email) {
throw new InvalidTokenException();
}

const result = await this.updateUserService.setPassword(email, newPassword, newPasswordConf);

if (!result) {
throw new UpdateFailedException(UPDATE_FAILED);
}

return {
status: 'ok',
message: 'Password updated successfully!'
};
}
}
25 changes: 25 additions & 0 deletions backend/src/modules/auth/applications/signIn.use-case.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Inject, Injectable } from '@nestjs/common';
import UserDto from 'src/modules/users/dto/user.dto';
import { TYPES } from '../interfaces/types';
import { GetTokenAuthServiceInterface } from '../interfaces/services/get-token.auth.service.interface';
import { signIn } from '../shared/login.auth';
import { SignInUseCaseInterface } from '../interfaces/applications/signIn.use-case.interface';
import { UserNotFoundException } from 'src/libs/exceptions/userNotFoundException';

@Injectable()
export default class SignInUseCase implements SignInUseCaseInterface {
constructor(
@Inject(TYPES.services.GetTokenAuthService)
private getTokenAuthService: GetTokenAuthServiceInterface
) {}

public async execute(user: UserDto) {
const loggedUser = await signIn(user, this.getTokenAuthService, 'local');

if (!loggedUser) {
throw new UserNotFoundException();
}

return loggedUser;
}
}
30 changes: 30 additions & 0 deletions backend/src/modules/auth/applications/statistics.auth.use-case.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Inject, Injectable } from '@nestjs/common';
import * as User from 'src/modules/users/interfaces/types';
import * as Teams from 'src/modules/teams/interfaces/types';
import * as Boards from 'src/modules/boards/interfaces/types';
import { GetBoardApplicationInterface } from 'src/modules/boards/interfaces/applications/get.board.application.interface';
import { GetTeamApplicationInterface } from 'src/modules/teams/interfaces/applications/get.team.application.interface';
import { GetUserServiceInterface } from 'src/modules/users/interfaces/services/get.user.service.interface';
import { StatisticsAuthUserUseCaseInterface } from '../interfaces/applications/statistics.auth.use-case.interface';

@Injectable()
export default class StatisticsAuthUserUseCase implements StatisticsAuthUserUseCaseInterface {
constructor(
@Inject(User.TYPES.services.GetUserService)
private getUserService: GetUserServiceInterface,
@Inject(Teams.TYPES.applications.GetTeamApplication)
private getTeamsService: GetTeamApplicationInterface,
@Inject(Boards.TYPES.applications.GetBoardApplication)
private getBoardService: GetBoardApplicationInterface
) {}

public async execute(userId: string) {
const [usersCount, teamsCount, boardsCount] = await Promise.all([
this.getUserService.countUsers(),
this.getTeamsService.countTeams(userId),
this.getBoardService.countBoards(userId)
]);

return { usersCount, teamsCount, boardsCount };
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Inject, Injectable } from '@nestjs/common';
import { TYPES } from 'src/modules/users/interfaces/types';
import { ValidateUserEmailUseCaseInterface } from '../interfaces/applications/validate-email.use-case.interface';
import { GetUserServiceInterface } from 'src/modules/users/interfaces/services/get.user.service.interface';

@Injectable()
export default class ValidateUserEmailUseCase implements ValidateUserEmailUseCaseInterface {
constructor(
@Inject(TYPES.services.GetUserService)
private readonly getUserService: GetUserServiceInterface
) {}

async execute(email: string) {
const user = await this.getUserService.getByEmail(email);

return !!user;
}
}
Loading

0 comments on commit 486c344

Please sign in to comment.