Compare commits

...
68 Commits
Author SHA1 Message Date
Gabriel Amorim 246de83142 Merge pull request #159 from dadosfera/ref/catalog
Catalog Refactor
2022-10-26 17:40:42 -03:00
Gabriel Rosa 4a08e5f560 Merge branch 'main' into ref/catalog 2022-10-25 17:33:04 -03:00
Gabriel Rosa f2f09cc9c7 FIX: oauth redirect adjusted 2022-10-24 15:24:14 -03:00
Victor Radael d486231fd6 FEAT: RLS new barnch 2022-10-21 15:44:21 -03:00
Victor Radael 526a3bddcd Merge pull request #158 from dadosfera/ft/rls-old-catalog
FEAT: Rls first change
2022-10-21 15:18:01 -03:00
Victor Radael 45108d3019 FEAT: Rls first change 2022-10-21 14:49:28 -03:00
Victor Radael ac3e26b851 FIX: RLS 2022-10-21 14:36:59 -03:00
Gabriel Rosa 7fbc919716 FIX: catalog filters 2022-10-20 11:23:30 -03:00
Gabriel Rosa 5b1eb19511 FIX: catalog sort by 2022-10-20 10:27:38 -03:00
Victor Radael b714f3cf36 FIX: Filters 2022-10-20 10:04:45 -03:00
Victor Radael 48c1e29168 FIX: Filters 2022-10-20 09:45:12 -03:00
Victor Radael 04ea1d0f04 FIX: Get a total and fix owner type 2022-10-19 17:01:22 -03:00
Victor Radael 0de5e1d5d1 PATCH: Ref/Catalog new functions 2022-10-18 14:13:24 -03:00
Victor Radael b8c41fad1b PATCH: Ref/Catalog new functions 2022-10-18 13:43:18 -03:00
Victor Radael ef9ec5ad42 PATCH: Ref/Catalog new functions 2022-10-18 13:05:47 -03:00
Victor Radael 65e71f21a0 Merge branch 'ref/catalog' of github.com:dadosfera/maestro into ref/catalog 2022-10-18 13:05:27 -03:00
Victor Radael b921393ba1 PATCH: Ref/Catalog new functions 2022-10-18 13:05:05 -03:00
Gabriel Rosa 18aa7d8674 FIX: permission language fixed 2022-10-17 17:53:47 -03:00
Victor Radael f2dd871de2 FIX: Ref Catalogo new functions models 2022-10-17 16:16:31 -03:00
Victor Radael cf3fa88196 FIX: Ref Catalogo new functions models 2022-10-17 15:00:29 -03:00
Victor Radael 131810533c FIX: Ref Catalogo new functions models 2022-10-17 14:58:11 -03:00
Victor Radael ea06f3f571 FIX: Ref Catalogo new functions models 2022-10-17 14:51:28 -03:00
Victor Radael 81921a7eb2 FIX: Ref Catalogo new functions models 2022-10-17 14:38:31 -03:00
Victor Radael e9fdd0285b FIX: Ref Catalogo new functions models 2022-10-17 13:42:13 -03:00
Victor Radael 167470adba FIX: Ref Catalogo new functions models 2022-10-17 13:35:13 -03:00
Victor Radael fbb9a59214 FIX: Ref Catalogo new functions models 2022-10-17 13:32:41 -03:00
Gabriel Amorim ef6d8594a3 Merge pull request #157 from dadosfera/fix/get-user-permissions
FIX: new function to get all user permissions
2022-10-14 11:57:05 -03:00
Gabriel Rosa ac73c0b046 FIX: new function to get all user permissions 2022-10-14 11:33:15 -03:00
Gabriel Amorim 5a30bf08b2 Merge pull request #156 from dadosfera/fix/pipeline-properties
Fix/pipeline properties
2022-10-13 16:39:41 -03:00
Gabriel Rosa 62b4eb709e Return properties object on findOneProperties 2022-10-13 16:24:32 -03:00
Gabriel Rosa b37a18d1da Merge branch 'main' into fix/pipeline-properties 2022-10-13 15:59:53 -03:00
Gabriel Rosa 379bac704f FIX: getPipelineproperties 2022-10-13 14:59:27 -03:00
Gabriel Rosa 9178530a21 FEAT: get pipeline properties 2022-10-13 14:58:41 -03:00
Gabriel Amorim 667d3f874d Merge pull request #155 from dadosfera/fix/user-permissions
FIX: permissions array on user findOneById
2022-10-13 14:03:02 -03:00
Victor Radael 475af224bf Merge remote-tracking branch 'origin' into ref/catalog 2022-10-13 11:43:16 -03:00
Gabriel Rosa 11f1df5537 FIX: permissions array on user findOneById 2022-10-13 09:23:56 -03:00
Victor Radael e3b02571c8 Merge pull request #154 from dadosfera/fix/oauth
FIX: Public oauth route
2022-10-13 09:05:29 -03:00
Gabriel Rosa 979a12aa7f Merge branch 'main' into fix/oauth 2022-10-13 09:02:17 -03:00
Gabriel Rosa 7646d7a3c5 WIP 2022-10-13 08:57:21 -03:00
Victor Radael 8f0e851a88 FIX: Public oauth route 2022-10-12 23:12:33 -03:00
Victor Radael 779418f471 clear catalog 2022-10-11 22:23:36 -03:00
Gabriel Amorim 6e6d03f302 Merge pull request #153 from dadosfera/fix/user-roles
Fix/user roles
2022-10-11 16:40:12 -03:00
Victor Radael 85f41521ed Merge remote-tracking branch 'origin' into ref/catalog 2022-10-11 15:36:08 -03:00
Victor Radael e2bb119745 refactor/catalog 2022-10-11 15:35:29 -03:00
Gabriel Rosa 3d5ce59b52 FIX: user can get own info, even with no users:admin permission 2022-10-11 11:54:39 -03:00
Gabriel Rosa 1c63271f64 FIX: send language to request that need terms of use 2022-10-11 10:26:13 -03:00
Gabriel Rosa 31a51c20aa FIX: pass metadata to signIn request 2022-10-11 08:41:59 -03:00
Gabriel Rosa 62730eb969 FIX: terms of use dynamic language 2022-10-10 19:56:57 -03:00
Victor Radael 5a2c760bab Merge pull request #152 from dadosfera/fix/dashboards
FIX: Dashboard get all permisisons
2022-10-08 18:00:24 -03:00
Victor Radael 28b4f3ac4b FIX: Dashboard get all permisisons 2022-10-08 17:56:19 -03:00
Gabriel Amorim 43d181a429 Merge pull request #151 from dadosfera/fix/old-pipelines
FIX: Stop using old pipelines
2022-10-07 15:41:13 -03:00
Gabriel Rosa a72fe1b60d FIX: Stop using old pipelines 2022-10-07 15:37:36 -03:00
Gabriel Amorim b52a1227b1 Merge pull request #150 from dadosfera/fix/bulk-connectors-upload
fix/bulk-connectors-upload
2022-10-06 10:11:34 -03:00
Gabriel Rosa 31478ed61d FIX: new protospack version 2022-10-06 09:41:00 -03:00
Gabriel Rosa 79b1ba910e FIX: removed unused import 2022-10-06 09:17:27 -03:00
Gabriel Rosa 7fd929915b FIX: new bulk upload request 2022-10-06 09:15:42 -03:00
Victor Radael e4b27c5f76 Merge pull request #149 from dadosfera/ft/+200meltano
Ft/+200meltano
2022-10-05 17:22:40 -03:00
Victor Radael 92e449d6d3 FIX: Permissions and paths 2022-10-05 17:13:06 -03:00
Victor Radael 5073b2e188 FIX: Permissions and paths 2022-10-05 16:58:02 -03:00
Victor Radael 8a11eda24d FIX: +200 Meltano - Productboard API 2022-10-05 16:44:07 -03:00
Victor Radael 9d732d4a48 FIX: +200 Meltano - Productboard API 2022-10-05 16:42:41 -03:00
Gabriel Amorim 5fa10a939b Merge pull request #148 from dadosfera/fix/data-asset-sharing-permission
FIX: no permission needed for sharing data assets
2022-10-05 14:49:47 -03:00
Gabriel Rosa 4be3ffe3a2 FIX: no permission needed for sharing data assets 2022-10-05 14:45:06 -03:00
Victor Radael 8af9c638ef Merge pull request #147 from dadosfera/feat/openSearchCatalog
FIX: Individual data assets permissions
2022-10-05 08:45:58 -03:00
Victor Radael 97d6f914cc FIX: Individual data assets permissions 2022-10-05 08:43:20 -03:00
Victor Radael 9ad2e3770e FIX: Individual data assets permissions 2022-10-05 08:41:48 -03:00
Victor Radael ea2cc8809f FIX: Individual data assets permissions 2022-10-05 08:40:57 -03:00
Victor Radael 410e190e7c FIX: Individual data assets permissions 2022-10-05 08:39:40 -03:00
30 changed files with 1137 additions and 910 deletions
+7 -7
View File
@@ -12,7 +12,7 @@
"dependencies": {
"@aws-sdk/client-secrets-manager": "^3.112.0",
"@dadosfera/dadosfera-logs": "^1.0.0-beta.4",
"@dadosfera/protospack-v2": "3.18.8",
"@dadosfera/protospack-v2": "3.18.18",
"@grpc/grpc-js": "^1.6.7",
"@grpc/proto-loader": "^0.6.13",
"@nestjs/common": "^8.4.7",
@@ -1726,9 +1726,9 @@
}
},
"node_modules/@dadosfera/protospack-v2": {
"version": "3.18.8",
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.18.8.tgz",
"integrity": "sha512-pzvuIzCrIf/ZG//lwMdCxtZ7w/ZhiLFBA3VWyN9uM7AjeqVl7LllHKV08Fw6YjNNGBmQF3DLJQTK8kMCQja4hA==",
"version": "3.18.18",
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.18.18.tgz",
"integrity": "sha512-4KiuMUDMZu8ouic0RBBuM7Ky9wfczeS4GKLRyD29GV371m/NOo+1ujrcLysc8OuevPdXmaqzCgE6WWi6SIt9sQ==",
"dependencies": {
"@grpc/grpc-js": "^1.6.7",
"rxjs": "^7.5.5",
@@ -12306,9 +12306,9 @@
}
},
"@dadosfera/protospack-v2": {
"version": "3.18.8",
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.18.8.tgz",
"integrity": "sha512-pzvuIzCrIf/ZG//lwMdCxtZ7w/ZhiLFBA3VWyN9uM7AjeqVl7LllHKV08Fw6YjNNGBmQF3DLJQTK8kMCQja4hA==",
"version": "3.18.18",
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.18.18.tgz",
"integrity": "sha512-4KiuMUDMZu8ouic0RBBuM7Ky9wfczeS4GKLRyD29GV371m/NOo+1ujrcLysc8OuevPdXmaqzCgE6WWi6SIt9sQ==",
"requires": {
"@grpc/grpc-js": "^1.6.7",
"rxjs": "^7.5.5",
+2 -1
View File
@@ -10,6 +10,7 @@
},
"scripts": {
"preinstall": "aws codeartifact login --tool npm --namespace @dadosfera --repository dadosfera-npm --domain dadosfera --domain-owner 611330257153 --region us-east-1",
"proto-update": "npm i @dadosfera/protospack-v2@latest --save-exact",
"prebuild": "rimraf dist",
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
@@ -27,7 +28,7 @@
"dependencies": {
"@aws-sdk/client-secrets-manager": "^3.112.0",
"@dadosfera/dadosfera-logs": "^1.0.0-beta.4",
"@dadosfera/protospack-v2": "3.18.8",
"@dadosfera/protospack-v2": "3.18.18",
"@grpc/grpc-js": "^1.6.7",
"@grpc/proto-loader": "^0.6.13",
"@nestjs/common": "^8.4.7",
+2
View File
@@ -23,6 +23,7 @@ import { HealthModule } from './modules/health/health.module';
import { CatalogModule } from './modules/catalog/catalog.module';
import { ConfigModule } from '@nestjs/config';
import { PipelinesV2Module } from './modules/pipelinesV2/pipelines.module';
import { ProductboardModule } from './modules/productboard/productboard.module';
@Module({
controllers: [],
@@ -54,6 +55,7 @@ import { PipelinesV2Module } from './modules/pipelinesV2/pipelines.module';
OauthModule,
PipelinesV2Module,
CatalogModule,
ProductboardModule,
],
})
export class AppModule {}
+1 -1
View File
@@ -132,7 +132,7 @@ export const PERMISSIONS_GROUPS = {
name: {
'pt-br': 'Excluir Fonte',
'en-us': 'Remove Source',
'es-s': 'Eliminar Source',
'es-es': 'Eliminar Source',
},
},
UPDATE: {
+12 -4
View File
@@ -27,6 +27,7 @@ import { AuthClientService } from './auth.service';
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
import { GrpcToHttpExceptionFilter } from '../../error/grpc-to-http-exception.filter';
import { RequestUser, User } from 'src/authentication/user.decorator';
import { Metadata } from '@grpc/grpc-js';
@ApiTags('Auth')
@UseFilters(new GrpcToHttpExceptionFilter())
@@ -59,20 +60,27 @@ export class AuthController {
@Post('sign-in')
@HttpCode(HttpStatus.OK)
async signIn(@Body() { username, password, totp }: AuthSignInRequest) {
async signIn(
@Body() { username, password, totp }: AuthSignInRequest,
@Headers('Dadosfera-Lang') language: string,
) {
this.logger.info('/auth - SignIn');
return this.authClient.signIn({ username, password, totp });
const metadata = new Metadata();
metadata.add('language', language || 'pt-br');
return this.authClient.signIn({ username, password, totp }, metadata);
}
@Post('refresh-access-token')
@HttpCode(HttpStatus.OK)
async refreshAccessToken(
@Body() { refreshToken }: AuthRefreshAccessTokenRequest,
@Headers('Dadosfera-Lang') language: string,
) {
this.logger.info('/auth - RefreshAccessToken');
const metadata = new Metadata();
metadata.add('language', language || 'pt-br');
return this.authClient.refreshAccessToken({ refreshToken });
return this.authClient.refreshAccessToken({ refreshToken }, metadata);
}
@Post('change-password')
+11 -4
View File
@@ -19,6 +19,7 @@ import {
AuthConfirmResetPasswordRequest,
} from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/messages';
import { DucClient } from '../duc/client.config';
import { Metadata } from '@grpc/grpc-js';
@Injectable()
export class AuthClientService implements OnModuleInit {
@@ -51,19 +52,25 @@ export class AuthClientService implements OnModuleInit {
return lastValueFrom(this.authService.AuthSnowflakeSignIn(input));
}
async signIn({ username, password, totp }: AuthSignInRequest) {
async signIn(
{ username, password, totp }: AuthSignInRequest,
metadata: Metadata,
) {
this.logger.info('SignIn');
return lastValueFrom(
this.authService.AuthSignIn({ username, password, totp }),
this.authService.AuthSignIn({ username, password, totp }, metadata),
);
}
async refreshAccessToken({ refreshToken }: AuthRefreshAccessTokenRequest) {
async refreshAccessToken(
{ refreshToken }: AuthRefreshAccessTokenRequest,
metadata: Metadata,
) {
this.logger.info('RefreshAccessToken');
return lastValueFrom(
this.authService.AuthRefreshAccessToken({ refreshToken }),
this.authService.AuthRefreshAccessToken({ refreshToken }, metadata),
);
}
+355 -475
View File
@@ -3,24 +3,41 @@ import {
Controller,
Delete,
Get,
Headers,
HttpException,
Inject,
Param,
Post,
Put,
Query,
UnsupportedMediaTypeException,
} from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { AuthenticateCondition } from '../../authentication/authentication.decorator';
import {
AuthenticateCondition,
Authenticated,
} from '../../authentication/authentication.decorator';
import { PERMISSIONS_GROUPS } from '../../authentication/permissions.enum';
import { CatalogService } from './catalog.service';
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
import { PackTheMetadata } from 'src/utils/ PackTheMetadata';
import { RequestUser, User } from 'src/authentication/user.decorator';
import {
ICatalogAllResponse,
IColumnsMetadataResponse,
IDeleteComment,
IDocsResponse,
IMakeAComment,
IOneDataAsset,
IPreviewResponse,
IUpdateDataRequest,
} from './dtos';
@ApiTags('Catalog')
@Controller('catalog')
@Authenticated()
@AuthenticateCondition((req, user) => {
if (req.path.includes('/manage_permissions/')) return true;
let action;
switch (req.method) {
@@ -50,54 +67,15 @@ export class CatalogController {
this.logger = dadosferaLogger.logger;
}
@Put('manage_permissions/:id')
async manageDataAssetPermissions(
@Param('id') id: string,
@Get()
async catalogAll(
@User() user: RequestUser,
@Body() body,
) {
const { customer_id, customer_name, user_id, username } = user;
const metadata = PackTheMetadata({
customer_id,
customer_name,
user_id,
username,
});
const response = await this.catalogService.managePermissions(
{ ...body, id },
metadata,
);
return { data_asset: JSON.parse(response.data_asset) };
}
@Put('revoke_permissions/:id')
async revokeDataAssetPermissions(
@Param('id') id: string,
@User() user: RequestUser,
@Body() body,
) {
const { customer_id, customer_name, user_id, username } = user;
const metadata = PackTheMetadata({
customer_id,
customer_name,
user_id,
username,
});
const response = await this.catalogService.revokePermissions(
{ ...body, id },
metadata,
);
return { message: response.message };
}
@Get('all')
async catalogAll(@User() user: RequestUser, @Body() body, @Query() params) {
@Query() query,
): Promise<ICatalogAllResponse> {
const { user_id, customer_name, customer_id, username, permissions } = user;
this.logger.info(`/catalog - ON CATALOG ALL ROUTE`, {
user: body.info.user_id,
customer: body.info.customer,
this.logger.info(`/catalog - Catalog all data assets`, {
user_id,
customer_name,
});
const is_data_manager = permissions.includes(
@@ -116,378 +94,12 @@ export class CatalogController {
});
const res = await this.catalogService.getAllOpenSearchDataAssets(
params,
query,
metadata,
customer_id,
);
return res.data_assets;
}
@Get('data_apps')
async dataAppsAll(@Body() body) {
this.logger.info(`/catalog - ON FIND ALL DATA APPS ROUTE`, {
user: body.info.user_id,
customer: body.info.customer,
});
const res = await this.catalogService.dataAppsAll(body);
return res;
}
@Delete('data_apps/:id')
async dataAppsOne(@Param() params, @Body() body) {
this.logger.info(`/catalog - ON FIND ONE DATA APP ROUTE`, {
user: body.info.user_id,
customer: body.info.customer,
});
const { id } = params;
const res = await this.catalogService.dataAppsOne(id, body);
return res;
}
@Get('dashboard-metabase')
async getAllDashboardMetabase(@Body() body) {
this.logger.info(`/catalog - ON GET ALL DASHBOARDS METABASE ROUTE`, {
user: body.info.user_id,
customer: body.info.customer,
});
const res = await this.catalogService.getAllDashboardMetabase(body);
return res;
}
@Get('dashboard-metabase/:id')
async getOneDashboardMetabase(
@Body() body,
@Param() params,
@User() user: RequestUser,
) {
const { id } = params;
this.logger.info(`/catalog - ON GET ONE DASHBOARD METABASE ROUTE`, {
user: body.info.user_id,
customer: body.info.customer,
});
const { username, user_id, customer_id, customer_name, permissions } = user;
const is_data_manager = permissions.includes(
PERMISSIONS_GROUPS.CATALOG.permissions.DATA_MANAGER.seqid,
);
let has_permission = false;
const metadata = PackTheMetadata({
username,
user_id,
customer_id,
customer_name,
});
const user_roles = await this.catalogService.getUserRolesIds(user_id);
const res = await this.catalogService.getOneDashboardMetabase(
id,
body,
metadata,
customer_id,
);
const dashboard = res.dashboard;
if (dashboard.owner === username) has_permission = true;
for (const role of user_roles) {
if (dashboard.p_roles.includes(role)) has_permission = true;
}
if (dashboard.p_users.includes(user_id)) has_permission = true;
if (is_data_manager || has_permission) {
delete res[0].p_roles;
delete res[0].p_users;
return res;
}
throw new HttpException(
'You do not have permission to access this data asset.',
403,
);
}
@Get('table-metadata')
async getAllTableMetadata(
@Body() body,
@Query() query,
@User() user: RequestUser,
) {
this.logger.info(`/catalog - ON GET ALL TABLES METADATA ROUTE`, {
user: user.user_id,
customer: user.customer_name,
});
const { user_id, customer_name, customer_id, permissions, username } = user;
const is_data_manager = permissions.includes(
PERMISSIONS_GROUPS.CATALOG.permissions.DATA_MANAGER.seqid,
);
let has_permission = false;
const metadata = PackTheMetadata({
user_id,
customer_id,
customer_name,
});
if (!query) {
const res = await this.catalogService.getAllTableMetadata(body);
return res;
} else {
const user_roles = await this.catalogService.getUserRolesIds(user_id);
const res = await this.catalogService.getOneTableMetadata(
body,
query,
metadata,
customer_id,
);
const table = res[0];
if (table.owner === username) has_permission = true;
for (const role of user_roles) {
if (table.p_roles.includes(role)) has_permission = true;
}
if (table.p_users.includes(user_id)) has_permission = true;
if (is_data_manager || has_permission) {
delete res[0].p_roles;
delete res[0].p_users;
return res;
}
throw new HttpException(
'You do not have permission to access this data asset.',
403,
);
}
}
@Delete('table-metadata/:id')
async deleteOneTableMetadata(@Param() params, @Body() body) {
const { id } = params;
this.logger.info(`/catalog - ON DELETE ONE TABLE METADATA ROUTE`, {
user: body.info.user_id,
customer: body.info.customer,
});
const res = await this.catalogService.deleteOneTableMetadata(id, body);
return res;
}
@Get('column-metadata')
async getOneColumnMetadata(@Body() body, @Query() params) {
this.logger.info(`/catalog - ON GET ONE COLUMN METADATA ROUTE`, {
user: body.info.user_id,
customer: body.info.customer,
});
const res = await this.catalogService.getOneColumnMetadata(body, params);
return res;
}
@Delete('column-metadata/:id')
async deleteOneColumnMetadata(@Param() params, @Body() body) {
this.logger.info(`/catalog - ON DELETE ONE COLUMN METADATA ROUTE`, {
user: body.info.user_id,
customer: body.info.customer,
});
const { id } = params;
const res = await this.catalogService.deleteOneColumnMetadata(id, body);
return res;
}
@Get('data-preview')
async getOneDataPreview(@Body() body, @Query() params) {
this.logger.info(`/catalog - ON GET ONE DATAPREVIEW ROUTE`, {
user: body.info.user_id,
customer: body.info.customer,
});
const res = await this.catalogService.getOneDataPreview(body, params);
return res;
}
@Get('data-status')
async getDataStatus(@Body() body) {
this.logger.info(`/catalog - ON GET DATA STATUS ROUTE`, {
user: body.info.user_id,
customer: body.info.customer,
});
const res = await this.catalogService.getDataStatus(body);
return res;
}
@Get('data-status')
async createDataStatus(@Body() body) {
this.logger.info(`/catalog - ON CREATE DATA STATUS ROUTE`, {
user: body.info.user_id,
customer: body.info.customer,
});
const res = await this.catalogService.createDataStatus(body);
return res;
}
@Get('data-description')
async getDataDescription(@Body() body) {
this.logger.info(`/catalog - ON GET DATA DESCRIPTION ROUTE`, {
user: body.info.user_id,
customer: body.info.customer,
});
const res = await this.catalogService.getDataDescription(body);
return res;
}
@Post('data-description')
async createDataDescription(@Body() body, @User() user: RequestUser) {
this.logger.info(`/catalog - ON CREATE DATA DESCRIPTION ROUTE`, {
user: user.user_id,
customer: user.customer_name,
});
const { user_id, customer_name, customer_id } = user;
const metadata = PackTheMetadata({
user_id,
customer_id,
customer_name,
});
return await this.catalogService.createDataDescription(body, metadata);
}
@Get('data-docs')
async getDataDocs(@Body() body) {
this.logger.info(`/catalog - ON GET DATA DOCS ROUTE`, {
user: body.info.user_id,
customer: body.info.customer,
});
const res = await this.catalogService.getDataDocs(body);
return res;
}
@Post('data-docs')
async createDataDocs(@Body() body) {
this.logger.info(`/catalog - ON CREATE DATA DOCS ROUTE`, {
user: body.info.user_id,
customer: body.info.customer,
});
const res = await this.catalogService.createDataDocs(body);
return res;
}
@Get('data-rating')
async getDataRating(@Body() body) {
this.logger.info(`/catalog - ON GET DATA RATING ROUTE`, {
user: body.info.user_id,
customer: body.info.customer,
});
const res = await this.catalogService.getDataRating(body);
return res;
}
@Post('data-rating')
async createDataRating(@Body() body) {
this.logger.info(`/catalog - ON GET DATA RATING ROUTE`, {
user: body.info.user_id,
customer: body.info.customer,
});
const res = await this.catalogService.createDataRating(body);
return res;
}
@Get('summary-rating/:id')
async getSummaryRating() {
this.logger.info(`/catalog - ON GET SUMMARY RATING ROUTE`);
//const { id } = params;
//
//const res = await this.catalogService.getSummaryRating(id, body);
return {
avg_rating: 0,
rating_count: 0,
};
}
@Get('data-comment')
async getDataComment(@Body() body) {
this.logger.info(`/catalog - ON GET DATA COMMENT ROUTE`, {
user: body.info.user_id,
customer: body.info.customer,
});
const res = await this.catalogService.getDataComment(body);
return res;
}
@Post('data-comment')
async createDataComment(@Body() body) {
this.logger.info(`/catalog - ON GET DATA COMMENT ROUTE`, {
user: body.info.user_id,
customer: body.info.customer,
});
const res = await this.catalogService.createDataComment(body);
return res;
}
@Get('data-review')
async getDataReview(@Body() body, @Query() params) {
this.logger.info(`/catalog - ON GET DATA REVIEW ROUTE`, {
user: body.info.user_id,
customer: body.info.customer,
});
const res = await this.catalogService.getDataReview(body, params);
return res;
}
@Post('tags')
async createTags(@Body() body, @User() user: RequestUser) {
this.logger.info(`/catalog - ON CREATE TAG ROUTE`, {
user: user.user_id,
customer: user.customer_name,
});
const { user_id, customer_name, customer_id } = user;
const metadata = PackTheMetadata({
user_id,
customer_id,
customer_name,
});
const res = await this.catalogService.createTags(body, metadata);
return res.data_assets;
return { ...res };
}
@Get('tags')
@@ -509,89 +121,357 @@ export class CatalogController {
return res;
}
@Delete('tags/:id')
async deleteTags(@Param() params, @Body() body) {
this.logger.info(`/catalog - ON DELETE TAG ROUTE`, {
user: body.info.user_id,
customer: body.info.customer,
@Get('data-asset/:id')
async getDataAsset(
@User() user: RequestUser,
@Headers() headers,
@Param('id') id,
) {
const { username, user_id, customer_id, customer_name, permissions } = user;
const [data_asset_type, data_asset_id] = id.split('-');
this.logger.info(`/catalog - ON GET ONE DASHBOARD METABASE ROUTE`, {
username,
customer_name,
});
const { id } = params;
body.data_asset_id = id;
const { user_id, customer, customer_id } = body.info;
const is_data_manager = permissions.includes(
PERMISSIONS_GROUPS.CATALOG.permissions.DATA_MANAGER.seqid,
);
let has_permission = false;
const metadata = PackTheMetadata({
username,
user_id: undefined,
customer_id,
customer_name,
});
const user_roles = await this.catalogService.getUserRolesIds(user_id);
const { data_asset } = await this.catalogService.getOneDataAsset({
customer_id,
data_asset_id,
data_asset_type,
metadata,
});
if (data_asset?.owner === username) has_permission = true;
for (const role of user_roles) {
if (data_asset.p_roles.includes(role)) has_permission = true;
}
if (data_asset.p_users.includes(user_id)) has_permission = true;
if (is_data_manager || has_permission) {
delete data_asset.p_roles;
delete data_asset.p_users;
return { data_asset };
}
throw new HttpException(
'You do not have permission to access this data asset.',
403,
);
}
@Get('data-asset/rls/:id')
async getDataAssetRls(
@User() user: RequestUser,
@Headers() headers,
@Param('id') id,
) {
const { username, user_id, customer_id, customer_name, permissions } = user;
const [data_asset_type, data_asset_id] = id.split('-');
this.logger.info(`/catalog - ON GET ONE DASHBOARD METABASE ROUTE`, {
username,
customer_name,
});
const is_data_manager = permissions.includes(
PERMISSIONS_GROUPS.CATALOG.permissions.DATA_MANAGER.seqid,
);
let has_permission = false;
const metadata = PackTheMetadata({
username,
user_id,
customer_id,
customer_name: customer,
});
const res = await this.catalogService.deleteTags(body, metadata);
return res;
}
@Post('table-tags')
async createTableTags(@Body() body) {
this.logger.info(`/catalog - ON CREATE TABLE TAG ROUTE`, {
user: body.info.user_id,
customer: body.info.customer,
customer_name,
});
const res = await this.catalogService.createTableTags(body);
const user_roles = await this.catalogService.getUserRolesIds(user_id);
return res;
}
@Get('table-tags/:data_asset_id')
async getAllTableTags(@Body() body, @Param() params) {
this.logger.info(`/catalog - ON GET ALL TABLE TAGS ROUTE`, {
user: body.info.user_id,
customer: body.info.customer,
});
const { user_id, customer, customer_id } = body.info;
const metadata = PackTheMetadata({
user_id,
const { data_asset } = await this.catalogService.getOneDataAsset({
customer_id,
customer_name: customer,
data_asset_id,
data_asset_type,
metadata,
});
if (data_asset?.owner === username) has_permission = true;
for (const role of user_roles) {
if (data_asset.p_roles.includes(role)) has_permission = true;
}
if (data_asset.p_users.includes(user_id)) has_permission = true;
if (is_data_manager || has_permission) {
delete data_asset.p_roles;
delete data_asset.p_users;
return { data_asset };
}
throw new HttpException(
'You do not have permission to access this data asset.',
403,
);
}
@Get('data-asset/:id/columns-metadata')
async getDataAssetColumnsMetadata(
@User() user: RequestUser,
@Headers('Dadosfera-Lang') language,
@Param('id') id,
): Promise<IColumnsMetadataResponse> {
const { customer_name, customer_id, user_id, username } = user;
const data_asset_type = id.split('-')[0];
const supported_data_assets = ['dataset'];
if (!supported_data_assets.includes(data_asset_type)) {
throw new UnsupportedMediaTypeException(
`${data_asset_type} does not have a preview function for the time being.`,
);
}
this.logger.info(`/catalog - ON GET DATA DOCS ROUTE`, {
user_id,
customer_name,
});
const metadata = PackTheMetadata({
customer_name,
customer_id,
user_id,
username,
language,
});
const columns_metadata =
await this.catalogService.getDatasetColumnsMetadata(id, metadata);
return { columns_metadata };
}
@Get('data-asset/:id/preview')
async getDataAssetPreview(
@User() user: RequestUser,
@Headers('Dadosfera-lang') language,
@Param('id') id,
): Promise<IPreviewResponse> {
const { customer_name, customer_id, user_id, username } = user;
const data_asset_type = id.split('-')[0];
const supported_data_assets = ['dataset'];
if (!supported_data_assets.includes(data_asset_type)) {
throw new UnsupportedMediaTypeException(
`${data_asset_type} does not have a preview function for the time being.`,
);
}
this.logger.info(`/catalog - ON GET DATA DOCS ROUTE`, {
user_id,
customer_name,
});
const metadata = PackTheMetadata({
customer_name,
customer_id,
user_id,
username,
language,
});
const preview = await this.catalogService.getDatasetPreview(id, metadata);
return { preview };
}
@Get('data-asset/:id/docs')
async getDataAssetDocs(
@User() user: RequestUser,
@Headers('Dadosfera-Lang') language,
@Param('id') id,
): Promise<IDocsResponse> {
const { customer_name, customer_id, user_id, username } = user;
const data_asset_type = id.split('-')[0];
const supported_data_assets = ['dataset'];
if (!supported_data_assets.includes(data_asset_type)) {
throw new UnsupportedMediaTypeException(
`${data_asset_type} does not have a documentation function for the time being.`,
);
}
this.logger.info(`/catalog - ON GET DATA DOCS ROUTE`, {
user_id,
customer_name,
});
const metadata = PackTheMetadata({
customer_name,
customer_id,
user_id,
username,
language,
});
const docs = await this.catalogService.getDataDocs(id, metadata);
return { docs };
}
@Put('data-asset/:id')
async updateDataAsset(
@User() user: RequestUser,
@Headers('Dadosfera-Lang') language,
@Param('id') id,
@Body() body: IUpdateDataRequest,
): Promise<IOneDataAsset> {
const { customer_id, customer_name, user_id, username } = user;
const metadata = PackTheMetadata({
customer_id,
customer_name,
user_id,
username,
language,
});
const result = await this.catalogService.updateOneDataAsset({
body,
data_asset_id: id,
customer_id,
metadata,
});
delete result.data_asset.p_roles;
delete result.data_asset.p_users;
return result;
}
@Post('data-asset/:id/docs')
async manageDataAssetDocs(
@User() user: RequestUser,
@Headers() headers,
@Param('id') data_asset_id,
@Body('docs') docs: string,
) {
const { user_id, customer_name } = user;
const [data_asset_type, id] = data_asset_id.split('-');
this.logger.info(`/catalog - ON GET DATA DOCS ROUTE`, {
user_id,
customer_name,
});
const res = await this.catalogService.createDataDocs({
table_id: id,
docs,
info: {
customer: customer_name,
},
});
const res = await this.catalogService.findAllTableTags(params, metadata);
return res;
}
@Delete('table-tags/:id')
async deleteTableTags(@Param() params, @Body() body) {
this.logger.info(`/catalog - ON CREATE TABLE TAGS ROUTE`, {
user: body.info.user_id,
customer: body.info.customer,
@Put('data-asset/:id/manage-permissions')
async manageDataAssetPermissions(
@Param('id') id: string,
@User() user: RequestUser,
@Body() body,
) {
const { customer_id, customer_name, user_id, username } = user;
const metadata = PackTheMetadata({
customer_id,
customer_name,
user_id,
username,
});
const { id } = params;
const response = await this.catalogService.managePermissions(
{ ...body, id },
metadata,
);
const res = await this.catalogService.deleteTableTags(id, body);
return res;
return { data_asset: JSON.parse(response.data_asset) };
}
@Get('table-rules')
async getTableRules(@Body() body) {
this.logger.info(`/catalog - ON GET TABLE RULES ROUTE`, {
user: body.info.user_id,
customer: body.info.customer,
@Put('data-asset/:id/revoke-permissions')
async revokeDataAssetPermissions(
@Param('id') id: string,
@User() user: RequestUser,
@Body() body,
) {
const { customer_id, customer_name, user_id, username } = user;
const metadata = PackTheMetadata({
customer_id,
customer_name,
user_id,
username,
});
const response = await this.catalogService.revokePermissions(
{ ...body, id },
metadata,
);
const res = await this.catalogService.getTableRules(body);
return res;
return { message: response.message };
}
@Delete('table-rules/:id')
async deleteTableRules(@Param() params, @Body() body) {
this.logger.info(`/catalog - ON DELETE TABLE RULES ROUTE`, {
user: body.info.user_id,
customer: body.info.customer,
@Post('data-asset/:id/comment')
async commentOnDataAsset(
@Param('id') id: string,
@User() user: RequestUser,
@Body() body: IMakeAComment,
) {
const { message } = body;
const { customer_id, customer_name, user_id, username } = user;
const metadata = PackTheMetadata({
customer_id,
customer_name,
user_id,
username,
});
const { id } = params;
const response = await this.catalogService.commentOnDataAsset(
{ data_asset_id: id, username, message },
metadata,
);
const res = await this.catalogService.deleteTableRules(id, body);
return response;
}
return res;
@Delete('data-asset/:id/comment')
async deleteComment(
@Param('id') id: string,
@User() user: RequestUser,
@Body() body: IDeleteComment,
) {
const { customer_id, customer_name, user_id, username } = user;
const metadata = PackTheMetadata({
customer_id,
customer_name,
user_id,
username,
});
const response = await this.catalogService.deleteComment(
{ data_asset_id: id, comment: body.comment },
metadata,
);
return response;
}
}
+133 -343
View File
@@ -1,8 +1,10 @@
import DadosferaLogger from '@dadosfera/dadosfera-logs/dist';
import { ReadService } from '@dadosfera/protospack-v2/dist/lib/Catalog';
import { ProtoServices } from '@dadosfera/protospack-v2/dist/lib/Catalog';
import { Messages } from '@dadosfera/protospack-v2/dist/lib/Catalog';
import { WriteService } from '@dadosfera/protospack-v2/dist/lib/Catalog';
import {
WriteService,
ReadService,
ProtoServices,
Messages,
} from '@dadosfera/protospack-v2/dist/lib/Catalog';
import {
HttpException,
HttpStatus,
@@ -15,6 +17,7 @@ import { lastValueFrom } from 'rxjs';
import { CatalogClientConfiguration } from './catalog-client';
import { UsersService } from '../users/users.service';
import { RolesService } from '../roles/roles.service';
import { Metadata } from '@grpc/grpc-js';
class CatalogService implements OnModuleInit {
catalogReadService: ReadService.CatalogReadServices;
@@ -81,34 +84,30 @@ class CatalogService implements OnModuleInit {
});
}
async catalogAll(body) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.get(`${nimbusUrl}/api/catalog/all/`);
async commentOnDataAsset(data: Messages.MakeACommentRequest, metadata) {
this.logger.info('CatalogService - Manage Data assets permissions');
return data;
return lastValueFrom(
this.catalogWriteService.MakeAComment(data, metadata),
).catch((err) => {
throw new HttpException(
err.details,
err.code === 6 ? HttpStatus.CONFLICT : 404,
);
});
}
async dataAppsAll(body) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.get(`${nimbusUrl}/api/catalog/data_apps/`);
return data;
}
async deleteComment(data: Messages.UpdateACommentRequest, metadata) {
this.logger.info('CatalogService - Manage Data assets permissions');
async dataAppsOne(id, body) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.get(
`${nimbusUrl}/api/catalog/data_apps/${id}/`,
);
return data;
}
async getAllDashboardMetabase(body) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.get(
`${nimbusUrl}/api/catalog/dashboard-metabase/`,
);
return data;
return lastValueFrom(
this.catalogWriteService.UpdateAComment(data, metadata),
).catch((err) => {
throw new HttpException(
err.details,
err.code === 6 ? HttpStatus.CONFLICT : 404,
);
});
}
async getUserRolesIds(userId: string) {
@@ -145,15 +144,23 @@ class CatalogService implements OnModuleInit {
return [customer_users, customer_roles];
}
async getAllOpenSearchDataAssets(
data: Messages.GetAllDataAssetsRequest,
metadata,
customer_id,
) {
async getAllOpenSearchDataAssets(query, metadata, customer_id) {
this.logger.info('CatalogService - getAllOpenSearchDashboard');
const response = await lastValueFrom(
this.catalogReadService.GetAllDataAssets(data, metadata),
const { search, page, size, sort_by, order, ...filters } = query;
const { data_assets, total } = await lastValueFrom(
this.catalogReadService.GetAllDataAssets(
{
search,
page,
size,
sort_by,
order,
filters: JSON.stringify(filters),
},
metadata,
),
).catch((err) => {
throw new HttpException(
err.details,
@@ -161,12 +168,12 @@ class CatalogService implements OnModuleInit {
);
});
const data_assets = JSON.parse(response.data_assets);
const result = JSON.parse(data_assets);
const [customer_users, customer_roles] =
await this.getUsernamesAndRolesByCustomerId(customer_id);
for (const asset of data_assets.tables) {
for (const asset of result.data_assets) {
const condition =
asset.owner && !asset.owner.includes('@') ? true : false;
const result = condition
@@ -198,30 +205,18 @@ class CatalogService implements OnModuleInit {
});
}
for (const asset of data_assets.dashboards) {
const condition =
asset.owner && !asset.owner.includes('@') ? true : false;
const result = condition
? await this.userService.findOneById(asset.owner).catch(() => null)
: null;
const owner = result !== null ? result.user.username : null;
Object.assign(asset, { ...asset, owner });
}
return { data_assets };
return { data_assets: result.data_assets, total };
}
async getOneDashboardMetabase(id, body, metadata, customer_id) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.get(
`${nimbusUrl}/api/catalog/dashboard-metabase/${id}`,
);
async getOneDataAsset({
data_asset_id,
data_asset_type,
customer_id,
metadata,
}) {
const { data_asset } = await lastValueFrom(
this.catalogReadService.GetOneDataAsset(
{ id, type: 'dashboard' },
{ id: data_asset_id, type: data_asset_type },
metadata,
),
);
@@ -253,9 +248,7 @@ class CatalogService implements OnModuleInit {
}
}
Object.assign(data.dashboard, {
tags: opensearchTable.tags,
description: opensearchTable.description || null,
Object.assign(opensearchTable, {
p_roles: opensearchTable.roles,
p_users: opensearchTable.users,
roles,
@@ -263,163 +256,94 @@ class CatalogService implements OnModuleInit {
owner,
});
return data;
return { data_asset: opensearchTable };
}
async getAllTableMetadata(body) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.get(
`${nimbusUrl}/api/catalog/table-metadata/`,
);
return data;
}
async getOneTableMetadata(body, params, metadata, customer_id) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.get(
`${nimbusUrl}/api/catalog/table-metadata/`,
{ params: params },
);
if (data?.length === 1) {
const { data_asset } = await lastValueFrom(
this.catalogReadService.GetOneDataAsset(
{ id: data[0].id, type: 'dataset' },
metadata,
),
);
const opensearchTable = JSON.parse(data_asset);
const result = opensearchTable.owner
? await this.userService
.findOneById(opensearchTable.owner)
.catch(() => null)
: null;
const owner = result !== null ? result.user.username : null;
const [customer_users, customer_roles] =
await this.getUsernamesAndRolesByCustomerId(customer_id);
const users = [];
const roles = [];
for (const role of customer_roles) {
for (const role_id of opensearchTable.roles) {
if (role.id === role_id) roles.push(role);
}
}
for (const user of customer_users) {
for (const user_id of opensearchTable.users) {
if (user.id === user_id) users.push(user);
}
}
return [
{
...data[0],
tags: opensearchTable.tags,
table_description: opensearchTable.description,
p_roles: opensearchTable.roles,
p_users: opensearchTable.users,
users,
roles,
owner,
},
];
}
return data;
}
async deleteOneTableMetadata(id, body) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.delete(
`${nimbusUrl}/api/catalog/table-metadata/${id}`,
);
return data;
}
async getOneColumnMetadata(body, params) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.get(
`${nimbusUrl}/api/catalog/column-metadata/`,
{ params: params },
);
return data;
}
async deleteOneColumnMetadata(id, body) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.delete(
`${nimbusUrl}/api/catalog/column-metadata/${id}/`,
);
return data;
}
async getOneDataPreview(body, params) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.get(`${nimbusUrl}/api/catalog/data-preview/`, {
params: params,
});
return data;
}
async getDataStatus(body) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.get(`${nimbusUrl}/api/catalog/data-status/`);
return data;
}
async createDataStatus(body) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.post(
`${nimbusUrl}/api/catalog/data-status/`,
body,
);
return data;
}
async getDataDescription(body) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.get(
`${nimbusUrl}/api/catalog/data-description/`,
);
return data;
}
async createDataDescription(body, metadata) {
const response = await lastValueFrom(
async updateOneDataAsset({ data_asset_id, customer_id, body, metadata }) {
const { data_asset } = await lastValueFrom(
this.catalogWriteService.UpdateDataAsset(
{
id: `dataset-${body.table_id}`,
description: body.description,
tags: undefined,
},
{ id: data_asset_id, ...body },
metadata,
),
);
// {
// description: 'descrição nova';
// id: 5;
// table_id: 4;
// }
// const nimbusUrl = this._getNimbusUrl(body);
// const { data } = await axios.post(
// `${nimbusUrl}/api/catalog/data-description/`,
// body,
// );
// {"id":5,"description":"descrição nova","updated_at":"2022-09-28T14:35:15.618750Z","table_id":4}
return {
id: 0,
description: body.description,
updated_at: new Date().toISOString(),
table_id: body.table_id,
};
const opensearchTable = JSON.parse(data_asset);
const result = opensearchTable.owner
? await this.userService
.findOneById(opensearchTable.owner)
.catch(() => null)
: null;
const owner = result !== null ? result.user.username : null;
const [customer_users, customer_roles] =
await this.getUsernamesAndRolesByCustomerId(customer_id);
const users = [];
const roles = [];
for (const role of customer_roles) {
for (const role_id of opensearchTable.roles) {
if (role.id === role_id) roles.push(role);
}
}
for (const user of customer_users) {
for (const user_id of opensearchTable.users) {
if (user.id === user_id) users.push(user);
}
}
Object.assign(opensearchTable, {
p_roles: opensearchTable.roles,
p_users: opensearchTable.users,
roles,
users,
owner,
});
return { data_asset: opensearchTable };
}
async getDataDocs(body) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.get(`${nimbusUrl}/api/catalog/data-docs/`);
return data;
async getDataDocs(data_asset_id: string, metadata: Metadata) {
const [data_asset_type, id] = data_asset_id.split('-');
const { documentation } = await lastValueFrom(
this.catalogReadService.GetDatasetDoc(
{ id, type: data_asset_type },
metadata,
),
);
console.log(documentation);
const docs = JSON.parse(documentation);
return docs;
}
async getDatasetPreview(data_asset_id: string, metadata: Metadata) {
const [data_asset_type, id] = data_asset_id.split('-');
const { preview } = await lastValueFrom(
this.catalogReadService.GetDatasetPreview(
{ id, type: data_asset_type },
metadata,
),
);
const result = JSON.parse(preview);
return result;
}
async getDatasetColumnsMetadata(data_asset_id: string, metadata: Metadata) {
const [data_asset_type, id] = data_asset_id.split('-');
const { columns_metadata } = await lastValueFrom(
this.catalogReadService.GetDatasetColumnsMetadata(
{ id, type: data_asset_type },
metadata,
),
);
const result = JSON.parse(columns_metadata);
return result;
}
async createDataDocs(body) {
@@ -431,70 +355,6 @@ class CatalogService implements OnModuleInit {
return data;
}
async getDataRating(body) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.get(`${nimbusUrl}/api/catalog/data-rating/`);
return data;
}
async createDataRating(body) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.post(
`${nimbusUrl}/api/catalog/data-rating/`,
body,
);
return data;
}
async getSummaryRating(id, body) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.get(
`${nimbusUrl}/api/catalog/summary-rating/${id}`,
);
return data;
}
async getDataComment(body) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.get(`${nimbusUrl}/api/catalog/data-comment/`);
return data;
}
async createDataComment(body) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.post(
`${nimbusUrl}/api/catalog/data-comment/`,
body,
);
return data;
}
async getDataReview(body, params) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.get(`${nimbusUrl}/api/catalog/data-review/`, {
params: params,
});
return data;
}
async createTags(data: Messages.TagTableRequest, metadata) {
this.logger.info('CatalogService - createTags');
const response = await lastValueFrom(
this.catalogWriteService.TagTable(data, metadata),
)
.then((res) => {
this.logger.info('Done');
return res;
})
.catch((err) => {
this.logger.error(err.message);
throw new Error(err);
});
return { data_assets: response };
}
async findAllTags(data, metadata) {
this.logger.info('CatalogService - findAllCustomerTags');
@@ -512,76 +372,6 @@ class CatalogService implements OnModuleInit {
return response;
}
async findAllTableTags(data, metadata) {
this.logger.info('CatalogService - findAllTableTags');
const response = await lastValueFrom(
this.catalogReadService.GetTableTags(data, metadata),
)
.then((res) => {
this.logger.info('Done');
return res;
})
.catch((err) => {
this.logger.error(err.message);
throw new Error(err);
});
return response;
}
async deleteTags(data, metadata) {
this.logger.info('CatalogService - deleteTags');
const response = await lastValueFrom(
this.catalogWriteService.UntagTable(data, metadata),
)
.then((res) => {
this.logger.info('Done');
return res;
})
.catch((err) => {
this.logger.error(err.message);
throw new Error(err);
});
return response;
}
async createTableTags(body) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.post(
`${nimbusUrl}/api/catalog/table-tags/`,
body,
);
return data;
}
async deleteTableTags(id, body) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.delete(
`${nimbusUrl}/api/catalog/table-tags/${id}`,
);
return data;
}
async getTableRules(body) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.get(
`${nimbusUrl}/api/catalog/table-rules/`,
body,
);
return data;
}
async deleteTableRules(id, body) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.delete(
`${nimbusUrl}/api/catalog/table-rules/${id}`,
);
return data;
}
}
export { CatalogService };
+203
View File
@@ -0,0 +1,203 @@
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
export class IRole {
@ApiProperty()
name: string;
@ApiProperty()
id: string;
}
export class IUser {
@ApiProperty()
username: string;
@ApiProperty()
id: string;
}
export class IComment {
@ApiProperty()
id: number;
@ApiProperty()
message: string;
@ApiProperty()
created_at: string;
@ApiProperty()
username: string;
}
export class IDataAsset {
@ApiProperty()
id: number;
@ApiPropertyOptional()
database_name?: string;
@ApiPropertyOptional()
table_name?: string;
@ApiPropertyOptional()
num_columns?: number;
@ApiPropertyOptional()
location?: string;
@ApiPropertyOptional()
created_time?: string;
@ApiPropertyOptional()
table_type?: string;
@ApiPropertyOptional()
size_in_bytes?: number;
@ApiPropertyOptional()
num_files?: number;
@ApiPropertyOptional()
data_encrypted?: string;
@ApiPropertyOptional()
num_rows?: number;
@ApiPropertyOptional()
display_name?: string;
@ApiProperty()
pipeline_id: string;
@ApiProperty()
user_id: string;
@ApiProperty()
description: string;
@ApiProperty()
data_asset_type: string;
@ApiProperty()
tags: string[];
@ApiProperty()
owner: string;
@ApiProperty({ type: [IRole] })
roles: IRole[];
@ApiProperty({ type: [IUser] })
users: IUser[];
@ApiPropertyOptional()
dashboard_id?: number;
@ApiPropertyOptional()
name?: string;
@ApiPropertyOptional()
parameters?: string[];
@ApiPropertyOptional()
embedding_params?: object;
@ApiPropertyOptional()
created_at?: string;
@ApiPropertyOptional()
updated_at?: string;
@ApiProperty({ type: [IComment] })
comments: IComment[];
}
export class IOneDataAsset {
@ApiProperty()
data_asset: IDataAsset;
}
export class IMakeAComment {
@ApiProperty()
message: string;
}
export class IDeleteComment {
@ApiProperty()
comment: IComment;
}
export class ICatalogAllResponse {
@ApiProperty({ type: [IDataAsset] })
data_assets: IDataAsset[];
@ApiProperty()
total: number;
}
export class IData {
@ApiProperty()
var: number;
@ApiProperty()
date: string;
@ApiProperty()
last: number;
@ApiProperty()
maximum: number;
@ApiProperty()
minimum: number;
@ApiProperty()
day_opening: number;
}
export class IUpdateDataRequest {
@ApiProperty()
name: string;
@ApiProperty()
description: string;
@ApiProperty()
tags: string[];
}
export class IPreview {
@ApiProperty()
id: string;
@ApiProperty()
database_name: string;
@ApiProperty()
table_name: string;
@ApiProperty({ type: [IData] })
data: IData[];
}
export class IDocs {
@ApiProperty()
id: string;
@ApiProperty()
docs: string;
@ApiProperty()
updated_at: string;
@ApiProperty()
table_id: string;
}
export class IColumnMetadata {
@ApiProperty()
id: string;
@ApiProperty()
table_name: string;
@ApiProperty()
column_name: string;
@ApiProperty()
data_type: string;
@ApiProperty()
missing_count: string;
@ApiProperty()
min: string;
@ApiProperty()
max: string;
@ApiProperty()
count: string;
@ApiProperty()
histogram: string;
@ApiProperty()
mean: string;
@ApiProperty()
median: string;
@ApiProperty()
missing_rate: string;
@ApiProperty()
stddev: string;
@ApiProperty()
unique_count: string;
@ApiProperty()
unique_rate: string;
@ApiProperty()
analyzer_rules: string[];
@ApiProperty()
version: string;
}
export class IPreviewResponse {
@ApiProperty()
preview: IPreview;
}
export class IDocsResponse {
@ApiProperty()
docs: IDocs;
}
export class IColumnsMetadataResponse {
@ApiProperty({ type: [IColumnMetadata] })
columns_metadata: IColumnMetadata[];
}
+164 -17
View File
@@ -71,27 +71,174 @@ export class ConnectorClientService implements OnModuleInit {
);
}
async uploadConnectorsFile(uploadFile) {
const connectors = JSON.parse(uploadFile.file.buffer.toString('utf8'));
const body = connectors.map((connector) => {
return JSON.stringify(connector);
});
const request = {
connectors: body,
};
return lastValueFrom(
this.connectorServiceWrite.RegisterMultipleConnectorsWithoutImage(
request,
),
async uploadConnectorsFile(uploadFile: Express.Multer.File) {
const res = await lastValueFrom(
this.connectorServiceWrite.RegisterMultipleConnectorsWithoutImage({
connectors: uploadFile.buffer,
}),
).catch((err) => {
throw new HttpException(
err.details,
err.code === 6 ? HttpStatus.CONFLICT : 400,
);
});
const responseParsed = JSON.parse(res.message);
const connectorErrors = responseParsed.items
.filter((i) => i.update._index === 'connector' && i.update.error)
.map((i) => ({
id: i.update._id,
reason: i.update.error,
status: i.error.status,
}));
const connectionControlsErrors = responseParsed.items
.filter(
(i) => i.update._index === 'connection_controls' && i.update.error,
)
.map((i) => ({
id: i.update._id,
reason: i.update.error,
status: i.error.status,
}));
const connectionStepsErrors = responseParsed.items
.filter((i) => i.update._index === 'connection_steps' && i.update.error)
.map((i) => ({
id: i.update._id,
reason: i.update.error,
status: i.error.status,
}));
const configControlsErrors = responseParsed.items
.filter((i) => i.update._index === 'config_controls' && i.update.error)
.map((i) => ({
id: i.update._id,
reason: i.update.error,
status: i.error.status,
}));
const connectorCreated = responseParsed.items
.filter(
(i) => i.update._index === 'connector' && i.update.result === 'created',
)
.map((i) => ({
id: i.update._id,
}));
const connectionControlsCreated = responseParsed.items
.filter(
(i) =>
i.update._index === 'connection_controls' &&
i.update.result === 'created',
)
.map((i) => ({
id: i.update._id,
}));
const connectionStepsCreated = responseParsed.items
.filter(
(i) =>
i.update._index === 'connection_steps' &&
i.update.result === 'created',
)
.map((i) => ({
id: i.update._id,
}));
const configControlsCreated = responseParsed.items
.filter(
(i) =>
i.update._index === 'config_controls' &&
i.update.result === 'created',
)
.map((i) => ({
id: i.update._id,
}));
const connectorUpdated = responseParsed.items
.filter(
(i) => i.update._index === 'connector' && i.update.result === 'updated',
)
.map((i) => ({
id: i.update._id,
}));
const connectionControlsUpdated = responseParsed.items
.filter(
(i) =>
i.update._index === 'connection_controls' &&
i.update.result === 'updated',
)
.map((i) => ({
id: i.update._id,
}));
const connectionStepsUpdated = responseParsed.items
.filter(
(i) =>
i.update._index === 'connection_steps' &&
i.update.result === 'updated',
)
.map((i) => ({
id: i.update._id,
}));
const configControlsUpdated = responseParsed.items
.filter(
(i) =>
i.update._index === 'config_controls' &&
i.update.result === 'updated',
)
.map((i) => ({
id: i.update._id,
}));
const connectorNoop = responseParsed.items
.filter(
(i) => i.update._index === 'connector' && i.update.result === 'noop',
)
.map((i) => ({
id: i.update._id,
}));
const connectionControlsNoop = responseParsed.items
.filter(
(i) =>
i.update._index === 'connection_controls' &&
i.update.result === 'noop',
)
.map((i) => ({
id: i.update._id,
}));
const connectionStepsNoop = responseParsed.items
.filter(
(i) =>
i.update._index === 'connection_steps' && i.update.result === 'noop',
)
.map((i) => ({
id: i.update._id,
}));
const configControlsNoop = responseParsed.items
.filter(
(i) =>
i.update._index === 'config_controls' && i.update.result === 'noop',
)
.map((i) => ({
id: i.update._id,
}));
return {
errors: {
connectors: connectorErrors,
connection_controls: connectionControlsErrors,
connection_steps: connectionStepsErrors,
config_controls: configControlsErrors,
},
created: {
connectors: connectorCreated,
connection_controls: connectionControlsCreated,
connection_steps: connectionStepsCreated,
config_controls: configControlsCreated,
},
updated: {
connectors: connectorUpdated,
connection_controls: connectionControlsUpdated,
connection_steps: connectionStepsUpdated,
config_controls: configControlsUpdated,
},
noop: {
connectors: connectorNoop,
connection_controls: connectionControlsNoop,
connection_steps: connectionStepsNoop,
config_controls: configControlsNoop,
},
};
}
async getAllConnectors(body) {
@@ -116,13 +263,13 @@ export class ConnectorClientService implements OnModuleInit {
});
}
async getConnectorDetails(plugin: string, language: string) {
async getConnectorDetails(connectorId: string, language: string) {
const meta = new Metadata();
meta.add('Language', language);
return lastValueFrom(
this.connectorServiceRead.GetConnectorDetails(
{
plugin,
plugin: connectorId,
},
meta,
),
@@ -19,7 +19,6 @@ import { ApiBearerAuth, ApiConsumes, ApiTags } from '@nestjs/swagger';
import { ConnectorClientService } from './client.service';
import { AddTagDto } from './dtos/add-tag';
import { CreateConnectorDto } from './dtos/create-connector';
import { UploadConnectorsFileDto } from './dtos/create-multiple-connector';
import { DeleteConnectorDto } from './dtos/delete-connector';
import { GetAllDto } from './dtos/get-all';
import { RemoveTagDto } from './dtos/remove-tag';
@@ -85,14 +84,10 @@ export class ConnectorController {
@RequireAllPermissions(PERMISSIONS_GROUPS.CONNECTORS.permissions.CREATE)
@ApiConsumes('multipart/form-data')
@UseInterceptors(FileInterceptor('file'))
async uploadConnectorsFile(@UploadedFile() file: UploadConnectorsFileDto) {
async uploadConnectorsFile(@UploadedFile() file: Express.Multer.File) {
this.logger.info(`/upload`, 'Upload Connector Route');
const response = await this.connectorClientService.uploadConnectorsFile({
file,
});
return response;
return await this.connectorClientService.uploadConnectorsFile(file);
}
@Get()
@@ -19,17 +19,18 @@ import { RequestUser, User } from 'src/authentication/user.decorator';
import {
CreateNetworkConfigReq,
CreateNetworkConfigRes,
DeleteNetworkConfigRes,
FindAllNetworkConfigsRes,
UpdateNetworkConfigReq,
UpdateNetworkConfigRes,
} from './dto/network-config';
import { FileInterceptor } from '@nestjs/platform-express';
import { PERMISSIONS_GROUPS } from 'src/authentication/permissions.enum';
import { RequireAllPermissions } from 'src/authentication/authentication.decorator';
import {
Authenticated,
RequireAllPermissions,
} from 'src/authentication/authentication.decorator';
const networkConfigPermissions = PERMISSIONS_GROUPS.NETWORK_CONFIG.permissions;
@ApiTags('Network Config')
@Authenticated()
@Controller('network-config')
export class NetworkConfigController {
logger: any;
+3 -3
View File
@@ -17,13 +17,13 @@ export class OauthController {
switch (process.env.ENV) {
case 'dev':
case 'stg':
this.redirectUrl = `https://app.${process.env.ENV}.dadosfera.ai/coletix/auth-callback`;
this.redirectUrl = `https://app.${process.env.ENV}.dadosfera.ai/collect/auth-callback`;
break;
case 'prd':
this.redirectUrl = `https://app.dadosfera.ai/coletix/auth-callback`;
this.redirectUrl = `https://app.dadosfera.ai/collect/auth-callback`;
break;
default:
this.redirectUrl = `http://localhost:4200/coletix/auth-callback`;
this.redirectUrl = `http://localhost:4200/collect/auth-callback`;
}
}
@Get('hubspot')
@@ -15,6 +15,7 @@ import { GetPublicPermissionsRes } from './dto/entities';
import { PermissionsService } from './permissions.service';
@ApiTags('Permissions')
@Authenticated()
@Controller('permissions')
@ApiHeader({
name: 'dadosfera-lang',
@@ -22,7 +23,6 @@ import { PermissionsService } from './permissions.service';
required: false,
description: 'Defaults to pt-br',
})
@Authenticated()
export class PermissionsController {
logger: DadosferaLogger;
@@ -9,7 +9,10 @@ import {
Put,
} from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { AuthenticateCondition } from 'src/authentication/authentication.decorator';
import {
AuthenticateCondition,
Authenticated,
} from 'src/authentication/authentication.decorator';
import { PERMISSIONS_GROUPS } from '../../authentication/permissions.enum';
import { PipelinesService } from './pipelines.service';
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
@@ -17,6 +20,7 @@ import { RequestUser, User } from 'src/authentication/user.decorator';
@ApiTags('Pipelines')
@Controller('pipelines')
@Authenticated()
@AuthenticateCondition((req, user) => {
let action;
+27 -25
View File
@@ -61,7 +61,7 @@ export class PipelinesController {
@User() user: RequestUser,
@Body() createPipelineDto: ICreatePipelineV2Req,
) {
this.logger.info(process.env.DEV_URL + `/pipelines ON CREATE ROUTE`);
this.logger.info('PipelinesController - create', { user });
if (!language) language = 'en-us';
const { customer_id, customer_name, username, user_id } = user;
const metadata = PackTheMetadata({
@@ -86,10 +86,7 @@ export class PipelinesController {
@Headers('Dadosfera-Lang') language,
@Query() data,
) {
this.logger.info(process.env.DEV_URL + `/pipeline ON Find All ROUTE`, {
user: user.user_id,
customer: user.customer_name,
});
this.logger.info('PipelinesController - findAll', { user });
if (!language) language = 'en-us';
@@ -103,24 +100,34 @@ export class PipelinesController {
});
const response = await this.pipelinesClientService.findAll(data, metadata);
const oldResponse = await this.oldPipelinesService.findAll({
customer_name,
user_id,
customer_id,
});
return {
pipelines: [...response.pipelines, ...oldResponse.pipelines],
pipelines: [...response.pipelines],
};
}
@Get(':id/config')
async getPipelineproperties(
@Headers('Dadosfera-Lang') language,
@User() user: RequestUser,
@Param('id') id,
) {
this.logger.info('PipelinesController - getPipelineproperties', { user });
const metadata = PackTheMetadata({
...user,
language: language || 'pt-br',
});
return this.pipelinesClientService.findOneProperties(id, metadata);
}
@Get('/:id')
async findOne(
@Headers('Dadosfera-Lang') language,
@User() user: RequestUser,
@Param('id') id,
): Promise<Messages.PipelineV2FindOneResponse> {
this.logger.info(process.env.DEV_URL + `/pipeline/${id} ON Find One ROUTE`);
this.logger.info('PipelinesController - findOne', { user });
if (!language) language = 'en-us';
const { customer_id, customer_name, user_id, username } = user;
@@ -149,24 +156,19 @@ export class PipelinesController {
: {},
});
return res;
})
.catch(async (err) => {
this.logger.error(err);
return await this.oldPipelinesService.findOne({
id,
info: { customer_id, customer: customer_name, user_id },
});
});
return result;
}
@Put('/:id')
async update(@Body() updatePipelineDto, @Param('id') id) {
async update(
@Body() updatePipelineDto,
@Param('id') id,
@User() user: RequestUser,
) {
this.logger.info('PipelinesController - findOne', { user });
const { info } = updatePipelineDto;
delete updatePipelineDto.info;
this.logger.info(process.env.DEV_URL + `/pipeline/${id} ON UPDATE ROUTE`);
const response = await this.pipelinesClientService.update({
...updatePipelineDto,
info,
@@ -177,9 +179,9 @@ export class PipelinesController {
}
@Delete(':id')
async delete(@Body() data, @Param() params) {
async delete(@Body() data, @Param() params, @User() user: RequestUser) {
const { id } = params;
this.logger.info(process.env.DEV_URL + `/pipeline/${id} ON DELETE ROUTE`);
this.logger.info('PipelinesController - findOne', { user });
const response = await this.pipelinesClientService.remove({ id, ...data });
@@ -8,6 +8,7 @@ import { PipelinesService } from './pipelines.service';
import { PipelinesClientConfiguration } from './pipelines-client';
import { PipelinesModule as OldPipelineModule } from 'src/modules/pipelines/pipelines.module';
import { ConnectorModule } from '../connector/connector.module';
const client = new PipelinesClientConfiguration();
@@ -15,6 +16,7 @@ const client = new PipelinesClientConfiguration();
imports: [
ClientsModule.register([client.providerOptions]),
OldPipelineModule,
ConnectorModule,
],
controllers: [PipelinesController],
providers: [PipelinesService, DadosferaLogger],
@@ -17,6 +17,8 @@ import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
import { PipelinesClientConfiguration } from './pipelines-client';
import { ICreatePipelineV2Req } from './interfaces';
import { PipelineV2CreateRequest } from '@dadosfera/protospack-v2/dist/lib/PipelineV2/interfaces/messages';
import { Metadata } from '@grpc/grpc-js';
import { ConnectorClientService } from '../connector/client.service';
export class PipelinesService implements OnModuleInit {
logger: DadosferaLogger;
@@ -27,6 +29,7 @@ export class PipelinesService implements OnModuleInit {
dadosferaLogger: DadosferaLogger,
@Inject(PipelinesClientConfiguration.name)
private readonly grpcClient: ClientGrpc,
private readonly connectorService: ConnectorClientService,
) {
this.logger = dadosferaLogger.logger;
}
@@ -169,4 +172,40 @@ export class PipelinesService implements OnModuleInit {
return removePipelineResponse;
}
async findOneProperties(id: string, metadata: Metadata) {
this.logger.info('PipelinesClientService - findOneProperties');
const { pipeline } = await this.findOne({ id }, metadata);
const pipelineProperties = JSON.parse(pipeline.properties);
const connectorId = `${pipeline.connector_plugin}-${pipeline.connector_version}`;
const res = await this.connectorService.getConnectorDetails(
connectorId,
metadata.get('language')[0].toString(),
);
const connector = JSON.parse(res.connector);
const config_controls = connector.config_controls || [];
for (const key in pipelineProperties) {
const i = config_controls
.map((cc) => cc.name)
.indexOf(`properties.${key}`);
if (i > -1) {
config_controls[i] = {
...config_controls[i],
default_value: pipelineProperties[key],
};
}
}
return {
pipeline: {
...pipeline,
config_controls,
properties: pipelineProperties,
},
};
}
}
+12
View File
@@ -0,0 +1,12 @@
import { ApiProperty } from '@nestjs/swagger';
export class INote {
@ApiProperty()
title: string;
@ApiProperty()
content: string;
@ApiProperty()
tags: string[];
}
@@ -0,0 +1,19 @@
import { Test, TestingModule } from '@nestjs/testing';
import { ProductboardController } from './productboard.controller';
describe('ProductboardController', () => {
let controller: ProductboardController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [ProductboardController],
providers: [],
}).compile();
controller = module.get<ProductboardController>(ProductboardController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});
@@ -0,0 +1,51 @@
import { Body, Controller, HttpException, Post } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import axios from 'axios';
import { User, RequestUser } from 'src/authentication/user.decorator';
import { getSecreteFromSecreteManager } from 'src/utils/SecretManager';
import { INote } from './dtos';
@ApiTags('Productboard')
@Controller('productboard')
export class ProductboardController {
@Post('notes')
async sendNote(@Body() note: INote, @User() user: RequestUser) {
const { title, content, tags } = note;
const { username, customer_name } = user;
const email = username.includes('@')
? username
: username + `@${customer_name}.default`;
const path = process.env.PB_TOKEN_PATH;
const token = await getSecreteFromSecreteManager(path);
const response = await axios
.post(
`https://api.productboard.com/notes`,
{
title,
content,
tags,
user: {
email,
},
},
{
headers: {
Authorization: 'Bearer ' + token,
},
},
)
.catch(() => null);
if (!response) {
throw new HttpException(
'Your request could not be submitted, please try again in a few moments or contact support.',
502,
);
}
return response.data;
}
}
@@ -0,0 +1,8 @@
import { Module } from '@nestjs/common';
import { ProductboardController } from './productboard.controller';
@Module({
controllers: [ProductboardController],
providers: [],
})
export class ProductboardModule {}
+1 -1
View File
@@ -53,8 +53,8 @@ import { LanguageEnum } from 'src/utils/languages.enum';
required: false,
description: 'Defaults to pt-br',
})
@UseFilters(new GrpcToHttpExceptionFilter())
@Authenticated()
@UseFilters(new GrpcToHttpExceptionFilter())
@Controller('roles')
export class RolesController {
logger: DadosferaLogger;
@@ -17,6 +17,7 @@ import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
import { GrpcToHttpExceptionFilter } from '../../error/grpc-to-http-exception.filter';
import { RequestUser, User } from '../../authentication/user.decorator';
import { Metadata } from '@grpc/grpc-js';
@ApiTags('TermsOfUse')
@UseFilters(new GrpcToHttpExceptionFilter())
@@ -33,10 +34,15 @@ export class TermsOfUseController {
}
@Get('token')
async getToken(@User({ required: true }) user: RequestUser) {
async getToken(
@User({ required: true }) user: RequestUser,
@Headers('Dadosfera-Lang') language: string,
) {
this.logger.info('/terms-of-use - get token');
const metadata = new Metadata();
metadata.add('language', language || 'pt-br');
return this.termsOfUseClient.getToken({ userId: user.user_id });
return this.termsOfUseClient.getToken({ userId: user.user_id }, metadata);
}
@Post('accept')
+5 -2
View File
@@ -10,6 +10,7 @@ import {
TermsOfUseAcceptRequest,
} from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/messages';
import { DucClient } from '../duc/client.config';
import { Metadata } from '@grpc/grpc-js';
@Injectable()
export class TermsOfUseClientService implements OnModuleInit {
@@ -31,8 +32,10 @@ export class TermsOfUseClientService implements OnModuleInit {
);
}
async getToken(data: TermsOfUseGetTokenRequest) {
return lastValueFrom(this.termsOfUseService.TermsOfUseGetToken(data));
async getToken(data: TermsOfUseGetTokenRequest, metadata: Metadata) {
return lastValueFrom(
this.termsOfUseService.TermsOfUseGetToken(data, metadata),
);
}
async accept(data: TermsOfUseAcceptRequest) {
+8 -5
View File
@@ -55,7 +55,10 @@ export class UserNoRoles extends OmitType(User, ['roles']) {}
export class UserNoRolesAndCustomer extends OmitType(UserNoRoles, [
'customer',
]) {}
export class UserByCustomer extends OmitType(User, ['customer']) {}
export class IUserByCustomer extends OmitType(User, ['customer']) {
@ApiPropertyOptional()
permissions?: string[];
}
export class CreateUserReq {
@ApiPropertyOptional()
@@ -111,11 +114,11 @@ export class UpdateUserReq {
export class UpdateUserRes {
@ApiProperty()
user: UserByCustomer;
user: IUserByCustomer;
}
export class GetAllUsersByCustomerIdRes {
@ApiProperty({ type: [UserByCustomer] })
users: UserByCustomer[];
@ApiProperty({ type: [IUserByCustomer] })
users: IUserByCustomer[];
@ApiProperty()
departments: string[];
@ApiProperty()
@@ -153,7 +156,7 @@ export class SetUserRolesReq {
export class SetUserRolesRes {
@ApiProperty()
user: UserByCustomer;
user: IUserByCustomer;
}
export class SearchUserRes extends GetAllUsersByCustomerIdRes {}
+17 -4
View File
@@ -21,7 +21,10 @@ import {
ApiTags,
} from '@nestjs/swagger';
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
import { RequireAllPermissions } from 'src/authentication/authentication.decorator';
import {
Authenticated,
RequireAllPermissions,
} from 'src/authentication/authentication.decorator';
import { PERMISSIONS_GROUPS } from 'src/authentication/permissions.enum';
import { RequestUser, User } from 'src/authentication/user.decorator';
import { GrpcToHttpExceptionFilter } from 'src/error/grpc-to-http-exception.filter';
@@ -42,10 +45,12 @@ import {
UnassignRoleToUserReq,
UpdateUserReq,
UpdateUserRes,
UserByCustomer,
IUserByCustomer,
} from './dtos/entities';
import { UsersService } from './users.service';
import { Metadata } from '@grpc/grpc-js';
import ErrorBuilder from 'src/utils/ErrorBuilder';
import ErrorCodes from 'src/utils/errorCodes';
// TODO GET de hierarquias e do PATCH em usuário
@ApiTags('Users')
@@ -56,6 +61,7 @@ import { Metadata } from '@grpc/grpc-js';
required: false,
description: 'Defaults to pt-br',
})
@Authenticated()
@UseFilters(GrpcToHttpExceptionFilter)
export class UsersController {
logger: DadosferaLogger;
@@ -119,9 +125,8 @@ export class UsersController {
}
@Get(':id')
@RequireAllPermissions(PERMISSIONS_GROUPS.USERS.permissions.ADMIN)
@ApiOkResponse({
type: UserByCustomer,
type: IUserByCustomer,
})
async findOneById(
@User() user: RequestUser,
@@ -130,6 +135,14 @@ export class UsersController {
) {
this.logger.info('findOneById', { user });
this.userService.setLanguage(language);
if (
id !== user.user_id &&
!user.permissions.includes(
PERMISSIONS_GROUPS.USERS.permissions.ADMIN.seqid,
)
) {
throw new ErrorBuilder(ErrorCodes.AUTH.FORBIDDEN);
}
return await this.userService.findOneById(id);
}
+16 -2
View File
@@ -18,6 +18,7 @@ import {
BatchCreateUserReq,
CreateUserReq,
Hierarchy,
IUserByCustomer,
SetUserRolesReq,
UpdateUserReq,
} from './dtos/entities';
@@ -77,11 +78,24 @@ export class UsersService implements OnModuleInit {
};
}
async findOneById(id: string) {
async findOneById(id: string): Promise<{ user: IUserByCustomer }> {
const { user } = await lastValueFrom(
this.usersClientService.UserFindOneById({ id }),
);
return { user: this.adjustUsersPayload([user])[0] };
const res: { user: IUserByCustomer } = {
user: this.adjustUsersPayload([user])[0],
};
const { permissions } = await lastValueFrom(
this.usersClientService.GetUserPermissions({ id }),
).catch((error) => {
this.logger.error('UsersService.findOneById - GetUserPermissions', {
error,
});
const permissions: string[] = [];
return { permissions };
});
res.user.permissions = permissions;
return res;
}
async createUser(req: CreateUserReq, meta?: Metadata) {
+17
View File
@@ -0,0 +1,17 @@
import {
SecretsManagerClient,
GetSecretValueCommand,
} from '@aws-sdk/client-secrets-manager';
export async function getSecreteFromSecreteManager(path: string) {
const secretsManagerClient = new SecretsManagerClient({});
const getSecretComand = new GetSecretValueCommand({
SecretId: `${path}`,
});
const res = await secretsManagerClient
.send(getSecretComand)
.catch(() => null);
return res?.SecretString;
}
+1 -1
View File
File diff suppressed because one or more lines are too long