MERGE MAIN

This commit is contained in:
Gabriel Rosa
2022-08-03 10:36:57 -03:00
43 changed files with 2253 additions and 230 deletions
+4 -2
View File
@@ -10,7 +10,7 @@ import {
} from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { AuthenticateCondition } from '../../authentication/authentication.decorator';
import { Permissions } from '../../authentication/permissions.enum';
import { PERMISSIONS } from '../../authentication/permissions.enum';
import { CatalogService } from './catalog.service';
import { DadosferaLogger } from 'dadosfera-logs';
@@ -32,7 +32,9 @@ import { DadosferaLogger } from 'dadosfera-logs';
action = req.method;
}
return user.permissions.includes(Permissions.CATALOG[action].seqid);
return user.permissions.includes(
PERMISSIONS.CATALOG.permissions[action].seqid,
);
})
export class CatalogController {
logger: any;
@@ -18,7 +18,7 @@ import {
Authenticated,
RequireAllPermissions,
} from 'src/authentication/authentication.decorator';
import { Permissions } from 'src/authentication/permissions.enum';
import { PERMISSIONS } from 'src/authentication/permissions.enum';
import { User } from 'src/authentication/user.decorator';
import { ValidationPipe } from '../../pipes/object-validation.pipe';
import { UpdateConnectionDto } from './dtos/update-connection';
+12 -12
View File
@@ -29,7 +29,7 @@ import {
Authenticated,
RequireAllPermissions,
} from 'src/authentication/authentication.decorator';
import { Permissions } from 'src/authentication/permissions.enum';
import { PERMISSIONS } from 'src/authentication/permissions.enum';
@ApiTags('connectors')
@ApiBearerAuth()
@@ -46,7 +46,7 @@ export class ConnectorController {
}
@Post()
@RequireAllPermissions(Permissions.CONNECTORS.CREATE)
@RequireAllPermissions(PERMISSIONS.CONNECTORS.permissions.CREATE)
@ApiConsumes('multipart/form-data')
@UseInterceptors(FileInterceptor('file'))
async uploadConnector(
@@ -64,7 +64,7 @@ export class ConnectorController {
}
@Post('/uploads')
@RequireAllPermissions(Permissions.CONNECTORS.CREATE)
@RequireAllPermissions(PERMISSIONS.CONNECTORS.permissions.CREATE)
@ApiConsumes('multipart/form-data')
@UseInterceptors(FilesInterceptor('files'))
async uploadFile(@UploadedFiles() files) {
@@ -81,7 +81,7 @@ export class ConnectorController {
}
@Post('/multiple-connectors-upload')
@RequireAllPermissions(Permissions.CONNECTORS.CREATE)
@RequireAllPermissions(PERMISSIONS.CONNECTORS.permissions.CREATE)
@ApiConsumes('multipart/form-data')
@UseInterceptors(FileInterceptor('file'))
async uploadConnectorsFile(@UploadedFile() file: UploadConnectorsFileDto) {
@@ -95,7 +95,7 @@ export class ConnectorController {
}
@Get()
@RequireAllPermissions(Permissions.CONNECTORS.GET)
@RequireAllPermissions(PERMISSIONS.CONNECTORS.permissions.GET)
async getAllConnectors(
@Headers('dadosfera-lang') language,
@Query() queries: GetAllDto,
@@ -121,13 +121,13 @@ export class ConnectorController {
}
@Get('/tags')
@RequireAllPermissions(Permissions.CONNECTORS.GET)
@RequireAllPermissions(PERMISSIONS.CONNECTORS.permissions.GET)
async getConnectorsTags() {
return await this.connectorClientService.getConnectorsTags();
}
@Get('/:plugin')
@RequireAllPermissions(Permissions.CONNECTORS.GET)
@RequireAllPermissions(PERMISSIONS.CONNECTORS.permissions.GET)
async getConnector(
@Headers('dadosfera-lang') language,
@Param('plugin') plugin: string,
@@ -149,7 +149,7 @@ export class ConnectorController {
}
@Get('/:plugin/details')
@RequireAllPermissions(Permissions.CONNECTORS.GET)
@RequireAllPermissions(PERMISSIONS.CONNECTORS.permissions.GET)
async getConnectorDetails(
@Headers('dadosfera-lang') language,
@Param('plugin') plugin: string,
@@ -171,7 +171,7 @@ export class ConnectorController {
}
@Put('/:plugin')
@RequireAllPermissions(Permissions.CONNECTORS.UPDATE)
@RequireAllPermissions(PERMISSIONS.CONNECTORS.permissions.UPDATE)
@ApiConsumes('multipart/form-data')
async updateConnector(
@Param('plugin') plugin: string,
@@ -193,7 +193,7 @@ export class ConnectorController {
}
@Put('/:plugin/add-tag')
@RequireAllPermissions(Permissions.CONNECTORS.UPDATE)
@RequireAllPermissions(PERMISSIONS.CONNECTORS.permissions.UPDATE)
async addTagOnConnector(
@Param('plugin') plugin: string,
@Body() body: AddTagDto,
@@ -220,7 +220,7 @@ export class ConnectorController {
}
@Put('/:plugin/remove-tag')
@RequireAllPermissions(Permissions.CONNECTORS.UPDATE)
@RequireAllPermissions(PERMISSIONS.CONNECTORS.permissions.UPDATE)
async removeTagOnConnector(
@Param('plugin') plugin: string,
@Body() body: RemoveTagDto,
@@ -248,7 +248,7 @@ export class ConnectorController {
}
@Delete('/:plugin')
@RequireAllPermissions(Permissions.CONNECTORS.DELETE)
@RequireAllPermissions(PERMISSIONS.CONNECTORS.permissions.DELETE)
async deleteConnector(
@Param('plugin') plugin: string,
@Body() { version }: DeleteConnectorDto,
+3 -3
View File
@@ -12,7 +12,7 @@ import { InputsService } from './inputs.service';
import { DadosferaLogger } from 'dadosfera-logs';
import { InputsClientService } from 'src/clients/inputs/client.service';
import { UpdateInputRequest } from 'src/clients/inputs/interfaces';
import { Permissions } from '../../authentication/permissions.enum';
import { PERMISSIONS } from '../../authentication/permissions.enum';
import { AuthenticateCondition } from 'src/authentication/authentication.decorator';
import { ApiOkResponse, ApiTags } from '@nestjs/swagger';
import {
@@ -41,7 +41,7 @@ import {
break;
case 'PATCH':
action = 'UPDATE_PARTIAL';
action = 'UPDATE';
break;
default:
@@ -55,7 +55,7 @@ import {
action = 'GET_ENTITIES';
}
return user.permissions.includes(Permissions.INPUT[action].seqid);
return user.permissions.includes(PERMISSIONS.INPUT.permissions[action].seqid);
})
export class InputsController {
inputService: InputsService;
+3 -2
View File
@@ -7,7 +7,7 @@ import { IIdRequest, Info } from 'src/clients/inputs/interfaces';
@Injectable()
export class InputsService {
constructor(private inputClient: InputsClientService) { }
constructor(private inputClient: InputsClientService) {}
secondsInADay = 60 * 60 * 24;
secondsInAnHour = 60 * 60;
@@ -54,7 +54,7 @@ export class InputsService {
switch (data.plugin.toLowerCase()) {
case 'csv':
case 'json':
case 'parquet':
case 'parquet': {
const { info, ...input } = data;
const inputPayload = this.generateInputS3Payload(input);
response = await this.inputClient.createS3Inputs({
@@ -62,6 +62,7 @@ export class InputsService {
info,
});
break;
}
case 'oracle':
case 'mysql':
case 'postgresql':
+4 -2
View File
@@ -12,7 +12,7 @@ import { Payload } from '@nestjs/microservices';
import { ApiTags } from '@nestjs/swagger';
import { OutputsClientService } from 'src/clients/outputs/client.service';
import { AuthenticateCondition } from 'src/authentication/authentication.decorator';
import { Permissions } from '../../authentication/permissions.enum';
import { PERMISSIONS } from '../../authentication/permissions.enum';
import { OutputsService } from './outputs.service';
import { DadosferaLogger } from 'dadosfera-logs';
@@ -34,7 +34,9 @@ import { DadosferaLogger } from 'dadosfera-logs';
action = req.method;
}
return user.permissions.includes(Permissions.OUTPUT[action].seqid);
return user.permissions.includes(
PERMISSIONS.OUTPUT.permissions[action].seqid,
);
})
export class OutputsController {
logger: any;
+49
View File
@@ -0,0 +1,49 @@
import { ApiProperty } from '@nestjs/swagger';
export class PermissionGroupPermission {
@ApiProperty()
name: string;
@ApiProperty()
id: number;
}
export class PermissionGroup {
@ApiProperty()
title: string;
@ApiProperty({ type: [PermissionGroupPermission] })
permissions: PermissionGroupPermission[];
}
export class Permission {
@ApiProperty()
id: string;
@ApiProperty()
seqid: number;
@ApiProperty()
name: string;
@ApiProperty()
claim: string;
@ApiProperty()
createdAt: string;
@ApiProperty()
updatedAt: string;
}
export class PermissionDto {
@ApiProperty()
id: number;
@ApiProperty()
seqid: number;
@ApiProperty()
name: string;
@ApiProperty()
claim: string;
@ApiProperty()
createdAt: string;
@ApiProperty()
updatedAt: string;
}
export class GetPublicPermissionsRes {
@ApiProperty({ type: [PermissionGroup] })
permissionGroups: PermissionGroup[];
}
@@ -0,0 +1,42 @@
import { ClientsModule } from '@nestjs/microservices';
import { Test, TestingModule } from '@nestjs/testing';
import { DucClient } from 'src/clients/duc/client.config';
import { PermissionsController } from './permissions.controller';
import { DadosferaLogger } from 'dadosfera-logs';
import { PermissionsService } from './permissions.service';
const ducClient = new DucClient();
const logger = {
info: (...args) => args,
error: (...args) => args,
};
describe('PermissionsController', () => {
let controller: PermissionsController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [
ClientsModule.register([
{
name: 'DUC_PACKAGE',
...ducClient.config(),
},
]),
],
controllers: [PermissionsController],
providers: [
{
provide: DadosferaLogger,
useValue: { logger },
},
PermissionsService,
],
}).compile();
controller = module.get<PermissionsController>(PermissionsController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});
@@ -0,0 +1,51 @@
import { Controller, Get, Headers, Inject } from '@nestjs/common';
import { ApiHeader, ApiOkResponse, ApiTags } from '@nestjs/swagger';
import { DadosferaLogger } from 'dadosfera-logs';
import {
Authenticated,
RequireAllPermissions,
} from 'src/authentication/authentication.decorator';
import {
PERMISSIONS,
PermissionUsages,
} from 'src/authentication/permissions.enum';
import { RequestUser, User } from 'src/authentication/user.decorator';
import { LanguageEnum } from 'src/utils/languages.enum';
import { GetPublicPermissionsRes } from './dto/entities';
import { PermissionsService } from './permissions.service';
@ApiTags('Permissions')
@Controller('permissions')
@ApiHeader({
name: 'dadosfera-lang',
enum: LanguageEnum,
required: false,
description: 'Defaults to pt-br',
})
@Authenticated()
export class PermissionsController {
logger: any;
constructor(
@Inject(DadosferaLogger)
dadosferaLogger: DadosferaLogger,
private permissionsService: PermissionsService,
) {
this.logger = dadosferaLogger.logger;
}
@Get()
@ApiOkResponse({ type: GetPublicPermissionsRes })
@RequireAllPermissions(PERMISSIONS.USERS.permissions.ADMIN)
getPublicPermissions(
@User() user: RequestUser,
@Headers('dadosfera-lang') language,
) {
this.logger.info('getPublicPermissions', { user });
const permissionGroups = this.permissionsService.getPermissionsGrouped(
PermissionUsages.PUBLIC,
language,
);
return { permissionGroups };
}
}
@@ -2,9 +2,11 @@ import { Module } from '@nestjs/common';
import { ClientsModule } from '@nestjs/microservices';
import { DadosferaLogger } from 'dadosfera-logs';
import { PermissionsClientService } from './permissions.service';
import { PermissionsService } from './permissions.service';
import { DucClient } from '../../clients/duc/client.config';
import { PermissionsController } from './permissions.controller';
const ducClient = new DucClient();
@Module({
@@ -16,6 +18,8 @@ const ducClient = new DucClient();
},
]),
],
providers: [PermissionsClientService, DadosferaLogger],
providers: [PermissionsService, DadosferaLogger],
controllers: [PermissionsController],
exports: [PermissionsService],
})
export class PermissionsModule {}
+55 -7
View File
@@ -11,16 +11,23 @@ import { ProtoServices } from '@dadosfera/protospack-v2/dist/lib/Duc';
import { PermissionsProtoService as PermissionsServiceInterface } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/write-service';
import { InjectPermissionsRequest } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/messages';
import { DadosferaLogger } from 'dadosfera-logs';
import { Permissions } from '../../authentication/permissions.enum';
import {
PERMISSIONS,
PermissionUsages,
PermissionsObjectGroup,
PermissionsObjectPermissionTranslated,
} from '../../authentication/permissions.enum';
import ErrorBuilder from '../../utils/ErrorBuilder';
import { PermissionGroupPermission, PermissionGroup } from './dto/entities';
import { LanguageEnum } from 'src/utils/languages.enum';
@Injectable()
export class PermissionsClientService
export class PermissionsService
implements OnModuleInit, OnApplicationBootstrap
{
logger: any;
private permissionsService: PermissionsServiceInterface;
private permissionsClientService: PermissionsServiceInterface;
constructor(
@Inject(DadosferaLogger)
dadosferaLogger: DadosferaLogger,
@@ -30,7 +37,7 @@ export class PermissionsClientService
}
onModuleInit() {
this.permissionsService =
this.permissionsClientService =
this.grpcClient.getService<PermissionsServiceInterface>(
ProtoServices.PermissionsProtoService,
);
@@ -40,8 +47,8 @@ export class PermissionsClientService
async onApplicationBootstrap() {
this.logger.info('sending permissions to DUC...');
const permissions = Object.values(Permissions).flatMap((namespace) =>
Object.values(namespace),
const permissions = Object.values(PERMISSIONS).flatMap((namespace) =>
Object.values(namespace.permissions),
);
return this.injectPermissions({
@@ -64,7 +71,48 @@ export class PermissionsClientService
this.logger.info('InjectPermissions');
return lastValueFrom(
this.permissionsService.InjectPermissions({ permissions }),
this.permissionsClientService.InjectPermissions({ permissions }),
);
}
getPermissionsGrouped(
permissionUsage?: PermissionUsages,
language: LanguageEnum = LanguageEnum.ptbr,
): PermissionGroup[] {
const groups: PermissionGroup[] = [];
for (const key in PERMISSIONS) {
const permissionGroup: PermissionsObjectGroup = PERMISSIONS[key];
const title = permissionGroup.title[language];
const permissions: PermissionGroupPermission[] = Object.values(
permissionGroup.permissions,
)
.filter(({ usage }) =>
permissionUsage ? usage === permissionUsage : true,
)
.map(({ seqid, name }) => ({ id: seqid, name: name[language] }));
if (permissions?.length)
groups.push({
title,
permissions,
});
}
return groups;
}
getAllPermissions(language: LanguageEnum = LanguageEnum.ptbr) {
let permissions: PermissionsObjectPermissionTranslated[] = [];
for (const key in PERMISSIONS) {
const permissionGroup: PermissionsObjectGroup = PERMISSIONS[key];
const permissionGroupPermissions: PermissionsObjectPermissionTranslated[] =
Object.values(permissionGroup.permissions).map((p) => ({
...p,
name: p.name[language],
}));
permissions = permissions.concat(permissionGroupPermissions);
}
return permissions;
}
getPermissionsBySeqId(seqIds: number[]) {
const permissionGroupPermissions = this.getAllPermissions();
return permissionGroupPermissions.filter((p) => seqIds.includes(p.seqid));
}
}
@@ -11,7 +11,7 @@ import {
import { ApiTags } from '@nestjs/swagger';
import { PipelinesClientService } from 'src/clients/pipelines/client.service';
import { AuthenticateCondition } from 'src/authentication/authentication.decorator';
import { Permissions } from '../../authentication/permissions.enum';
import { PERMISSIONS } from '../../authentication/permissions.enum';
import { PipelinesService } from './pipelines.service';
import { DadosferaLogger } from 'dadosfera-logs';
@@ -33,7 +33,9 @@ import { DadosferaLogger } from 'dadosfera-logs';
action = req.method;
}
return user.permissions.includes(Permissions.PIPELINE[action].seqid);
return user.permissions.includes(
PERMISSIONS.PIPELINE.permissions[action].seqid,
);
})
export class PipelinesController {
logger: any;
+115
View File
@@ -0,0 +1,115 @@
import { ApiProperty, ApiPropertyOptional, OmitType } from '@nestjs/swagger';
import { PermissionDto } from 'src/modules/permissions/dto/entities';
import {
Customer,
UserNoRolesAndCustomer,
} from 'src/modules/users/dtos/entities';
export class RoleDto {
@ApiProperty()
id: string;
@ApiProperty()
name: string;
@ApiProperty()
description: string;
@ApiPropertyOptional({ type: () => [PermissionDto] })
permissions: PermissionDto[];
@ApiPropertyOptional({ type: () => [UserNoRolesAndCustomer] })
users?: UserNoRolesAndCustomer[];
@ApiProperty()
createdAt: string;
@ApiProperty()
updatedAt: string;
@ApiProperty()
isPublic: boolean;
@ApiProperty({ type: () => Customer })
customer?: Customer;
}
export class CustomerRole extends OmitType(RoleDto, ['customer']) {}
export class UserRole extends OmitType(RoleDto, ['users']) {}
export enum TrueOrFalseEnum {
true = 'true',
false = 'false',
}
export class GetRolesByCustomerReq {
@ApiPropertyOptional()
permissionId: string[];
@ApiPropertyOptional({ enum: TrueOrFalseEnum })
getUsers: TrueOrFalseEnum;
}
export class GetRolesByCustomerRes {
@ApiProperty({ type: [RoleDto] })
roles: RoleDto[];
}
export class CreateRoleReq {
@ApiProperty()
name: string;
@ApiProperty()
permissionIds: number[];
@ApiPropertyOptional()
userIds: string[];
@ApiProperty()
description: string;
}
export class CreateRoleRes {
@ApiProperty()
role: CustomerRole;
}
export class GrantPermissionsToRoleReq {
@ApiProperty()
roleId: string;
@ApiProperty()
permissionIds: number[];
}
export class GrantPermissionsToRoleRes {
@ApiProperty()
role: RoleDto;
}
export class RevokePermissionsFromRoleReq {
@ApiProperty()
roleId: string;
@ApiProperty()
permissionIds: number[];
}
export class RevokePermissionsFromRoleRes {
@ApiProperty()
role: RoleDto;
}
export class UpdateRoleReq {
@ApiPropertyOptional()
name: string;
@ApiPropertyOptional()
description: string;
}
export class UpdateRoleRes {
@ApiProperty()
role: RoleDto;
}
export class SetRolePermissionsReq {
@ApiProperty()
roleId: string;
@ApiProperty()
permissionIds: number[];
}
export class SetRolePermissionsRes {
@ApiProperty()
role: RoleDto;
}
export class SetRoleUsersReq {
@ApiProperty()
roleId: string;
@ApiProperty()
userIds: string[];
}
export class SetRoleUsersRes {
@ApiProperty()
role: RoleDto;
}
@@ -0,0 +1,46 @@
import { ClientsModule } from '@nestjs/microservices';
import { Test, TestingModule } from '@nestjs/testing';
import { DucClient } from 'src/clients/duc/client.config';
import { RolesController } from './roles.controller';
import { RolesService } from './roles.service';
import { DadosferaLogger } from 'dadosfera-logs';
import { PermissionsModule } from '../permissions/permissions.module';
const ducClient = new DucClient();
const logger = {
info: (...args) => args,
error: (...args) => args,
};
describe('RolesController', () => {
let controller: RolesController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [
ClientsModule.register([
{
name: 'DUC_PACKAGE',
...ducClient.config(),
},
]),
PermissionsModule,
],
controllers: [RolesController],
providers: [
RolesService,
{
provide: DadosferaLogger,
useValue: { logger },
},
],
exports: [RolesService],
}).compile();
controller = module.get<RolesController>(RolesController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});
+186
View File
@@ -0,0 +1,186 @@
import {
Body,
Controller,
Delete,
Get,
Headers,
Inject,
Param,
Patch,
Post,
Put,
Query,
UseFilters,
} from '@nestjs/common';
import {
ApiCreatedResponse,
ApiHeader,
ApiOkResponse,
ApiTags,
} from '@nestjs/swagger';
import { RequestUser, User } from 'src/authentication/user.decorator';
import { DadosferaLogger } from 'dadosfera-logs';
import { RolesService } from './roles.service';
import {
GrantPermissionsToRoleReq,
GrantPermissionsToRoleRes,
CreateRoleReq,
CreateRoleRes,
GetRolesByCustomerReq,
GetRolesByCustomerRes,
RevokePermissionsFromRoleReq,
RevokePermissionsFromRoleRes,
UpdateRoleReq,
UpdateRoleRes,
RoleDto,
SetRolePermissionsReq,
SetRolePermissionsRes,
SetRoleUsersRes,
SetRoleUsersReq,
} from './dto/entities';
import { GrpcToHttpExceptionFilter } from 'src/error/grpc-to-http-exception.filter';
import { PERMISSIONS } from 'src/authentication/permissions.enum';
import {
Authenticated,
RequireAllPermissions,
} from 'src/authentication/authentication.decorator';
import { LanguageEnum } from 'src/utils/languages.enum';
@ApiTags('Roles')
@ApiHeader({
name: 'dadosfera-lang',
enum: LanguageEnum,
required: false,
description: 'Defaults to pt-br',
})
@UseFilters(new GrpcToHttpExceptionFilter())
@Authenticated()
@Controller('roles')
export class RolesController {
logger: any;
constructor(
@Inject(DadosferaLogger)
dadosferaLogger: DadosferaLogger,
private rolesService: RolesService,
) {
this.logger = dadosferaLogger.logger;
}
@Get()
@ApiOkResponse({ type: GetRolesByCustomerRes })
@RequireAllPermissions(PERMISSIONS.USERS.permissions.ADMIN)
async searchRoles(
@User() user: RequestUser,
@Query() filters: GetRolesByCustomerReq,
@Headers('dadosfera-lang') language,
) {
this.logger.info('searchRoles', { user });
this.rolesService.setLanguage(language);
return await this.rolesService.roleSearch(filters, user);
}
@Post()
@ApiCreatedResponse({ type: CreateRoleRes })
@RequireAllPermissions(PERMISSIONS.USERS.permissions.ADMIN)
async createRole(
@User() user: RequestUser,
@Body() body: CreateRoleReq,
@Headers('dadosfera-lang') language,
) {
this.logger.info('createRole', { user });
this.rolesService.setLanguage(language);
return await this.rolesService.createRole(body, user);
}
@Put('permissions')
@ApiOkResponse({ type: GrantPermissionsToRoleRes })
@RequireAllPermissions(PERMISSIONS.USERS.permissions.ADMIN)
async grantPermissionsToRole(
@User() user: RequestUser,
@Body() body: GrantPermissionsToRoleReq,
@Headers('dadosfera-lang') language,
) {
this.logger.info('grantPermissionsToRole', { user });
this.rolesService.setLanguage(language);
return await this.rolesService.grantPermissionsToRole(body, user);
}
@Delete('permissions')
@ApiOkResponse({ type: RevokePermissionsFromRoleRes })
@RequireAllPermissions(PERMISSIONS.USERS.permissions.ADMIN)
async revokePermissionsFromRole(
@User() user: RequestUser,
@Body() body: RevokePermissionsFromRoleReq,
@Headers('dadosfera-lang') language,
) {
this.logger.info('revokePermissionsToRole', { user });
this.rolesService.setLanguage(language);
return await this.rolesService.revokePermissionFromRole(body, user);
}
@Patch('permissions')
@ApiOkResponse({ type: SetRolePermissionsRes })
@RequireAllPermissions(PERMISSIONS.USERS.permissions.ADMIN)
async setRolePermissions(
@User() user: RequestUser,
@Body() body: SetRolePermissionsReq,
@Headers('dadosfera-lang') language,
) {
this.logger.info('setRolePermissions', { user });
this.rolesService.setLanguage(language);
return this.rolesService.setRolePermissions(body, user);
}
@Patch('users')
@ApiOkResponse({ type: SetRoleUsersRes })
@RequireAllPermissions(PERMISSIONS.USERS.permissions.ADMIN)
async setRoleUsers(
@User() user: RequestUser,
@Body() body: SetRoleUsersReq,
@Headers('dadosfera-lang') language,
) {
this.logger.info('setRoleUsers', { user });
this.rolesService.setLanguage(language);
return this.rolesService.setRoleUsers(body, user);
}
@Get(':id')
@ApiOkResponse({ type: RoleDto })
@RequireAllPermissions(PERMISSIONS.USERS.permissions.ADMIN)
async getRoleById(
@User() user: RequestUser,
@Param('id') id: string,
@Headers('dadosfera-lang') language,
) {
this.logger.info('getRoleById', { user });
this.rolesService.setLanguage(language);
return await this.rolesService.getRolesById(id, user);
}
@Delete(':id')
@RequireAllPermissions(PERMISSIONS.USERS.permissions.ADMIN)
async deleteRole(
@User() user: RequestUser,
@Param('id') id: string,
@Headers('dadosfera-lang') language,
) {
this.logger.info('deleteRole', { user });
this.rolesService.setLanguage(language);
return await this.rolesService.removeRole(id, user);
}
@Patch(':id')
@ApiOkResponse({ type: UpdateRoleRes })
@RequireAllPermissions(PERMISSIONS.USERS.permissions.ADMIN)
async updateRole(
@User() user: RequestUser,
@Param('id') id: string,
@Body() body: UpdateRoleReq,
@Headers('dadosfera-lang') language,
) {
this.logger.info('updateRole', { user });
this.rolesService.setLanguage(language);
return this.rolesService.updateRole(id, body, user);
}
}
+25
View File
@@ -0,0 +1,25 @@
import { Module } from '@nestjs/common';
import { ClientsModule } from '@nestjs/microservices';
import { DucClient } from 'src/clients/duc/client.config';
import { RolesController } from './roles.controller';
import { RolesService } from './roles.service';
import { DadosferaLogger } from 'dadosfera-logs';
import { PermissionsModule } from '../permissions/permissions.module';
const ducClient = new DucClient();
@Module({
imports: [
ClientsModule.register([
{
name: 'DUC_PACKAGE',
...ducClient.config(),
},
]),
PermissionsModule,
],
controllers: [RolesController],
providers: [RolesService, DadosferaLogger],
exports: [RolesService],
})
export class RolesModule {}
+46
View File
@@ -0,0 +1,46 @@
import { ClientsModule } from '@nestjs/microservices';
import { Test, TestingModule } from '@nestjs/testing';
import { RolesController } from './roles.controller';
import { RolesService } from './roles.service';
import { DadosferaLogger } from 'dadosfera-logs';
import { DucClient } from 'src/clients/duc/client.config';
import { PermissionsModule } from '../permissions/permissions.module';
const ducClient = new DucClient();
const logger = {
info: (...args) => args,
error: (...args) => args,
};
describe('RolesService', () => {
let service: RolesService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [
ClientsModule.register([
{
name: 'DUC_PACKAGE',
...ducClient.config(),
},
]),
PermissionsModule,
],
controllers: [RolesController],
providers: [
RolesService,
{
provide: DadosferaLogger,
useValue: { logger },
},
],
exports: [RolesService],
}).compile();
service = module.get<RolesService>(RolesService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});
+260
View File
@@ -0,0 +1,260 @@
import { BadRequestException, Inject, Injectable } from '@nestjs/common';
import { ProtoServices } from '@dadosfera/protospack-v2/dist/lib/Duc';
import { RolesProtoService } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/write-service';
import {
CreateRoleReq,
GetRolesByCustomerReq,
GrantPermissionsToRoleReq,
RevokePermissionsFromRoleReq,
RoleDto,
SetRolePermissionsReq,
SetRoleUsersReq,
UpdateRoleReq,
} from './dto/entities';
import { DadosferaLogger } from 'dadosfera-logs';
import { Metadata } from '@grpc/grpc-js';
import { ClientGrpc } from '@nestjs/microservices';
import { Permission } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/entities';
import { lastValueFrom } from 'rxjs';
import { PermissionsService } from '../permissions/permissions.service';
import { LanguageEnum } from 'src/utils/languages.enum';
import { RequestUser } from 'src/authentication/user.decorator';
interface GetRolesPermissionsName {
id: string;
name: string;
description: string;
permissions: Permission[];
isPublic?: boolean;
createdAt: string;
updatedAt: string;
}
@Injectable()
export class RolesService {
logger: any;
private language: LanguageEnum = LanguageEnum.ptbr;
private rolesClientService: RolesProtoService;
constructor(
@Inject(DadosferaLogger)
dadosferaLogger: DadosferaLogger,
@Inject('DUC_PACKAGE') private readonly grpcClient: ClientGrpc,
private permissionsService: PermissionsService,
) {
this.logger = dadosferaLogger.logger;
}
setLanguage(lang: LanguageEnum = LanguageEnum.ptbr) {
if (Object.values(LanguageEnum).includes(lang)) this.language = lang;
this.language = lang;
}
onModuleInit() {
this.rolesClientService = this.grpcClient.getService<RolesProtoService>(
ProtoServices.RolesProtoService,
);
}
async getRolesById(id: string, { access_token }: RequestUser) {
const meta = new Metadata();
meta.add('access_token', access_token);
const role = await lastValueFrom(
this.rolesClientService.RoleFindOneById(
{
id,
},
meta,
),
);
const [roleTreated] = this.getRolesPermissionsName([role.role]);
return { role: roleTreated };
}
async roleSearch(
filters: GetRolesByCustomerReq,
{ customer_id, access_token }: RequestUser,
) {
const meta = new Metadata();
meta.add('access_token', access_token);
let { permissionId: permissionIds } = filters;
if (permissionIds && !Array.isArray(permissionIds))
permissionIds = [permissionIds];
const { getUsers } = filters;
const isGetUsers = getUsers === 'true';
const permissionSeqIds =
permissionIds?.map((id) => {
const seqId = Number(id);
if (isNaN(seqId))
throw new BadRequestException(`permissionId ${id} not valid`);
return seqId;
}) || [];
const roles = await lastValueFrom(
this.rolesClientService.RoleSearch(
{
customerId: customer_id,
getUsers: isGetUsers,
permissionIds: [],
permissionSeqIds,
},
meta,
),
);
const rolesTreated = this.getRolesPermissionsName(roles.roles);
return { roles: rolesTreated };
}
async createRole(
data: CreateRoleReq,
{ customer_id, access_token }: RequestUser,
) {
const meta = new Metadata();
meta.add('access_token', access_token);
const { description, name, permissionIds, userIds } = data;
const role = await lastValueFrom(
this.rolesClientService.RoleCreate(
{
customerId: customer_id,
name,
permissionIds: [],
permissionSeqIds: permissionIds,
description,
userIds,
},
meta,
),
);
const [roleTreated] = this.getRolesPermissionsName([role.role]);
return { role: roleTreated };
}
async removeRole(id: string, { access_token }: RequestUser) {
const meta = new Metadata();
meta.add('access_token', access_token);
return lastValueFrom(this.rolesClientService.RoleRemove({ id }, meta));
}
async grantPermissionsToRole(
{ roleId, permissionIds }: GrantPermissionsToRoleReq,
{ access_token }: RequestUser,
) {
const meta = new Metadata();
meta.add('access_token', access_token);
const role = await lastValueFrom(
this.rolesClientService.GrantPermissionsToRole(
{
permissionIds: [],
roleId,
permissionSeqIds: permissionIds,
},
meta,
),
);
const [roleTreated] = this.getRolesPermissionsName([role.role]);
return { role: roleTreated };
}
async revokePermissionFromRole(
{ roleId, permissionIds }: RevokePermissionsFromRoleReq,
{ access_token }: RequestUser,
) {
const meta = new Metadata();
meta.add('access_token', access_token);
const role = await lastValueFrom(
this.rolesClientService.RevokePermissionsFromRole(
{
permissionIds: [],
roleId,
permissionSeqIds: permissionIds,
},
meta,
),
);
const [roleTreated] = this.getRolesPermissionsName([role.role]);
return { role: roleTreated };
}
async updateRole(
id: string,
req: UpdateRoleReq,
{ access_token }: RequestUser,
) {
const meta = new Metadata();
meta.add('access_token', access_token);
const { description, name } = req;
const role = await lastValueFrom(
this.rolesClientService.RoleUpdate(
{
id,
description,
name,
},
meta,
),
);
const [roleTreated] = this.getRolesPermissionsName([role.role]);
return { role: roleTreated };
}
async setRolePermissions(
req: SetRolePermissionsReq,
{ access_token }: RequestUser,
) {
const meta = new Metadata();
meta.add('access_token', access_token);
const { roleId: id, permissionIds } = req;
const clearPermissions =
Array.isArray(permissionIds) && permissionIds.length === 0;
const role = await lastValueFrom(
this.rolesClientService.RoleSetPermissions(
{
id,
permissionSeqIds: permissionIds,
clearPermissions,
},
meta,
),
);
const [roleTreated] = this.getRolesPermissionsName([role.role]);
return { role: roleTreated };
}
async setRoleUsers(req: SetRoleUsersReq, { access_token }: RequestUser) {
const meta = new Metadata();
meta.add('access_token', access_token);
const { roleId: id, userIds } = req;
const clearUsers = Array.isArray(userIds) && userIds.length === 0;
const role = await lastValueFrom(
this.rolesClientService.RoleSetUsers(
{
id,
userIds,
clearUsers,
},
meta,
),
);
const [roleTreated] = this.getRolesPermissionsName([role.role]);
return { role: roleTreated };
}
getRolesPermissionsName(roles: GetRolesPermissionsName[]): RoleDto[] {
const newRoles: RoleDto[] = [];
for (const role of roles) {
const allPermissions = this.permissionsService.getAllPermissions(
this.language,
);
const newPermissions = role.permissions.map((p) => {
const permission = allPermissions.find((per) => per.seqid === p.seqid);
return {
...p,
name: permission.name,
id: p.seqid,
};
});
const newRole: RoleDto = {
...role,
permissions: newPermissions,
isPublic: role.isPublic,
};
newRoles.push(newRole);
}
return newRoles;
}
}
@@ -13,7 +13,7 @@ import { ApiTags } from '@nestjs/swagger';
import { TransformationsClientService } from 'src/clients/transformations/client.service';
import { IIdRequest } from 'src/clients/transformations/interfaces';
import { AuthenticateCondition } from 'src/authentication/authentication.decorator';
import { Permissions } from '../../authentication/permissions.enum';
import { PERMISSIONS } from '../../authentication/permissions.enum';
import { TransformationsService } from './transformations.service';
import { DadosferaLogger } from 'dadosfera-logs';
@@ -35,7 +35,9 @@ import { DadosferaLogger } from 'dadosfera-logs';
action = req.method;
}
return user.permissions.includes(Permissions.TRANSFORMATIONS[action].seqid);
return user.permissions.includes(
PERMISSIONS.TRANSFORMATIONS.permissions[action].seqid,
);
})
export class TransformationsController {
logger: any;
+171
View File
@@ -0,0 +1,171 @@
import { ApiProperty, ApiPropertyOptional, OmitType } from '@nestjs/swagger';
import { UserRole } from 'src/modules/roles/dto/entities';
export class Hierarchy {
@ApiProperty()
id: string;
@ApiProperty()
name: string;
}
export class Customer {
@ApiProperty()
id: string;
@ApiProperty()
name: string;
@ApiProperty()
domain: string;
@ApiProperty()
tier: string;
@ApiProperty()
info: string;
@ApiProperty()
createdAt: string;
@ApiProperty()
updatedAt: string;
}
export class User {
@ApiProperty()
id: string;
@ApiProperty()
name: string;
@ApiProperty()
email: string;
@ApiProperty({ type: [UserRole] })
roles: UserRole[];
@ApiProperty()
jobTitle?: string;
@ApiProperty()
department?: string;
@ApiProperty()
hierarchy?: string;
@ApiPropertyOptional()
customer?: Customer;
@ApiProperty()
mfaStatus: string;
@ApiProperty()
createdAt: string;
@ApiProperty()
updatedAt: string;
@ApiProperty()
status: string;
@ApiPropertyOptional()
lastLogin?: string;
}
export class UserNoRoles extends OmitType(User, ['roles']) {}
export class UserNoRolesAndCustomer extends OmitType(UserNoRoles, [
'customer',
]) {}
export class UserByCustomer extends OmitType(User, ['customer']) {}
export class CreateUserReq {
@ApiPropertyOptional()
name?: string;
@ApiProperty()
email: string;
@ApiPropertyOptional()
roleNames?: string[];
@ApiPropertyOptional()
jobTitle?: string;
@ApiPropertyOptional()
department?: string;
@ApiPropertyOptional()
hierarchy?: string;
}
export class CreateUserRes {
@ApiProperty()
user: User;
}
export class BatchCreateUserReq {
@ApiProperty({ type: [CreateUserReq] })
users: CreateUserReq[];
}
class ErrorUsers {
@ApiProperty()
user: CreateUserReq;
@ApiProperty()
error: string;
}
export class BatchCreateUserRes {
@ApiProperty({ type: [User] })
usersCreated: User[];
@ApiProperty({ type: [ErrorUsers] })
errorUsers: ErrorUsers[];
}
export class UpdateUserReq {
@ApiPropertyOptional()
name?: string;
@ApiPropertyOptional()
jobTitle?: string;
@ApiPropertyOptional()
department?: string;
@ApiPropertyOptional()
hierarchy?: string;
@ApiPropertyOptional()
roleNames?: string[];
}
export class UpdateUserRes {
@ApiProperty()
user: UserByCustomer;
}
export class GetAllUsersByCustomerIdRes {
@ApiProperty({ type: [UserByCustomer] })
users: UserByCustomer[];
@ApiProperty()
departments: string[];
@ApiProperty()
jobTitles: string[];
}
export class AssignRoleToUserReq {
@ApiProperty()
userId: string;
@ApiProperty()
roleId: string;
}
export class UnassignRoleToUserReq {
@ApiProperty()
userId: string;
@ApiProperty()
roleId: string;
}
export class DeleteUserRes {
@ApiProperty()
id: string;
}
export class SearchUserReq {
@ApiProperty()
s: string;
}
export class SetUserRolesReq {
@ApiProperty()
userId: string;
@ApiProperty()
roleNames: string[];
}
export class SetUserRolesRes {
@ApiProperty()
user: UserByCustomer;
}
export class SearchUserRes extends GetAllUsersByCustomerIdRes {}
export class GetAllHierarchiesRes {
@ApiProperty({ type: [Hierarchy] })
hierarchies: Hierarchy[];
}
export class GetAllJobTitlesRes {
@ApiProperty()
jobTitles: string[];
}
export class GetAllDepartmentsRes {
@ApiProperty()
departments: string[];
}
+79
View File
@@ -0,0 +1,79 @@
import { LanguageEnum } from 'src/utils/languages.enum';
interface InternalHierarchyType {
name: Record<LanguageEnum, string>;
}
export const HIERARCHIES: Record<string, InternalHierarchyType> = {
presidence: {
name: {
'pt-br': 'Presidência',
'en-us': 'Presidence',
},
},
directory: {
name: {
'pt-br': 'Diretoria',
'en-us': 'Directory',
},
},
management: {
name: {
'pt-br': 'Gerência',
'en-us': 'Management',
},
},
specialist: {
name: {
'pt-br': 'Especialista',
'en-us': 'Specialist',
},
},
supervisor: {
name: {
'pt-br': 'Coordenador ou Supervisor',
'en-us': 'Supervisor',
},
},
trainee: {
name: {
'pt-br': 'Trainee',
'en-us': 'Trainee',
},
},
'senior-analyst': {
name: {
'pt-br': 'Analista Sênior',
'en-us': 'Senior Analyst',
},
},
'midlevel-analyst': {
name: {
'pt-br': 'Analista Pleno',
'en-us': 'Mid-level Analyst',
},
},
'junior-analyst': {
name: {
'pt-br': 'Analista Júnior',
'en-us': 'Junior Analyst',
},
},
intern: {
name: {
'pt-br': 'Estagiário',
'en-us': 'Intern',
},
},
'youth-apprentice': {
name: {
'pt-br': 'Jovem aprendiz',
'en-us': 'Youth Apprentice',
},
},
other: {
name: {
'pt-br': 'Outro',
'en-us': 'Other',
},
},
};
@@ -0,0 +1,47 @@
import { ClientsModule } from '@nestjs/microservices';
import { Test, TestingModule } from '@nestjs/testing';
import { DucClient } from 'src/clients/duc/client.config';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
import { DadosferaLogger } from 'dadosfera-logs';
import { RolesModule } from '../roles/roles.module';
import { PermissionsModule } from '../permissions/permissions.module';
const ducClient = new DucClient();
const logger = {
info: (...args) => args,
error: (...args) => args,
};
describe('UsersController', () => {
let controller: UsersController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [
ClientsModule.register([
{
name: 'DUC_PACKAGE',
...ducClient.config(),
},
]),
RolesModule,
PermissionsModule,
],
controllers: [UsersController],
providers: [
UsersService,
{
provide: DadosferaLogger,
useValue: { logger },
},
],
}).compile();
controller = module.get<UsersController>(UsersController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});
+238
View File
@@ -0,0 +1,238 @@
import {
Body,
Controller,
Delete,
Get,
Headers,
HttpCode,
HttpStatus,
Inject,
Param,
Patch,
Post,
Put,
Req,
UseFilters,
} from '@nestjs/common';
import {
ApiCreatedResponse,
ApiHeader,
ApiOkResponse,
ApiTags,
} from '@nestjs/swagger';
import { DadosferaLogger } from 'dadosfera-logs';
import { RequireAllPermissions } from 'src/authentication/authentication.decorator';
import { PERMISSIONS } from 'src/authentication/permissions.enum';
import { RequestUser, User } from 'src/authentication/user.decorator';
import { GrpcToHttpExceptionFilter } from 'src/error/grpc-to-http-exception.filter';
import { LanguageEnum } from 'src/utils/languages.enum';
import {
AssignRoleToUserReq,
BatchCreateUserReq,
BatchCreateUserRes,
CreateUserReq,
CreateUserRes,
DeleteUserRes,
GetAllDepartmentsRes,
GetAllHierarchiesRes,
GetAllJobTitlesRes,
GetAllUsersByCustomerIdRes,
SetUserRolesReq,
SetUserRolesRes,
UnassignRoleToUserReq,
UpdateUserReq,
UpdateUserRes,
UserByCustomer,
} from './dtos/entities';
import { UsersService } from './users.service';
// TODO GET de hierarquias e do PATCH em usuário
@ApiTags('Users')
@Controller('users')
@ApiHeader({
name: 'dadosfera-lang',
enum: LanguageEnum,
required: false,
description: 'Defaults to pt-br',
})
@UseFilters(GrpcToHttpExceptionFilter)
export class UsersController {
logger: any;
constructor(
@Inject(DadosferaLogger)
dadosferaLogger: DadosferaLogger,
private userService: UsersService,
) {
this.logger = dadosferaLogger.logger;
}
@Get()
@RequireAllPermissions(PERMISSIONS.USERS.permissions.ADMIN)
@ApiOkResponse({
type: GetAllUsersByCustomerIdRes,
description: 'List of users of a customer',
})
async getAllUsersByCustomerId(
@User() user: RequestUser,
@Headers('dadosfera-lang') language,
): Promise<GetAllUsersByCustomerIdRes> {
this.logger.info('getAllUsersByCustomerId', { user });
this.userService.setLanguage(language);
return await this.userService.findAllUsersByCustomerId(user.customer_id);
}
@Get('hierarchies')
@RequireAllPermissions(PERMISSIONS.USERS.permissions.ADMIN)
@ApiOkResponse({ type: GetAllHierarchiesRes })
async getAllHierarchies(
@User() user: RequestUser,
@Headers('dadosfera-lang') language,
): Promise<GetAllHierarchiesRes> {
this.logger.info('getAllHierarchies', { user });
this.userService.setLanguage(language);
return await this.userService.getAllHierarchies();
}
@Get('departments')
@RequireAllPermissions(PERMISSIONS.USERS.permissions.ADMIN)
@ApiOkResponse({ type: GetAllDepartmentsRes })
async getAllDepartments(
@User() user: RequestUser,
@Headers('dadosfera-lang') language,
): Promise<GetAllDepartmentsRes> {
this.logger.info('getAllHierarchies', { user });
this.userService.setLanguage(language);
return await this.userService.getAllDepartments(user.customer_id);
}
@Get('jobTitles')
@RequireAllPermissions(PERMISSIONS.USERS.permissions.ADMIN)
@ApiOkResponse({ type: GetAllDepartmentsRes })
async getAllJobTitles(
@User() user: RequestUser,
@Headers('dadosfera-lang') language,
): Promise<GetAllJobTitlesRes> {
this.logger.info('getAllHierarchies', { user });
this.userService.setLanguage(language);
return await this.userService.getAllJobTitles(user.customer_id);
}
@Get(':id')
@RequireAllPermissions(PERMISSIONS.USERS.permissions.ADMIN)
@ApiOkResponse({
type: UserByCustomer,
})
async findOneById(
@User() user: RequestUser,
@Param('id') id: string,
@Headers('dadosfera-lang') language,
) {
this.logger.info('findOneById', { user });
this.userService.setLanguage(language);
return await this.userService.findOneById(id);
}
@Post()
@RequireAllPermissions(PERMISSIONS.USERS.permissions.ADMIN)
@ApiCreatedResponse({ type: CreateUserRes })
async createUser(
@User() user: RequestUser,
@Body() body: CreateUserReq,
@Headers('dadosfera-lang') language,
) {
this.logger.info('createUser', { user });
this.userService.setLanguage(language);
return await this.userService.createUser(body);
}
@Post('batch')
@RequireAllPermissions(PERMISSIONS.USERS.permissions.ADMIN)
@ApiCreatedResponse({ type: BatchCreateUserRes })
async batchCreateUser(
@User() user: RequestUser,
@Body() body: BatchCreateUserReq,
@Headers('dadosfera-lang') language,
) {
this.logger.info('batchCreateUser', { user });
this.userService.setLanguage(language);
return await this.userService.batchCreateUser(body);
}
@Post(':id/resend-invite')
@RequireAllPermissions(PERMISSIONS.USERS.permissions.ADMIN)
@HttpCode(HttpStatus.OK)
async resendInvite(
@User() user: RequestUser,
@Param('id') id: string,
@Headers('dadosfera-lang') language,
) {
this.logger.info('resendInvite', { user });
this.userService.setLanguage(language);
return this.userService.resendInvite({ id });
}
@Delete(':id')
@RequireAllPermissions(PERMISSIONS.USERS.permissions.ADMIN)
@ApiOkResponse({ type: DeleteUserRes })
async deleteUser(
@User() user: RequestUser,
@Param('id') id: string,
@Headers('dadosfera-lang') language,
) {
this.logger.info('deleteUser', { user });
this.userService.setLanguage(language);
return await this.userService.deleteUser({ id });
}
@Patch('roles')
@RequireAllPermissions(PERMISSIONS.USERS.permissions.ADMIN)
@ApiOkResponse({ type: SetUserRolesRes })
async setUserRoles(
@User() user: RequestUser,
@Body() body: SetUserRolesReq,
@Headers('dadosfera-lang') language,
) {
this.logger.info('createUser', { user });
this.userService.setLanguage(language);
return await this.userService.setRoles(body, user.customer_id);
}
@Put('role')
@RequireAllPermissions(PERMISSIONS.USERS.permissions.ADMIN)
async assignRoleToUser(
@User() user: RequestUser,
@Body() body: AssignRoleToUserReq,
@Headers('dadosfera-lang') language,
) {
this.logger.info('assignRoleToUser', { user });
this.userService.setLanguage(language);
return await this.userService.assignRoleToUser(body);
}
@Delete('role')
@RequireAllPermissions(PERMISSIONS.USERS.permissions.ADMIN)
async unassignRoleToUser(
@User() user: RequestUser,
@Req() request: UnassignRoleToUserReq,
@Headers('dadosfera-lang') language,
) {
this.logger.info('unassignRoleToUser', { user });
this.userService.setLanguage(language);
return await this.userService.unassignRoleToUser(request);
}
@Patch(':id')
@RequireAllPermissions(PERMISSIONS.USERS.permissions.ADMIN)
@ApiOkResponse({ type: UpdateUserRes })
async updateUser(
@User() user: RequestUser,
@Body() body: UpdateUserReq,
@Param('id') id: string,
@Headers('dadosfera-lang') language,
) {
this.logger.info('updateUser', { user });
this.userService.setLanguage(language);
return await this.userService.updateUser(body, id, user.customer_id);
}
}
+26
View File
@@ -0,0 +1,26 @@
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
import { DadosferaLogger } from 'dadosfera-logs';
import { ClientsModule } from '@nestjs/microservices';
import { DucClient } from 'src/clients/duc/client.config';
import { RolesModule } from '../roles/roles.module';
import { PermissionsModule } from '../permissions/permissions.module';
const ducClient = new DucClient();
@Module({
imports: [
ClientsModule.register([
{
name: 'DUC_PACKAGE',
...ducClient.config(),
},
]),
RolesModule,
PermissionsModule,
],
controllers: [UsersController],
providers: [UsersService, DadosferaLogger],
})
export class UsersModule {}
+47
View File
@@ -0,0 +1,47 @@
import { ClientsModule } from '@nestjs/microservices';
import { Test, TestingModule } from '@nestjs/testing';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
import { DadosferaLogger } from 'dadosfera-logs';
import { DucClient } from 'src/clients/duc/client.config';
import { RolesModule } from '../roles/roles.module';
import { PermissionsModule } from '../permissions/permissions.module';
const ducClient = new DucClient();
const logger = {
info: (...args) => args,
error: (...args) => args,
};
describe('UsersService', () => {
let service: UsersService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [
ClientsModule.register([
{
name: 'DUC_PACKAGE',
...ducClient.config(),
},
]),
RolesModule,
PermissionsModule,
],
controllers: [UsersController],
providers: [
UsersService,
{
provide: DadosferaLogger,
useValue: { logger },
},
],
}).compile();
service = module.get<UsersService>(UsersService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});
+202
View File
@@ -0,0 +1,202 @@
import { OnModuleInit, Inject, Injectable } from '@nestjs/common';
import { ClientGrpc } from '@nestjs/microservices';
import { DadosferaLogger } from 'dadosfera-logs';
import { ProtoServices } from '@dadosfera/protospack-v2/dist/lib/Duc';
import { UsersProtoService } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/write-service';
import {
AssignRoleToUserRequest,
IdRequest,
UnassignRoleFromUserRequest,
UserCreateRequest,
} from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/messages';
import { lastValueFrom } from 'rxjs';
import {
BatchCreateUserReq,
CreateUserReq,
Hierarchy,
SetUserRolesReq,
UpdateUserReq,
} from './dtos/entities';
import { RolesService } from '../roles/roles.service';
import { HIERARCHIES } from './hierarchies';
import { LanguageEnum } from 'src/utils/languages.enum';
import { UserByCustomer } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/entities';
import { EnrichErrorCode } from 'src/utils/ErrorBuilder';
@Injectable()
export class UsersService implements OnModuleInit {
logger: any;
language: LanguageEnum = LanguageEnum.ptbr;
private usersClientService: UsersProtoService;
constructor(
@Inject(DadosferaLogger)
dadosferaLogger: DadosferaLogger,
@Inject('DUC_PACKAGE') private readonly grpcClient: ClientGrpc,
private rolesService: RolesService,
) {
this.logger = dadosferaLogger.logger;
}
onModuleInit() {
this.usersClientService = this.grpcClient.getService<UsersProtoService>(
ProtoServices.UsersProtoService,
);
}
setLanguage(l: LanguageEnum = LanguageEnum.ptbr) {
if (Object.values(LanguageEnum).includes(l)) this.language = l;
this.rolesService.setLanguage(l);
}
async findAllUsersByCustomerId(customerId: string) {
const { users } = await lastValueFrom(
this.usersClientService.UserFindAllByCustomerId({ customerId }),
);
const usersAdj = this.adjustUsersPayload(users);
const dintinctDepartments = [...new Set(usersAdj.map((u) => u.department))]
.filter((value) => value != null)
.sort();
const dintinctJobTitles = [...new Set(usersAdj.map((u) => u.jobTitle))]
.filter((value) => value != null)
.sort();
return {
users: usersAdj,
jobTitles: dintinctJobTitles,
departments: dintinctDepartments,
};
}
async findOneById(id: string) {
const { user } = await lastValueFrom(
this.usersClientService.UserFindOneById({ id }),
);
return { user: this.adjustUsersPayload([user])[0] };
}
async createUser(req: CreateUserReq) {
const { email, department, hierarchy, jobTitle, name, roleNames } = req;
const { user } = await lastValueFrom(
this.usersClientService.UserCreate({
email,
hierarchy,
name,
roleIds: [],
department,
jobTitle,
roleNames,
}),
);
return { user: this.adjustUsersPayload([user])[0] };
}
async updateUser(req: UpdateUserReq, id: string, customerId: string) {
const { department, hierarchy, jobTitle, name, roleNames } = req;
if (roleNames) {
await this.setRoles({ roleNames, userId: id }, customerId);
}
const { user } = await lastValueFrom(
this.usersClientService.UserUpdate({
name,
customerId,
id,
department,
hierarchy,
jobTitle,
}),
);
return { user: this.adjustUsersPayload([user])[0] };
}
async setRoles(body: SetUserRolesReq, customerId: string) {
const { roleNames, userId } = body;
const clearRoles = roleNames && roleNames.length === 0;
const { user } = await lastValueFrom(
this.usersClientService.UserSetRoles({
userId,
roleIds: [],
roleNames,
clearRoles,
customerId,
}),
);
return { user: this.adjustUsersPayload([user])[0] };
}
async batchCreateUser({ users }: BatchCreateUserReq) {
const usersToCreate: UserCreateRequest[] = users.map(
({ roleNames, email, department, hierarchy, jobTitle, name }) => ({
roleNames,
email,
department,
hierarchy,
jobTitle,
name,
roleIds: [],
}),
);
const { errorUsers, usersCreated } = await lastValueFrom(
this.usersClientService.UserBatchCreate({
users: usersToCreate,
}),
);
return {
usersCreated: this.adjustUsersPayload(usersCreated),
// mapping error code to message
errorUsers: errorUsers.map(({ user, error }) => ({
user,
error: EnrichErrorCode(error).message,
})),
};
}
async resendInvite(body: IdRequest) {
return lastValueFrom(this.usersClientService.UserResendInvite(body));
}
async assignRoleToUser(body: AssignRoleToUserRequest) {
return lastValueFrom(this.usersClientService.AssignRoleToUser(body));
}
async unassignRoleToUser(body: UnassignRoleFromUserRequest) {
return lastValueFrom(this.usersClientService.UnassignRoleFromUser(body));
}
async deleteUser(id: IdRequest) {
return lastValueFrom(this.usersClientService.UserRemove(id));
}
getAllHierarchies(): { hierarchies: Hierarchy[] } {
const hierarchies = Object.keys(HIERARCHIES).map((key) => ({
id: key,
name: HIERARCHIES[key]?.name[this.language] || key,
}));
return { hierarchies };
}
async getAllDepartments(customerId?: string) {
return lastValueFrom(
this.usersClientService.FindDistinctDepartments({ customerId }),
);
}
async getAllJobTitles(customerId?: string) {
return lastValueFrom(
this.usersClientService.FindDistinctJobTitles({ customerId }),
);
}
private adjustUsersPayload(users: UserByCustomer[]) {
return users.map((u) => {
if (!u) return undefined;
return {
...u,
roles: this.rolesService.getRolesPermissionsName(u.roles),
hierarchy: HIERARCHIES[u.hierarchy]?.name[this.language] || u.hierarchy,
};
});
}
}