mirror of
https://github.com/dadosfera/maestro.git
synced 2026-09-01 04:08:16 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43d181a429 | ||
|
|
a72fe1b60d | ||
|
|
b52a1227b1 | ||
|
|
31478ed61d | ||
|
|
79b1ba910e | ||
|
|
7fd929915b | ||
|
|
e4b27c5f76 | ||
|
|
92e449d6d3 | ||
|
|
5073b2e188 | ||
|
|
8a11eda24d | ||
|
|
9d732d4a48 | ||
|
|
5fa10a939b | ||
|
|
4be3ffe3a2 | ||
|
|
8af9c638ef | ||
|
|
97d6f914cc | ||
|
|
9ad2e3770e | ||
|
|
ea2cc8809f | ||
|
|
410e190e7c | ||
|
|
c1b213c34c | ||
|
|
a6c58eb82d | ||
|
|
b756cb5a1e | ||
|
|
46cafc2d50 | ||
|
|
a087775e3a | ||
|
|
69305610ff | ||
|
|
69008a9ffb | ||
|
|
687b4e40e1 | ||
|
|
d56544568b | ||
|
|
cad1e4b3de | ||
|
|
b311a84bde | ||
|
|
28280dca8d | ||
|
|
63fbfa6b52 | ||
|
|
2b03c4e4a9 | ||
|
|
18c3c9c58c | ||
|
|
450c82446e | ||
|
|
beb27a0f60 | ||
|
|
166c45728f | ||
|
|
d0f5da0270 | ||
|
|
dade8d59e5 | ||
|
|
fe261667f8 | ||
|
|
722bb1ec7c | ||
|
|
a371db355b | ||
|
|
1ff135c0d7 |
Generated
+7
-7
@@ -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.7",
|
||||
"@dadosfera/protospack-v2": "3.18.10",
|
||||
"@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.7",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.18.7.tgz",
|
||||
"integrity": "sha512-MloW230CUyK+g+HFkSv1OuaJNT5mfEGRh7tpZjjKxO2Qxm4eKkmI9uh/cNXCDzUpRBFXzBJ+5w12bxw2UnMRSw==",
|
||||
"version": "3.18.10",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.18.10.tgz",
|
||||
"integrity": "sha512-0bRUvo4p7cJJOL+B0hVTiSDaA2MGtirPkFVQW4lUfzsyY5vrsbAkMz6R3iPdPPwFSxGn5LwidHGkP3/l7hlEpA==",
|
||||
"dependencies": {
|
||||
"@grpc/grpc-js": "^1.6.7",
|
||||
"rxjs": "^7.5.5",
|
||||
@@ -12306,9 +12306,9 @@
|
||||
}
|
||||
},
|
||||
"@dadosfera/protospack-v2": {
|
||||
"version": "3.18.7",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.18.7.tgz",
|
||||
"integrity": "sha512-MloW230CUyK+g+HFkSv1OuaJNT5mfEGRh7tpZjjKxO2Qxm4eKkmI9uh/cNXCDzUpRBFXzBJ+5w12bxw2UnMRSw==",
|
||||
"version": "3.18.10",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.18.10.tgz",
|
||||
"integrity": "sha512-0bRUvo4p7cJJOL+B0hVTiSDaA2MGtirPkFVQW4lUfzsyY5vrsbAkMz6R3iPdPPwFSxGn5LwidHGkP3/l7hlEpA==",
|
||||
"requires": {
|
||||
"@grpc/grpc-js": "^1.6.7",
|
||||
"rxjs": "^7.5.5",
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-secrets-manager": "^3.112.0",
|
||||
"@dadosfera/dadosfera-logs": "^1.0.0-beta.4",
|
||||
"@dadosfera/protospack-v2": "3.18.7",
|
||||
"@dadosfera/protospack-v2": "3.18.10",
|
||||
"@grpc/grpc-js": "^1.6.7",
|
||||
"@grpc/proto-loader": "^0.6.13",
|
||||
"@nestjs/common": "^8.4.7",
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -125,17 +125,16 @@ export const PERMISSIONS_GROUPS = {
|
||||
'es-es': 'Crear Source',
|
||||
},
|
||||
},
|
||||
//TODO descomentar quando tiver ok o DELETE de conexões
|
||||
// DELETE: {
|
||||
// seqid: 38,
|
||||
// claim: 'connection:delete',
|
||||
// usage: PermissionUsages.PUBLIC,
|
||||
// name: {
|
||||
// 'pt-br': 'Excluir Fonte',
|
||||
// 'en-us': 'Remove Source',
|
||||
// 'es-s': 'Eliminar Source',
|
||||
// },
|
||||
// },
|
||||
DELETE: {
|
||||
seqid: 38,
|
||||
claim: 'connection:delete',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'Excluir Fonte',
|
||||
'en-us': 'Remove Source',
|
||||
'es-s': 'Eliminar Source',
|
||||
},
|
||||
},
|
||||
UPDATE: {
|
||||
seqid: 39,
|
||||
claim: 'connection:update',
|
||||
@@ -326,6 +325,16 @@ export const PERMISSIONS_GROUPS = {
|
||||
'es-es': 'Eliminar atributos',
|
||||
},
|
||||
},
|
||||
DATA_MANAGER: {
|
||||
seqid: 42,
|
||||
claim: 'catalog:data_manager',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
name: {
|
||||
'pt-br': 'Vizualizar todos os recursos do catálogo.',
|
||||
'en-us': 'View all data assets.',
|
||||
'es-es': 'Ver todos los activos de datos',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
@@ -2,7 +2,9 @@ import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
ForbiddenException,
|
||||
Get,
|
||||
HttpException,
|
||||
Inject,
|
||||
Param,
|
||||
Post,
|
||||
@@ -10,7 +12,10 @@ import {
|
||||
Query,
|
||||
} 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';
|
||||
@@ -19,7 +24,9 @@ import { RequestUser, User } from 'src/authentication/user.decorator';
|
||||
|
||||
@ApiTags('Catalog')
|
||||
@Controller('catalog')
|
||||
@Authenticated()
|
||||
@AuthenticateCondition((req, user) => {
|
||||
if (req.path.includes('/manage_permissions/')) return true;
|
||||
let action;
|
||||
|
||||
switch (req.method) {
|
||||
@@ -93,12 +100,16 @@ export class CatalogController {
|
||||
|
||||
@Get('all')
|
||||
async catalogAll(@User() user: RequestUser, @Body() body, @Query() params) {
|
||||
const { user_id, customer_name, customer_id, username } = user;
|
||||
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,
|
||||
});
|
||||
|
||||
const is_data_manager = permissions.includes(
|
||||
PERMISSIONS_GROUPS.CATALOG.permissions.DATA_MANAGER.seqid,
|
||||
);
|
||||
|
||||
const roles = await this.catalogService.getUserRolesIds(user_id);
|
||||
|
||||
const metadata = PackTheMetadata({
|
||||
@@ -107,11 +118,13 @@ export class CatalogController {
|
||||
customer_name,
|
||||
username,
|
||||
roles,
|
||||
is_data_manager,
|
||||
});
|
||||
|
||||
const res = await this.catalogService.getAllOpenSearchDataAssets(
|
||||
params,
|
||||
metadata,
|
||||
customer_id,
|
||||
);
|
||||
|
||||
return res.data_assets;
|
||||
@@ -166,7 +179,11 @@ export class CatalogController {
|
||||
customer: body.info.customer,
|
||||
});
|
||||
|
||||
const { username, user_id, customer_id, customer_name } = user;
|
||||
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,
|
||||
@@ -174,13 +191,35 @@ export class CatalogController {
|
||||
customer_name,
|
||||
});
|
||||
|
||||
const user_roles = await this.catalogService.getUserRolesIds(user_id);
|
||||
|
||||
const res = await this.catalogService.getOneDashboardMetabase(
|
||||
id,
|
||||
body,
|
||||
metadata,
|
||||
customer_id,
|
||||
);
|
||||
|
||||
return res;
|
||||
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 dashboard.p_roles;
|
||||
delete dashboard.p_users;
|
||||
return res;
|
||||
}
|
||||
|
||||
throw new HttpException(
|
||||
'You do not have permission to access this data asset.',
|
||||
403,
|
||||
);
|
||||
}
|
||||
|
||||
@Get('table-metadata')
|
||||
@@ -193,7 +232,11 @@ export class CatalogController {
|
||||
user: user.user_id,
|
||||
customer: user.customer_name,
|
||||
});
|
||||
const { user_id, customer_name, customer_id } = user;
|
||||
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,
|
||||
@@ -204,12 +247,32 @@ export class CatalogController {
|
||||
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 table.p_roles;
|
||||
delete table.p_users;
|
||||
return res;
|
||||
}
|
||||
|
||||
throw new ForbiddenException(
|
||||
'You do not have permission to access this data asset.',
|
||||
);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import { CatalogClientConfiguration } from './catalog-client';
|
||||
import { ClientsModule } from '@nestjs/microservices';
|
||||
import { PipelinesModule as OldPipelineModule } from 'src/modules/pipelines/pipelines.module';
|
||||
import { UsersModule } from '../users/users.module';
|
||||
import { RolesModule } from '../roles/roles.module';
|
||||
|
||||
const client = new CatalogClientConfiguration();
|
||||
|
||||
@@ -16,6 +17,7 @@ const client = new CatalogClientConfiguration();
|
||||
ClientsModule.register([client.providerOptions]),
|
||||
OldPipelineModule,
|
||||
UsersModule,
|
||||
RolesModule,
|
||||
],
|
||||
controllers: [CatalogController],
|
||||
providers: [CatalogService, DadosferaLogger],
|
||||
|
||||
@@ -14,6 +14,7 @@ import axios from 'axios';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import { CatalogClientConfiguration } from './catalog-client';
|
||||
import { UsersService } from '../users/users.service';
|
||||
import { RolesService } from '../roles/roles.service';
|
||||
|
||||
class CatalogService implements OnModuleInit {
|
||||
catalogReadService: ReadService.CatalogReadServices;
|
||||
@@ -25,6 +26,7 @@ class CatalogService implements OnModuleInit {
|
||||
@Inject(CatalogClientConfiguration.name)
|
||||
private readonly grpcClient: ClientGrpc,
|
||||
private readonly userService: UsersService,
|
||||
private readonly roleService: RolesService,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
@@ -110,36 +112,97 @@ class CatalogService implements OnModuleInit {
|
||||
}
|
||||
|
||||
async getUserRolesIds(userId: string) {
|
||||
const result = await this.userService.findOneById(userId);
|
||||
const result = await this.userService.findOneById(userId).catch(() => null);
|
||||
|
||||
const roles_ids = result.user.roles.map((role) => role.id);
|
||||
|
||||
return roles_ids;
|
||||
}
|
||||
|
||||
async getUsernamesAndRolesByCustomerId(customerId: string) {
|
||||
const resultUsers = await this.userService.findAllUsersByCustomerId(
|
||||
customerId,
|
||||
);
|
||||
const resultRoles = await this.roleService.roleSearch(
|
||||
{},
|
||||
{ customer_id: customerId },
|
||||
);
|
||||
|
||||
const customer_users = resultUsers.users.map((user) => {
|
||||
return {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
};
|
||||
});
|
||||
|
||||
const customer_roles = resultRoles.roles.map((role) => {
|
||||
return {
|
||||
id: role.id,
|
||||
name: role.name,
|
||||
};
|
||||
});
|
||||
|
||||
return [customer_users, customer_roles];
|
||||
}
|
||||
|
||||
async getAllOpenSearchDataAssets(
|
||||
data: Messages.GetAllDataAssetsRequest,
|
||||
metadata,
|
||||
customer_id,
|
||||
) {
|
||||
this.logger.info('CatalogService - getAllOpenSearchDashboard');
|
||||
|
||||
const response = await lastValueFrom(
|
||||
this.catalogReadService.GetAllDataAssets(data, metadata),
|
||||
)
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return JSON.parse(res.data_assets);
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
).catch((err) => {
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 404,
|
||||
);
|
||||
});
|
||||
|
||||
const data_assets = JSON.parse(response.data_assets);
|
||||
|
||||
const [customer_users, customer_roles] =
|
||||
await this.getUsernamesAndRolesByCustomerId(customer_id);
|
||||
|
||||
for (const asset of data_assets.tables) {
|
||||
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;
|
||||
|
||||
const roles = [];
|
||||
const users = [];
|
||||
|
||||
for (const role of customer_roles) {
|
||||
for (const role_id of asset.roles) {
|
||||
if (role.id === role_id) roles.push(role);
|
||||
}
|
||||
}
|
||||
|
||||
for (const user of customer_users) {
|
||||
for (const user_id of asset.users) {
|
||||
if (user.id === user_id) users.push(user);
|
||||
}
|
||||
}
|
||||
|
||||
Object.assign(asset, {
|
||||
...asset,
|
||||
owner,
|
||||
roles,
|
||||
users,
|
||||
});
|
||||
}
|
||||
|
||||
for (const asset of response.tables) {
|
||||
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)
|
||||
? await this.userService.findOneById(asset.owner).catch(() => null)
|
||||
: null;
|
||||
|
||||
const owner = result !== null ? result.user.username : null;
|
||||
@@ -147,22 +210,10 @@ class CatalogService implements OnModuleInit {
|
||||
Object.assign(asset, { ...asset, owner });
|
||||
}
|
||||
|
||||
for (const asset of response.dashboards) {
|
||||
const condition =
|
||||
asset.owner && !asset.owner.includes('@') ? true : false;
|
||||
const result = condition
|
||||
? await this.userService.findOneById(asset.owner)
|
||||
: null;
|
||||
|
||||
const owner = result !== null ? result.user.username : null;
|
||||
|
||||
Object.assign(asset, { ...asset, owner });
|
||||
}
|
||||
|
||||
return { data_assets: response };
|
||||
return { data_assets };
|
||||
}
|
||||
|
||||
async getOneDashboardMetabase(id, body, metadata) {
|
||||
async getOneDashboardMetabase(id, body, metadata, customer_id) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(
|
||||
`${nimbusUrl}/api/catalog/dashboard-metabase/${id}`,
|
||||
@@ -176,18 +227,43 @@ class CatalogService implements OnModuleInit {
|
||||
);
|
||||
const opensearchTable = JSON.parse(data_asset);
|
||||
|
||||
const result = opensearchTable.user_id
|
||||
? await this.userService.findOneById(opensearchTable.owner)
|
||||
const result = opensearchTable.owner
|
||||
? await this.userService
|
||||
.findOneById(opensearchTable.owner)
|
||||
.catch(() => null)
|
||||
: null;
|
||||
|
||||
const owner = result !== null ? result.user.username : null;
|
||||
|
||||
return {
|
||||
...data,
|
||||
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(data.dashboard, {
|
||||
tags: opensearchTable.tags,
|
||||
description: opensearchTable.description || null,
|
||||
p_roles: opensearchTable.roles,
|
||||
p_users: opensearchTable.users,
|
||||
roles,
|
||||
users,
|
||||
owner,
|
||||
};
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async getAllTableMetadata(body) {
|
||||
@@ -198,7 +274,7 @@ class CatalogService implements OnModuleInit {
|
||||
return data;
|
||||
}
|
||||
|
||||
async getOneTableMetadata(body, params, metadata) {
|
||||
async getOneTableMetadata(body, params, metadata, customer_id) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(
|
||||
`${nimbusUrl}/api/catalog/table-metadata/`,
|
||||
@@ -212,17 +288,41 @@ class CatalogService implements OnModuleInit {
|
||||
),
|
||||
);
|
||||
const opensearchTable = JSON.parse(data_asset);
|
||||
const result = opensearchTable.user_id
|
||||
? await this.userService.findOneById(opensearchTable.owner)
|
||||
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,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -105,29 +105,29 @@ export class ConnectionController {
|
||||
return response;
|
||||
}
|
||||
|
||||
// @Delete('/:id')
|
||||
// @RequireAllPermissions(connectionPermissions.DELETE)
|
||||
// async deleteConnection(
|
||||
// @User() user: RequestUser,
|
||||
// @Param('id') id: string,
|
||||
// ): Promise<ConnectionRes> {
|
||||
// this.logger.info('/connections - Delete Connection');
|
||||
@Delete('/:id')
|
||||
@RequireAllPermissions(connectionPermissions.DELETE)
|
||||
async deleteConnection(
|
||||
@User() user: RequestUser,
|
||||
@Param('id') id: string,
|
||||
): Promise<ConnectionRes> {
|
||||
this.logger.info('/connections - Delete Connection');
|
||||
|
||||
// const { user_id, customer_id, customer_name, username } = user;
|
||||
// const metadata = PackTheMetadata({
|
||||
// user_id,
|
||||
// customer_id,
|
||||
// customer_name,
|
||||
// username,
|
||||
// });
|
||||
const { user_id, customer_id, customer_name, username } = user;
|
||||
const metadata = PackTheMetadata({
|
||||
user_id,
|
||||
customer_id,
|
||||
customer_name,
|
||||
username,
|
||||
});
|
||||
|
||||
// const response: any = await this.clientService.deleteConnection({
|
||||
// body: { id },
|
||||
// metadata,
|
||||
// });
|
||||
const response: any = await this.clientService.deleteConnection({
|
||||
body: { id },
|
||||
metadata,
|
||||
});
|
||||
|
||||
// return response;
|
||||
// }
|
||||
return response;
|
||||
}
|
||||
|
||||
@Get()
|
||||
async getAllConnections(
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -5,7 +5,9 @@ import { ConnectionClientService } from '../connection/client.service';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import DadosferaLogger from '@dadosfera/dadosfera-logs/dist';
|
||||
import { PackTheMetadata } from 'src/utils/ PackTheMetadata';
|
||||
import { Authenticated } from 'src/authentication/authentication.decorator';
|
||||
@ApiTags('oauth')
|
||||
@Authenticated()
|
||||
@Controller('oauth')
|
||||
export class OauthController {
|
||||
redirectUrl: string;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -36,7 +36,6 @@ export class PermissionsController {
|
||||
|
||||
@Get()
|
||||
@ApiOkResponse({ type: GetPublicPermissionsRes })
|
||||
@RequireAllPermissions(PERMISSIONS_GROUPS.USERS.permissions.ADMIN)
|
||||
getPublicPermissions(
|
||||
@User() user: RequestUser,
|
||||
@Headers('dadosfera-lang') language,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -103,14 +103,9 @@ 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],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -149,13 +144,6 @@ 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;
|
||||
}
|
||||
|
||||
@@ -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 {}
|
||||
@@ -36,9 +36,9 @@ export enum TrueOrFalseEnum {
|
||||
}
|
||||
export class GetRolesByCustomerReq {
|
||||
@ApiPropertyOptional()
|
||||
permissionId: string[];
|
||||
permissionId?: string[];
|
||||
@ApiPropertyOptional({ enum: TrueOrFalseEnum })
|
||||
getUsers: TrueOrFalseEnum;
|
||||
getUsers?: TrueOrFalseEnum;
|
||||
}
|
||||
|
||||
export class GetRolesByCustomerRes {
|
||||
|
||||
@@ -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;
|
||||
@@ -69,7 +69,6 @@ export class RolesController {
|
||||
|
||||
@Get()
|
||||
@ApiOkResponse({ type: GetRolesByCustomerRes })
|
||||
@RequireAllPermissions(PERMISSIONS_GROUPS.USERS.permissions.ADMIN)
|
||||
async searchRoles(
|
||||
@User() user: RequestUser,
|
||||
@Query() filters: GetRolesByCustomerReq,
|
||||
|
||||
@@ -72,7 +72,7 @@ export class RolesService {
|
||||
|
||||
async roleSearch(
|
||||
filters: GetRolesByCustomerReq,
|
||||
{ customer_id, access_token }: RequestUser,
|
||||
{ customer_id, access_token }: any,
|
||||
) {
|
||||
const meta = new Metadata();
|
||||
meta.add('access_token', access_token);
|
||||
|
||||
@@ -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';
|
||||
@@ -56,6 +59,7 @@ import { Metadata } from '@grpc/grpc-js';
|
||||
required: false,
|
||||
description: 'Defaults to pt-br',
|
||||
})
|
||||
@Authenticated()
|
||||
@UseFilters(GrpcToHttpExceptionFilter)
|
||||
export class UsersController {
|
||||
logger: DadosferaLogger;
|
||||
@@ -69,7 +73,6 @@ export class UsersController {
|
||||
}
|
||||
|
||||
@Get()
|
||||
@RequireAllPermissions(PERMISSIONS_GROUPS.USERS.permissions.ADMIN)
|
||||
@ApiOkResponse({
|
||||
type: GetAllUsersByCustomerIdRes,
|
||||
description: 'List of users of a customer',
|
||||
|
||||
@@ -8,6 +8,7 @@ interface IMetadata {
|
||||
language?: string;
|
||||
details?: string;
|
||||
roles?: string[];
|
||||
is_data_manager?: boolean;
|
||||
}
|
||||
|
||||
export function PackTheMetadata(info: IMetadata): Metadata {
|
||||
|
||||
@@ -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
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user