mirror of
https://gitlab.com/mobicoop/v3/service/auth.git
synced 2026-01-12 02:42:39 +00:00
update packages, refactor
This commit is contained in:
@@ -31,14 +31,12 @@ export class AuthenticationMapper
|
||||
const record: AuthenticationWriteModel = {
|
||||
uuid: copy.id,
|
||||
password: copy.password,
|
||||
usernames: copy.usernames
|
||||
? {
|
||||
create: copy.usernames.map((username: UsernameProps) => ({
|
||||
username: username.name,
|
||||
type: username.type,
|
||||
})),
|
||||
}
|
||||
: undefined,
|
||||
usernames: {
|
||||
create: copy.usernames.map((username: UsernameProps) => ({
|
||||
username: username.name,
|
||||
type: username.type,
|
||||
})),
|
||||
},
|
||||
};
|
||||
return record;
|
||||
};
|
||||
@@ -54,7 +52,7 @@ export class AuthenticationMapper
|
||||
usernames: record.usernames?.map((username: UsernameModel) => ({
|
||||
userId: record.uuid,
|
||||
name: username.username,
|
||||
type: Type[username.type],
|
||||
type: username.type as Type,
|
||||
})),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
AuthenticationAlreadyExistsException,
|
||||
UsernameAlreadyExistsException,
|
||||
} from '@modules/authentication/core/domain/authentication.errors';
|
||||
import { Username } from '../../types/username';
|
||||
|
||||
@CommandHandler(CreateAuthenticationCommand)
|
||||
export class CreateAuthenticationService implements ICommandHandler {
|
||||
@@ -26,7 +27,11 @@ export class CreateAuthenticationService implements ICommandHandler {
|
||||
await AuthenticationEntity.create({
|
||||
userId: command.userId,
|
||||
password: command.password,
|
||||
usernames: command.usernames,
|
||||
usernames: command.usernames.map((username: Username) => ({
|
||||
name: username.name,
|
||||
type: username.type,
|
||||
userId: command.userId,
|
||||
})),
|
||||
});
|
||||
try {
|
||||
await this.authenticationRepository.insert(authentication);
|
||||
|
||||
@@ -18,9 +18,8 @@ export class DeleteAuthenticationService implements ICommandHandler {
|
||||
usernames: true,
|
||||
});
|
||||
authentication.delete();
|
||||
const isDeleted: boolean = await this.authenticationRepository.delete(
|
||||
authentication,
|
||||
);
|
||||
const isDeleted: boolean =
|
||||
await this.authenticationRepository.delete(authentication);
|
||||
return isDeleted;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,9 +24,8 @@ export class DeleteUsernameService implements ICommandHandler {
|
||||
'Authentication must have at least one username',
|
||||
);
|
||||
username.delete();
|
||||
const isDeleted: boolean = await this.usernameRepository.deleteUsername(
|
||||
username,
|
||||
);
|
||||
const isDeleted: boolean =
|
||||
await this.usernameRepository.deleteUsername(username);
|
||||
return isDeleted;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { UsernameProps } from './username.types';
|
||||
import { NameProps } from './username.types';
|
||||
|
||||
// All properties that an Authentication has
|
||||
export interface AuthenticationProps {
|
||||
userId: string;
|
||||
password: string;
|
||||
usernames: UsernameProps[];
|
||||
usernames: NameProps[];
|
||||
}
|
||||
|
||||
// Properties that are needed for an Authentication creation
|
||||
export interface CreateAuthenticationProps {
|
||||
userId: string;
|
||||
password: string;
|
||||
usernames: UsernameProps[];
|
||||
usernames: NameProps[];
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ export class UsernameEntity extends AggregateRoot<UsernameProps> {
|
||||
const username = new UsernameEntity({
|
||||
id: props.name,
|
||||
props: {
|
||||
name: props.name,
|
||||
userId: props.userId,
|
||||
name: props.name,
|
||||
type: props.type,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
export interface UsernameProps {
|
||||
name: string;
|
||||
userId?: string;
|
||||
type: Type;
|
||||
export interface UsernameProps extends NameProps {
|
||||
userId: string;
|
||||
}
|
||||
|
||||
export interface CreateUsernameProps {
|
||||
name: string;
|
||||
export interface CreateUsernameProps extends NameProps {
|
||||
userId: string;
|
||||
}
|
||||
|
||||
export interface NameProps {
|
||||
name: string;
|
||||
type: Type;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { INestApplication, Injectable, OnModuleInit } from '@nestjs/common';
|
||||
import { Injectable, OnModuleInit } from '@nestjs/common';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
@Injectable()
|
||||
@@ -6,10 +6,4 @@ export class PrismaService extends PrismaClient implements OnModuleInit {
|
||||
async onModuleInit() {
|
||||
await this.$connect();
|
||||
}
|
||||
|
||||
async enableShutdownHooks(app: INestApplication) {
|
||||
this.$on('beforeExit', async () => {
|
||||
await app.close();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ type UsernameBaseModel = {
|
||||
};
|
||||
|
||||
export type UsernameReadModel = UsernameBaseModel & {
|
||||
createdAt?: Date;
|
||||
updatedAt?: Date;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
};
|
||||
|
||||
export type UsernameWriteModel = UsernameBaseModel;
|
||||
|
||||
@@ -10,6 +10,7 @@ import { GrpcMethod, RpcException } from '@nestjs/microservices';
|
||||
import { UsernameAlreadyExistsException } from '@modules/authentication/core/domain/authentication.errors';
|
||||
import { AddUsernameRequestDto } from './dtos/add-username.request.dto';
|
||||
import { AddUsernameCommand } from '@modules/authentication/core/application/commands/add-username/add-username.command';
|
||||
import { GRPC_AUTHENTICATION_SERVICE_NAME } from '@src/app.constants';
|
||||
|
||||
@UsePipes(
|
||||
new RpcValidationPipe({
|
||||
@@ -21,7 +22,7 @@ import { AddUsernameCommand } from '@modules/authentication/core/application/com
|
||||
export class AddUsernameGrpcController {
|
||||
constructor(private readonly commandBus: CommandBus) {}
|
||||
|
||||
@GrpcMethod('AuthenticationService', 'AddUsername')
|
||||
@GrpcMethod(GRPC_AUTHENTICATION_SERVICE_NAME, 'AddUsername')
|
||||
async addUsername(data: AddUsernameRequestDto): Promise<IdResponse> {
|
||||
try {
|
||||
const aggregateID: AggregateID = await this.commandBus.execute(
|
||||
|
||||
@@ -10,6 +10,7 @@ import { GrpcMethod, RpcException } from '@nestjs/microservices';
|
||||
import { CreateAuthenticationRequestDto } from './dtos/create-authentication.request.dto';
|
||||
import { CreateAuthenticationCommand } from '@modules/authentication/core/application/commands/create-authentication/create-authentication.command';
|
||||
import { AuthenticationAlreadyExistsException } from '@modules/authentication/core/domain/authentication.errors';
|
||||
import { GRPC_AUTHENTICATION_SERVICE_NAME } from '@src/app.constants';
|
||||
|
||||
@UsePipes(
|
||||
new RpcValidationPipe({
|
||||
@@ -21,7 +22,7 @@ import { AuthenticationAlreadyExistsException } from '@modules/authentication/co
|
||||
export class CreateAuthenticationGrpcController {
|
||||
constructor(private readonly commandBus: CommandBus) {}
|
||||
|
||||
@GrpcMethod('AuthenticationService', 'Create')
|
||||
@GrpcMethod(GRPC_AUTHENTICATION_SERVICE_NAME, 'Create')
|
||||
async create(data: CreateAuthenticationRequestDto): Promise<IdResponse> {
|
||||
try {
|
||||
const aggregateID: AggregateID = await this.commandBus.execute(
|
||||
|
||||
@@ -9,6 +9,7 @@ import { CommandBus } from '@nestjs/cqrs';
|
||||
import { GrpcMethod, RpcException } from '@nestjs/microservices';
|
||||
import { DeleteAuthenticationCommand } from '@modules/authentication/core/application/commands/delete-authentication/delete-authentication.command';
|
||||
import { DeleteAuthenticationRequestDto } from './dtos/delete-authentication.request.dto';
|
||||
import { GRPC_AUTHENTICATION_SERVICE_NAME } from '@src/app.constants';
|
||||
|
||||
@UsePipes(
|
||||
new RpcValidationPipe({
|
||||
@@ -20,7 +21,7 @@ import { DeleteAuthenticationRequestDto } from './dtos/delete-authentication.req
|
||||
export class DeleteAuthenticationGrpcController {
|
||||
constructor(private readonly commandBus: CommandBus) {}
|
||||
|
||||
@GrpcMethod('AuthenticationService', 'Delete')
|
||||
@GrpcMethod(GRPC_AUTHENTICATION_SERVICE_NAME, 'Delete')
|
||||
async delete(data: DeleteAuthenticationRequestDto): Promise<void> {
|
||||
try {
|
||||
await this.commandBus.execute(new DeleteAuthenticationCommand(data));
|
||||
|
||||
@@ -9,6 +9,7 @@ import { CommandBus } from '@nestjs/cqrs';
|
||||
import { GrpcMethod, RpcException } from '@nestjs/microservices';
|
||||
import { DeleteUsernameRequestDto } from './dtos/delete-username.request.dto';
|
||||
import { DeleteUsernameCommand } from '@modules/authentication/core/application/commands/delete-username/delete-username.command';
|
||||
import { GRPC_AUTHENTICATION_SERVICE_NAME } from '@src/app.constants';
|
||||
|
||||
@UsePipes(
|
||||
new RpcValidationPipe({
|
||||
@@ -20,7 +21,7 @@ import { DeleteUsernameCommand } from '@modules/authentication/core/application/
|
||||
export class DeleteUsernameGrpcController {
|
||||
constructor(private readonly commandBus: CommandBus) {}
|
||||
|
||||
@GrpcMethod('AuthenticationService', 'DeleteUsername')
|
||||
@GrpcMethod(GRPC_AUTHENTICATION_SERVICE_NAME, 'DeleteUsername')
|
||||
async delete(data: DeleteUsernameRequestDto): Promise<void> {
|
||||
try {
|
||||
await this.commandBus.execute(new DeleteUsernameCommand(data));
|
||||
|
||||
@@ -16,7 +16,7 @@ export function IsValidUsername(validationOptions?: ValidationOptions) {
|
||||
options: validationOptions,
|
||||
validator: {
|
||||
validate(value: any, args: ValidationArguments) {
|
||||
const usernameType: Type = args.object['type'];
|
||||
const usernameType: Type = (args.object as any)['type'];
|
||||
switch (usernameType) {
|
||||
case Type.PHONE:
|
||||
return isPhoneNumber(value);
|
||||
|
||||
@@ -9,6 +9,7 @@ import { CommandBus } from '@nestjs/cqrs';
|
||||
import { GrpcMethod, RpcException } from '@nestjs/microservices';
|
||||
import { UpdatePasswordRequestDto } from './dtos/update-password.request.dto';
|
||||
import { UpdatePasswordCommand } from '@modules/authentication/core/application/commands/update-password/update-password.command';
|
||||
import { GRPC_AUTHENTICATION_SERVICE_NAME } from '@src/app.constants';
|
||||
|
||||
@UsePipes(
|
||||
new RpcValidationPipe({
|
||||
@@ -20,7 +21,7 @@ import { UpdatePasswordCommand } from '@modules/authentication/core/application/
|
||||
export class UpdatePasswordGrpcController {
|
||||
constructor(private readonly commandBus: CommandBus) {}
|
||||
|
||||
@GrpcMethod('AuthenticationService', 'UpdatePassword')
|
||||
@GrpcMethod(GRPC_AUTHENTICATION_SERVICE_NAME, 'UpdatePassword')
|
||||
async updatePassword(data: UpdatePasswordRequestDto): Promise<IdResponse> {
|
||||
try {
|
||||
const aggregateID: AggregateID = await this.commandBus.execute(
|
||||
|
||||
@@ -10,6 +10,7 @@ import { GrpcMethod, RpcException } from '@nestjs/microservices';
|
||||
import { UsernameAlreadyExistsException } from '@modules/authentication/core/domain/authentication.errors';
|
||||
import { UpdateUsernameRequestDto } from './dtos/update-username.request.dto';
|
||||
import { UpdateUsernameCommand } from '@modules/authentication/core/application/commands/update-username/update-username.command';
|
||||
import { GRPC_AUTHENTICATION_SERVICE_NAME } from '@src/app.constants';
|
||||
|
||||
@UsePipes(
|
||||
new RpcValidationPipe({
|
||||
@@ -21,7 +22,7 @@ import { UpdateUsernameCommand } from '@modules/authentication/core/application/
|
||||
export class UpdateUsernameGrpcController {
|
||||
constructor(private readonly commandBus: CommandBus) {}
|
||||
|
||||
@GrpcMethod('AuthenticationService', 'UpdateUsername')
|
||||
@GrpcMethod(GRPC_AUTHENTICATION_SERVICE_NAME, 'UpdateUsername')
|
||||
async updateUsername(data: UpdateUsernameRequestDto): Promise<IdResponse> {
|
||||
try {
|
||||
const aggregateID: AggregateID = await this.commandBus.execute(
|
||||
|
||||
@@ -9,6 +9,7 @@ import { QueryBus } from '@nestjs/cqrs';
|
||||
import { GrpcMethod, RpcException } from '@nestjs/microservices';
|
||||
import { ValidateAuthenticationRequestDto } from './dtos/validate-authentication.request.dto';
|
||||
import { ValidateAuthenticationQuery } from '@modules/authentication/core/application/queries/validate-authentication/validate-authentication.query';
|
||||
import { GRPC_AUTHENTICATION_SERVICE_NAME } from '@src/app.constants';
|
||||
|
||||
@UsePipes(
|
||||
new RpcValidationPipe({
|
||||
@@ -20,7 +21,7 @@ import { ValidateAuthenticationQuery } from '@modules/authentication/core/applic
|
||||
export class ValidateAuthenticationGrpcController {
|
||||
constructor(private readonly queryBus: QueryBus) {}
|
||||
|
||||
@GrpcMethod('AuthenticationService', 'Validate')
|
||||
@GrpcMethod(GRPC_AUTHENTICATION_SERVICE_NAME, 'Validate')
|
||||
async validate(data: ValidateAuthenticationRequestDto): Promise<IdResponse> {
|
||||
try {
|
||||
const aggregateID: AggregateID = await this.queryBus.execute(
|
||||
|
||||
@@ -2,13 +2,14 @@ import { Injectable } from '@nestjs/common';
|
||||
import { CommandBus } from '@nestjs/cqrs';
|
||||
import { RabbitSubscribe } from '@mobicoop/message-broker-module';
|
||||
import { DeleteAuthenticationCommand } from '@modules/authentication/core/application/commands/delete-authentication/delete-authentication.command';
|
||||
import { USER_DELETED_MESSAGE_HANDLER } from '@src/app.constants';
|
||||
|
||||
@Injectable()
|
||||
export class UserDeletedMessageHandler {
|
||||
constructor(private readonly commandBus: CommandBus) {}
|
||||
|
||||
@RabbitSubscribe({
|
||||
name: 'userDeleted',
|
||||
name: USER_DELETED_MESSAGE_HANDLER,
|
||||
})
|
||||
public async userDeleted(message: string) {
|
||||
const deletedUser = JSON.parse(message);
|
||||
|
||||
@@ -3,13 +3,14 @@ import { CommandBus } from '@nestjs/cqrs';
|
||||
import { RabbitSubscribe } from '@mobicoop/message-broker-module';
|
||||
import { Type } from '@modules/authentication/core/domain/username.types';
|
||||
import { UpdateUsernameCommand } from '@modules/authentication/core/application/commands/update-username/update-username.command';
|
||||
import { USER_UPDATED_MESSAGE_HANDLER } from '@src/app.constants';
|
||||
|
||||
@Injectable()
|
||||
export class UserUpdatedMessageHandler {
|
||||
constructor(private readonly commandBus: CommandBus) {}
|
||||
|
||||
@RabbitSubscribe({
|
||||
name: 'userUpdated',
|
||||
name: USER_UPDATED_MESSAGE_HANDLER,
|
||||
})
|
||||
public async userUpdated(message: string) {
|
||||
const updatedUser = JSON.parse(message);
|
||||
|
||||
@@ -147,9 +147,9 @@ describe('AuthenticationRepository', () => {
|
||||
},
|
||||
});
|
||||
|
||||
expect(updatedAuthentication.uuid).toBe(uuid);
|
||||
expect((updatedAuthentication as any).uuid).toBe(uuid);
|
||||
expect(authenticationToUpdate.updatedAt.getTime()).toBeLessThan(
|
||||
updatedAuthentication.updatedAt.getTime(),
|
||||
(updatedAuthentication as any).updatedAt.getTime(),
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -84,9 +84,8 @@ describe('UsernameRepository', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const username = await usernameRepository.findByName(
|
||||
'john.doe@email.com',
|
||||
);
|
||||
const username =
|
||||
await usernameRepository.findByName('john.doe@email.com');
|
||||
expect(username.id).toBe('john.doe@email.com');
|
||||
});
|
||||
|
||||
@@ -103,9 +102,8 @@ describe('UsernameRepository', () => {
|
||||
it('should create a username', async () => {
|
||||
const beforeCount = await prismaService.username.count();
|
||||
|
||||
const usernameToCreate: UsernameEntity = await UsernameEntity.create(
|
||||
createUsernameProps,
|
||||
);
|
||||
const usernameToCreate: UsernameEntity =
|
||||
await UsernameEntity.create(createUsernameProps);
|
||||
await usernameRepository.insert(usernameToCreate);
|
||||
|
||||
const afterCount = await prismaService.username.count();
|
||||
@@ -122,9 +120,8 @@ describe('UsernameRepository', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const usernameToCreate: UsernameEntity = await UsernameEntity.create(
|
||||
createUsernameProps,
|
||||
);
|
||||
const usernameToCreate: UsernameEntity =
|
||||
await UsernameEntity.create(createUsernameProps);
|
||||
await expect(
|
||||
usernameRepository.insert(usernameToCreate),
|
||||
).rejects.toBeInstanceOf(UniqueConstraintException);
|
||||
@@ -141,9 +138,8 @@ describe('UsernameRepository', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const toUpdate: UsernameEntity = await UsernameEntity.create(
|
||||
createUsernameProps,
|
||||
);
|
||||
const toUpdate: UsernameEntity =
|
||||
await UsernameEntity.create(createUsernameProps);
|
||||
await usernameRepository.updateUsername(
|
||||
usernameToUpdate.username,
|
||||
toUpdate,
|
||||
@@ -155,16 +151,15 @@ describe('UsernameRepository', () => {
|
||||
},
|
||||
});
|
||||
|
||||
expect(updatedUsername.username).toBe('john.doe@email.com');
|
||||
expect((updatedUsername as any).username).toBe('john.doe@email.com');
|
||||
expect(usernameToUpdate.updatedAt.getTime()).toBeLessThan(
|
||||
updatedUsername.updatedAt.getTime(),
|
||||
(updatedUsername as any).updatedAt.getTime(),
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw a DatabaseException if id is unknown', async () => {
|
||||
const toUpdate: UsernameEntity = await UsernameEntity.create(
|
||||
createUsernameProps,
|
||||
);
|
||||
const toUpdate: UsernameEntity =
|
||||
await UsernameEntity.create(createUsernameProps);
|
||||
|
||||
await expect(
|
||||
usernameRepository.updateUsername('jane.doe@email.com', toUpdate),
|
||||
@@ -181,9 +176,8 @@ describe('UsernameRepository', () => {
|
||||
username: 'john.doe@email.com',
|
||||
},
|
||||
});
|
||||
const toDelete: UsernameEntity = await UsernameEntity.create(
|
||||
createUsernameProps,
|
||||
);
|
||||
const toDelete: UsernameEntity =
|
||||
await UsernameEntity.create(createUsernameProps);
|
||||
await usernameRepository.deleteUsername(toDelete);
|
||||
|
||||
const count = await prismaService.username.count();
|
||||
@@ -191,9 +185,8 @@ describe('UsernameRepository', () => {
|
||||
});
|
||||
|
||||
it('should throw a DatabaseException if username does not exist', async () => {
|
||||
const toDelete: UsernameEntity = await UsernameEntity.create(
|
||||
createUsernameProps,
|
||||
);
|
||||
const toDelete: UsernameEntity =
|
||||
await UsernameEntity.create(createUsernameProps);
|
||||
await expect(usernameRepository.delete(toDelete)).rejects.toBeInstanceOf(
|
||||
DatabaseErrorException,
|
||||
);
|
||||
|
||||
@@ -82,9 +82,8 @@ describe('Add Username Service', () => {
|
||||
})),
|
||||
});
|
||||
it('should add a new username', async () => {
|
||||
const result: AggregateID = await addUsernameService.execute(
|
||||
addUsernameCommand,
|
||||
);
|
||||
const result: AggregateID =
|
||||
await addUsernameService.execute(addUsernameCommand);
|
||||
expect(result).toBe('john.doe@email.com');
|
||||
});
|
||||
it('should throw a dedicated exception if username already exists for this type', async () => {
|
||||
|
||||
@@ -80,17 +80,15 @@ describe('Authentication password validation', () => {
|
||||
it('should validate a valid password', async () => {
|
||||
const authenticationEntity: AuthenticationEntity =
|
||||
await AuthenticationEntity.create(createAuthenticationProps);
|
||||
const result: boolean = await authenticationEntity.authenticate(
|
||||
'somePassword',
|
||||
);
|
||||
const result: boolean =
|
||||
await authenticationEntity.authenticate('somePassword');
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
it('should not validate an invalid password', async () => {
|
||||
const authenticationEntity: AuthenticationEntity =
|
||||
await AuthenticationEntity.create(createAuthenticationProps);
|
||||
const result: boolean = await authenticationEntity.authenticate(
|
||||
'someWrongPassword',
|
||||
);
|
||||
const result: boolean =
|
||||
await authenticationEntity.authenticate('someWrongPassword');
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -14,18 +14,16 @@ const createUsernameProps: CreateUsernameProps = {
|
||||
|
||||
describe('Username entity create', () => {
|
||||
it('should create a new username entity', async () => {
|
||||
const usernameEntity: UsernameEntity = await UsernameEntity.create(
|
||||
createUsernameProps,
|
||||
);
|
||||
const usernameEntity: UsernameEntity =
|
||||
await UsernameEntity.create(createUsernameProps);
|
||||
expect(usernameEntity.id).toBe('john.doe@email.com');
|
||||
expect(usernameEntity.domainEvents.length).toBe(1);
|
||||
});
|
||||
});
|
||||
describe('Username entity update', () => {
|
||||
it('should update a username entity', async () => {
|
||||
const usernameEntity: UsernameEntity = await UsernameEntity.create(
|
||||
createUsernameProps,
|
||||
);
|
||||
const usernameEntity: UsernameEntity =
|
||||
await UsernameEntity.create(createUsernameProps);
|
||||
usernameEntity.update({
|
||||
name: 'new-john.doe@email.com',
|
||||
});
|
||||
@@ -38,9 +36,8 @@ describe('Username entity update', () => {
|
||||
});
|
||||
describe('Username entity delete', () => {
|
||||
it('should delete a username entity', async () => {
|
||||
const usernameEntity: UsernameEntity = await UsernameEntity.create(
|
||||
createUsernameProps,
|
||||
);
|
||||
const usernameEntity: UsernameEntity =
|
||||
await UsernameEntity.create(createUsernameProps);
|
||||
usernameEntity.delete();
|
||||
expect(usernameEntity.domainEvents.length).toBe(2);
|
||||
expect(usernameEntity.domainEvents[1]).toBeInstanceOf(
|
||||
|
||||
@@ -85,9 +85,8 @@ describe('Username repository', () => {
|
||||
|
||||
it('should find a username by its name', async () => {
|
||||
jest.spyOn(usernameRepository, 'findOne');
|
||||
const username: UsernameEntity = await usernameRepository.findByName(
|
||||
'john.doe@email.com',
|
||||
);
|
||||
const username: UsernameEntity =
|
||||
await usernameRepository.findByName('john.doe@email.com');
|
||||
expect(usernameRepository.findOne).toHaveBeenCalledTimes(1);
|
||||
expect(usernameRepository.findOne).toHaveBeenCalledWith({
|
||||
username: 'john.doe@email.com',
|
||||
|
||||
@@ -55,9 +55,8 @@ describe('Add Username Grpc Controller', () => {
|
||||
|
||||
it('should add a new username', async () => {
|
||||
jest.spyOn(mockCommandBus, 'execute');
|
||||
const result: IdResponse = await addUsernameGrpcController.addUsername(
|
||||
addUsernameRequest,
|
||||
);
|
||||
const result: IdResponse =
|
||||
await addUsernameGrpcController.addUsername(addUsernameRequest);
|
||||
expect(result).toBeInstanceOf(IdResponse);
|
||||
expect(result.id).toBe('john.doe@email.com');
|
||||
expect(mockCommandBus.execute).toHaveBeenCalledTimes(1);
|
||||
|
||||
@@ -42,15 +42,13 @@ export class UsernameMapper
|
||||
updatedAt: new Date(record.updatedAt),
|
||||
props: {
|
||||
name: record.username,
|
||||
type: Type[record.type],
|
||||
type: record.type as Type,
|
||||
userId: record.authUuid,
|
||||
},
|
||||
});
|
||||
return entity;
|
||||
};
|
||||
|
||||
toResponse = (entity: UsernameEntity): UsernameResponseDto => {
|
||||
const response = new UsernameResponseDto(entity);
|
||||
return response;
|
||||
};
|
||||
toResponse = (entity: UsernameEntity): UsernameResponseDto =>
|
||||
new UsernameResponseDto(entity);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@ export abstract class DecisionMakerPort {
|
||||
abstract decide(
|
||||
domain: Domain,
|
||||
action: Action,
|
||||
context: ContextItem[],
|
||||
context?: ContextItem[],
|
||||
): Promise<boolean>;
|
||||
}
|
||||
|
||||
@@ -21,12 +21,14 @@ export class OpaDecisionMaker extends DecisionMakerPort {
|
||||
decide = async (
|
||||
domain: Domain,
|
||||
action: Action,
|
||||
context: ContextItem[],
|
||||
context?: ContextItem[],
|
||||
): Promise<boolean> => {
|
||||
const reducedContext = context.reduce(
|
||||
(obj, item) => Object.assign(obj, { [item.name]: item.value }),
|
||||
{},
|
||||
);
|
||||
const reducedContext = context
|
||||
? context.reduce(
|
||||
(obj, item) => Object.assign(obj, { [item.name]: item.value }),
|
||||
{},
|
||||
)
|
||||
: undefined;
|
||||
try {
|
||||
const { data } = await lastValueFrom(
|
||||
this.httpService.post<Decision>(
|
||||
|
||||
@@ -5,6 +5,7 @@ import { GrpcMethod, RpcException } from '@nestjs/microservices';
|
||||
import { DecisionRequestDto } from './dtos/decision.request.dto';
|
||||
import { DecisionQuery } from '@modules/authorization/core/application/queries/decision/decision.query';
|
||||
import { DecisionResponseDto } from '../dtos/decision.response.dto';
|
||||
import { GRPC_AUTHORIZATION_SERVICE_NAME } from '@src/app.constants';
|
||||
|
||||
@UsePipes(
|
||||
new RpcValidationPipe({
|
||||
@@ -16,7 +17,7 @@ import { DecisionResponseDto } from '../dtos/decision.response.dto';
|
||||
export class DecideGrpcController {
|
||||
constructor(private readonly queryBus: QueryBus) {}
|
||||
|
||||
@GrpcMethod('AuthorizationService', 'Decide')
|
||||
@GrpcMethod(GRPC_AUTHORIZATION_SERVICE_NAME, 'Decide')
|
||||
async decide(data: DecisionRequestDto): Promise<DecisionResponseDto> {
|
||||
try {
|
||||
const allow: boolean = await this.queryBus.execute(
|
||||
|
||||
@@ -49,9 +49,8 @@ describe('Decision Query Handler', () => {
|
||||
value: '96d99d44-e0a6-458e-a656-de2a400d60a8',
|
||||
},
|
||||
]);
|
||||
const decision: boolean = await decisionQueryHandler.execute(
|
||||
decisionQuery,
|
||||
);
|
||||
const decision: boolean =
|
||||
await decisionQueryHandler.execute(decisionQuery);
|
||||
expect(decision).toBeTruthy();
|
||||
});
|
||||
it('should return a negative decision', async () => {
|
||||
@@ -65,9 +64,8 @@ describe('Decision Query Handler', () => {
|
||||
value: '96d99d44-e0a6-458e-a656-de2a400d60a9',
|
||||
},
|
||||
]);
|
||||
const decision: boolean = await decisionQueryHandler.execute(
|
||||
decisionQuery,
|
||||
);
|
||||
const decision: boolean =
|
||||
await decisionQueryHandler.execute(decisionQuery);
|
||||
expect(decision).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,6 +6,15 @@ import {
|
||||
MessageBrokerPublisher,
|
||||
} from '@mobicoop/message-broker-module';
|
||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||
import {
|
||||
SERVICE_NAME,
|
||||
USER_DELETED_MESSAGE_HANDLER,
|
||||
USER_DELETED_QUEUE,
|
||||
USER_DELETED_ROUTING_KEY,
|
||||
USER_UPDATED_MESSAGE_HANDLER,
|
||||
USER_UPDATED_QUEUE,
|
||||
USER_UPDATED_ROUTING_KEY,
|
||||
} from '@src/app.constants';
|
||||
|
||||
const imports = [
|
||||
MessageBrokerModule.forRootAsync({
|
||||
@@ -14,17 +23,22 @@ const imports = [
|
||||
useFactory: async (
|
||||
configService: ConfigService,
|
||||
): Promise<MessageBrokerModuleOptions> => ({
|
||||
uri: configService.get<string>('MESSAGE_BROKER_URI'),
|
||||
exchange: configService.get<string>('MESSAGE_BROKER_EXCHANGE'),
|
||||
name: 'auth',
|
||||
uri: configService.get<string>('MESSAGE_BROKER_URI') as string,
|
||||
exchange: {
|
||||
name: configService.get<string>('MESSAGE_BROKER_EXCHANGE') as string,
|
||||
durable: configService.get<boolean>(
|
||||
'MESSAGE_BROKER_EXCHANGE_DURABILITY',
|
||||
) as boolean,
|
||||
},
|
||||
name: SERVICE_NAME,
|
||||
handlers: {
|
||||
userUpdated: {
|
||||
routingKey: 'user.updated',
|
||||
queue: 'auth-user-updated',
|
||||
[USER_UPDATED_MESSAGE_HANDLER]: {
|
||||
routingKey: USER_UPDATED_ROUTING_KEY,
|
||||
queue: USER_UPDATED_QUEUE,
|
||||
},
|
||||
userDeleted: {
|
||||
routingKey: 'user.deleted',
|
||||
queue: 'auth-user-deleted',
|
||||
[USER_DELETED_MESSAGE_HANDLER]: {
|
||||
routingKey: USER_DELETED_ROUTING_KEY,
|
||||
queue: USER_DELETED_QUEUE,
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user