mirror of
https://github.com/dadosfera/maestro.git
synced 2026-08-31 19:58:21 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
526a3bddcd | ||
|
|
45108d3019 | ||
|
|
ef6d8594a3 | ||
|
|
ac73c0b046 | ||
|
|
5a30bf08b2 | ||
|
|
62b4eb709e | ||
|
|
b37a18d1da | ||
|
|
379bac704f | ||
|
|
9178530a21 | ||
|
|
667d3f874d | ||
|
|
11f1df5537 | ||
|
|
e3b02571c8 | ||
|
|
979a12aa7f | ||
|
|
7646d7a3c5 | ||
|
|
8f0e851a88 | ||
|
|
6e6d03f302 | ||
|
|
3d5ce59b52 | ||
|
|
1c63271f64 | ||
|
|
31a51c20aa | ||
|
|
62730eb969 | ||
|
|
5a2c760bab | ||
|
|
28b4f3ac4b | ||
|
|
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 | ||
|
|
0360711ab4 | ||
|
|
b6ec2a83b2 | ||
|
|
812dc0c735 | ||
|
|
11715dd528 | ||
|
|
be476c1a6d | ||
|
|
a8414f780a | ||
|
|
1da61a4c13 | ||
|
|
7e8f5c49b5 | ||
|
|
96a485afd1 | ||
|
|
e3c203d673 | ||
|
|
d7da68241e | ||
|
|
5d924f8a92 | ||
|
|
f9b4ddd070 | ||
|
|
c0e0732b7e | ||
|
|
37ea7c2f4d | ||
|
|
d42584fcfc | ||
|
|
a28781423c | ||
|
|
8c638610c7 | ||
|
|
55ff485fd0 | ||
|
|
4877fab945 | ||
|
|
e724ef5ccc | ||
|
|
9dc96416e8 | ||
|
|
49663c4115 | ||
|
|
c16664c7f9 | ||
|
|
7245942707 | ||
|
|
c29cf5aee1 | ||
|
|
d96658c9cd | ||
|
|
cbd736b87d | ||
|
|
e4e6d95f8a | ||
|
|
a8e13c01d2 | ||
|
|
cdf2ce3cc2 | ||
|
|
c3877657ef | ||
|
|
3d39affc61 | ||
|
|
5d045b675c | ||
|
|
bb61990f6e | ||
|
|
80442c509a | ||
|
|
8551239038 | ||
|
|
4cf7c6e17b | ||
|
|
88c9c36eb0 | ||
|
|
4b317778f7 | ||
|
|
2eea9787cd | ||
|
|
c1ab5d152f | ||
|
|
8798f5d54e | ||
|
|
1da733b5bc | ||
|
|
930c8bc037 | ||
|
|
0913741500 | ||
|
|
3e9d0063ae | ||
|
|
2bc0fe1e9e | ||
|
|
f0fb6e6b4a | ||
|
|
74c27d9637 | ||
|
|
216c83d7fa | ||
|
|
08e66eeb1e | ||
|
|
cf3fd90787 | ||
|
|
bb1decb08f | ||
|
|
642cb0e70b | ||
|
|
0acf759e84 | ||
|
|
7bbb87a54a | ||
|
|
69af7ba626 | ||
|
|
0b14221d5a | ||
|
|
16bddf3d40 | ||
|
|
fb6ea7ba14 | ||
|
|
83d649a210 | ||
|
|
319fc80bfe | ||
|
|
35172681ce | ||
|
|
35db24dc59 | ||
|
|
ad9c1fc40c | ||
|
|
4660751023 | ||
|
|
25cf13923b | ||
|
|
d724c1644b | ||
|
|
c64529a37c | ||
|
|
8b06f0b12c | ||
|
|
311a4e4b93 | ||
|
|
6f8985baa7 | ||
|
|
11cb5a61da | ||
|
|
35c0520750 | ||
|
|
8c6ec8b1b9 | ||
|
|
77db6f3771 | ||
|
|
952a76e905 | ||
|
|
2ec62dae45 | ||
|
|
0d431a816b | ||
|
|
932e7413bd | ||
|
|
5cb83ee679 | ||
|
|
dcd558bd58 | ||
|
|
01e74473c0 | ||
|
|
d0c15fe290 | ||
|
|
b9d07e3677 | ||
|
|
2c8ed40bc6 | ||
|
|
46d9fd8446 | ||
|
|
1ca7e647d3 | ||
|
|
469f165cba | ||
|
|
203a161879 | ||
|
|
31e9a07489 | ||
|
|
e24925036d | ||
|
|
53f8f6986f | ||
|
|
5e0a422b35 | ||
|
|
8294b5591b | ||
|
|
01d41a4586 | ||
|
|
b8afdcf87d | ||
|
|
fa216053c2 | ||
|
|
e9a4a77eae | ||
|
|
fe041262eb | ||
|
|
7ef0ff1502 | ||
|
|
d8c55def7e | ||
|
|
dfcc3dcb53 | ||
|
|
080c8fc52a | ||
|
|
ecf0b1de51 | ||
|
|
2248dbe5a3 | ||
|
|
f5ec6661ff | ||
|
|
0deee0ef9c | ||
|
|
85f79f14cd | ||
|
|
01bdf134ca | ||
|
|
10a89632b5 | ||
|
|
24d8f832fa | ||
|
|
8efe3d26f8 | ||
|
|
6d21f29005 | ||
|
|
e526180902 | ||
|
|
be37eb0321 | ||
|
|
8c85172554 | ||
|
|
61296555fe | ||
|
|
5b6673a367 | ||
|
|
2968647e73 | ||
|
|
a1a55d645a | ||
|
|
b7748970cd | ||
|
|
8fb487435a | ||
|
|
e94ace09d0 | ||
|
|
c713b65979 | ||
|
|
195fdae0e6 | ||
|
|
0f079a7b22 | ||
|
|
93b44e8249 | ||
|
|
e18dc21670 | ||
|
|
ae443b5b03 | ||
|
|
3bfcc7a412 | ||
|
|
09e3b3fd33 | ||
|
|
6b7500136f | ||
|
|
7fa903fa1c | ||
|
|
19c35f5cc4 | ||
|
|
7b8b1bd8e0 | ||
|
|
5cc2d704ea | ||
|
|
d09bf96e6f | ||
|
|
0759f66144 | ||
|
|
8bd5bf1526 | ||
|
|
9772e18332 | ||
|
|
6f0f93d80d | ||
|
|
4b6d30859c | ||
|
|
5b4b1ae55e | ||
|
|
00dacfdbb9 | ||
|
|
7671567c8c | ||
|
|
64a8110649 | ||
|
|
4cbeea8281 | ||
|
|
adf9c11358 | ||
|
|
033752789a | ||
|
|
71617612b9 | ||
|
|
6219d61fe1 | ||
|
|
2fd51804fc | ||
|
|
874a3aa3a0 | ||
|
|
a9f68b87ca | ||
|
|
6807b3e1a9 | ||
|
|
5f17a7106f | ||
|
|
0a0ecb20bb | ||
|
|
35abb24ea7 | ||
|
|
372fc74bcb | ||
|
|
626f785994 | ||
|
|
f88f559b70 | ||
|
|
3981751ac0 | ||
|
|
61752a547f | ||
|
|
3356f306b3 | ||
|
|
6dd894e11b | ||
|
|
7a1b5c7dbf | ||
|
|
afc187d01a | ||
|
|
d0cd62cd3c | ||
|
|
acd4dafc57 | ||
|
|
d8ce82793d | ||
|
|
117704cd8c | ||
|
|
430e09c159 | ||
|
|
fa11df5684 | ||
|
|
e9b85537d7 | ||
|
|
17060332fd | ||
|
|
fde6d0a74c | ||
|
|
0ca6ed8636 | ||
|
|
7c5cf3f541 | ||
|
|
54f4331bcc | ||
|
|
2f006c607c | ||
|
|
9fbbfc2064 | ||
|
|
ba12d45bf7 | ||
|
|
ec418b00e7 | ||
|
|
89a02a4e8a | ||
|
|
cbee264182 | ||
|
|
2514245a44 | ||
|
|
0761c42041 | ||
|
|
688bf49f3b | ||
|
|
a1cdad42ab | ||
|
|
7546e6100d | ||
|
|
7cf178db42 | ||
|
|
2673e75f81 | ||
|
|
6382939e1e | ||
|
|
3bea2e4cda | ||
|
|
d9a7555d01 | ||
|
|
5122dbde85 | ||
|
|
4e6883a404 | ||
|
|
dcb3094890 | ||
|
|
c8e4e90100 | ||
|
|
09cff9fa15 | ||
|
|
79b624cea6 | ||
|
|
5356334258 | ||
|
|
5f6e4e88a5 | ||
|
|
32ab834834 | ||
|
|
ebbfe0abff | ||
|
|
4fb24d5b5c | ||
|
|
d76a2b4ab8 | ||
|
|
047737eadd | ||
|
|
00687dc84e | ||
|
|
61a1939c02 | ||
|
|
43cec9b6fa | ||
|
|
97214280bc | ||
|
|
e20ae71672 | ||
|
|
97b6047cf1 | ||
|
|
9c6d2b499a | ||
|
|
0de4a72388 | ||
|
|
f65f1d01ce | ||
|
|
6161865f1a | ||
|
|
d28684a9d0 | ||
|
|
f43c270c33 | ||
|
|
b0ccb39f2c | ||
|
|
54c2a41466 | ||
|
|
037f5cfec0 | ||
|
|
22631478b9 | ||
|
|
9f900882cb | ||
|
|
a24abed9ed | ||
|
|
b04a38bcc0 | ||
|
|
349ae780a7 | ||
|
|
60fb2ee7cb | ||
|
|
67706c5fc3 | ||
|
|
0fa4dcb933 | ||
|
|
04284e1feb | ||
|
|
3e7581e20c | ||
|
|
c61c37b268 | ||
|
|
5ce8099c25 | ||
|
|
9cdb0a5d38 | ||
|
|
57f47d3b2e | ||
|
|
4ab955a7a1 | ||
|
|
1ca3694b75 | ||
|
|
a6a35c507a | ||
|
|
cfcb8c1c42 | ||
|
|
a55da8e20f | ||
|
|
82310c6314 | ||
|
|
52f9d06ad0 | ||
|
|
a83f91a720 | ||
|
|
ccef7628f9 | ||
|
|
a5e424c854 | ||
|
|
339432df16 | ||
|
|
7dfa10d5ee | ||
|
|
c87ceec77b | ||
|
|
071c524a2e | ||
|
|
1de4eedd38 | ||
|
|
29276d6070 | ||
|
|
344a251de1 | ||
|
|
3b95032554 | ||
|
|
a0089b5d5d | ||
|
|
1b620b6fb0 | ||
|
|
1eb76d4b1c | ||
|
|
314bc5a562 | ||
|
|
d01b0357ed | ||
|
|
de57bfed1e | ||
|
|
14cfc46492 | ||
|
|
9d10e58b1b | ||
|
|
6dec2c1e56 | ||
|
|
23a65d18a6 | ||
|
|
d5cd562860 | ||
|
|
f5064420a7 | ||
|
|
bb5befb2f6 | ||
|
|
398360fadb | ||
|
|
13072978f5 | ||
|
|
b9612609d9 | ||
|
|
e7b37629a1 | ||
|
|
5b6994b247 | ||
|
|
039f837914 | ||
|
|
83dcc7942c | ||
|
|
5c079bb4f5 | ||
|
|
730fab8ed1 | ||
|
|
04e1e1ff2b | ||
|
|
d309c20cbf | ||
|
|
4cff593695 | ||
|
|
03d42df3fd | ||
|
|
ea04f59e04 | ||
|
|
d1961a9710 | ||
|
|
358dd6a15a | ||
|
|
395db05b05 | ||
|
|
2d69e6db70 | ||
|
|
9514134db1 | ||
|
|
0c69cebca1 | ||
|
|
9791b8bdb0 | ||
|
|
6803ab3420 | ||
|
|
6aa7be98d2 | ||
|
|
f5665557c9 | ||
|
|
4356adea65 | ||
|
|
8d23eaeea2 |
@@ -134,3 +134,73 @@ jobs:
|
||||
run: |
|
||||
docker system prune --volumes -a -f
|
||||
docker system df
|
||||
api_docs:
|
||||
needs: [extract_environment, semantic_release, deploy]
|
||||
runs-on:
|
||||
[self-hosted, '${{ needs.extract_environment.outputs.environment }}']
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Extract Docs PageId
|
||||
env:
|
||||
ENV: ${{ needs.extract_environment.outputs.environment }}
|
||||
DEV_DOCS_PAGE_ID: ${{ secrets.DEV_DOCS_PAGE_ID }}
|
||||
STG_DOCS_PAGE_ID: ${{ secrets.STG_DOCS_PAGE_ID }}
|
||||
PRD_DOCS_PAGE_ID: ${{ secrets.PRD_DOCS_PAGE_ID }}
|
||||
shell: bash
|
||||
run: |
|
||||
if [ $ENV == "dev" ]; then
|
||||
echo "##[set-output name=result;]$(echo $DEV_DOCS_PAGE_ID)"
|
||||
elif [ $ENV == "stg" ]; then
|
||||
echo "##[set-output name=result;]$(echo $STG_DOCS_PAGE_ID)"
|
||||
elif [ $ENV == "prd" ]; then
|
||||
echo "##[set-output name=result;]$(echo $PRD_DOCS_PAGE_ID)"
|
||||
fi
|
||||
id: extract_docs_page_id
|
||||
|
||||
- name: Extract Docs BlockId
|
||||
env:
|
||||
ENV: ${{ needs.extract_environment.outputs.environment }}
|
||||
DEV_DOCS_BLOCK_ID: ${{ secrets.DEV_DOCS_BLOCK_ID }}
|
||||
STG_DOCS_BLOCK_ID: ${{ secrets.STG_DOCS_BLOCK_ID }}
|
||||
PRD_DOCS_BLOCK_ID: ${{ secrets.PRD_DOCS_BLOCK_ID }}
|
||||
shell: bash
|
||||
run: |
|
||||
if [ $ENV == "dev" ]; then
|
||||
echo "##[set-output name=result;]$(echo $DEV_DOCS_BLOCK_ID)"
|
||||
elif [ $ENV == "stg" ]; then
|
||||
echo "##[set-output name=result;]$(echo $STG_DOCS_BLOCK_ID)"
|
||||
elif [ $ENV == "prd" ]; then
|
||||
echo "##[set-output name=result;]$(echo $PRD_DOCS_BLOCK_ID)"
|
||||
fi
|
||||
id: extract_docs_block_id
|
||||
|
||||
- name: Generate API docs
|
||||
env:
|
||||
ENV: ${{ needs.extract_environment.outputs.environment }}
|
||||
DOCS_URL: ${{ secrets.DOCS_URL }}
|
||||
DOCS_API_TOKEN: ${{ secrets.DOCS_API_TOKEN }}
|
||||
DOCS_PAGE_ID: ${{ steps.extract_docs_page_id.outputs.result }}
|
||||
DOCS_BLOCK_ID: ${{ steps.extract_docs_block_id.outputs.result }}
|
||||
continue-on-error: true
|
||||
run: |
|
||||
SWAGGER=`cat swagger.txt`
|
||||
curl --request POST \
|
||||
--url $DOCS_URL \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data @<(cat <<EOF
|
||||
{
|
||||
"service": "$DOCS_API_TOKEN",
|
||||
"pageId": "$DOCS_PAGE_ID",
|
||||
"blockId": "$DOCS_BLOCK_ID",
|
||||
"schema": $SWAGGER
|
||||
}
|
||||
EOF
|
||||
)
|
||||
- name: Cleanup Docker's Leftovers
|
||||
if: always()
|
||||
continue-on-error: true
|
||||
run: |
|
||||
docker system prune
|
||||
docker rmi -f $(docker images -aq)
|
||||
|
||||
@@ -11,30 +11,18 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install Docker Compose
|
||||
run: |
|
||||
python3 -m pip install docker-compose --upgrade
|
||||
|
||||
- name: Build
|
||||
env:
|
||||
ENV: test
|
||||
IMAGE_TAG: test
|
||||
APP_NAME: ${{ github.event.repository.name }}
|
||||
run: |
|
||||
export ENV=test
|
||||
export IMAGE_TAG=test
|
||||
export ACCOUNT_ID=test
|
||||
docker-compose -f build.docker-compose.yml build
|
||||
docker build -t $APP_NAME --target test .
|
||||
|
||||
- name: Run Test
|
||||
env:
|
||||
ENV: test
|
||||
IMAGE_TAG: test
|
||||
ACCOUNT_ID: test
|
||||
APP_NAME: ${{ github.event.repository.name }}
|
||||
run: |
|
||||
export ENV=test
|
||||
export IMAGE_TAG=test
|
||||
docker-compose -f build.docker-compose.yml run --rm --entrypoint="npm run test" $APP_NAME
|
||||
docker run --rm --entrypoint="npm" $APP_NAME run test
|
||||
|
||||
- name: Remove Docker's Trash
|
||||
if: always()
|
||||
|
||||
+1
-1
@@ -37,4 +37,4 @@ lerna-debug.log*
|
||||
# Ignore .env files
|
||||
*.env
|
||||
|
||||
.env
|
||||
.env
|
||||
|
||||
Vendored
+22
@@ -0,0 +1,22 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Debug NestJs",
|
||||
"request": "launch",
|
||||
"runtimeArgs": [
|
||||
"run",
|
||||
"start:debug"
|
||||
],
|
||||
"runtimeExecutable": "npm",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"type": "node",
|
||||
"console": "integratedTerminal"
|
||||
}
|
||||
]
|
||||
}
|
||||
+12
-7
@@ -1,16 +1,21 @@
|
||||
# install all dependencies
|
||||
FROM node:18.3.0-alpine3.15 as packages
|
||||
WORKDIR /packages
|
||||
COPY package.json .
|
||||
COPY package-lock.json .
|
||||
RUN apk update \
|
||||
&& apk add --no-cache aws-cli \
|
||||
&& aws codeartifact login --tool npm --repository dadosfera-npm --domain dadosfera --domain-owner 611330257153 --region us-east-1 \
|
||||
WORKDIR /app
|
||||
COPY package.json package-lock.json ./
|
||||
RUN apk add --no-cache aws-cli \
|
||||
&& aws codeartifact login --tool npm --namespace @dadosfera --repository dadosfera-npm --domain dadosfera --domain-owner 611330257153 --region us-east-1 \
|
||||
&& npm install
|
||||
|
||||
# unit test specific build
|
||||
FROM node:18.3.0-alpine3.15 as test
|
||||
WORKDIR /app
|
||||
COPY --from=packages /app/node_modules ./node_modules
|
||||
COPY . ./
|
||||
|
||||
FROM node:18.3.0-alpine3.15
|
||||
WORKDIR /app
|
||||
COPY . /app/
|
||||
COPY --from=packages /packages/node_modules /app/node_modules
|
||||
COPY --from=packages /app/node_modules ./node_modules
|
||||
RUN npm run build
|
||||
EXPOSE 3333
|
||||
ENTRYPOINT npm run start
|
||||
|
||||
Binary file not shown.
@@ -110,7 +110,7 @@ This decorator requires that **all permissions** listed are granted to the reque
|
||||
|
||||
```ts
|
||||
import { RequireAllPermissions } from '../../authentication/authentication.decorator';
|
||||
import { Permissions } from '../../authentication/permissions.enum';
|
||||
import { PERMISSIONS } from '../../authentication/permissions.enum';
|
||||
|
||||
@Controller('foo')
|
||||
class FooController {
|
||||
@@ -129,7 +129,7 @@ In the following case, the user is required to have **at least one** listed perm
|
||||
|
||||
```ts
|
||||
import { RequireSomePermission } from '../../authentication/authentication.decorator';
|
||||
import { Permissions } from '../../authentication/permissions.enum';
|
||||
import { PERMISSIONS } from '../../authentication/permissions.enum';
|
||||
|
||||
@Controller('foo')
|
||||
@RequireSomePermission(Permissions.FOO.MANAGE, Permissions.FOO.CREATE)
|
||||
@@ -184,7 +184,7 @@ class FooController {
|
||||
RequireSomePermission,
|
||||
AuthenticateCondition,
|
||||
} from '../../authentication/authentication.decorator';
|
||||
import { Permissions } from '../../authentication/permissions.enum';
|
||||
import { PERMISSIONS } from '../../authentication/permissions.enum';
|
||||
import { Waa, Baz } from './authenticationFunctions'
|
||||
|
||||
@Controller('foo')
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import type { Config } from '@jest/types';
|
||||
const config: Config.InitialOptions = {
|
||||
moduleFileExtensions: ['ts', 'js', 'json'],
|
||||
modulePaths: ['<rootDir>'],
|
||||
roots: ['<rootDir>/src/', '<rootDir>/test/'],
|
||||
testRegex: '.*\\.(test|spec)\\.[jt]s$',
|
||||
transform: { '\\.[jt]s$': 'ts-jest' },
|
||||
collectCoverageFrom: ['**/*.[jt]s'],
|
||||
coverageDirectory: 'coverage',
|
||||
coveragePathIgnorePatterns: [
|
||||
'<rootDir>/node_modules/',
|
||||
'.*\\.module\\.[jt]s$',
|
||||
],
|
||||
// moduleDirectories: ['node_modules'], // default is already 'node_modules'
|
||||
// rootDir: '.', //No need
|
||||
// testEnvironment: 'node', //Defaults to 'node'
|
||||
};
|
||||
export default config;
|
||||
+5
-1
@@ -3,7 +3,11 @@
|
||||
"sourceRoot": "src",
|
||||
"compilerOptions": {
|
||||
"assets": [
|
||||
"**/*.proto"
|
||||
"**/*.proto",
|
||||
{
|
||||
"include": "i18n/**/*",
|
||||
"watchAssets": true
|
||||
}
|
||||
],
|
||||
"plugins": [
|
||||
"@nestjs/swagger"
|
||||
|
||||
Generated
+230
-141
@@ -7,9 +7,12 @@
|
||||
"": {
|
||||
"name": "maestro",
|
||||
"version": "0.0.0",
|
||||
"hasInstallScript": true,
|
||||
"license": "UNLICENSED",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-secrets-manager": "^3.112.0",
|
||||
"@dadosfera/dadosfera-logs": "^1.0.0-beta.4",
|
||||
"@dadosfera/protospack-v2": "3.18.11",
|
||||
"@grpc/grpc-js": "^1.6.7",
|
||||
"@grpc/proto-loader": "^0.6.13",
|
||||
"@nestjs/common": "^8.4.7",
|
||||
@@ -21,9 +24,10 @@
|
||||
"@nestjs/platform-express": "^8.4.7",
|
||||
"@nestjs/schedule": "^1.1.0",
|
||||
"@nestjs/swagger": "^5.2.1",
|
||||
"axios": "^0.25.0",
|
||||
"axios": "^0.27.2",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.13.2",
|
||||
"cron-parser": "^4.4.0",
|
||||
"dadosfera-logs": "^1.0.0-alpha.10",
|
||||
"dotenv": "^14.3.2",
|
||||
"elastic-apm-node": "^3.36.0",
|
||||
"helmet": "^5.1.0",
|
||||
@@ -35,8 +39,7 @@
|
||||
"passport-google-oauth20": "^2.0.0",
|
||||
"passport-hubspot-oauth2": "^1.0.3",
|
||||
"passport-mailchimp": "^1.1.0",
|
||||
"protospack": "2.5.1",
|
||||
"protospack-v2": "3.1.1",
|
||||
"protospack": "2.5.2",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"rxjs": "^7.5.5",
|
||||
@@ -1712,6 +1715,26 @@
|
||||
"kuler": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dadosfera/dadosfera-logs": {
|
||||
"version": "1.0.0-beta.4",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@dadosfera/dadosfera-logs/-/dadosfera-logs-1.0.0-beta.4.tgz",
|
||||
"integrity": "sha512-fFncbNVMbfQa2EFl7NJgmtuSRWHGtmwCbl5p++lSLvGcTIMjLGJ4HAMzSMemQhSxiiYlokdwweb7jJY7Ms62SQ==",
|
||||
"dependencies": {
|
||||
"@elastic/ecs-winston-format": "^1.3.1",
|
||||
"winston": "^3.7.2",
|
||||
"winston-log2gelf": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dadosfera/protospack-v2": {
|
||||
"version": "3.18.11",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.18.11.tgz",
|
||||
"integrity": "sha512-8/+RLEM6qheWIQf0hlgE3Rfu9y2vmoze0LvJ/imRkg2tObO+HRxxpZuGKaY+naH8maUawyOX8xO4lpmfotjOEw==",
|
||||
"dependencies": {
|
||||
"@grpc/grpc-js": "^1.6.7",
|
||||
"rxjs": "^7.5.5",
|
||||
"ts-proto": "^1.112.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@elastic/ecs-helpers": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@elastic/ecs-helpers/-/ecs-helpers-1.1.0.tgz",
|
||||
@@ -2407,26 +2430,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@nestjs/common/node_modules/axios": {
|
||||
"version": "0.27.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.14.9",
|
||||
"form-data": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nestjs/common/node_modules/form-data": {
|
||||
"version": "4.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/@nestjs/config": {
|
||||
"version": "1.2.1",
|
||||
"license": "MIT",
|
||||
@@ -3029,7 +3032,7 @@
|
||||
},
|
||||
"node_modules/@types/object-hash": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/object-hash/-/object-hash-1.3.4.tgz",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@types/object-hash/-/object-hash-1.3.4.tgz",
|
||||
"integrity": "sha512-xFdpkAkikBgqBdG9vIlsqffDV8GpvnPEzs0IUtr1v3BEB97ijsFQ4RXVbUZwjFThhB4MDSTUfvmxUD5PGx0wXA=="
|
||||
},
|
||||
"node_modules/@types/parse-json": {
|
||||
@@ -3763,10 +3766,25 @@
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "0.25.0",
|
||||
"license": "MIT",
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/axios/-/axios-0.27.2.tgz",
|
||||
"integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.14.7"
|
||||
"follow-redirects": "^1.14.9",
|
||||
"form-data": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/axios/node_modules/form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/babel-jest": {
|
||||
@@ -4237,6 +4255,20 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/class-transformer": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/class-transformer/-/class-transformer-0.5.1.tgz",
|
||||
"integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw=="
|
||||
},
|
||||
"node_modules/class-validator": {
|
||||
"version": "0.13.2",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/class-validator/-/class-validator-0.13.2.tgz",
|
||||
"integrity": "sha512-yBUcQy07FPlGzUjoLuUfIOXzgynnQPPruyK1Ge2B74k9ROwnle1E+NxLWnUv5OLU8hA/qL5leAE9XnXq3byaBw==",
|
||||
"dependencies": {
|
||||
"libphonenumber-js": "^1.9.43",
|
||||
"validator": "^13.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cli-cursor": {
|
||||
"version": "3.1.0",
|
||||
"dev": true,
|
||||
@@ -4553,16 +4585,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/dadosfera-logs": {
|
||||
"version": "1.0.0-alpha.10",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/dadosfera-logs/-/dadosfera-logs-1.0.0-alpha.10.tgz",
|
||||
"integrity": "sha512-OZ5sAkELiEQrViSvHjxM/Vb/skiXnkimNfgExdKPrHuVfy2s46d47p0QkL5XabFCvjEGyRKUCK8+UL/kRsKnnw==",
|
||||
"dependencies": {
|
||||
"@elastic/ecs-winston-format": "^1.3.1",
|
||||
"winston": "^3.7.2",
|
||||
"winston-log2gelf": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/data-urls": {
|
||||
"version": "2.0.0",
|
||||
"dev": true,
|
||||
@@ -4578,7 +4600,7 @@
|
||||
},
|
||||
"node_modules/dataloader": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/dataloader/-/dataloader-1.4.0.tgz",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/dataloader/-/dataloader-1.4.0.tgz",
|
||||
"integrity": "sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw=="
|
||||
},
|
||||
"node_modules/debug": {
|
||||
@@ -4663,6 +4685,17 @@
|
||||
"npm": "1.2.8000 || >= 1.4.16"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-libc": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/detect-libc/-/detect-libc-1.0.3.tgz",
|
||||
"integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
|
||||
"bin": {
|
||||
"detect-libc": "bin/detect-libc.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-newline": {
|
||||
"version": "3.1.0",
|
||||
"dev": true,
|
||||
@@ -4749,6 +4782,14 @@
|
||||
"version": "5.1.0",
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/dprint-node": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/dprint-node/-/dprint-node-1.0.7.tgz",
|
||||
"integrity": "sha512-NTZOW9A7ipb0n7z7nC3wftvsbceircwVHSgzobJsEQa+7RnOMbhrfX5IflA6CtC4GA63DSAiHYXa4JKEy9F7cA==",
|
||||
"dependencies": {
|
||||
"detect-libc": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/ecdsa-sig-formatter": {
|
||||
"version": "1.0.11",
|
||||
"license": "Apache-2.0",
|
||||
@@ -7823,6 +7864,11 @@
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/libphonenumber-js": {
|
||||
"version": "1.10.9",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/libphonenumber-js/-/libphonenumber-js-1.10.9.tgz",
|
||||
"integrity": "sha512-BvPlectKyHuA8xVBU4PerKdI1t+l71F/GCh6CQhe4j5bTwibF6Jcle88kDcyvq4aW55CXxWZg7yIYhzmjgrjkQ=="
|
||||
},
|
||||
"node_modules/lines-and-columns": {
|
||||
"version": "1.2.4",
|
||||
"dev": true,
|
||||
@@ -7929,9 +7975,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/logform": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/logform/-/logform-2.4.1.tgz",
|
||||
"integrity": "sha512-7XB/tqc3VRbri9pRjU6E97mQ8vC27ivJ3lct4jhyT+n0JNDd4YKldFl0D75NqDp46hk8RC7Ma1Vjv/UPf67S+A==",
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/logform/-/logform-2.4.2.tgz",
|
||||
"integrity": "sha512-W4c9himeAwXEdZ05dQNerhFz2XG80P9Oj0loPUMV23VC2it0orMHQhJm4hdnnor3rd1HsGf6a2lPwBM1zeXHGw==",
|
||||
"dependencies": {
|
||||
"@colors/colors": "1.5.0",
|
||||
"fecha": "^4.2.0",
|
||||
@@ -8175,8 +8221,9 @@
|
||||
"integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A=="
|
||||
},
|
||||
"node_modules/moment": {
|
||||
"version": "2.29.3",
|
||||
"license": "MIT",
|
||||
"version": "2.29.4",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
|
||||
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
@@ -8890,6 +8937,7 @@
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
|
||||
"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"prettier": "bin-prettier.js"
|
||||
},
|
||||
@@ -8989,22 +9037,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/protospack": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/protospack/-/protospack-2.5.1.tgz",
|
||||
"integrity": "sha512-4JTx7B7WxpC1G3S8T7SUEAEgVM9UjdYrOG37fr42wKxl9y6wOyCZJYjG/lXeAqFXOEPj9KSlM+MqBfLIMHWHeA==",
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/protospack/-/protospack-2.5.2.tgz",
|
||||
"integrity": "sha512-t7NyWE4WDuAVixjL10SDUXHu8iW4H0azndTC3n/w335D/IodPgN47ebm3iMXbvoQTlQcCbjjc+HblaRa9oR8bA==",
|
||||
"dependencies": {
|
||||
"rxjs": "^7.5.5"
|
||||
}
|
||||
},
|
||||
"node_modules/protospack-v2": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/protospack-v2/-/protospack-v2-3.1.1.tgz",
|
||||
"integrity": "sha512-uY9hsP2oO7kar1EUUjUhVLI8VQ3seWO2+WVS0XS9vjWZPUI82k7KqB70uYB+5ws2dMSowomPjiqpQ13VNjk6ZQ==",
|
||||
"dependencies": {
|
||||
"rxjs": "^7.5.5",
|
||||
"ts-proto": "^1.112.2"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-addr": {
|
||||
"version": "2.0.7",
|
||||
"license": "MIT",
|
||||
@@ -9966,9 +10005,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/terser": {
|
||||
"version": "5.14.0",
|
||||
"version": "5.14.2",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz",
|
||||
"integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"@jridgewell/source-map": "^0.3.2",
|
||||
"acorn": "^8.5.0",
|
||||
@@ -10289,34 +10329,33 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ts-poet": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-poet/-/ts-poet-4.14.0.tgz",
|
||||
"integrity": "sha512-hLGzWo3H3GLjVubftvaycGSconJrNpjjdpn43Lthnu61l/R2CaPIu+1JhaWZyqh2yj5NaOv+wZ5zoSJzDouAHw==",
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/ts-poet/-/ts-poet-6.1.0.tgz",
|
||||
"integrity": "sha512-PFwbNJjGrb44wzHUGQicG2/nhjR+3+k7zYLDTa8D61NVUitl7K/JgIc9/P+8oMNenntKzLc8tjLDOkPrxIhm6A==",
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.15",
|
||||
"prettier": "^2.5.1"
|
||||
"dprint-node": "^1.0.7"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-proto": {
|
||||
"version": "1.115.5",
|
||||
"resolved": "https://registry.npmjs.org/ts-proto/-/ts-proto-1.115.5.tgz",
|
||||
"integrity": "sha512-JGk6hln3JP0T0wJlqIOUGE/qHDYcI547hrJwAzeLq1E2l7IdYnYiAJRsvJEOsvotIyZXMbHNlZedIZEVIPAspQ==",
|
||||
"version": "1.126.1",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/ts-proto/-/ts-proto-1.126.1.tgz",
|
||||
"integrity": "sha512-PKrcgd0mCQJDY7tp+th349uYhnjs2Tz7wSqm9+DBcodl3YCKPt1pFtFmApOZdQ8WlghhgKAuJDIRQJBd6jD5YA==",
|
||||
"dependencies": {
|
||||
"@types/object-hash": "^1.3.0",
|
||||
"dataloader": "^1.4.0",
|
||||
"object-hash": "^1.3.1",
|
||||
"protobufjs": "^6.11.3",
|
||||
"ts-poet": "^4.11.0",
|
||||
"ts-proto-descriptors": "1.6.0"
|
||||
"ts-poet": "^6.1.0",
|
||||
"ts-proto-descriptors": "1.7.1"
|
||||
},
|
||||
"bin": {
|
||||
"protoc-gen-ts_proto": "protoc-gen-ts_proto"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-proto-descriptors": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-proto-descriptors/-/ts-proto-descriptors-1.6.0.tgz",
|
||||
"integrity": "sha512-Vrhue2Ti99us/o76mGy28nF3W/Uanl1/8detyJw2yyRwiBC5yxy+hEZqQ/ZX2PbZ1vyCpJ51A9L4PnCCnkBMTQ==",
|
||||
"version": "1.7.1",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/ts-proto-descriptors/-/ts-proto-descriptors-1.7.1.tgz",
|
||||
"integrity": "sha512-oIKUh3K4Xts4v29USGLfUG+2mEk32MsqpgZAOUyUlkrcIdv34yE+k2oZ2Nzngm6cV/JgFdOxRCqeyvmWHuYAyw==",
|
||||
"dependencies": {
|
||||
"long": "^4.0.0",
|
||||
"protobufjs": "^6.8.8"
|
||||
@@ -10324,7 +10363,7 @@
|
||||
},
|
||||
"node_modules/ts-proto/node_modules/object-hash": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.3.1.tgz",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/object-hash/-/object-hash-1.3.1.tgz",
|
||||
"integrity": "sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==",
|
||||
"engines": {
|
||||
"node": ">= 0.10.0"
|
||||
@@ -10570,6 +10609,14 @@
|
||||
"node": ">=10.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/validator": {
|
||||
"version": "13.7.0",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/validator/-/validator-13.7.0.tgz",
|
||||
"integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==",
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/vary": {
|
||||
"version": "1.1.2",
|
||||
"license": "MIT",
|
||||
@@ -10809,10 +10856,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/winston": {
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/winston/-/winston-3.7.2.tgz",
|
||||
"integrity": "sha512-QziIqtojHBoyzUOdQvQiar1DH0Xp9nF1A1y7NVy2DGEsz82SBDtOalS0ulTRGVT14xPX3WRWkCsdcJKqNflKng==",
|
||||
"version": "3.8.2",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/winston/-/winston-3.8.2.tgz",
|
||||
"integrity": "sha512-MsE1gRx1m5jdTTO9Ld/vND4krP2To+lgDoMEHGGa4HIlAUyXJtfc7CxQcGXVyz2IBpw5hbFkj2b/AtUdQwyRew==",
|
||||
"dependencies": {
|
||||
"@colors/colors": "1.5.0",
|
||||
"@dabh/diagnostics": "^2.0.2",
|
||||
"async": "^3.2.3",
|
||||
"is-stream": "^2.0.0",
|
||||
@@ -12247,6 +12295,26 @@
|
||||
"kuler": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"@dadosfera/dadosfera-logs": {
|
||||
"version": "1.0.0-beta.4",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@dadosfera/dadosfera-logs/-/dadosfera-logs-1.0.0-beta.4.tgz",
|
||||
"integrity": "sha512-fFncbNVMbfQa2EFl7NJgmtuSRWHGtmwCbl5p++lSLvGcTIMjLGJ4HAMzSMemQhSxiiYlokdwweb7jJY7Ms62SQ==",
|
||||
"requires": {
|
||||
"@elastic/ecs-winston-format": "^1.3.1",
|
||||
"winston": "^3.7.2",
|
||||
"winston-log2gelf": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"@dadosfera/protospack-v2": {
|
||||
"version": "3.18.11",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.18.11.tgz",
|
||||
"integrity": "sha512-8/+RLEM6qheWIQf0hlgE3Rfu9y2vmoze0LvJ/imRkg2tObO+HRxxpZuGKaY+naH8maUawyOX8xO4lpmfotjOEw==",
|
||||
"requires": {
|
||||
"@grpc/grpc-js": "^1.6.7",
|
||||
"rxjs": "^7.5.5",
|
||||
"ts-proto": "^1.112.2"
|
||||
}
|
||||
},
|
||||
"@elastic/ecs-helpers": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@elastic/ecs-helpers/-/ecs-helpers-1.1.0.tgz",
|
||||
@@ -12733,23 +12801,6 @@
|
||||
"iterare": "1.2.1",
|
||||
"tslib": "2.4.0",
|
||||
"uuid": "8.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": {
|
||||
"version": "0.27.2",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.14.9",
|
||||
"form-data": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"form-data": {
|
||||
"version": "4.0.0",
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@nestjs/config": {
|
||||
@@ -13137,7 +13188,7 @@
|
||||
},
|
||||
"@types/object-hash": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/object-hash/-/object-hash-1.3.4.tgz",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@types/object-hash/-/object-hash-1.3.4.tgz",
|
||||
"integrity": "sha512-xFdpkAkikBgqBdG9vIlsqffDV8GpvnPEzs0IUtr1v3BEB97ijsFQ4RXVbUZwjFThhB4MDSTUfvmxUD5PGx0wXA=="
|
||||
},
|
||||
"@types/parse-json": {
|
||||
@@ -13663,9 +13714,24 @@
|
||||
"integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ=="
|
||||
},
|
||||
"axios": {
|
||||
"version": "0.25.0",
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/axios/-/axios-0.27.2.tgz",
|
||||
"integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.14.7"
|
||||
"follow-redirects": "^1.14.9",
|
||||
"form-data": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"babel-jest": {
|
||||
@@ -13969,6 +14035,20 @@
|
||||
"version": "1.2.2",
|
||||
"dev": true
|
||||
},
|
||||
"class-transformer": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/class-transformer/-/class-transformer-0.5.1.tgz",
|
||||
"integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw=="
|
||||
},
|
||||
"class-validator": {
|
||||
"version": "0.13.2",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/class-validator/-/class-validator-0.13.2.tgz",
|
||||
"integrity": "sha512-yBUcQy07FPlGzUjoLuUfIOXzgynnQPPruyK1Ge2B74k9ROwnle1E+NxLWnUv5OLU8hA/qL5leAE9XnXq3byaBw==",
|
||||
"requires": {
|
||||
"libphonenumber-js": "^1.9.43",
|
||||
"validator": "^13.7.0"
|
||||
}
|
||||
},
|
||||
"cli-cursor": {
|
||||
"version": "3.1.0",
|
||||
"dev": true,
|
||||
@@ -14199,16 +14279,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"dadosfera-logs": {
|
||||
"version": "1.0.0-alpha.10",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/dadosfera-logs/-/dadosfera-logs-1.0.0-alpha.10.tgz",
|
||||
"integrity": "sha512-OZ5sAkELiEQrViSvHjxM/Vb/skiXnkimNfgExdKPrHuVfy2s46d47p0QkL5XabFCvjEGyRKUCK8+UL/kRsKnnw==",
|
||||
"requires": {
|
||||
"@elastic/ecs-winston-format": "^1.3.1",
|
||||
"winston": "^3.7.2",
|
||||
"winston-log2gelf": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"data-urls": {
|
||||
"version": "2.0.0",
|
||||
"dev": true,
|
||||
@@ -14220,7 +14290,7 @@
|
||||
},
|
||||
"dataloader": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/dataloader/-/dataloader-1.4.0.tgz",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/dataloader/-/dataloader-1.4.0.tgz",
|
||||
"integrity": "sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw=="
|
||||
},
|
||||
"debug": {
|
||||
@@ -14269,6 +14339,11 @@
|
||||
"destroy": {
|
||||
"version": "1.2.0"
|
||||
},
|
||||
"detect-libc": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/detect-libc/-/detect-libc-1.0.3.tgz",
|
||||
"integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="
|
||||
},
|
||||
"detect-newline": {
|
||||
"version": "3.1.0",
|
||||
"dev": true
|
||||
@@ -14324,6 +14399,14 @@
|
||||
"dotenv-expand": {
|
||||
"version": "5.1.0"
|
||||
},
|
||||
"dprint-node": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/dprint-node/-/dprint-node-1.0.7.tgz",
|
||||
"integrity": "sha512-NTZOW9A7ipb0n7z7nC3wftvsbceircwVHSgzobJsEQa+7RnOMbhrfX5IflA6CtC4GA63DSAiHYXa4JKEy9F7cA==",
|
||||
"requires": {
|
||||
"detect-libc": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"ecdsa-sig-formatter": {
|
||||
"version": "1.0.11",
|
||||
"requires": {
|
||||
@@ -16407,6 +16490,11 @@
|
||||
"type-check": "~0.4.0"
|
||||
}
|
||||
},
|
||||
"libphonenumber-js": {
|
||||
"version": "1.10.9",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/libphonenumber-js/-/libphonenumber-js-1.10.9.tgz",
|
||||
"integrity": "sha512-BvPlectKyHuA8xVBU4PerKdI1t+l71F/GCh6CQhe4j5bTwibF6Jcle88kDcyvq4aW55CXxWZg7yIYhzmjgrjkQ=="
|
||||
},
|
||||
"lines-and-columns": {
|
||||
"version": "1.2.4",
|
||||
"dev": true
|
||||
@@ -16481,9 +16569,9 @@
|
||||
}
|
||||
},
|
||||
"logform": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/logform/-/logform-2.4.1.tgz",
|
||||
"integrity": "sha512-7XB/tqc3VRbri9pRjU6E97mQ8vC27ivJ3lct4jhyT+n0JNDd4YKldFl0D75NqDp46hk8RC7Ma1Vjv/UPf67S+A==",
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/logform/-/logform-2.4.2.tgz",
|
||||
"integrity": "sha512-W4c9himeAwXEdZ05dQNerhFz2XG80P9Oj0loPUMV23VC2it0orMHQhJm4hdnnor3rd1HsGf6a2lPwBM1zeXHGw==",
|
||||
"requires": {
|
||||
"@colors/colors": "1.5.0",
|
||||
"fecha": "^4.2.0",
|
||||
@@ -16643,7 +16731,9 @@
|
||||
"integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A=="
|
||||
},
|
||||
"moment": {
|
||||
"version": "2.29.3"
|
||||
"version": "2.29.4",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
|
||||
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
|
||||
},
|
||||
"moment-timezone": {
|
||||
"version": "0.5.34",
|
||||
@@ -17127,7 +17217,8 @@
|
||||
"prettier": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
|
||||
"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g=="
|
||||
"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
|
||||
"dev": true
|
||||
},
|
||||
"prettier-linter-helpers": {
|
||||
"version": "1.0.0",
|
||||
@@ -17190,22 +17281,13 @@
|
||||
}
|
||||
},
|
||||
"protospack": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/protospack/-/protospack-2.5.1.tgz",
|
||||
"integrity": "sha512-4JTx7B7WxpC1G3S8T7SUEAEgVM9UjdYrOG37fr42wKxl9y6wOyCZJYjG/lXeAqFXOEPj9KSlM+MqBfLIMHWHeA==",
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/protospack/-/protospack-2.5.2.tgz",
|
||||
"integrity": "sha512-t7NyWE4WDuAVixjL10SDUXHu8iW4H0azndTC3n/w335D/IodPgN47ebm3iMXbvoQTlQcCbjjc+HblaRa9oR8bA==",
|
||||
"requires": {
|
||||
"rxjs": "^7.5.5"
|
||||
}
|
||||
},
|
||||
"protospack-v2": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/protospack-v2/-/protospack-v2-3.1.1.tgz",
|
||||
"integrity": "sha512-uY9hsP2oO7kar1EUUjUhVLI8VQ3seWO2+WVS0XS9vjWZPUI82k7KqB70uYB+5ws2dMSowomPjiqpQ13VNjk6ZQ==",
|
||||
"requires": {
|
||||
"rxjs": "^7.5.5",
|
||||
"ts-proto": "^1.112.2"
|
||||
}
|
||||
},
|
||||
"proxy-addr": {
|
||||
"version": "2.0.7",
|
||||
"requires": {
|
||||
@@ -17848,7 +17930,9 @@
|
||||
}
|
||||
},
|
||||
"terser": {
|
||||
"version": "5.14.0",
|
||||
"version": "5.14.2",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz",
|
||||
"integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@jridgewell/source-map": "^0.3.2",
|
||||
@@ -18039,38 +18123,37 @@
|
||||
}
|
||||
},
|
||||
"ts-poet": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-poet/-/ts-poet-4.14.0.tgz",
|
||||
"integrity": "sha512-hLGzWo3H3GLjVubftvaycGSconJrNpjjdpn43Lthnu61l/R2CaPIu+1JhaWZyqh2yj5NaOv+wZ5zoSJzDouAHw==",
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/ts-poet/-/ts-poet-6.1.0.tgz",
|
||||
"integrity": "sha512-PFwbNJjGrb44wzHUGQicG2/nhjR+3+k7zYLDTa8D61NVUitl7K/JgIc9/P+8oMNenntKzLc8tjLDOkPrxIhm6A==",
|
||||
"requires": {
|
||||
"lodash": "^4.17.15",
|
||||
"prettier": "^2.5.1"
|
||||
"dprint-node": "^1.0.7"
|
||||
}
|
||||
},
|
||||
"ts-proto": {
|
||||
"version": "1.115.5",
|
||||
"resolved": "https://registry.npmjs.org/ts-proto/-/ts-proto-1.115.5.tgz",
|
||||
"integrity": "sha512-JGk6hln3JP0T0wJlqIOUGE/qHDYcI547hrJwAzeLq1E2l7IdYnYiAJRsvJEOsvotIyZXMbHNlZedIZEVIPAspQ==",
|
||||
"version": "1.126.1",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/ts-proto/-/ts-proto-1.126.1.tgz",
|
||||
"integrity": "sha512-PKrcgd0mCQJDY7tp+th349uYhnjs2Tz7wSqm9+DBcodl3YCKPt1pFtFmApOZdQ8WlghhgKAuJDIRQJBd6jD5YA==",
|
||||
"requires": {
|
||||
"@types/object-hash": "^1.3.0",
|
||||
"dataloader": "^1.4.0",
|
||||
"object-hash": "^1.3.1",
|
||||
"protobufjs": "^6.11.3",
|
||||
"ts-poet": "^4.11.0",
|
||||
"ts-proto-descriptors": "1.6.0"
|
||||
"ts-poet": "^6.1.0",
|
||||
"ts-proto-descriptors": "1.7.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"object-hash": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.3.1.tgz",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/object-hash/-/object-hash-1.3.1.tgz",
|
||||
"integrity": "sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"ts-proto-descriptors": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-proto-descriptors/-/ts-proto-descriptors-1.6.0.tgz",
|
||||
"integrity": "sha512-Vrhue2Ti99us/o76mGy28nF3W/Uanl1/8detyJw2yyRwiBC5yxy+hEZqQ/ZX2PbZ1vyCpJ51A9L4PnCCnkBMTQ==",
|
||||
"version": "1.7.1",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/ts-proto-descriptors/-/ts-proto-descriptors-1.7.1.tgz",
|
||||
"integrity": "sha512-oIKUh3K4Xts4v29USGLfUG+2mEk32MsqpgZAOUyUlkrcIdv34yE+k2oZ2Nzngm6cV/JgFdOxRCqeyvmWHuYAyw==",
|
||||
"requires": {
|
||||
"long": "^4.0.0",
|
||||
"protobufjs": "^6.8.8"
|
||||
@@ -18241,6 +18324,11 @@
|
||||
"source-map": "^0.7.3"
|
||||
}
|
||||
},
|
||||
"validator": {
|
||||
"version": "13.7.0",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/validator/-/validator-13.7.0.tgz",
|
||||
"integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw=="
|
||||
},
|
||||
"vary": {
|
||||
"version": "1.1.2"
|
||||
},
|
||||
@@ -18399,10 +18487,11 @@
|
||||
}
|
||||
},
|
||||
"winston": {
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/winston/-/winston-3.7.2.tgz",
|
||||
"integrity": "sha512-QziIqtojHBoyzUOdQvQiar1DH0Xp9nF1A1y7NVy2DGEsz82SBDtOalS0ulTRGVT14xPX3WRWkCsdcJKqNflKng==",
|
||||
"version": "3.8.2",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/winston/-/winston-3.8.2.tgz",
|
||||
"integrity": "sha512-MsE1gRx1m5jdTTO9Ld/vND4krP2To+lgDoMEHGGa4HIlAUyXJtfc7CxQcGXVyz2IBpw5hbFkj2b/AtUdQwyRew==",
|
||||
"requires": {
|
||||
"@colors/colors": "1.5.0",
|
||||
"@dabh/diagnostics": "^2.0.2",
|
||||
"async": "^3.2.3",
|
||||
"is-stream": "^2.0.0",
|
||||
|
||||
+7
-21
@@ -9,6 +9,7 @@
|
||||
"node": "18.3.0"
|
||||
},
|
||||
"scripts": {
|
||||
"preinstall": "aws codeartifact login --tool npm --namespace @dadosfera --repository dadosfera-npm --domain dadosfera --domain-owner 611330257153 --region us-east-1",
|
||||
"prebuild": "rimraf dist",
|
||||
"build": "nest build",
|
||||
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
||||
@@ -25,6 +26,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-secrets-manager": "^3.112.0",
|
||||
"@dadosfera/dadosfera-logs": "^1.0.0-beta.4",
|
||||
"@dadosfera/protospack-v2": "3.18.11",
|
||||
"@grpc/grpc-js": "^1.6.7",
|
||||
"@grpc/proto-loader": "^0.6.13",
|
||||
"@nestjs/common": "^8.4.7",
|
||||
@@ -36,9 +39,10 @@
|
||||
"@nestjs/platform-express": "^8.4.7",
|
||||
"@nestjs/schedule": "^1.1.0",
|
||||
"@nestjs/swagger": "^5.2.1",
|
||||
"axios": "^0.25.0",
|
||||
"axios": "^0.27.2",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.13.2",
|
||||
"cron-parser": "^4.4.0",
|
||||
"dadosfera-logs": "^1.0.0-alpha.10",
|
||||
"dotenv": "^14.3.2",
|
||||
"elastic-apm-node": "^3.36.0",
|
||||
"helmet": "^5.1.0",
|
||||
@@ -50,8 +54,7 @@
|
||||
"passport-google-oauth20": "^2.0.0",
|
||||
"passport-hubspot-oauth2": "^1.0.3",
|
||||
"passport-mailchimp": "^1.1.0",
|
||||
"protospack": "2.5.1",
|
||||
"protospack-v2": "3.1.1",
|
||||
"protospack": "2.5.2",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"rxjs": "^7.5.5",
|
||||
@@ -89,22 +92,5 @@
|
||||
"ts-node": "^10.8.1",
|
||||
"tsconfig-paths": "^3.14.1",
|
||||
"typescript": "^4.6.3"
|
||||
},
|
||||
"jest": {
|
||||
"moduleFileExtensions": [
|
||||
"js",
|
||||
"json",
|
||||
"ts"
|
||||
],
|
||||
"rootDir": "src",
|
||||
"testRegex": ".*\\.spec\\.ts$",
|
||||
"transform": {
|
||||
"^.+\\.(t|j)s$": "ts-jest"
|
||||
},
|
||||
"collectCoverageFrom": [
|
||||
"**/*.(t|j)s"
|
||||
],
|
||||
"coverageDirectory": "../coverage",
|
||||
"testEnvironment": "node"
|
||||
}
|
||||
}
|
||||
|
||||
+37
-94
@@ -1,83 +1,34 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ClientsModule } from '@nestjs/microservices';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { DadosferaLogger } from 'dadosfera-logs';
|
||||
|
||||
import { InputsController } from './modules/inputs/inputs.controller';
|
||||
import { TransformationsController } from './modules/transformations/transformations.controller';
|
||||
import { OutputsController } from './modules/outputs/outputs.controllers';
|
||||
import { PipelinesController } from './modules/pipelines/pipelines.controller';
|
||||
import { HealthController } from './modules/health/health.controller';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
|
||||
import { InputsService } from './modules/inputs/inputs.service';
|
||||
import { TransformationsService } from './modules/transformations/transformations.service';
|
||||
import { OutputsService } from './modules/outputs/outputs.service';
|
||||
import { PipelinesService } from './modules/pipelines/pipelines.service';
|
||||
import { HealthService } from './modules/health/health.service';
|
||||
|
||||
import { AuthModule } from './modules/auth/auth.module';
|
||||
import { InputsClientService } from './clients/inputs/client.service';
|
||||
import { TransformationsClientService } from './clients/transformations/client.service';
|
||||
import { OutputsClientService } from './clients/outputs/client.service';
|
||||
import { PipelinesClientService } from './clients/pipelines/client.service';
|
||||
import { PermissionsModule } from './modules/permissions/permissions.module';
|
||||
|
||||
import { OutputsClientConfiguration } from './clients/outputs/client.config';
|
||||
import { TransformationsClientConfiguration } from './clients/transformations/client.config';
|
||||
import { InputsClientConfiguration } from './clients/inputs/client.config';
|
||||
import { PipelinesClientConfiguration } from './clients/pipelines/client.config';
|
||||
import { CatalogController } from './modules/catalog/catalog.controller';
|
||||
import { CatalogService } from './modules/catalog/catalog.service';
|
||||
import { OauthController } from './modules/oauth/oauth.controller';
|
||||
import { getOauthSecrets } from './utils/OauthSecrets';
|
||||
import { HubspotStrategy } from './modules/oauth/passport-strategies/hubspot-strategy';
|
||||
import { FacebookStrategy } from './modules/oauth/passport-strategies/facebook-strategy';
|
||||
import { AuthenticationGuard } from './authentication/authentication.guard';
|
||||
import { APP_GUARD } from '@nestjs/core';
|
||||
import { GoogleStrategy } from './modules/oauth/passport-strategies/google-strategy';
|
||||
import { MailChimpStrategy } from './modules/oauth/passport-strategies/mailchimp-strategy';
|
||||
import { SalesforceStrategy } from './modules/oauth/passport-strategies/salesforce-strategy';
|
||||
import { ConnectorClientConfiguration } from './clients/connector/client.config';
|
||||
import { ConnectorController } from './modules/connector/connector.controller';
|
||||
import { ConnectorClientService } from './clients/connector/client.service';
|
||||
import { TermsOfUseModule } from './modules/termsOfUse/termsOfUse.module';
|
||||
|
||||
const inputClient = new InputsClientConfiguration();
|
||||
const outputClient = new OutputsClientConfiguration();
|
||||
const pipelineClient = new PipelinesClientConfiguration();
|
||||
const transformationClient = new TransformationsClientConfiguration();
|
||||
const connectorClient = new ConnectorClientConfiguration();
|
||||
import { APP_GUARD } from '@nestjs/core';
|
||||
|
||||
import { UsersModule } from './modules/users/users.module';
|
||||
import { RolesModule } from './modules/roles/roles.module';
|
||||
import { ConnectorModule } from './modules/connector/connector.module';
|
||||
import { AuthModule } from './modules/auth/auth.module';
|
||||
import { PermissionsModule } from './modules/permissions/permissions.module';
|
||||
import { TermsOfUseModule } from './modules/termsOfUse/termsOfUse.module';
|
||||
import { ConnectionModule } from './modules/connection/connection.module';
|
||||
import { ConnectionTestModule } from './modules/connection-test/connection-test.module';
|
||||
import { NetworkConfigModule } from './modules/network-config/network-config.module';
|
||||
import { InputsModule } from './modules/inputs/inputs.module';
|
||||
import { OauthModule } from './modules/oauth/oauth.module';
|
||||
import { PipelinesModule } from './modules/pipelines/pipelines.module';
|
||||
import { TransformationsModule } from './modules/transformations/transformations.module';
|
||||
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: [
|
||||
InputsController,
|
||||
TransformationsController,
|
||||
OutputsController,
|
||||
PipelinesController,
|
||||
HealthController,
|
||||
CatalogController,
|
||||
OauthController,
|
||||
ConnectorController,
|
||||
],
|
||||
controllers: [],
|
||||
providers: [
|
||||
DadosferaLogger,
|
||||
{ provide: 'OAUTH_SECRETS', useValue: getOauthSecrets() },
|
||||
InputsService,
|
||||
TransformationsService,
|
||||
OutputsService,
|
||||
PipelinesService,
|
||||
ConnectorClientService,
|
||||
HealthService,
|
||||
InputsClientService,
|
||||
TransformationsClientService,
|
||||
OutputsClientService,
|
||||
PipelinesClientService,
|
||||
CatalogService,
|
||||
HubspotStrategy,
|
||||
FacebookStrategy,
|
||||
GoogleStrategy,
|
||||
MailChimpStrategy,
|
||||
SalesforceStrategy,
|
||||
{
|
||||
provide: APP_GUARD,
|
||||
useClass: AuthenticationGuard,
|
||||
@@ -87,32 +38,24 @@ const connectorClient = new ConnectorClientConfiguration();
|
||||
ConfigModule.forRoot({
|
||||
isGlobal: true,
|
||||
}),
|
||||
ConnectorModule,
|
||||
AuthModule,
|
||||
PermissionsModule,
|
||||
TermsOfUseModule,
|
||||
|
||||
ClientsModule.register([
|
||||
{
|
||||
name: 'INPUTS_PACKAGE',
|
||||
...inputClient.config(),
|
||||
},
|
||||
{
|
||||
name: 'TRANSFORMATIONS_PACKAGE',
|
||||
...transformationClient.config(),
|
||||
},
|
||||
{
|
||||
name: 'OUTPUTS_PACKAGE',
|
||||
...outputClient.config(),
|
||||
},
|
||||
{
|
||||
name: 'PIPELINES_PACKAGE',
|
||||
...pipelineClient.config(),
|
||||
},
|
||||
{
|
||||
name: 'CONNECTOR_PACKAGE',
|
||||
...connectorClient.config(),
|
||||
},
|
||||
]),
|
||||
ConnectionModule,
|
||||
NetworkConfigModule,
|
||||
ConnectionTestModule,
|
||||
PipelinesModule,
|
||||
TransformationsModule,
|
||||
HealthModule,
|
||||
CatalogModule,
|
||||
UsersModule,
|
||||
RolesModule,
|
||||
InputsModule,
|
||||
OauthModule,
|
||||
PipelinesV2Module,
|
||||
CatalogModule,
|
||||
ProductboardModule,
|
||||
],
|
||||
})
|
||||
export class AppModule {}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Request } from 'express';
|
||||
import { CustomDecorator } from '@nestjs/common';
|
||||
import { Permission } from './permissions.enum';
|
||||
import { PermissionsObjectPermission } from './permissions.enum';
|
||||
import { RequestUser } from './user.decorator';
|
||||
|
||||
export const AUTH_FUNCTION_KEY = '__AUTH_FUNCTION__';
|
||||
@@ -31,13 +31,17 @@ function SetMultipleMetadata(metadataKey, metadataValue): CustomDecorator {
|
||||
return decoratorFactory as any;
|
||||
}
|
||||
|
||||
export function RequireAllPermissions(...permissions: Permission[]) {
|
||||
export function RequireAllPermissions(
|
||||
...permissions: PermissionsObjectPermission[]
|
||||
) {
|
||||
return SetMultipleMetadata(AUTH_FUNCTION_KEY, (req, user: RequestUser) =>
|
||||
permissions.every(({ seqid }) => user.permissions.includes(seqid)),
|
||||
);
|
||||
}
|
||||
|
||||
export function RequireSomePermission(...permissions: Permission[]) {
|
||||
export function RequireSomePermission(
|
||||
...permissions: PermissionsObjectPermission[]
|
||||
) {
|
||||
return SetMultipleMetadata(AUTH_FUNCTION_KEY, (req, user: RequestUser) =>
|
||||
permissions.some(({ seqid }) => user.permissions.includes(seqid)),
|
||||
);
|
||||
|
||||
@@ -5,7 +5,7 @@ import { APP_GUARD } from '@nestjs/core';
|
||||
import jwt from 'jsonwebtoken';
|
||||
|
||||
import { Body, Controller, Get } from '@nestjs/common';
|
||||
import { DadosferaLogger } from 'dadosfera-logs';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import {
|
||||
AuthenticateCondition,
|
||||
Authenticated,
|
||||
@@ -13,11 +13,15 @@ import {
|
||||
RequireSomePermission,
|
||||
} from './authentication.decorator';
|
||||
import { AuthenticationGuard } from './authentication.guard';
|
||||
import { Permissions } from './permissions.enum';
|
||||
import { PERMISSIONS_GROUPS } from './permissions.enum';
|
||||
import { AuthClientService } from '../modules/auth/auth.service';
|
||||
|
||||
import ErrorCodes from '../utils/errorCodes';
|
||||
|
||||
const logger = {
|
||||
info: (...args) => args,
|
||||
error: (...args) => args,
|
||||
};
|
||||
@Controller('no-class-auth')
|
||||
class NoClassAuthController {
|
||||
@Get('body')
|
||||
@@ -32,19 +36,25 @@ class NoClassAuthController {
|
||||
}
|
||||
|
||||
@Get('required-permission')
|
||||
@RequireSomePermission(Permissions.ZENDESK.OPEN)
|
||||
@RequireSomePermission(PERMISSIONS_GROUPS.ZENDESK.permissions.OPEN)
|
||||
async requiredPermission(@Body() body) {
|
||||
return { body };
|
||||
}
|
||||
|
||||
@Get('has-all-permissions')
|
||||
@RequireAllPermissions(Permissions.ZENDESK.OPEN, Permissions.METABASE.OPEN)
|
||||
@RequireAllPermissions(
|
||||
PERMISSIONS_GROUPS.ZENDESK.permissions.OPEN,
|
||||
PERMISSIONS_GROUPS.METABASE.permissions.OPEN,
|
||||
)
|
||||
async hasAllPermissions(@Body() body) {
|
||||
return { body };
|
||||
}
|
||||
|
||||
@Get('has-some-permission')
|
||||
@RequireSomePermission(Permissions.ZENDESK.OPEN, Permissions.METABASE.OPEN)
|
||||
@RequireSomePermission(
|
||||
PERMISSIONS_GROUPS.ZENDESK.permissions.OPEN,
|
||||
PERMISSIONS_GROUPS.METABASE.permissions.OPEN,
|
||||
)
|
||||
async hasSomePermission(@Body() body) {
|
||||
return { body };
|
||||
}
|
||||
@@ -52,7 +62,7 @@ class NoClassAuthController {
|
||||
|
||||
@Controller('class-auth-condition')
|
||||
@AuthenticateCondition((req) => req.get('x-on-class') === 'ok')
|
||||
@RequireSomePermission(Permissions.METABASE.OPEN)
|
||||
@RequireSomePermission(PERMISSIONS_GROUPS.METABASE.permissions.OPEN)
|
||||
class ClassAuthConditionController {
|
||||
@Get('body')
|
||||
async getBody(@Body() body) {
|
||||
@@ -67,7 +77,7 @@ class ClassAuthConditionController {
|
||||
|
||||
@Get('required-permission')
|
||||
@AuthenticateCondition((req) => req.get('x-on-route') === 'ok')
|
||||
@RequireSomePermission(Permissions.ZENDESK.OPEN)
|
||||
@RequireSomePermission(PERMISSIONS_GROUPS.ZENDESK.permissions.OPEN)
|
||||
async requiredPermission(@Body() body) {
|
||||
return { body };
|
||||
}
|
||||
@@ -104,7 +114,7 @@ describe('authentication.guard', () => {
|
||||
},
|
||||
{
|
||||
provide: DadosferaLogger,
|
||||
useValue: { logger: console },
|
||||
useValue: { logger },
|
||||
},
|
||||
{
|
||||
provide: APP_GUARD,
|
||||
@@ -430,17 +440,17 @@ describe('authentication.guard', () => {
|
||||
NoClassAuthTest(null, null);
|
||||
ClassAuthConditionTest(null, null);
|
||||
|
||||
const tokenZ = CreateToken([Permissions.ZENDESK.OPEN]);
|
||||
const tokenZ = CreateToken([PERMISSIONS_GROUPS.ZENDESK.permissions.OPEN]);
|
||||
NoClassAuthTest(tokenZ, ['zendesk']);
|
||||
ClassAuthConditionTest(tokenZ, ['zendesk']);
|
||||
|
||||
const tokenM = CreateToken([Permissions.METABASE.OPEN]);
|
||||
const tokenM = CreateToken([PERMISSIONS_GROUPS.METABASE.permissions.OPEN]);
|
||||
NoClassAuthTest(tokenM, ['metabase']);
|
||||
ClassAuthConditionTest(tokenM, ['metabase']);
|
||||
|
||||
const tokenZM = CreateToken([
|
||||
Permissions.ZENDESK.OPEN,
|
||||
Permissions.METABASE.OPEN,
|
||||
PERMISSIONS_GROUPS.ZENDESK.permissions.OPEN,
|
||||
PERMISSIONS_GROUPS.METABASE.permissions.OPEN,
|
||||
]);
|
||||
NoClassAuthTest(tokenZM, ['zendesk', 'metabase']);
|
||||
ClassAuthConditionTest(tokenZM, ['zendesk', 'metabase']);
|
||||
|
||||
@@ -3,13 +3,12 @@ import {
|
||||
CanActivate,
|
||||
OnApplicationBootstrap,
|
||||
ExecutionContext,
|
||||
Logger,
|
||||
Inject,
|
||||
} from '@nestjs/common';
|
||||
import { Reflector } from '@nestjs/core';
|
||||
import assert from 'assert';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { DadosferaLogger } from 'dadosfera-logs';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import { AuthClientService } from '../modules/auth/auth.service';
|
||||
import {
|
||||
AuthenticationFunction,
|
||||
@@ -23,7 +22,7 @@ import ErrorCodes from '../utils/errorCodes';
|
||||
export class AuthenticationGuard
|
||||
implements CanActivate, OnApplicationBootstrap
|
||||
{
|
||||
logger: any;
|
||||
logger: DadosferaLogger;
|
||||
|
||||
pems: Map<string, string>;
|
||||
|
||||
@@ -96,7 +95,7 @@ export class AuthenticationGuard
|
||||
);*/
|
||||
|
||||
assert(
|
||||
accessTokenDecoded.payload.token_use === 'access',
|
||||
accessTokenDecoded?.payload?.token_use === 'access',
|
||||
'should be an access token',
|
||||
);
|
||||
|
||||
@@ -108,7 +107,7 @@ export class AuthenticationGuard
|
||||
} catch (err) {
|
||||
// log errors if authentication is required
|
||||
if (mustBeAuthenticated) {
|
||||
this.logger.error('Unable to verify duc access token\n' + err.stack);
|
||||
this.logger.error('Unable to verify duc access token\n' + err?.stack);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -122,6 +121,7 @@ export class AuthenticationGuard
|
||||
customer_id: accessTokenPayload.customer_id,
|
||||
customer_name: accessTokenPayload.customer_name,
|
||||
customer_tier: accessTokenPayload.customer_tier,
|
||||
access_token: accessToken,
|
||||
};
|
||||
// TODO: for backwards compatibility. remove in the future
|
||||
request.body.info = {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Logger } from '@nestjs/common';
|
||||
import assert from 'assert';
|
||||
import { LanguageEnum } from 'src/utils/languages.enum';
|
||||
|
||||
const logger = new Logger();
|
||||
|
||||
@@ -8,10 +9,24 @@ export enum PermissionUsages {
|
||||
INTERNAL = 'internal',
|
||||
}
|
||||
|
||||
export interface Permission {
|
||||
export interface PermissionsObjectPermission {
|
||||
seqid: number;
|
||||
claim: string;
|
||||
usage: PermissionUsages;
|
||||
name?: Record<LanguageEnum, string>;
|
||||
}
|
||||
export interface PermissionsObjectPermissionTranslated {
|
||||
seqid: number;
|
||||
claim: string;
|
||||
usage: PermissionUsages;
|
||||
name?: string;
|
||||
}
|
||||
export interface PermissionsObjectGroup {
|
||||
title: {
|
||||
'pt-br': string;
|
||||
'en-us': string;
|
||||
};
|
||||
permissions: Record<string, PermissionsObjectPermission>;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -22,216 +37,516 @@ export interface Permission {
|
||||
/*export const Permissions: {
|
||||
[P in keyof any]: { [Q in keyof any]: Permission };
|
||||
} = {*/
|
||||
export const Permissions = {
|
||||
export const PERMISSIONS_GROUPS = {
|
||||
AUTH: {
|
||||
CREATE: {
|
||||
seqid: 18,
|
||||
claim: 'POST /auth',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
title: {
|
||||
'pt-br': 'Autenticação',
|
||||
'en-us': 'Authentication',
|
||||
'es-es': 'Authentication',
|
||||
},
|
||||
permissions: {
|
||||
CREATE: {
|
||||
seqid: 18,
|
||||
claim: 'POST /auth',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': '',
|
||||
'en-us': '',
|
||||
'es-es': '',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
PIPELINE: {
|
||||
CREATE: {
|
||||
seqid: 23,
|
||||
claim: 'POST /pipelines',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
title: {
|
||||
'pt-br': 'Coletar | Pipelines',
|
||||
'en-us': 'Collect | Pipelines',
|
||||
'es-es': 'Colecta | Pipelines',
|
||||
},
|
||||
GET: {
|
||||
seqid: 13,
|
||||
claim: 'GET /pipelines',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
UPDATE: {
|
||||
seqid: 29,
|
||||
claim: 'PUT /pipelines',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
DELETE: {
|
||||
seqid: 5,
|
||||
claim: 'DELETE /pipelines',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
permissions: {
|
||||
CREATE: {
|
||||
seqid: 23,
|
||||
claim: 'POST /pipelines',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
name: {
|
||||
'pt-br': 'Criar pipelines',
|
||||
'en-us': 'Create pipelines',
|
||||
'es-es': 'Crear pipelines',
|
||||
},
|
||||
},
|
||||
GET: {
|
||||
seqid: 13,
|
||||
claim: 'GET /pipelines',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
name: {
|
||||
'pt-br': 'Buscar pipelines',
|
||||
'en-us': 'Get pipelines',
|
||||
'es-es': 'Obtener pipelines',
|
||||
},
|
||||
},
|
||||
UPDATE: {
|
||||
seqid: 29,
|
||||
claim: 'PUT /pipelines',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
name: {
|
||||
'pt-br': 'Atualizar pipeline',
|
||||
'en-us': 'Update pipeline',
|
||||
'es-es': 'Actualizar pipeline',
|
||||
},
|
||||
},
|
||||
DELETE: {
|
||||
seqid: 5,
|
||||
claim: 'DELETE /pipelines',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
name: {
|
||||
'pt-br': 'Excluir pipeline',
|
||||
'en-us': 'Delete pipeline',
|
||||
'es-es': 'Eliminar pipeline',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
INPUT: {
|
||||
CREATE: {
|
||||
seqid: 21,
|
||||
claim: 'POST /inputs',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
CONNECTION: {
|
||||
title: {
|
||||
'pt-br': 'Coletar | Fontes de dados',
|
||||
'en-us': 'Collect | Sources',
|
||||
'es-es': 'Colecta | Sources',
|
||||
},
|
||||
GET: {
|
||||
seqid: 9,
|
||||
claim: 'GET /inputs',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
permissions: {
|
||||
CREATE: {
|
||||
seqid: 37,
|
||||
claim: 'connection:create',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
name: {
|
||||
'pt-br': 'Cadastrar Fonte',
|
||||
'en-us': 'Create Source',
|
||||
'es-es': 'Crear 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',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'Editar Fonte',
|
||||
'en-us': 'Edit Source',
|
||||
'es-es': 'Editar Source',
|
||||
},
|
||||
},
|
||||
},
|
||||
UPDATE: {
|
||||
seqid: 27,
|
||||
claim: 'PUT /inputs',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
|
||||
NETWORK_CONFIG: {
|
||||
title: {
|
||||
'pt-br': 'Coletar | Redes',
|
||||
'en-us': 'Collect | Network',
|
||||
'es-es': 'Colecta | Network',
|
||||
},
|
||||
UPDATE_PARTIAL: {
|
||||
seqid: 17,
|
||||
claim: 'PATCH /inputs',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
DELETE: {
|
||||
seqid: 3,
|
||||
claim: 'DELETE /inputs',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
GET_ENTITIES: {
|
||||
seqid: 10,
|
||||
claim: 'GET /inputs/available-entities',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
permissions: {
|
||||
CREATE: {
|
||||
seqid: 35,
|
||||
claim: 'network_config:create',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
name: {
|
||||
'pt-br': 'Cadastrar VPN',
|
||||
'en-us': 'Create VPN',
|
||||
'es-es': 'Crear VPN',
|
||||
},
|
||||
},
|
||||
// DELETE: {
|
||||
// seqid: 36,
|
||||
// claim: 'network_config:delete',
|
||||
// usage: PermissionUsages.PUBLIC,
|
||||
// name: {
|
||||
// 'pt-br': 'Excluir VPN',
|
||||
// 'en-us': 'Remove VPN',
|
||||
// 'es-es': 'Eliminar VPN',
|
||||
// },
|
||||
// },
|
||||
},
|
||||
},
|
||||
|
||||
OUTPUT: {
|
||||
CREATE: {
|
||||
seqid: 22,
|
||||
claim: 'POST /outputs',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
title: {
|
||||
'pt-br': 'Output',
|
||||
'en-us': 'Output',
|
||||
'es-es': 'Output',
|
||||
},
|
||||
GET: {
|
||||
seqid: 12,
|
||||
claim: 'GET /outputs',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
UPDATE: {
|
||||
seqid: 28,
|
||||
claim: 'PUT /outputs',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
DELETE: {
|
||||
seqid: 4,
|
||||
claim: 'DELETE /outputs',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
permissions: {
|
||||
CREATE: {
|
||||
seqid: 22,
|
||||
claim: 'POST /outputs',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'Criar outputs',
|
||||
'en-us': 'Create outputs',
|
||||
'es-es': 'Crear outputs',
|
||||
},
|
||||
},
|
||||
GET: {
|
||||
seqid: 12,
|
||||
claim: 'GET /outputs',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'Buscar outputs',
|
||||
'en-us': 'Get outputs',
|
||||
'es-es': 'Obtener outputs',
|
||||
},
|
||||
},
|
||||
UPDATE: {
|
||||
seqid: 28,
|
||||
claim: 'PUT /outputs',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'Editar outputs',
|
||||
'en-us': 'Edit outputs',
|
||||
'es-es': 'Editar outputs',
|
||||
},
|
||||
},
|
||||
DELETE: {
|
||||
seqid: 4,
|
||||
claim: 'DELETE /outputs',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'Excluir outputs',
|
||||
'en-us': 'Remove outputs',
|
||||
'es-es': 'Eliminar outputs',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
TRANSFORMATIONS: {
|
||||
CREATE: {
|
||||
seqid: 24,
|
||||
claim: 'POST /transformations',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
title: {
|
||||
'pt-br': 'Micro-transformações',
|
||||
'en-us': 'Micro-transformations',
|
||||
'es-es': 'Micro-transformaciones',
|
||||
},
|
||||
GET: {
|
||||
seqid: 15,
|
||||
claim: 'GET /transformations',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
UPDATE: {
|
||||
seqid: 30,
|
||||
claim: 'PUT /transformations',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
DELETE: {
|
||||
seqid: 6,
|
||||
claim: 'DELETE /transformations',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
permissions: {
|
||||
CREATE: {
|
||||
seqid: 24,
|
||||
claim: 'POST /transformations',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'Criar micro-transformações',
|
||||
'en-us': 'Create micro-transformations',
|
||||
'es-es': 'Crear micro-transformaciones',
|
||||
},
|
||||
},
|
||||
GET: {
|
||||
seqid: 15,
|
||||
claim: 'GET /transformations',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'Buscar micro-transformações',
|
||||
'en-us': 'Get micro-transformations',
|
||||
'es-es': 'Obtener micro-transformaciones',
|
||||
},
|
||||
},
|
||||
UPDATE: {
|
||||
seqid: 30,
|
||||
claim: 'PUT /transformations',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'Editar micro-transformações',
|
||||
'en-us': 'Edit micro-transformations',
|
||||
'es-es': 'Editar micro-transformaciones',
|
||||
},
|
||||
},
|
||||
DELETE: {
|
||||
seqid: 6,
|
||||
claim: 'DELETE /transformations',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'Excluir micro-transformações',
|
||||
'en-us': 'Remove micro-transformations',
|
||||
'es-es': 'Eliminar micro-transformaciones',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
CATALOG: {
|
||||
CREATE: {
|
||||
seqid: 19,
|
||||
claim: 'POST /catalog',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
title: {
|
||||
'pt-br': 'Explorar | Catálogo',
|
||||
'en-us': 'Explore | Catalog',
|
||||
'es-es': 'Explorar | Catalogar',
|
||||
},
|
||||
GET: {
|
||||
seqid: 7,
|
||||
claim: 'GET /catalog',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
UPDATE: {
|
||||
seqid: 25,
|
||||
claim: 'PUT /catalog',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
DELETE: {
|
||||
seqid: 1,
|
||||
claim: 'DELETE /catalog',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
permissions: {
|
||||
GET: {
|
||||
seqid: 7,
|
||||
claim: 'GET /catalog',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
name: {
|
||||
'pt-br': 'Buscar data assets',
|
||||
'en-us': 'Search for data assets',
|
||||
'es-es': 'Buscar data assets',
|
||||
},
|
||||
},
|
||||
CREATE: {
|
||||
seqid: 19,
|
||||
claim: 'POST /catalog',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
name: {
|
||||
'pt-br': 'Criar atributos no catálogo',
|
||||
'en-us': 'Create attributes',
|
||||
'es-es': 'Crear atributos',
|
||||
},
|
||||
},
|
||||
UPDATE: {
|
||||
seqid: 25,
|
||||
claim: 'PUT /catalog',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'Editar atributos no catálogo',
|
||||
'en-us': 'Edit attributes',
|
||||
'es-es': 'Editar atributos',
|
||||
},
|
||||
},
|
||||
DELETE: {
|
||||
seqid: 1,
|
||||
claim: 'DELETE /catalog',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'Excluir atributos no catálogo',
|
||||
'en-us': 'Remove attributes',
|
||||
'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',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
CONNECTORS: {
|
||||
CREATE: {
|
||||
seqid: 20,
|
||||
claim: 'POST /connectors',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
title: {
|
||||
'pt-br': 'Conectores',
|
||||
'en-us': 'Connectors',
|
||||
'es-es': 'Conectores',
|
||||
},
|
||||
GET: {
|
||||
seqid: 8,
|
||||
claim: 'GET /connectors',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
UPDATE: {
|
||||
seqid: 26,
|
||||
claim: 'PUT /connectors',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
DELETE: {
|
||||
seqid: 2,
|
||||
claim: 'DELETE /connectors',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
permissions: {
|
||||
CREATE: {
|
||||
seqid: 20,
|
||||
claim: 'POST /connectors',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'Criar conectores',
|
||||
'en-us': 'Create connectors',
|
||||
'es-es': 'Crear conectores',
|
||||
},
|
||||
},
|
||||
GET: {
|
||||
seqid: 8,
|
||||
claim: 'GET /connectors',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'Buscar conectores',
|
||||
'en-us': 'Get connectors',
|
||||
'es-es': 'Obtener conectores',
|
||||
},
|
||||
},
|
||||
UPDATE: {
|
||||
seqid: 26,
|
||||
claim: 'PUT /connectors',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'Editar conectores',
|
||||
'en-us': 'Edit connectors',
|
||||
'es-es': 'Editar conectores',
|
||||
},
|
||||
},
|
||||
DELETE: {
|
||||
seqid: 2,
|
||||
claim: 'DELETE /connectors',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'Excluir conectores',
|
||||
'en-us': 'Remove connectors',
|
||||
'es-es': 'Eliminar conectores',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
SNOWFLAKE: {
|
||||
OPEN: {
|
||||
seqid: 14,
|
||||
claim: 'GET /snowflake',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
title: {
|
||||
'pt-br': 'Explorar | Consolidar',
|
||||
'en-us': 'Explore | Data consolidation',
|
||||
'es-es': 'Explorar | Consolidación de datos',
|
||||
},
|
||||
permissions: {
|
||||
OPEN: {
|
||||
seqid: 14,
|
||||
claim: 'GET /snowflake',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
name: {
|
||||
'pt-br': 'Acessar Snowflake',
|
||||
'en-us': 'Access Snowflake',
|
||||
'es-es': 'Acceso Snowflake',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
ZENDESK: {
|
||||
OPEN: {
|
||||
seqid: 16,
|
||||
claim: 'GET /zendesk',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
title: {
|
||||
'pt-br': 'Zendesk',
|
||||
'en-us': 'Zendesk',
|
||||
'es-es': 'Zendesk',
|
||||
},
|
||||
permissions: {
|
||||
OPEN: {
|
||||
seqid: 16,
|
||||
claim: 'GET /zendesk',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'Acessar Zendesk',
|
||||
'en-us': 'Access Zendesk',
|
||||
'es-es': 'Acceso Zendesk',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
METABASE: {
|
||||
OPEN: {
|
||||
seqid: 11,
|
||||
claim: 'GET /metabase',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
title: {
|
||||
'pt-br': 'Analisar | Visualização',
|
||||
'en-us': 'Analyze | Visualization',
|
||||
'es-es': 'Analizar | Visualización',
|
||||
},
|
||||
permissions: {
|
||||
OPEN: {
|
||||
seqid: 11,
|
||||
claim: 'GET /metabase',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
name: {
|
||||
'pt-br': 'Acessar Metabase',
|
||||
'en-us': 'Access Metabase',
|
||||
'es-es': 'Acceso Metabase',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
ORCHEST: {
|
||||
INTELLIGENCE: {
|
||||
seqid: 31,
|
||||
claim: 'intelligence:open',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
title: {
|
||||
'pt-br': 'Analisar | Inteligência',
|
||||
'en-us': 'Analyze | Intelligence',
|
||||
'es-es': 'Analizar | Inteligencia',
|
||||
},
|
||||
APP_BUILDER: {
|
||||
seqid: 32,
|
||||
claim: 'app-builder:open',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
permissions: {
|
||||
INTELLIGENCE: {
|
||||
seqid: 31,
|
||||
claim: 'intelligence:open',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'Acessar Orchest',
|
||||
'en-us': 'Access Orchest',
|
||||
'es-s': 'Acceso Orchest',
|
||||
},
|
||||
},
|
||||
APP_BUILDER: {
|
||||
seqid: 32,
|
||||
claim: 'app-builder:open',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'Acessar App Builder',
|
||||
'en-us': 'Access App Builder',
|
||||
'es-es': 'Acceso App Builder',
|
||||
},
|
||||
},
|
||||
MACHINE_LEARNING: {
|
||||
seqid: 33,
|
||||
claim: 'machine-learning:open',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'Acessar Machine Learning',
|
||||
'en-us': 'Access Machine Learning',
|
||||
'es-es': 'Acceso Machine Learning',
|
||||
},
|
||||
},
|
||||
},
|
||||
MACHINE_LEARNING: {
|
||||
seqid: 33,
|
||||
claim: 'machine-learning:open',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
USERS: {
|
||||
title: {
|
||||
'pt-br': 'Usuários',
|
||||
'en-us': 'Users',
|
||||
'es-es': 'Usuarios',
|
||||
},
|
||||
permissions: {
|
||||
ADMIN: {
|
||||
seqid: 34,
|
||||
claim: 'users:admin',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
name: {
|
||||
'pt-br': 'Gestão de usuários e grupos',
|
||||
'en-us': 'Manage user and roles',
|
||||
'es-es': 'Administrar usuarios y roles',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
DADOSFERA: {
|
||||
title: {
|
||||
'pt-br': 'Usuários',
|
||||
'en-us': 'Users',
|
||||
'es-es': 'Usuarios',
|
||||
},
|
||||
permissions: {
|
||||
CONNECTIONS_MIGRATION: {
|
||||
seqid: 40,
|
||||
claim: 'dadosfera:connections-migration',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'connections-migration',
|
||||
'en-us': 'connections-migration',
|
||||
'es-es': 'connections-migration',
|
||||
},
|
||||
},
|
||||
SYNC_USER: {
|
||||
seqid: 41,
|
||||
claim: 'dadosfera:sync-user',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'sync-user',
|
||||
'en-us': 'sync-user',
|
||||
'es-es': 'sync-user',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// traverses the object searching for duplicate seqids or claims (executes at runtime)
|
||||
let nextAvailableSeqid = 0;
|
||||
const seqids = Object.values(Permissions).flatMap((namespace) =>
|
||||
Object.values(namespace).map(({ seqid }) => seqid),
|
||||
const seqids = Object.values(PERMISSIONS_GROUPS).flatMap((namespace) =>
|
||||
Object.values(namespace.permissions).map(({ seqid }) => seqid),
|
||||
);
|
||||
const claims = Object.values(Permissions).flatMap((namespace) =>
|
||||
Object.values(namespace).map(({ claim }) => claim),
|
||||
const claims = Object.values(PERMISSIONS_GROUPS).flatMap((namespace) =>
|
||||
Object.values(namespace.permissions).map(({ claim }) => claim),
|
||||
);
|
||||
Object.values(Permissions).map((namespace) =>
|
||||
Object.values(namespace).map(({ seqid, claim }) => {
|
||||
Object.values(PERMISSIONS_GROUPS).map((namespace) =>
|
||||
Object.values(namespace.permissions).map(({ seqid, claim }) => {
|
||||
const seqidsCount = seqids.filter((x) => x === seqid).length;
|
||||
assert(seqidsCount === 1, `seqid ${seqid} count is not 1`);
|
||||
|
||||
|
||||
@@ -5,14 +5,18 @@ import { APP_GUARD } from '@nestjs/core';
|
||||
import jwt from 'jsonwebtoken';
|
||||
|
||||
import { Controller, Get } from '@nestjs/common';
|
||||
import { DadosferaLogger } from 'dadosfera-logs';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import { AuthenticationGuard } from './authentication.guard';
|
||||
import { AuthClientService } from '../modules/auth/auth.service';
|
||||
|
||||
import ErrorCodes from '../utils/errorCodes';
|
||||
import { User } from './user.decorator';
|
||||
import { Permissions } from './permissions.enum';
|
||||
import { PERMISSIONS_GROUPS } from './permissions.enum';
|
||||
|
||||
const logger = {
|
||||
info: (...args) => args,
|
||||
error: (...args) => args,
|
||||
};
|
||||
@Controller('user')
|
||||
class UserController {
|
||||
@Get()
|
||||
@@ -45,10 +49,13 @@ describe('user.decorator', () => {
|
||||
const fakeUserPayload = {
|
||||
user_id: 'd50d33c7-6c2b-463c-861f-e21667e7c125',
|
||||
username: 'super.admin',
|
||||
permissions: [Permissions.METABASE.OPEN].map(({ seqid }) => seqid),
|
||||
permissions: [PERMISSIONS_GROUPS.METABASE.permissions.OPEN].map(
|
||||
({ seqid }) => seqid,
|
||||
),
|
||||
customer_id: '9d18e8ae-24b9-41a3-9e8f-a25ce57555b11',
|
||||
customer_name: 'dadosfera',
|
||||
customer_tier: 'BASIC',
|
||||
access_token: '',
|
||||
};
|
||||
|
||||
beforeAll(async () => {
|
||||
@@ -64,7 +71,7 @@ describe('user.decorator', () => {
|
||||
},
|
||||
{
|
||||
provide: DadosferaLogger,
|
||||
useValue: { logger: console },
|
||||
useValue: { logger },
|
||||
},
|
||||
{
|
||||
provide: APP_GUARD,
|
||||
@@ -170,5 +177,6 @@ describe('user.decorator', () => {
|
||||
UserTest(null);
|
||||
|
||||
const token = CreateToken();
|
||||
fakeUserPayload.access_token = token;
|
||||
UserTest(token);
|
||||
});
|
||||
|
||||
@@ -10,6 +10,7 @@ export interface RequestUser {
|
||||
customer_id: string;
|
||||
customer_name: string;
|
||||
customer_tier: string;
|
||||
access_token: string;
|
||||
}
|
||||
|
||||
export const User: (options?: { required?: boolean }) => ParameterDecorator =
|
||||
@@ -19,6 +20,5 @@ export const User: (options?: { required?: boolean }) => ParameterDecorator =
|
||||
if (!request.user && options?.required) {
|
||||
throw new ErrorBuilder(ErrorCodes.AUTH.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
return request.user;
|
||||
});
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
import { credentials } from '@grpc/grpc-js';
|
||||
import { ClientOptions, Transport } from '@nestjs/microservices';
|
||||
import { ConnectorManager } from 'protospack-v2';
|
||||
|
||||
export class ConnectorClientConfiguration {
|
||||
config(): ClientOptions {
|
||||
return {
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
url: process.env.INFACTORY_URL,
|
||||
package: [
|
||||
ConnectorManager.ProtoPackages.WritePackage,
|
||||
ConnectorManager.ProtoPackages.ReadPackage,
|
||||
],
|
||||
credentials:
|
||||
process.env.LOCAL_ENV === 'local'
|
||||
? undefined
|
||||
: credentials.createSsl(),
|
||||
protoPath: [
|
||||
ConnectorManager.ProtoPaths.WriteFilePath,
|
||||
ConnectorManager.ProtoPaths.ReadFilePath,
|
||||
],
|
||||
loader: {
|
||||
enums: String,
|
||||
objects: true,
|
||||
arrays: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,307 +0,0 @@
|
||||
import {
|
||||
OnModuleInit,
|
||||
Inject,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
} from '@nestjs/common';
|
||||
import { DadosferaLogger } from 'dadosfera-logs';
|
||||
import { ClientGrpc } from '@nestjs/microservices';
|
||||
import { ConnectorManager } from 'protospack-v2';
|
||||
import { from } from 'rxjs';
|
||||
|
||||
export class ConnectorClientService implements OnModuleInit {
|
||||
private connectorServiceRead: ConnectorManager.ReadService.ConnectorManagerReadServices;
|
||||
private connectorServiceWrite: ConnectorManager.WriteService.ConnectorManagerWriteServices;
|
||||
logger: any;
|
||||
constructor(
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
@Inject('CONNECTOR_PACKAGE') private readonly grpcClient: ClientGrpc,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
|
||||
onModuleInit() {
|
||||
this.connectorServiceWrite =
|
||||
this.grpcClient.getService<ConnectorManager.WriteService.ConnectorManagerWriteServices>(
|
||||
ConnectorManager.ProtoServices.ConnectorManagerWriteServices,
|
||||
);
|
||||
|
||||
this.connectorServiceRead =
|
||||
this.grpcClient.getService<ConnectorManager.ReadService.ConnectorManagerReadServices>(
|
||||
ConnectorManager.ProtoServices.ConnectorManagerReadServices,
|
||||
);
|
||||
}
|
||||
|
||||
async uploadConnector(uploadConnector) {
|
||||
const connector: ConnectorManager.Entities.ConnectorCreateRequest = {
|
||||
file: {
|
||||
buffer: uploadConnector.file.buffer,
|
||||
mimetypes: uploadConnector.file.mimetype,
|
||||
},
|
||||
connector: JSON.stringify(uploadConnector.connector),
|
||||
};
|
||||
const serviceBody: ConnectorManager.Messages.RegisterConnectorRequest = {
|
||||
connector,
|
||||
};
|
||||
|
||||
const observable = from(
|
||||
this.connectorServiceWrite.RegisterConnector(serviceBody),
|
||||
);
|
||||
|
||||
const result = await new Promise((resolve, reject) => {
|
||||
observable.subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
//console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.details);
|
||||
this.logger.error(err);
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 400,
|
||||
);
|
||||
});
|
||||
|
||||
this.logger.info('ConnectorClientService - Upload');
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async uploadFile(uploadFile) {
|
||||
const body: ConnectorManager.Messages.UploadFileRequest = {
|
||||
file: {
|
||||
buffer: uploadFile.file.buffer,
|
||||
mimetypes: uploadFile.file.mimetype,
|
||||
},
|
||||
name: uploadFile.name,
|
||||
};
|
||||
|
||||
const observable = from(this.connectorServiceWrite.UploadFile(body));
|
||||
|
||||
const result = await new Promise((resolve, reject) => {
|
||||
observable.subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
//console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.details);
|
||||
this.logger.error(err);
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 400,
|
||||
);
|
||||
});
|
||||
|
||||
this.logger.info('ConnectorClientService - Upload');
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async getAllConnectors(body) {
|
||||
const observable = from(
|
||||
this.connectorServiceRead.GetAllConnectors({
|
||||
search: body.search,
|
||||
filters: JSON.stringify(body.filters),
|
||||
}),
|
||||
);
|
||||
const result = await new Promise((resolve, reject) => {
|
||||
observable.subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
//console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err);
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 400,
|
||||
);
|
||||
});
|
||||
|
||||
this.logger.info('ConnectorClientService - getAllConnectors');
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async getConnectorDetails(plugin: string) {
|
||||
const observable = from(
|
||||
this.connectorServiceRead.GetConnectorDetails({
|
||||
plugin,
|
||||
}),
|
||||
);
|
||||
const result = await new Promise((resolve, reject) => {
|
||||
observable.subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
//console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err);
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 400,
|
||||
);
|
||||
});
|
||||
|
||||
this.logger.info('ConnectorClientService - getAllConnectors');
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async getConnector(plugin: string) {
|
||||
const observable = from(
|
||||
this.connectorServiceRead.GetConnector({
|
||||
plugin,
|
||||
}),
|
||||
);
|
||||
const result = await new Promise((resolve, reject) => {
|
||||
observable.subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
//console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err);
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 400,
|
||||
);
|
||||
});
|
||||
|
||||
this.logger.info('ConnectorClientService - getAllConnectors');
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async deleteConnector(plugin: string, version: string) {
|
||||
const observable = from(
|
||||
this.connectorServiceWrite.DeleteConnector({
|
||||
version,
|
||||
plugin,
|
||||
}),
|
||||
);
|
||||
const result = await new Promise((resolve, reject) => {
|
||||
observable.subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
//console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err);
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 400,
|
||||
);
|
||||
});
|
||||
|
||||
this.logger.info('ConnectorClientService - getAllConnectors');
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async updateConnector({ plugin, changes }) {
|
||||
const observable = from(
|
||||
this.connectorServiceWrite.UpdateConnector({
|
||||
plugin,
|
||||
changes,
|
||||
}),
|
||||
);
|
||||
const result = await new Promise((resolve, reject) => {
|
||||
observable.subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
//console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err);
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 400,
|
||||
);
|
||||
});
|
||||
|
||||
this.logger.info('ConnectorClientService - getAllConnectors');
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
import { credentials } from '@grpc/grpc-js';
|
||||
import { ClientOptions, Transport } from '@nestjs/microservices';
|
||||
import {
|
||||
ProtoPackages,
|
||||
ProtoPaths,
|
||||
} from 'protospack-v2/dist/lib/Duc';
|
||||
|
||||
export class DucClient {
|
||||
config(): ClientOptions {
|
||||
return {
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
url: process.env.DUC_URL,
|
||||
package: ProtoPackages.WritePackage,
|
||||
credentials: process.env.LOCAL_ENV
|
||||
? undefined
|
||||
: credentials.createSsl(),
|
||||
protoPath: ProtoPaths.WriteFilePath,
|
||||
loader: {
|
||||
keepCase: true,
|
||||
enums: String,
|
||||
objects: true,
|
||||
arrays: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import { credentials } from '@grpc/grpc-js';
|
||||
import { ClientOptions, Transport } from '@nestjs/microservices';
|
||||
|
||||
import { InputPackages, InputProtoFilePath } from 'protospack';
|
||||
|
||||
export class InputsClientConfiguration {
|
||||
config(): ClientOptions {
|
||||
return {
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
url: process.env.INFACTORY_URL,
|
||||
package: InputPackages,
|
||||
credentials: process.env.LOCAL_ENV
|
||||
? undefined
|
||||
: credentials.createSsl(),
|
||||
protoPath: InputProtoFilePath,
|
||||
loader: {
|
||||
enums: String,
|
||||
objects: true,
|
||||
arrays: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,310 +0,0 @@
|
||||
import {
|
||||
OnModuleInit,
|
||||
Inject,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
NotFoundException,
|
||||
InternalServerErrorException,
|
||||
} from '@nestjs/common';
|
||||
import { ClientGrpc } from '@nestjs/microservices';
|
||||
import {
|
||||
DecodeGrpcStruct,
|
||||
EncodeJsonToGrpcStruct,
|
||||
InputCreateS3Request,
|
||||
InputNewCreateRequest,
|
||||
InputService,
|
||||
TestConnectionGetColumnsRequest,
|
||||
TestConnectionRequest,
|
||||
} from 'protospack';
|
||||
import axios, { AxiosRequestConfig } from 'axios';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import { InputModel } from 'src/modules/inputs/dtos/input.model';
|
||||
import {
|
||||
objectCamelToSnake,
|
||||
objectSnakeToCamel,
|
||||
} from 'src/utils/CaseConverter';
|
||||
import { mustache } from 'src/utils/mustache';
|
||||
import { DadosferaLogger } from 'dadosfera-logs';
|
||||
import { OauthSecrets } from 'src/utils/OauthSecrets';
|
||||
import { URLSearchParams } from 'url';
|
||||
import { IIdRequest, UpdateInputRequest } from './interfaces';
|
||||
|
||||
export class InputsClientService implements OnModuleInit {
|
||||
private inputService: InputService;
|
||||
logger: any;
|
||||
constructor(
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
@Inject('INPUTS_PACKAGE') private readonly grpcClient: ClientGrpc,
|
||||
@Inject('OAUTH_SECRETS') private readonly oauthSecrets: OauthSecrets,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
|
||||
async onModuleInit() {
|
||||
this.inputService =
|
||||
this.grpcClient.getService<InputService>('InputService');
|
||||
}
|
||||
|
||||
async newCreate(createInputDto: InputNewCreateRequest) {
|
||||
this.logger.info('InputClientService - Create');
|
||||
|
||||
const input = await lastValueFrom(
|
||||
this.inputService.NewCreate(objectSnakeToCamel(createInputDto)),
|
||||
);
|
||||
objectCamelToSnake(input);
|
||||
return input;
|
||||
}
|
||||
|
||||
async createGeneric(createInputGeneric) {
|
||||
this.logger.info('InputClientService - Create');
|
||||
const { info, ...data } = createInputGeneric;
|
||||
// data.credentials = await this.getInputTokens(data);
|
||||
if (data.options) delete data.options;
|
||||
if (data.credentials.oauth_code) delete data.credentials.oauth_code;
|
||||
const grpcPayload = {
|
||||
input: EncodeJsonToGrpcStruct(data),
|
||||
info,
|
||||
};
|
||||
objectSnakeToCamel(grpcPayload);
|
||||
|
||||
const structReturn = await lastValueFrom(
|
||||
this.inputService.Create(grpcPayload),
|
||||
).catch((err: { details: string }) => {
|
||||
if (err.details === 'Item Not found!') {
|
||||
throw new NotFoundException('Input not found');
|
||||
}
|
||||
throw new InternalServerErrorException(err.details);
|
||||
});
|
||||
objectCamelToSnake(structReturn);
|
||||
const inputCreated = DecodeGrpcStruct(structReturn.input);
|
||||
return { input: inputCreated };
|
||||
}
|
||||
|
||||
async createS3Inputs(createInputDto: InputCreateS3Request) {
|
||||
this.logger.info('InputClientService - Create');
|
||||
objectSnakeToCamel(createInputDto);
|
||||
const createInputResponse = await lastValueFrom(
|
||||
this.inputService.CreateS3(createInputDto),
|
||||
).catch((e) => {
|
||||
throw new HttpException(e.details, 500);
|
||||
});
|
||||
this.logger.info('Done');
|
||||
objectCamelToSnake(createInputResponse);
|
||||
return createInputResponse;
|
||||
}
|
||||
|
||||
async findOne(data: IIdRequest) {
|
||||
this.logger.info('InputClientService - FindOne');
|
||||
const findOneInputResponse = await lastValueFrom(
|
||||
this.inputService.FindOne(objectSnakeToCamel(data)),
|
||||
).catch((e) => {
|
||||
this.logger.error(e.details);
|
||||
throw new HttpException(e.details, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
});
|
||||
objectCamelToSnake(findOneInputResponse);
|
||||
return findOneInputResponse;
|
||||
}
|
||||
|
||||
async findAll(data) {
|
||||
this.logger.info('InputClientService - FindAll');
|
||||
const findAllInputResponse = await lastValueFrom(
|
||||
this.inputService.FindAll(objectSnakeToCamel(data)),
|
||||
).catch((e) => {
|
||||
this.logger.error(e.details);
|
||||
throw new HttpException(e.details, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
});
|
||||
findAllInputResponse.inputs.forEach((input) => objectCamelToSnake(input));
|
||||
|
||||
return findAllInputResponse;
|
||||
}
|
||||
|
||||
async update(updateInputDTO: UpdateInputRequest) {
|
||||
this.logger.info('InputClientService - Update');
|
||||
const updateInputResponse = await new Promise((resolve, reject) => {
|
||||
this.inputService.Update(objectSnakeToCamel(updateInputDTO)).subscribe({
|
||||
next(x) {
|
||||
resolve(objectCamelToSnake(x));
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
// console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return updateInputResponse;
|
||||
}
|
||||
|
||||
async remove(idRequest: IIdRequest) {
|
||||
this.logger.info('InputClientService - Remove');
|
||||
|
||||
const removeInputResponse = await new Promise((resolve, reject) => {
|
||||
this.inputService.Remove(objectSnakeToCamel(idRequest)).subscribe({
|
||||
next(x) {
|
||||
resolve(objectCamelToSnake(x));
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
// console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return removeInputResponse;
|
||||
}
|
||||
|
||||
async testConnection(data: TestConnectionRequest) {
|
||||
this.logger.info('InputClientService - TestConnection');
|
||||
const testConnectionResponse = await new Promise((resolve, reject) => {
|
||||
this.inputService.NewTestConnection(objectSnakeToCamel(data)).subscribe({
|
||||
next(x) {
|
||||
resolve(objectCamelToSnake(x));
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
// console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return testConnectionResponse;
|
||||
}
|
||||
|
||||
async getColumns(data: TestConnectionGetColumnsRequest) {
|
||||
this.logger.info('InputClientService - TestConnection/Get-Columns');
|
||||
const getColumnsResponse = await new Promise((resolve, reject) => {
|
||||
this.inputService.GetColumns(objectSnakeToCamel(data)).subscribe({
|
||||
next(x) {
|
||||
resolve(objectCamelToSnake(x));
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
// console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return getColumnsResponse;
|
||||
}
|
||||
async getAuthSecrets(plugin) {
|
||||
switch (plugin) {
|
||||
case 'hubspot':
|
||||
return {
|
||||
client_id: this.oauthSecrets.hubspot.client_id || '',
|
||||
client_secret: this.oauthSecrets.hubspot.client_secret || '',
|
||||
};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
async getInputTokens(input: InputModel) {
|
||||
const { credentials } = input;
|
||||
let credentialsTokens = {};
|
||||
switch (credentials.connection_type) {
|
||||
case 'oauth':
|
||||
credentialsTokens = await this.getOauthTokens(input);
|
||||
break;
|
||||
}
|
||||
return { ...credentials, ...credentialsTokens };
|
||||
}
|
||||
async getOauthTokens(input: InputModel) {
|
||||
const tokens: Record<string, any> = {};
|
||||
const { options, credentials } = input;
|
||||
const { oauth } = options;
|
||||
const { get_tokens_url_params, get_tokens_set_response } = oauth;
|
||||
const secrets = await this.getAuthSecrets(input.plugin);
|
||||
const get_tokens_url_params_string = mustache(get_tokens_url_params, {
|
||||
...secrets,
|
||||
...credentials,
|
||||
});
|
||||
let get_tokens_url_params_obj: Record<string, any> = {};
|
||||
try {
|
||||
get_tokens_url_params_obj = JSON.parse(get_tokens_url_params_string);
|
||||
} catch (error) {
|
||||
throw new HttpException('Erro transformando get_tokens_url_params', 400);
|
||||
}
|
||||
let params = {};
|
||||
switch (oauth.content_type) {
|
||||
case 'application/x-www-form-urlencoded':
|
||||
params = new URLSearchParams(get_tokens_url_params_obj);
|
||||
params = params.toString();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
const axiosRequestConfig: AxiosRequestConfig = {
|
||||
url: oauth.get_tokens_url,
|
||||
method: oauth.get_tokens_method || 'POST',
|
||||
data: params,
|
||||
headers: { 'content-type': oauth.content_type || 'application/json' },
|
||||
};
|
||||
|
||||
const { data } = await axios(axiosRequestConfig).catch((err) => {
|
||||
this.logger.error(err.response.data);
|
||||
throw new HttpException(err.response.data.message, err.response.status);
|
||||
});
|
||||
for (const key in get_tokens_set_response) {
|
||||
const responseKey = get_tokens_set_response[key];
|
||||
tokens[key] = data[responseKey];
|
||||
}
|
||||
const { redirect_uri } = get_tokens_url_params_obj;
|
||||
tokens.redirect_uri = redirect_uri;
|
||||
return tokens;
|
||||
}
|
||||
|
||||
async getAvailableEntities(data) {
|
||||
this.logger.info('InputClientService - GetAvailableEntities');
|
||||
objectSnakeToCamel(data);
|
||||
const response = await lastValueFrom(
|
||||
this.inputService.GetAvailableEntities(data),
|
||||
).catch((err) => {
|
||||
this.logger.info(err.details);
|
||||
if (err.details && err.details.includes('400'))
|
||||
throw new HttpException('Plugin inválido', HttpStatus.BAD_REQUEST);
|
||||
throw new HttpException(err.details, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
});
|
||||
objectCamelToSnake(response);
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
import { OutputPackages, OutputProtoFilePath } from 'protospack';
|
||||
import { ClientOptions, Transport } from '@nestjs/microservices';
|
||||
import { credentials } from '@grpc/grpc-js';
|
||||
|
||||
export class OutputsClientConfiguration {
|
||||
config(): ClientOptions {
|
||||
return {
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
url: process.env.OTFACTORY_URL,
|
||||
package: OutputPackages,
|
||||
credentials: process.env.LOCAL_ENV
|
||||
? undefined
|
||||
: credentials.createSsl(),
|
||||
protoPath: OutputProtoFilePath,
|
||||
loader: {
|
||||
enums: String,
|
||||
objects: true,
|
||||
arrays: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,181 +0,0 @@
|
||||
import { Controller, Inject, OnModuleInit } from '@nestjs/common';
|
||||
import { ClientGrpc, Payload } from '@nestjs/microservices';
|
||||
import { DadosferaLogger } from 'dadosfera-logs';
|
||||
import {
|
||||
OutputServicesNames,
|
||||
OutputsServiceInterface,
|
||||
} from 'protospack';
|
||||
import {
|
||||
objectCamelToSnake,
|
||||
objectSnakeToCamel,
|
||||
} from 'src/utils/CaseConverter';
|
||||
import {
|
||||
ICreateOutputRequest,
|
||||
IIdRequest,
|
||||
IOutputUpdateRequest,
|
||||
} from './interfaces';
|
||||
|
||||
@Controller('output')
|
||||
export class OutputsClientService implements OnModuleInit {
|
||||
private outputService: OutputsServiceInterface;
|
||||
logger: any;
|
||||
constructor(
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
@Inject('OUTPUTS_PACKAGE') private readonly grpcClient: ClientGrpc,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
|
||||
onModuleInit() {
|
||||
this.outputService = this.grpcClient.getService<OutputsServiceInterface>(
|
||||
OutputServicesNames.OutputService,
|
||||
);
|
||||
}
|
||||
|
||||
async create(@Payload() createOutputDto: ICreateOutputRequest) {
|
||||
this.logger.info('OutputClientService - Create');
|
||||
|
||||
const createOutputResponse = await new Promise((resolve, reject) => {
|
||||
this.outputService.Create(objectSnakeToCamel(createOutputDto)).subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
// console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
const convertedItem = objectCamelToSnake(createOutputResponse['output']);
|
||||
createOutputResponse['output'] = convertedItem;
|
||||
return createOutputResponse;
|
||||
}
|
||||
|
||||
async findAll(data) {
|
||||
this.logger.info('OutputClientService - FindAll');
|
||||
|
||||
const findAllOutputResponse = await new Promise((resolve, reject) => {
|
||||
this.outputService.FindAll(objectSnakeToCamel(data)).subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
// console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
const convertedOutputs = findAllOutputResponse['outputs'].map((ot) => {
|
||||
return objectCamelToSnake(ot);
|
||||
});
|
||||
|
||||
return { outputs: convertedOutputs };
|
||||
}
|
||||
|
||||
async findOne(data: IIdRequest) {
|
||||
this.logger.info('OutputClientService - FindOne');
|
||||
|
||||
const findOneOutputResponse = await new Promise((resolve, reject) => {
|
||||
this.outputService.FindOne(objectSnakeToCamel(data)).subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
// console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return objectCamelToSnake(findOneOutputResponse);
|
||||
}
|
||||
|
||||
async update(updateOutPutDTO: IOutputUpdateRequest) {
|
||||
this.logger.info('OutputClientService - Update');
|
||||
|
||||
const updateOutputResponse = await new Promise((resolve, reject) => {
|
||||
this.outputService.Update(objectSnakeToCamel(updateOutPutDTO)).subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
// console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return objectCamelToSnake(updateOutputResponse);
|
||||
}
|
||||
|
||||
async remove(data: IIdRequest) {
|
||||
this.logger.info('OutputClientService - Remove');
|
||||
|
||||
const removeOutputResponse = await new Promise((resolve, reject) => {
|
||||
this.outputService.Remove(objectSnakeToCamel(data)).subscribe({
|
||||
next(x) {
|
||||
resolve(objectCamelToSnake(x));
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
// console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return removeOutputResponse;
|
||||
}
|
||||
}
|
||||
Vendored
-29
@@ -1,29 +0,0 @@
|
||||
export interface ICreateOutputRequest {
|
||||
operation: string;
|
||||
name: string;
|
||||
plugin: string;
|
||||
values: Values;
|
||||
}
|
||||
|
||||
export interface Values {
|
||||
prefix: string;
|
||||
}
|
||||
|
||||
interface Info {
|
||||
user_id: string;
|
||||
customer_id: string;
|
||||
}
|
||||
|
||||
export interface IIdRequest {
|
||||
id: string;
|
||||
info: Info;
|
||||
}
|
||||
|
||||
export interface IOutputUpdateRequest {
|
||||
id: string;
|
||||
operation: string;
|
||||
values: Values;
|
||||
plugin: string;
|
||||
name: string;
|
||||
info: Info;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import { ClientOptions, Transport } from '@nestjs/microservices';
|
||||
import {
|
||||
PipelinePackages,
|
||||
PipelineProtoFilePath,
|
||||
} from 'protospack';
|
||||
import { credentials } from '@grpc/grpc-js';
|
||||
|
||||
export class PipelinesClientConfiguration {
|
||||
config(): ClientOptions {
|
||||
return {
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
url: process.env.PIFACTORY_URL,
|
||||
package: PipelinePackages,
|
||||
credentials: process.env.LOCAL_ENV
|
||||
? undefined
|
||||
: credentials.createSsl(),
|
||||
protoPath: PipelineProtoFilePath,
|
||||
loader: {
|
||||
enums: String,
|
||||
objects: true,
|
||||
arrays: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,273 +0,0 @@
|
||||
import {
|
||||
BadRequestException,
|
||||
Inject,
|
||||
InternalServerErrorException,
|
||||
OnModuleInit,
|
||||
} from '@nestjs/common';
|
||||
import { ClientGrpc, Payload } from '@nestjs/microservices';
|
||||
import { PipelineServicesNames, PipelinesServiceInterface } from 'protospack';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import {
|
||||
objectCamelToSnake,
|
||||
objectSnakeToCamel,
|
||||
} from 'src/utils/CaseConverter';
|
||||
import {
|
||||
ICreatePipelineDto,
|
||||
IGetPipelineLogsRequest,
|
||||
IIdRequest,
|
||||
IUpdatePipelineRequest,
|
||||
} from './interfaces';
|
||||
import { DadosferaLogger } from 'dadosfera-logs';
|
||||
|
||||
export class PipelinesClientService implements OnModuleInit {
|
||||
private pipelineService: PipelinesServiceInterface;
|
||||
logger: any;
|
||||
constructor(
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
@Inject('PIPELINES_PACKAGE') private readonly grpcClient: ClientGrpc,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
|
||||
onModuleInit() {
|
||||
this.pipelineService =
|
||||
this.grpcClient.getService<PipelinesServiceInterface>(
|
||||
PipelineServicesNames.PipelineService,
|
||||
);
|
||||
}
|
||||
|
||||
async create(@Payload() createPipelineDto: ICreatePipelineDto) {
|
||||
this.logger.info('PipelinesClientService - Create');
|
||||
const createPipelineResponse = await lastValueFrom(
|
||||
this.pipelineService.Create(objectSnakeToCamel(createPipelineDto)),
|
||||
)
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((error: { details: string }) => {
|
||||
if (error.details.includes('INVALID_REQUEST')) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [errorType, message] = error.details.split('|');
|
||||
throw new BadRequestException(message);
|
||||
}
|
||||
throw new InternalServerErrorException(error.details);
|
||||
});
|
||||
|
||||
return createPipelineResponse;
|
||||
}
|
||||
|
||||
async findAll(data: IIdRequest) {
|
||||
this.logger.info('PipelinesClientService - FindAll');
|
||||
const findAllPipelineResponse = await new Promise((resolve, reject) => {
|
||||
this.pipelineService.FindAll(objectSnakeToCamel(data)).subscribe({
|
||||
next(x) {
|
||||
resolve(x.pipelines);
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
// console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return findAllPipelineResponse;
|
||||
}
|
||||
|
||||
async findOne(data: IIdRequest) {
|
||||
this.logger.info('PipelinesClientService - FindOne');
|
||||
|
||||
const findOnePipelineResponse = await new Promise((resolve, reject) => {
|
||||
this.pipelineService.FindOne(objectSnakeToCamel(data)).subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
// console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return findOnePipelineResponse;
|
||||
}
|
||||
|
||||
async update(UpdatePipelineRequest: IUpdatePipelineRequest) {
|
||||
this.logger.info('PipelinesClientService - Update');
|
||||
|
||||
const updatePipelineResponse = await new Promise((resolve, reject) => {
|
||||
this.pipelineService
|
||||
.Update(objectSnakeToCamel(UpdatePipelineRequest))
|
||||
.subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
//console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return updatePipelineResponse;
|
||||
}
|
||||
|
||||
async remove(data: IIdRequest) {
|
||||
this.logger.info('PipelinesClientService - Remove');
|
||||
|
||||
const removePipelineResponse = await new Promise((resolve, reject) => {
|
||||
this.pipelineService.remove(objectSnakeToCamel(data)).subscribe({
|
||||
next(x) {
|
||||
resolve(objectCamelToSnake(x));
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
// this.logger.info('Done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return removePipelineResponse;
|
||||
}
|
||||
|
||||
async getPipelineLogsMessages(data: IGetPipelineLogsRequest) {
|
||||
this.logger.info('PipelinesClientService - GetPipelineLogsMessages');
|
||||
|
||||
const logsPipelineResponse = await new Promise((resolve, reject) => {
|
||||
this.pipelineService.getPipelineLogs(data).subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
// this.logger.info('Done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return logsPipelineResponse;
|
||||
}
|
||||
|
||||
async getPipelineStatus(data) {
|
||||
this.logger.info('PipelinesClientService - GetPipelineStatus');
|
||||
|
||||
const statusPipelineResponse = await new Promise((resolve, reject) => {
|
||||
this.pipelineService
|
||||
.getPipelineStatus(objectSnakeToCamel(data))
|
||||
.subscribe({
|
||||
next(x) {
|
||||
const statusArray = x.status.sort((a, b) => {
|
||||
if (a.id < b.id) {
|
||||
return 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
});
|
||||
resolve({ status: statusArray });
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
// this.logger.info('Done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return statusPipelineResponse;
|
||||
}
|
||||
|
||||
async runPipeline({ id, info }: IIdRequest) {
|
||||
this.logger.info('PipelinesClientService - RunPipeline');
|
||||
const statusPipelineResponse = await new Promise((resolve, reject) => {
|
||||
this.pipelineService
|
||||
.triggerPipeline(objectSnakeToCamel({ id, info }))
|
||||
.subscribe({
|
||||
next(x) {
|
||||
if (x.status == false) {
|
||||
reject(
|
||||
'This pipeline is not ready yet to execute, Try again later!',
|
||||
);
|
||||
}
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
this.logger.error('Observable Error');
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
this.logger.info('Done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return statusPipelineResponse;
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import { ClientOptions, Transport } from '@nestjs/microservices';
|
||||
import {
|
||||
TransformationPackages,
|
||||
TransformationProtoFilePath,
|
||||
} from 'protospack';
|
||||
import { credentials } from '@grpc/grpc-js';
|
||||
|
||||
export class TransformationsClientConfiguration {
|
||||
config(): ClientOptions {
|
||||
return {
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
url: process.env.INFACTORY_URL,
|
||||
package: TransformationPackages,
|
||||
credentials: credentials.createSsl(),
|
||||
protoPath: TransformationProtoFilePath,
|
||||
loader: {
|
||||
enums: String,
|
||||
objects: true,
|
||||
arrays: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,194 +0,0 @@
|
||||
import { Controller, Inject, OnModuleInit, Post } from '@nestjs/common';
|
||||
import { ClientGrpc } from '@nestjs/microservices';
|
||||
import { TransformationsServiceInterface } from 'protospack';
|
||||
import { DadosferaLogger } from 'dadosfera-logs';
|
||||
import {
|
||||
objectCamelToSnake,
|
||||
objectSnakeToCamel,
|
||||
} from 'src/utils/CaseConverter';
|
||||
import { ICreateTransformationsRequest, IIdRequest } from './interfaces';
|
||||
|
||||
@Controller('transformation')
|
||||
export class TransformationsClientService implements OnModuleInit {
|
||||
private transformationService: TransformationsServiceInterface;
|
||||
logger: any;
|
||||
constructor(
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
@Inject('TRANSFORMATIONS_PACKAGE') private readonly grpcClient: ClientGrpc,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
|
||||
onModuleInit() {
|
||||
this.transformationService =
|
||||
this.grpcClient.getService<TransformationsServiceInterface>(
|
||||
'TransformationService',
|
||||
);
|
||||
}
|
||||
|
||||
@Post()
|
||||
async create(createTransformationsDto: ICreateTransformationsRequest) {
|
||||
this.logger.info('TransformationClientService - Create');
|
||||
|
||||
const createTransformationResponse = await new Promise(
|
||||
(resolve, reject) => {
|
||||
this.transformationService
|
||||
.Create(objectSnakeToCamel(createTransformationsDto))
|
||||
.subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
// console.log('done');
|
||||
},
|
||||
});
|
||||
},
|
||||
)
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
const convertedTransforms = createTransformationResponse[
|
||||
'transformations'
|
||||
].map((tr) => {
|
||||
return objectCamelToSnake(tr);
|
||||
});
|
||||
|
||||
return { transformations: convertedTransforms };
|
||||
}
|
||||
|
||||
async findAll(data) {
|
||||
this.logger.info('TransformationClientService - FindAll');
|
||||
|
||||
const findAllTransformationResponse = await new Promise(
|
||||
(resolve, reject) => {
|
||||
this.transformationService.FindAll(objectSnakeToCamel(data)).subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
// console.log('done');
|
||||
},
|
||||
});
|
||||
},
|
||||
)
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
const convertedTransforms = findAllTransformationResponse[
|
||||
'transformations'
|
||||
].map((tr) => {
|
||||
return objectCamelToSnake(tr);
|
||||
});
|
||||
return { transformations: convertedTransforms };
|
||||
}
|
||||
|
||||
async findOne(data: IIdRequest) {
|
||||
this.logger.info('TransformationClientService - FindOne');
|
||||
|
||||
const findOneTransformationResponse = await new Promise(
|
||||
(resolve, reject) => {
|
||||
this.transformationService.FindOne(objectSnakeToCamel(data)).subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
// console.log('done');
|
||||
},
|
||||
});
|
||||
},
|
||||
)
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return objectCamelToSnake(findOneTransformationResponse);
|
||||
}
|
||||
|
||||
async update(updateTransformationDTO) {
|
||||
this.logger.info('TransformationClientService - Update');
|
||||
|
||||
const updateTransformationResponse = await new Promise(
|
||||
(resolve, reject) => {
|
||||
this.transformationService
|
||||
.Update(objectSnakeToCamel(updateTransformationDTO))
|
||||
.subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
// console.log('done');
|
||||
},
|
||||
});
|
||||
},
|
||||
)
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return objectCamelToSnake(updateTransformationResponse);
|
||||
}
|
||||
|
||||
async remove(data: IIdRequest) {
|
||||
this.logger.info('TransformationClientService - Remove');
|
||||
|
||||
const removeTransformationResponse = await new Promise(
|
||||
(resolve, reject) => {
|
||||
this.transformationService.Remove(objectSnakeToCamel(data)).subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
// console.log('done');
|
||||
},
|
||||
});
|
||||
},
|
||||
)
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return objectCamelToSnake(removeTransformationResponse);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,32 @@
|
||||
import { ExceptionFilter, Catch, ArgumentsHost } from '@nestjs/common';
|
||||
import {
|
||||
ExceptionFilter,
|
||||
Catch,
|
||||
ArgumentsHost,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
} from '@nestjs/common';
|
||||
import { Response } from 'express';
|
||||
|
||||
import ErrorBuilder from '../utils/ErrorBuilder';
|
||||
|
||||
/**
|
||||
* ExceptionFilter to handle RpcException thrown by our microservices
|
||||
*
|
||||
* If it detects that the exception is already an **HttpException** or it is generated by our **ErrorBuilder**,
|
||||
* it will return the exception without any treatment.
|
||||
*/
|
||||
@Catch(Error)
|
||||
export class GrpcToHttpExceptionFilter implements ExceptionFilter {
|
||||
catch(exception: any, host: ArgumentsHost) {
|
||||
const ctx = host.switchToHttp();
|
||||
const response = ctx.getResponse<Response>();
|
||||
|
||||
// return this exception directly if is already of type ErrorBuilder,
|
||||
// else transform it using the ErrorBuilder
|
||||
if (exception instanceof HttpException) {
|
||||
return response
|
||||
.status(exception.getStatus())
|
||||
.json(exception.getResponse());
|
||||
}
|
||||
|
||||
const err =
|
||||
exception.constructor.name === ErrorBuilder.name
|
||||
? exception
|
||||
|
||||
+13
-21
@@ -2,31 +2,19 @@ if (process.env.ENV !== 'local') require('elastic-apm-node/start');
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
||||
import helmet from 'helmet';
|
||||
import { DadosferaLogger } from 'dadosfera-logs';
|
||||
|
||||
import documentEmpty from '../swagger_empty.json';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
|
||||
import { AppModule } from './app.module';
|
||||
import { writeFileSync } from 'fs';
|
||||
async function bootstrap() {
|
||||
DadosferaLogger.setupLogger({
|
||||
serviceName: 'maestro',
|
||||
serviceEnvironment: process.env.ENV,
|
||||
});
|
||||
const logger = new DadosferaLogger().logger;
|
||||
|
||||
const orginalWinstonLog = logger.log.bind(logger);
|
||||
logger.log = function (...kwargs: any[]) {
|
||||
if (kwargs[0] in logger.levels) {
|
||||
if (kwargs[0] == 'error') {
|
||||
orginalWinstonLog('error', kwargs[2]);
|
||||
}
|
||||
} else {
|
||||
orginalWinstonLog('info', ...kwargs);
|
||||
}
|
||||
};
|
||||
const logger = new DadosferaLogger();
|
||||
|
||||
const app = await NestFactory.create(AppModule, {
|
||||
logger: logger,
|
||||
logger,
|
||||
cors: {
|
||||
origin: '*',
|
||||
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
|
||||
@@ -37,20 +25,24 @@ async function bootstrap() {
|
||||
|
||||
app.use(helmet());
|
||||
|
||||
const date = new Date();
|
||||
|
||||
const config = new DocumentBuilder()
|
||||
.setTitle('Maestro')
|
||||
.setDescription('Documentation for Maestro gateway')
|
||||
.setVersion('1.0')
|
||||
.setVersion(
|
||||
`${date.getDate()}.${
|
||||
date.getMonth() + 1
|
||||
}.${date.getFullYear()} - ${date.getHours()}:${date.getMinutes()}`,
|
||||
)
|
||||
.addBearerAuth()
|
||||
.build();
|
||||
|
||||
const document = SwaggerModule.createDocument(app, config);
|
||||
|
||||
if (process.env.ENV != 'stg' && process.env.ENV != 'prd')
|
||||
SwaggerModule.setup('api', app, document);
|
||||
if (process.env.ENV === 'local') SwaggerModule.setup('api', app, document);
|
||||
|
||||
const swaggerDoc = process.env.ENV === 'dev' ? document : documentEmpty;
|
||||
SwaggerModule.setup('api', app, swaggerDoc);
|
||||
await writeFileSync('swagger.txt', JSON.stringify(JSON.stringify(document)));
|
||||
|
||||
await app.listen(3333);
|
||||
}
|
||||
|
||||
@@ -19,17 +19,21 @@ import {
|
||||
AuthEnableTotpMfaRequest,
|
||||
AuthDisableTotpMfaRequest,
|
||||
AuthVerifyTotpMfaRequest,
|
||||
} from 'protospack-v2/dist/lib/Duc/interfaces/messages';
|
||||
} from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/messages';
|
||||
|
||||
import { PERMISSIONS_GROUPS } from 'src/authentication/permissions.enum';
|
||||
import { RequireAllPermissions } from 'src/authentication/authentication.decorator';
|
||||
import { AuthClientService } from './auth.service';
|
||||
import { DadosferaLogger } from 'dadosfera-logs';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import { GrpcToHttpExceptionFilter } from '../../error/grpc-to-http-exception.filter';
|
||||
import { RequestUser, User } from 'src/authentication/user.decorator';
|
||||
import { Metadata } from '@grpc/grpc-js';
|
||||
|
||||
@ApiTags('Auth')
|
||||
@UseFilters(new GrpcToHttpExceptionFilter())
|
||||
@Controller('auth')
|
||||
export class AuthController {
|
||||
logger: any;
|
||||
logger: DadosferaLogger;
|
||||
|
||||
constructor(
|
||||
@Inject(DadosferaLogger)
|
||||
@@ -39,22 +43,44 @@ export class AuthController {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
|
||||
@Post('/sso/snowflake')
|
||||
@RequireAllPermissions(PERMISSIONS_GROUPS.SNOWFLAKE.permissions.OPEN)
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async snowflakeSignIn(
|
||||
@User() user: RequestUser,
|
||||
@Body('RelayState') relayState: string,
|
||||
) {
|
||||
this.logger.info('/auth - snowflakeSignIn');
|
||||
|
||||
return this.authClient.snowflakeSignIn({
|
||||
userId: user.user_id,
|
||||
relayState,
|
||||
});
|
||||
}
|
||||
|
||||
@Post('sign-in')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async signIn(@Body() { username, password, totp }: AuthSignInRequest) {
|
||||
async signIn(
|
||||
@Body() { username, password, totp }: AuthSignInRequest,
|
||||
@Headers('Dadosfera-Lang') language: string,
|
||||
) {
|
||||
this.logger.info('/auth - SignIn');
|
||||
|
||||
return this.authClient.signIn({ username, password, totp });
|
||||
const metadata = new Metadata();
|
||||
metadata.add('language', language || 'pt-br');
|
||||
return this.authClient.signIn({ username, password, totp }, metadata);
|
||||
}
|
||||
|
||||
@Post('refresh-access-token')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async refreshAccessToken(
|
||||
@Body() { refreshToken }: AuthRefreshAccessTokenRequest,
|
||||
@Headers('Dadosfera-Lang') language: string,
|
||||
) {
|
||||
this.logger.info('/auth - RefreshAccessToken');
|
||||
const metadata = new Metadata();
|
||||
metadata.add('language', language || 'pt-br');
|
||||
|
||||
return this.authClient.refreshAccessToken({ refreshToken });
|
||||
return this.authClient.refreshAccessToken({ refreshToken }, metadata);
|
||||
}
|
||||
|
||||
@Post('change-password')
|
||||
|
||||
@@ -1,22 +1,15 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ClientsModule } from '@nestjs/microservices';
|
||||
import { DadosferaLogger } from 'dadosfera-logs';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
|
||||
import { AuthController } from './auth.controller';
|
||||
import { AuthClientService } from './auth.service';
|
||||
|
||||
import { DucClient } from '../../clients/duc/client.config';
|
||||
const ducClient = new DucClient();
|
||||
import { DucClient } from '../duc/client.config';
|
||||
const client = new DucClient();
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ClientsModule.register([
|
||||
{
|
||||
name: 'DUC_PACKAGE',
|
||||
...ducClient.config(),
|
||||
},
|
||||
]),
|
||||
],
|
||||
imports: [ClientsModule.register([client.providerOptions])],
|
||||
controllers: [AuthController],
|
||||
providers: [AuthClientService, DadosferaLogger],
|
||||
exports: [AuthClientService],
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { OnModuleInit, Inject, Injectable } from '@nestjs/common';
|
||||
import { ClientGrpc } from '@nestjs/microservices';
|
||||
import { DadosferaLogger } from 'dadosfera-logs';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
|
||||
import { ProtoServices } from 'protospack-v2/dist/lib/Duc';
|
||||
import { AuthProtoService as AuthServiceInterface } from 'protospack-v2/dist/lib/Duc/interfaces/write-service';
|
||||
import { ProtoServices } from '@dadosfera/protospack-v2/dist/lib/Duc';
|
||||
import { AuthProtoService as AuthServiceInterface } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/write-service';
|
||||
import {
|
||||
AuthSnowflakeSignInRequest,
|
||||
AuthSignInRequest,
|
||||
AuthRefreshAccessTokenRequest,
|
||||
AuthEnableTotpMfaRequest,
|
||||
@@ -16,17 +17,19 @@ import {
|
||||
AuthResetPasswordRequest,
|
||||
AuthVerifyResetPasswordCodeRequest,
|
||||
AuthConfirmResetPasswordRequest,
|
||||
} from 'protospack-v2/dist/lib/Duc/interfaces/messages';
|
||||
} from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/messages';
|
||||
import { DucClient } from '../duc/client.config';
|
||||
import { Metadata } from '@grpc/grpc-js';
|
||||
|
||||
@Injectable()
|
||||
export class AuthClientService implements OnModuleInit {
|
||||
logger: any;
|
||||
logger: DadosferaLogger;
|
||||
|
||||
private authService: AuthServiceInterface;
|
||||
constructor(
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
@Inject('DUC_PACKAGE') private readonly grpcClient: ClientGrpc,
|
||||
@Inject(DucClient.name) private readonly grpcClient: ClientGrpc,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
@@ -43,19 +46,31 @@ export class AuthClientService implements OnModuleInit {
|
||||
return lastValueFrom(this.authService.AuthGetPublicKeys({}));
|
||||
}
|
||||
|
||||
async signIn({ username, password, totp }: AuthSignInRequest) {
|
||||
async snowflakeSignIn(input: AuthSnowflakeSignInRequest) {
|
||||
this.logger.info('snowflakeSignIn');
|
||||
|
||||
return lastValueFrom(this.authService.AuthSnowflakeSignIn(input));
|
||||
}
|
||||
|
||||
async signIn(
|
||||
{ username, password, totp }: AuthSignInRequest,
|
||||
metadata: Metadata,
|
||||
) {
|
||||
this.logger.info('SignIn');
|
||||
|
||||
return lastValueFrom(
|
||||
this.authService.AuthSignIn({ username, password, totp }),
|
||||
this.authService.AuthSignIn({ username, password, totp }, metadata),
|
||||
);
|
||||
}
|
||||
|
||||
async refreshAccessToken({ refreshToken }: AuthRefreshAccessTokenRequest) {
|
||||
async refreshAccessToken(
|
||||
{ refreshToken }: AuthRefreshAccessTokenRequest,
|
||||
metadata: Metadata,
|
||||
) {
|
||||
this.logger.info('RefreshAccessToken');
|
||||
|
||||
return lastValueFrom(
|
||||
this.authService.AuthRefreshAccessToken({ refreshToken }),
|
||||
this.authService.AuthRefreshAccessToken({ refreshToken }, metadata),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import {
|
||||
ClientsProviderAsyncOptions,
|
||||
GrpcOptions,
|
||||
Transport,
|
||||
} from '@nestjs/microservices';
|
||||
import { credentials } from '@grpc/grpc-js';
|
||||
import { Catalog } from '@dadosfera/protospack-v2';
|
||||
|
||||
export class CatalogClientConfiguration {
|
||||
public name = 'CatalogClientConfiguration';
|
||||
private config: GrpcOptions = {
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
url: process.env.PIFACTORY_URL,
|
||||
package: [
|
||||
Catalog.ProtoPackages.ReadPackage,
|
||||
Catalog.ProtoPackages.WritePackage,
|
||||
],
|
||||
credentials:
|
||||
process.env.LOCAL_ENV || process.env.ENV === 'local'
|
||||
? undefined
|
||||
: credentials.createSsl(),
|
||||
protoPath: [
|
||||
Catalog.ProtoPaths.ReadFilePath,
|
||||
Catalog.ProtoPaths.WriteFilePath,
|
||||
],
|
||||
loader: {
|
||||
keepCase: true,
|
||||
enums: String,
|
||||
defaults: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
providerOptions: ClientsProviderAsyncOptions = {
|
||||
name: this.name,
|
||||
...this.config,
|
||||
};
|
||||
}
|
||||
@@ -2,21 +2,31 @@ import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
ForbiddenException,
|
||||
Get,
|
||||
HttpException,
|
||||
Inject,
|
||||
Param,
|
||||
Post,
|
||||
Put,
|
||||
Query,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { AuthenticateCondition } from '../../authentication/authentication.decorator';
|
||||
import { Permissions } from '../../authentication/permissions.enum';
|
||||
import {
|
||||
AuthenticateCondition,
|
||||
Authenticated,
|
||||
} from '../../authentication/authentication.decorator';
|
||||
import { PERMISSIONS_GROUPS } from '../../authentication/permissions.enum';
|
||||
import { CatalogService } from './catalog.service';
|
||||
import { DadosferaLogger } from 'dadosfera-logs';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import { PackTheMetadata } from 'src/utils/ PackTheMetadata';
|
||||
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) {
|
||||
@@ -32,10 +42,12 @@ import { DadosferaLogger } from 'dadosfera-logs';
|
||||
action = req.method;
|
||||
}
|
||||
|
||||
return user.permissions.includes(Permissions.CATALOG[action].seqid);
|
||||
return user.permissions.includes(
|
||||
PERMISSIONS_GROUPS.CATALOG.permissions[action].seqid,
|
||||
);
|
||||
})
|
||||
export class CatalogController {
|
||||
logger: any;
|
||||
logger: DadosferaLogger;
|
||||
constructor(
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
@@ -44,16 +56,78 @@ export class CatalogController {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
|
||||
@Put('manage_permissions/:id')
|
||||
async manageDataAssetPermissions(
|
||||
@Param('id') id: string,
|
||||
@User() user: RequestUser,
|
||||
@Body() body,
|
||||
) {
|
||||
const { customer_id, customer_name, user_id, username } = user;
|
||||
const metadata = PackTheMetadata({
|
||||
customer_id,
|
||||
customer_name,
|
||||
user_id,
|
||||
username,
|
||||
});
|
||||
const response = await this.catalogService.managePermissions(
|
||||
{ ...body, id },
|
||||
metadata,
|
||||
);
|
||||
|
||||
return { data_asset: JSON.parse(response.data_asset) };
|
||||
}
|
||||
|
||||
@Put('revoke_permissions/:id')
|
||||
async revokeDataAssetPermissions(
|
||||
@Param('id') id: string,
|
||||
@User() user: RequestUser,
|
||||
@Body() body,
|
||||
) {
|
||||
const { customer_id, customer_name, user_id, username } = user;
|
||||
const metadata = PackTheMetadata({
|
||||
customer_id,
|
||||
customer_name,
|
||||
user_id,
|
||||
username,
|
||||
});
|
||||
const response = await this.catalogService.revokePermissions(
|
||||
{ ...body, id },
|
||||
metadata,
|
||||
);
|
||||
|
||||
return { message: response.message };
|
||||
}
|
||||
|
||||
@Get('all')
|
||||
async catalogAll(@Body() body) {
|
||||
async catalogAll(@User() user: RequestUser, @Body() body, @Query() params) {
|
||||
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 res = await this.catalogService.catalogAll(body);
|
||||
const is_data_manager = permissions.includes(
|
||||
PERMISSIONS_GROUPS.CATALOG.permissions.DATA_MANAGER.seqid,
|
||||
);
|
||||
|
||||
return res;
|
||||
const roles = await this.catalogService.getUserRolesIds(user_id);
|
||||
|
||||
const metadata = PackTheMetadata({
|
||||
user_id,
|
||||
customer_id,
|
||||
customer_name,
|
||||
username,
|
||||
roles,
|
||||
is_data_manager,
|
||||
});
|
||||
|
||||
const res = await this.catalogService.getAllOpenSearchDataAssets(
|
||||
params,
|
||||
metadata,
|
||||
customer_id,
|
||||
);
|
||||
|
||||
return res.data_assets;
|
||||
}
|
||||
|
||||
@Get('data_apps')
|
||||
@@ -94,31 +168,168 @@ export class CatalogController {
|
||||
}
|
||||
|
||||
@Get('dashboard-metabase/:id')
|
||||
async getOneDashboardMetabase(@Body() body, @Param() params) {
|
||||
async getOneDashboardMetabase(
|
||||
@Body() body,
|
||||
@Param() params,
|
||||
@User() user: RequestUser,
|
||||
) {
|
||||
const { id } = params;
|
||||
this.logger.info(`/catalog - ON GET ONE DASHBOARD METABASE ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
});
|
||||
|
||||
const res = await this.catalogService.getOneDashboardMetabase(id, body);
|
||||
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,
|
||||
customer_id,
|
||||
customer_name,
|
||||
});
|
||||
|
||||
return res;
|
||||
const user_roles = await this.catalogService.getUserRolesIds(user_id);
|
||||
|
||||
const res = await this.catalogService.getOneDashboardMetabase({
|
||||
id,
|
||||
body,
|
||||
metadata,
|
||||
customer_id,
|
||||
user_id: undefined,
|
||||
});
|
||||
|
||||
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('dashboard-metabase/rls/:id')
|
||||
async getOneDashboardMetabaseRls(
|
||||
@Body() body,
|
||||
@Param() params,
|
||||
@User() user: RequestUser,
|
||||
) {
|
||||
const { username, user_id, customer_id, customer_name, permissions } = user;
|
||||
const { id } = params;
|
||||
this.logger.info(`/catalog - ON GET ONE DASHBOARD METABASE ROUTE`, {
|
||||
username,
|
||||
customer_name,
|
||||
});
|
||||
|
||||
const is_data_manager = permissions.includes(
|
||||
PERMISSIONS_GROUPS.CATALOG.permissions.DATA_MANAGER.seqid,
|
||||
);
|
||||
let has_permission = false;
|
||||
const metadata = PackTheMetadata({
|
||||
username,
|
||||
user_id,
|
||||
customer_id,
|
||||
customer_name,
|
||||
});
|
||||
|
||||
const user_roles = await this.catalogService.getUserRolesIds(user_id);
|
||||
|
||||
const res = await this.catalogService.getOneDashboardMetabase({
|
||||
id,
|
||||
body,
|
||||
metadata,
|
||||
customer_id,
|
||||
user_id,
|
||||
});
|
||||
|
||||
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')
|
||||
async getAllTableMetadata(@Body() body, @Query() query) {
|
||||
async getAllTableMetadata(
|
||||
@Body() body,
|
||||
@Query() query,
|
||||
@User() user: RequestUser,
|
||||
) {
|
||||
this.logger.info(`/catalog - ON GET ALL TABLES METADATA ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
user: user.user_id,
|
||||
customer: user.customer_name,
|
||||
});
|
||||
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,
|
||||
customer_name,
|
||||
});
|
||||
|
||||
if (!query) {
|
||||
const res = await this.catalogService.getAllTableMetadata(body);
|
||||
return res;
|
||||
} else {
|
||||
const res = await this.catalogService.getOneTableMetadata(body, query);
|
||||
return res;
|
||||
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.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,15 +420,19 @@ export class CatalogController {
|
||||
}
|
||||
|
||||
@Post('data-description')
|
||||
async createDataDescription(@Body() body) {
|
||||
async createDataDescription(@Body() body, @User() user: RequestUser) {
|
||||
this.logger.info(`/catalog - ON CREATE DATA DESCRIPTION ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
user: user.user_id,
|
||||
customer: user.customer_name,
|
||||
});
|
||||
|
||||
const res = await this.catalogService.createDataDescription(body);
|
||||
|
||||
return res;
|
||||
const { user_id, customer_name, customer_id } = user;
|
||||
const metadata = PackTheMetadata({
|
||||
user_id,
|
||||
customer_id,
|
||||
customer_name,
|
||||
});
|
||||
return await this.catalogService.createDataDescription(body, metadata);
|
||||
}
|
||||
|
||||
@Get('data-docs')
|
||||
@@ -320,15 +535,21 @@ export class CatalogController {
|
||||
}
|
||||
|
||||
@Post('tags')
|
||||
async createTags(@Body() body) {
|
||||
async createTags(@Body() body, @User() user: RequestUser) {
|
||||
this.logger.info(`/catalog - ON CREATE TAG ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
user: user.user_id,
|
||||
customer: user.customer_name,
|
||||
});
|
||||
const { user_id, customer_name, customer_id } = user;
|
||||
const metadata = PackTheMetadata({
|
||||
user_id,
|
||||
customer_id,
|
||||
customer_name,
|
||||
});
|
||||
|
||||
const res = await this.catalogService.createTags(body);
|
||||
const res = await this.catalogService.createTags(body, metadata);
|
||||
|
||||
return res;
|
||||
return res.data_assets;
|
||||
}
|
||||
|
||||
@Get('tags')
|
||||
@@ -338,7 +559,14 @@ export class CatalogController {
|
||||
customer: body.info.customer,
|
||||
});
|
||||
|
||||
const res = await this.catalogService.findAllTags(body);
|
||||
const { user_id, customer, customer_id } = body.info;
|
||||
const metadata = PackTheMetadata({
|
||||
user_id,
|
||||
customer_id,
|
||||
customer_name: customer,
|
||||
});
|
||||
|
||||
const res = await this.catalogService.findAllTags(body, metadata);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -350,8 +578,14 @@ export class CatalogController {
|
||||
customer: body.info.customer,
|
||||
});
|
||||
const { id } = params;
|
||||
|
||||
const res = await this.catalogService.deleteTags(id, body);
|
||||
body.data_asset_id = id;
|
||||
const { user_id, customer, customer_id } = body.info;
|
||||
const metadata = PackTheMetadata({
|
||||
user_id,
|
||||
customer_id,
|
||||
customer_name: customer,
|
||||
});
|
||||
const res = await this.catalogService.deleteTags(body, metadata);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -368,14 +602,19 @@ export class CatalogController {
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('table-tags')
|
||||
async getAllTableTags(@Body() body) {
|
||||
@Get('table-tags/:data_asset_id')
|
||||
async getAllTableTags(@Body() body, @Param() params) {
|
||||
this.logger.info(`/catalog - ON GET ALL TABLE TAGS ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
});
|
||||
|
||||
const res = await this.catalogService.findAllTableTags(body);
|
||||
const { user_id, customer, customer_id } = body.info;
|
||||
const metadata = PackTheMetadata({
|
||||
user_id,
|
||||
customer_id,
|
||||
customer_name: customer,
|
||||
});
|
||||
const res = await this.catalogService.findAllTableTags(params, metadata);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
|
||||
import { CatalogController } from './catalog.controller';
|
||||
import { CatalogService } from './catalog.service';
|
||||
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();
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ClientsModule.register([client.providerOptions]),
|
||||
OldPipelineModule,
|
||||
UsersModule,
|
||||
RolesModule,
|
||||
],
|
||||
controllers: [CatalogController],
|
||||
providers: [CatalogService, DadosferaLogger],
|
||||
exports: [CatalogService],
|
||||
})
|
||||
export class CatalogModule {}
|
||||
@@ -1,6 +1,47 @@
|
||||
import DadosferaLogger from '@dadosfera/dadosfera-logs/dist';
|
||||
import { ReadService } from '@dadosfera/protospack-v2/dist/lib/Catalog';
|
||||
import { ProtoServices } from '@dadosfera/protospack-v2/dist/lib/Catalog';
|
||||
import { Messages } from '@dadosfera/protospack-v2/dist/lib/Catalog';
|
||||
import { WriteService } from '@dadosfera/protospack-v2/dist/lib/Catalog';
|
||||
import {
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
Inject,
|
||||
OnModuleInit,
|
||||
} from '@nestjs/common';
|
||||
import { ClientGrpc } from '@nestjs/microservices';
|
||||
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;
|
||||
catalogWriteService: WriteService.CatalogWriteServices;
|
||||
logger: any;
|
||||
constructor(
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
@Inject(CatalogClientConfiguration.name)
|
||||
private readonly grpcClient: ClientGrpc,
|
||||
private readonly userService: UsersService,
|
||||
private readonly roleService: RolesService,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
|
||||
onModuleInit() {
|
||||
this.catalogReadService =
|
||||
this.grpcClient.getService<ReadService.CatalogReadServices>(
|
||||
ProtoServices.CatalogReadServices,
|
||||
);
|
||||
this.catalogWriteService =
|
||||
this.grpcClient.getService<WriteService.CatalogWriteServices>(
|
||||
ProtoServices.CatalogWriteServices,
|
||||
);
|
||||
}
|
||||
|
||||
class CatalogService {
|
||||
_getNimbusUrl(body) {
|
||||
const customer = body.info.customer.toLowerCase();
|
||||
|
||||
@@ -8,7 +49,36 @@ class CatalogService {
|
||||
return `https://nimbus-${customer}.dadosfera.ai`;
|
||||
}
|
||||
|
||||
return `https://nimbus-${customer}.${process.env.ENV}.dadosfera.ai`;
|
||||
return `https://nimbus-${customer}.${process.env.ENV.replace(
|
||||
'local',
|
||||
'stg',
|
||||
)}.dadosfera.ai`;
|
||||
}
|
||||
|
||||
async managePermissions(data: Messages.ManagePermissionRequest, metadata) {
|
||||
this.logger.info('CatalogService - Manage Data assets permissions');
|
||||
|
||||
return lastValueFrom(
|
||||
this.catalogWriteService.ManagePermission(data, metadata),
|
||||
).catch((err) => {
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 404,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async revokePermissions(data: Messages.RevokePermissionRequest, metadata) {
|
||||
this.logger.info('CatalogService - Manage Data assets permissions');
|
||||
|
||||
return lastValueFrom(
|
||||
this.catalogWriteService.RevokePermission(data, metadata),
|
||||
).catch((err) => {
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 404,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async catalogAll(body) {
|
||||
@@ -41,15 +111,177 @@ class CatalogService {
|
||||
return data;
|
||||
}
|
||||
|
||||
async getOneDashboardMetabase(id, body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(
|
||||
`${nimbusUrl}/api/catalog/dashboard-metabase/${id}`,
|
||||
async getUserRolesIds(userId: string) {
|
||||
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 [, path] = data.iframe_url.split('.dadosfera');
|
||||
// const host = `httpss://metabase-${body.info.customer.toLowerCase()}.dadosfera.ai`;
|
||||
// data.iframe_url = host + path;
|
||||
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),
|
||||
).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 data_assets.dashboards) {
|
||||
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,
|
||||
});
|
||||
}
|
||||
|
||||
return { data_assets };
|
||||
}
|
||||
|
||||
async getOneDashboardMetabase({ id, body, metadata, customer_id, user_id }) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(
|
||||
`${nimbusUrl}/api/catalog/dashboard-metabase/${id}?user_id=${user_id}`,
|
||||
);
|
||||
|
||||
const { data_asset } = await lastValueFrom(
|
||||
this.catalogReadService.GetOneDataAsset(
|
||||
{ id, type: 'dashboard' },
|
||||
metadata,
|
||||
),
|
||||
);
|
||||
const opensearchTable = JSON.parse(data_asset);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Object.assign(data.dashboard, {
|
||||
tags: opensearchTable.tags,
|
||||
description: opensearchTable.description || null,
|
||||
p_roles: opensearchTable.roles,
|
||||
p_users: opensearchTable.users,
|
||||
roles,
|
||||
users,
|
||||
owner,
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
@@ -62,12 +294,59 @@ class CatalogService {
|
||||
return data;
|
||||
}
|
||||
|
||||
async getOneTableMetadata(body, params) {
|
||||
async getOneTableMetadata(body, params, metadata, customer_id) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(
|
||||
`${nimbusUrl}/api/catalog/table-metadata/`,
|
||||
{ params: params },
|
||||
);
|
||||
if (data?.length === 1) {
|
||||
const { data_asset } = await lastValueFrom(
|
||||
this.catalogReadService.GetOneDataAsset(
|
||||
{ id: data[0].id, type: 'dataset' },
|
||||
metadata,
|
||||
),
|
||||
);
|
||||
const opensearchTable = JSON.parse(data_asset);
|
||||
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,
|
||||
},
|
||||
];
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -127,13 +406,34 @@ class CatalogService {
|
||||
return data;
|
||||
}
|
||||
|
||||
async createDataDescription(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.post(
|
||||
`${nimbusUrl}/api/catalog/data-description/`,
|
||||
body,
|
||||
async createDataDescription(body, metadata) {
|
||||
await lastValueFrom(
|
||||
this.catalogWriteService.UpdateDataAsset(
|
||||
{
|
||||
id: `dataset-${body.table_id}`,
|
||||
description: body.description,
|
||||
tags: undefined,
|
||||
},
|
||||
metadata,
|
||||
),
|
||||
);
|
||||
return data;
|
||||
// {
|
||||
// description: 'descrição nova';
|
||||
// id: 5;
|
||||
// table_id: 4;
|
||||
// }
|
||||
// const nimbusUrl = this._getNimbusUrl(body);
|
||||
// const { data } = await axios.post(
|
||||
// `${nimbusUrl}/api/catalog/data-description/`,
|
||||
// body,
|
||||
// );
|
||||
// {"id":5,"description":"descrição nova","updated_at":"2022-09-28T14:35:15.618750Z","table_id":4}
|
||||
return {
|
||||
id: 0,
|
||||
description: body.description,
|
||||
updated_at: new Date().toISOString(),
|
||||
table_id: body.table_id,
|
||||
};
|
||||
}
|
||||
|
||||
async getDataDocs(body) {
|
||||
@@ -197,31 +497,76 @@ class CatalogService {
|
||||
return data;
|
||||
}
|
||||
|
||||
async createTags(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.post(`${nimbusUrl}/api/catalog/tags/`, body);
|
||||
return data;
|
||||
async createTags(data: Messages.TagTableRequest, metadata) {
|
||||
this.logger.info('CatalogService - createTags');
|
||||
|
||||
const response = await lastValueFrom(
|
||||
this.catalogWriteService.TagTable(data, metadata),
|
||||
)
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return { data_assets: response };
|
||||
}
|
||||
|
||||
async findAllTags(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(`${nimbusUrl}/api/catalog/tags/`, body);
|
||||
return data;
|
||||
async findAllTags(data, metadata) {
|
||||
this.logger.info('CatalogService - findAllCustomerTags');
|
||||
|
||||
const response = await lastValueFrom(
|
||||
this.catalogReadService.GetCustomerTags(data, metadata),
|
||||
)
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
async findAllTableTags(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(
|
||||
`${nimbusUrl}/api/catalog/table-tags/`,
|
||||
body,
|
||||
);
|
||||
return data;
|
||||
async findAllTableTags(data, metadata) {
|
||||
this.logger.info('CatalogService - findAllTableTags');
|
||||
|
||||
const response = await lastValueFrom(
|
||||
this.catalogReadService.GetTableTags(data, metadata),
|
||||
)
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
async deleteTags(id, body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.delete(`${nimbusUrl}/api/catalog/tags/${id}`);
|
||||
return data;
|
||||
async deleteTags(data, metadata) {
|
||||
this.logger.info('CatalogService - deleteTags');
|
||||
|
||||
const response = await lastValueFrom(
|
||||
this.catalogWriteService.UntagTable(data, metadata),
|
||||
)
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
async createTableTags(body) {
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import { credentials } from '@grpc/grpc-js';
|
||||
import {
|
||||
ClientProviderOptions,
|
||||
GrpcOptions,
|
||||
Transport,
|
||||
} from '@nestjs/microservices';
|
||||
import { ConnectionTest } from '@dadosfera/protospack-v2';
|
||||
|
||||
export class ConnectionTestClientConfiguration {
|
||||
private config: GrpcOptions = {
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
url: process.env.INFACTORY_URL,
|
||||
package: [ConnectionTest.ProtoPackages.ReadPackage],
|
||||
credentials:
|
||||
process.env.ENV === 'local' ? undefined : credentials.createSsl(),
|
||||
protoPath: [ConnectionTest.ProtoPaths.ReadFilePath],
|
||||
loader: {
|
||||
keepCase: true,
|
||||
enums: String,
|
||||
objects: true,
|
||||
arrays: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
providerOptions: ClientProviderOptions = {
|
||||
name: 'ConnectionTestGrpcClient',
|
||||
...this.config,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
HttpCode,
|
||||
HttpStatus,
|
||||
Inject,
|
||||
Post,
|
||||
UseFilters,
|
||||
ValidationPipe,
|
||||
} from '@nestjs/common';
|
||||
import { ApiOkResponse, ApiTags } from '@nestjs/swagger';
|
||||
import { User, RequestUser } from 'src/authentication/user.decorator';
|
||||
import { ConnectionTestService } from './connection-test.service';
|
||||
import {
|
||||
ConnectionTestPingRes,
|
||||
ConnectionTestPingReq,
|
||||
ConnectionTestCredentialsReq,
|
||||
ConnectionTestCredentialsRes,
|
||||
ConnectionTestListSchemasReq,
|
||||
ConnectionTestListSchemasRes,
|
||||
ConnectionTestListTablesReq,
|
||||
ConnectionTestListTablesRes,
|
||||
GetTableMetadataRes,
|
||||
GetTableMetadataReq,
|
||||
} from './dto/connection-test';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import { Authenticated } from 'src/authentication/authentication.decorator';
|
||||
import { GrpcToHttpExceptionFilter } from 'src/error/grpc-to-http-exception.filter';
|
||||
|
||||
@ApiTags('Connection Test')
|
||||
@Controller('connection-test')
|
||||
@UseFilters(new GrpcToHttpExceptionFilter())
|
||||
@Authenticated()
|
||||
export class ConnectionTestController {
|
||||
logger: any;
|
||||
constructor(
|
||||
private connectionTestService: ConnectionTestService,
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
|
||||
@Post('ping')
|
||||
@ApiOkResponse({ type: ConnectionTestPingRes })
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async connectionTestPing(
|
||||
@User() user: RequestUser,
|
||||
@Body(new ValidationPipe()) body: ConnectionTestPingReq,
|
||||
) {
|
||||
this.logger.info('/connection-test/ping', {
|
||||
user: user.user_id,
|
||||
customer: user.customer_name,
|
||||
});
|
||||
return this.connectionTestService.connectionTestPing(body, user);
|
||||
}
|
||||
|
||||
@Post('credentials')
|
||||
@ApiOkResponse({ type: ConnectionTestCredentialsRes })
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async connectionTestCredentials(
|
||||
@User() user: RequestUser,
|
||||
@Body() body: ConnectionTestCredentialsReq,
|
||||
) {
|
||||
this.logger.info('/connection-test/credentials', {
|
||||
user: user.user_id,
|
||||
customer: user.customer_name,
|
||||
});
|
||||
return this.connectionTestService.connectionTestCredentials(body, user);
|
||||
}
|
||||
|
||||
@Post('schemas')
|
||||
@ApiOkResponse({ type: ConnectionTestListSchemasRes })
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async connectionTestListSchemas(
|
||||
@User() user: RequestUser,
|
||||
@Body(new ValidationPipe()) body: ConnectionTestListSchemasReq,
|
||||
) {
|
||||
this.logger.info('/connection-test/schemas', {
|
||||
user: user.user_id,
|
||||
customer: user.customer_name,
|
||||
});
|
||||
return this.connectionTestService.connectionTestListSchemas(
|
||||
body,
|
||||
user.customer_name,
|
||||
);
|
||||
}
|
||||
|
||||
@Post('tables')
|
||||
@ApiOkResponse({ type: ConnectionTestListTablesRes })
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async connectionTestListTables(
|
||||
@User() user: RequestUser,
|
||||
@Body(new ValidationPipe()) body: ConnectionTestListTablesReq,
|
||||
) {
|
||||
this.logger.info('/connection-test/tables', {
|
||||
user: user.user_id,
|
||||
customer: user.customer_name,
|
||||
});
|
||||
return this.connectionTestService.connectionTestListTables(
|
||||
body,
|
||||
user.customer_name,
|
||||
);
|
||||
}
|
||||
|
||||
@Post('table-metadata')
|
||||
@ApiOkResponse({ type: GetTableMetadataRes })
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async getTableMetadata(
|
||||
@User() user: RequestUser,
|
||||
@Body(new ValidationPipe()) body: GetTableMetadataReq,
|
||||
) {
|
||||
this.logger.info('/connection-test/table-metadata', {
|
||||
user: user.user_id,
|
||||
customer: user.customer_name,
|
||||
});
|
||||
return this.connectionTestService.getTableMetadata(
|
||||
body,
|
||||
user.customer_name,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ConnectionTestController } from './connection-test.controller';
|
||||
import { ConnectionTestService } from './connection-test.service';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import { ClientsModule } from '@nestjs/microservices';
|
||||
import { ConnectionTestClientConfiguration } from './connection-test-client.config';
|
||||
import { ConnectionModule } from '../connection/connection.module';
|
||||
const client = new ConnectionTestClientConfiguration();
|
||||
@Module({
|
||||
controllers: [ConnectionTestController],
|
||||
providers: [ConnectionTestService, DadosferaLogger],
|
||||
imports: [ClientsModule.register([client.providerOptions]), ConnectionModule],
|
||||
})
|
||||
export class ConnectionTestModule {}
|
||||
@@ -0,0 +1,191 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { ClientGrpc } from '@nestjs/microservices';
|
||||
import { ConnectionTest } from '@dadosfera/protospack-v2';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import {
|
||||
ConnectionTestCredentialsReq,
|
||||
ConnectionTestCredentialsRes,
|
||||
ConnectionTestListSchemasReq,
|
||||
ConnectionTestListSchemasRes,
|
||||
ConnectionTestListTablesReq,
|
||||
ConnectionTestListTablesRes,
|
||||
ConnectionTestPingReq,
|
||||
ConnectionTestPingRes,
|
||||
GetTableMetadataReq,
|
||||
GetTableMetadataRes,
|
||||
} from './dto/connection-test';
|
||||
import { ConnectionClientService } from '../connection/client.service';
|
||||
import {
|
||||
CreateConnectionDto,
|
||||
DatabaseConnectionPropertiesDto,
|
||||
} from '../connection/dtos/connection';
|
||||
import { RequestUser } from 'src/authentication/user.decorator';
|
||||
import { PackTheMetadata } from 'src/utils/ PackTheMetadata';
|
||||
|
||||
@Injectable()
|
||||
export class ConnectionTestService {
|
||||
private connectionTestReadClient: ConnectionTest.ReadService.ConnectionTestReadServices;
|
||||
constructor(
|
||||
@Inject('ConnectionTestGrpcClient') private readonly grpcClient: ClientGrpc,
|
||||
private connectionsService: ConnectionClientService,
|
||||
) {
|
||||
this.connectionTestReadClient =
|
||||
grpcClient.getService<ConnectionTest.ReadService.ConnectionTestReadServices>(
|
||||
ConnectionTest.ProtoServices.ConnectionTestReadServices,
|
||||
);
|
||||
}
|
||||
|
||||
async connectionTestPing(
|
||||
body: ConnectionTestPingReq,
|
||||
user: RequestUser,
|
||||
): Promise<ConnectionTestPingRes> {
|
||||
const {
|
||||
host: endpoint,
|
||||
plugin,
|
||||
port,
|
||||
network_config_id,
|
||||
connection_id,
|
||||
} = body;
|
||||
const { user_id, customer_id, customer_name } = user;
|
||||
const metadata = PackTheMetadata({
|
||||
customer_name,
|
||||
customer_id,
|
||||
user_id,
|
||||
});
|
||||
|
||||
if (connection_id) {
|
||||
const con = await this.connectionsService.getConnectionDetails({
|
||||
body,
|
||||
metadata,
|
||||
});
|
||||
const conPayload = JSON.parse(con.connection.properties);
|
||||
const { plugin, network_config_id } = con.connection;
|
||||
const { host, port, endpoint } = conPayload;
|
||||
|
||||
return lastValueFrom(
|
||||
this.connectionTestReadClient.ConnectionTestPing({
|
||||
customer_name,
|
||||
endpoint: endpoint || host,
|
||||
network_config_id,
|
||||
plugin,
|
||||
port: port ? port.toString() : undefined,
|
||||
connection_id,
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
return lastValueFrom(
|
||||
this.connectionTestReadClient.ConnectionTestPing({
|
||||
customer_name,
|
||||
endpoint,
|
||||
network_config_id,
|
||||
plugin,
|
||||
port: port ? port.toString() : undefined,
|
||||
connection_id,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
async connectionTestCredentials(
|
||||
body: ConnectionTestCredentialsReq,
|
||||
user: RequestUser,
|
||||
): Promise<ConnectionTestCredentialsRes> {
|
||||
const { plugin, ...connectionBody } = body;
|
||||
let { connection_id } = body;
|
||||
const { customer_id, customer_name, user_id, username } = user;
|
||||
const metadata = PackTheMetadata({
|
||||
customer_id,
|
||||
customer_name,
|
||||
user_id,
|
||||
username,
|
||||
});
|
||||
|
||||
if (body.network_config_id == '') {
|
||||
body.network_config_id = undefined;
|
||||
}
|
||||
|
||||
/********* CREATE CONNECTION *********/
|
||||
if (!connection_id) {
|
||||
const properties: DatabaseConnectionPropertiesDto = {
|
||||
...connectionBody.properties,
|
||||
plugin,
|
||||
credentials_type: 'basic_auth',
|
||||
};
|
||||
const createConnectionBody: CreateConnectionDto = {
|
||||
...body,
|
||||
properties,
|
||||
};
|
||||
const { connection } = await this.connectionsService.createConnection(
|
||||
createConnectionBody,
|
||||
metadata,
|
||||
);
|
||||
connection_id = connection.id;
|
||||
}
|
||||
/************************************/
|
||||
const { operation_result } = await lastValueFrom(
|
||||
this.connectionTestReadClient.ConnectionTestCredentials({
|
||||
connection_id,
|
||||
customer_name,
|
||||
plugin,
|
||||
}),
|
||||
).catch(async (e) => {
|
||||
if (!body.connection_id) {
|
||||
await this.connectionsService.deleteConnection({
|
||||
body: { id: connection_id },
|
||||
metadata,
|
||||
});
|
||||
}
|
||||
throw e;
|
||||
});
|
||||
if (!operation_result && !body.connection_id) {
|
||||
await this.connectionsService.deleteConnection({
|
||||
body: { id: connection_id },
|
||||
metadata,
|
||||
});
|
||||
connection_id = null;
|
||||
}
|
||||
return { operation_result, connection_id };
|
||||
}
|
||||
async connectionTestListSchemas(
|
||||
body: ConnectionTestListSchemasReq,
|
||||
customer_name: string,
|
||||
): Promise<ConnectionTestListSchemasRes> {
|
||||
const { connection_id, plugin } = body;
|
||||
return lastValueFrom(
|
||||
this.connectionTestReadClient.ListSchemas({
|
||||
connection_id,
|
||||
customer_name,
|
||||
plugin,
|
||||
}),
|
||||
);
|
||||
}
|
||||
async connectionTestListTables(
|
||||
body: ConnectionTestListTablesReq,
|
||||
customer_name: string,
|
||||
): Promise<ConnectionTestListTablesRes> {
|
||||
const { connection_id, plugin, schema } = body;
|
||||
return lastValueFrom(
|
||||
this.connectionTestReadClient.ListTables({
|
||||
connection_id,
|
||||
customer_name,
|
||||
plugin,
|
||||
schema,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
async getTableMetadata(
|
||||
body: GetTableMetadataReq,
|
||||
customer_name: string,
|
||||
): Promise<GetTableMetadataRes> {
|
||||
const { schema, plugin, table_list, connection_id } = body;
|
||||
return lastValueFrom(
|
||||
this.connectionTestReadClient.GetTableMetadata({
|
||||
connection_id,
|
||||
customer_name,
|
||||
plugin,
|
||||
schema,
|
||||
table_list,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
import { ApiProperty, ApiPropertyOptional, OmitType } from '@nestjs/swagger';
|
||||
import { IsString, IsOptional } from 'class-validator';
|
||||
import { DatabaseConnectionPropertiesDto } from 'src/modules/connection/dtos/connection';
|
||||
import { CreateConnectionDto } from 'src/modules/connection/dtos/connection';
|
||||
export class ColumnDto {
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
@ApiProperty()
|
||||
type: string;
|
||||
}
|
||||
export class TableMetadataDto {
|
||||
@ApiProperty()
|
||||
table_name: string;
|
||||
@ApiProperty({ type: [ColumnDto] })
|
||||
columns: ColumnDto[];
|
||||
@ApiProperty({ type: [ColumnDto] })
|
||||
references: ColumnDto[];
|
||||
}
|
||||
|
||||
export class ConnectionTestPingReq {
|
||||
@ApiPropertyOptional()
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
plugin: string;
|
||||
|
||||
@ApiPropertyOptional()
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
host: string;
|
||||
|
||||
@ApiPropertyOptional()
|
||||
@IsOptional()
|
||||
port: number;
|
||||
|
||||
@ApiPropertyOptional()
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
network_config_id?: string;
|
||||
|
||||
@ApiPropertyOptional()
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
connection_id: string;
|
||||
}
|
||||
|
||||
export class ConnectionTestPingRes {
|
||||
@ApiProperty()
|
||||
operation_result: boolean;
|
||||
}
|
||||
|
||||
export class ConnectionTestCredentialsProperties extends OmitType(
|
||||
DatabaseConnectionPropertiesDto,
|
||||
['plugin', 'credentials_type'],
|
||||
) {}
|
||||
export class ConnectionTestCredentialsReq extends OmitType(
|
||||
CreateConnectionDto,
|
||||
['properties'],
|
||||
) {
|
||||
@ApiProperty()
|
||||
properties: ConnectionTestCredentialsProperties;
|
||||
@ApiPropertyOptional()
|
||||
connection_id?: string;
|
||||
}
|
||||
|
||||
export class ConnectionTestCredentialsRes {
|
||||
@ApiProperty()
|
||||
operation_result: boolean;
|
||||
@ApiProperty()
|
||||
connection_id: string;
|
||||
}
|
||||
|
||||
export class ConnectionTestListSchemasReq {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
plugin: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
connection_id: string;
|
||||
}
|
||||
|
||||
export class ConnectionTestListSchemasRes {
|
||||
@ApiProperty()
|
||||
operation_result: boolean;
|
||||
@ApiProperty()
|
||||
schema_list: string[];
|
||||
}
|
||||
|
||||
export class ConnectionTestListTablesReq {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
plugin: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
connection_id: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
schema: string;
|
||||
}
|
||||
|
||||
export class ConnectionTestListTablesRes {
|
||||
@ApiProperty()
|
||||
operation_result: boolean;
|
||||
@ApiProperty()
|
||||
table_list: string[];
|
||||
}
|
||||
|
||||
export class GetTableMetadataReq {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
connection_id: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
plugin: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
schema: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString({ each: true })
|
||||
table_list: string[];
|
||||
}
|
||||
|
||||
export class GetTableMetadataRes {
|
||||
@ApiProperty()
|
||||
operation_result: boolean;
|
||||
@ApiProperty({ type: [TableMetadataDto] })
|
||||
tables_metadata: TableMetadataDto[];
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { credentials } from '@grpc/grpc-js';
|
||||
import {
|
||||
ClientsProviderAsyncOptions,
|
||||
GrpcOptions,
|
||||
Transport,
|
||||
} from '@nestjs/microservices';
|
||||
import { ConnectionManager } from '@dadosfera/protospack-v2';
|
||||
|
||||
export class ConnectionClientConfiguration {
|
||||
public name = 'ConnectionClientConfiguration';
|
||||
private config: GrpcOptions = {
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
url: process.env.INFACTORY_URL,
|
||||
package: [
|
||||
ConnectionManager.ProtoPackages.WritePackage,
|
||||
ConnectionManager.ProtoPackages.ReadPackage,
|
||||
],
|
||||
credentials:
|
||||
process.env.LOCAL_ENV || process.env.ENV === 'local'
|
||||
? undefined
|
||||
: credentials.createSsl(),
|
||||
protoPath: [
|
||||
ConnectionManager.ProtoPaths.WriteFilePath,
|
||||
ConnectionManager.ProtoPaths.ReadFilePath,
|
||||
],
|
||||
loader: {
|
||||
keepCase: true,
|
||||
enums: String,
|
||||
objects: true,
|
||||
arrays: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
providerOptions: ClientsProviderAsyncOptions = {
|
||||
name: this.name,
|
||||
...this.config,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,370 @@
|
||||
import {
|
||||
OnModuleInit,
|
||||
Inject,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
} from '@nestjs/common';
|
||||
import { ClientGrpc } from '@nestjs/microservices';
|
||||
import { ConnectionManager } from '@dadosfera/protospack-v2';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import {
|
||||
ConnectionApiConnection,
|
||||
ConnectionRes,
|
||||
ConnectionsRes,
|
||||
ConnectionToCatalogDto,
|
||||
CreateConnectionDto,
|
||||
UpdateConnectionDto,
|
||||
} from './dtos/connection';
|
||||
import { ConnectionClientConfiguration } from './client.config';
|
||||
import {
|
||||
GetConnectionDetailsResponse,
|
||||
INTERNAL_GetAllConnectionsResponse,
|
||||
} from '@dadosfera/protospack-v2/dist/lib/ConnectionManager/interfaces/messages';
|
||||
import { UsersService } from '../users/users.service';
|
||||
import { ConnectorClientService } from '../connector/client.service';
|
||||
import {
|
||||
ConnectionsApiNetworkConfig,
|
||||
NetworkConfigDto,
|
||||
} from '../network-config/dto/network-config';
|
||||
import DadosferaLogger from '@dadosfera/dadosfera-logs/dist';
|
||||
|
||||
export class ConnectionClientService implements OnModuleInit {
|
||||
private connectionServiceRead: ConnectionManager.ReadService.ConnectionManagerReadServices;
|
||||
private connectionServiceWrite: ConnectionManager.WriteService.ConnectionManagerWriteServices;
|
||||
logger: DadosferaLogger;
|
||||
|
||||
constructor(
|
||||
@Inject(ConnectionClientConfiguration.name)
|
||||
private readonly grpcClient: ClientGrpc,
|
||||
private usersService: UsersService,
|
||||
private connectorService: ConnectorClientService,
|
||||
private dadosferaLogger: DadosferaLogger,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
|
||||
onModuleInit() {
|
||||
this.connectionServiceWrite =
|
||||
this.grpcClient.getService<ConnectionManager.WriteService.ConnectionManagerWriteServices>(
|
||||
ConnectionManager.ProtoServices.ConnectionManagerWriteServices,
|
||||
);
|
||||
|
||||
this.connectionServiceRead =
|
||||
this.grpcClient.getService<ConnectionManager.ReadService.ConnectionManagerReadServices>(
|
||||
ConnectionManager.ProtoServices.ConnectionManagerReadServices,
|
||||
);
|
||||
}
|
||||
|
||||
async createConnection(
|
||||
body: CreateConnectionDto,
|
||||
metadata,
|
||||
): Promise<ConnectionRes> {
|
||||
const {
|
||||
connector_id,
|
||||
description,
|
||||
image_url,
|
||||
name,
|
||||
network_config_id,
|
||||
properties,
|
||||
type,
|
||||
connector_name,
|
||||
plugin,
|
||||
} = body;
|
||||
|
||||
return lastValueFrom(
|
||||
this.connectionServiceWrite.CreateConnection(
|
||||
{
|
||||
connector_id,
|
||||
connector_name,
|
||||
description,
|
||||
image_url,
|
||||
name,
|
||||
network_config_id,
|
||||
properties: JSON.stringify(properties),
|
||||
type,
|
||||
plugin,
|
||||
},
|
||||
metadata,
|
||||
),
|
||||
).catch((err) => {
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 400,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async updateConnection(
|
||||
id: string,
|
||||
body: UpdateConnectionDto,
|
||||
metadata,
|
||||
): Promise<ConnectionRes> {
|
||||
const { description, name, network_config_id, properties } = body;
|
||||
|
||||
return lastValueFrom(
|
||||
this.connectionServiceWrite.UpdateConnection(
|
||||
{
|
||||
id,
|
||||
description,
|
||||
name,
|
||||
network_config_id,
|
||||
properties: JSON.stringify(properties),
|
||||
},
|
||||
metadata,
|
||||
),
|
||||
).catch((err) => {
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 400,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async deleteConnection({ body, metadata }): Promise<ConnectionRes> {
|
||||
const { id } = body;
|
||||
|
||||
return lastValueFrom(
|
||||
this.connectionServiceWrite.DeleteConnection(
|
||||
{
|
||||
id,
|
||||
},
|
||||
metadata,
|
||||
),
|
||||
).catch((err) => {
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 400,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async getAllConnections({ body, metadata }): Promise<ConnectionsRes> {
|
||||
const { search, filters, size, page } = body;
|
||||
|
||||
return lastValueFrom(
|
||||
this.connectionServiceRead.GetAllConnection(
|
||||
{ search, filters: JSON.stringify(filters), size, page },
|
||||
metadata,
|
||||
),
|
||||
).catch((err) => {
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 400,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async getConnectionDetails({
|
||||
body,
|
||||
metadata,
|
||||
}): Promise<GetConnectionDetailsResponse> {
|
||||
const id = body.connection_id || body.id;
|
||||
|
||||
return lastValueFrom(
|
||||
this.connectionServiceRead.GetConnectionDetails({ id }, metadata),
|
||||
).catch((err) => {
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 400,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async INTERNAL_getAllConnections({
|
||||
customer_name,
|
||||
}: {
|
||||
customer_name: string;
|
||||
}): Promise<INTERNAL_GetAllConnectionsResponse> {
|
||||
return lastValueFrom(
|
||||
this.connectionServiceRead.INTERNAL_GetAllConnections({ customer_name }),
|
||||
);
|
||||
}
|
||||
|
||||
async catalogExistingConnection(data: {
|
||||
connection?: ConnectionToCatalogDto;
|
||||
networkConfig?: NetworkConfigDto;
|
||||
}) {
|
||||
return lastValueFrom(
|
||||
this.connectionServiceRead.INTERNAL_CatalogExistingConnection({
|
||||
data_str: JSON.stringify(data),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
async synchronizeConnections(apply: boolean) {
|
||||
const connectors = await this.connectorService
|
||||
.getAllConnectors({
|
||||
search: undefined,
|
||||
filters: undefined,
|
||||
language: 'pt-br',
|
||||
page: 1,
|
||||
size: 500,
|
||||
})
|
||||
.then(({ connectors: connectorsStr }) =>
|
||||
JSON.parse(connectorsStr).map((c) => c),
|
||||
);
|
||||
const { customers } = await this.usersService.findAllCustomers();
|
||||
|
||||
const customer_connections: {
|
||||
customer_name: string;
|
||||
customer_id: string;
|
||||
productConnections: Record<string, any>[];
|
||||
platformConnections: ConnectionApiConnection[];
|
||||
productNetworkConfigs: Record<string, any>[];
|
||||
platformNetworkConfigs: ConnectionsApiNetworkConfig[];
|
||||
}[] = [];
|
||||
for (const customer of customers) {
|
||||
const { name: customer_name, id: customer_id } = customer;
|
||||
|
||||
const customer_connection = await this.INTERNAL_getAllConnections({
|
||||
customer_name,
|
||||
}).then((res) => ({
|
||||
customer_name,
|
||||
customer_id,
|
||||
platformConnections: res.platformConnections
|
||||
? JSON.parse(res.platformConnections)
|
||||
: [],
|
||||
productConnections: res.productConnections
|
||||
? JSON.parse(res.productConnections)
|
||||
: [],
|
||||
productNetworkConfigs: res.productNetworkConfigs
|
||||
? JSON.parse(res.productNetworkConfigs)
|
||||
: [],
|
||||
platformNetworkConfigs: res.platformNetworkConfigs
|
||||
? JSON.parse(res.platformNetworkConfigs)
|
||||
: [],
|
||||
}));
|
||||
customer_connections.push(customer_connection);
|
||||
}
|
||||
this.logger.info(
|
||||
'DEBUG_ConnectionsMigrations - ' + JSON.stringify(customer_connections),
|
||||
);
|
||||
|
||||
const migrations: {
|
||||
customer_name: string;
|
||||
status: any[];
|
||||
productConnectionsMissing: ConnectionApiConnection[];
|
||||
productNetworkConfigsMissing: ConnectionsApiNetworkConfig[];
|
||||
}[] = [];
|
||||
for (const customer_connection of customer_connections) {
|
||||
const productConnectionsMissing: ConnectionApiConnection[] = [];
|
||||
const productNetworkConfigsMissing: ConnectionsApiNetworkConfig[] = [];
|
||||
const status: any[] = [];
|
||||
let updatePromises: Promise<any>[] = [];
|
||||
|
||||
this.logger.info(
|
||||
'DEBUG_ConnectionsMigrations - customer_connections ' +
|
||||
JSON.stringify(customer_connection),
|
||||
);
|
||||
const {
|
||||
customer_name,
|
||||
productConnections,
|
||||
platformConnections,
|
||||
productNetworkConfigs,
|
||||
platformNetworkConfigs,
|
||||
customer_id,
|
||||
} = customer_connection;
|
||||
|
||||
platformConnections?.forEach((plc) => {
|
||||
const productConnection = productConnections.find(
|
||||
(prc) => prc.id === plc.config_id,
|
||||
);
|
||||
if (!productConnection) productConnectionsMissing.push(plc);
|
||||
});
|
||||
platformNetworkConfigs?.forEach((platNetConfig) => {
|
||||
const productNetworkConfig = productNetworkConfigs.find(
|
||||
(prodNetConfig) => prodNetConfig.id === platNetConfig.config_id,
|
||||
);
|
||||
if (!productNetworkConfig)
|
||||
productNetworkConfigsMissing.push(platNetConfig);
|
||||
});
|
||||
if (apply) {
|
||||
for (const network_config of productNetworkConfigsMissing) {
|
||||
const networkConfigToCatalog = {
|
||||
id: network_config.config_id,
|
||||
created_at: network_config.created_at,
|
||||
updated_at: network_config.updated_at,
|
||||
customer_name: customer_name,
|
||||
customer_id: customer_id,
|
||||
user_id: '',
|
||||
network_type_id: '',
|
||||
network_type_name: network_config.type,
|
||||
type: network_config.type,
|
||||
plugin: network_config.plugin,
|
||||
name: network_config.name,
|
||||
description: network_config.description,
|
||||
properties: undefined,
|
||||
keywords: undefined,
|
||||
tags: undefined,
|
||||
};
|
||||
|
||||
updatePromises.push(
|
||||
this.catalogExistingConnection({
|
||||
networkConfig: networkConfigToCatalog,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
this.logger.info(
|
||||
'DEBUG_ConnectionsMigrations - Creating missing network configs for customer' +
|
||||
customer_name +
|
||||
' - ' +
|
||||
JSON.stringify(customer_connection),
|
||||
);
|
||||
const updateStatuses = await Promise.all(updatePromises);
|
||||
status.push(...updateStatuses);
|
||||
updatePromises = [];
|
||||
for (const connection of productConnectionsMissing) {
|
||||
const connector = connectors.find(
|
||||
(c) => c._source.plugin === connection.plugin,
|
||||
);
|
||||
const connectionToCatalog = {
|
||||
id: connection.config_id,
|
||||
created_at: connection.created_at,
|
||||
updated_at: new Date().toISOString(),
|
||||
customer_id: customer_id,
|
||||
user_id: '',
|
||||
plugin: connection.plugin,
|
||||
name: connection.name,
|
||||
description: connection.description,
|
||||
image_url: connector._source.image,
|
||||
network_config_id: connection.network_config_id,
|
||||
type: connection.type,
|
||||
connector_id: connector._id,
|
||||
connector_name: connector._source.name,
|
||||
in_use: 1,
|
||||
username: '',
|
||||
customer_name,
|
||||
};
|
||||
|
||||
updatePromises.push(
|
||||
this.catalogExistingConnection({ connection: connectionToCatalog }),
|
||||
);
|
||||
}
|
||||
this.logger.info(
|
||||
'DEBUG_ConnectionsMigrations - Creating missing connections for customer' +
|
||||
' - ' +
|
||||
customer_name +
|
||||
JSON.stringify(customer_connection),
|
||||
);
|
||||
const updateStatuses_2 = await Promise.all(updatePromises);
|
||||
status.push(...updateStatuses_2);
|
||||
}
|
||||
|
||||
this.logger.info(
|
||||
'DEBUG_ConnectionsMigrations - migrations for customer ' +
|
||||
customer_name +
|
||||
' - ' +
|
||||
JSON.stringify(customer_connection),
|
||||
);
|
||||
migrations.push({
|
||||
customer_name,
|
||||
status,
|
||||
productConnectionsMissing,
|
||||
productNetworkConfigsMissing,
|
||||
});
|
||||
}
|
||||
|
||||
return { migrations };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Post,
|
||||
Inject,
|
||||
Put,
|
||||
Param,
|
||||
Delete,
|
||||
Get,
|
||||
Headers,
|
||||
Query,
|
||||
} from '@nestjs/common';
|
||||
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
|
||||
import { ConnectionClientService } from './client.service';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
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 { ValidationPipe } from '../../pipes/object-validation.pipe';
|
||||
import {
|
||||
ConnectionDetailsRes,
|
||||
ConnectionRes,
|
||||
ConnectionsRes,
|
||||
UpdateConnectionDto,
|
||||
} from './dtos/connection';
|
||||
import { CreateConnectionDto } from './dtos/connection';
|
||||
import { PackTheMetadata } from 'src/utils/ PackTheMetadata';
|
||||
|
||||
const connectionPermissions = PERMISSIONS_GROUPS.CONNECTION.permissions;
|
||||
@ApiTags('connections')
|
||||
@ApiBearerAuth()
|
||||
@Authenticated()
|
||||
@Controller('connections')
|
||||
export class ConnectionController {
|
||||
logger: any;
|
||||
constructor(
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
private clientService: ConnectionClientService,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
|
||||
@Get('connections-migration')
|
||||
@RequireAllPermissions(
|
||||
PERMISSIONS_GROUPS.DADOSFERA.permissions.CONNECTIONS_MIGRATION,
|
||||
)
|
||||
async synchronizeConnections(@Query('apply') apply: string) {
|
||||
return this.clientService.synchronizeConnections(apply === 'true');
|
||||
}
|
||||
|
||||
@Post()
|
||||
@RequireAllPermissions(connectionPermissions.CREATE)
|
||||
async createConnection(
|
||||
@User() user: RequestUser,
|
||||
@Body(new ValidationPipe()) body: CreateConnectionDto,
|
||||
): Promise<ConnectionRes> {
|
||||
this.logger.info('/connections - Create Connection');
|
||||
|
||||
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.createConnection(
|
||||
body,
|
||||
metadata,
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Put('/:id')
|
||||
@RequireAllPermissions(connectionPermissions.CREATE)
|
||||
async updateConnection(
|
||||
@User() user: RequestUser,
|
||||
@Headers('Dadosfera-Lang') language: string,
|
||||
@Param('id') id: string,
|
||||
@Body(new ValidationPipe()) body: UpdateConnectionDto,
|
||||
): Promise<ConnectionRes> {
|
||||
this.logger.info('/connections - Update Connection');
|
||||
if (!language) language = 'en-us';
|
||||
|
||||
const { user_id, customer_id, customer_name, username } = user;
|
||||
const metadata = PackTheMetadata({
|
||||
user_id,
|
||||
customer_id,
|
||||
customer_name,
|
||||
language,
|
||||
username,
|
||||
});
|
||||
|
||||
const response: any = await this.clientService.updateConnection(
|
||||
id,
|
||||
body,
|
||||
metadata,
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@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 response: any = await this.clientService.deleteConnection({
|
||||
body: { id },
|
||||
metadata,
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Get()
|
||||
async getAllConnections(
|
||||
@User() user: RequestUser,
|
||||
@Headers('Dadosfera-Lang') language,
|
||||
@Query() queries,
|
||||
): Promise<ConnectionsRes> {
|
||||
this.logger.info('/connections - Get All Connection');
|
||||
if (!language) language = 'en-us';
|
||||
|
||||
const { user_id, customer_id, customer_name, username } = user;
|
||||
const { search, size, page, ...filters } = queries;
|
||||
const metadata = PackTheMetadata({
|
||||
user_id,
|
||||
customer_id,
|
||||
customer_name,
|
||||
language,
|
||||
username,
|
||||
});
|
||||
|
||||
const response = await this.clientService.getAllConnections({
|
||||
body: { search, size, page, filters },
|
||||
metadata,
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Get('/:id')
|
||||
async getConnectionDetails(
|
||||
@Headers('Dadosfera-Lang') language,
|
||||
@User() user: RequestUser,
|
||||
@Param('id') id,
|
||||
@Query('details') details,
|
||||
): Promise<ConnectionDetailsRes> {
|
||||
this.logger.info('/connections - Get Connection Details');
|
||||
if (!language) language = 'en-us';
|
||||
|
||||
const { user_id, customer_id, customer_name, username } = user;
|
||||
const metadata = PackTheMetadata({
|
||||
user_id,
|
||||
customer_id,
|
||||
customer_name,
|
||||
username,
|
||||
details,
|
||||
language,
|
||||
});
|
||||
|
||||
const response: any = await this.clientService.getConnectionDetails({
|
||||
body: { id },
|
||||
metadata,
|
||||
});
|
||||
|
||||
if (details === 'true') {
|
||||
const properties = JSON.parse(response.connection.properties);
|
||||
|
||||
Object.assign(response.connection, {
|
||||
pipelines: JSON.parse(response.connection.pipelines),
|
||||
connection_controls: properties.connection_controls,
|
||||
config_controls: properties.config_controls,
|
||||
connection_steps: properties.connection_steps,
|
||||
});
|
||||
|
||||
delete response.connection.properties;
|
||||
} else {
|
||||
Object.assign(response.connection, {
|
||||
properties: JSON.parse(response.connection.properties),
|
||||
pipelines: JSON.parse(response.connection.pipelines),
|
||||
});
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ClientsModule } from '@nestjs/microservices';
|
||||
import { ConnectionClientService } from './client.service';
|
||||
import { ConnectionClientConfiguration } from './client.config';
|
||||
import { ConnectionController } from './connection.controller';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import { UsersModule } from '../users/users.module';
|
||||
import { ConnectorModule } from '../connector/connector.module';
|
||||
|
||||
const client = new ConnectionClientConfiguration();
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ClientsModule.register([client.providerOptions]),
|
||||
UsersModule,
|
||||
ConnectorModule,
|
||||
],
|
||||
controllers: [ConnectionController],
|
||||
providers: [ConnectionClientService, DadosferaLogger],
|
||||
exports: [ConnectionClientService],
|
||||
})
|
||||
export class ConnectionModule {}
|
||||
@@ -0,0 +1,189 @@
|
||||
import {
|
||||
ApiProperty,
|
||||
ApiPropertyOptional,
|
||||
OmitType,
|
||||
PickType,
|
||||
} from '@nestjs/swagger';
|
||||
import {
|
||||
Connection,
|
||||
ConnectionToCatalog,
|
||||
} from '@dadosfera/protospack-v2/dist/lib/ConnectionManager/interfaces/entities';
|
||||
import {
|
||||
GetAllConnectionResponse,
|
||||
GetConnectionDetailsResponse,
|
||||
GetConnectionResponse,
|
||||
} from '@dadosfera/protospack-v2/dist/lib/ConnectionManager/interfaces/messages';
|
||||
export type ConnectionTypes = 'database' | 'file' | 'application';
|
||||
export type ConnectionCredentialsType =
|
||||
| 'basic_auth'
|
||||
| 'iam_user'
|
||||
| 'role_name'
|
||||
| 'oauth'
|
||||
| 'api_key'
|
||||
| 'service_account'
|
||||
| 'headers_authF';
|
||||
export interface ConnectionApiConnection {
|
||||
config_id: string;
|
||||
plugin: string;
|
||||
secret_id: string;
|
||||
created_at: string;
|
||||
network_config_id: null;
|
||||
type: ConnectionTypes;
|
||||
credentials_type: ConnectionCredentialsType;
|
||||
credentials: Record<string, any>;
|
||||
sensitive_fields: string[];
|
||||
name: string;
|
||||
customer_name: string;
|
||||
description: string;
|
||||
updated_at: string;
|
||||
}
|
||||
export class ConnectionDto implements Connection {
|
||||
// ---Automatically generated information will not be sent by the frontend--- //
|
||||
@ApiProperty()
|
||||
id: string;
|
||||
|
||||
@ApiProperty()
|
||||
customer_id: string;
|
||||
|
||||
@ApiProperty()
|
||||
customer_name: string;
|
||||
|
||||
@ApiProperty()
|
||||
user_id: string;
|
||||
|
||||
@ApiProperty()
|
||||
updated_at: string;
|
||||
|
||||
@ApiProperty()
|
||||
created_at: string;
|
||||
|
||||
@ApiProperty()
|
||||
pipelines: string;
|
||||
|
||||
// ---Information sent by the frontend--- //
|
||||
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
|
||||
@ApiProperty()
|
||||
description: string;
|
||||
|
||||
@ApiProperty()
|
||||
type: string;
|
||||
|
||||
@ApiPropertyOptional()
|
||||
network_config_id: string | null;
|
||||
|
||||
@ApiProperty()
|
||||
properties: DatabaseConnectionPropertiesDto | any;
|
||||
|
||||
// ---Information sent by the frontend (Heirs of Connector)--- //
|
||||
|
||||
@ApiProperty()
|
||||
connector_id: string;
|
||||
|
||||
@ApiProperty()
|
||||
connector_name: string;
|
||||
|
||||
@ApiProperty()
|
||||
plugin: string;
|
||||
|
||||
@ApiProperty()
|
||||
image_url: string;
|
||||
}
|
||||
|
||||
export class ConnectionToCatalogDto implements ConnectionToCatalog {
|
||||
// ---Automatically generated information - will not be sent by the frontend--- //
|
||||
id: string;
|
||||
customer_id: string;
|
||||
updated_at: string;
|
||||
created_at: string;
|
||||
// ---Information extracted from token--- //
|
||||
user_id: string;
|
||||
username: string;
|
||||
customer_name: string;
|
||||
|
||||
// ---Information sent by the frontend--- //
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
|
||||
@ApiProperty()
|
||||
description: string;
|
||||
|
||||
@ApiProperty()
|
||||
type: string;
|
||||
|
||||
@ApiPropertyOptional()
|
||||
network_config_id: string | null;
|
||||
|
||||
// ---Information sent by the frontend (Heirs of Connector)--- //
|
||||
@ApiProperty()
|
||||
connector_id: string;
|
||||
|
||||
@ApiProperty()
|
||||
connector_name: string;
|
||||
|
||||
@ApiProperty()
|
||||
plugin: string;
|
||||
|
||||
@ApiProperty()
|
||||
image_url: string;
|
||||
}
|
||||
|
||||
export class CreateConnectionDto extends OmitType(ConnectionDto, [
|
||||
'id',
|
||||
'customer_id',
|
||||
'customer_name',
|
||||
'user_id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
'pipelines',
|
||||
]) {}
|
||||
|
||||
export class UpdateConnectionDto extends PickType(ConnectionDto, [
|
||||
'name',
|
||||
'description',
|
||||
'network_config_id',
|
||||
'properties',
|
||||
]) {}
|
||||
|
||||
export class ConnectionsRes implements GetAllConnectionResponse {
|
||||
@ApiProperty({ type: [ConnectionToCatalogDto] })
|
||||
connections: ConnectionToCatalogDto[];
|
||||
|
||||
@ApiProperty()
|
||||
message: string;
|
||||
}
|
||||
|
||||
export class ConnectionRes implements GetConnectionResponse {
|
||||
@ApiProperty()
|
||||
connection?: ConnectionToCatalogDto;
|
||||
|
||||
@ApiProperty()
|
||||
message: string;
|
||||
}
|
||||
|
||||
export class ConnectionDetailsRes implements GetConnectionDetailsResponse {
|
||||
@ApiProperty()
|
||||
connection?: ConnectionDto;
|
||||
|
||||
@ApiProperty()
|
||||
message: string;
|
||||
}
|
||||
|
||||
export class DatabaseConnectionPropertiesDto {
|
||||
@ApiProperty()
|
||||
credentials_type: 'basic_auth';
|
||||
@ApiProperty()
|
||||
plugin: string;
|
||||
@ApiProperty()
|
||||
host: string;
|
||||
@ApiProperty()
|
||||
port: string;
|
||||
@ApiProperty()
|
||||
username: string;
|
||||
@ApiProperty()
|
||||
password: string;
|
||||
@ApiProperty()
|
||||
database: string;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { credentials } from '@grpc/grpc-js';
|
||||
import {
|
||||
ClientsProviderAsyncOptions,
|
||||
GrpcOptions,
|
||||
Transport,
|
||||
} from '@nestjs/microservices';
|
||||
import { ConnectorManager } from '@dadosfera/protospack-v2';
|
||||
|
||||
export class ConnectorClientConfiguration {
|
||||
public name = 'ConnectorClientConfiguration';
|
||||
private config: GrpcOptions = {
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
url: process.env.INFACTORY_URL,
|
||||
package: [
|
||||
ConnectorManager.ProtoPackages.WritePackage,
|
||||
ConnectorManager.ProtoPackages.ReadPackage,
|
||||
],
|
||||
credentials:
|
||||
process.env.LOCAL_ENV || process.env.ENV === 'local'
|
||||
? undefined
|
||||
: credentials.createSsl(),
|
||||
protoPath: [
|
||||
ConnectorManager.ProtoPaths.WriteFilePath,
|
||||
ConnectorManager.ProtoPaths.ReadFilePath,
|
||||
],
|
||||
loader: {
|
||||
keepCase: true,
|
||||
enums: String,
|
||||
objects: true,
|
||||
arrays: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
providerOptions: ClientsProviderAsyncOptions = {
|
||||
name: this.name,
|
||||
...this.config,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,340 @@
|
||||
import { Metadata } from '@grpc/grpc-js';
|
||||
import {
|
||||
OnModuleInit,
|
||||
Inject,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
} from '@nestjs/common';
|
||||
import { ClientGrpc } from '@nestjs/microservices';
|
||||
import { ConnectorManager } from '@dadosfera/protospack-v2';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import { ConnectorClientConfiguration } from './client.config';
|
||||
|
||||
export class ConnectorClientService implements OnModuleInit {
|
||||
private connectorServiceRead: ConnectorManager.ReadService.ConnectorManagerReadServices;
|
||||
private connectorServiceWrite: ConnectorManager.WriteService.ConnectorManagerWriteServices;
|
||||
constructor(
|
||||
@Inject(ConnectorClientConfiguration.name)
|
||||
private readonly grpcClient: ClientGrpc,
|
||||
) {}
|
||||
|
||||
onModuleInit() {
|
||||
this.connectorServiceWrite =
|
||||
this.grpcClient.getService<ConnectorManager.WriteService.ConnectorManagerWriteServices>(
|
||||
ConnectorManager.ProtoServices.ConnectorManagerWriteServices,
|
||||
);
|
||||
|
||||
this.connectorServiceRead =
|
||||
this.grpcClient.getService<ConnectorManager.ReadService.ConnectorManagerReadServices>(
|
||||
ConnectorManager.ProtoServices.ConnectorManagerReadServices,
|
||||
);
|
||||
}
|
||||
|
||||
async uploadConnector(uploadConnector) {
|
||||
const connector: ConnectorManager.Entities.ConnectorCreateRequest = {
|
||||
file: {
|
||||
buffer: uploadConnector.file.buffer,
|
||||
mimetypes: uploadConnector.file.mimetype,
|
||||
},
|
||||
connector: JSON.stringify(uploadConnector.connector),
|
||||
};
|
||||
const serviceBody: ConnectorManager.Messages.RegisterConnectorRequest = {
|
||||
connector,
|
||||
};
|
||||
|
||||
return lastValueFrom(
|
||||
this.connectorServiceWrite.RegisterConnector(serviceBody),
|
||||
).catch((err) => {
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 400,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async uploadFile(uploadFile) {
|
||||
const body: ConnectorManager.Messages.UploadFileRequest = {
|
||||
file: {
|
||||
buffer: uploadFile.file.buffer,
|
||||
mimetypes: uploadFile.file.mimetype,
|
||||
},
|
||||
name: uploadFile.name,
|
||||
};
|
||||
|
||||
return lastValueFrom(this.connectorServiceWrite.UploadFile(body)).catch(
|
||||
(err) => {
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 400,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
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) {
|
||||
const meta = new Metadata();
|
||||
meta.add('Language', body.language);
|
||||
return lastValueFrom(
|
||||
this.connectorServiceRead.GetAllConnectors(
|
||||
{
|
||||
search: body.search,
|
||||
filters: JSON.stringify(body.filters),
|
||||
language: body.language,
|
||||
page: body.page,
|
||||
size: body.size,
|
||||
},
|
||||
meta,
|
||||
),
|
||||
).catch((err) => {
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 400,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async getConnectorDetails(connectorId: string, language: string) {
|
||||
const meta = new Metadata();
|
||||
meta.add('Language', language);
|
||||
return lastValueFrom(
|
||||
this.connectorServiceRead.GetConnectorDetails(
|
||||
{
|
||||
plugin: connectorId,
|
||||
},
|
||||
meta,
|
||||
),
|
||||
).catch((err) => {
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 400,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async getConnector(plugin: string, language: string) {
|
||||
const meta = new Metadata();
|
||||
meta.add('Language', language);
|
||||
return lastValueFrom(
|
||||
this.connectorServiceRead.GetConnector(
|
||||
{
|
||||
plugin,
|
||||
},
|
||||
meta,
|
||||
),
|
||||
).catch((err) => {
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 400,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async getConnectorsTags() {
|
||||
return lastValueFrom(this.connectorServiceRead.GetConnectorsTags({})).catch(
|
||||
(err) => {
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 400,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
async deleteConnector(plugin: string, version: string) {
|
||||
return lastValueFrom(
|
||||
this.connectorServiceWrite.DeleteConnector({
|
||||
version,
|
||||
plugin,
|
||||
}),
|
||||
).catch((err) => {
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 400,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async updateConnector({ plugin, changes }) {
|
||||
return lastValueFrom(
|
||||
this.connectorServiceWrite.UpdateConnector({
|
||||
plugin,
|
||||
changes,
|
||||
}),
|
||||
).catch((err) => {
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 400,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -11,24 +11,32 @@ import {
|
||||
UploadedFile,
|
||||
UseInterceptors,
|
||||
Inject,
|
||||
Headers,
|
||||
UploadedFiles,
|
||||
} from '@nestjs/common';
|
||||
import { FileInterceptor } from '@nestjs/platform-express';
|
||||
import { FileInterceptor, FilesInterceptor } from '@nestjs/platform-express';
|
||||
import { ApiBearerAuth, ApiConsumes, ApiTags } from '@nestjs/swagger';
|
||||
import { ConnectorClientService } from 'src/clients/connector/client.service';
|
||||
import { ConnectorClientService } from './client.service';
|
||||
import { AddTagDto } from './dtos/add-tag';
|
||||
import { CreateConnectorDto } from './dtos/create-connector';
|
||||
import { DeleteConnectorDto } from './dtos/delete-connector';
|
||||
import { GetAllDto } from './dtos/get-all';
|
||||
import { RemoveTagDto } from './dtos/remove-tag';
|
||||
import { UpdateDto } from './dtos/update';
|
||||
import { UploadFileDto } from './dtos/upload-file';
|
||||
import { DadosferaLogger } from 'dadosfera-logs';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import {
|
||||
Authenticated,
|
||||
RequireAllPermissions,
|
||||
RequireSomePermission,
|
||||
} from 'src/authentication/authentication.decorator';
|
||||
import { PERMISSIONS_GROUPS } from 'src/authentication/permissions.enum';
|
||||
|
||||
@ApiTags('connectors')
|
||||
@ApiBearerAuth()
|
||||
@Authenticated()
|
||||
@Controller('connectors')
|
||||
export class ConnectorController {
|
||||
logger: any;
|
||||
logger: DadosferaLogger;
|
||||
constructor(
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
@@ -38,6 +46,7 @@ export class ConnectorController {
|
||||
}
|
||||
|
||||
@Post()
|
||||
@RequireAllPermissions(PERMISSIONS_GROUPS.CONNECTORS.permissions.CREATE)
|
||||
@ApiConsumes('multipart/form-data')
|
||||
@UseInterceptors(FileInterceptor('file'))
|
||||
async uploadConnector(
|
||||
@@ -54,32 +63,59 @@ export class ConnectorController {
|
||||
return response;
|
||||
}
|
||||
|
||||
@Post('/upload')
|
||||
@Post('/uploads')
|
||||
@RequireAllPermissions(PERMISSIONS_GROUPS.CONNECTORS.permissions.CREATE)
|
||||
@ApiConsumes('multipart/form-data')
|
||||
@UseInterceptors(FileInterceptor('file'))
|
||||
async uploadFile(@UploadedFile() file, @Body() { name }: UploadFileDto) {
|
||||
@UseInterceptors(FilesInterceptor('files'))
|
||||
async uploadFile(@UploadedFiles() files) {
|
||||
this.logger.info('/upload - Upload Connector Route');
|
||||
|
||||
const response = await this.connectorClientService.uploadFile({
|
||||
file,
|
||||
name,
|
||||
const promises = files.map(async (file) => {
|
||||
return await this.connectorClientService.uploadFile({
|
||||
file,
|
||||
name: file.originalname.split('.')[0],
|
||||
});
|
||||
});
|
||||
|
||||
const response = await Promise.all(promises);
|
||||
return response;
|
||||
}
|
||||
|
||||
@Get()
|
||||
async getAllConnectors(@Query() queries: GetAllDto) {
|
||||
this.logger.info('/upload - Upload Connector Route');
|
||||
@Post('/multiple-connectors-upload')
|
||||
@RequireAllPermissions(PERMISSIONS_GROUPS.CONNECTORS.permissions.CREATE)
|
||||
@ApiConsumes('multipart/form-data')
|
||||
@UseInterceptors(FileInterceptor('file'))
|
||||
async uploadConnectorsFile(@UploadedFile() file: Express.Multer.File) {
|
||||
this.logger.info(`/upload`, 'Upload Connector Route');
|
||||
|
||||
const { search, ...filters } = queries;
|
||||
return await this.connectorClientService.uploadConnectorsFile(file);
|
||||
}
|
||||
|
||||
@Get()
|
||||
@RequireSomePermission(
|
||||
PERMISSIONS_GROUPS.CONNECTORS.permissions.GET,
|
||||
PERMISSIONS_GROUPS.PIPELINE.permissions.CREATE,
|
||||
PERMISSIONS_GROUPS.PIPELINE.permissions.GET,
|
||||
PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE,
|
||||
PERMISSIONS_GROUPS.PIPELINE.permissions.DELETE,
|
||||
)
|
||||
async getAllConnectors(
|
||||
@Headers('dadosfera-lang') language,
|
||||
@Query() queries: GetAllDto,
|
||||
) {
|
||||
this.logger.info('/GET - getAllConnectors Route');
|
||||
if (!language) language = 'en-us';
|
||||
|
||||
const { search, size, page, ...filters } = queries;
|
||||
|
||||
const response: any = await this.connectorClientService.getAllConnectors({
|
||||
filters: filters || {},
|
||||
search: search || '',
|
||||
language: language || 'pt-br',
|
||||
size: size || 10,
|
||||
page: page || 1,
|
||||
});
|
||||
|
||||
const connectors = JSON.parse(response.connectors).connectors;
|
||||
const connectors = JSON.parse(response.connectors);
|
||||
|
||||
return {
|
||||
message: response.message,
|
||||
@@ -87,17 +123,39 @@ export class ConnectorController {
|
||||
};
|
||||
}
|
||||
|
||||
@Get('/tags')
|
||||
@RequireSomePermission(
|
||||
PERMISSIONS_GROUPS.CONNECTORS.permissions.GET,
|
||||
PERMISSIONS_GROUPS.PIPELINE.permissions.CREATE,
|
||||
PERMISSIONS_GROUPS.PIPELINE.permissions.GET,
|
||||
PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE,
|
||||
PERMISSIONS_GROUPS.PIPELINE.permissions.DELETE,
|
||||
)
|
||||
async getConnectorsTags() {
|
||||
return await this.connectorClientService.getConnectorsTags();
|
||||
}
|
||||
|
||||
@Get('/:plugin')
|
||||
@RequireSomePermission(
|
||||
PERMISSIONS_GROUPS.CONNECTORS.permissions.GET,
|
||||
PERMISSIONS_GROUPS.PIPELINE.permissions.CREATE,
|
||||
PERMISSIONS_GROUPS.PIPELINE.permissions.GET,
|
||||
PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE,
|
||||
PERMISSIONS_GROUPS.PIPELINE.permissions.DELETE,
|
||||
)
|
||||
async getConnector(
|
||||
@Headers('dadosfera-lang') language,
|
||||
@Param('plugin') plugin: string,
|
||||
@Query('version') version: string,
|
||||
) {
|
||||
this.logger.info('/upload - Upload Connector Route');
|
||||
this.logger.info('/GET/:plugin - getConnector Route');
|
||||
if (!language) language = 'en-us';
|
||||
|
||||
const pluginId = `${plugin}-${version}`;
|
||||
|
||||
const response: any = await this.connectorClientService.getConnector(
|
||||
pluginId,
|
||||
language,
|
||||
);
|
||||
|
||||
return {
|
||||
@@ -107,16 +165,26 @@ export class ConnectorController {
|
||||
}
|
||||
|
||||
@Get('/:plugin/details')
|
||||
@RequireSomePermission(
|
||||
PERMISSIONS_GROUPS.CONNECTORS.permissions.GET,
|
||||
PERMISSIONS_GROUPS.PIPELINE.permissions.CREATE,
|
||||
PERMISSIONS_GROUPS.PIPELINE.permissions.GET,
|
||||
PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE,
|
||||
PERMISSIONS_GROUPS.PIPELINE.permissions.DELETE,
|
||||
)
|
||||
async getConnectorDetails(
|
||||
@Headers('dadosfera-lang') language,
|
||||
@Param('plugin') plugin: string,
|
||||
@Query('version') version: string,
|
||||
) {
|
||||
this.logger.info('/upload - Upload Connector Route');
|
||||
if (!language) language = 'en-us';
|
||||
|
||||
const pluginId = `${plugin}-${version}`;
|
||||
|
||||
const response: any = await this.connectorClientService.getConnectorDetails(
|
||||
pluginId,
|
||||
language || 'pt-br',
|
||||
);
|
||||
|
||||
return {
|
||||
@@ -126,6 +194,7 @@ export class ConnectorController {
|
||||
}
|
||||
|
||||
@Put('/:plugin')
|
||||
@RequireAllPermissions(PERMISSIONS_GROUPS.CONNECTORS.permissions.UPDATE)
|
||||
@ApiConsumes('multipart/form-data')
|
||||
async updateConnector(
|
||||
@Param('plugin') plugin: string,
|
||||
@@ -147,6 +216,7 @@ export class ConnectorController {
|
||||
}
|
||||
|
||||
@Put('/:plugin/add-tag')
|
||||
@RequireAllPermissions(PERMISSIONS_GROUPS.CONNECTORS.permissions.UPDATE)
|
||||
async addTagOnConnector(
|
||||
@Param('plugin') plugin: string,
|
||||
@Body() body: AddTagDto,
|
||||
@@ -173,6 +243,7 @@ export class ConnectorController {
|
||||
}
|
||||
|
||||
@Put('/:plugin/remove-tag')
|
||||
@RequireAllPermissions(PERMISSIONS_GROUPS.CONNECTORS.permissions.UPDATE)
|
||||
async removeTagOnConnector(
|
||||
@Param('plugin') plugin: string,
|
||||
@Body() body: RemoveTagDto,
|
||||
@@ -200,6 +271,7 @@ export class ConnectorController {
|
||||
}
|
||||
|
||||
@Delete('/:plugin')
|
||||
@RequireAllPermissions(PERMISSIONS_GROUPS.CONNECTORS.permissions.DELETE)
|
||||
async deleteConnector(
|
||||
@Param('plugin') plugin: string,
|
||||
@Body() { version }: DeleteConnectorDto,
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ClientsModule } from '@nestjs/microservices';
|
||||
import { ConnectorClientService } from './client.service';
|
||||
import { ConnectorClientConfiguration } from './client.config';
|
||||
import { ConnectorController } from './connector.controller';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
|
||||
const client = new ConnectorClientConfiguration();
|
||||
|
||||
@Module({
|
||||
controllers: [ConnectorController],
|
||||
providers: [ConnectorClientService, DadosferaLogger],
|
||||
imports: [ClientsModule.register([client.providerOptions])],
|
||||
exports: [ConnectorClientService],
|
||||
})
|
||||
export class ConnectorModule {}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
export class UploadConnectorsFileDto {
|
||||
@ApiProperty({ format: 'binary' })
|
||||
file: string;
|
||||
}
|
||||
@@ -4,6 +4,15 @@ export class GetAllDto {
|
||||
@ApiProperty()
|
||||
search: string;
|
||||
|
||||
@ApiProperty()
|
||||
language: string;
|
||||
|
||||
@ApiProperty()
|
||||
size: string;
|
||||
|
||||
@ApiProperty()
|
||||
page: string;
|
||||
|
||||
@ApiProperty()
|
||||
filters: any;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { credentials } from '@grpc/grpc-js';
|
||||
import {
|
||||
ClientsProviderAsyncOptions,
|
||||
GrpcOptions,
|
||||
Transport,
|
||||
} from '@nestjs/microservices';
|
||||
import {
|
||||
ProtoPackages,
|
||||
ProtoPaths,
|
||||
} from '@dadosfera/protospack-v2/dist/lib/Duc';
|
||||
|
||||
export class DucClient {
|
||||
public name = 'DucClient';
|
||||
|
||||
private config: GrpcOptions = {
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
url: process.env.DUC_URL,
|
||||
package: ProtoPackages.WritePackage,
|
||||
credentials:
|
||||
process.env.LOCAL_ENV || process.env.ENV === 'local'
|
||||
? undefined
|
||||
: credentials.createSsl(),
|
||||
protoPath: ProtoPaths.WriteFilePath,
|
||||
loader: {
|
||||
keepCase: true,
|
||||
enums: String,
|
||||
objects: true,
|
||||
arrays: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
providerOptions: ClientsProviderAsyncOptions = {
|
||||
name: this.name,
|
||||
...this.config,
|
||||
};
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Controller, Get, Inject } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { HealthService } from './health.service';
|
||||
import { DadosferaLogger } from 'dadosfera-logs';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
|
||||
@ApiTags('Health')
|
||||
@Controller('health')
|
||||
export class HealthController {
|
||||
logger: any;
|
||||
logger: DadosferaLogger;
|
||||
constructor(
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
|
||||
import { HealthController } from './health.controller';
|
||||
import { HealthService } from './health.service';
|
||||
|
||||
@Module({
|
||||
controllers: [HealthController],
|
||||
providers: [HealthService, DadosferaLogger],
|
||||
})
|
||||
export class HealthModule {}
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DadosferaLogger } from 'dadosfera-logs';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
|
||||
@Injectable()
|
||||
export class HealthService {
|
||||
logger: any;
|
||||
logger: DadosferaLogger;
|
||||
constructor(
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
|
||||
@@ -1,30 +1,7 @@
|
||||
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||
import { Info } from 'src/clients/inputs/interfaces';
|
||||
import { Method } from 'axios';
|
||||
import { ApiProperty, ApiPropertyOptional, OmitType } from '@nestjs/swagger';
|
||||
import { Info } from 'protospack/dist/lib/interfaces';
|
||||
|
||||
export class InputModel {
|
||||
category: string;
|
||||
plugin: string;
|
||||
name: string;
|
||||
cron?: string;
|
||||
credentials?: {
|
||||
connection_type: string;
|
||||
oauth: string;
|
||||
oauth_code: string;
|
||||
start_date: string;
|
||||
};
|
||||
options?: {
|
||||
oauth?: {
|
||||
get_tokens_url: string;
|
||||
get_tokens_method?: Method;
|
||||
get_tokens_url_params: string;
|
||||
get_tokens_set_response: Record<string, string>;
|
||||
content_type: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
class GoogleAnalyticsClientSecrets {
|
||||
export class GoogleAnalyticsClientSecrets {
|
||||
@ApiProperty()
|
||||
type: string;
|
||||
@ApiProperty()
|
||||
@@ -46,7 +23,7 @@ class GoogleAnalyticsClientSecrets {
|
||||
@ApiProperty()
|
||||
client_x509_cert_url: string;
|
||||
}
|
||||
class OauthObject {
|
||||
export class OauthObject {
|
||||
@ApiPropertyOptional()
|
||||
get_tokens_url: string;
|
||||
@ApiPropertyOptional()
|
||||
@@ -56,7 +33,7 @@ class OauthObject {
|
||||
@ApiPropertyOptional()
|
||||
content_type: string;
|
||||
}
|
||||
class InputOptions {
|
||||
export class InputOptions {
|
||||
@ApiPropertyOptional()
|
||||
oauth: OauthObject;
|
||||
@ApiPropertyOptional()
|
||||
@@ -66,8 +43,22 @@ class InputOptions {
|
||||
@ApiPropertyOptional()
|
||||
skip_transformation: true;
|
||||
}
|
||||
export class FileFormatParams {
|
||||
@ApiProperty()
|
||||
sep: string;
|
||||
@ApiProperty()
|
||||
header: boolean;
|
||||
@ApiProperty()
|
||||
encoding: string;
|
||||
}
|
||||
|
||||
class CredentialsJdbc {
|
||||
export class AuthParameters {
|
||||
@ApiProperty()
|
||||
aws_access_key_id: string;
|
||||
@ApiProperty()
|
||||
aws_secret_access_key: string;
|
||||
}
|
||||
export class CredentialsJdbc {
|
||||
@ApiPropertyOptional()
|
||||
jdbc_user: string;
|
||||
@ApiPropertyOptional()
|
||||
@@ -83,14 +74,7 @@ class CredentialsJdbc {
|
||||
@ApiPropertyOptional()
|
||||
schema: string;
|
||||
}
|
||||
class FileFormatParams {
|
||||
@ApiPropertyOptional()
|
||||
file_format: string;
|
||||
@ApiPropertyOptional()
|
||||
encoding: string;
|
||||
}
|
||||
|
||||
class Credentials extends CredentialsJdbc {
|
||||
export class Credentials extends CredentialsJdbc {
|
||||
@ApiProperty()
|
||||
connection_type: string;
|
||||
|
||||
@@ -117,20 +101,59 @@ class Credentials extends CredentialsJdbc {
|
||||
@ApiPropertyOptional()
|
||||
oauth_code: string;
|
||||
}
|
||||
class Column {
|
||||
export class Column {
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
@ApiProperty()
|
||||
type: string;
|
||||
}
|
||||
class TableColumns {
|
||||
export class TableColumns {
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
@ApiProperty()
|
||||
columns: Column[];
|
||||
columns: string[];
|
||||
@ApiProperty()
|
||||
references: Column[];
|
||||
}
|
||||
|
||||
export class Input {
|
||||
@ApiProperty()
|
||||
id: string;
|
||||
@ApiProperty({ type: [TableColumns] })
|
||||
tables: TableColumns[];
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
@ApiProperty()
|
||||
description: string;
|
||||
@ApiProperty()
|
||||
plugin: string;
|
||||
@ApiPropertyOptional()
|
||||
type?: string;
|
||||
@ApiProperty()
|
||||
created_at: string;
|
||||
@ApiProperty()
|
||||
updated_at: string;
|
||||
|
||||
//deprecated attributes (for retro compatibility)
|
||||
@ApiPropertyOptional({ deprecated: true })
|
||||
category: string;
|
||||
@ApiPropertyOptional({ deprecated: true })
|
||||
credentials: Credentials;
|
||||
@ApiPropertyOptional({ deprecated: true })
|
||||
options: InputOptions;
|
||||
@ApiPropertyOptional({ deprecated: true })
|
||||
info: Info;
|
||||
@ApiPropertyOptional({ deprecated: true })
|
||||
cron: string;
|
||||
@ApiPropertyOptional({ deprecated: true })
|
||||
source_bucket: string;
|
||||
@ApiPropertyOptional({ deprecated: true })
|
||||
source_prefix: string;
|
||||
@ApiPropertyOptional({ deprecated: true })
|
||||
auth_parameters: AuthParameters;
|
||||
@ApiPropertyOptional({ deprecated: true })
|
||||
file_format_params: FileFormatParams;
|
||||
}
|
||||
export class GetAvailableEntitiesReq {
|
||||
@ApiProperty()
|
||||
plugin: string;
|
||||
@@ -154,7 +177,7 @@ export class TestConnectionGetColumnsReq {
|
||||
info: Info;
|
||||
}
|
||||
export class TestConnectionGetColumnsRes {
|
||||
@ApiProperty()
|
||||
@ApiProperty({ type: [TableColumns] })
|
||||
tables: TableColumns[];
|
||||
}
|
||||
|
||||
@@ -174,42 +197,8 @@ export class TestConnectionRes {
|
||||
@ApiProperty()
|
||||
database_tables: string[];
|
||||
}
|
||||
export class CreateInputReq {
|
||||
@ApiPropertyOptional()
|
||||
id: string;
|
||||
@ApiProperty()
|
||||
plugin: string;
|
||||
@ApiProperty()
|
||||
category: string;
|
||||
@ApiProperty()
|
||||
credentials: Credentials;
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
@ApiPropertyOptional()
|
||||
options: InputOptions;
|
||||
@ApiPropertyOptional()
|
||||
info: Info;
|
||||
}
|
||||
|
||||
export class Input {
|
||||
@ApiProperty()
|
||||
id: string;
|
||||
@ApiProperty()
|
||||
category: string;
|
||||
@ApiProperty()
|
||||
plugin: string;
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
@ApiProperty()
|
||||
cron: string;
|
||||
@ApiProperty()
|
||||
credentials: Credentials;
|
||||
@ApiProperty()
|
||||
client_id: string;
|
||||
@ApiProperty()
|
||||
created_at: string;
|
||||
@ApiProperty()
|
||||
updated_at: string;
|
||||
@ApiPropertyOptional()
|
||||
info: Info;
|
||||
}
|
||||
export class CreateInputReq extends OmitType(Input, [
|
||||
'id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
]) {}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { Info } from 'protospack/dist/lib/interfaces';
|
||||
|
||||
interface Values {
|
||||
jdbc_user: string;
|
||||
jdbc_password: string;
|
||||
@@ -9,32 +11,6 @@ interface Values {
|
||||
schema: string;
|
||||
}
|
||||
|
||||
interface Cron {
|
||||
hours: string[];
|
||||
hour_interval: boolean;
|
||||
hour_resourse: boolean;
|
||||
hour_resourse_value: number;
|
||||
month_day: string[];
|
||||
month_day_interval: boolean;
|
||||
month_day_resourse: boolean;
|
||||
month_day_resourse_value: number;
|
||||
month: string[];
|
||||
month_interval: boolean;
|
||||
month_resourse: boolean;
|
||||
month_resourse_value: number;
|
||||
week_days: string[];
|
||||
week_days_interval: boolean;
|
||||
week_days_resourse: boolean;
|
||||
week_days_resourse_value: number;
|
||||
}
|
||||
|
||||
export interface Info {
|
||||
customer_id: string;
|
||||
user_id: string;
|
||||
customer: string;
|
||||
customer_tier: string;
|
||||
}
|
||||
|
||||
export interface ICreateInputRequest {
|
||||
cron: string;
|
||||
name: string;
|
||||
@@ -56,6 +32,7 @@ export interface UpdateInputRequest {
|
||||
values: Values;
|
||||
operation: string;
|
||||
info: Info;
|
||||
tables: any[];
|
||||
}
|
||||
|
||||
export interface ITestConnectionRequest {
|
||||
@@ -0,0 +1,38 @@
|
||||
import { Input } from '@dadosfera/protospack-v2';
|
||||
import { credentials } from '@grpc/grpc-js';
|
||||
import {
|
||||
ClientProviderOptions,
|
||||
GrpcOptions,
|
||||
Transport,
|
||||
} from '@nestjs/microservices';
|
||||
|
||||
export class InputsGrpcClient {
|
||||
public readonly name = 'InputsGrpcClient';
|
||||
private config: GrpcOptions = {
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
url: process.env.INFACTORY_URL,
|
||||
package: [
|
||||
Input.ProtoPackages.WritePackage,
|
||||
Input.ProtoPackages.ReadPackage,
|
||||
],
|
||||
credentials:
|
||||
process.env.LOCAL_ENV || process.env.ENV === 'local'
|
||||
? undefined
|
||||
: credentials.createSsl(),
|
||||
protoPath: [
|
||||
Input.ProtoPaths.WriteFilePath,
|
||||
Input.ProtoPaths.ReadFilePath,
|
||||
],
|
||||
loader: {
|
||||
keepCase: true,
|
||||
enums: String,
|
||||
defaults: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
providerOptions: ClientProviderOptions = {
|
||||
name: this.name,
|
||||
...this.config,
|
||||
};
|
||||
}
|
||||
@@ -9,10 +9,8 @@ import {
|
||||
Post,
|
||||
} from '@nestjs/common';
|
||||
import { InputsService } from './inputs.service';
|
||||
import { DadosferaLogger } from 'dadosfera-logs';
|
||||
import { InputsClientService } from 'src/clients/inputs/client.service';
|
||||
import { UpdateInputRequest } from 'src/clients/inputs/interfaces';
|
||||
import { Permissions } from '../../authentication/permissions.enum';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import { PERMISSIONS_GROUPS } from '../../authentication/permissions.enum';
|
||||
import { AuthenticateCondition } from 'src/authentication/authentication.decorator';
|
||||
import { ApiOkResponse, ApiTags } from '@nestjs/swagger';
|
||||
import {
|
||||
@@ -25,48 +23,44 @@ import {
|
||||
TestConnectionReq,
|
||||
TestConnectionRes,
|
||||
} from './dtos/input.model';
|
||||
import { UpdateInputRequest } from './dtos/old_interfaces';
|
||||
import { RequestUser, User } from 'src/authentication/user.decorator';
|
||||
import { Info } from '@dadosfera/protospack-v2/dist/lib/Input/interfaces/entities';
|
||||
|
||||
@ApiTags('inputs')
|
||||
@Controller('inputs')
|
||||
@AuthenticateCondition((req, user) => {
|
||||
let action: any;
|
||||
|
||||
switch (req.method) {
|
||||
case 'POST':
|
||||
action = 'CREATE';
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
action = 'UPDATE';
|
||||
break;
|
||||
|
||||
case 'PATCH':
|
||||
action = 'UPDATE_PARTIAL';
|
||||
break;
|
||||
return (
|
||||
user.permissions.includes(
|
||||
PERMISSIONS_GROUPS.PIPELINE.permissions.CREATE.seqid,
|
||||
) ||
|
||||
user.permissions.includes(PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE.seqid)
|
||||
);
|
||||
|
||||
default:
|
||||
action = req.method;
|
||||
return (
|
||||
user.permissions.includes(
|
||||
PERMISSIONS_GROUPS.PIPELINE.permissions.CREATE.seqid,
|
||||
) ||
|
||||
user.permissions.includes(
|
||||
PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE.seqid,
|
||||
) ||
|
||||
user.permissions.includes(PERMISSIONS_GROUPS.PIPELINE.permissions.GET.seqid)
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
`${req.method} ${req.route.path}` ===
|
||||
'GET /inputs/available-entities/:plugin'
|
||||
) {
|
||||
action = 'GET_ENTITIES';
|
||||
}
|
||||
|
||||
return user.permissions.includes(Permissions.INPUT[action].seqid);
|
||||
})
|
||||
export class InputsController {
|
||||
inputService: InputsService;
|
||||
logger: any;
|
||||
logger: DadosferaLogger;
|
||||
constructor(
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
private inputsClientService: InputsClientService,
|
||||
private inputService: InputsService,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
this.inputService = new InputsService(this.inputsClientService);
|
||||
}
|
||||
|
||||
@Get('available-entities/:plugin')
|
||||
@@ -111,36 +105,35 @@ export class InputsController {
|
||||
|
||||
@Post()
|
||||
@ApiOkResponse({ type: Input })
|
||||
async create(@Body() createInputDto: CreateInputReq) {
|
||||
async create(@Body() body: CreateInputReq, @User() user: RequestUser) {
|
||||
const info: Info = {
|
||||
user_id: user.user_id,
|
||||
customer: user.customer_name,
|
||||
customer_id: user.customer_id,
|
||||
};
|
||||
this.logger.info(`/input - ON CREATE ROUTE`, {
|
||||
user: createInputDto.info.user_id,
|
||||
customer: createInputDto.info.customer,
|
||||
user: info.user_id,
|
||||
customer: info.customer,
|
||||
});
|
||||
|
||||
const response = await this.inputService.create(createInputDto);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Post(':id')
|
||||
@ApiOkResponse({ type: Input })
|
||||
async reCreate(@Param('id') id: string, @Body() input: CreateInputReq) {
|
||||
if (!input.id) input.id = id;
|
||||
this.logger.info(`POST /${id}`, 'ON RECREATE ROUTE');
|
||||
|
||||
const response = await this.inputService.reCreate(input);
|
||||
const response = await this.inputService.create({ body, info });
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Get()
|
||||
async findAll(@Body() body) {
|
||||
async findAll(@User() user: RequestUser) {
|
||||
const { user_id, customer_id, customer_name: customer } = user;
|
||||
this.logger.info(`/input - ON FIND ALL ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
user: user.user_id,
|
||||
customer,
|
||||
});
|
||||
|
||||
const response = await this.inputService.findAll(body);
|
||||
const info: Info = {
|
||||
customer,
|
||||
customer_id,
|
||||
user_id,
|
||||
};
|
||||
const response = await this.inputService.findAll(info);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ClientsModule } from '@nestjs/microservices';
|
||||
import { InputsGrpcClient } from './inputs-client.config';
|
||||
import { InputsController } from './inputs.controller';
|
||||
import { InputsService } from './inputs.service';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
|
||||
const client = new InputsGrpcClient();
|
||||
|
||||
@Module({
|
||||
controllers: [InputsController],
|
||||
providers: [InputsService, DadosferaLogger],
|
||||
imports: [ClientsModule.register([client.providerOptions])],
|
||||
exports: [InputsService],
|
||||
})
|
||||
export class InputsModule {}
|
||||
@@ -1,20 +1,177 @@
|
||||
import { Body, HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||
import {
|
||||
ForbiddenException,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
Inject,
|
||||
Injectable,
|
||||
} from '@nestjs/common';
|
||||
import { Timeout } from '@nestjs/schedule';
|
||||
import { DecodeGrpcStruct } from 'protospack';
|
||||
import CronParser, { CronExpression } from 'cron-parser';
|
||||
import { InputsClientService } from 'src/clients/inputs/client.service';
|
||||
import { IIdRequest, Info } from 'src/clients/inputs/interfaces';
|
||||
import { ClientGrpc } from '@nestjs/microservices';
|
||||
import DadosferaLogger from '@dadosfera/dadosfera-logs/dist';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import { objectCamelToSnake } from 'src/utils/CaseConverter';
|
||||
import { IIdRequest, UpdateInputRequest } from './dtos/old_interfaces';
|
||||
import { Input } from '@dadosfera/protospack-v2';
|
||||
import {
|
||||
InputCreateGenericRequest,
|
||||
InputCreateS3Request,
|
||||
InputNewCreateRequest,
|
||||
TestConnectionGetColumnsRequest,
|
||||
TestConnectionRequest,
|
||||
} from '@dadosfera/protospack-v2/dist/lib/Input/interfaces/messages';
|
||||
import { Info } from '@dadosfera/protospack-v2/dist/lib/Input/interfaces/entities';
|
||||
import { CreateInputReq } from './dtos/input.model';
|
||||
|
||||
@Injectable()
|
||||
|
||||
//TODO refactor this class to remove OLD_inputClient
|
||||
export class InputsService {
|
||||
constructor(private inputClient: InputsClientService) { }
|
||||
logger: DadosferaLogger;
|
||||
inputWriteService: Input.WriteService.InputWriteService;
|
||||
inputReadService: Input.ReadService.InputReadService;
|
||||
|
||||
constructor(
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
@Inject('InputsGrpcClient') private readonly grpcClient: ClientGrpc,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
|
||||
async onModuleInit() {
|
||||
this.inputWriteService =
|
||||
this.grpcClient.getService<Input.WriteService.InputWriteService>(
|
||||
Input.ProtoServices.InputWriteService,
|
||||
);
|
||||
this.inputReadService =
|
||||
this.grpcClient.getService<Input.ReadService.InputReadService>(
|
||||
Input.ProtoServices.InputReadService,
|
||||
);
|
||||
}
|
||||
|
||||
OLD_inputClient = {
|
||||
newCreate: async (createInputDto: InputNewCreateRequest) => {
|
||||
this.logger.info('InputClientService - Create');
|
||||
|
||||
const input = await lastValueFrom(
|
||||
this.inputWriteService.InputNewCreate(createInputDto),
|
||||
);
|
||||
objectCamelToSnake(input);
|
||||
return input;
|
||||
},
|
||||
createS3Inputs: async (createInputDto: InputCreateS3Request) => {
|
||||
this.logger.info('InputClientService - Create');
|
||||
createInputDto;
|
||||
const createInputResponse = await lastValueFrom(
|
||||
this.inputWriteService.InputCreateS3(createInputDto),
|
||||
).catch((e) => {
|
||||
throw new HttpException(e.details, 500);
|
||||
});
|
||||
this.logger.info('Done');
|
||||
objectCamelToSnake(createInputResponse);
|
||||
return createInputResponse;
|
||||
},
|
||||
findOne: async (data: IIdRequest) => {
|
||||
this.logger.info('InputClientService - FindOne');
|
||||
const findOneInputResponse = await lastValueFrom(
|
||||
this.inputReadService.InputFindOne(data),
|
||||
).catch((e) => {
|
||||
this.logger.error(e.details);
|
||||
throw new HttpException(e.details, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
});
|
||||
objectCamelToSnake(findOneInputResponse);
|
||||
return findOneInputResponse;
|
||||
},
|
||||
update: async (updateInputDTO: UpdateInputRequest) => {
|
||||
this.logger.info('InputClientService - Update');
|
||||
const updateInputResponse = await lastValueFrom(
|
||||
this.inputWriteService.InputUpdate(updateInputDTO),
|
||||
);
|
||||
|
||||
return updateInputResponse;
|
||||
},
|
||||
remove: async (idRequest: IIdRequest) => {
|
||||
this.logger.info('InputClientService - Remove');
|
||||
const removeInputResponse = await lastValueFrom(
|
||||
this.inputWriteService.InputRemove(idRequest),
|
||||
);
|
||||
|
||||
return removeInputResponse;
|
||||
},
|
||||
testConnection: async (data: TestConnectionRequest) => {
|
||||
this.logger.info('InputClientService - TestConnection');
|
||||
const testConnectionResponse = await lastValueFrom(
|
||||
this.inputReadService.NewTestConnection(data),
|
||||
);
|
||||
|
||||
return testConnectionResponse;
|
||||
},
|
||||
getColumns: async (data: TestConnectionGetColumnsRequest) => {
|
||||
this.logger.info('InputClientService - TestConnection/Get-Columns');
|
||||
const getColumnsResponse = await new Promise((resolve, reject) => {
|
||||
this.inputReadService.GetColumns(data).subscribe({
|
||||
next(x) {
|
||||
resolve(objectCamelToSnake(x));
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
// console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return getColumnsResponse;
|
||||
},
|
||||
getAvailableEntities: async (data) => {
|
||||
this.logger.info('InputClientService - GetAvailableEntities');
|
||||
data;
|
||||
const response = await lastValueFrom(
|
||||
this.inputReadService.GetAvailableEntities(data),
|
||||
).catch((err) => {
|
||||
this.logger.info(err.details);
|
||||
if (err.details && err.details.includes('400'))
|
||||
throw new HttpException('Plugin inválido', HttpStatus.BAD_REQUEST);
|
||||
throw new HttpException(err.details, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
});
|
||||
objectCamelToSnake(response);
|
||||
|
||||
return response;
|
||||
},
|
||||
};
|
||||
|
||||
secondsInADay = 60 * 60 * 24;
|
||||
secondsInAnHour = 60 * 60;
|
||||
|
||||
adjustInputPayload(payload) {
|
||||
if (payload?.input_generic) return DecodeGrpcStruct(payload.input_generic);
|
||||
if (!payload.input_s3 && !payload.input_jdbc) return payload;
|
||||
return payload?.input_s3 || payload?.input_jdbc;
|
||||
if (payload) {
|
||||
if (payload.input_generic) {
|
||||
const { credentials } = payload.input_generic;
|
||||
return {
|
||||
...payload.input_generic,
|
||||
credentials: credentials && JSON.parse(credentials),
|
||||
};
|
||||
}
|
||||
if (payload.input_s3) return payload.input_s3;
|
||||
if (payload.input_jdbc) return payload.input_jdbc;
|
||||
|
||||
const { credentials } = payload;
|
||||
return {
|
||||
...payload,
|
||||
credentials: credentials && JSON.parse(credentials),
|
||||
};
|
||||
}
|
||||
return payload;
|
||||
}
|
||||
getDifferenceInSeconds(date1: Date, date2: Date) {
|
||||
const diffInMs = Math.abs(date2.getTime() - date1.getTime());
|
||||
@@ -37,71 +194,53 @@ export class InputsService {
|
||||
const afterNextDate = interval.next().toDate();
|
||||
const secondsApart = this.getDifferenceInSeconds(nextDate, afterNextDate);
|
||||
if (customer_tier === 'BASIC' && secondsApart < this.secondsInADay) {
|
||||
throw new HttpException(
|
||||
throw new ForbiddenException(
|
||||
'Intervalo de tempo não pode ser inferior a um dia.',
|
||||
HttpStatus.FORBIDDEN,
|
||||
);
|
||||
} else if (secondsApart < this.secondsInAnHour) {
|
||||
throw new HttpException(
|
||||
throw new ForbiddenException(
|
||||
'Intervalo de tempo não pode ser inferior a uma hora.',
|
||||
HttpStatus.FORBIDDEN,
|
||||
);
|
||||
}
|
||||
}
|
||||
async create(@Body() data) {
|
||||
this.validateCron(data);
|
||||
let response;
|
||||
switch (data.plugin.toLowerCase()) {
|
||||
case 'csv':
|
||||
case 'json':
|
||||
case 'parquet':
|
||||
const { info, ...input } = data;
|
||||
const inputPayload = this.generateInputS3Payload(input);
|
||||
response = await this.inputClient.createS3Inputs({
|
||||
input: inputPayload,
|
||||
info,
|
||||
});
|
||||
break;
|
||||
case 'oracle':
|
||||
case 'mysql':
|
||||
case 'postgresql':
|
||||
case 'sqlserver':
|
||||
response = await this.inputClient.newCreate(data);
|
||||
break;
|
||||
default:
|
||||
response = await this.inputClient.createGeneric(data);
|
||||
break;
|
||||
}
|
||||
const adjustedInput = this.adjustInputPayload(response.input);
|
||||
return { ...response, input: adjustedInput };
|
||||
}
|
||||
async reCreate(data) {
|
||||
const { info, cron } = data;
|
||||
if (cron) this.validateCron({ info, cron });
|
||||
const response = await this.inputClient.createGeneric(data);
|
||||
const adjustedInput = this.adjustInputPayload(response.input);
|
||||
return { ...response, input: adjustedInput };
|
||||
async create(data: { body: CreateInputReq; info: Info }) {
|
||||
// this.validateCron(data);
|
||||
const { body, info } = data;
|
||||
|
||||
if (body.info) delete body.info;
|
||||
|
||||
const inputCreateGenericRequest: any | InputCreateGenericRequest = {
|
||||
input: {
|
||||
...body,
|
||||
credentials: body.credentials && JSON.stringify(body.credentials),
|
||||
},
|
||||
info,
|
||||
};
|
||||
|
||||
const { input } = await lastValueFrom(
|
||||
this.inputWriteService.InputCreate(inputCreateGenericRequest),
|
||||
);
|
||||
const adjustedInput = this.adjustInputPayload(input);
|
||||
return { input: adjustedInput };
|
||||
}
|
||||
|
||||
async getAvailableEntities(data): Promise<{ entities: string[] }> {
|
||||
return await this.inputClient.getAvailableEntities(data);
|
||||
return await this.OLD_inputClient.getAvailableEntities(data);
|
||||
}
|
||||
async findAll(body) {
|
||||
try {
|
||||
const findAllInputResponse: any = await this.inputClient.findAll(body);
|
||||
if (findAllInputResponse?.inputs?.length) {
|
||||
findAllInputResponse.inputs = findAllInputResponse.inputs.map((input) =>
|
||||
this.adjustInputPayload(input),
|
||||
);
|
||||
}
|
||||
return findAllInputResponse;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
async findAll(info: Info) {
|
||||
const { inputs } = await lastValueFrom(
|
||||
this.inputReadService.InputFindAll({ info }),
|
||||
);
|
||||
if (!inputs) return { inputs: [] };
|
||||
|
||||
const inputsReturn = inputs.map((i) => this.adjustInputPayload(i));
|
||||
return { inputs: inputsReturn };
|
||||
}
|
||||
|
||||
async findOne(idRequest: IIdRequest) {
|
||||
try {
|
||||
const findOneInputResponse: any = await this.inputClient.findOne(
|
||||
const findOneInputResponse: any = await this.OLD_inputClient.findOne(
|
||||
idRequest,
|
||||
);
|
||||
findOneInputResponse.input = this.adjustInputPayload(
|
||||
@@ -116,7 +255,7 @@ export class InputsService {
|
||||
async update(id: string, data, info: Info) {
|
||||
this.validateCron({ ...data, info });
|
||||
try {
|
||||
const updateInputResponse: any = await this.inputClient.update({
|
||||
const updateInputResponse: any = await this.OLD_inputClient.update({
|
||||
id,
|
||||
info,
|
||||
...data,
|
||||
@@ -133,7 +272,7 @@ export class InputsService {
|
||||
|
||||
async remove(idRequest: IIdRequest) {
|
||||
try {
|
||||
const removeInputResponse = await this.inputClient.remove(idRequest);
|
||||
const removeInputResponse = await this.OLD_inputClient.remove(idRequest);
|
||||
|
||||
return removeInputResponse;
|
||||
} catch (err) {
|
||||
@@ -144,9 +283,8 @@ export class InputsService {
|
||||
@Timeout(60000 * 10) // Timeout set for 10 minutes
|
||||
async testConnection(data) {
|
||||
try {
|
||||
const testConnectionInputResponse = await this.inputClient.testConnection(
|
||||
data,
|
||||
);
|
||||
const testConnectionInputResponse =
|
||||
await this.OLD_inputClient.testConnection(data);
|
||||
|
||||
return testConnectionInputResponse;
|
||||
} catch (err) {
|
||||
@@ -157,7 +295,7 @@ export class InputsService {
|
||||
async getColumns(data) {
|
||||
try {
|
||||
const testConnectionGetColumnsResponse =
|
||||
await this.inputClient.getColumns(data);
|
||||
await this.OLD_inputClient.getColumns(data);
|
||||
|
||||
return testConnectionGetColumnsResponse;
|
||||
} catch (err) {
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
import {
|
||||
NetworkConfigEntity,
|
||||
NetworkConfigToCatalog,
|
||||
} from '@dadosfera/protospack-v2/dist/lib/NetworkConfig/interfaces/entities';
|
||||
import {
|
||||
ApiProperty,
|
||||
ApiPropertyOptional,
|
||||
OmitType,
|
||||
PickType,
|
||||
} from '@nestjs/swagger';
|
||||
|
||||
export enum NetworkConfigTypesEnum {
|
||||
vpn = 'vpn',
|
||||
}
|
||||
export enum NetworkConfigPluginsEnum {
|
||||
openvpn = 'openvpn',
|
||||
}
|
||||
export interface ConnectionsApiNetworkConfig {
|
||||
config_id: string;
|
||||
created_at: string;
|
||||
credentials: {
|
||||
CERTIFICATE_FILE: string;
|
||||
OVPN_CREDENTIALS: string;
|
||||
TLS_AUTH_FILE: string;
|
||||
OVPN_FILE: string;
|
||||
};
|
||||
customer_name: string;
|
||||
description: string;
|
||||
name: string;
|
||||
plugin: string;
|
||||
secret_id: string;
|
||||
sensitive_fields: string[];
|
||||
type: string;
|
||||
updated_at: string;
|
||||
}
|
||||
export class NetworkConfigDto implements NetworkConfigEntity {
|
||||
@ApiProperty()
|
||||
id: string;
|
||||
@ApiProperty()
|
||||
created_at: string;
|
||||
@ApiProperty()
|
||||
updated_at: string;
|
||||
@ApiProperty()
|
||||
customer_name: string;
|
||||
@ApiProperty()
|
||||
customer_id: string;
|
||||
@ApiProperty()
|
||||
properties: any;
|
||||
@ApiProperty()
|
||||
user_id: string;
|
||||
@ApiProperty()
|
||||
keywords: string;
|
||||
@ApiProperty()
|
||||
tags: string;
|
||||
|
||||
@ApiProperty()
|
||||
network_type_id: string;
|
||||
@ApiProperty()
|
||||
network_type_name: string;
|
||||
@ApiProperty({ enum: NetworkConfigTypesEnum })
|
||||
type: string;
|
||||
@ApiProperty({ enum: NetworkConfigPluginsEnum })
|
||||
plugin: string;
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
@ApiProperty()
|
||||
description: string;
|
||||
}
|
||||
|
||||
export class CreateNetworkConfigReq extends PickType(NetworkConfigDto, [
|
||||
'network_type_id',
|
||||
'network_type_name',
|
||||
'name',
|
||||
'description',
|
||||
]) {
|
||||
@ApiProperty({ format: 'binary' })
|
||||
ovpn_file: string;
|
||||
}
|
||||
|
||||
export class NetworkConfigOpenVpnProperties {
|
||||
@ApiProperty({ enum: NetworkConfigPluginsEnum })
|
||||
plugin: NetworkConfigPluginsEnum;
|
||||
@ApiProperty()
|
||||
OVPN_FILE: string;
|
||||
@ApiPropertyOptional()
|
||||
CERTIFICATE_FILE?: string;
|
||||
@ApiPropertyOptional()
|
||||
OVPN_CREDENTIALS?: string;
|
||||
@ApiPropertyOptional()
|
||||
TLS_AUTH_FILE?: string;
|
||||
}
|
||||
|
||||
export class NetworkConfigToCatalogDto implements NetworkConfigToCatalog {
|
||||
@ApiProperty()
|
||||
id: string;
|
||||
|
||||
@ApiProperty()
|
||||
customer_id: string;
|
||||
|
||||
@ApiProperty()
|
||||
plugin: string;
|
||||
|
||||
@ApiProperty()
|
||||
type: string;
|
||||
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
|
||||
@ApiProperty()
|
||||
description: string;
|
||||
|
||||
@ApiProperty()
|
||||
created_at: string;
|
||||
|
||||
@ApiProperty()
|
||||
updated_at: string;
|
||||
|
||||
@ApiProperty()
|
||||
network_type_id: string;
|
||||
|
||||
@ApiProperty()
|
||||
network_type_name: string;
|
||||
}
|
||||
export class FindAllNetworkConfigsRes {
|
||||
@ApiProperty({ type: [NetworkConfigToCatalogDto] })
|
||||
network_configs: NetworkConfigToCatalogDto[];
|
||||
|
||||
@ApiProperty()
|
||||
message: string;
|
||||
}
|
||||
|
||||
export class FindNetworkConfigByidRes {
|
||||
@ApiProperty()
|
||||
network_config: NetworkConfigToCatalogDto;
|
||||
}
|
||||
|
||||
export class FindNetworkConfigByidDetails extends PickType(NetworkConfigDto, [
|
||||
'id',
|
||||
'name',
|
||||
'description',
|
||||
'type',
|
||||
'network_type_id',
|
||||
'customer_name',
|
||||
]) {
|
||||
@ApiProperty()
|
||||
properties: NetworkConfigOpenVpnProperties | string;
|
||||
}
|
||||
export class FindNetworkConfigByidDetailsRes {
|
||||
@ApiProperty()
|
||||
network_config: FindNetworkConfigByidDetails;
|
||||
}
|
||||
|
||||
export class CreateNetworkConfigRes {
|
||||
@ApiProperty()
|
||||
network_config: NetworkConfigToCatalogDto;
|
||||
}
|
||||
|
||||
export class UpdateNetworkConfigReq {
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
@ApiProperty()
|
||||
description: string;
|
||||
}
|
||||
export class UpdateNetworkConfigRes {
|
||||
@ApiProperty()
|
||||
network_config: NetworkConfigToCatalogDto;
|
||||
}
|
||||
|
||||
export class DeleteNetworkConfigRes {
|
||||
@ApiProperty()
|
||||
message: string;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { credentials } from '@grpc/grpc-js';
|
||||
import {
|
||||
ClientProviderOptions,
|
||||
GrpcOptions,
|
||||
Transport,
|
||||
} from '@nestjs/microservices';
|
||||
import { NetworkConfig } from '@dadosfera/protospack-v2';
|
||||
|
||||
export class NetworkConfigGrpcClient {
|
||||
public name = 'NetworkConfigGrpcClient';
|
||||
|
||||
private config: GrpcOptions = {
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
url: process.env.INFACTORY_URL,
|
||||
package: [
|
||||
NetworkConfig.ProtoPackages.ReadPackage,
|
||||
NetworkConfig.ProtoPackages.WritePackage,
|
||||
],
|
||||
credentials:
|
||||
process.env.ENV === 'local' ? undefined : credentials.createSsl(),
|
||||
protoPath: [
|
||||
NetworkConfig.ProtoPaths.ReadFilePath,
|
||||
NetworkConfig.ProtoPaths.WriteFilePath,
|
||||
],
|
||||
loader: {
|
||||
keepCase: true,
|
||||
enums: String,
|
||||
objects: true,
|
||||
arrays: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
providerOptions: ClientProviderOptions = {
|
||||
name: this.name,
|
||||
...this.config,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Headers,
|
||||
Inject,
|
||||
Param,
|
||||
Patch,
|
||||
Post,
|
||||
Query,
|
||||
UploadedFile,
|
||||
UseInterceptors,
|
||||
} from '@nestjs/common';
|
||||
import { NetworkConfigService } from './network-config.service';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import { ApiConsumes, ApiOkResponse, ApiTags } from '@nestjs/swagger';
|
||||
import { RequestUser, User } from 'src/authentication/user.decorator';
|
||||
import {
|
||||
CreateNetworkConfigReq,
|
||||
CreateNetworkConfigRes,
|
||||
FindAllNetworkConfigsRes,
|
||||
} from './dto/network-config';
|
||||
import { FileInterceptor } from '@nestjs/platform-express';
|
||||
import { PERMISSIONS_GROUPS } from 'src/authentication/permissions.enum';
|
||||
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;
|
||||
constructor(
|
||||
private networkConfigService: NetworkConfigService,
|
||||
@Inject(DadosferaLogger) dadosferaLogger: DadosferaLogger,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
@Get()
|
||||
@ApiOkResponse({ type: FindAllNetworkConfigsRes })
|
||||
async findAllNetworkConfigs(
|
||||
@User() user: RequestUser,
|
||||
@Headers('Dadosfera-Lang') language,
|
||||
@Query() queries,
|
||||
) {
|
||||
this.logger.info('GET /network-config', {
|
||||
user: user.user_id,
|
||||
customer: user.customer_name,
|
||||
});
|
||||
if (!language) language = 'en-us';
|
||||
|
||||
const { user_id, customer_id, customer_name } = user;
|
||||
const { search, size, page, ...filters } = queries;
|
||||
|
||||
return this.networkConfigService.findAllNetworkConfigs({
|
||||
body: { search, size, page, filters },
|
||||
info: { user_id, customer_id, customer_name, language },
|
||||
});
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@ApiOkResponse({ type: FindAllNetworkConfigsRes })
|
||||
async findNetworkConfigById(
|
||||
@User() user: RequestUser,
|
||||
@Param('id') id: string,
|
||||
) {
|
||||
this.logger.info('GET /network-config/:id', {
|
||||
user: user.user_id,
|
||||
customer: user.customer_name,
|
||||
});
|
||||
return this.networkConfigService.findNetworkConfigById(id);
|
||||
}
|
||||
|
||||
@Get(':id/details')
|
||||
@ApiOkResponse({ type: FindAllNetworkConfigsRes })
|
||||
async findNetworkConfigByIdDetails(
|
||||
@User() user: RequestUser,
|
||||
@Headers('Dadosfera-Lang') language,
|
||||
@Param('id') id: string,
|
||||
) {
|
||||
this.logger.info('GET /network-config/:id', {
|
||||
user: user.user_id,
|
||||
customer: user.customer_name,
|
||||
});
|
||||
if (!language) language = 'en-us';
|
||||
return this.networkConfigService.findNetworkConfigByIdDetails(id, {
|
||||
customer_name: user.customer_name,
|
||||
customer_id: user.customer_id,
|
||||
language,
|
||||
});
|
||||
}
|
||||
|
||||
@Post()
|
||||
@ApiOkResponse({ type: CreateNetworkConfigRes })
|
||||
@RequireAllPermissions(networkConfigPermissions.CREATE)
|
||||
@ApiConsumes('multipart/form-data')
|
||||
@UseInterceptors(FileInterceptor('ovpn_file'))
|
||||
async createNetworkConfigs(
|
||||
@User() user: RequestUser,
|
||||
@UploadedFile() file: Express.Multer.File,
|
||||
@Body() body: CreateNetworkConfigReq,
|
||||
) {
|
||||
this.logger.info('POST /network-config', {
|
||||
user: user.user_id,
|
||||
customer: user.customer_name,
|
||||
});
|
||||
const { customer_id, customer_name, user_id } = user;
|
||||
return this.networkConfigService.createNetworkConfig(body, file, {
|
||||
customer_name,
|
||||
customer_id,
|
||||
user_id,
|
||||
});
|
||||
}
|
||||
|
||||
// @Patch(':id')
|
||||
// @ApiOkResponse({ type: UpdateNetworkConfigRes })
|
||||
// @RequireAllPermissions(networkConfigPermissions.CREATE)
|
||||
// async updateNetworkConfig(
|
||||
// @User() user: RequestUser,
|
||||
// @Param('id') network_config_id: string,
|
||||
// @Body() body: UpdateNetworkConfigReq,
|
||||
// ) {
|
||||
// this.logger.info('PATCH /network-config/:id', {
|
||||
// user: user.user_id,
|
||||
// customer: user.customer_name,
|
||||
// });
|
||||
// return this.networkConfigService.updateNetworkConfig(
|
||||
// body,
|
||||
// network_config_id,
|
||||
// );
|
||||
// }
|
||||
|
||||
// @Delete(':id')
|
||||
// @ApiOkResponse({ type: DeleteNetworkConfigRes })
|
||||
// async deleteNetworkConfig(
|
||||
// @User() user: RequestUser,
|
||||
// @Param('id') network_config_id: string,
|
||||
// ) {
|
||||
// this.logger.info('DELETE /network-config', {
|
||||
// user: user.user_id,
|
||||
// customer: user.customer_name,
|
||||
// });
|
||||
// return this.networkConfigService.deleteNetworkConfig(network_config_id, {
|
||||
// customer_name: user.customer_name,
|
||||
// customer_id: user.customer_id,
|
||||
// });
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { NetworkConfigController } from './network-config.controller';
|
||||
import { NetworkConfigService } from './network-config.service';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import { ClientsModule } from '@nestjs/microservices';
|
||||
import { NetworkConfigGrpcClient } from './network-config-client.config';
|
||||
const client = new NetworkConfigGrpcClient();
|
||||
|
||||
@Module({
|
||||
controllers: [NetworkConfigController],
|
||||
providers: [NetworkConfigService, DadosferaLogger],
|
||||
imports: [ClientsModule.register([client.providerOptions])],
|
||||
})
|
||||
export class NetworkConfigModule {}
|
||||
@@ -0,0 +1,158 @@
|
||||
import { Metadata } from '@grpc/grpc-js';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { ClientGrpc } from '@nestjs/microservices';
|
||||
import { NetworkConfig } from '@dadosfera/protospack-v2';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import {
|
||||
CreateNetworkConfigReq,
|
||||
CreateNetworkConfigRes,
|
||||
DeleteNetworkConfigRes,
|
||||
FindAllNetworkConfigsRes,
|
||||
FindNetworkConfigByidDetailsRes,
|
||||
FindNetworkConfigByidRes,
|
||||
UpdateNetworkConfigReq,
|
||||
UpdateNetworkConfigRes,
|
||||
} from './dto/network-config';
|
||||
import { NetworkConfigGrpcClient } from './network-config-client.config';
|
||||
|
||||
@Injectable()
|
||||
export class NetworkConfigService {
|
||||
private networkConfigReadClient: NetworkConfig.ReadService.NetworkConfigReadService;
|
||||
private networkConfigWriteClient: NetworkConfig.WriteService.NetworkConfigWriteService;
|
||||
constructor(
|
||||
@Inject(NetworkConfigGrpcClient.name)
|
||||
private readonly grpcClient: ClientGrpc,
|
||||
) {
|
||||
this.networkConfigReadClient =
|
||||
grpcClient.getService<NetworkConfig.ReadService.NetworkConfigReadService>(
|
||||
NetworkConfig.ProtoServices.NetworkConfigReadService,
|
||||
);
|
||||
this.networkConfigWriteClient =
|
||||
grpcClient.getService<NetworkConfig.WriteService.NetworkConfigWriteService>(
|
||||
NetworkConfig.ProtoServices.NetworkConfigWriteService,
|
||||
);
|
||||
}
|
||||
async findAllNetworkConfigs({
|
||||
body,
|
||||
info,
|
||||
}): Promise<FindAllNetworkConfigsRes> {
|
||||
const { search, page, size, filters } = body;
|
||||
const { language, customer_id, customer_name, user_id } = info;
|
||||
|
||||
const meta = new Metadata();
|
||||
|
||||
meta.add('language', language);
|
||||
meta.add('customer_id', customer_id);
|
||||
meta.add('customer_name', customer_name);
|
||||
meta.add('user_id', user_id);
|
||||
|
||||
return lastValueFrom(
|
||||
this.networkConfigReadClient.NetworkConfigFindAll(
|
||||
{ search, filters: JSON.stringify(filters), page, size },
|
||||
meta,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
async findNetworkConfigById(id: string): Promise<FindNetworkConfigByidRes> {
|
||||
const { network_config } = await lastValueFrom(
|
||||
this.networkConfigReadClient.NetworkConfigFindOneById({
|
||||
id,
|
||||
}),
|
||||
);
|
||||
return { network_config };
|
||||
}
|
||||
|
||||
async findNetworkConfigByIdDetails(
|
||||
id: string,
|
||||
info?,
|
||||
): Promise<FindNetworkConfigByidDetailsRes> {
|
||||
const { customer_name, customer_id, language } = info;
|
||||
|
||||
const meta = new Metadata();
|
||||
|
||||
meta.add('customer_name', customer_name);
|
||||
meta.add('customer_id', customer_id);
|
||||
meta.add('language', language);
|
||||
|
||||
const { network_config } = await lastValueFrom(
|
||||
this.networkConfigReadClient.NetworkConfigFindOneDetailsById(
|
||||
{ id },
|
||||
meta,
|
||||
),
|
||||
);
|
||||
|
||||
Object.assign(network_config, {
|
||||
properties: JSON.parse(network_config.properties),
|
||||
});
|
||||
return { network_config };
|
||||
}
|
||||
|
||||
async createNetworkConfig(
|
||||
body: CreateNetworkConfigReq,
|
||||
file: Express.Multer.File,
|
||||
{ customer_name, customer_id, user_id },
|
||||
): Promise<CreateNetworkConfigRes> {
|
||||
const { description, name, network_type_id, network_type_name } = body;
|
||||
|
||||
const type = 'vpn';
|
||||
const plugin = 'openvpn';
|
||||
|
||||
const OVPN_FILE_STRING = Buffer.from(file.buffer).toString();
|
||||
|
||||
const meta = new Metadata();
|
||||
|
||||
meta.add('customer_id', customer_id);
|
||||
meta.add('customer_name', customer_name);
|
||||
meta.add('user_id', user_id);
|
||||
|
||||
const { network_config } = await lastValueFrom(
|
||||
this.networkConfigWriteClient.NetworkConfigCreate(
|
||||
{
|
||||
description,
|
||||
name,
|
||||
properties: JSON.stringify({
|
||||
OVPN_FILE: OVPN_FILE_STRING,
|
||||
plugin,
|
||||
}),
|
||||
type,
|
||||
network_type_id,
|
||||
network_type_name,
|
||||
plugin,
|
||||
},
|
||||
meta,
|
||||
),
|
||||
);
|
||||
return { network_config };
|
||||
}
|
||||
|
||||
async updateNetworkConfig(
|
||||
body: UpdateNetworkConfigReq,
|
||||
network_config_id: string,
|
||||
): Promise<UpdateNetworkConfigRes> {
|
||||
const { description, name } = body;
|
||||
const { network_config } = await lastValueFrom(
|
||||
this.networkConfigWriteClient.NetworkConfigUpdate({
|
||||
id: network_config_id,
|
||||
description,
|
||||
name,
|
||||
}),
|
||||
);
|
||||
return { network_config };
|
||||
}
|
||||
|
||||
async deleteNetworkConfig(
|
||||
network_config_id: string,
|
||||
{ customer_name, customer_id },
|
||||
): Promise<DeleteNetworkConfigRes> {
|
||||
const meta = new Metadata();
|
||||
meta.add('customer_id', customer_id);
|
||||
meta.add('customer_name', customer_name);
|
||||
return lastValueFrom(
|
||||
this.networkConfigWriteClient.NetworkConfigDelete(
|
||||
{ id: network_config_id },
|
||||
meta,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,29 @@
|
||||
import { Controller, Get, Redirect, Req, UseGuards } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
import { InputsClientService } from 'src/clients/inputs/client.service';
|
||||
import { InputsService } from '../inputs/inputs.service';
|
||||
import { Request } from 'express';
|
||||
|
||||
import { ConnectionClientService } from '../connection/client.service';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import DadosferaLogger from '@dadosfera/dadosfera-logs/dist';
|
||||
import { PackTheMetadata } from 'src/utils/ PackTheMetadata';
|
||||
@ApiTags('oauth')
|
||||
@Controller('oauth')
|
||||
export class OauthController {
|
||||
inputService: InputsService;
|
||||
frontendRedirectUri = '';
|
||||
constructor(private inputsClientService: InputsClientService) {
|
||||
this.inputService = new InputsService(this.inputsClientService);
|
||||
redirectUrl: string;
|
||||
|
||||
constructor(
|
||||
private connectionService: ConnectionClientService,
|
||||
private logger: DadosferaLogger,
|
||||
) {
|
||||
switch (process.env.ENV) {
|
||||
case 'dev':
|
||||
case 'stg':
|
||||
this.frontendRedirectUri = `https://app.${process.env.ENV}.dadosfera.ai/coletix/auth-callback`;
|
||||
this.redirectUrl = `https://app.${process.env.ENV}.dadosfera.ai/coletix/auth-callback`;
|
||||
break;
|
||||
case 'prd':
|
||||
this.frontendRedirectUri = `https://app.dadosfera.ai/coletix/auth-callback`;
|
||||
this.redirectUrl = `https://app.dadosfera.ai/coletix/auth-callback`;
|
||||
break;
|
||||
default:
|
||||
this.frontendRedirectUri = `http://localhost:4200/coletix/auth-callback`;
|
||||
this.redirectUrl = `http://localhost:4200/coletix/auth-callback`;
|
||||
}
|
||||
}
|
||||
@Get('hubspot')
|
||||
@@ -34,7 +36,7 @@ export class OauthController {
|
||||
@UseGuards(AuthGuard('hubspot'))
|
||||
@Redirect()
|
||||
async oauthHubspotCallback(@Req() req) {
|
||||
return await this.callback(req, 'hubspot');
|
||||
return await this.callback(req);
|
||||
}
|
||||
|
||||
@Get('googleads')
|
||||
@@ -47,7 +49,7 @@ export class OauthController {
|
||||
@UseGuards(AuthGuard('google'))
|
||||
@Redirect()
|
||||
async oauthGoogleAdsCallback(@Req() req) {
|
||||
return await this.callback(req, 'googleads');
|
||||
return await this.callback(req);
|
||||
}
|
||||
|
||||
@Get('google-sheets')
|
||||
@@ -60,7 +62,7 @@ export class OauthController {
|
||||
@UseGuards(AuthGuard('google'))
|
||||
@Redirect()
|
||||
async oauthGoogleSheetsCallback(@Req() req) {
|
||||
return await this.callback(req, 'google-sheets');
|
||||
return await this.callback(req);
|
||||
}
|
||||
|
||||
@Get('facebook')
|
||||
@@ -73,7 +75,7 @@ export class OauthController {
|
||||
@UseGuards(AuthGuard('facebook'))
|
||||
@Redirect()
|
||||
async oauthFacebookCallback(@Req() req) {
|
||||
return await this.callback(req, 'facebook');
|
||||
return await this.callback(req);
|
||||
}
|
||||
|
||||
@Get('mailchimp')
|
||||
@@ -86,7 +88,7 @@ export class OauthController {
|
||||
@UseGuards(AuthGuard('mailchimp'))
|
||||
@Redirect()
|
||||
async oauthMailchimpCallback(@Req() req) {
|
||||
return await this.callback(req, 'mailchimp');
|
||||
return await this.callback(req);
|
||||
}
|
||||
|
||||
@Get('salesforce')
|
||||
@@ -99,32 +101,67 @@ export class OauthController {
|
||||
@UseGuards(AuthGuard('salesforce'))
|
||||
@Redirect()
|
||||
async oauthSalesforceCallback(@Req() req) {
|
||||
return await this.callback(req, 'salesforce');
|
||||
return await this.callback(req);
|
||||
}
|
||||
|
||||
async callback(@Req() req: Request, plugin) {
|
||||
const { error, state: customer_id } = req.query;
|
||||
async callback(@Req() req) {
|
||||
const { error, state } = req.query;
|
||||
const url = new URL(this.redirectUrl);
|
||||
|
||||
if (error)
|
||||
return {
|
||||
url: `${this.frontendRedirectUri}?error=${error}`,
|
||||
};
|
||||
const request: any = req;
|
||||
const { authInfo } = request;
|
||||
if (error) {
|
||||
this.logger.error(error);
|
||||
url.searchParams.set('error', 'Erro ao autorizar');
|
||||
url.searchParams.set(
|
||||
'error_description',
|
||||
`Credenciais inválidas. Erro: [${error}]`,
|
||||
);
|
||||
return { url: url.href };
|
||||
}
|
||||
|
||||
if (!authInfo)
|
||||
return {
|
||||
url: `${this.frontendRedirectUri}?error=invalid_credentials`,
|
||||
};
|
||||
const { authInfo } = req;
|
||||
|
||||
if (!authInfo) {
|
||||
this.logger.error('No authInfo', req);
|
||||
url.searchParams.set('error', 'Erro ao autorizar');
|
||||
url.searchParams.set('error_description', `Credenciais inválidas.`);
|
||||
return { url: url.href };
|
||||
}
|
||||
|
||||
const { accessToken: access_token, refreshToken: refresh_token } = authInfo;
|
||||
|
||||
const response = await this.inputService.create({
|
||||
info: { customer_id, customer: 'customer', user_id: 'empty' },
|
||||
plugin,
|
||||
credentials: { access_token, refresh_token },
|
||||
});
|
||||
let connectionInfo: any;
|
||||
try {
|
||||
connectionInfo = jwt.verify(state as string, process.env.JWT_PRIVATE_KEY);
|
||||
} catch (error) {
|
||||
this.logger.error('Invalid state JWT', { state, req, error });
|
||||
url.searchParams.set('error', 'Erro ao autorizar');
|
||||
url.searchParams.set(
|
||||
'error_description',
|
||||
'Ocorreu um erro ao autorizá-lo. Por favor tente novamente',
|
||||
);
|
||||
return { url: url.href };
|
||||
}
|
||||
|
||||
return { url: `${this.frontendRedirectUri}?input_id=${response.input.id}` };
|
||||
connectionInfo.properties.access_token = access_token;
|
||||
connectionInfo.properties.refresh_token = refresh_token;
|
||||
|
||||
const { customer_id, customer_name, user_id } = connectionInfo;
|
||||
|
||||
try {
|
||||
const response = await this.connectionService.createConnection(
|
||||
connectionInfo,
|
||||
PackTheMetadata({ customer_id, customer_name, user_id }),
|
||||
);
|
||||
url.searchParams.set('connection_id', response.connection.id);
|
||||
return { url: url.href };
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
url.searchParams.set('error', 'Erro ao autorizar');
|
||||
url.searchParams.set(
|
||||
'error_description',
|
||||
'Ocorreu um erro interno ao autorizá-lo. Por favor tente novamente mais tarde',
|
||||
);
|
||||
return { url: url.href };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { OauthController } from './oauth.controller';
|
||||
|
||||
import { getOauthSecrets } from '../../utils/OauthSecrets';
|
||||
|
||||
import { HubspotStrategy } from './passport-strategies/hubspot-strategy';
|
||||
import { FacebookStrategy } from './passport-strategies/facebook-strategy';
|
||||
import { GoogleStrategy } from './passport-strategies/google-strategy';
|
||||
import { MailChimpStrategy } from './passport-strategies/mailchimp-strategy';
|
||||
import { SalesforceStrategy } from './passport-strategies/salesforce-strategy';
|
||||
import { ConnectionModule } from '../connection/connection.module';
|
||||
import { OauthService } from './oauth.service';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
|
||||
@Module({
|
||||
providers: [
|
||||
DadosferaLogger,
|
||||
{ provide: 'OAUTH_SECRETS', useValue: getOauthSecrets() },
|
||||
HubspotStrategy,
|
||||
FacebookStrategy,
|
||||
GoogleStrategy,
|
||||
MailChimpStrategy,
|
||||
SalesforceStrategy,
|
||||
OauthService,
|
||||
],
|
||||
controllers: [OauthController],
|
||||
imports: [ConnectionModule],
|
||||
})
|
||||
export class OauthModule {}
|
||||
@@ -0,0 +1,51 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ConnectionDto } from '../connection/dtos/connection';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { PartialType } from '@nestjs/swagger';
|
||||
|
||||
class PartialConnection extends PartialType(ConnectionDto) {}
|
||||
|
||||
@Injectable()
|
||||
export class OauthService {
|
||||
generateStateFromRequest(prevState, req, type): string {
|
||||
if (req.route.path.includes('callback')) {
|
||||
return prevState;
|
||||
}
|
||||
const plugin: string = req.route.path.replace('/oauth/', '');
|
||||
|
||||
const { query } = req;
|
||||
const {
|
||||
name,
|
||||
description,
|
||||
connector_id,
|
||||
connector_name,
|
||||
image_url,
|
||||
user_id,
|
||||
customer_id,
|
||||
customer_name,
|
||||
} = query;
|
||||
|
||||
const properties = { plugin, credentials_type: 'oauth' };
|
||||
for (const key in query) {
|
||||
if (key.includes('properties.')) {
|
||||
const propertyKey = key.split('.')[1];
|
||||
properties[propertyKey] = query[key];
|
||||
}
|
||||
}
|
||||
|
||||
const newConnection: PartialConnection = {
|
||||
name,
|
||||
description,
|
||||
connector_id,
|
||||
connector_name,
|
||||
image_url,
|
||||
user_id,
|
||||
customer_id,
|
||||
customer_name,
|
||||
type,
|
||||
properties,
|
||||
plugin,
|
||||
};
|
||||
return jwt.sign({ ...newConnection }, process.env.JWT_PRIVATE_KEY);
|
||||
}
|
||||
}
|
||||
@@ -10,12 +10,14 @@ import { OauthSecrets } from 'src/utils/OauthSecrets';
|
||||
import { Request } from 'express';
|
||||
import { ParamsDictionary } from 'express-serve-static-core';
|
||||
import { ParsedQs } from 'qs';
|
||||
import { OauthService } from '../oauth.service';
|
||||
|
||||
@Injectable()
|
||||
export class FacebookStrategy extends PassportStrategy(Strategy) {
|
||||
constructor(
|
||||
@Inject('OAUTH_SECRETS')
|
||||
private readonly oauthSecrets: OauthSecrets,
|
||||
private oauthService: OauthService,
|
||||
) {
|
||||
const options: StrategyOption = {
|
||||
clientID: oauthSecrets.facebook.client_id,
|
||||
@@ -37,8 +39,11 @@ export class FacebookStrategy extends PassportStrategy(Strategy) {
|
||||
req: Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>,
|
||||
options?: any,
|
||||
): void {
|
||||
const { customer_id } = req.query;
|
||||
options.state = customer_id;
|
||||
options.state = this.oauthService.generateStateFromRequest(
|
||||
options.state,
|
||||
req,
|
||||
'application',
|
||||
);
|
||||
options.scope = 'ads_read ads_management';
|
||||
super.authenticate(req, options);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Profile, Strategy, StrategyOptions } from 'passport-google-oauth20';
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { OauthSecrets } from 'src/utils/OauthSecrets';
|
||||
import { OauthService } from '../oauth.service';
|
||||
|
||||
@Injectable()
|
||||
export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
|
||||
@@ -9,6 +10,7 @@ export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
|
||||
constructor(
|
||||
@Inject('OAUTH_SECRETS')
|
||||
private readonly oauthSecrets: OauthSecrets,
|
||||
private oauthService: OauthService,
|
||||
) {
|
||||
const options: StrategyOptions = {
|
||||
clientID: oauthSecrets.google.client_id,
|
||||
@@ -44,23 +46,30 @@ export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
|
||||
const plugin: string = req.route.path
|
||||
.replace('/oauth/', '')
|
||||
.replace('/callback', '');
|
||||
|
||||
const { customer_id } = req.query;
|
||||
options.scope = ['https://www.googleapis.com/auth/userinfo.email'];
|
||||
options.callbackURL = `${this.redirect_uri}/${plugin}/callback`;
|
||||
|
||||
switch (plugin) {
|
||||
case 'googleads':
|
||||
options.state = this.oauthService.generateStateFromRequest(
|
||||
options.state,
|
||||
req,
|
||||
'application',
|
||||
);
|
||||
options.scope.push('https://www.googleapis.com/auth/adwords');
|
||||
break;
|
||||
case 'google-sheets':
|
||||
options.state = this.oauthService.generateStateFromRequest(
|
||||
options.state,
|
||||
req,
|
||||
'file',
|
||||
);
|
||||
options.scope.push(
|
||||
'https://www.googleapis.com/auth/drive.metadata.readonly',
|
||||
'https://www.googleapis.com/auth/spreadsheets.readonly',
|
||||
);
|
||||
break;
|
||||
}
|
||||
options.state = customer_id;
|
||||
options.accessType = 'offline';
|
||||
options.prompt = 'consent';
|
||||
super.authenticate(req, options);
|
||||
|
||||
@@ -2,12 +2,14 @@ import { Strategy } from 'passport-hubspot-oauth2';
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { OauthSecrets } from 'src/utils/OauthSecrets';
|
||||
import { OauthService } from '../oauth.service';
|
||||
|
||||
@Injectable()
|
||||
export class HubspotStrategy extends PassportStrategy(Strategy) {
|
||||
constructor(
|
||||
@Inject('OAUTH_SECRETS')
|
||||
private readonly oauthSecrets: OauthSecrets,
|
||||
private oauthService: OauthService,
|
||||
) {
|
||||
super(
|
||||
{
|
||||
@@ -25,8 +27,11 @@ export class HubspotStrategy extends PassportStrategy(Strategy) {
|
||||
}
|
||||
|
||||
authenticate(req, options) {
|
||||
const { customer_id } = req.query;
|
||||
options.state = customer_id;
|
||||
options.state = this.oauthService.generateStateFromRequest(
|
||||
options.state,
|
||||
req,
|
||||
'application',
|
||||
);
|
||||
super.authenticate(req, options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,14 @@ import { Strategy } from 'passport-mailchimp';
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
import { Inject, Injectable, Req } from '@nestjs/common';
|
||||
import { OauthSecrets } from 'src/utils/OauthSecrets';
|
||||
import { OauthService } from '../oauth.service';
|
||||
|
||||
@Injectable()
|
||||
export class MailChimpStrategy extends PassportStrategy(Strategy, 'mailchimp') {
|
||||
constructor(
|
||||
@Inject('OAUTH_SECRETS')
|
||||
private readonly oauthSecrets: OauthSecrets,
|
||||
private oauthService: OauthService,
|
||||
) {
|
||||
const options = {
|
||||
clientID: oauthSecrets.mailchimp.client_id,
|
||||
@@ -28,8 +30,12 @@ export class MailChimpStrategy extends PassportStrategy(Strategy, 'mailchimp') {
|
||||
}
|
||||
|
||||
authenticate(@Req() req, options) {
|
||||
const { customer_id } = req.query;
|
||||
options.state = customer_id;
|
||||
if (!req.route.path.includes('callback'))
|
||||
options.state = this.oauthService.generateStateFromRequest(
|
||||
options.state,
|
||||
req,
|
||||
'application',
|
||||
);
|
||||
super.authenticate(req, options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Strategy } from 'passport-forcedotcom';
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { OauthSecrets } from 'src/utils/OauthSecrets';
|
||||
import { OauthService } from '../oauth.service';
|
||||
|
||||
@Injectable()
|
||||
export class SalesforceStrategy extends PassportStrategy(
|
||||
@@ -11,6 +12,7 @@ export class SalesforceStrategy extends PassportStrategy(
|
||||
constructor(
|
||||
@Inject('OAUTH_SECRETS')
|
||||
private readonly oauthSecrets: OauthSecrets,
|
||||
private oauthService: OauthService,
|
||||
) {
|
||||
const options = {
|
||||
clientID: oauthSecrets.salesforce.client_id,
|
||||
@@ -40,8 +42,11 @@ export class SalesforceStrategy extends PassportStrategy(
|
||||
}
|
||||
|
||||
authenticate(req, options) {
|
||||
const { customer_id } = req.query;
|
||||
options.state = customer_id;
|
||||
options.state = this.oauthService.generateStateFromRequest(
|
||||
options.state,
|
||||
req,
|
||||
'application',
|
||||
);
|
||||
super.authenticate(req, options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Inject,
|
||||
Param,
|
||||
Post,
|
||||
Put,
|
||||
} from '@nestjs/common';
|
||||
import { Payload } from '@nestjs/microservices';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { OutputsClientService } from 'src/clients/outputs/client.service';
|
||||
import { AuthenticateCondition } from 'src/authentication/authentication.decorator';
|
||||
import { Permissions } from '../../authentication/permissions.enum';
|
||||
import { OutputsService } from './outputs.service';
|
||||
import { DadosferaLogger } from 'dadosfera-logs';
|
||||
|
||||
@ApiTags('Outputs')
|
||||
@Controller('outputs')
|
||||
@AuthenticateCondition((req, user) => {
|
||||
let action;
|
||||
|
||||
switch (req.method) {
|
||||
case 'POST':
|
||||
action = 'CREATE';
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
action = 'UPDATE';
|
||||
break;
|
||||
|
||||
default:
|
||||
action = req.method;
|
||||
}
|
||||
|
||||
return user.permissions.includes(Permissions.OUTPUT[action].seqid);
|
||||
})
|
||||
export class OutputsController {
|
||||
logger: any;
|
||||
constructor(
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
private outputsClientService: OutputsClientService,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
|
||||
@Post()
|
||||
async create(@Body() createOutputDto) {
|
||||
this.logger.info(process.env.DEV_URL + `/output - ON CREATE ROUTE`, {
|
||||
user: createOutputDto.info.user_id,
|
||||
customer: createOutputDto.info.customer,
|
||||
});
|
||||
|
||||
const outputService = new OutputsService(this.outputsClientService);
|
||||
const response = await outputService.create(createOutputDto);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Get()
|
||||
async findAll(@Body() data) {
|
||||
this.logger.info(process.env.DEV_URL + `/output - ON Find All ROUTE`, {
|
||||
user: data.info.user_id,
|
||||
customer: data.info.customer,
|
||||
});
|
||||
|
||||
const outputService = new OutputsService(this.outputsClientService);
|
||||
const response = await outputService.findAll(data);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Get('/:id')
|
||||
async findOne(@Body() data, @Param() params) {
|
||||
const { id } = params;
|
||||
this.logger.info(
|
||||
process.env.DEV_URL + `/output/${id} - ON Find One ROUTE`,
|
||||
{
|
||||
user: data.info.user_id,
|
||||
customer: data.info.customer,
|
||||
},
|
||||
);
|
||||
|
||||
const outputService = new OutputsService(this.outputsClientService);
|
||||
const response = await outputService.findOne({ id, ...data });
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Put(':id')
|
||||
async update(@Payload() updateOutputDto, @Param() params) {
|
||||
const { id } = params;
|
||||
const { info } = updateOutputDto;
|
||||
this.logger.info(process.env.DEV_URL + `/output/${id} - ON UPDATE ROUTE`, {
|
||||
user: updateOutputDto.info.user_id,
|
||||
customer: updateOutputDto.info.customer,
|
||||
});
|
||||
delete updateOutputDto.info;
|
||||
|
||||
const outputService = new OutputsService(this.outputsClientService);
|
||||
const response = await outputService.update(id, updateOutputDto, info);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
async delete(@Body() data, @Param() params) {
|
||||
const { id } = params;
|
||||
this.logger.info(process.env.DEV_URL + `/output/${id} - ON DELETE ROUTE`, {
|
||||
user: data.info.user_id,
|
||||
customer: data.info.customer,
|
||||
});
|
||||
|
||||
const outputService = new OutputsService(this.outputsClientService);
|
||||
const response = await outputService.remove({ id, ...data });
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||
import { IIdRequest, Info } from 'src/clients/outputs/interfaces';
|
||||
import { OutputsClientService } from 'src/clients/outputs/client.service';
|
||||
|
||||
@Injectable()
|
||||
export class OutputsService {
|
||||
constructor(private outputClient: OutputsClientService) {}
|
||||
|
||||
async create(createOutputDto) {
|
||||
try {
|
||||
const createOutputResponse = await this.outputClient.create(
|
||||
createOutputDto,
|
||||
);
|
||||
|
||||
return createOutputResponse;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
async findOne(data: IIdRequest) {
|
||||
try {
|
||||
const findOneOutputResponse = await this.outputClient.findOne(data);
|
||||
return findOneOutputResponse;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
async findAll(data) {
|
||||
try {
|
||||
const findAllOutputResponse = await this.outputClient.findAll(data);
|
||||
|
||||
return findAllOutputResponse;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
async update(id: string, data, info: Info) {
|
||||
try {
|
||||
const updateOutputResponse = await this.outputClient.update({
|
||||
id,
|
||||
info,
|
||||
...data,
|
||||
});
|
||||
|
||||
return updateOutputResponse;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
async remove(data: IIdRequest) {
|
||||
try {
|
||||
const removeOutputResponse = await this.outputClient.remove(data);
|
||||
|
||||
return removeOutputResponse;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
export class PermissionGroupPermission {
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
@ApiProperty()
|
||||
id: number;
|
||||
}
|
||||
|
||||
export class PermissionGroup {
|
||||
@ApiProperty()
|
||||
title: string;
|
||||
@ApiProperty({ type: [PermissionGroupPermission] })
|
||||
permissions: PermissionGroupPermission[];
|
||||
}
|
||||
|
||||
export class Permission {
|
||||
@ApiProperty()
|
||||
id: string;
|
||||
@ApiProperty()
|
||||
seqid: number;
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
@ApiProperty()
|
||||
claim: string;
|
||||
@ApiProperty()
|
||||
createdAt: string;
|
||||
@ApiProperty()
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export class PermissionDto {
|
||||
@ApiProperty()
|
||||
id: number;
|
||||
@ApiProperty()
|
||||
seqid: number;
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
@ApiProperty()
|
||||
claim: string;
|
||||
@ApiProperty()
|
||||
createdAt: string;
|
||||
@ApiProperty()
|
||||
updatedAt: string;
|
||||
}
|
||||
export class GetPublicPermissionsRes {
|
||||
@ApiProperty({ type: [PermissionGroup] })
|
||||
permissionGroups: PermissionGroup[];
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { ClientsModule } from '@nestjs/microservices';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
// import { DucClient } from 'src/clients/duc/client.config';
|
||||
import { PermissionsController } from './permissions.controller';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import { PermissionsService } from './permissions.service';
|
||||
|
||||
// const client = new DucClient();
|
||||
const logger = {
|
||||
info: (...args) => args,
|
||||
error: (...args) => args,
|
||||
};
|
||||
describe.skip('PermissionsController', () => {
|
||||
let controller: PermissionsController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
// imports: [ClientsModule.register([client.providerOptions])],
|
||||
controllers: [PermissionsController],
|
||||
providers: [
|
||||
{
|
||||
provide: DadosferaLogger,
|
||||
useValue: { logger },
|
||||
},
|
||||
PermissionsService,
|
||||
],
|
||||
}).compile();
|
||||
|
||||
controller = module.get<PermissionsController>(PermissionsController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,51 @@
|
||||
import { Controller, Get, Headers, Inject } from '@nestjs/common';
|
||||
import { ApiHeader, ApiOkResponse, ApiTags } from '@nestjs/swagger';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import {
|
||||
Authenticated,
|
||||
RequireAllPermissions,
|
||||
} from 'src/authentication/authentication.decorator';
|
||||
import {
|
||||
PERMISSIONS_GROUPS,
|
||||
PermissionUsages,
|
||||
} from 'src/authentication/permissions.enum';
|
||||
import { RequestUser, User } from 'src/authentication/user.decorator';
|
||||
import { LanguageEnum } from 'src/utils/languages.enum';
|
||||
import { GetPublicPermissionsRes } from './dto/entities';
|
||||
import { PermissionsService } from './permissions.service';
|
||||
|
||||
@ApiTags('Permissions')
|
||||
@Authenticated()
|
||||
@Controller('permissions')
|
||||
@ApiHeader({
|
||||
name: 'dadosfera-lang',
|
||||
enum: LanguageEnum,
|
||||
required: false,
|
||||
description: 'Defaults to pt-br',
|
||||
})
|
||||
export class PermissionsController {
|
||||
logger: DadosferaLogger;
|
||||
|
||||
constructor(
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
private permissionsService: PermissionsService,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
|
||||
@Get()
|
||||
@ApiOkResponse({ type: GetPublicPermissionsRes })
|
||||
getPublicPermissions(
|
||||
@User() user: RequestUser,
|
||||
@Headers('dadosfera-lang') language,
|
||||
) {
|
||||
this.logger.info('getPublicPermissions', { user });
|
||||
if (!language) language = 'en-us';
|
||||
const permissionGroups = this.permissionsService.getPermissionsGrouped(
|
||||
PermissionUsages.PUBLIC,
|
||||
language,
|
||||
);
|
||||
return { permissionGroups };
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,18 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ClientsModule } from '@nestjs/microservices';
|
||||
import { DadosferaLogger } from 'dadosfera-logs';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
|
||||
import { PermissionsClientService } from './permissions.service';
|
||||
import { PermissionsService } from './permissions.service';
|
||||
|
||||
import { DucClient } from '../../clients/duc/client.config';
|
||||
const ducClient = new DucClient();
|
||||
import { DucClient } from '../duc/client.config';
|
||||
import { PermissionsController } from './permissions.controller';
|
||||
|
||||
const client = new DucClient();
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ClientsModule.register([
|
||||
{
|
||||
name: 'DUC_PACKAGE',
|
||||
...ducClient.config(),
|
||||
},
|
||||
]),
|
||||
],
|
||||
providers: [PermissionsClientService, DadosferaLogger],
|
||||
imports: [ClientsModule.register([client.providerOptions])],
|
||||
providers: [PermissionsService, DadosferaLogger],
|
||||
controllers: [PermissionsController],
|
||||
exports: [PermissionsService],
|
||||
})
|
||||
export class PermissionsModule {}
|
||||
|
||||
@@ -7,30 +7,38 @@ import {
|
||||
import { ClientGrpc } from '@nestjs/microservices';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
|
||||
import { ProtoServices } from 'protospack-v2/dist/lib/Duc';
|
||||
import { PermissionsProtoService as PermissionsServiceInterface } from 'protospack-v2/dist/lib/Duc/interfaces/write-service';
|
||||
import { InjectPermissionsRequest } from 'protospack-v2/dist/lib/Duc/interfaces/messages';
|
||||
import { DadosferaLogger } from 'dadosfera-logs';
|
||||
import { Permissions } from '../../authentication/permissions.enum';
|
||||
import { ProtoServices } from '@dadosfera/protospack-v2/dist/lib/Duc';
|
||||
import { PermissionsProtoService as PermissionsServiceInterface } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/write-service';
|
||||
import { InjectPermissionsRequest } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/messages';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import {
|
||||
PERMISSIONS_GROUPS,
|
||||
PermissionUsages,
|
||||
PermissionsObjectGroup,
|
||||
PermissionsObjectPermissionTranslated,
|
||||
} from '../../authentication/permissions.enum';
|
||||
import ErrorBuilder from '../../utils/ErrorBuilder';
|
||||
import { PermissionGroupPermission, PermissionGroup } from './dto/entities';
|
||||
import { LanguageEnum } from 'src/utils/languages.enum';
|
||||
import { DucClient } from '../duc/client.config';
|
||||
|
||||
@Injectable()
|
||||
export class PermissionsClientService
|
||||
export class PermissionsService
|
||||
implements OnModuleInit, OnApplicationBootstrap
|
||||
{
|
||||
logger: any;
|
||||
logger: DadosferaLogger;
|
||||
|
||||
private permissionsService: PermissionsServiceInterface;
|
||||
private permissionsClientService: PermissionsServiceInterface;
|
||||
constructor(
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
@Inject('DUC_PACKAGE') private readonly grpcClient: ClientGrpc,
|
||||
@Inject(DucClient.name) private readonly grpcClient: ClientGrpc,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
|
||||
onModuleInit() {
|
||||
this.permissionsService =
|
||||
this.permissionsClientService =
|
||||
this.grpcClient.getService<PermissionsServiceInterface>(
|
||||
ProtoServices.PermissionsProtoService,
|
||||
);
|
||||
@@ -40,8 +48,8 @@ export class PermissionsClientService
|
||||
async onApplicationBootstrap() {
|
||||
this.logger.info('sending permissions to DUC...');
|
||||
|
||||
const permissions = Object.values(Permissions).flatMap((namespace) =>
|
||||
Object.values(namespace),
|
||||
const permissions = Object.values(PERMISSIONS_GROUPS).flatMap((namespace) =>
|
||||
Object.values(namespace.permissions),
|
||||
);
|
||||
|
||||
return this.injectPermissions({
|
||||
@@ -49,7 +57,7 @@ export class PermissionsClientService
|
||||
}).catch((err: ErrorBuilder) => {
|
||||
if (
|
||||
err.code === 'No connection established' &&
|
||||
process.env.LOCAL_ENV === 'true'
|
||||
(process.env.LOCAL_ENV === 'true' || process.env.ENV === 'local')
|
||||
) {
|
||||
return this.logger.info(
|
||||
"couldn't connect to DUC. suppresing in local env",
|
||||
@@ -64,7 +72,48 @@ export class PermissionsClientService
|
||||
this.logger.info('InjectPermissions');
|
||||
|
||||
return lastValueFrom(
|
||||
this.permissionsService.InjectPermissions({ permissions }),
|
||||
this.permissionsClientService.InjectPermissions({ permissions }),
|
||||
);
|
||||
}
|
||||
getPermissionsGrouped(
|
||||
permissionUsage?: PermissionUsages,
|
||||
language: LanguageEnum = LanguageEnum.ptbr,
|
||||
): PermissionGroup[] {
|
||||
const groups: PermissionGroup[] = [];
|
||||
for (const key in PERMISSIONS_GROUPS) {
|
||||
const permissionGroup: PermissionsObjectGroup = PERMISSIONS_GROUPS[key];
|
||||
const title = permissionGroup.title[language];
|
||||
const permissions: PermissionGroupPermission[] = Object.values(
|
||||
permissionGroup.permissions,
|
||||
)
|
||||
.filter(({ usage }) =>
|
||||
permissionUsage ? usage === permissionUsage : true,
|
||||
)
|
||||
.map(({ seqid, name }) => ({ id: seqid, name: name[language] }));
|
||||
if (permissions?.length)
|
||||
groups.push({
|
||||
title,
|
||||
permissions,
|
||||
});
|
||||
}
|
||||
return groups;
|
||||
}
|
||||
getAllPermissions(language: LanguageEnum = LanguageEnum.ptbr) {
|
||||
let permissions: PermissionsObjectPermissionTranslated[] = [];
|
||||
for (const key in PERMISSIONS_GROUPS) {
|
||||
const permissionGroup: PermissionsObjectGroup = PERMISSIONS_GROUPS[key];
|
||||
const permissionGroupPermissions: PermissionsObjectPermissionTranslated[] =
|
||||
Object.values(permissionGroup.permissions).map((p) => ({
|
||||
...p,
|
||||
name: p.name[language],
|
||||
}));
|
||||
permissions = permissions.concat(permissionGroupPermissions);
|
||||
}
|
||||
return permissions;
|
||||
}
|
||||
getPermissionsBySeqId(seqIds: number[]) {
|
||||
const permissionGroupPermissions = this.getAllPermissions();
|
||||
|
||||
return permissionGroupPermissions.filter((p) => seqIds.includes(p.seqid));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
import {
|
||||
BadRequestException,
|
||||
ConflictException,
|
||||
Inject,
|
||||
InternalServerErrorException,
|
||||
OnModuleInit,
|
||||
} from '@nestjs/common';
|
||||
import { ClientGrpc, Payload } from '@nestjs/microservices';
|
||||
import { PipelineServicesNames, PipelinesServiceInterface } from 'protospack';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import { objectSnakeToCamel } from 'src/utils/CaseConverter';
|
||||
|
||||
import {
|
||||
ICreatePipelineDto,
|
||||
IGetPipelineLogsRequest,
|
||||
IIdRequest,
|
||||
IUpdatePipelineRequest,
|
||||
} from './interfaces';
|
||||
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import { PipelinesClientConfiguration } from './pipelines-client';
|
||||
|
||||
export class PipelinesClientService implements OnModuleInit {
|
||||
private pipelineService: PipelinesServiceInterface;
|
||||
logger: DadosferaLogger;
|
||||
constructor(
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
@Inject(PipelinesClientConfiguration.name)
|
||||
private readonly grpcClient: ClientGrpc,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
|
||||
onModuleInit() {
|
||||
this.pipelineService =
|
||||
this.grpcClient.getService<PipelinesServiceInterface>(
|
||||
PipelineServicesNames.PipelineService,
|
||||
);
|
||||
}
|
||||
|
||||
async create(@Payload() createPipelineDto: ICreatePipelineDto) {
|
||||
this.logger.info('PipelinesClientService - Create');
|
||||
const createPipelineResponse = await lastValueFrom(
|
||||
this.pipelineService.Create(objectSnakeToCamel(createPipelineDto)),
|
||||
).catch((error: { details: string }) => {
|
||||
if (error.details.includes('INVALID_REQUEST')) {
|
||||
const [, message] = error.details.split('|');
|
||||
throw new BadRequestException(message);
|
||||
}
|
||||
throw new InternalServerErrorException(error.details);
|
||||
});
|
||||
this.logger.info('Done');
|
||||
|
||||
return createPipelineResponse;
|
||||
}
|
||||
|
||||
async findAll(data) {
|
||||
this.logger.info('PipelinesClientService - FindAll');
|
||||
const findAllPipelineResponse = await lastValueFrom(
|
||||
this.pipelineService.FindAll(data),
|
||||
).catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
this.logger.info('Done');
|
||||
|
||||
return findAllPipelineResponse;
|
||||
}
|
||||
|
||||
async findOne(data: IIdRequest) {
|
||||
this.logger.info('PipelinesClientService - FindOne');
|
||||
|
||||
const findOnePipelineResponse = await lastValueFrom(
|
||||
this.pipelineService.FindOne(data),
|
||||
).catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
this.logger.info('Done');
|
||||
|
||||
return findOnePipelineResponse;
|
||||
}
|
||||
|
||||
async update(UpdatePipelineRequest: IUpdatePipelineRequest) {
|
||||
this.logger.info('PipelinesClientService - Update');
|
||||
|
||||
const updatePipelineResponse = await lastValueFrom(
|
||||
this.pipelineService.Update(UpdatePipelineRequest),
|
||||
).catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
this.logger.info('Done');
|
||||
|
||||
return updatePipelineResponse;
|
||||
}
|
||||
|
||||
async remove(data: IIdRequest) {
|
||||
this.logger.info('PipelinesClientService - Remove');
|
||||
|
||||
const removePipelineResponse = await lastValueFrom(
|
||||
this.pipelineService.remove(data),
|
||||
).catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
this.logger.info('Done');
|
||||
|
||||
return removePipelineResponse;
|
||||
}
|
||||
|
||||
async getPipelineLogsMessages(data: IGetPipelineLogsRequest) {
|
||||
this.logger.info('PipelinesClientService - GetPipelineLogsMessages');
|
||||
|
||||
const logsPipelineResponse = await lastValueFrom(
|
||||
this.pipelineService.getPipelineLogs(data),
|
||||
).catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
this.logger.info('Done');
|
||||
|
||||
return logsPipelineResponse;
|
||||
}
|
||||
|
||||
async getPipelineStatus(data) {
|
||||
this.logger.info('PipelinesClientService - GetPipelineStatus');
|
||||
|
||||
const statusPipelineResponse = await lastValueFrom(
|
||||
this.pipelineService.getPipelineStatus(data),
|
||||
)
|
||||
.then((res) => {
|
||||
const statusArray =
|
||||
res.status?.sort((a, b) => {
|
||||
if (a.id < b.id) {
|
||||
return 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}) || [];
|
||||
return { status: statusArray };
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
this.logger.info('Done');
|
||||
|
||||
return statusPipelineResponse;
|
||||
}
|
||||
|
||||
async runPipeline({ id, info }: IIdRequest) {
|
||||
this.logger.info('PipelinesClientService - RunPipeline');
|
||||
const statusPipelineResponse = await lastValueFrom(
|
||||
this.pipelineService.triggerPipeline({ id, info }),
|
||||
).catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
if (statusPipelineResponse.status == false) {
|
||||
throw new ConflictException(
|
||||
'This pipeline is not ready yet to execute, Try again later!',
|
||||
);
|
||||
}
|
||||
|
||||
this.logger.info('Done');
|
||||
return statusPipelineResponse;
|
||||
}
|
||||
}
|
||||
+2
-5
@@ -1,3 +1,5 @@
|
||||
import { Info } from 'protospack/dist/lib/interfaces';
|
||||
|
||||
export interface ICreatePipelineDto {
|
||||
input: IdRequest;
|
||||
transformations: IdRequest[];
|
||||
@@ -8,11 +10,6 @@ export interface ICreatePipelineDto {
|
||||
info: Info;
|
||||
}
|
||||
|
||||
export interface Info {
|
||||
customer_id: sting;
|
||||
user_id: string;
|
||||
}
|
||||
|
||||
export interface IdRequest {
|
||||
id: string;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import {
|
||||
ClientsProviderAsyncOptions,
|
||||
GrpcOptions,
|
||||
Transport,
|
||||
} from '@nestjs/microservices';
|
||||
import { PipelinePackages, PipelineProtoFilePath } from 'protospack';
|
||||
import { credentials } from '@grpc/grpc-js';
|
||||
|
||||
export class PipelinesClientConfiguration {
|
||||
public name = 'PipelinesClientConfiguration';
|
||||
private config: GrpcOptions = {
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
url: process.env.PIFACTORY_URL,
|
||||
package: PipelinePackages,
|
||||
credentials:
|
||||
process.env.LOCAL_ENV || process.env.ENV === 'local'
|
||||
? undefined
|
||||
: credentials.createSsl(),
|
||||
protoPath: PipelineProtoFilePath,
|
||||
loader: {
|
||||
keepCase: true,
|
||||
enums: String,
|
||||
defaults: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
providerOptions: ClientsProviderAsyncOptions = {
|
||||
name: this.name,
|
||||
...this.config,
|
||||
};
|
||||
}
|
||||
@@ -9,14 +9,18 @@ import {
|
||||
Put,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { PipelinesClientService } from 'src/clients/pipelines/client.service';
|
||||
import { AuthenticateCondition } from 'src/authentication/authentication.decorator';
|
||||
import { Permissions } from '../../authentication/permissions.enum';
|
||||
import {
|
||||
AuthenticateCondition,
|
||||
Authenticated,
|
||||
} from 'src/authentication/authentication.decorator';
|
||||
import { PERMISSIONS_GROUPS } from '../../authentication/permissions.enum';
|
||||
import { PipelinesService } from './pipelines.service';
|
||||
import { DadosferaLogger } from 'dadosfera-logs';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import { RequestUser, User } from 'src/authentication/user.decorator';
|
||||
|
||||
@ApiTags('Pipelines')
|
||||
@Controller('pipelines')
|
||||
@Authenticated()
|
||||
@AuthenticateCondition((req, user) => {
|
||||
let action;
|
||||
|
||||
@@ -33,14 +37,16 @@ import { DadosferaLogger } from 'dadosfera-logs';
|
||||
action = req.method;
|
||||
}
|
||||
|
||||
return user.permissions.includes(Permissions.PIPELINE[action].seqid);
|
||||
return user.permissions.includes(
|
||||
PERMISSIONS_GROUPS.PIPELINE.permissions[action].seqid,
|
||||
);
|
||||
})
|
||||
export class PipelinesController {
|
||||
logger: any;
|
||||
logger: DadosferaLogger;
|
||||
constructor(
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
private pipelinesClientService: PipelinesClientService,
|
||||
private pipelineService: PipelinesService,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
@@ -58,8 +64,7 @@ export class PipelinesController {
|
||||
},
|
||||
);
|
||||
|
||||
const pipelineService = new PipelinesService(this.pipelinesClientService);
|
||||
const response = await pipelineService.runPipeline({ id, info });
|
||||
const response = await this.pipelineService.runPipeline({ id, info });
|
||||
|
||||
return response;
|
||||
}
|
||||
@@ -77,8 +82,7 @@ export class PipelinesController {
|
||||
},
|
||||
);
|
||||
|
||||
const pipelineService = new PipelinesService(this.pipelinesClientService);
|
||||
const response = await pipelineService.getPipelineStatus(body);
|
||||
const response = await this.pipelineService.getPipelineStatus(body);
|
||||
|
||||
return response;
|
||||
}
|
||||
@@ -91,8 +95,10 @@ export class PipelinesController {
|
||||
{},
|
||||
);
|
||||
|
||||
const pipelineService = new PipelinesService(this.pipelinesClientService);
|
||||
const response = await pipelineService.getPipelineLogsMessages(id, details);
|
||||
const response = await this.pipelineService.getPipelineLogsMessages(
|
||||
id,
|
||||
details,
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
@@ -101,21 +107,25 @@ export class PipelinesController {
|
||||
async create(@Body() createPipelineDto) {
|
||||
this.logger.info(process.env.DEV_URL + `/pipelines ON CREATE ROUTE`);
|
||||
|
||||
const pipelineService = new PipelinesService(this.pipelinesClientService);
|
||||
const response = await pipelineService.create(createPipelineDto);
|
||||
const response = await this.pipelineService.create(createPipelineDto);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Get()
|
||||
async findAll(@Body() data) {
|
||||
async findAll(@User() user: RequestUser) {
|
||||
this.logger.info(process.env.DEV_URL + `/pipeline ON Find All ROUTE`, {
|
||||
user: data.info.user_id,
|
||||
customer: data.info.customer,
|
||||
user: user.user_id,
|
||||
customer: user.customer_id,
|
||||
});
|
||||
|
||||
const pipelineService = new PipelinesService(this.pipelinesClientService);
|
||||
const response = await pipelineService.findAll(data);
|
||||
const { customer_id, user_id, customer_name } = user;
|
||||
|
||||
const response = await this.pipelineService.findAll({
|
||||
customer_name,
|
||||
customer_id,
|
||||
user_id,
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
@@ -125,8 +135,7 @@ export class PipelinesController {
|
||||
const { id } = params;
|
||||
this.logger.info(process.env.DEV_URL + `/pipeline/${id} ON Find One ROUTE`);
|
||||
|
||||
const pipelineService = new PipelinesService(this.pipelinesClientService);
|
||||
const response = await pipelineService.findOne({ id, ...data });
|
||||
const response = await this.pipelineService.findOne({ id, ...data });
|
||||
|
||||
return response;
|
||||
}
|
||||
@@ -139,8 +148,11 @@ export class PipelinesController {
|
||||
|
||||
this.logger.info(process.env.DEV_URL + `/pipeline/${id} ON UPDATE ROUTE`);
|
||||
|
||||
const pipelineService = new PipelinesService(this.pipelinesClientService);
|
||||
const response = await pipelineService.update(id, updatePipelineDto, info);
|
||||
const response = await this.pipelineService.update(
|
||||
id,
|
||||
updatePipelineDto,
|
||||
info,
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
@@ -150,8 +162,7 @@ export class PipelinesController {
|
||||
const { id } = params;
|
||||
this.logger.info(process.env.DEV_URL + `/pipeline/${id} ON DELETE ROUTE`);
|
||||
|
||||
const pipelineService = new PipelinesService(this.pipelinesClientService);
|
||||
const response = await pipelineService.remove({ id, ...data });
|
||||
const response = await this.pipelineService.remove({ id, ...data });
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ClientsModule } from '@nestjs/microservices';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
|
||||
import { PipelinesController } from './pipelines.controller';
|
||||
import { PipelinesService } from './pipelines.service';
|
||||
|
||||
import { PipelinesClientConfiguration } from './pipelines-client';
|
||||
import { PipelinesClientService } from './client.service';
|
||||
|
||||
const client = new PipelinesClientConfiguration();
|
||||
|
||||
@Module({
|
||||
imports: [ClientsModule.register([client.providerOptions])],
|
||||
controllers: [PipelinesController],
|
||||
providers: [PipelinesService, PipelinesClientService, DadosferaLogger],
|
||||
exports: [PipelinesService],
|
||||
})
|
||||
export class PipelinesModule {}
|
||||
@@ -1,7 +1,8 @@
|
||||
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||
import { DecodeGrpcStruct } from 'protospack';
|
||||
import { PipelinesClientService } from 'src/clients/pipelines/client.service';
|
||||
import { IIdRequest, Info } from 'src/clients/pipelines/interfaces';
|
||||
import { Info } from 'protospack/dist/lib/interfaces';
|
||||
import { PipelinesClientService } from './client.service';
|
||||
import { IIdRequest } from './interfaces';
|
||||
import { objectCamelToSnake } from 'src/utils/CaseConverter';
|
||||
|
||||
@Injectable()
|
||||
@@ -42,13 +43,14 @@ export class PipelinesService {
|
||||
|
||||
async findAll(data) {
|
||||
try {
|
||||
const findAllPipelineResponse = await this.pipelineClient.findAll(data);
|
||||
|
||||
const pipelines = objectCamelToSnake(findAllPipelineResponse);
|
||||
pipelines.forEach((pipeline) => {
|
||||
this.adjustPayload(pipeline);
|
||||
const { pipelines } = await this.pipelineClient.findAll({
|
||||
info: data,
|
||||
});
|
||||
return { pipelines };
|
||||
if (pipelines)
|
||||
pipelines.forEach((pipeline) => {
|
||||
this.adjustPayload(pipeline);
|
||||
});
|
||||
return { pipelines: pipelines || [] };
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
import { ApiProperty, ApiPropertyOptional, OmitType } from '@nestjs/swagger';
|
||||
import { Info } from 'protospack/dist/lib/interfaces';
|
||||
|
||||
export class IPipelineV2 {
|
||||
@ApiProperty()
|
||||
id: string;
|
||||
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
@ApiProperty()
|
||||
description: string;
|
||||
@ApiProperty()
|
||||
connection_id: string;
|
||||
@ApiProperty()
|
||||
cron: string;
|
||||
@ApiPropertyOptional()
|
||||
input_id?: string;
|
||||
@ApiPropertyOptional()
|
||||
transformations_ids?: string[];
|
||||
@ApiPropertyOptional()
|
||||
tags?: string[];
|
||||
@ApiPropertyOptional()
|
||||
properties?: any;
|
||||
|
||||
@ApiProperty()
|
||||
connector_name: string;
|
||||
@ApiProperty()
|
||||
connector_plugin: string;
|
||||
@ApiProperty()
|
||||
connector_version: string;
|
||||
@ApiProperty()
|
||||
image_url: string;
|
||||
|
||||
@ApiProperty()
|
||||
created_at: string;
|
||||
@ApiProperty()
|
||||
updated_at: string;
|
||||
}
|
||||
export class ICreatePipelineV2Req extends OmitType(IPipelineV2, [
|
||||
'id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
]) {}
|
||||
|
||||
export interface IdRequest {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface IIdRequest {
|
||||
id: string;
|
||||
info: Info;
|
||||
}
|
||||
|
||||
export interface IUpdatePipelineRequest {
|
||||
input: IdRequest;
|
||||
transformations: IdRequest[];
|
||||
output: IdRequest;
|
||||
tags: string[];
|
||||
name: string;
|
||||
description: string;
|
||||
id: string;
|
||||
info: Info;
|
||||
}
|
||||
|
||||
export interface IGetPipelineLogsRequest {
|
||||
id: string;
|
||||
details: string;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import {
|
||||
ClientsProviderAsyncOptions,
|
||||
GrpcOptions,
|
||||
Transport,
|
||||
} from '@nestjs/microservices';
|
||||
import {
|
||||
ProtoPackages,
|
||||
ProtoPaths,
|
||||
} from '@dadosfera/protospack-v2/dist/lib/PipelineV2';
|
||||
import { credentials } from '@grpc/grpc-js';
|
||||
|
||||
export class PipelinesClientConfiguration {
|
||||
public name = 'PipelinesClientConfiguration';
|
||||
private config: GrpcOptions = {
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
url: process.env.PIFACTORY_URL,
|
||||
package: [ProtoPackages.ReadPackage, ProtoPackages.WritePackage],
|
||||
credentials:
|
||||
process.env.LOCAL_ENV || process.env.ENV === 'local'
|
||||
? undefined
|
||||
: credentials.createSsl(),
|
||||
protoPath: [ProtoPaths.ReadFilePath, ProtoPaths.WriteFilePath],
|
||||
loader: {
|
||||
keepCase: true,
|
||||
enums: String,
|
||||
objects: true,
|
||||
arrays: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
providerOptions: ClientsProviderAsyncOptions = {
|
||||
name: this.name,
|
||||
...this.config,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Inject,
|
||||
Param,
|
||||
Post,
|
||||
Put,
|
||||
Headers,
|
||||
Query,
|
||||
} from '@nestjs/common';
|
||||
import { ApiCreatedResponse, ApiTags } from '@nestjs/swagger';
|
||||
import { AuthenticateCondition } from 'src/authentication/authentication.decorator';
|
||||
import { PERMISSIONS_GROUPS } from '../../authentication/permissions.enum';
|
||||
import { PipelinesService } from './pipelines.service';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import { Messages } from '@dadosfera/protospack-v2/dist/lib/PipelineV2';
|
||||
import { RequestUser, User } from 'src/authentication/user.decorator';
|
||||
import { PackTheMetadata } from 'src/utils/ PackTheMetadata';
|
||||
|
||||
import { PipelinesService as OldPipelineService } from 'src/modules/pipelines/pipelines.service';
|
||||
import { ICreatePipelineV2Req, IPipelineV2 } from './interfaces';
|
||||
@ApiTags('Pipelines')
|
||||
@Controller('pipelinesV2')
|
||||
@AuthenticateCondition((req, user) => {
|
||||
let action;
|
||||
|
||||
switch (req.method) {
|
||||
case 'POST':
|
||||
action = 'CREATE';
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
action = 'UPDATE';
|
||||
break;
|
||||
|
||||
default:
|
||||
action = req.method;
|
||||
}
|
||||
|
||||
return user.permissions.includes(
|
||||
PERMISSIONS_GROUPS.PIPELINE.permissions[action].seqid,
|
||||
);
|
||||
})
|
||||
export class PipelinesController {
|
||||
logger: DadosferaLogger;
|
||||
constructor(
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
private pipelinesClientService: PipelinesService,
|
||||
private oldPipelinesService: OldPipelineService,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
|
||||
@Post()
|
||||
@ApiCreatedResponse({ type: IPipelineV2 })
|
||||
async create(
|
||||
@Headers('Dadosfera-Lang') language,
|
||||
@User() user: RequestUser,
|
||||
@Body() createPipelineDto: ICreatePipelineV2Req,
|
||||
) {
|
||||
this.logger.info('PipelinesController - create', { user });
|
||||
if (!language) language = 'en-us';
|
||||
const { customer_id, customer_name, username, user_id } = user;
|
||||
const metadata = PackTheMetadata({
|
||||
customer_id,
|
||||
customer_name,
|
||||
username,
|
||||
user_id,
|
||||
language,
|
||||
});
|
||||
|
||||
const response = await this.pipelinesClientService.create(
|
||||
createPipelineDto,
|
||||
metadata,
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Get()
|
||||
async findAll(
|
||||
@User() user: RequestUser,
|
||||
@Headers('Dadosfera-Lang') language,
|
||||
@Query() data,
|
||||
) {
|
||||
this.logger.info('PipelinesController - findAll', { user });
|
||||
|
||||
if (!language) language = 'en-us';
|
||||
|
||||
const { customer_id, customer_name, user_id, username } = user;
|
||||
const metadata = PackTheMetadata({
|
||||
customer_id,
|
||||
customer_name,
|
||||
user_id,
|
||||
username,
|
||||
language,
|
||||
});
|
||||
|
||||
const response = await this.pipelinesClientService.findAll(data, metadata);
|
||||
|
||||
return {
|
||||
pipelines: [...response.pipelines],
|
||||
};
|
||||
}
|
||||
|
||||
@Get(':id/config')
|
||||
async getPipelineproperties(
|
||||
@Headers('Dadosfera-Lang') language,
|
||||
@User() user: RequestUser,
|
||||
@Param('id') id,
|
||||
) {
|
||||
this.logger.info('PipelinesController - getPipelineproperties', { user });
|
||||
const metadata = PackTheMetadata({
|
||||
...user,
|
||||
language: language || 'pt-br',
|
||||
});
|
||||
return this.pipelinesClientService.findOneProperties(id, metadata);
|
||||
}
|
||||
|
||||
@Get('/:id')
|
||||
async findOne(
|
||||
@Headers('Dadosfera-Lang') language,
|
||||
@User() user: RequestUser,
|
||||
@Param('id') id,
|
||||
): Promise<Messages.PipelineV2FindOneResponse> {
|
||||
this.logger.info('PipelinesController - findOne', { user });
|
||||
|
||||
if (!language) language = 'en-us';
|
||||
|
||||
const { customer_id, customer_name, user_id, username } = user;
|
||||
|
||||
const metadata = PackTheMetadata({
|
||||
customer_id,
|
||||
customer_name,
|
||||
user_id,
|
||||
username,
|
||||
language,
|
||||
});
|
||||
|
||||
const result = await this.pipelinesClientService
|
||||
.findOne({ id }, metadata)
|
||||
.then((res) => {
|
||||
Object.assign(res.pipeline, {
|
||||
transformations: res.pipeline.transformations
|
||||
? JSON.parse(res.pipeline.transformations)
|
||||
: [],
|
||||
config: {
|
||||
cron: res.pipeline.config.cron,
|
||||
tables: JSON.parse(res.pipeline.config.tables),
|
||||
},
|
||||
properties: res.pipeline.properties
|
||||
? JSON.parse(res.pipeline.properties)
|
||||
: {},
|
||||
});
|
||||
return res;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
@Put('/:id')
|
||||
async update(
|
||||
@Body() updatePipelineDto,
|
||||
@Param('id') id,
|
||||
@User() user: RequestUser,
|
||||
) {
|
||||
this.logger.info('PipelinesController - findOne', { user });
|
||||
const { info } = updatePipelineDto;
|
||||
delete updatePipelineDto.info;
|
||||
|
||||
const response = await this.pipelinesClientService.update({
|
||||
...updatePipelineDto,
|
||||
info,
|
||||
id,
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
async delete(@Body() data, @Param() params, @User() user: RequestUser) {
|
||||
const { id } = params;
|
||||
this.logger.info('PipelinesController - findOne', { user });
|
||||
|
||||
const response = await this.pipelinesClientService.remove({ id, ...data });
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ClientsModule } from '@nestjs/microservices';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
|
||||
import { PipelinesController } from './pipelines.controller';
|
||||
import { PipelinesService } from './pipelines.service';
|
||||
|
||||
import { PipelinesClientConfiguration } from './pipelines-client';
|
||||
|
||||
import { PipelinesModule as OldPipelineModule } from 'src/modules/pipelines/pipelines.module';
|
||||
import { ConnectorModule } from '../connector/connector.module';
|
||||
|
||||
const client = new PipelinesClientConfiguration();
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ClientsModule.register([client.providerOptions]),
|
||||
OldPipelineModule,
|
||||
ConnectorModule,
|
||||
],
|
||||
controllers: [PipelinesController],
|
||||
providers: [PipelinesService, DadosferaLogger],
|
||||
exports: [PipelinesService],
|
||||
})
|
||||
export class PipelinesV2Module {}
|
||||
@@ -0,0 +1,211 @@
|
||||
import {
|
||||
BadRequestException,
|
||||
Inject,
|
||||
InternalServerErrorException,
|
||||
OnModuleInit,
|
||||
} from '@nestjs/common';
|
||||
import { ClientGrpc } from '@nestjs/microservices';
|
||||
import {
|
||||
Messages,
|
||||
WriteService,
|
||||
ReadService,
|
||||
ProtoServices,
|
||||
} from '@dadosfera/protospack-v2/dist/lib/PipelineV2';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import { PipelinesClientConfiguration } from './pipelines-client';
|
||||
import { ICreatePipelineV2Req } from './interfaces';
|
||||
import { PipelineV2CreateRequest } from '@dadosfera/protospack-v2/dist/lib/PipelineV2/interfaces/messages';
|
||||
import { Metadata } from '@grpc/grpc-js';
|
||||
import { ConnectorClientService } from '../connector/client.service';
|
||||
|
||||
export class PipelinesService implements OnModuleInit {
|
||||
logger: DadosferaLogger;
|
||||
pipelineWriteService: WriteService.PipelineV2WriteService;
|
||||
pipelineReadService: ReadService.PipelineV2ReadService;
|
||||
constructor(
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
@Inject(PipelinesClientConfiguration.name)
|
||||
private readonly grpcClient: ClientGrpc,
|
||||
private readonly connectorService: ConnectorClientService,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
|
||||
onModuleInit() {
|
||||
this.pipelineReadService =
|
||||
this.grpcClient.getService<ReadService.PipelineV2ReadService>(
|
||||
ProtoServices.PipelineV2ReadService,
|
||||
);
|
||||
|
||||
this.pipelineWriteService =
|
||||
this.grpcClient.getService<WriteService.PipelineV2WriteService>(
|
||||
ProtoServices.PipelineV2WriteService,
|
||||
);
|
||||
}
|
||||
|
||||
adjustInputPayload(payload) {
|
||||
const { input } = payload;
|
||||
if (input) {
|
||||
if (input.input_generic) {
|
||||
const { credentials } = input.input_generic;
|
||||
return {
|
||||
...input.input_generic,
|
||||
credentials: credentials && JSON.parse(credentials),
|
||||
};
|
||||
}
|
||||
if (input.input_s3) return input.input_s3;
|
||||
if (input.input_jdbc) return input.input_jdbc;
|
||||
|
||||
const { credentials } = input;
|
||||
return {
|
||||
...input,
|
||||
credentials: credentials && JSON.parse(credentials),
|
||||
};
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
async create(
|
||||
body: ICreatePipelineV2Req,
|
||||
metadata,
|
||||
): Promise<Messages.PipelineV2CreateResponse> {
|
||||
this.logger.info('PipelinesV2ClientService - Create');
|
||||
|
||||
const pipelineV2CreateRequest: PipelineV2CreateRequest = {
|
||||
...body,
|
||||
input_id: body.input_id,
|
||||
transformations_ids: body.transformations_ids,
|
||||
tags: body.tags,
|
||||
properties: body.properties && JSON.stringify(body.properties),
|
||||
};
|
||||
|
||||
const createPipelineResponse = await lastValueFrom(
|
||||
this.pipelineWriteService.PipelineV2Create(
|
||||
pipelineV2CreateRequest,
|
||||
metadata,
|
||||
),
|
||||
).catch((error: { details: string }) => {
|
||||
if (error.details.includes('INVALID_REQUEST')) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [errorType, message] = error.details.split('|');
|
||||
throw new BadRequestException(message);
|
||||
}
|
||||
throw new InternalServerErrorException(error.details);
|
||||
});
|
||||
this.logger.info('Done');
|
||||
|
||||
return createPipelineResponse;
|
||||
}
|
||||
|
||||
async findAll(
|
||||
data: Messages.PipelineV2FindAllRequest,
|
||||
metadata,
|
||||
): Promise<Messages.PipelineV2FindAllResponse> {
|
||||
this.logger.info('PipelinesClientService - FindAll');
|
||||
const findAllPipelineResponse = await lastValueFrom(
|
||||
this.pipelineReadService.PipelineV2FindAll(data, metadata),
|
||||
)
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return findAllPipelineResponse;
|
||||
}
|
||||
|
||||
async findOne(
|
||||
data: Messages.PipelineV2FindOneRequest,
|
||||
metadata,
|
||||
): Promise<Messages.PipelineV2FindOneResponse> {
|
||||
this.logger.info('PipelinesClientService - FindOne');
|
||||
|
||||
const findOnePipelineResponse = await lastValueFrom(
|
||||
this.pipelineReadService.PipelineV2FindOne(data, metadata),
|
||||
).catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
this.logger.info('Done');
|
||||
|
||||
return findOnePipelineResponse;
|
||||
}
|
||||
|
||||
async update(UpdatePipelineRequest: Messages.PipelineV2UpdateRequest) {
|
||||
this.logger.info('PipelinesClientService - Update');
|
||||
|
||||
const updatePipelineResponse = await lastValueFrom(
|
||||
this.pipelineWriteService.PipelineV2Update(UpdatePipelineRequest),
|
||||
)
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return updatePipelineResponse;
|
||||
}
|
||||
|
||||
async remove(data: Messages.PipelineV2RemoveRequest) {
|
||||
this.logger.info('PipelinesClientService - Remove');
|
||||
|
||||
const removePipelineResponse = await lastValueFrom(
|
||||
this.pipelineWriteService.PipelineV2Remove(data),
|
||||
)
|
||||
.then((res) => {
|
||||
this.logger.info('Done');
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(err.message);
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return removePipelineResponse;
|
||||
}
|
||||
|
||||
async findOneProperties(id: string, metadata: Metadata) {
|
||||
this.logger.info('PipelinesClientService - findOneProperties');
|
||||
const { pipeline } = await this.findOne({ id }, metadata);
|
||||
|
||||
const pipelineProperties = JSON.parse(pipeline.properties);
|
||||
|
||||
const connectorId = `${pipeline.connector_plugin}-${pipeline.connector_version}`;
|
||||
|
||||
const res = await this.connectorService.getConnectorDetails(
|
||||
connectorId,
|
||||
metadata.get('language')[0].toString(),
|
||||
);
|
||||
const connector = JSON.parse(res.connector);
|
||||
const config_controls = connector.config_controls || [];
|
||||
|
||||
for (const key in pipelineProperties) {
|
||||
const i = config_controls
|
||||
.map((cc) => cc.name)
|
||||
.indexOf(`properties.${key}`);
|
||||
if (i > -1) {
|
||||
config_controls[i] = {
|
||||
...config_controls[i],
|
||||
default_value: pipelineProperties[key],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
pipeline: {
|
||||
...pipeline,
|
||||
config_controls,
|
||||
properties: pipelineProperties,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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 {}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user