Merge branch 'main' into feat/oauth-login

This commit is contained in:
Gabriel Rosa
2023-02-09 15:21:05 -03:00
11 changed files with 109 additions and 44 deletions
+1
View File
@@ -299,3 +299,4 @@ Some technologies used in this project:
## ⚙️ Back-end Architecture
The architecture can be found at [this link](https://sites.google.com/dadosfera.ai/wikidoproduto/time/back-end).
+18 -1
View File
@@ -2919,7 +2919,16 @@
"/catalog/data-asset/{id}": {
"get": {
"operationId": "CatalogController_getDataAsset",
"parameters": [],
"parameters": [
{
"name": "shared",
"required": true,
"in": "query",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": ""
@@ -5976,6 +5985,14 @@
},
"embed": {
"$ref": "#/components/schemas/EmbedObject"
},
"share_type": {
"type": "string",
"enum": [
"none",
"public",
"private"
]
}
},
"required": [
+43 -1
View File
@@ -336,6 +336,16 @@ export const PERMISSIONS_GROUPS = {
'es-es': 'Gestor de catálogos. Puede ver y editar todos los activos.',
},
},
EMBED_ANALYTICS: {
seqid: 44,
claim: 'catalog:embed',
usage: PermissionUsages.INTERNAL,
name: {
'pt-br': 'Acessar Módulo de Incorporação de Ativos',
'en-us': 'Access Embedding analytics Module',
'es-es': 'Acceder al Módulo de Incorporación de Activos',
},
},
},
},
@@ -556,7 +566,34 @@ export const PERMISSIONS_GROUPS = {
},
},
};
export interface DadosferaModule {
name: string;
description: string;
key: string;
permissionSeqId: number;
}
export const DADOSFERA_MODULES: Array<DadosferaModule> = [
{
name: 'Intelligence Module',
description: 'Orchest Module',
key: 'intelligence',
permissionSeqId: PERMISSIONS_GROUPS.ANALYZE.permissions.INTELLIGENCE.seqid,
},
{
name: 'Proccessing Module',
description: 'Proccessing Module',
key: 'process',
permissionSeqId:
PERMISSIONS_GROUPS.PROCESS.permissions.TRANSFORMATION.seqid,
},
{
name: 'Embedded Analytics',
description: 'Embedded Analytics Module',
key: 'embedded-analytics',
permissionSeqId:
PERMISSIONS_GROUPS.PROCESS.permissions.TRANSFORMATION.seqid,
},
];
// traverses the object searching for duplicate seqids or claims (executes at runtime)
let nextAvailableSeqid = 0;
const seqids = Object.values(PERMISSIONS_GROUPS).flatMap((namespace) =>
@@ -576,4 +613,9 @@ Object.values(PERMISSIONS_GROUPS).map((namespace) =>
}),
);
DADOSFERA_MODULES.map((m) => m.key).forEach((m, i, arr) => {
if (arr.indexOf(m) !== i)
throw new Error(`DADOSFERA_MODULES[${i}] does not have a unique key`);
});
logger.log(`next available seqid ${nextAvailableSeqid + 1}`);
+27 -27
View File
@@ -1,11 +1,14 @@
import {
BadRequestException,
Body,
Controller,
Delete,
ForbiddenException,
Get,
Headers,
HttpException,
Inject,
NotFoundException,
Param,
Post,
Put,
@@ -98,7 +101,7 @@ export class CatalogController {
});
if (!pipeline || !object) {
throw new HttpException('Query params not provided', 400);
throw new BadRequestException('Query params not provided');
}
const is_data_manager = permissions.includes(
@@ -136,9 +139,8 @@ export class CatalogController {
return { data_asset };
}
throw new HttpException(
throw new ForbiddenException(
'You do not have permission to access this data asset.',
403,
);
}
@@ -172,12 +174,12 @@ export class CatalogController {
)
async getDataAsset(
@User() user: RequestUser,
@Headers() headers,
@Param('id') id,
@Query('shared') shared?: 'true',
) {
const { username, user_id, customer_id, customer_name, permissions } = user;
this.logger.info(`/catalog - ON GET ONE DASHBOARD METABASE ROUTE`, {
this.logger.info(`GET /data-asset/${id}`, {
username,
customer_name,
});
@@ -200,25 +202,24 @@ export class CatalogController {
id,
metadata,
});
has_permission =
is_data_manager ||
data_asset?.owner === username ||
(user_roles as Array<any>).some((r) => data_asset.p_roles.includes(r)) ||
data_asset.p_users.includes(user_id);
if (
shared === 'true' &&
(data_asset.share_type === undefined || data_asset.share_type === 'none')
)
throw new NotFoundException();
if (!has_permission)
throw new ForbiddenException(
'You do not have permission to access this data asset.',
);
delete data_asset.p_roles;
delete data_asset.p_users;
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,
);
return { data_asset };
}
@Get('data-asset/rls/:id')
@@ -271,9 +272,8 @@ export class CatalogController {
return { data_asset };
}
throw new HttpException(
throw new ForbiddenException(
'You do not have permission to access this data asset.',
403,
);
}
@@ -376,7 +376,7 @@ export class CatalogController {
async updateDataAsset(
@User() user: RequestUser,
@Headers('Dadosfera-Lang') language,
@Param('id') id,
@Param('id') data_asset_id,
@Body() body: IUpdateDataRequest,
): Promise<IOneDataAsset> {
const { customer_id, customer_name, user_id, username } = user;
@@ -390,7 +390,7 @@ export class CatalogController {
const result = await this.catalogService.updateOneDataAsset({
body,
data_asset_id: id,
data_asset_id,
customer_id,
metadata,
});
+7
View File
@@ -1,6 +1,11 @@
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { CreateDataAssetRequest } from '@dadosfera/protospack-v2/dist/lib/Catalog/interfaces/messages';
export enum DataAssetShareType {
none = 'none',
public = 'public',
private = 'private',
}
export class EmbedObject {
@ApiProperty()
url: string;
@@ -135,6 +140,8 @@ export class IUpdateDataRequest {
tags: string[];
@ApiPropertyOptional()
embed: EmbedObject;
@ApiPropertyOptional({ enum: DataAssetShareType })
share_type: DataAssetShareType;
}
export class ICreateDataAsset implements CreateDataAssetRequest {
@ApiProperty()
+3 -4
View File
@@ -9,6 +9,8 @@ import {
ProtoPaths,
} from '@dadosfera/protospack-v2/dist/lib/Duc';
const isLocalConnection = !!process.env.DUC_URL?.includes('0.0.0.0');
export class DucClient {
public name = 'DucClient';
@@ -17,10 +19,7 @@ export class DucClient {
options: {
url: process.env.DUC_URL,
package: [ProtoPackages.WritePackage, ProtoPackages.ReadPackage],
credentials:
process.env.LOCAL_ENV || process.env.ENV === 'local'
? undefined
: credentials.createSsl(),
credentials: isLocalConnection ? undefined : credentials.createSsl(),
protoPath: [ProtoPaths.WriteFilePath, ProtoPaths.ReadFilePath],
loader: {
keepCase: true,
+3 -5
View File
@@ -2,10 +2,11 @@ import { Input } from '@dadosfera/protospack-v2';
import { credentials } from '@grpc/grpc-js';
import {
ClientProviderOptions,
GrpcOptions,
Transport,
type GrpcOptions,
} from '@nestjs/microservices';
const isLocalConnection = !!process.env.INFACTORY_URL?.includes('0.0.0.0');
export class InputsGrpcClient {
public readonly name = 'InputsGrpcClient';
private config: GrpcOptions = {
@@ -16,10 +17,7 @@ export class InputsGrpcClient {
Input.ProtoPackages.WritePackage,
Input.ProtoPackages.ReadPackage,
],
credentials:
process.env.LOCAL_ENV || process.env.ENV === 'local'
? undefined
: credentials.createSsl(),
credentials: isLocalConnection ? undefined : credentials.createSsl(),
protoPath: [
Input.ProtoPaths.WriteFilePath,
Input.ProtoPaths.ReadFilePath,
+2 -2
View File
@@ -1,5 +1,5 @@
import { Module } from '@nestjs/common';
import { getSecreteFromSecreteManager } from 'src/utils/SecretManager';
import { getSecretFromSecretsManager } from 'src/utils/SecretManager';
import { MixpanelController } from './mixpanel.controller';
@Module({
@@ -7,7 +7,7 @@ import { MixpanelController } from './mixpanel.controller';
providers: [
{
provide: 'MIXPANEL_TOKEN',
useValue: getSecreteFromSecreteManager(
useValue: getSecretFromSecretsManager(
`${process.env.ENV}/root/mixpanel_token`,
),
},
@@ -44,7 +44,8 @@ export class FacebookStrategy extends PassportStrategy(Strategy) {
req,
'application',
);
options.scope = 'ads_read ads_management';
options.scope =
'pages_show_list ads_read pages_read_engagement ads_management';
super.authenticate(req, options);
}
}
@@ -2,7 +2,7 @@ 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 { getSecretFromSecretsManager } from 'src/utils/SecretManager';
import { INote } from './dtos';
@ApiTags('Productboard')
@@ -18,7 +18,7 @@ export class ProductboardController {
: username + `@${customer_name}.default`;
const path = process.env.PB_TOKEN_PATH;
const token = await getSecreteFromSecreteManager(path);
const token = await getSecretFromSecretsManager(path);
const response = await axios
.post(
+1 -1
View File
@@ -3,7 +3,7 @@ import {
GetSecretValueCommand,
} from '@aws-sdk/client-secrets-manager';
export async function getSecreteFromSecreteManager(path: string) {
export async function getSecretFromSecretsManager(path: string) {
const secretsManagerClient = new SecretsManagerClient({});
const getSecretComand = new GetSecretValueCommand({