FEAT: ROle management

This commit is contained in:
Gabriel Rosa
2022-07-15 11:08:57 -03:00
parent de57bfed1e
commit 1b620b6fb0
11 changed files with 179 additions and 48 deletions
+2 -2
View File
@@ -9017,7 +9017,7 @@
"node_modules/protospack-v2": {
"version": "0.0.0",
"resolved": "file:../protospack-v2/protospack-v2-0.0.0.tgz",
"integrity": "sha512-kj/mJbme5CULhsRW4fyXdRUtJKzG5Q5zVYg4BSYMRovHi/jcZUgOIXWwOn0rnqLlMlzdl2msx0S9mA7b62IQzQ==",
"integrity": "sha512-ABgU0d8MFh0VhWkGFa3nnSLzmm8Her2rof9Ajoi46FMjwp3N0895F6e7IecM13CUJgcOtkFqbmQF7JU33hB+BA==",
"license": "ISC",
"dependencies": {
"@grpc/grpc-js": "^1.6.7",
@@ -17247,7 +17247,7 @@
},
"protospack-v2": {
"version": "file:../protospack-v2/protospack-v2-0.0.0.tgz",
"integrity": "sha512-kj/mJbme5CULhsRW4fyXdRUtJKzG5Q5zVYg4BSYMRovHi/jcZUgOIXWwOn0rnqLlMlzdl2msx0S9mA7b62IQzQ==",
"integrity": "sha512-ABgU0d8MFh0VhWkGFa3nnSLzmm8Her2rof9Ajoi46FMjwp3N0895F6e7IecM13CUJgcOtkFqbmQF7JU33hB+BA==",
"requires": {
"@grpc/grpc-js": "^1.6.7",
"rxjs": "^7.5.5",
+1 -1
View File
@@ -107,7 +107,7 @@ export class AuthenticationGuard
} catch (err) {
// log errors if authentication is required
if (mustBeAuthenticated) {
this.logger.error('Unable to verify duc access token\n' + err.stack);
this.logger.error('Unable to verify duc access token\n' + err?.stack);
}
return false;
+6 -4
View File
@@ -3,6 +3,11 @@ import assert from 'assert';
const logger = new Logger();
export enum LanguageEnum {
ptbr = 'pt-br',
enus = 'en-us',
}
export enum PermissionUsages {
PUBLIC = 'public',
INTERNAL = 'internal',
@@ -12,10 +17,7 @@ export interface PermissionsObjectPermission {
seqid: number;
claim: string;
usage: PermissionUsages;
name?: {
'pt-br': string;
'en-us': string;
};
name?: Record<LanguageEnum, string>;
}
export interface PermissionsObjectPermissionTranslated {
seqid: number;
-9
View File
@@ -33,12 +33,3 @@ export class GetPublicPermissionsRes {
@ApiProperty({ type: [PermissionGroup] })
permissionGroups: PermissionGroup[];
}
export enum LanguageEnum {
ptbr = 'pt-br',
enus = 'en-us',
}
export class GetPublicPermissionsHeader {
@ApiPropertyOptional({ enum: LanguageEnum })
'dadosfera-lang';
}
@@ -1,13 +1,12 @@
import { Controller, Get, Headers, Inject } from '@nestjs/common';
import { ApiOkResponse, ApiTags } from '@nestjs/swagger';
import { DadosferaLogger } from 'dadosfera-logs';
import { PermissionUsages } from 'src/authentication/permissions.enum';
import { RequestUser, User } from 'src/authentication/user.decorator';
import {
GetPublicPermissionsHeader,
GetPublicPermissionsRes,
LanguageEnum,
} from './dto/entities';
PermissionUsages,
} from 'src/authentication/permissions.enum';
import { RequestUser, User } from 'src/authentication/user.decorator';
import { GetPublicPermissionsRes } from './dto/entities';
import { PermissionsService } from './permissions.service';
@ApiTags('Permissions')
@@ -27,11 +26,9 @@ export class PermissionsController {
@ApiOkResponse({ type: GetPublicPermissionsRes })
getPublicPermissions(
@User() user: RequestUser,
@Headers() headers: GetPublicPermissionsHeader,
@Headers('dadosfera-lang') language: LanguageEnum,
) {
this.logger.info('getPublicPermissions', { user });
const language: LanguageEnum = headers['dadosfera-lang'];
return this.permissionsService.getPermissionsGrouped(
PermissionUsages.PUBLIC,
language,
@@ -16,9 +16,10 @@ import {
PermissionUsages,
PermissionsObjectGroup,
PermissionsObjectPermissionTranslated,
LanguageEnum,
} from '../../authentication/permissions.enum';
import ErrorBuilder from '../../utils/ErrorBuilder';
import { LanguageEnum, PermissionDto, PermissionGroup } from './dto/entities';
import { PermissionDto, PermissionGroup } from './dto/entities';
@Injectable()
export class PermissionsService
@@ -97,7 +98,7 @@ export class PermissionsService
return groups;
}
getAllPermissions(language: LanguageEnum = LanguageEnum.ptbr) {
const permissions: PermissionsObjectPermissionTranslated[] = [];
let permissions: PermissionsObjectPermissionTranslated[] = [];
for (const key in PERMISSIONS) {
const permissionGroup: PermissionsObjectGroup = PERMISSIONS[key];
const permissionGroupPermissions: PermissionsObjectPermissionTranslated[] =
@@ -105,7 +106,7 @@ export class PermissionsService
...p,
name: p.name[language],
}));
permissions.concat(permissionGroupPermissions);
permissions = permissions.concat(permissionGroupPermissions);
}
return permissions;
}
+22 -4
View File
@@ -82,13 +82,31 @@ export class UpdateRoleReq {
name: string;
@ApiPropertyOptional()
description: string;
@ApiPropertyOptional()
userIds: string[];
@ApiPropertyOptional()
permissionIds: number[];
}
export class UpdateRoleRes {
@ApiProperty()
role: Role;
}
export class SetRolePermissionsReq {
@ApiProperty()
roleId: string;
@ApiProperty()
permissionIds: number[];
}
export class SetRolePermissionsRes {
@ApiProperty()
role: Role;
}
export class SetRoleUsersReq {
@ApiProperty()
roleId: string;
@ApiProperty()
userIds: string[];
}
export class SetRoleUsersRes {
@ApiProperty()
role: Role;
}
+81 -8
View File
@@ -3,6 +3,7 @@ import {
Controller,
Delete,
Get,
Headers,
Inject,
Param,
Patch,
@@ -11,7 +12,12 @@ import {
Query,
UseFilters,
} from '@nestjs/common';
import { ApiCreatedResponse, ApiOkResponse, ApiTags } from '@nestjs/swagger';
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';
@@ -26,11 +32,25 @@ import {
RevokePermissionsFromRoleRes,
UpdateRoleReq,
UpdateRoleRes,
Role,
SetRolePermissionsReq,
SetRolePermissionsRes,
SetRoleUsersRes,
SetRoleUsersReq,
} from './dto/entities';
import { GrpcToHttpExceptionFilter } from 'src/error/grpc-to-http-exception.filter';
import { LanguageEnum } from 'src/authentication/permissions.enum';
import { Authenticated } from 'src/authentication/authentication.decorator';
@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;
@@ -48,8 +68,10 @@ export class RolesController {
async getRolesByCustomer(
@User() user: RequestUser,
@Query() filters: GetRolesByCustomerReq,
@Headers('dadosfera-lang') language,
) {
this.logger.info('getRolesByCustomer', { user });
this.rolesService.setLanguage(language);
return await this.rolesService.getRolesByCustomer(
filters,
user.customer_id,
@@ -58,24 +80,25 @@ export class RolesController {
@Post()
@ApiCreatedResponse({ type: CreateRoleRes })
async createRole(@User() user: RequestUser, @Body() body: CreateRoleReq) {
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.customer_id);
}
@Delete(':id')
async deleteRole(@User() user: RequestUser, @Param('id') id: string) {
this.logger.info('deleteRole', { user });
return await this.rolesService.removeRole(id);
}
@Put('permissions')
@ApiOkResponse({ type: GrantPermissionsToRoleRes })
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);
}
@@ -84,19 +107,69 @@ export class RolesController {
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);
}
@Patch('permissions')
@ApiOkResponse({ type: SetRolePermissionsRes })
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);
}
@Patch('users')
@ApiOkResponse({ type: SetRoleUsersRes })
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);
}
@Get(':id')
@ApiOkResponse({ type: Role })
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);
}
@Delete(':id')
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);
}
@Patch(':id')
@ApiOkResponse({ type: UpdateRoleRes })
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);
}
}
+48 -7
View File
@@ -7,17 +7,20 @@ import {
GrantPermissionsToRoleReq,
RevokePermissionsFromRoleReq,
Role,
SetRolePermissionsReq,
SetRoleUsersReq,
UpdateRoleReq,
} from './dto/entities';
import { DadosferaLogger } from 'dadosfera-logs';
import { ClientGrpc } from '@nestjs/microservices';
import { lastValueFrom } from 'rxjs';
import { PermissionsService } from '../permissions/permissions.service';
import { LanguageEnum } from 'src/authentication/permissions.enum';
@Injectable()
export class RolesService {
logger: any;
private language: LanguageEnum = LanguageEnum.ptbr;
private rolesClientService: RolesProtoService;
constructor(
@Inject(DadosferaLogger)
@@ -27,12 +30,24 @@ export class RolesService {
) {
this.logger = dadosferaLogger.logger;
}
setLanguage(lang: LanguageEnum = LanguageEnum.ptbr) {
this.language = lang;
}
onModuleInit() {
this.rolesClientService = this.grpcClient.getService<RolesProtoService>(
ProtoServices.RolesProtoService,
);
}
async getRolesById(id: string) {
const role = await lastValueFrom(
this.rolesClientService.RoleFindOneById({
id,
}),
);
const [roleTreated] = this.getRolesPermissionsName([role.role]);
return { role: roleTreated };
}
async getRolesByCustomer(filters: GetRolesByCustomerReq, customerId: string) {
let { permissionIds } = filters;
if (permissionIds && !Array.isArray(permissionIds))
@@ -109,15 +124,41 @@ export class RolesService {
}
async updateRole(id: string, req: UpdateRoleReq) {
const { description, name, permissionIds, userIds } = req;
const { description, name } = req;
const role = await lastValueFrom(
this.rolesClientService.RoleUpdate({
id,
description,
name,
permissionIds: [],
permissionReqIds: permissionIds,
}),
);
const [roleTreated] = this.getRolesPermissionsName([role.role]);
return { role: roleTreated };
}
async setRolePermissions(req: SetRolePermissionsReq) {
const { roleId: id, permissionIds } = req;
const clearPermissions =
Array.isArray(permissionIds) && permissionIds.length === 0;
const role = await lastValueFrom(
this.rolesClientService.RoleSetPermissions({
id,
permissionSeqIds: permissionIds,
clearPermissions,
}),
);
const [roleTreated] = this.getRolesPermissionsName([role.role]);
return { role: roleTreated };
}
async setRoleUsers(req: SetRoleUsersReq) {
const { roleId: id, userIds } = req;
const clearUsers = Array.isArray(userIds) && userIds.length === 0;
const role = await lastValueFrom(
this.rolesClientService.RoleSetUsers({
id,
userIds,
clearUsers,
}),
);
const [roleTreated] = this.getRolesPermissionsName([role.role]);
@@ -125,9 +166,9 @@ export class RolesService {
}
getRolesPermissionsName(roles: Role[]) {
for (const role of roles) {
const permisisonSeqIds = role.permissions.map((p) => p.seqid);
const permissions =
this.permissionsService.getPermissionsBySeqId(permisisonSeqIds);
const permissions = this.permissionsService.getAllPermissions(
this.language,
);
role.permissions.forEach((p) => {
const permission = permissions.find((per) => per.seqid === p.seqid);
p.name = permission.name;
+9 -2
View File
@@ -119,6 +119,13 @@ export function EnrichErrorCode(code: string) {
message: 'Não é possível criar um grupo com esse nome',
code,
};
case ErrorCodes.ROLE.NOT_FOUND:
return {
statusCode: HttpStatus.NOT_FOUND,
error: 'Grupo não encontrado',
message: 'Grupo solicitado não encontrado',
code,
};
case ErrorCodes.INTERNAL:
case ErrorCodes.UNKNOWN:
default:
@@ -138,9 +145,9 @@ const logger = new Logger();
export default class ErrorBuilder extends HttpException {
code: string;
constructor(code: string | RpcException) {
constructor(code: string | RpcException = '') {
if (typeof code !== 'string') {
logger.log(code.stack);
logger.log(code?.stack);
code = (code as any).details as string;
} else {
logger.log(code);
+1
View File
@@ -15,6 +15,7 @@ export const AUTH = {
};
export const ROLE = {
ALREADY_EXIST: 'ROLE.ALREADY_EXISTS',
NOT_FOUND: 'ROLE.NOT_FOUND',
};
const ErrorCodes = {
UNKNOWN: 'UNKNOWN',