multiple usernames
This commit is contained in:
parent
3b02341275
commit
57d4172580
|
@ -1,10 +0,0 @@
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE "auth" (
|
|
||||||
"uuid" UUID NOT NULL,
|
|
||||||
"username" TEXT NOT NULL,
|
|
||||||
"password" TEXT NOT NULL,
|
|
||||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
||||||
|
|
||||||
CONSTRAINT "auth_pkey" PRIMARY KEY ("uuid")
|
|
||||||
);
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
-- CreateEnum
|
||||||
|
CREATE TYPE "Type" AS ENUM ('EMAIL', 'PHONE');
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "auth" (
|
||||||
|
"uuid" UUID NOT NULL,
|
||||||
|
"password" TEXT NOT NULL,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "auth_pkey" PRIMARY KEY ("uuid")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "username" (
|
||||||
|
"username" TEXT NOT NULL,
|
||||||
|
"uuid" UUID NOT NULL,
|
||||||
|
"type" "Type" NOT NULL DEFAULT 'EMAIL',
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "username_pkey" PRIMARY KEY ("username")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "username_uuid_type_key" ON "username"("uuid", "type");
|
|
@ -12,10 +12,25 @@ datasource db {
|
||||||
|
|
||||||
model Auth {
|
model Auth {
|
||||||
uuid String @id @db.Uuid
|
uuid String @id @db.Uuid
|
||||||
username String
|
|
||||||
password String
|
password String
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
@@map("auth")
|
@@map("auth")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model Username {
|
||||||
|
username String @id
|
||||||
|
uuid String @db.Uuid
|
||||||
|
type Type @default(EMAIL) // type is needed in case of username update
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
@@unique([uuid, type])
|
||||||
|
@@map("username")
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Type {
|
||||||
|
EMAIL
|
||||||
|
PHONE
|
||||||
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ async function bootstrap() {
|
||||||
'modules/auth/adapters/primaries/auth.proto',
|
'modules/auth/adapters/primaries/auth.proto',
|
||||||
),
|
),
|
||||||
url: process.env.SERVICE_URL + ':' + process.env.SERVICE_PORT,
|
url: process.env.SERVICE_URL + ':' + process.env.SERVICE_PORT,
|
||||||
loader: { keepCase: true },
|
loader: { keepCase: true, enums: String },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -4,14 +4,24 @@ import { Controller } 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';
|
||||||
|
import { AddUsernameCommand } from '../../commands/add-username.command';
|
||||||
import { CreateAuthCommand } from '../../commands/create-auth.command';
|
import { CreateAuthCommand } from '../../commands/create-auth.command';
|
||||||
import { UpdateAuthCommand } from '../../commands/update-auth.command';
|
import { DeleteAuthCommand } from '../../commands/delete-auth.command';
|
||||||
|
import { DeleteUsernameCommand } from '../../commands/delete-username.command';
|
||||||
|
import { UpdatePasswordCommand } from '../../commands/update-password.command';
|
||||||
|
import { UpdateUsernameCommand } from '../../commands/update-username.command';
|
||||||
|
import { AddUsernameRequest } from '../../domain/dtos/add-username.request';
|
||||||
import { CreateAuthRequest } from '../../domain/dtos/create-auth.request';
|
import { CreateAuthRequest } from '../../domain/dtos/create-auth.request';
|
||||||
import { UpdateAuthRequest } from '../../domain/dtos/update-auth.request';
|
import { DeleteAuthRequest } from '../../domain/dtos/delete-auth.request';
|
||||||
|
import { DeleteUsernameRequest } from '../../domain/dtos/delete-username.request';
|
||||||
|
import { UpdatePasswordRequest } from '../../domain/dtos/update-password.request';
|
||||||
|
import { UpdateUsernameRequest } from '../../domain/dtos/update-username.request';
|
||||||
import { ValidateAuthRequest } from '../../domain/dtos/validate-auth.request';
|
import { ValidateAuthRequest } from '../../domain/dtos/validate-auth.request';
|
||||||
import { Auth } from '../../domain/entities/auth';
|
import { Auth } from '../../domain/entities/auth';
|
||||||
|
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 { UsernamePresenter } from './username.presenter';
|
||||||
|
|
||||||
@Controller()
|
@Controller()
|
||||||
export class AuthController {
|
export class AuthController {
|
||||||
|
@ -24,7 +34,7 @@ export class AuthController {
|
||||||
@GrpcMethod('AuthService', 'Validate')
|
@GrpcMethod('AuthService', 'Validate')
|
||||||
async validate(data: ValidateAuthRequest): Promise<AuthPresenter> {
|
async validate(data: ValidateAuthRequest): Promise<AuthPresenter> {
|
||||||
try {
|
try {
|
||||||
const auth = await this._queryBus.execute(
|
const auth: Auth = await this._queryBus.execute(
|
||||||
new ValidateAuthQuery(data.username, data.password),
|
new ValidateAuthQuery(data.username, data.password),
|
||||||
);
|
);
|
||||||
return this._mapper.map(auth, Auth, AuthPresenter);
|
return this._mapper.map(auth, Auth, AuthPresenter);
|
||||||
|
@ -39,7 +49,9 @@ export class AuthController {
|
||||||
@GrpcMethod('AuthService', 'Create')
|
@GrpcMethod('AuthService', 'Create')
|
||||||
async createUser(data: CreateAuthRequest): Promise<AuthPresenter> {
|
async createUser(data: CreateAuthRequest): Promise<AuthPresenter> {
|
||||||
try {
|
try {
|
||||||
const auth = await this._commandBus.execute(new CreateAuthCommand(data));
|
const auth: Auth = await this._commandBus.execute(
|
||||||
|
new CreateAuthCommand(data),
|
||||||
|
);
|
||||||
return this._mapper.map(auth, Auth, AuthPresenter);
|
return this._mapper.map(auth, Auth, AuthPresenter);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof DatabaseException) {
|
if (e instanceof DatabaseException) {
|
||||||
|
@ -50,14 +62,69 @@ export class AuthController {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new RpcException({});
|
throw new RpcException({
|
||||||
|
code: 7,
|
||||||
|
message: 'Permission denied',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@GrpcMethod('AuthService', 'Update')
|
@GrpcMethod('AuthService', 'AddUsername')
|
||||||
async updateAuth(data: UpdateAuthRequest): Promise<AuthPresenter> {
|
async addUsername(data: AddUsernameRequest): Promise<UsernamePresenter> {
|
||||||
try {
|
try {
|
||||||
const auth = await this._commandBus.execute(new UpdateAuthCommand(data));
|
const username: Username = await this._commandBus.execute(
|
||||||
|
new AddUsernameCommand(data),
|
||||||
|
);
|
||||||
|
|
||||||
|
return this._mapper.map(username, Username, UsernamePresenter);
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof DatabaseException) {
|
||||||
|
if (e.message.includes('Already exists')) {
|
||||||
|
throw new RpcException({
|
||||||
|
code: 6,
|
||||||
|
message: 'Username already exists',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new RpcException({
|
||||||
|
code: 7,
|
||||||
|
message: 'Permission denied',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GrpcMethod('AuthService', 'UpdateUsername')
|
||||||
|
async updateUsername(
|
||||||
|
data: UpdateUsernameRequest,
|
||||||
|
): Promise<UsernamePresenter> {
|
||||||
|
try {
|
||||||
|
const username: Username = await this._commandBus.execute(
|
||||||
|
new UpdateUsernameCommand(data),
|
||||||
|
);
|
||||||
|
|
||||||
|
return this._mapper.map(username, Username, UsernamePresenter);
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof DatabaseException) {
|
||||||
|
if (e.message.includes('Already exists')) {
|
||||||
|
throw new RpcException({
|
||||||
|
code: 6,
|
||||||
|
message: 'Username already exists',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new RpcException({
|
||||||
|
code: 7,
|
||||||
|
message: 'Permission denied',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GrpcMethod('AuthService', 'UpdatePassword')
|
||||||
|
async updatePassword(data: UpdatePasswordRequest): Promise<AuthPresenter> {
|
||||||
|
try {
|
||||||
|
const auth: Auth = await this._commandBus.execute(
|
||||||
|
new UpdatePasswordCommand(data),
|
||||||
|
);
|
||||||
|
|
||||||
return this._mapper.map(auth, Auth, AuthPresenter);
|
return this._mapper.map(auth, Auth, AuthPresenter);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -67,4 +134,28 @@ export class AuthController {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GrpcMethod('AuthService', 'DeleteUsername')
|
||||||
|
async deleteUsername(data: DeleteUsernameRequest) {
|
||||||
|
try {
|
||||||
|
return await this._commandBus.execute(new DeleteUsernameCommand(data));
|
||||||
|
} catch (e) {
|
||||||
|
throw new RpcException({
|
||||||
|
code: 7,
|
||||||
|
message: 'Permission denied',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GrpcMethod('AuthService', 'Delete')
|
||||||
|
async deleteAuth(data: DeleteAuthRequest) {
|
||||||
|
try {
|
||||||
|
return await this._commandBus.execute(new DeleteAuthCommand(data));
|
||||||
|
} catch (e) {
|
||||||
|
throw new RpcException({
|
||||||
|
code: 7,
|
||||||
|
message: 'Permission denied',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,4 @@ import { AutoMap } from '@automapper/classes';
|
||||||
export class AuthPresenter {
|
export class AuthPresenter {
|
||||||
@AutoMap()
|
@AutoMap()
|
||||||
uuid: string;
|
uuid: string;
|
||||||
|
|
||||||
@AutoMap()
|
|
||||||
username: string;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,13 @@ syntax = "proto3";
|
||||||
package auth;
|
package auth;
|
||||||
|
|
||||||
service AuthService {
|
service AuthService {
|
||||||
rpc Validate(AuthByUsernamePassword) returns (AuthByUuid);
|
rpc Validate(AuthByUsernamePassword) returns (Uuid);
|
||||||
rpc Create(AuthWithPassword) returns (Auth);
|
rpc Create(Auth) returns (Uuid);
|
||||||
rpc Update(AuthWithPassword) returns (Auth);
|
rpc AddUsername(Username) returns (Uuid);
|
||||||
rpc Delete(AuthByUuid) returns (Empty);
|
rpc UpdatePassword(Password) returns (Uuid);
|
||||||
|
rpc UpdateUsername(Username) returns (Uuid);
|
||||||
|
rpc DeleteUsername(Username) returns (Uuid);
|
||||||
|
rpc Delete(Uuid) returns (Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
message AuthByUsernamePassword {
|
message AuthByUsernamePassword {
|
||||||
|
@ -14,19 +17,31 @@ message AuthByUsernamePassword {
|
||||||
string password = 2;
|
string password = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message AuthWithPassword {
|
enum Type {
|
||||||
string uuid = 1;
|
EMAIL = 0;
|
||||||
string username = 2;
|
PHONE = 1;
|
||||||
string password = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
message AuthByUuid {
|
|
||||||
string uuid = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message Auth {
|
message Auth {
|
||||||
string uuid = 1;
|
string uuid = 1;
|
||||||
string username = 2;
|
string username = 2;
|
||||||
|
string password = 3;
|
||||||
|
Type type = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Password {
|
||||||
|
string uuid = 1;
|
||||||
|
string password = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Username {
|
||||||
|
string uuid = 1;
|
||||||
|
string username = 2;
|
||||||
|
Type type = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Uuid {
|
||||||
|
string uuid = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Empty {}
|
message Empty {}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { AutoMap } from '@automapper/classes';
|
||||||
|
|
||||||
|
export class UsernamePresenter {
|
||||||
|
@AutoMap()
|
||||||
|
uuid: string;
|
||||||
|
|
||||||
|
@AutoMap()
|
||||||
|
username: string;
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { AuthNZRepository } from '../../../database/src/domain/authnz-repository';
|
||||||
|
import { Username } from '../../domain/entities/username';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UsernameRepository extends AuthNZRepository<Username> {
|
||||||
|
protected _model = 'username';
|
||||||
|
}
|
|
@ -6,17 +6,27 @@ import { CreateAuthUseCase } from './domain/usecases/create-auth.usecase';
|
||||||
import { ValidateAuthUseCase } from './domain/usecases/validate-auth.usecase';
|
import { ValidateAuthUseCase } from './domain/usecases/validate-auth.usecase';
|
||||||
import { AuthProfile } from './mappers/auth.profile';
|
import { AuthProfile } from './mappers/auth.profile';
|
||||||
import { AuthRepository } from './adapters/secondaries/auth.repository';
|
import { AuthRepository } from './adapters/secondaries/auth.repository';
|
||||||
import { UpdateAuthUseCase } from './domain/usecases/update-auth.usecase';
|
import { UpdateUsernameUseCase } from './domain/usecases/update-username.usecase';
|
||||||
|
import { UsernameProfile } from './mappers/username.profile';
|
||||||
|
import { AddUsernameUseCase } from './domain/usecases/add-username.usecase';
|
||||||
|
import { UpdatePasswordUseCase } from './domain/usecases/update-password.usecase';
|
||||||
|
import { DeleteUsernameUseCase } from './domain/usecases/delete-username.usecase';
|
||||||
|
import { DeleteAuthUseCase } from './domain/usecases/delete-auth.usecase';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [DatabaseModule, CqrsModule],
|
imports: [DatabaseModule, CqrsModule],
|
||||||
controllers: [AuthController],
|
controllers: [AuthController],
|
||||||
providers: [
|
providers: [
|
||||||
AuthProfile,
|
AuthProfile,
|
||||||
|
UsernameProfile,
|
||||||
AuthRepository,
|
AuthRepository,
|
||||||
ValidateAuthUseCase,
|
ValidateAuthUseCase,
|
||||||
CreateAuthUseCase,
|
CreateAuthUseCase,
|
||||||
UpdateAuthUseCase,
|
AddUsernameUseCase,
|
||||||
|
UpdateUsernameUseCase,
|
||||||
|
UpdatePasswordUseCase,
|
||||||
|
DeleteUsernameUseCase,
|
||||||
|
DeleteAuthUseCase,
|
||||||
],
|
],
|
||||||
exports: [],
|
exports: [],
|
||||||
})
|
})
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { AddUsernameRequest } from '../domain/dtos/add-username.request';
|
||||||
|
|
||||||
|
export class AddUsernameCommand {
|
||||||
|
readonly addUsernameRequest: AddUsernameRequest;
|
||||||
|
|
||||||
|
constructor(request: AddUsernameRequest) {
|
||||||
|
this.addUsernameRequest = request;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { DeleteAuthRequest } from '../domain/dtos/delete-auth.request';
|
||||||
|
|
||||||
|
export class DeleteAuthCommand {
|
||||||
|
readonly deleteAuthRequest: DeleteAuthRequest;
|
||||||
|
|
||||||
|
constructor(request: DeleteAuthRequest) {
|
||||||
|
this.deleteAuthRequest = request;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { DeleteUsernameRequest } from '../domain/dtos/delete-username.request';
|
||||||
|
|
||||||
|
export class DeleteUsernameCommand {
|
||||||
|
readonly deleteUsernameRequest: DeleteUsernameRequest;
|
||||||
|
|
||||||
|
constructor(request: DeleteUsernameRequest) {
|
||||||
|
this.deleteUsernameRequest = request;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +0,0 @@
|
||||||
import { UpdateAuthRequest } from '../domain/dtos/update-auth.request';
|
|
||||||
|
|
||||||
export class UpdateAuthCommand {
|
|
||||||
readonly updateAuthRequest: UpdateAuthRequest;
|
|
||||||
|
|
||||||
constructor(request: UpdateAuthRequest) {
|
|
||||||
this.updateAuthRequest = request;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { UpdatePasswordRequest } from '../domain/dtos/update-password.request';
|
||||||
|
|
||||||
|
export class UpdatePasswordCommand {
|
||||||
|
readonly updatePasswordRequest: UpdatePasswordRequest;
|
||||||
|
|
||||||
|
constructor(request: UpdatePasswordRequest) {
|
||||||
|
this.updatePasswordRequest = request;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { UpdateUsernameRequest } from '../domain/dtos/update-username.request';
|
||||||
|
|
||||||
|
export class UpdateUsernameCommand {
|
||||||
|
readonly updateUsernameRequest: UpdateUsernameRequest;
|
||||||
|
|
||||||
|
constructor(request: UpdateUsernameRequest) {
|
||||||
|
this.updateUsernameRequest = request;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { AutoMap } from '@automapper/classes';
|
||||||
|
import { IsEnum, IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
import { Type } from './type.enum';
|
||||||
|
|
||||||
|
export class AddUsernameRequest {
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
@AutoMap()
|
||||||
|
uuid: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
@AutoMap()
|
||||||
|
username: string;
|
||||||
|
|
||||||
|
@IsEnum(Type)
|
||||||
|
@IsNotEmpty()
|
||||||
|
@AutoMap()
|
||||||
|
type: Type;
|
||||||
|
}
|
|
@ -1,8 +1,10 @@
|
||||||
import { AutoMap } from '@automapper/classes';
|
import { AutoMap } from '@automapper/classes';
|
||||||
import { IsNotEmpty, IsString } from 'class-validator';
|
import { IsEnum, IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
import { Type } from './type.enum';
|
||||||
|
|
||||||
export class CreateAuthRequest {
|
export class CreateAuthRequest {
|
||||||
@IsString()
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
@AutoMap()
|
@AutoMap()
|
||||||
uuid: string;
|
uuid: string;
|
||||||
|
|
||||||
|
@ -15,4 +17,9 @@ export class CreateAuthRequest {
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@AutoMap()
|
@AutoMap()
|
||||||
password: string;
|
password: string;
|
||||||
|
|
||||||
|
@IsEnum(Type)
|
||||||
|
@IsNotEmpty()
|
||||||
|
@AutoMap()
|
||||||
|
type: Type;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { AutoMap } from '@automapper/classes';
|
||||||
|
import { IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
|
||||||
|
export class DeleteAuthRequest {
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
@AutoMap()
|
||||||
|
uuid: string;
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { AutoMap } from '@automapper/classes';
|
||||||
|
import { IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
|
||||||
|
export class DeleteUsernameRequest {
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
@AutoMap()
|
||||||
|
username: string;
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
export enum Type {
|
||||||
|
EMAIL = 'EMAIL',
|
||||||
|
PHONE = 'PHONE',
|
||||||
|
}
|
|
@ -1,16 +0,0 @@
|
||||||
import { AutoMap } from '@automapper/classes';
|
|
||||||
import { IsString } from 'class-validator';
|
|
||||||
|
|
||||||
export class UpdateAuthRequest {
|
|
||||||
@IsString()
|
|
||||||
@AutoMap()
|
|
||||||
uuid: string;
|
|
||||||
|
|
||||||
@IsString()
|
|
||||||
@AutoMap()
|
|
||||||
username?: string;
|
|
||||||
|
|
||||||
@IsString()
|
|
||||||
@AutoMap()
|
|
||||||
password?: string;
|
|
||||||
}
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { AutoMap } from '@automapper/classes';
|
||||||
|
import { IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
|
||||||
|
export class UpdatePasswordRequest {
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
@AutoMap()
|
||||||
|
uuid: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
@AutoMap()
|
||||||
|
password: string;
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { AutoMap } from '@automapper/classes';
|
||||||
|
import { IsEnum, IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
import { Type } from './type.enum';
|
||||||
|
|
||||||
|
export class UpdateUsernameRequest {
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
@AutoMap()
|
||||||
|
uuid: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
@AutoMap()
|
||||||
|
username: string;
|
||||||
|
|
||||||
|
@IsEnum(Type)
|
||||||
|
@IsNotEmpty()
|
||||||
|
@AutoMap()
|
||||||
|
type: Type;
|
||||||
|
}
|
|
@ -4,9 +4,5 @@ export class Auth {
|
||||||
@AutoMap()
|
@AutoMap()
|
||||||
uuid: string;
|
uuid: string;
|
||||||
|
|
||||||
@AutoMap()
|
|
||||||
username: string;
|
|
||||||
|
|
||||||
@AutoMap()
|
|
||||||
password: string;
|
password: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { AutoMap } from '@automapper/classes';
|
||||||
|
import { Type } from '../dtos/type.enum';
|
||||||
|
|
||||||
|
export class Username {
|
||||||
|
@AutoMap()
|
||||||
|
uuid: string;
|
||||||
|
|
||||||
|
@AutoMap()
|
||||||
|
username: string;
|
||||||
|
|
||||||
|
@AutoMap()
|
||||||
|
type: Type;
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { CommandHandler } from '@nestjs/cqrs';
|
||||||
|
import { UsernameRepository } from '../../adapters/secondaries/username.repository';
|
||||||
|
import { AddUsernameCommand } from '../../commands/add-username.command';
|
||||||
|
import { Username } from '../entities/username';
|
||||||
|
|
||||||
|
@CommandHandler(AddUsernameCommand)
|
||||||
|
export class AddUsernameUseCase {
|
||||||
|
constructor(private readonly _usernameRepository: UsernameRepository) {}
|
||||||
|
|
||||||
|
async execute(command: AddUsernameCommand): Promise<Username> {
|
||||||
|
const { uuid, username, type } = command.addUsernameRequest;
|
||||||
|
try {
|
||||||
|
return await this._usernameRepository.create({
|
||||||
|
uuid,
|
||||||
|
type,
|
||||||
|
username,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,18 +3,33 @@ import { AuthRepository } from '../../adapters/secondaries/auth.repository';
|
||||||
import { CreateAuthCommand } from '../../commands/create-auth.command';
|
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';
|
||||||
|
|
||||||
@CommandHandler(CreateAuthCommand)
|
@CommandHandler(CreateAuthCommand)
|
||||||
export class CreateAuthUseCase {
|
export class CreateAuthUseCase {
|
||||||
constructor(private readonly _repository: AuthRepository) {}
|
constructor(
|
||||||
|
private readonly _authRepository: AuthRepository,
|
||||||
|
private readonly _usernameRepository: UsernameRepository,
|
||||||
|
) {}
|
||||||
|
|
||||||
async execute(command: CreateAuthCommand): Promise<Auth> {
|
async execute(command: CreateAuthCommand): Promise<Auth> {
|
||||||
const { password, ...authWithoutPassword } = command.createAuthRequest;
|
const { uuid, password, ...username } = command.createAuthRequest;
|
||||||
const hash = await bcrypt.hash(password, 10);
|
const hash = await bcrypt.hash(password, 10);
|
||||||
|
|
||||||
return this._repository.create({
|
try {
|
||||||
password: hash,
|
const auth = await this._authRepository.create({
|
||||||
...authWithoutPassword,
|
uuid,
|
||||||
});
|
password: hash,
|
||||||
|
});
|
||||||
|
|
||||||
|
await this._usernameRepository.create({
|
||||||
|
uuid,
|
||||||
|
...username,
|
||||||
|
});
|
||||||
|
|
||||||
|
return auth;
|
||||||
|
} catch (e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
import { CommandHandler } from '@nestjs/cqrs';
|
||||||
|
import { AuthRepository } from '../../adapters/secondaries/auth.repository';
|
||||||
|
import { UsernameRepository } from '../../adapters/secondaries/username.repository';
|
||||||
|
import { DeleteAuthCommand } from '../../commands/delete-auth.command';
|
||||||
|
|
||||||
|
@CommandHandler(DeleteAuthCommand)
|
||||||
|
export class DeleteAuthUseCase {
|
||||||
|
constructor(
|
||||||
|
private readonly _authRepository: AuthRepository,
|
||||||
|
private readonly _usernameRepository: UsernameRepository,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async execute(command: DeleteAuthCommand) {
|
||||||
|
try {
|
||||||
|
const usernames = await this._usernameRepository.findAll(1, 99, {
|
||||||
|
uuid: command.deleteAuthRequest.uuid,
|
||||||
|
});
|
||||||
|
usernames.data.map(
|
||||||
|
async (username) =>
|
||||||
|
await this._usernameRepository.delete({
|
||||||
|
username: username.username,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
return await this._authRepository.delete({
|
||||||
|
uuid: command.deleteAuthRequest.uuid,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { UnauthorizedException } from '@nestjs/common';
|
||||||
|
import { CommandHandler } from '@nestjs/cqrs';
|
||||||
|
import { UsernameRepository } from '../../adapters/secondaries/username.repository';
|
||||||
|
import { DeleteUsernameCommand } from '../../commands/delete-username.command';
|
||||||
|
|
||||||
|
@CommandHandler(DeleteUsernameCommand)
|
||||||
|
export class DeleteUsernameUseCase {
|
||||||
|
constructor(private readonly _usernameRepository: UsernameRepository) {}
|
||||||
|
|
||||||
|
async execute(command: DeleteUsernameCommand) {
|
||||||
|
try {
|
||||||
|
const { username } = command.deleteUsernameRequest;
|
||||||
|
const usernameFound = await this._usernameRepository.findOne({
|
||||||
|
username,
|
||||||
|
});
|
||||||
|
const usernames = await this._usernameRepository.findAll(1, 1, {
|
||||||
|
uuid: usernameFound.uuid,
|
||||||
|
});
|
||||||
|
if (usernames.total > 1) {
|
||||||
|
return await this._usernameRepository.delete({ username });
|
||||||
|
}
|
||||||
|
throw new UnauthorizedException();
|
||||||
|
} catch (e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,29 +0,0 @@
|
||||||
import { Mapper } from '@automapper/core';
|
|
||||||
import { InjectMapper } from '@automapper/nestjs';
|
|
||||||
import { CommandHandler } from '@nestjs/cqrs';
|
|
||||||
import { AuthRepository } from '../../adapters/secondaries/auth.repository';
|
|
||||||
import { UpdateAuthCommand } from '../../commands/update-auth.command';
|
|
||||||
import { Auth } from '../entities/auth';
|
|
||||||
import * as bcrypt from 'bcrypt';
|
|
||||||
|
|
||||||
@CommandHandler(UpdateAuthCommand)
|
|
||||||
export class UpdateAuthUseCase {
|
|
||||||
constructor(
|
|
||||||
private readonly _repository: AuthRepository,
|
|
||||||
@InjectMapper() private readonly _mapper: Mapper,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
async execute(command: UpdateAuthCommand): Promise<Auth> {
|
|
||||||
const { uuid, username, password } = command.updateAuthRequest;
|
|
||||||
const request = {};
|
|
||||||
if (username) {
|
|
||||||
request['username'] = username;
|
|
||||||
}
|
|
||||||
if (password) {
|
|
||||||
const hash = await bcrypt.hash(password, 10);
|
|
||||||
request['password'] = hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this._repository.update(uuid, request);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { CommandHandler } from '@nestjs/cqrs';
|
||||||
|
import { AuthRepository } from '../../adapters/secondaries/auth.repository';
|
||||||
|
import { Auth } from '../entities/auth';
|
||||||
|
import * as bcrypt from 'bcrypt';
|
||||||
|
import { UpdatePasswordCommand } from '../../commands/update-password.command';
|
||||||
|
|
||||||
|
@CommandHandler(UpdatePasswordCommand)
|
||||||
|
export class UpdatePasswordUseCase {
|
||||||
|
constructor(private readonly _authRepository: AuthRepository) {}
|
||||||
|
|
||||||
|
async execute(command: UpdatePasswordCommand): Promise<Auth> {
|
||||||
|
const { uuid, password } = command.updatePasswordRequest;
|
||||||
|
const hash = await bcrypt.hash(password, 10);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return await this._authRepository.update(uuid, {
|
||||||
|
password: hash,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { CommandHandler } from '@nestjs/cqrs';
|
||||||
|
import { UsernameRepository } from '../../adapters/secondaries/username.repository';
|
||||||
|
import { UpdateUsernameCommand } from '../../commands/update-username.command';
|
||||||
|
import { Username } from '../entities/username';
|
||||||
|
|
||||||
|
@CommandHandler(UpdateUsernameCommand)
|
||||||
|
export class UpdateUsernameUseCase {
|
||||||
|
constructor(private readonly _usernameRepository: UsernameRepository) {}
|
||||||
|
|
||||||
|
async execute(command: UpdateUsernameCommand): Promise<Username> {
|
||||||
|
const { uuid, username, type } = command.updateUsernameRequest;
|
||||||
|
try {
|
||||||
|
return await this._usernameRepository.updateWhere(
|
||||||
|
{
|
||||||
|
uuid_type: {
|
||||||
|
uuid,
|
||||||
|
type,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
username,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,20 +4,31 @@ import { ValidateAuthQuery } from '../../queries/validate-auth.query';
|
||||||
import { Auth } from '../entities/auth';
|
import { Auth } from '../entities/auth';
|
||||||
import * as bcrypt from 'bcrypt';
|
import * as bcrypt from 'bcrypt';
|
||||||
import { NotFoundException, UnauthorizedException } from '@nestjs/common';
|
import { NotFoundException, UnauthorizedException } from '@nestjs/common';
|
||||||
|
import { UsernameRepository } from '../../adapters/secondaries/username.repository';
|
||||||
|
|
||||||
@QueryHandler(ValidateAuthQuery)
|
@QueryHandler(ValidateAuthQuery)
|
||||||
export class ValidateAuthUseCase {
|
export class ValidateAuthUseCase {
|
||||||
constructor(private readonly _authRepository: AuthRepository) {}
|
constructor(
|
||||||
|
private readonly _authRepository: AuthRepository,
|
||||||
|
private readonly _usernameRepository: UsernameRepository,
|
||||||
|
) {}
|
||||||
|
|
||||||
async execute(validate: ValidateAuthQuery): Promise<Auth> {
|
async execute(validate: ValidateAuthQuery): Promise<Auth> {
|
||||||
const auth = await this._authRepository.findOne({
|
try {
|
||||||
username: validate.username,
|
const username = await this._usernameRepository.findOne({
|
||||||
});
|
username: validate.username,
|
||||||
if (auth) {
|
});
|
||||||
const isMatch = await bcrypt.compare(validate.password, auth.password);
|
const auth = await this._authRepository.findOne({
|
||||||
if (isMatch) return auth;
|
uuid: username.uuid,
|
||||||
|
});
|
||||||
|
if (auth) {
|
||||||
|
const isMatch = await bcrypt.compare(validate.password, auth.password);
|
||||||
|
if (isMatch) return auth;
|
||||||
|
throw new UnauthorizedException();
|
||||||
|
}
|
||||||
|
throw new NotFoundException();
|
||||||
|
} catch (e) {
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
}
|
}
|
||||||
throw new NotFoundException();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ export class AuthProfile extends AutomapperProfile {
|
||||||
}
|
}
|
||||||
|
|
||||||
override get profile() {
|
override get profile() {
|
||||||
return (mapper) => {
|
return (mapper: any) => {
|
||||||
createMap(mapper, Auth, AuthPresenter);
|
createMap(mapper, Auth, AuthPresenter);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { createMap, Mapper } from '@automapper/core';
|
||||||
|
import { AutomapperProfile, InjectMapper } from '@automapper/nestjs';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { UsernamePresenter } from '../adapters/primaries/username.presenter';
|
||||||
|
import { Username } from '../domain/entities/username';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UsernameProfile extends AutomapperProfile {
|
||||||
|
constructor(@InjectMapper() mapper: Mapper) {
|
||||||
|
super(mapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
override get profile() {
|
||||||
|
return (mapper: any) => {
|
||||||
|
createMap(mapper, Username, UsernamePresenter);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
import { classes } from '@automapper/classes';
|
||||||
|
import { AutomapperModule } from '@automapper/nestjs';
|
||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { AuthProfile } from '../../mappers/auth.profile';
|
||||||
|
import { UsernameRepository } from '../../adapters/secondaries/username.repository';
|
||||||
|
import { Username } from '../../domain/entities/username';
|
||||||
|
import { Type } from '../../domain/dtos/type.enum';
|
||||||
|
import { AddUsernameRequest } from '../../domain/dtos/add-username.request';
|
||||||
|
import { AddUsernameCommand } from '../../commands/add-username.command';
|
||||||
|
import { AddUsernameUseCase } from '../../domain/usecases/add-username.usecase';
|
||||||
|
|
||||||
|
const addUsernameRequest: AddUsernameRequest = {
|
||||||
|
uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
|
||||||
|
username: '0611223344',
|
||||||
|
type: Type.PHONE,
|
||||||
|
};
|
||||||
|
const addUsernameCommand: AddUsernameCommand = new AddUsernameCommand(
|
||||||
|
addUsernameRequest,
|
||||||
|
);
|
||||||
|
|
||||||
|
const mockUsernameRepository = {
|
||||||
|
create: jest.fn().mockResolvedValue(addUsernameRequest),
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('AddUsernameUseCase', () => {
|
||||||
|
let addUsernameUseCase: AddUsernameUseCase;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
imports: [AutomapperModule.forRoot({ strategyInitializer: classes() })],
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: UsernameRepository,
|
||||||
|
useValue: mockUsernameRepository,
|
||||||
|
},
|
||||||
|
AddUsernameUseCase,
|
||||||
|
AuthProfile,
|
||||||
|
],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
addUsernameUseCase = module.get<AddUsernameUseCase>(AddUsernameUseCase);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(addUsernameUseCase).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('execute', () => {
|
||||||
|
it('should add a username for phone type', async () => {
|
||||||
|
const addedUsername: Username = await addUsernameUseCase.execute(
|
||||||
|
addUsernameCommand,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(addedUsername.username).toBe(addUsernameRequest.username);
|
||||||
|
expect(addedUsername.type).toBe(addUsernameRequest.type);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -6,24 +6,33 @@ import { CreateAuthCommand } from '../../commands/create-auth.command';
|
||||||
import { CreateAuthRequest } from '../../domain/dtos/create-auth.request';
|
import { CreateAuthRequest } from '../../domain/dtos/create-auth.request';
|
||||||
import { Auth } from '../../domain/entities/auth';
|
import { Auth } from '../../domain/entities/auth';
|
||||||
import { CreateAuthUseCase } from '../../domain/usecases/create-auth.usecase';
|
import { CreateAuthUseCase } from '../../domain/usecases/create-auth.usecase';
|
||||||
import { AuthProfile } from '../../mappers/auth.profile';
|
|
||||||
import * as bcrypt from 'bcrypt';
|
import * as bcrypt from 'bcrypt';
|
||||||
|
import { UsernameRepository } from '../../adapters/secondaries/username.repository';
|
||||||
|
import { Type } from '../../domain/dtos/type.enum';
|
||||||
|
|
||||||
const newAuthRequest: CreateAuthRequest = {
|
const newAuthRequest: CreateAuthRequest = {
|
||||||
uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
|
uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
|
||||||
username: 'john.doe@email.com',
|
username: 'john.doe@email.com',
|
||||||
password: 'John123',
|
password: 'John123',
|
||||||
|
type: Type.EMAIL,
|
||||||
};
|
};
|
||||||
const newAuthCommand: CreateAuthCommand = new CreateAuthCommand(newAuthRequest);
|
const newAuthCommand: CreateAuthCommand = new CreateAuthCommand(newAuthRequest);
|
||||||
|
|
||||||
const mockAuthRepository = {
|
const mockAuthRepository = {
|
||||||
create: jest.fn().mockResolvedValue({
|
create: jest.fn().mockResolvedValue({
|
||||||
uuid: newAuthRequest.uuid,
|
uuid: newAuthRequest.uuid,
|
||||||
username: newAuthRequest.username,
|
|
||||||
password: bcrypt.hashSync(newAuthRequest.password, 10),
|
password: bcrypt.hashSync(newAuthRequest.password, 10),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const mockUsernameRepository = {
|
||||||
|
create: jest.fn().mockResolvedValue({
|
||||||
|
uuid: newAuthRequest.uuid,
|
||||||
|
username: newAuthRequest.username,
|
||||||
|
type: newAuthRequest.type,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
describe('CreateAuthUseCase', () => {
|
describe('CreateAuthUseCase', () => {
|
||||||
let createAuthUseCase: CreateAuthUseCase;
|
let createAuthUseCase: CreateAuthUseCase;
|
||||||
|
|
||||||
|
@ -35,8 +44,11 @@ describe('CreateAuthUseCase', () => {
|
||||||
provide: AuthRepository,
|
provide: AuthRepository,
|
||||||
useValue: mockAuthRepository,
|
useValue: mockAuthRepository,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: UsernameRepository,
|
||||||
|
useValue: mockUsernameRepository,
|
||||||
|
},
|
||||||
CreateAuthUseCase,
|
CreateAuthUseCase,
|
||||||
AuthProfile,
|
|
||||||
],
|
],
|
||||||
}).compile();
|
}).compile();
|
||||||
|
|
||||||
|
@ -48,11 +60,9 @@ describe('CreateAuthUseCase', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('execute', () => {
|
describe('execute', () => {
|
||||||
it('should create an auth and returns new entity object', async () => {
|
it('should create an auth with an encrypted password', async () => {
|
||||||
const newAuth: Auth = await createAuthUseCase.execute(newAuthCommand);
|
const newAuth: Auth = await createAuthUseCase.execute(newAuthCommand);
|
||||||
|
|
||||||
expect(newAuth.username).toBe(newAuthRequest.username);
|
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
bcrypt.compareSync(newAuthRequest.password, newAuth.password),
|
bcrypt.compareSync(newAuthRequest.password, newAuth.password),
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
import { classes } from '@automapper/classes';
|
||||||
|
import { AutomapperModule } from '@automapper/nestjs';
|
||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { AuthRepository } from '../../adapters/secondaries/auth.repository';
|
||||||
|
import { UsernameRepository } from '../../adapters/secondaries/username.repository';
|
||||||
|
import { DeleteAuthCommand } from '../../commands/delete-auth.command';
|
||||||
|
import { DeleteAuthRequest } from '../../domain/dtos/delete-auth.request';
|
||||||
|
import { Type } from '../../domain/dtos/type.enum';
|
||||||
|
import { DeleteAuthUseCase } from '../../domain/usecases/delete-auth.usecase';
|
||||||
|
|
||||||
|
const usernames = {
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
uuid: 'cf76af29-f75d-4f6e-bb40-4ecbcfa3356e',
|
||||||
|
username: 'john.doe@email.com',
|
||||||
|
type: Type.EMAIL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uuid: 'cf76af29-f75d-4f6e-bb40-4ecbcfa3356e',
|
||||||
|
username: '0611223344',
|
||||||
|
type: Type.PHONE,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
total: 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteAuthRequest: DeleteAuthRequest = {
|
||||||
|
uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
|
||||||
|
};
|
||||||
|
const deleteAuthCommand: DeleteAuthCommand = new DeleteAuthCommand(
|
||||||
|
deleteAuthRequest,
|
||||||
|
);
|
||||||
|
|
||||||
|
const mockAuthRepository = {
|
||||||
|
delete: jest.fn().mockResolvedValue(undefined),
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockUsernameRepository = {
|
||||||
|
findAll: jest.fn().mockImplementation((page, perPage, query) => {
|
||||||
|
return Promise.resolve(usernames);
|
||||||
|
}),
|
||||||
|
delete: jest.fn().mockResolvedValue(undefined),
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('DeleteAuthUseCase', () => {
|
||||||
|
let deleteAuthUseCase: DeleteAuthUseCase;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
imports: [AutomapperModule.forRoot({ strategyInitializer: classes() })],
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: AuthRepository,
|
||||||
|
useValue: mockAuthRepository,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: UsernameRepository,
|
||||||
|
useValue: mockUsernameRepository,
|
||||||
|
},
|
||||||
|
DeleteAuthUseCase,
|
||||||
|
],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
deleteAuthUseCase = module.get<DeleteAuthUseCase>(DeleteAuthUseCase);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(deleteAuthUseCase).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('execute', () => {
|
||||||
|
it('should delete an auth and its usernames', async () => {
|
||||||
|
const deletedAuth = await deleteAuthUseCase.execute(deleteAuthCommand);
|
||||||
|
|
||||||
|
expect(deletedAuth).toBe(undefined);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,106 @@
|
||||||
|
import { classes } from '@automapper/classes';
|
||||||
|
import { AutomapperModule } from '@automapper/nestjs';
|
||||||
|
import { UnauthorizedException } from '@nestjs/common';
|
||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { UsernameRepository } from '../../adapters/secondaries/username.repository';
|
||||||
|
import { DeleteUsernameCommand } from '../../commands/delete-username.command';
|
||||||
|
import { DeleteUsernameRequest } from '../../domain/dtos/delete-username.request';
|
||||||
|
import { Type } from '../../domain/dtos/type.enum';
|
||||||
|
import { DeleteUsernameUseCase } from '../../domain/usecases/delete-username.usecase';
|
||||||
|
|
||||||
|
const usernamesEmail = {
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
uuid: 'cf76af29-f75d-4f6e-bb40-4ecbcfa3356e',
|
||||||
|
username: 'john.doe@email.com',
|
||||||
|
type: Type.EMAIL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uuid: 'cf76af29-f75d-4f6e-bb40-4ecbcfa3356e',
|
||||||
|
username: '0611223344',
|
||||||
|
type: Type.PHONE,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
total: 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
const usernamesPhone = {
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
uuid: 'a7fa221f-dd77-481c-bb77-ae89da662c87',
|
||||||
|
username: '0611223344',
|
||||||
|
type: Type.PHONE,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
total: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteUsernameEmailRequest: DeleteUsernameRequest = {
|
||||||
|
username: 'john.doe@email.com',
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteUsernamePhoneRequest: DeleteUsernameRequest = {
|
||||||
|
username: '0611223344',
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteUsernameEmailCommand: DeleteUsernameCommand =
|
||||||
|
new DeleteUsernameCommand(deleteUsernameEmailRequest);
|
||||||
|
|
||||||
|
const deleteUsernamePhoneCommand: DeleteUsernameCommand =
|
||||||
|
new DeleteUsernameCommand(deleteUsernamePhoneRequest);
|
||||||
|
|
||||||
|
const mockUsernameRepository = {
|
||||||
|
findOne: jest.fn().mockImplementation((where) => {
|
||||||
|
if (where.username == 'john.doe@email.com') {
|
||||||
|
return { uuid: 'cf76af29-f75d-4f6e-bb40-4ecbcfa3356e' };
|
||||||
|
}
|
||||||
|
return { uuid: 'a7fa221f-dd77-481c-bb77-ae89da662c87' };
|
||||||
|
}),
|
||||||
|
findAll: jest.fn().mockImplementation((page, perPage, query) => {
|
||||||
|
if (query.uuid == 'cf76af29-f75d-4f6e-bb40-4ecbcfa3356e') {
|
||||||
|
return Promise.resolve(usernamesEmail);
|
||||||
|
}
|
||||||
|
return Promise.resolve(usernamesPhone);
|
||||||
|
}),
|
||||||
|
delete: jest.fn().mockResolvedValue(undefined),
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('DeleteUsernameUseCase', () => {
|
||||||
|
let deleteUsernameUseCase: DeleteUsernameUseCase;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
imports: [AutomapperModule.forRoot({ strategyInitializer: classes() })],
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: UsernameRepository,
|
||||||
|
useValue: mockUsernameRepository,
|
||||||
|
},
|
||||||
|
DeleteUsernameUseCase,
|
||||||
|
],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
deleteUsernameUseCase = module.get<DeleteUsernameUseCase>(
|
||||||
|
DeleteUsernameUseCase,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(deleteUsernameUseCase).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('execute', () => {
|
||||||
|
it('should delete a username', async () => {
|
||||||
|
const deletedEmailUsername = await deleteUsernameUseCase.execute(
|
||||||
|
deleteUsernameEmailCommand,
|
||||||
|
);
|
||||||
|
expect(deletedEmailUsername).toBe(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an exception if auth has only one username', async () => {
|
||||||
|
await expect(
|
||||||
|
deleteUsernameUseCase.execute(deleteUsernamePhoneCommand),
|
||||||
|
).rejects.toBeInstanceOf(UnauthorizedException);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,119 +0,0 @@
|
||||||
import { classes } from '@automapper/classes';
|
|
||||||
import { AutomapperModule } from '@automapper/nestjs';
|
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
|
||||||
import { UpdateAuthCommand } from '../../commands/update-auth.command';
|
|
||||||
import { UpdateAuthRequest } from '../../domain/dtos/update-auth.request';
|
|
||||||
import { Auth } from '../../domain/entities/auth';
|
|
||||||
import * as bcrypt from 'bcrypt';
|
|
||||||
import { UpdateAuthUseCase } from '../../domain/usecases/update-auth.usecase';
|
|
||||||
import { AuthRepository } from '../../adapters/secondaries/auth.repository';
|
|
||||||
import { AuthProfile } from '../../mappers/auth.profile';
|
|
||||||
|
|
||||||
const originalAuth: Auth = new Auth();
|
|
||||||
originalAuth.uuid = 'bb281075-1b98-4456-89d6-c643d3044a91';
|
|
||||||
originalAuth.username = 'john.doe@email.com';
|
|
||||||
originalAuth.password = 'encrypted_password';
|
|
||||||
|
|
||||||
const updateUsernameAuthRequest: UpdateAuthRequest = {
|
|
||||||
uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
|
|
||||||
username: 'johnny.doe@email.com',
|
|
||||||
};
|
|
||||||
|
|
||||||
const updatePasswordAuthRequest: UpdateAuthRequest = {
|
|
||||||
uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
|
|
||||||
password: 'John1234',
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateAuthRequest: UpdateAuthRequest = {
|
|
||||||
uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
|
|
||||||
username: 'johnny.doe@email.com',
|
|
||||||
password: 'John1234',
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateUsernameAuthCommand: UpdateAuthCommand = new UpdateAuthCommand(
|
|
||||||
updateUsernameAuthRequest,
|
|
||||||
);
|
|
||||||
|
|
||||||
const updatePasswordAuthCommand: UpdateAuthCommand = new UpdateAuthCommand(
|
|
||||||
updatePasswordAuthRequest,
|
|
||||||
);
|
|
||||||
|
|
||||||
const updateAuthCommand: UpdateAuthCommand = new UpdateAuthCommand(
|
|
||||||
updateAuthRequest,
|
|
||||||
);
|
|
||||||
|
|
||||||
const mockAuthRepository = {
|
|
||||||
update: jest.fn().mockImplementation((uuid: string, params: any) => {
|
|
||||||
if (params.username && params.password) {
|
|
||||||
const auth: Auth = { ...originalAuth };
|
|
||||||
auth.username = params.username;
|
|
||||||
auth.password = params.password;
|
|
||||||
return Promise.resolve(auth);
|
|
||||||
}
|
|
||||||
if (params.username) {
|
|
||||||
const auth: Auth = { ...originalAuth };
|
|
||||||
auth.username = params.username;
|
|
||||||
return Promise.resolve(auth);
|
|
||||||
}
|
|
||||||
if (params.password) {
|
|
||||||
const auth: Auth = { ...originalAuth };
|
|
||||||
auth.password = params.password;
|
|
||||||
return Promise.resolve(auth);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('UpdateAuthUseCase', () => {
|
|
||||||
let updateAuthUseCase: UpdateAuthUseCase;
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
const module: TestingModule = await Test.createTestingModule({
|
|
||||||
imports: [AutomapperModule.forRoot({ strategyInitializer: classes() })],
|
|
||||||
|
|
||||||
providers: [
|
|
||||||
{
|
|
||||||
provide: AuthRepository,
|
|
||||||
useValue: mockAuthRepository,
|
|
||||||
},
|
|
||||||
UpdateAuthUseCase,
|
|
||||||
AuthProfile,
|
|
||||||
],
|
|
||||||
}).compile();
|
|
||||||
|
|
||||||
updateAuthUseCase = module.get<UpdateAuthUseCase>(UpdateAuthUseCase);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be defined', () => {
|
|
||||||
expect(updateAuthUseCase).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('execute', () => {
|
|
||||||
it('should update the username of an Auth', async () => {
|
|
||||||
const updatedAuth: Auth = await updateAuthUseCase.execute(
|
|
||||||
updateUsernameAuthCommand,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(updatedAuth.username).toBe(updateUsernameAuthRequest.username);
|
|
||||||
});
|
|
||||||
it('should update the password of an Auth', async () => {
|
|
||||||
const updatedAuth: Auth = await updateAuthUseCase.execute(
|
|
||||||
updatePasswordAuthCommand,
|
|
||||||
);
|
|
||||||
expect(
|
|
||||||
bcrypt.compareSync(
|
|
||||||
updatePasswordAuthRequest.password,
|
|
||||||
updatedAuth.password,
|
|
||||||
),
|
|
||||||
).toBeTruthy();
|
|
||||||
});
|
|
||||||
it('should update the username and the password of an Auth', async () => {
|
|
||||||
const updatedAuth: Auth = await updateAuthUseCase.execute(
|
|
||||||
updateAuthCommand,
|
|
||||||
);
|
|
||||||
expect(updatedAuth.username).toBe(updateAuthRequest.username);
|
|
||||||
expect(
|
|
||||||
bcrypt.compareSync(updateAuthRequest.password, updatedAuth.password),
|
|
||||||
).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
import { classes } from '@automapper/classes';
|
||||||
|
import { AutomapperModule } from '@automapper/nestjs';
|
||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { AuthRepository } from '../../adapters/secondaries/auth.repository';
|
||||||
|
import { Auth } from '../../domain/entities/auth';
|
||||||
|
import * as bcrypt from 'bcrypt';
|
||||||
|
import { UpdatePasswordRequest } from '../../domain/dtos/update-password.request';
|
||||||
|
import { UpdatePasswordCommand } from '../../commands/update-password.command';
|
||||||
|
import { UpdatePasswordUseCase } from '../../domain/usecases/update-password.usecase';
|
||||||
|
|
||||||
|
const updatePasswordRequest: UpdatePasswordRequest = {
|
||||||
|
uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
|
||||||
|
password: 'John123',
|
||||||
|
};
|
||||||
|
const updatePasswordCommand: UpdatePasswordCommand = new UpdatePasswordCommand(
|
||||||
|
updatePasswordRequest,
|
||||||
|
);
|
||||||
|
|
||||||
|
const mockAuthRepository = {
|
||||||
|
update: jest.fn().mockResolvedValue({
|
||||||
|
uuid: updatePasswordRequest.uuid,
|
||||||
|
password: bcrypt.hashSync(updatePasswordRequest.password, 10),
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('UpdatePasswordUseCase', () => {
|
||||||
|
let updatePasswordUseCase: UpdatePasswordUseCase;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
imports: [AutomapperModule.forRoot({ strategyInitializer: classes() })],
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: AuthRepository,
|
||||||
|
useValue: mockAuthRepository,
|
||||||
|
},
|
||||||
|
UpdatePasswordUseCase,
|
||||||
|
],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
updatePasswordUseCase = module.get<UpdatePasswordUseCase>(
|
||||||
|
UpdatePasswordUseCase,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(updatePasswordUseCase).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('execute', () => {
|
||||||
|
it('should update an auth with an new encrypted password', async () => {
|
||||||
|
const newAuth: Auth = await updatePasswordUseCase.execute(
|
||||||
|
updatePasswordCommand,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
bcrypt.compareSync(updatePasswordRequest.password, newAuth.password),
|
||||||
|
).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,58 @@
|
||||||
|
import { classes } from '@automapper/classes';
|
||||||
|
import { AutomapperModule } from '@automapper/nestjs';
|
||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { UsernameRepository } from '../../adapters/secondaries/username.repository';
|
||||||
|
import { Username } from '../../domain/entities/username';
|
||||||
|
import { UpdateUsernameRequest } from '../../domain/dtos/update-username.request';
|
||||||
|
import { UpdateUsernameCommand } from '../../commands/update-username.command';
|
||||||
|
import { Type } from '../../domain/dtos/type.enum';
|
||||||
|
import { UpdateUsernameUseCase } from '../../domain/usecases/update-username.usecase';
|
||||||
|
|
||||||
|
const updateUsernameRequest: UpdateUsernameRequest = {
|
||||||
|
uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
|
||||||
|
username: 'johnny.doe@email.com',
|
||||||
|
type: Type.EMAIL,
|
||||||
|
};
|
||||||
|
const updateUsernameCommand: UpdateUsernameCommand = new UpdateUsernameCommand(
|
||||||
|
updateUsernameRequest,
|
||||||
|
);
|
||||||
|
|
||||||
|
const mockUsernameRepository = {
|
||||||
|
updateWhere: jest.fn().mockResolvedValue(updateUsernameRequest),
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('UpdateUsernameUseCase', () => {
|
||||||
|
let updateUsernameUseCase: UpdateUsernameUseCase;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
imports: [AutomapperModule.forRoot({ strategyInitializer: classes() })],
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: UsernameRepository,
|
||||||
|
useValue: mockUsernameRepository,
|
||||||
|
},
|
||||||
|
UpdateUsernameUseCase,
|
||||||
|
],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
updateUsernameUseCase = module.get<UpdateUsernameUseCase>(
|
||||||
|
UpdateUsernameUseCase,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(updateUsernameUseCase).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('execute', () => {
|
||||||
|
it('should update a username for email type', async () => {
|
||||||
|
const updatedUsername: Username = await updateUsernameUseCase.execute(
|
||||||
|
updateUsernameCommand,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(updatedUsername.username).toBe(updateUsernameRequest.username);
|
||||||
|
expect(updatedUsername.type).toBe(updateUsernameRequest.type);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -5,17 +5,25 @@ import { AuthRepository } from '../../adapters/secondaries/auth.repository';
|
||||||
import { Auth } from '../../domain/entities/auth';
|
import { Auth } from '../../domain/entities/auth';
|
||||||
import * as bcrypt from 'bcrypt';
|
import * as bcrypt from 'bcrypt';
|
||||||
import { ValidateAuthUseCase } from '../../domain/usecases/validate-auth.usecase';
|
import { ValidateAuthUseCase } from '../../domain/usecases/validate-auth.usecase';
|
||||||
import { AuthProfile } from '../../mappers/auth.profile';
|
|
||||||
import { ValidateAuthQuery } from '../../queries/validate-auth.query';
|
import { ValidateAuthQuery } from '../../queries/validate-auth.query';
|
||||||
|
import { UsernameRepository } from '../../adapters/secondaries/username.repository';
|
||||||
|
import { Type } from '../../domain/dtos/type.enum';
|
||||||
|
|
||||||
const mockAuthRepository = {
|
const mockAuthRepository = {
|
||||||
findOne: jest.fn().mockResolvedValue({
|
findOne: jest.fn().mockResolvedValue({
|
||||||
uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
|
uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
|
||||||
username: 'john.doe@email.com',
|
|
||||||
password: bcrypt.hashSync('John123', 10),
|
password: bcrypt.hashSync('John123', 10),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const mockUsernameRepository = {
|
||||||
|
findOne: jest.fn().mockResolvedValue({
|
||||||
|
uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
|
||||||
|
username: 'john.doe@email.com',
|
||||||
|
type: Type.EMAIL,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
describe('ValidateAuthUseCase', () => {
|
describe('ValidateAuthUseCase', () => {
|
||||||
let validateAuthUseCase: ValidateAuthUseCase;
|
let validateAuthUseCase: ValidateAuthUseCase;
|
||||||
|
|
||||||
|
@ -27,8 +35,11 @@ describe('ValidateAuthUseCase', () => {
|
||||||
provide: AuthRepository,
|
provide: AuthRepository,
|
||||||
useValue: mockAuthRepository,
|
useValue: mockAuthRepository,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: UsernameRepository,
|
||||||
|
useValue: mockUsernameRepository,
|
||||||
|
},
|
||||||
ValidateAuthUseCase,
|
ValidateAuthUseCase,
|
||||||
AuthProfile,
|
|
||||||
],
|
],
|
||||||
}).compile();
|
}).compile();
|
||||||
|
|
||||||
|
@ -45,7 +56,6 @@ describe('ValidateAuthUseCase', () => {
|
||||||
new ValidateAuthQuery('john.doe@email.com', 'John123'),
|
new ValidateAuthQuery('john.doe@email.com', 'John123'),
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(auth.username).toBe('john.doe@email.com');
|
|
||||||
expect(bcrypt.compareSync('John123', auth.password)).toBeTruthy();
|
expect(bcrypt.compareSync('John123', auth.password)).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { AuthRepository } from '../auth/adapters/secondaries/auth.repository';
|
import { AuthRepository } from '../auth/adapters/secondaries/auth.repository';
|
||||||
|
import { UsernameRepository } from '../auth/adapters/secondaries/username.repository';
|
||||||
import { PrismaService } from './src/adapters/secondaries/prisma-service';
|
import { PrismaService } from './src/adapters/secondaries/prisma-service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
providers: [PrismaService, AuthRepository],
|
providers: [PrismaService, AuthRepository, UsernameRepository],
|
||||||
exports: [PrismaService, AuthRepository],
|
exports: [PrismaService, AuthRepository, UsernameRepository],
|
||||||
})
|
})
|
||||||
export class DatabaseModule {}
|
export class DatabaseModule {}
|
||||||
|
|
|
@ -143,14 +143,15 @@ export abstract class PrismaRepository<T> implements IRepository<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(uuid: string): Promise<void> {
|
async delete(where: any): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const entity = await this._prisma[this._model].delete({
|
const entity = await this._prisma[this._model].delete({
|
||||||
where: { uuid },
|
where: where,
|
||||||
});
|
});
|
||||||
|
|
||||||
return entity;
|
return entity;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
if (e instanceof PrismaClientKnownRequestError) {
|
if (e instanceof PrismaClientKnownRequestError) {
|
||||||
throw new DatabaseException(
|
throw new DatabaseException(
|
||||||
PrismaClientKnownRequestError.name,
|
PrismaClientKnownRequestError.name,
|
||||||
|
|
|
@ -217,7 +217,7 @@ describe('PrismaRepository', () => {
|
||||||
const savedUuid = fakeEntities[0].uuid;
|
const savedUuid = fakeEntities[0].uuid;
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
const res = await fakeRepository.delete(savedUuid);
|
const res = await fakeRepository.delete({ uuid: savedUuid });
|
||||||
|
|
||||||
const deletedEntity = fakeEntities.find(
|
const deletedEntity = fakeEntities.find(
|
||||||
(entity) => entity.uuid === savedUuid,
|
(entity) => entity.uuid === savedUuid,
|
||||||
|
|
Loading…
Reference in New Issue