Merge branch 'logging' into 'main'
Logging See merge request mobicoop/lab/v3/services/auth!3
This commit is contained in:
		
						commit
						5d1f92cb9e
					
				
							
								
								
									
										2
									
								
								.env
								
								
								
								
							
							
						
						
									
										2
									
								
								.env
								
								
								
								
							| 
						 | 
					@ -7,8 +7,6 @@ SERVICE_PORT=5002
 | 
				
			||||||
DATABASE_URL="postgresql://auth:auth@v3-auth-db:5432/auth?schema=public"
 | 
					DATABASE_URL="postgresql://auth:auth@v3-auth-db:5432/auth?schema=public"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# RABBIT MQ
 | 
					# RABBIT MQ
 | 
				
			||||||
RMQ_EXCHANGE_NAME=user
 | 
					 | 
				
			||||||
RMQ_EXCHANGE_TYPE=topic
 | 
					 | 
				
			||||||
RMQ_URI=amqp://v3-gateway-broker:5672
 | 
					RMQ_URI=amqp://v3-gateway-broker:5672
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# POSTGRES
 | 
					# POSTGRES
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,8 +7,6 @@ SERVICE_PORT=5002
 | 
				
			||||||
DATABASE_URL="postgresql://auth:auth@db:5432/auth?schema=public"
 | 
					DATABASE_URL="postgresql://auth:auth@db:5432/auth?schema=public"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# RABBIT MQ
 | 
					# RABBIT MQ
 | 
				
			||||||
RMQ_EXCHANGES=user
 | 
					 | 
				
			||||||
RMQ_EXCHANGE_TYPE=topic
 | 
					 | 
				
			||||||
