mirror of
https://github.com/dadosfera/maestro.git
synced 2026-08-31 19:58:21 +00:00
Merge branch 'main' into feat/oauth-login
This commit is contained in:
@@ -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
@@ -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": [
|
||||
|
||||
@@ -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}`);
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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({
|
||||
|
||||
Reference in New Issue
Block a user