mirror of
https://github.com/dadosfera/maestro.git
synced 2026-10-24 20:49:07 +00:00
Compare commits
29
Commits
+114
@@ -969,6 +969,41 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/users/download": {
|
||||||
|
"get": {
|
||||||
|
"operationId": "UsersController_downloadUsersInCsv",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "dadosfera-lang",
|
||||||
|
"in": "header",
|
||||||
|
"required": false,
|
||||||
|
"schema": {
|
||||||
|
"enum": [
|
||||||
|
"pt-br",
|
||||||
|
"en-us"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Users"
|
||||||
|
],
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"access-token": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"access-token": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"/users/hierarchies": {
|
"/users/hierarchies": {
|
||||||
"get": {
|
"get": {
|
||||||
"operationId": "UsersController_getAllHierarchies",
|
"operationId": "UsersController_getAllHierarchies",
|
||||||
@@ -3874,6 +3909,85 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/catalog/download": {
|
||||||
|
"get": {
|
||||||
|
"operationId": "CatalogController_dowloadAsserts",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "dadosfera-lang",
|
||||||
|
"in": "header",
|
||||||
|
"required": false,
|
||||||
|
"schema": {
|
||||||
|
"enum": [
|
||||||
|
"pt-br",
|
||||||
|
"en-us"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "size",
|
||||||
|
"required": false,
|
||||||
|
"in": "query",
|
||||||
|
"description": "Número de registros a ser retornado",
|
||||||
|
"schema": {
|
||||||
|
"minimum": 1,
|
||||||
|
"maximum": 10000,
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "page",
|
||||||
|
"required": false,
|
||||||
|
"in": "query",
|
||||||
|
"description": "Usado para paginação, em conjunto com `size`",
|
||||||
|
"schema": {
|
||||||
|
"minimum": 1,
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "sort_by",
|
||||||
|
"required": false,
|
||||||
|
"in": "query",
|
||||||
|
"description": "Campo do data asset para usar na ordenação. Padrão: `created_at` ",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "order",
|
||||||
|
"required": false,
|
||||||
|
"in": "query",
|
||||||
|
"description": "Tipo de ordenação - `asc`: crescente; `desc`: decrescente ",
|
||||||
|
"schema": {
|
||||||
|
"default": "asc",
|
||||||
|
"enum": [
|
||||||
|
"asc",
|
||||||
|
"desc"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Catalog"
|
||||||
|
],
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"access-token": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"access-token": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"/catalog/data-asset": {
|
"/catalog/data-asset": {
|
||||||
"get": {
|
"get": {
|
||||||
"operationId": "CatalogController_findByPipelineAndObject",
|
"operationId": "CatalogController_findByPipelineAndObject",
|
||||||
|
|||||||
Vendored
+1
@@ -14,6 +14,7 @@ declare global {
|
|||||||
AWS_REGION: string;
|
AWS_REGION: string;
|
||||||
OPEN_GROUP_ID: string;
|
OPEN_GROUP_ID: string;
|
||||||
OPEN_CUSTOMER_ID: string;
|
OPEN_CUSTOMER_ID: string;
|
||||||
|
DEDICATED_PROXY: string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ charts:
|
|||||||
values:
|
values:
|
||||||
- ../maestro/values.yaml
|
- ../maestro/values.yaml
|
||||||
set:
|
set:
|
||||||
|
- name: app_name
|
||||||
|
value: maestro
|
||||||
- name: maestro.duc_url
|
- name: maestro.duc_url
|
||||||
value: duc.dadosfera.ai
|
value: duc.dadosfera.ai
|
||||||
- name: hostname
|
- name: hostname
|
||||||
@@ -20,3 +22,32 @@ charts:
|
|||||||
value: c0afdcce-c5be-40d0-9d1d-2d271121f14a
|
value: c0afdcce-c5be-40d0-9d1d-2d271121f14a
|
||||||
- name: replicaCount
|
- name: replicaCount
|
||||||
value: 2
|
value: 2
|
||||||
|
|
||||||
|
- name: unimed-maestro
|
||||||
|
chart: ../maestro
|
||||||
|
values:
|
||||||
|
- ../maestro/values.yaml
|
||||||
|
set:
|
||||||
|
- name: app_name
|
||||||
|
value: maestro-unimed
|
||||||
|
- name: maestro.duc_url
|
||||||
|
value: duc.dadosfera.ai
|
||||||
|
- name: hostname
|
||||||
|
value: maestro-unimed.dadosfera.ai
|
||||||
|
- name: maestro.pi_factory_url
|
||||||
|
value: pi-factory.dadosfera.ai
|
||||||
|
- name: maestro.in_factory_url
|
||||||
|
value: in-factory.dadosfera.ai
|
||||||
|
- name: maestro.tr_factory_url
|
||||||
|
value: in-factory.dadosfera.ai
|
||||||
|
- name: maestro.open_customer_id
|
||||||
|
value: b3e3dfe5-b992-4586-a73c-c0b0c00f615d
|
||||||
|
- name: maestro.open_group_id
|
||||||
|
value: c0afdcce-c5be-40d0-9d1d-2d271121f14a
|
||||||
|
# Customer id
|
||||||
|
- name: maestro.dedicated_proxy
|
||||||
|
value: dea2c27f-0973-4588-a2e0-9e31b64c7ffd
|
||||||
|
- name: replicaCount
|
||||||
|
value: 1
|
||||||
|
- name: maestro.restricted_ip
|
||||||
|
value: "177.52.172.0/24,57.151.113.140/30"
|
||||||
|
|||||||
+31
-1
@@ -19,4 +19,34 @@ charts:
|
|||||||
- name: maestro.open_group_id
|
- name: maestro.open_group_id
|
||||||
value: e3f98a2f-7748-4981-8505-7695c8ca8218
|
value: e3f98a2f-7748-4981-8505-7695c8ca8218
|
||||||
- name: replicaCount
|
- name: replicaCount
|
||||||
value: 1
|
value: 1
|
||||||
|
|
||||||
|
# Environment to test Network Policies
|
||||||
|
- name: private-maestro
|
||||||
|
chart: ../maestro
|
||||||
|
values:
|
||||||
|
- ../maestro/values.yaml
|
||||||
|
set:
|
||||||
|
- name: app_name
|
||||||
|
value: maestro-private
|
||||||
|
- name: maestro.duc_url
|
||||||
|
value: duc.stg.dadosfera.ai
|
||||||
|
- name: hostname
|
||||||
|
value: private-maestro.stg.dadosfera.ai
|
||||||
|
- name: maestro.pi_factory_url
|
||||||
|
value: pi-factory.dadosfera.ai
|
||||||
|
- name: maestro.in_factory_url
|
||||||
|
value: in-factory.stg.dadosfera.ai
|
||||||
|
- name: maestro.tr_factory_url
|
||||||
|
value: in-factory.dadosfera.ai
|
||||||
|
- name: maestro.open_customer_id
|
||||||
|
value: b3e3dfe5-b992-4586-a73c-c0b0c00f615d
|
||||||
|
- name: maestro.open_group_id
|
||||||
|
value: e3f98a2f-7748-4981-8505-7695c8ca8218
|
||||||
|
# Customer id
|
||||||
|
- name: maestro.dedicated_proxy
|
||||||
|
value: 14d52fd4-d83d-4cdd-be34-bf11cc28b3bd
|
||||||
|
- name: replicaCount
|
||||||
|
value: 1
|
||||||
|
- name: maestro.restricted_ip
|
||||||
|
value: "57.151.113.140/30"
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: maestro
|
name: {{ .Values.app_name }}
|
||||||
namespace: applications
|
namespace: applications
|
||||||
labels:
|
labels:
|
||||||
app: maestro
|
app: {{ .Values.app_name }}
|
||||||
|
|
||||||
spec:
|
spec:
|
||||||
replicas: {{ .Values.replicaCount }}
|
replicas: {{ .Values.replicaCount }}
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app: maestro
|
app: {{ .Values.app_name }}
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
rollingUpdate:
|
rollingUpdate:
|
||||||
@@ -20,7 +20,7 @@ spec:
|
|||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
app: maestro
|
app: {{ .Values.app_name }}
|
||||||
|
|
||||||
spec:
|
spec:
|
||||||
imagePullSecrets:
|
imagePullSecrets:
|
||||||
@@ -100,6 +100,8 @@ spec:
|
|||||||
value: {{ .Values.maestro.open_customer_id }}
|
value: {{ .Values.maestro.open_customer_id }}
|
||||||
- name: OPEN_GROUP_ID
|
- name: OPEN_GROUP_ID
|
||||||
value: {{ .Values.maestro.open_group_id }}
|
value: {{ .Values.maestro.open_group_id }}
|
||||||
|
- name: DEDICATED_PROXY
|
||||||
|
value: {{ .Values.maestro.dedicated_proxy }}
|
||||||
- name: JWT_PRIVATE_KEY
|
- name: JWT_PRIVATE_KEY
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
@@ -108,15 +110,15 @@ spec:
|
|||||||
- name: AWS_ACCESS_KEY_ID
|
- name: AWS_ACCESS_KEY_ID
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: prd-maestro
|
name: prd-{{ .Values.app_name }}
|
||||||
key: AWS_ACCESS_KEY_ID
|
key: AWS_ACCESS_KEY_ID
|
||||||
- name: AWS_SECRET_ACCESS_KEY
|
- name: AWS_SECRET_ACCESS_KEY
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: prd-maestro
|
name: prd-{{ .Values.app_name }}
|
||||||
key: AWS_SECRET_ACCESS_KEY
|
key: AWS_SECRET_ACCESS_KEY
|
||||||
- name: AWS_DEFAULT_REGION
|
- name: AWS_DEFAULT_REGION
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: prd-maestro
|
name: prd-{{ .Values.app_name }}
|
||||||
key: AWS_DEFAULT_REGION
|
key: AWS_DEFAULT_REGION
|
||||||
|
|||||||
@@ -10,8 +10,12 @@ metadata:
|
|||||||
|
|
||||||
generation: 1
|
generation: 1
|
||||||
labels:
|
labels:
|
||||||
app: maestro
|
app: {{ .Values.app_name }}
|
||||||
|
{{- if .Values.maestro.dedicated_proxy}}
|
||||||
|
name: open-data-{{ .Values.app_name }}
|
||||||
|
{{- else }}
|
||||||
name: open-data
|
name: open-data
|
||||||
|
{{- end }}
|
||||||
namespace: applications
|
namespace: applications
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
ingressClassName: nginx
|
||||||
@@ -21,7 +25,7 @@ spec:
|
|||||||
paths:
|
paths:
|
||||||
- backend:
|
- backend:
|
||||||
service:
|
service:
|
||||||
name: maestro
|
name: {{ .Values.app_name }}
|
||||||
port:
|
port:
|
||||||
number: {{ .Values.ingress.port }}
|
number: {{ .Values.ingress.port }}
|
||||||
path: /open-data/sharing-ocean-data
|
path: /open-data/sharing-ocean-data
|
||||||
|
|||||||
@@ -3,14 +3,20 @@ kind: Ingress
|
|||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
nginx.ingress.kubernetes.io/proxy-body-size: "0"
|
nginx.ingress.kubernetes.io/proxy-body-size: "0"
|
||||||
|
nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
|
||||||
|
nginx.ingress.kubernetes.io/proxy-connect-timeout: "300"
|
||||||
|
nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
|
||||||
nginx.ingress.kubernetes.io/server-snippet: |
|
nginx.ingress.kubernetes.io/server-snippet: |
|
||||||
underscores_in_headers on;
|
underscores_in_headers on;
|
||||||
ignore_invalid_headers on;
|
ignore_invalid_headers on;
|
||||||
|
{{- if .Values.maestro.restricted_ip}}
|
||||||
|
nginx.ingress.kubernetes.io/whitelist-source-range: {{ .Values.maestro.restricted_ip }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
generation: 1
|
generation: 1
|
||||||
labels:
|
labels:
|
||||||
app: maestro
|
app: {{ .Values.app_name }}
|
||||||
name: maestro
|
name: {{ .Values.app_name }}
|
||||||
namespace: applications
|
namespace: applications
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
ingressClassName: nginx
|
||||||
@@ -20,7 +26,7 @@ spec:
|
|||||||
paths:
|
paths:
|
||||||
- backend:
|
- backend:
|
||||||
service:
|
service:
|
||||||
name: maestro
|
name: {{ .Values.app_name }}
|
||||||
port:
|
port:
|
||||||
number: {{ .Values.ingress.port }}
|
number: {{ .Values.ingress.port }}
|
||||||
path: /
|
path: /
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
apiVersion: external-secrets.io/v1beta1
|
apiVersion: external-secrets.io/v1beta1
|
||||||
kind: ExternalSecret
|
kind: ExternalSecret
|
||||||
metadata:
|
metadata:
|
||||||
name: prd-maestro
|
name: prd-{{ .Values.app_name }}
|
||||||
namespace: applications
|
namespace: applications
|
||||||
labels:
|
labels:
|
||||||
app: maestro
|
app: {{ .Values.app_name }}
|
||||||
spec:
|
spec:
|
||||||
refreshInterval: 1h
|
refreshInterval: 1h
|
||||||
secretStoreRef:
|
secretStoreRef:
|
||||||
name: secretsmanager-prd
|
name: secretsmanager-prd
|
||||||
kind: SecretStore
|
kind: SecretStore
|
||||||
target:
|
target:
|
||||||
name: prd-maestro
|
name: prd-{{ .Values.app_name }}
|
||||||
creationPolicy: Owner
|
creationPolicy: Owner
|
||||||
data:
|
data:
|
||||||
- secretKey: AWS_ACCESS_KEY_ID
|
- secretKey: AWS_ACCESS_KEY_ID
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: maestro
|
name: {{ .Values.app_name }}
|
||||||
namespace: applications
|
namespace: applications
|
||||||
labels:
|
labels:
|
||||||
app: maestro
|
app: {{ .Values.app_name }}
|
||||||
|
|
||||||
spec:
|
spec:
|
||||||
type: ClusterIP
|
type: ClusterIP
|
||||||
ports:
|
ports:
|
||||||
- name: maestro
|
- name: {{ .Values.app_name }}
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
port: {{ .Values.service.port }}
|
port: {{ .Values.service.port }}
|
||||||
targetPort: {{ .Values.service.targetPort }}
|
targetPort: {{ .Values.service.targetPort }}
|
||||||
selector:
|
selector:
|
||||||
app: maestro
|
app: {{ .Values.app_name }}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ image:
|
|||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
# Overrides the image tag whose default is the chart appVersion.
|
# Overrides the image tag whose default is the chart appVersion.
|
||||||
tag: 1.56.0
|
tag: 1.56.0
|
||||||
|
app_name: maestro
|
||||||
containerPort: 3333
|
containerPort: 3333
|
||||||
imagePullSecrets: "applications-secrets-ecr-auth-token-external-secret"
|
imagePullSecrets: "applications-secrets-ecr-auth-token-external-secret"
|
||||||
service:
|
service:
|
||||||
@@ -42,6 +43,8 @@ maestro:
|
|||||||
upload_file_agent_connection: cbc2f881-58c4-4d60-8003-0979b0b5b911
|
upload_file_agent_connection: cbc2f881-58c4-4d60-8003-0979b0b5b911
|
||||||
open_customer_id: f239718a-a271-4ef9-ae7e-02a2f0f3aa6e
|
open_customer_id: f239718a-a271-4ef9-ae7e-02a2f0f3aa6e
|
||||||
open_group_id: 401573bb-334f-44b2-b30e-88d4cea31ae9
|
open_group_id: 401573bb-334f-44b2-b30e-88d4cea31ae9
|
||||||
|
dedicated_proxy: ""
|
||||||
|
restricted_ip: ""
|
||||||
autoscaling:
|
autoscaling:
|
||||||
enabled: false
|
enabled: false
|
||||||
minReplicas: 1
|
minReplicas: 1
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
OnApplicationBootstrap,
|
OnApplicationBootstrap,
|
||||||
ExecutionContext,
|
ExecutionContext,
|
||||||
Inject,
|
Inject,
|
||||||
|
ForbiddenException,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { Reflector } from '@nestjs/core';
|
import { Reflector } from '@nestjs/core';
|
||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
@@ -113,6 +114,18 @@ export class AuthenticationGuard
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bloquear outros customer de usar o maestor dedicado
|
||||||
|
const DEDICATED_PROXY = process.env.DEDICATED_PROXY || '';
|
||||||
|
if (DEDICATED_PROXY !== '' && DEDICATED_PROXY !== accessTokenPayload.customer_id) {
|
||||||
|
throw new ErrorBuilder(ErrorCodes.AUTH.FORBIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bloquear o customer de acesso o maestro publico
|
||||||
|
// const hasNetworkPolicyModule = accessTokenPayload.customer_modules.includes('network-policy');
|
||||||
|
// if (hasNetworkPolicyModule && DEDICATED_PROXY === '') {
|
||||||
|
// throw new ForbiddenException();
|
||||||
|
// }
|
||||||
|
|
||||||
request.accessTokenPayload = accessTokenPayload;
|
request.accessTokenPayload = accessTokenPayload;
|
||||||
request.user = {
|
request.user = {
|
||||||
user_id: accessTokenPayload.user_id,
|
user_id: accessTokenPayload.user_id,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { NestFactory } from '@nestjs/core';
|
|||||||
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
||||||
import helmet from 'helmet';
|
import helmet from 'helmet';
|
||||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||||
|
import { json, urlencoded } from 'express';
|
||||||
|
|
||||||
import { AppModule } from './app.module';
|
import { AppModule } from './app.module';
|
||||||
import { writeFileSync } from 'fs';
|
import { writeFileSync } from 'fs';
|
||||||
@@ -25,6 +26,8 @@ async function bootstrap() {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
app.use(helmet());
|
app.use(helmet());
|
||||||
|
app.use('/catalog/register-dataset', json({ limit: '10mb' }));
|
||||||
|
app.use('/catalog/register-dataset', urlencoded({ extended: true, limit: '10mb' }));
|
||||||
configureSwagger(app);
|
configureSwagger(app);
|
||||||
await app.listen(3333);
|
await app.listen(3333);
|
||||||
if (process.env.KILL_AFTER_START) await app.close();
|
if (process.env.KILL_AFTER_START) await app.close();
|
||||||
|
|||||||
@@ -86,11 +86,9 @@ export class AuthController {
|
|||||||
async signIn(
|
async signIn(
|
||||||
@Body() { username, password, totp }: AuthSignInReq,
|
@Body() { username, password, totp }: AuthSignInReq,
|
||||||
@Language() language: LanguageEnum,
|
@Language() language: LanguageEnum,
|
||||||
@Headers('origin') origin = '',
|
|
||||||
): Promise<AuthSignInRes> {
|
): Promise<AuthSignInRes> {
|
||||||
this.logger.info('/auth - SignIn');
|
this.logger.info('/auth - SignIn');
|
||||||
const frontHost = origin.replace(/^https?:\/\//, '');
|
const metadata = PackTheMetadata({ language });
|
||||||
const metadata = PackTheMetadata({ language, custom_host: frontHost });
|
|
||||||
this.logger.info('metadata: ' + JSON.stringify(metadata.toJSON()));
|
this.logger.info('metadata: ' + JSON.stringify(metadata.toJSON()));
|
||||||
return this.authClient.signIn({ username, password, totp }, metadata);
|
return this.authClient.signIn({ username, password, totp }, metadata);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { OnModuleInit, Inject, Injectable } from '@nestjs/common';
|
import { OnModuleInit, Inject, Injectable, ForbiddenException } from '@nestjs/common';
|
||||||
import { ClientGrpc } from '@nestjs/microservices';
|
import { ClientGrpc } from '@nestjs/microservices';
|
||||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||||
import { lastValueFrom } from 'rxjs';
|
import { lastValueFrom } from 'rxjs';
|
||||||
@@ -17,6 +17,7 @@ import {
|
|||||||
AuthResetPasswordRequest,
|
AuthResetPasswordRequest,
|
||||||
AuthVerifyResetPasswordCodeRequest,
|
AuthVerifyResetPasswordCodeRequest,
|
||||||
AuthConfirmResetPasswordRequest,
|
AuthConfirmResetPasswordRequest,
|
||||||
|
AuthSignInResponse,
|
||||||
} from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/messages';
|
} from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/messages';
|
||||||
import { DucClient } from '../duc/client.config';
|
import { DucClient } from '../duc/client.config';
|
||||||
import { Metadata } from '@grpc/grpc-js';
|
import { Metadata } from '@grpc/grpc-js';
|
||||||
@@ -53,15 +54,49 @@ export class AuthClientService implements OnModuleInit {
|
|||||||
return lastValueFrom(this.authService.AuthSnowflakeSignIn(input));
|
return lastValueFrom(this.authService.AuthSnowflakeSignIn(input));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkDedicatedProxy({
|
||||||
|
customer
|
||||||
|
}: AuthSignInResponse) {
|
||||||
|
const DEDICATED_PROXY = process.env.DEDICATED_PROXY || '';
|
||||||
|
this.logger.info('SignIn - Setting customer ID for dedicated proxy: ' + DEDICATED_PROXY);
|
||||||
|
this.logger.info('Customer ID: ' + customer.id);
|
||||||
|
|
||||||
|
if (DEDICATED_PROXY !== '' && DEDICATED_PROXY !== customer.id) {
|
||||||
|
throw new ForbiddenException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bloquear o customer de acesso o maestro publico
|
||||||
|
this.logger.info('Check if customer have network policy: ' + customer.modules);
|
||||||
|
const hasNetworkPolicyModule = customer.modules.includes('network-policy');
|
||||||
|
if (hasNetworkPolicyModule && DEDICATED_PROXY === '') {
|
||||||
|
throw new ForbiddenException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async signIn(
|
async signIn(
|
||||||
{ username, password, totp }: AuthSignInRequest,
|
{ username, password, totp }: AuthSignInRequest,
|
||||||
metadata: Metadata,
|
metadata: Metadata,
|
||||||
) {
|
) {
|
||||||
this.logger.info('SignIn');
|
this.logger.info('SignIn');
|
||||||
|
|
||||||
return lastValueFrom(
|
let result: AuthSignInResponse;
|
||||||
this.authService.AuthSignIn({ username, password, totp }, metadata),
|
|
||||||
);
|
try {
|
||||||
|
result = await lastValueFrom(
|
||||||
|
this.authService.AuthSignIn({ username, password, totp }, metadata),
|
||||||
|
);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error('SignIn - Error during sign-in');
|
||||||
|
this.logger.error(error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.customer) {
|
||||||
|
this.checkDedicatedProxy(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
async refreshAccessToken(
|
async refreshAccessToken(
|
||||||
|
|||||||
@@ -117,6 +117,52 @@ export class CatalogController {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Get('/download')
|
||||||
|
@RequireSomePermission(
|
||||||
|
PERMISSIONS_GROUPS.CATALOG.permissions.GET,
|
||||||
|
PERMISSIONS_GROUPS.CATALOG.permissions.DATA_MANAGER,
|
||||||
|
)
|
||||||
|
async dowloadAsserts(
|
||||||
|
@User() user: RequestUser,
|
||||||
|
@Query() query: ICatalogAllRequest,
|
||||||
|
@Res() res: Response
|
||||||
|
) {
|
||||||
|
const { user_id, customer_name, customer_id, username, permissions } = user;
|
||||||
|
this.logger.info(`/catalog/download - searchCatalog`, {
|
||||||
|
user_id,
|
||||||
|
customer_name,
|
||||||
|
});
|
||||||
|
|
||||||
|
const is_data_manager = permissions.includes(
|
||||||
|
PERMISSIONS_GROUPS.CATALOG.permissions.DATA_MANAGER.seqid,
|
||||||
|
);
|
||||||
|
|
||||||
|
const roles = await this.catalogService.getUserRolesIds(user_id);
|
||||||
|
|
||||||
|
const metadata = PackTheMetadata({
|
||||||
|
user_id,
|
||||||
|
customer_id,
|
||||||
|
customer_name,
|
||||||
|
username,
|
||||||
|
roles,
|
||||||
|
is_data_manager,
|
||||||
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
file,
|
||||||
|
filename
|
||||||
|
} = await this.catalogService.downloadAssets(
|
||||||
|
query,
|
||||||
|
metadata,
|
||||||
|
customer_id,
|
||||||
|
);
|
||||||
|
|
||||||
|
res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
|
||||||
|
res.setHeader('Content-Type', 'text/csv');
|
||||||
|
|
||||||
|
res.end(file);
|
||||||
|
}
|
||||||
|
|
||||||
@ApiInternalOnlyEndpoint()
|
@ApiInternalOnlyEndpoint()
|
||||||
@Get('data-asset')
|
@Get('data-asset')
|
||||||
async findByPipelineAndObject(@User() user: RequestUser, @Query() query) {
|
async findByPipelineAndObject(@User() user: RequestUser, @Query() query) {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import { UsersService } from '../users/users.service';
|
|||||||
import { RolesService } from '../roles/roles.service';
|
import { RolesService } from '../roles/roles.service';
|
||||||
import { Metadata } from '@grpc/grpc-js';
|
import { Metadata } from '@grpc/grpc-js';
|
||||||
import {
|
import {
|
||||||
|
AssetReporter,
|
||||||
BatchRemoveRlsRulesRequest,
|
BatchRemoveRlsRulesRequest,
|
||||||
IUpdateDataRequest,
|
IUpdateDataRequest,
|
||||||
TriggerCatalogReq,
|
TriggerCatalogReq,
|
||||||
@@ -240,6 +241,34 @@ class CatalogService implements OnModuleInit {
|
|||||||
return { data_assets: response, total };
|
return { data_assets: response, total };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async downloadAssets(
|
||||||
|
query: Record<string, any>,
|
||||||
|
metadata: Metadata,
|
||||||
|
customer_id: string,
|
||||||
|
) {
|
||||||
|
const data = await this.searchDataAssets(query, metadata, customer_id);
|
||||||
|
|
||||||
|
const formatData = data.data_assets.map(asset => ({
|
||||||
|
id: asset.id,
|
||||||
|
display_name: asset.display_name,
|
||||||
|
data_asset_type: asset.data_asset_type,
|
||||||
|
created_at: asset.created_at,
|
||||||
|
tags: '[' + asset.tags.join(', ') + ']'
|
||||||
|
}))
|
||||||
|
|
||||||
|
const parser = ParserBuilder.build<AssetReporter>('csv');
|
||||||
|
|
||||||
|
const file = await parser.parse(formatData);
|
||||||
|
|
||||||
|
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
||||||
|
const filename = `dadosfera_assets_${timestamp}.csv`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
file,
|
||||||
|
filename
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async getOneDataAsset(data: {
|
async getOneDataAsset(data: {
|
||||||
id: string;
|
id: string;
|
||||||
customer_id: string;
|
customer_id: string;
|
||||||
|
|||||||
@@ -320,3 +320,11 @@ export class BatchRemoveRlsRulesRequest {
|
|||||||
@ApiPropertyOptional()
|
@ApiPropertyOptional()
|
||||||
id_rls?: string;
|
id_rls?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type AssetReporter = {
|
||||||
|
id: string;
|
||||||
|
display_name: string;
|
||||||
|
data_asset_type: string;
|
||||||
|
created_at: string;
|
||||||
|
tags: string;
|
||||||
|
}
|
||||||
|
|||||||
@@ -45,11 +45,11 @@ export class OpenDataController {
|
|||||||
) {
|
) {
|
||||||
this.logger.info('createUser for open data' + JSON.stringify(request.headers));
|
this.logger.info('createUser for open data' + JSON.stringify(request.headers));
|
||||||
|
|
||||||
const corslist = ["https://devsbm.dadosfera.io", "https://sharingoceandata.com"];
|
// const corslist = ["https://devsbm.dadosfera.io", "https://sharingoceandata.com"];
|
||||||
if (!corslist.includes(origin)) {
|
// if (!corslist.includes(origin)) {
|
||||||
this.logger.info('block request by cors list: '+ origin);
|
// this.logger.info('block request by cors list: '+ origin);
|
||||||
throw new ForbiddenException();
|
// throw new ForbiddenException();
|
||||||
}
|
// }
|
||||||
|
|
||||||
const OPENDATA_CUSTOMER_ID = process.env.OPEN_CUSTOMER_ID;
|
const OPENDATA_CUSTOMER_ID = process.env.OPEN_CUSTOMER_ID;
|
||||||
const OPENDATA_GROUP_ID = process.env.OPEN_GROUP_ID;
|
const OPENDATA_GROUP_ID = process.env.OPEN_GROUP_ID;
|
||||||
|
|||||||
@@ -174,3 +174,14 @@ export class GetAllDepartmentsRes {
|
|||||||
@ApiProperty()
|
@ApiProperty()
|
||||||
departments: string[];
|
departments: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface UserReporter {
|
||||||
|
name: string;
|
||||||
|
email: string;
|
||||||
|
mfaStatus: string;
|
||||||
|
status: string;
|
||||||
|
lastLogin: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
Post,
|
Post,
|
||||||
Put,
|
Put,
|
||||||
Query,
|
Query,
|
||||||
|
Res,
|
||||||
UseFilters,
|
UseFilters,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import {
|
import {
|
||||||
@@ -24,6 +25,7 @@ import { PERMISSIONS_GROUPS } from 'src/authentication/permissions.enum';
|
|||||||
import {
|
import {
|
||||||
Authenticated,
|
Authenticated,
|
||||||
RequireAllPermissions,
|
RequireAllPermissions,
|
||||||
|
RequireSomePermission,
|
||||||
} from 'src/decorators/authentication.decorator';
|
} from 'src/decorators/authentication.decorator';
|
||||||
import { Language } from 'src/decorators/language.decorator';
|
import { Language } from 'src/decorators/language.decorator';
|
||||||
import { ApiInternalOnlyController } from 'src/decorators/swagger.decorator';
|
import { ApiInternalOnlyController } from 'src/decorators/swagger.decorator';
|
||||||
@@ -52,6 +54,7 @@ import {
|
|||||||
UpdateUserRes,
|
UpdateUserRes,
|
||||||
} from './dtos/entities';
|
} from './dtos/entities';
|
||||||
import { UsersService } from './users.service';
|
import { UsersService } from './users.service';
|
||||||
|
import { Response } from 'express';
|
||||||
|
|
||||||
@ApiInternalOnlyController()
|
@ApiInternalOnlyController()
|
||||||
@ApiTags('Users')
|
@ApiTags('Users')
|
||||||
@@ -80,6 +83,26 @@ export class UsersController {
|
|||||||
return await this.userService.findAllUsersByCustomerId(user.customer_id);
|
return await this.userService.findAllUsersByCustomerId(user.customer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Get('/download')
|
||||||
|
@RequireSomePermission(PERMISSIONS_GROUPS.USERS.permissions.ADMIN)
|
||||||
|
async downloadUsersInCsv(
|
||||||
|
@User() user: RequestUser,
|
||||||
|
@Language() language: LanguageEnum,
|
||||||
|
@Res() res: Response
|
||||||
|
) {
|
||||||
|
this.logger.info('downloadUsersInCsv');
|
||||||
|
this.userService.setLanguage(language);
|
||||||
|
const {
|
||||||
|
file,
|
||||||
|
filename
|
||||||
|
} = await this.userService.downloadUsersInCsv(user.customer_id);
|
||||||
|
|
||||||
|
res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
|
||||||
|
res.setHeader('Content-Type', 'text/csv');
|
||||||
|
|
||||||
|
res.end(file);
|
||||||
|
}
|
||||||
|
|
||||||
@Get('hierarchies')
|
@Get('hierarchies')
|
||||||
@RequireAllPermissions(PERMISSIONS_GROUPS.USERS.permissions.ADMIN)
|
@RequireAllPermissions(PERMISSIONS_GROUPS.USERS.permissions.ADMIN)
|
||||||
@ApiOkResponse({ type: GetAllHierarchiesRes })
|
@ApiOkResponse({ type: GetAllHierarchiesRes })
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import {
|
|||||||
IUserByCustomer,
|
IUserByCustomer,
|
||||||
SetUserRolesReq,
|
SetUserRolesReq,
|
||||||
UpdateUserReq,
|
UpdateUserReq,
|
||||||
|
UserReporter,
|
||||||
} from './dtos/entities';
|
} from './dtos/entities';
|
||||||
import { RolesService } from '../roles/roles.service';
|
import { RolesService } from '../roles/roles.service';
|
||||||
import { HIERARCHIES } from './hierarchies';
|
import { HIERARCHIES } from './hierarchies';
|
||||||
@@ -29,6 +30,7 @@ import { UserByCustomer } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces
|
|||||||
import { EnrichErrorCode } from 'src/utils/ErrorBuilder';
|
import { EnrichErrorCode } from 'src/utils/ErrorBuilder';
|
||||||
import { DucClient } from '../duc/client.config';
|
import { DucClient } from '../duc/client.config';
|
||||||
import { Metadata } from '@grpc/grpc-js';
|
import { Metadata } from '@grpc/grpc-js';
|
||||||
|
import { ParserBuilder } from 'src/utils/FileParser/parser.builder';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UsersService implements OnModuleInit {
|
export class UsersService implements OnModuleInit {
|
||||||
@@ -78,6 +80,34 @@ export class UsersService implements OnModuleInit {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async downloadUsersInCsv(customerId: string) {
|
||||||
|
const { users } = await lastValueFrom(
|
||||||
|
this.usersClientService.UserFindAllByCustomerId({ customerId }),
|
||||||
|
);
|
||||||
|
|
||||||
|
const formatUsers: UserReporter[] = users.map(user => ({
|
||||||
|
createdAt: user.createdAt,
|
||||||
|
email: user.email,
|
||||||
|
lastLogin: user.lastLogin,
|
||||||
|
mfaStatus: user.mfaStatus,
|
||||||
|
name: user.name,
|
||||||
|
status: user.status,
|
||||||
|
updatedAt: user.updatedAt
|
||||||
|
}))
|
||||||
|
|
||||||
|
const parser = ParserBuilder.build<UserReporter>('csv');
|
||||||
|
|
||||||
|
const file = await parser.parse(formatUsers);
|
||||||
|
|
||||||
|
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
||||||
|
const filename = `dadosfera_users_${timestamp}.csv`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
file,
|
||||||
|
filename
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async findOneById(id: string): Promise<{ user: IUserByCustomer }> {
|
async findOneById(id: string): Promise<{ user: IUserByCustomer }> {
|
||||||
const { user } = await lastValueFrom(
|
const { user } = await lastValueFrom(
|
||||||
this.usersClientService.UserFindOneById({ id }),
|
this.usersClientService.UserFindOneById({ id }),
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export class PDFParser<T> implements Parser<T> {
|
|||||||
const html = await this.htmlParser.parse(data);
|
const html = await this.htmlParser.parse(data);
|
||||||
await page.setContent(html, {
|
await page.setContent(html, {
|
||||||
waitUntil: 'networkidle0',
|
waitUntil: 'networkidle0',
|
||||||
timeout: 30000,
|
timeout: 90000,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Configurações adicionais para garantir um PDF válido
|
// Configurações adicionais para garantir um PDF válido
|
||||||
@@ -43,7 +43,7 @@ export class PDFParser<T> implements Parser<T> {
|
|||||||
pageRanges: '',
|
pageRanges: '',
|
||||||
tagged: true,
|
tagged: true,
|
||||||
outline: false,
|
outline: false,
|
||||||
timeout: 30000,
|
timeout: 90000,
|
||||||
});
|
});
|
||||||
|
|
||||||
await browser.close();
|
await browser.close();
|
||||||
|
|||||||
Reference in New Issue
Block a user