RMQ_URI=amqp://localhost:5672
 | 
					RMQ_URI=amqp://localhost:5672
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# POSTGRES
 | 
					# POSTGRES
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,26 +13,27 @@ export class AuthMessagerController {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @RabbitSubscribe({
 | 
					  @RabbitSubscribe({
 | 
				
			||||||
    exchange: 'user',
 | 
					    exchange: 'user',
 | 
				
			||||||
    routingKey: 'user.update',
 | 
					    routingKey: 'update',
 | 
				
			||||||
 | 
					    queue: 'auth-user-update',
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
  public async userUpdatedHandler(message: string) {
 | 
					  public async userUpdatedHandler(message: string) {
 | 
				
			||||||
    const updatedUser = JSON.parse(message);
 | 
					    const updatedUser = JSON.parse(message);
 | 
				
			||||||
    if (!updatedUser.hasOwnProperty('uuid')) throw new Error();
 | 
					    if (!updatedUser.hasOwnProperty('uuid')) throw new Error();
 | 
				
			||||||
    if (updatedUser.hasOwnProperty('email')) {
 | 
					    if (updatedUser.hasOwnProperty('email') && updatedUser.email) {
 | 
				
			||||||
      const updateUsernameRequest = new UpdateUsernameRequest();
 | 
					      const updateUsernameRequest = new UpdateUsernameRequest();
 | 
				
			||||||
      updateUsernameRequest.uuid = updatedUser.uuid;
 | 
					      updateUsernameRequest.uuid = updatedUser.uuid;
 | 
				
			||||||
      updateUsernameRequest.username = updatedUser.email;
 | 
					      updateUsernameRequest.username = updatedUser.email;
 | 
				
			||||||
      updateUsernameRequest.type = Type.EMAIL;
 | 
					      updateUsernameRequest.type = Type.EMAIL;
 | 
				
			||||||
      this._commandBus.execute(
 | 
					      await this._commandBus.execute(
 | 
				
			||||||
        new UpdateUsernameCommand(updateUsernameRequest),
 | 
					        new UpdateUsernameCommand(updateUsernameRequest),
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (updatedUser.hasOwnProperty('phone')) {
 | 
					    if (updatedUser.hasOwnProperty('phone') && updatedUser.phone) {
 | 
				
			||||||
      const updateUsernameRequest = new UpdateUsernameRequest();
 | 
					      const updateUsernameRequest = new UpdateUsernameRequest();
 | 
				
			||||||
      updateUsernameRequest.uuid = updatedUser.uuid;
 | 
					      updateUsernameRequest.uuid = updatedUser.uuid;
 | 
				
			||||||
      updateUsernameRequest.username = updatedUser.phone;
 | 
					      updateUsernameRequest.username = updatedUser.phone;
 | 
				
			||||||
      updateUsernameRequest.type = Type.PHONE;
 | 
					      updateUsernameRequest.type = Type.PHONE;
 | 
				
			||||||
      this._commandBus.execute(
 | 
					      await this._commandBus.execute(
 | 
				
			||||||
        new UpdateUsernameCommand(updateUsernameRequest),
 | 
					        new UpdateUsernameCommand(updateUsernameRequest),
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -40,13 +41,14 @@ export class AuthMessagerController {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @RabbitSubscribe({
 | 
					  @RabbitSubscribe({
 | 
				
			||||||
    exchange: 'user',
 | 
					    exchange: 'user',
 | 
				
			||||||
    routingKey: 'user.delete',
 | 
					    routingKey: 'delete',
 | 
				
			||||||
 | 
					    queue: 'auth-user-delete',
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
  public async userDeletedHandler(message: string) {
 | 
					  public async userDeletedHandler(message: string) {
 | 
				
			||||||
    const deletedUser = JSON.parse(message);
 | 
					    const deletedUser = JSON.parse(message);
 | 
				
			||||||
    if (!deletedUser.hasOwnProperty('uuid')) throw new Error();
 | 
					    if (!deletedUser.hasOwnProperty('uuid')) throw new Error();
 | 
				
			||||||
    const deleteAuthRequest = new DeleteAuthRequest();
 | 
					    const deleteAuthRequest = new DeleteAuthRequest();
 | 
				
			||||||
    deleteAuthRequest.uuid = deletedUser.uuid;
 | 
					    deleteAuthRequest.uuid = deletedUser.uuid;
 | 
				
			||||||
    this._commandBus.execute(new DeleteAuthCommand(deleteAuthRequest));
 | 
					    await this._commandBus.execute(new DeleteAuthCommand(deleteAuthRequest));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
import { Mapper } from '@automapper/core';
 | 
					import { Mapper } from '@automapper/core';
 | 
				
			||||||
import { InjectMapper } from '@automapper/nestjs';
 | 
					import { InjectMapper } from '@automapper/nestjs';
 | 
				
			||||||
import { Controller } from '@nestjs/common';
 | 
					import { Controller, UsePipes } from '@nestjs/common';
 | 
				
			||||||
import { CommandBus, QueryBus } from '@nestjs/cqrs';
 | 
					import { CommandBus, QueryBus } from '@nestjs/cqrs';
 | 
				
			||||||
import { GrpcMethod, RpcException } from '@nestjs/microservices';
 | 
					import { GrpcMethod, RpcException } from '@nestjs/microservices';
 | 
				
			||||||
import { DatabaseException } from 'src/modules/database/src/exceptions/DatabaseException';
 | 
					import { DatabaseException } from 'src/modules/database/src/exceptions/DatabaseException';
 | 
				
			||||||
| 
						 | 
					@ -21,8 +21,15 @@ import { Auth } from '../../domain/entities/auth';
 | 
				
			||||||
import { Username } from '../../domain/entities/username';
 | 
					import { Username } from '../../domain/entities/username';
 | 
				
			||||||
import { ValidateAuthQuery } from '../../queries/validate-auth.query';
 | 
					import { ValidateAuthQuery } from '../../queries/validate-auth.query';
 | 
				
			||||||
import { AuthPresenter } from './auth.presenter';
 | 
					import { AuthPresenter } from './auth.presenter';
 | 
				
			||||||
 | 
					import { RpcValidationPipe } from './rpc.validation-pipe';
 | 
				
			||||||
import { UsernamePresenter } from './username.presenter';
 | 
					import { UsernamePresenter } from './username.presenter';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@UsePipes(
 | 
				
			||||||
 | 
					  new RpcValidationPipe({
 | 
				
			||||||
 | 
					    whitelist: true,
 | 
				
			||||||
 | 
					    forbidUnknownValues: false,
 | 
				
			||||||
 | 
					  }),
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
@Controller()
 | 
					@Controller()
 | 
				
			||||||
export class AuthController {
 | 
					export class AuthController {
 | 
				
			||||||
  constructor(
 | 
					  constructor(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,14 @@
 | 
				
			||||||
 | 
					import { Injectable, ValidationPipe } from '@nestjs/common';
 | 
				
			||||||
 | 
					import { RpcException } from '@nestjs/microservices';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Injectable()
 | 
				
			||||||
 | 
					export class RpcValidationPipe extends ValidationPipe {
 | 
				
			||||||
 | 
					  createExceptionFactory() {
 | 
				
			||||||
 | 
					    return (validationErrors = []) => {
 | 
				
			||||||
 | 
					      return new RpcException({
 | 
				
			||||||
 | 
					        code: 3,
 | 
				
			||||||
 | 
					        message: this.flattenValidationErrors(validationErrors),
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,14 @@
 | 
				
			||||||
 | 
					import { AmqpConnection } from '@golevelup/nestjs-rabbitmq';
 | 
				
			||||||
 | 
					import { Injectable } from '@nestjs/common';
 | 
				
			||||||
 | 
					import { IMessageBroker } from '../../domain/interfaces/message-broker';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Injectable()
 | 
				
			||||||
 | 
					export class AuthMessager extends IMessageBroker {
 | 
				
			||||||
 | 
					  constructor(private readonly _amqpConnection: AmqpConnection) {
 | 
				
			||||||
 | 
					    super('auth');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  publish(routingKey: string, message: string): void {
 | 
				
			||||||
 | 
					    this._amqpConnection.publish(this.exchange, routingKey, message);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,14 @@
 | 
				
			||||||
 | 
					import { AmqpConnection } from '@golevelup/nestjs-rabbitmq';
 | 
				
			||||||
 | 
					import { Injectable } from '@nestjs/common';
 | 
				
			||||||
 | 
					import { IMessageBroker } from '../../domain/interfaces/message-broker';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Injectable()
 | 
				
			||||||
 | 
					export class LoggingMessager extends IMessageBroker {
 | 
				
			||||||
 | 
					  constructor(private readonly _amqpConnection: AmqpConnection) {
 | 
				
			||||||
 | 
					    super('logging');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  publish(routingKey: string, message: string): void {
 | 
				
			||||||
 | 
					    this._amqpConnection.publish(this.exchange, routingKey, message);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -25,8 +25,12 @@ import { AuthMessagerController } from './adapters/primaries/auth-messager.contr
 | 
				
			||||||
      useFactory: async (configService: ConfigService) => ({
 | 
					      useFactory: async (configService: ConfigService) => ({
 | 
				
			||||||
        exchanges: [
 | 
					        exchanges: [
 | 
				
			||||||
          {
 | 
					          {
 | 
				
			||||||
            name: configService.get<string>('RMQ_EXCHANGE_NAME'),
 | 
					            name: 'user',
 | 
				
			||||||
            type: configService.get<string>('RMQ_EXCHANGE_TYPE'),
 | 
					            type: 'topic',
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            name: 'logging',
 | 
				
			||||||
 | 
					            type: 'topic',
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
        uri: configService.get<string>('RMQ_URI'),
 | 
					        uri: configService.get<string>('RMQ_URI'),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					import { Injectable } from '@nestjs/common';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Injectable()
 | 
				
			||||||
 | 
					export abstract class IMessageBroker {
 | 
				
			||||||
 | 
					  exchange: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  constructor(exchange: string) {
 | 
				
			||||||
 | 
					    this.exchange = exchange;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  abstract publish(routingKey: string, message: string): void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,11 +1,15 @@
 | 
				
			||||||
import { CommandHandler } from '@nestjs/cqrs';
 | 
					import { CommandHandler } from '@nestjs/cqrs';
 | 
				
			||||||
 | 
					import { LoggingMessager } from '../../adapters/secondaries/logging.messager';
 | 
				
			||||||
import { UsernameRepository } from '../../adapters/secondaries/username.repository';
 | 
					import { UsernameRepository } from '../../adapters/secondaries/username.repository';
 | 
				
			||||||
import { AddUsernameCommand } from '../../commands/add-username.command';
 | 
					import { AddUsernameCommand } from '../../commands/add-username.command';
 | 
				
			||||||
import { Username } from '../entities/username';
 | 
					import { Username } from '../entities/username';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@CommandHandler(AddUsernameCommand)
 | 
					@CommandHandler(AddUsernameCommand)
 | 
				
			||||||
export class AddUsernameUseCase {
 | 
					export class AddUsernameUseCase {
 | 
				
			||||||
  constructor(private readonly _usernameRepository: UsernameRepository) {}
 | 
					  constructor(
 | 
				
			||||||
 | 
					    private readonly _usernameRepository: UsernameRepository,
 | 
				
			||||||
 | 
					    private readonly _loggingMessager: LoggingMessager,
 | 
				
			||||||
 | 
					  ) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async execute(command: AddUsernameCommand): Promise<Username> {
 | 
					  async execute(command: AddUsernameCommand): Promise<Username> {
 | 
				
			||||||
    const { uuid, username, type } = command.addUsernameRequest;
 | 
					    const { uuid, username, type } = command.addUsernameRequest;
 | 
				
			||||||
| 
						 | 
					@ -15,8 +19,15 @@ export class AddUsernameUseCase {
 | 
				
			||||||
        type,
 | 
					        type,
 | 
				
			||||||
        username,
 | 
					        username,
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    } catch (e) {
 | 
					    } catch (error) {
 | 
				
			||||||
      throw e;
 | 
					      this._loggingMessager.publish(
 | 
				
			||||||
 | 
					        'auth.username.add.warning',
 | 
				
			||||||
 | 
					        JSON.stringify({
 | 
				
			||||||
 | 
					          command,
 | 
				
			||||||
 | 
					          error,
 | 
				
			||||||
 | 
					        }),
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      throw error;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,12 +4,14 @@ import { CreateAuthCommand } from '../../commands/create-auth.command';
 | 
				
			||||||
import { Auth } from '../entities/auth';
 | 
					import { Auth } from '../entities/auth';
 | 
				
			||||||
import * as bcrypt from 'bcrypt';
 | 
					import * as bcrypt from 'bcrypt';
 | 
				
			||||||
import { UsernameRepository } from '../../adapters/secondaries/username.repository';
 | 
					import { UsernameRepository } from '../../adapters/secondaries/username.repository';
 | 
				
			||||||
 | 
					import { LoggingMessager } from '../../adapters/secondaries/logging.messager';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@CommandHandler(CreateAuthCommand)
 | 
					@CommandHandler(CreateAuthCommand)
 | 
				
			||||||
export class CreateAuthUseCase {
 | 
					export class CreateAuthUseCase {
 | 
				
			||||||
  constructor(
 | 
					  constructor(
 | 
				
			||||||
    private readonly _authRepository: AuthRepository,
 | 
					    private readonly _authRepository: AuthRepository,
 | 
				
			||||||
    private readonly _usernameRepository: UsernameRepository,
 | 
					    private readonly _usernameRepository: UsernameRepository,
 | 
				
			||||||
 | 
					    private readonly _loggingMessager: LoggingMessager,
 | 
				
			||||||
  ) {}
 | 
					  ) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async execute(command: CreateAuthCommand): Promise<Auth> {
 | 
					  async execute(command: CreateAuthCommand): Promise<Auth> {
 | 
				
			||||||
| 
						 | 
					@ -28,8 +30,15 @@ export class CreateAuthUseCase {
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return auth;
 | 
					      return auth;
 | 
				
			||||||
    } catch (e) {
 | 
					    } catch (error) {
 | 
				
			||||||
      throw e;
 | 
					      this._loggingMessager.publish(
 | 
				
			||||||
 | 
					        'auth.create.critical',
 | 
				
			||||||
 | 
					        JSON.stringify({
 | 
				
			||||||
 | 
					          command,
 | 
				
			||||||
 | 
					          error,
 | 
				
			||||||
 | 
					        }),
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      throw error;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
import { CommandHandler } from '@nestjs/cqrs';
 | 
					import { CommandHandler } from '@nestjs/cqrs';
 | 
				
			||||||
import { AuthRepository } from '../../adapters/secondaries/auth.repository';
 | 
					import { AuthRepository } from '../../adapters/secondaries/auth.repository';
 | 
				
			||||||
 | 
					import { LoggingMessager } from '../../adapters/secondaries/logging.messager';
 | 
				
			||||||
import { UsernameRepository } from '../../adapters/secondaries/username.repository';
 | 
					import { UsernameRepository } from '../../adapters/secondaries/username.repository';
 | 
				
			||||||
import { DeleteAuthCommand } from '../../commands/delete-auth.command';
 | 
					import { DeleteAuthCommand } from '../../commands/delete-auth.command';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +9,7 @@ export class DeleteAuthUseCase {
 | 
				
			||||||
  constructor(
 | 
					  constructor(
 | 
				
			||||||
    private readonly _authRepository: AuthRepository,
 | 
					    private readonly _authRepository: AuthRepository,
 | 
				
			||||||
    private readonly _usernameRepository: UsernameRepository,
 | 
					    private readonly _usernameRepository: UsernameRepository,
 | 
				
			||||||
 | 
					    private readonly _loggingMessager: LoggingMessager,
 | 
				
			||||||
  ) {}
 | 
					  ) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async execute(command: DeleteAuthCommand) {
 | 
					  async execute(command: DeleteAuthCommand) {
 | 
				
			||||||
| 
						 | 
					@ -18,8 +20,15 @@ export class DeleteAuthUseCase {
 | 
				
			||||||
      return await this._authRepository.delete({
 | 
					      return await this._authRepository.delete({
 | 
				
			||||||
        uuid: command.deleteAuthRequest.uuid,
 | 
					        uuid: command.deleteAuthRequest.uuid,
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    } catch (e) {
 | 
					    } catch (error) {
 | 
				
			||||||
      throw e;
 | 
					      this._loggingMessager.publish(
 | 
				
			||||||
 | 
					        'auth.delete.critical',
 | 
				
			||||||
 | 
					        JSON.stringify({
 | 
				
			||||||
 | 
					          command,
 | 
				
			||||||
 | 
					          error,
 | 
				
			||||||
 | 
					        }),
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      throw error;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,11 +1,15 @@
 | 
				
			||||||
import { UnauthorizedException } from '@nestjs/common';
 | 
					import { UnauthorizedException } from '@nestjs/common';
 | 
				
			||||||
import { CommandHandler } from '@nestjs/cqrs';
 | 
					import { CommandHandler } from '@nestjs/cqrs';
 | 
				
			||||||
 | 
					import { LoggingMessager } from '../../adapters/secondaries/logging.messager';
 | 
				
			||||||
import { UsernameRepository } from '../../adapters/secondaries/username.repository';
 | 
					import { UsernameRepository } from '../../adapters/secondaries/username.repository';
 | 
				
			||||||
import { DeleteUsernameCommand } from '../../commands/delete-username.command';
 | 
					import { DeleteUsernameCommand } from '../../commands/delete-username.command';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@CommandHandler(DeleteUsernameCommand)
 | 
					@CommandHandler(DeleteUsernameCommand)
 | 
				
			||||||
export class DeleteUsernameUseCase {
 | 
					export class DeleteUsernameUseCase {
 | 
				
			||||||
  constructor(private readonly _usernameRepository: UsernameRepository) {}
 | 
					  constructor(
 | 
				
			||||||
 | 
					    private readonly _usernameRepository: UsernameRepository,
 | 
				
			||||||
 | 
					    private readonly _loggingMessager: LoggingMessager,
 | 
				
			||||||
 | 
					  ) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async execute(command: DeleteUsernameCommand) {
 | 
					  async execute(command: DeleteUsernameCommand) {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
| 
						 | 
					@ -20,8 +24,15 @@ export class DeleteUsernameUseCase {
 | 
				
			||||||
        return await this._usernameRepository.delete({ username });
 | 
					        return await this._usernameRepository.delete({ username });
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      throw new UnauthorizedException();
 | 
					      throw new UnauthorizedException();
 | 
				
			||||||
    } catch (e) {
 | 
					    } catch (error) {
 | 
				
			||||||
      throw e;
 | 
					      this._loggingMessager.publish(
 | 
				
			||||||
 | 
					        'auth.username.delete.warning',
 | 
				
			||||||
 | 
					        JSON.stringify({
 | 
				
			||||||
 | 
					          command,
 | 
				
			||||||
 | 
					          error,
 | 
				
			||||||
 | 
					        }),
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      throw error;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,10 +3,14 @@ import { AuthRepository } from '../../adapters/secondaries/auth.repository';
 | 
				
			||||||
import { Auth } from '../entities/auth';
 | 
					import { Auth } from '../entities/auth';
 | 
				
			||||||
import * as bcrypt from 'bcrypt';
 | 
					import * as bcrypt from 'bcrypt';
 | 
				
			||||||
import { UpdatePasswordCommand } from '../../commands/update-password.command';
 | 
					import { UpdatePasswordCommand } from '../../commands/update-password.command';
 | 
				
			||||||
 | 
					import { LoggingMessager } from '../../adapters/secondaries/logging.messager';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@CommandHandler(UpdatePasswordCommand)
 | 
					@CommandHandler(UpdatePasswordCommand)
 | 
				
			||||||
export class UpdatePasswordUseCase {
 | 
					export class UpdatePasswordUseCase {
 | 
				
			||||||
  constructor(private readonly _authRepository: AuthRepository) {}
 | 
					  constructor(
 | 
				
			||||||
 | 
					    private readonly _authRepository: AuthRepository,
 | 
				
			||||||
 | 
					    private readonly _loggingMessager: LoggingMessager,
 | 
				
			||||||
 | 
					  ) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async execute(command: UpdatePasswordCommand): Promise<Auth> {
 | 
					  async execute(command: UpdatePasswordCommand): Promise<Auth> {
 | 
				
			||||||
    const { uuid, password } = command.updatePasswordRequest;
 | 
					    const { uuid, password } = command.updatePasswordRequest;
 | 
				
			||||||
| 
						 | 
					@ -16,8 +20,15 @@ export class UpdatePasswordUseCase {
 | 
				
			||||||
      return await this._authRepository.update(uuid, {
 | 
					      return await this._authRepository.update(uuid, {
 | 
				
			||||||
        password: hash,
 | 
					        password: hash,
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    } catch (e) {
 | 
					    } catch (error) {
 | 
				
			||||||
      throw e;
 | 
					      this._loggingMessager.publish(
 | 
				
			||||||
 | 
					        'auth.password.update.warning',
 | 
				
			||||||
 | 
					        JSON.stringify({
 | 
				
			||||||
 | 
					          command,
 | 
				
			||||||
 | 
					          error,
 | 
				
			||||||
 | 
					        }),
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      throw error;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,14 +1,33 @@
 | 
				
			||||||
import { CommandHandler } from '@nestjs/cqrs';
 | 
					import { Mapper } from '@automapper/core';
 | 
				
			||||||
 | 
					import { InjectMapper } from '@automapper/nestjs';
 | 
				
			||||||
 | 
					import { BadRequestException } from '@nestjs/common';
 | 
				
			||||||
 | 
					import { CommandBus, CommandHandler } from '@nestjs/cqrs';
 | 
				
			||||||
 | 
					import { LoggingMessager } from '../../adapters/secondaries/logging.messager';
 | 
				
			||||||
import { UsernameRepository } from '../../adapters/secondaries/username.repository';
 | 
					import { UsernameRepository } from '../../adapters/secondaries/username.repository';
 | 
				
			||||||
 | 
					import { AddUsernameCommand } from '../../commands/add-username.command';
 | 
				
			||||||
import { UpdateUsernameCommand } from '../../commands/update-username.command';
 | 
					import { UpdateUsernameCommand } from '../../commands/update-username.command';
 | 
				
			||||||
 | 
					import { AddUsernameRequest } from '../dtos/add-username.request';
 | 
				
			||||||
 | 
					import { UpdateUsernameRequest } from '../dtos/update-username.request';
 | 
				
			||||||
import { Username } from '../entities/username';
 | 
					import { Username } from '../entities/username';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@CommandHandler(UpdateUsernameCommand)
 | 
					@CommandHandler(UpdateUsernameCommand)
 | 
				
			||||||
export class UpdateUsernameUseCase {
 | 
					export class UpdateUsernameUseCase {
 | 
				
			||||||
  constructor(private readonly _usernameRepository: UsernameRepository) {}
 | 
					  constructor(
 | 
				
			||||||
 | 
					    private readonly _usernameRepository: UsernameRepository,
 | 
				
			||||||
 | 
					    private readonly _commandBus: CommandBus,
 | 
				
			||||||
 | 
					    @InjectMapper() private readonly _mapper: Mapper,
 | 
				
			||||||
 | 
					    private readonly _loggingMessager: LoggingMessager,
 | 
				
			||||||
 | 
					  ) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async execute(command: UpdateUsernameCommand): Promise<Username> {
 | 
					  async execute(command: UpdateUsernameCommand): Promise<Username> {
 | 
				
			||||||
    const { uuid, username, type } = command.updateUsernameRequest;
 | 
					    const { uuid, username, type } = command.updateUsernameRequest;
 | 
				
			||||||
 | 
					    if (!username) throw new BadRequestException();
 | 
				
			||||||
 | 
					    // update username if it exists, otherwise create it
 | 
				
			||||||
 | 
					    const existingUsername = await this._usernameRepository.findOne({
 | 
				
			||||||
 | 
					      uuid,
 | 
				
			||||||
 | 
					      type,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    if (existingUsername) {
 | 
				
			||||||
      try {
 | 
					      try {
 | 
				
			||||||
        return await this._usernameRepository.updateWhere(
 | 
					        return await this._usernameRepository.updateWhere(
 | 
				
			||||||
          {
 | 
					          {
 | 
				
			||||||
| 
						 | 
					@ -21,6 +40,26 @@ export class UpdateUsernameUseCase {
 | 
				
			||||||
            username,
 | 
					            username,
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					      } catch (error) {
 | 
				
			||||||
 | 
					        this._loggingMessager.publish(
 | 
				
			||||||
 | 
					          'auth.username.update.warning',
 | 
				
			||||||
 | 
					          JSON.stringify({
 | 
				
			||||||
 | 
					            command,
 | 
				
			||||||
 | 
					            error,
 | 
				
			||||||
 | 
					          }),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        throw error;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const addUsernameRequest = this._mapper.map(
 | 
				
			||||||
 | 
					      command.updateUsernameRequest,
 | 
				
			||||||
 | 
					      UpdateUsernameRequest,
 | 
				
			||||||
 | 
					      AddUsernameRequest,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      return await this._commandBus.execute(
 | 
				
			||||||
 | 
					        new AddUsernameCommand(addUsernameRequest),
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
    } catch (e) {
 | 
					    } catch (e) {
 | 
				
			||||||
      throw e;
 | 
					      throw e;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,8 @@ import { createMap, Mapper } from '@automapper/core';
 | 
				
			||||||
import { AutomapperProfile, InjectMapper } from '@automapper/nestjs';
 | 
					import { AutomapperProfile, InjectMapper } from '@automapper/nestjs';
 | 
				
			||||||
import { Injectable } from '@nestjs/common';
 | 
					import { Injectable } from '@nestjs/common';
 | 
				
			||||||
import { UsernamePresenter } from '../adapters/primaries/username.presenter';
 | 
					import { UsernamePresenter } from '../adapters/primaries/username.presenter';
 | 
				
			||||||
 | 
					import { AddUsernameRequest } from '../domain/dtos/add-username.request';
 | 
				
			||||||
 | 
					import { UpdateUsernameRequest } from '../domain/dtos/update-username.request';
 | 
				
			||||||
import { Username } from '../domain/entities/username';
 | 
					import { Username } from '../domain/entities/username';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Injectable()
 | 
					@Injectable()
 | 
				
			||||||
| 
						 | 
					@ -13,6 +15,7 @@ export class UsernameProfile extends AutomapperProfile {
 | 
				
			||||||
  override get profile() {
 | 
					  override get profile() {
 | 
				
			||||||
    return (mapper: any) => {
 | 
					    return (mapper: any) => {
 | 
				
			||||||
      createMap(mapper, Username, UsernamePresenter);
 | 
					      createMap(mapper, Username, UsernamePresenter);
 | 
				
			||||||
 | 
					      createMap(mapper, UpdateUsernameRequest, AddUsernameRequest);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@ import { Type } from '../../domain/dtos/type.enum';
 | 
				
			||||||
import { AddUsernameRequest } from '../../domain/dtos/add-username.request';
 | 
					import { AddUsernameRequest } from '../../domain/dtos/add-username.request';
 | 
				
			||||||
import { AddUsernameCommand } from '../../commands/add-username.command';
 | 
					import { AddUsernameCommand } from '../../commands/add-username.command';
 | 
				
			||||||
import { AddUsernameUseCase } from '../../domain/usecases/add-username.usecase';
 | 
					import { AddUsernameUseCase } from '../../domain/usecases/add-username.usecase';
 | 
				
			||||||
 | 
					import { LoggingMessager } from '../../adapters/secondaries/logging.messager';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const addUsernameRequest: AddUsernameRequest = {
 | 
					const addUsernameRequest: AddUsernameRequest = {
 | 
				
			||||||
  uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
 | 
					  uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
 | 
				
			||||||
| 
						 | 
					@ -22,6 +23,10 @@ const mockUsernameRepository = {
 | 
				
			||||||
  create: jest.fn().mockResolvedValue(addUsernameRequest),
 | 
					  create: jest.fn().mockResolvedValue(addUsernameRequest),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const mockMessager = {
 | 
				
			||||||
 | 
					  publish: jest.fn().mockImplementation(),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('AddUsernameUseCase', () => {
 | 
					describe('AddUsernameUseCase', () => {
 | 
				
			||||||
  let addUsernameUseCase: AddUsernameUseCase;
 | 
					  let addUsernameUseCase: AddUsernameUseCase;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,6 +38,10 @@ describe('AddUsernameUseCase', () => {
 | 
				
			||||||
          provide: UsernameRepository,
 | 
					          provide: UsernameRepository,
 | 
				
			||||||
          useValue: mockUsernameRepository,
 | 
					          useValue: mockUsernameRepository,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          provide: LoggingMessager,
 | 
				
			||||||
 | 
					          useValue: mockMessager,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        AddUsernameUseCase,
 | 
					        AddUsernameUseCase,
 | 
				
			||||||
        AuthProfile,
 | 
					        AuthProfile,
 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,7 @@ import { CreateAuthUseCase } from '../../domain/usecases/create-auth.usecase';
 | 
				
			||||||
import * as bcrypt from 'bcrypt';
 | 
					import * as bcrypt from 'bcrypt';
 | 
				
			||||||
import { UsernameRepository } from '../../adapters/secondaries/username.repository';
 | 
					import { UsernameRepository } from '../../adapters/secondaries/username.repository';
 | 
				
			||||||
import { Type } from '../../domain/dtos/type.enum';
 | 
					import { Type } from '../../domain/dtos/type.enum';
 | 
				
			||||||
 | 
					import { LoggingMessager } from '../../adapters/secondaries/logging.messager';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const newAuthRequest: CreateAuthRequest = {
 | 
					const newAuthRequest: CreateAuthRequest = {
 | 
				
			||||||
  uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
 | 
					  uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
 | 
				
			||||||
| 
						 | 
					@ -33,6 +34,10 @@ const mockUsernameRepository = {
 | 
				
			||||||
  }),
 | 
					  }),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const mockMessager = {
 | 
				
			||||||
 | 
					  publish: jest.fn().mockImplementation(),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('CreateAuthUseCase', () => {
 | 
					describe('CreateAuthUseCase', () => {
 | 
				
			||||||
  let createAuthUseCase: CreateAuthUseCase;
 | 
					  let createAuthUseCase: CreateAuthUseCase;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,6 +53,10 @@ describe('CreateAuthUseCase', () => {
 | 
				
			||||||
          provide: UsernameRepository,
 | 
					          provide: UsernameRepository,
 | 
				
			||||||
          useValue: mockUsernameRepository,
 | 
					          useValue: mockUsernameRepository,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          provide: LoggingMessager,
 | 
				
			||||||
 | 
					          useValue: mockMessager,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        CreateAuthUseCase,
 | 
					        CreateAuthUseCase,
 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
    }).compile();
 | 
					    }).compile();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@ import { classes } from '@automapper/classes';
 | 
				
			||||||
import { AutomapperModule } from '@automapper/nestjs';
 | 
					import { AutomapperModule } from '@automapper/nestjs';
 | 
				
			||||||
import { Test, TestingModule } from '@nestjs/testing';
 | 
					import { Test, TestingModule } from '@nestjs/testing';
 | 
				
			||||||
import { AuthRepository } from '../../adapters/secondaries/auth.repository';
 | 
					import { AuthRepository } from '../../adapters/secondaries/auth.repository';
 | 
				
			||||||
 | 
					import { LoggingMessager } from '../../adapters/secondaries/logging.messager';
 | 
				
			||||||
import { UsernameRepository } from '../../adapters/secondaries/username.repository';
 | 
					import { UsernameRepository } from '../../adapters/secondaries/username.repository';
 | 
				
			||||||
import { DeleteAuthCommand } from '../../commands/delete-auth.command';
 | 
					import { DeleteAuthCommand } from '../../commands/delete-auth.command';
 | 
				
			||||||
import { DeleteAuthRequest } from '../../domain/dtos/delete-auth.request';
 | 
					import { DeleteAuthRequest } from '../../domain/dtos/delete-auth.request';
 | 
				
			||||||
| 
						 | 
					@ -44,6 +45,10 @@ const mockUsernameRepository = {
 | 
				
			||||||
  deleteMany: jest.fn().mockResolvedValue(undefined),
 | 
					  deleteMany: jest.fn().mockResolvedValue(undefined),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const mockMessager = {
 | 
				
			||||||
 | 
					  publish: jest.fn().mockImplementation(),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('DeleteAuthUseCase', () => {
 | 
					describe('DeleteAuthUseCase', () => {
 | 
				
			||||||
  let deleteAuthUseCase: DeleteAuthUseCase;
 | 
					  let deleteAuthUseCase: DeleteAuthUseCase;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,6 +64,10 @@ describe('DeleteAuthUseCase', () => {
 | 
				
			||||||
          provide: UsernameRepository,
 | 
					          provide: UsernameRepository,
 | 
				
			||||||
          useValue: mockUsernameRepository,
 | 
					          useValue: mockUsernameRepository,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          provide: LoggingMessager,
 | 
				
			||||||
 | 
					          useValue: mockMessager,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        DeleteAuthUseCase,
 | 
					        DeleteAuthUseCase,
 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
    }).compile();
 | 
					    }).compile();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@ import { classes } from '@automapper/classes';
 | 
				
			||||||
import { AutomapperModule } from '@automapper/nestjs';
 | 
					import { AutomapperModule } from '@automapper/nestjs';
 | 
				
			||||||
import { UnauthorizedException } from '@nestjs/common';
 | 
					import { UnauthorizedException } from '@nestjs/common';
 | 
				
			||||||
import { Test, TestingModule } from '@nestjs/testing';
 | 
					import { Test, TestingModule } from '@nestjs/testing';
 | 
				
			||||||
 | 
					import { LoggingMessager } from '../../adapters/secondaries/logging.messager';
 | 
				
			||||||
import { UsernameRepository } from '../../adapters/secondaries/username.repository';
 | 
					import { UsernameRepository } from '../../adapters/secondaries/username.repository';
 | 
				
			||||||
import { DeleteUsernameCommand } from '../../commands/delete-username.command';
 | 
					import { DeleteUsernameCommand } from '../../commands/delete-username.command';
 | 
				
			||||||
import { DeleteUsernameRequest } from '../../domain/dtos/delete-username.request';
 | 
					import { DeleteUsernameRequest } from '../../domain/dtos/delete-username.request';
 | 
				
			||||||
| 
						 | 
					@ -65,6 +66,10 @@ const mockUsernameRepository = {
 | 
				
			||||||
  delete: jest.fn().mockResolvedValue(undefined),
 | 
					  delete: jest.fn().mockResolvedValue(undefined),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const mockMessager = {
 | 
				
			||||||
 | 
					  publish: jest.fn().mockImplementation(),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('DeleteUsernameUseCase', () => {
 | 
					describe('DeleteUsernameUseCase', () => {
 | 
				
			||||||
  let deleteUsernameUseCase: DeleteUsernameUseCase;
 | 
					  let deleteUsernameUseCase: DeleteUsernameUseCase;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -76,6 +81,10 @@ describe('DeleteUsernameUseCase', () => {
 | 
				
			||||||
          provide: UsernameRepository,
 | 
					          provide: UsernameRepository,
 | 
				
			||||||
          useValue: mockUsernameRepository,
 | 
					          useValue: mockUsernameRepository,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          provide: LoggingMessager,
 | 
				
			||||||
 | 
					          useValue: mockMessager,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        DeleteUsernameUseCase,
 | 
					        DeleteUsernameUseCase,
 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
    }).compile();
 | 
					    }).compile();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,7 @@ import * as bcrypt from 'bcrypt';
 | 
				
			||||||
import { UpdatePasswordRequest } from '../../domain/dtos/update-password.request';
 | 
					import { UpdatePasswordRequest } from '../../domain/dtos/update-password.request';
 | 
				
			||||||
import { UpdatePasswordCommand } from '../../commands/update-password.command';
 | 
					import { UpdatePasswordCommand } from '../../commands/update-password.command';
 | 
				
			||||||
import { UpdatePasswordUseCase } from '../../domain/usecases/update-password.usecase';
 | 
					import { UpdatePasswordUseCase } from '../../domain/usecases/update-password.usecase';
 | 
				
			||||||
 | 
					import { LoggingMessager } from '../../adapters/secondaries/logging.messager';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const updatePasswordRequest: UpdatePasswordRequest = {
 | 
					const updatePasswordRequest: UpdatePasswordRequest = {
 | 
				
			||||||
  uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
 | 
					  uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
 | 
				
			||||||
| 
						 | 
					@ -23,6 +24,10 @@ const mockAuthRepository = {
 | 
				
			||||||
  }),
 | 
					  }),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const mockMessager = {
 | 
				
			||||||
 | 
					  publish: jest.fn().mockImplementation(),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('UpdatePasswordUseCase', () => {
 | 
					describe('UpdatePasswordUseCase', () => {
 | 
				
			||||||
  let updatePasswordUseCase: UpdatePasswordUseCase;
 | 
					  let updatePasswordUseCase: UpdatePasswordUseCase;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,6 +39,10 @@ describe('UpdatePasswordUseCase', () => {
 | 
				
			||||||
          provide: AuthRepository,
 | 
					          provide: AuthRepository,
 | 
				
			||||||
          useValue: mockAuthRepository,
 | 
					          useValue: mockAuthRepository,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          provide: LoggingMessager,
 | 
				
			||||||
 | 
					          useValue: mockMessager,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        UpdatePasswordUseCase,
 | 
					        UpdatePasswordUseCase,
 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
    }).compile();
 | 
					    }).compile();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,18 +7,61 @@ import { UpdateUsernameRequest } from '../../domain/dtos/update-username.request
 | 
				
			||||||
import { UpdateUsernameCommand } from '../../commands/update-username.command';
 | 
					import { UpdateUsernameCommand } from '../../commands/update-username.command';
 | 
				
			||||||
import { Type } from '../../domain/dtos/type.enum';
 | 
					import { Type } from '../../domain/dtos/type.enum';
 | 
				
			||||||
import { UpdateUsernameUseCase } from '../../domain/usecases/update-username.usecase';
 | 
					import { UpdateUsernameUseCase } from '../../domain/usecases/update-username.usecase';
 | 
				
			||||||
 | 
					import { CommandBus } from '@nestjs/cqrs';
 | 
				
			||||||
 | 
					import { UsernameProfile } from '../../mappers/username.profile';
 | 
				
			||||||
 | 
					import { BadRequestException } from '@nestjs/common';
 | 
				
			||||||
 | 
					import { LoggingMessager } from '../../adapters/secondaries/logging.messager';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const existingUsername = {
 | 
				
			||||||
 | 
					  uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
 | 
				
			||||||
 | 
					  username: 'john.doe@email.com',
 | 
				
			||||||
 | 
					  type: Type.EMAIL,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const updateUsernameRequest: UpdateUsernameRequest = {
 | 
					const updateUsernameRequest: UpdateUsernameRequest = {
 | 
				
			||||||
  uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
 | 
					  uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
 | 
				
			||||||
  username: 'johnny.doe@email.com',
 | 
					  username: 'johnny.doe@email.com',
 | 
				
			||||||
  type: Type.EMAIL,
 | 
					  type: Type.EMAIL,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const newUsernameRequest: UpdateUsernameRequest = {
 | 
				
			||||||
 | 
					  uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
 | 
				
			||||||
 | 
					  username: '+33611223344',
 | 
				
			||||||
 | 
					  type: Type.PHONE,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const invalidUpdateUsernameRequest: UpdateUsernameRequest = {
 | 
				
			||||||
 | 
					  uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
 | 
				
			||||||
 | 
					  username: '',
 | 
				
			||||||
 | 
					  type: Type.EMAIL,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const updateUsernameCommand: UpdateUsernameCommand = new UpdateUsernameCommand(
 | 
					const updateUsernameCommand: UpdateUsernameCommand = new UpdateUsernameCommand(
 | 
				
			||||||
  updateUsernameRequest,
 | 
					  updateUsernameRequest,
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const newUsernameCommand: UpdateUsernameCommand = new UpdateUsernameCommand(
 | 
				
			||||||
 | 
					  newUsernameRequest,
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const invalidUpdateUsernameCommand: UpdateUsernameCommand =
 | 
				
			||||||
 | 
					  new UpdateUsernameCommand(invalidUpdateUsernameRequest);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const mockUsernameRepository = {
 | 
					const mockUsernameRepository = {
 | 
				
			||||||
  updateWhere: jest.fn().mockResolvedValue(updateUsernameRequest),
 | 
					  findOne: jest.fn().mockResolvedValue(existingUsername),
 | 
				
			||||||
 | 
					  updateWhere: jest
 | 
				
			||||||
 | 
					    .fn()
 | 
				
			||||||
 | 
					    .mockResolvedValueOnce(updateUsernameRequest)
 | 
				
			||||||
 | 
					    .mockResolvedValueOnce(newUsernameRequest)
 | 
				
			||||||
 | 
					    .mockResolvedValueOnce(invalidUpdateUsernameRequest),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const mockAddUsernameCommand = {
 | 
				
			||||||
 | 
					  execute: jest.fn().mockResolvedValue(newUsernameRequest),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const mockMessager = {
 | 
				
			||||||
 | 
					  publish: jest.fn().mockImplementation(),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('UpdateUsernameUseCase', () => {
 | 
					describe('UpdateUsernameUseCase', () => {
 | 
				
			||||||
| 
						 | 
					@ -32,7 +75,16 @@ describe('UpdateUsernameUseCase', () => {
 | 
				
			||||||
          provide: UsernameRepository,
 | 
					          provide: UsernameRepository,
 | 
				
			||||||
          useValue: mockUsernameRepository,
 | 
					          useValue: mockUsernameRepository,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          provide: CommandBus,
 | 
				
			||||||
 | 
					          useValue: mockAddUsernameCommand,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          provide: LoggingMessager,
 | 
				
			||||||
 | 
					          useValue: mockMessager,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        UpdateUsernameUseCase,
 | 
					        UpdateUsernameUseCase,
 | 
				
			||||||
 | 
					        UsernameProfile,
 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
    }).compile();
 | 
					    }).compile();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -54,5 +106,20 @@ describe('UpdateUsernameUseCase', () => {
 | 
				
			||||||
      expect(updatedUsername.username).toBe(updateUsernameRequest.username);
 | 
					      expect(updatedUsername.username).toBe(updateUsernameRequest.username);
 | 
				
			||||||
      expect(updatedUsername.type).toBe(updateUsernameRequest.type);
 | 
					      expect(updatedUsername.type).toBe(updateUsernameRequest.type);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('should create a new username', async () => {
 | 
				
			||||||
 | 
					      const newUsername: Username = await updateUsernameUseCase.execute(
 | 
				
			||||||
 | 
					        newUsernameCommand,
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      expect(newUsername.username).toBe(newUsernameRequest.username);
 | 
				
			||||||
 | 
					      expect(newUsername.type).toBe(newUsernameRequest.type);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('should throw an exception if username is invalid', async () => {
 | 
				
			||||||
 | 
					      await expect(
 | 
				
			||||||
 | 
					        updateUsernameUseCase.execute(invalidUpdateUsernameCommand),
 | 
				
			||||||
 | 
					      ).rejects.toBeInstanceOf(BadRequestException);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -131,6 +131,7 @@ export abstract class PrismaRepository<T> implements IRepository<T> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return updatedEntity;
 | 
					      return updatedEntity;
 | 
				
			||||||
    } catch (e) {
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					      console.log('error', e);
 | 
				
			||||||
      if (e instanceof PrismaClientKnownRequestError) {
 | 
					      if (e instanceof PrismaClientKnownRequestError) {
 | 
				
			||||||
        throw new DatabaseException(
 | 
					        throw new DatabaseException(
 | 
				
			||||||
          PrismaClientKnownRequestError.name,
 | 
					          PrismaClientKnownRequestError.name,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue