Compare commits

...
42 Commits
Author SHA1 Message Date
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
Victor Radael c1b213c34c Merge pull request #146 from dadosfera/feat/openSearchCatalog
Feat/open search catalog
2022-10-04 18:34:50 -03:00
Victor Radael a6c58eb82d FIX: unitary permitting 2022-10-04 18:29:39 -03:00
Victor Radael b756cb5a1e FIX: unitary permitting 2022-10-04 18:26:49 -03:00
Victor Radael 46cafc2d50 FIX: unitary permitting 2022-10-04 18:26:27 -03:00
Victor Radael a087775e3a Merge pull request #145 from dadosfera/feat/openSearchCatalog
Feat/open search catalog
2022-10-04 17:55:07 -03:00
Victor Radael 69305610ff FIX: unitary permitting 2022-10-04 17:41:01 -03:00
Victor Radael 69008a9ffb FIX: unitary permitting 2022-10-04 17:19:09 -03:00
Victor Radael 687b4e40e1 FIX: unitary permitting 2022-10-04 16:49:41 -03:00
Victor Radael d56544568b FIX: unitary permitting 2022-10-04 16:47:42 -03:00
Gabriel Amorim cad1e4b3de Merge pull request #144 from dadosfera/fix/delete-connection-permission
FIX: delete connection permission
2022-10-04 15:40:14 -03:00
Gabriel Rosa b311a84bde FIX: delete route reimplemented 2022-10-04 15:22:43 -03:00
Gabriel Rosa 28280dca8d FIX: Delete connections permission 2022-10-04 14:46:52 -03:00
Victor Radael 63fbfa6b52 FIX: unitary permitting 2022-10-04 13:20:34 -03:00
Victor Radael 2b03c4e4a9 FIX: Individual data assets permissions 2022-10-04 11:10:40 -03:00
Victor Radael 18c3c9c58c FIX: Permission data manager 2022-10-03 18:07:38 -03:00
Victor Radael 450c82446e Merge pull request #143 from dadosfera/fix/dadoferademo
FIX: unkown error get user by id
2022-10-03 16:56:55 -03:00
Victor Radael beb27a0f60 FIX: unkown error get user by id 2022-10-03 16:52:42 -03:00
Victor Radael 166c45728f FIX: unkown error get user by id 2022-10-03 16:48:12 -03:00
Victor Radael d0f5da0270 Merge remote-tracking branch 'origin' into feat/openSearchCatalog 2022-10-03 16:46:08 -03:00
Victor Radael dade8d59e5 FIX: Get user by id unkown error 2022-10-03 16:45:50 -03:00
Victor Radael fe261667f8 FIX: Change Revoke Permissions 2022-10-03 10:43:17 -03:00
Victor Radael 722bb1ec7c FIX: Data asset sharing 2022-09-30 18:38:45 -03:00
Victor Radael a371db355b FIX: Data asset sharing 2022-09-30 18:22:29 -03:00
Victor Radael 1ff135c0d7 FIX: Data asset sharing 2022-09-30 18:13:23 -03:00
26 changed files with 550 additions and 128 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.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
View File
@@ -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",
+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 {}
+20 -11
View File
@@ -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',
},
},
},
},
+69 -6
View File
@@ -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;
}
}
+2
View File
@@ -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],
+133 -33
View File
@@ -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,
},
];
+20 -20
View File
@@ -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(
+162 -15
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) {
@@ -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;
+2
View File
@@ -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;
}
+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 {}
+2 -2
View File
@@ -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 {
+1 -2
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;
@@ -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,
+1 -1
View File
@@ -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);
+5 -2
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';
@@ -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',
+1
View File
@@ -8,6 +8,7 @@ interface IMetadata {
language?: string;
details?: string;
roles?: string[];
is_data_manager?: boolean;
}
export function PackTheMetadata(info: IMetadata): 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