mirror of
https://github.com/dadosfera/maestro.git
synced 2026-08-31 19:58:21 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
14e0f3d2d3 | ||
|
|
85ef0d7c74 | ||
|
|
e00b6481d0 | ||
|
|
8906c73d84 | ||
|
|
3bc37db891 | ||
|
|
fe44664970 | ||
|
|
0503732c1e | ||
|
|
fa0855d631 | ||
|
|
38aee30f2a | ||
|
|
19f5c947bd | ||
|
|
44aa0e6010 | ||
|
|
cf4e7da1d8 | ||
|
|
8bd7d54aa7 | ||
|
|
a00a66e0d0 | ||
|
|
f4c5d03269 | ||
|
|
060ba7da8a | ||
|
|
5ec2c01b20 | ||
|
|
4a7e660a49 | ||
|
|
abc6258492 | ||
|
|
7ee1215da2 | ||
|
|
cd5886337b | ||
|
|
5fb8dae312 | ||
|
|
5072a54ef6 | ||
|
|
718f5cb12a | ||
|
|
4c41dd8029 | ||
|
|
fe8a0b88b0 | ||
|
|
cd67ca61cd | ||
|
|
b9439685f3 | ||
|
|
04edce0c56 | ||
|
|
ef098dd74d | ||
|
|
2541960b44 | ||
|
|
2dc965ed90 | ||
|
|
b2f1ce669d | ||
|
|
602d81e51f | ||
|
|
bbdb023dde | ||
|
|
9cb4cd7093 | ||
|
|
efc5870d87 | ||
|
|
c3d33f8230 | ||
|
|
0654e8fa04 | ||
|
|
28ab892208 | ||
|
|
d1522eb0ea | ||
|
|
6be9e06b22 | ||
|
|
7af261d56c | ||
|
|
8fa924fdfb | ||
|
|
4b4bdfea61 | ||
|
|
d1064c852b | ||
|
|
63338f5250 | ||
|
|
5e1fb41930 | ||
|
|
a807da2414 | ||
|
|
85f14fcf4b | ||
|
|
d95898ce55 | ||
|
|
33075b0f85 | ||
|
|
ca75f8f6e7 | ||
|
|
af12a39959 | ||
|
|
f77476b9ae | ||
|
|
fb0c659cd1 | ||
|
|
aea6815de7 | ||
|
|
0103f100f5 | ||
|
|
66b6be43b7 | ||
|
|
c029e286b5 | ||
|
|
a8f94a2d53 | ||
|
|
aadb3fcdee | ||
|
|
a26e88d2b6 | ||
|
|
b20f67e8b8 | ||
|
|
4a8a8eb463 | ||
|
|
d52f8b78c8 | ||
|
|
bfbe7cce87 | ||
|
|
1ab8c1dd10 | ||
|
|
246de83142 | ||
|
|
dfa6222538 | ||
|
|
fc7a9c7909 | ||
|
|
932616a578 | ||
|
|
b64619ede1 | ||
|
|
4a08e5f560 | ||
|
|
4ffd0916c3 | ||
|
|
92041f453c | ||
|
|
f2f09cc9c7 | ||
|
|
d486231fd6 | ||
|
|
526a3bddcd | ||
|
|
45108d3019 | ||
|
|
ac3e26b851 | ||
|
|
7fbc919716 | ||
|
|
5b1eb19511 | ||
|
|
b714f3cf36 | ||
|
|
48c1e29168 | ||
|
|
04ea1d0f04 | ||
|
|
0de5e1d5d1 | ||
|
|
b8c41fad1b | ||
|
|
ef9ec5ad42 | ||
|
|
65e71f21a0 | ||
|
|
b921393ba1 | ||
|
|
18aa7d8674 | ||
|
|
f2dd871de2 | ||
|
|
cf3fa88196 | ||
|
|
131810533c | ||
|
|
ea06f3f571 | ||
|
|
81921a7eb2 | ||
|
|
e9fdd0285b | ||
|
|
167470adba | ||
|
|
fbb9a59214 | ||
|
|
ef6d8594a3 | ||
|
|
ac73c0b046 | ||
|
|
5a30bf08b2 | ||
|
|
62b4eb709e | ||
|
|
b37a18d1da | ||
|
|
379bac704f | ||
|
|
9178530a21 | ||
|
|
667d3f874d | ||
|
|
475af224bf | ||
|
|
11f1df5537 | ||
|
|
e3b02571c8 | ||
|
|
979a12aa7f | ||
|
|
7646d7a3c5 | ||
|
|
8f0e851a88 | ||
|
|
779418f471 | ||
|
|
6e6d03f302 | ||
|
|
85f41521ed | ||
|
|
e2bb119745 | ||
|
|
3d5ce59b52 | ||
|
|
1c63271f64 | ||
|
|
31a51c20aa | ||
|
|
62730eb969 | ||
|
|
5a2c760bab | ||
|
|
28b4f3ac4b | ||
|
|
43d181a429 | ||
|
|
a72fe1b60d | ||
|
|
b52a1227b1 | ||
|
|
31478ed61d | ||
|
|
79b1ba910e | ||
|
|
7fd929915b | ||
|
|
e4b27c5f76 | ||
|
|
92e449d6d3 | ||
|
|
5073b2e188 | ||
|
|
8a11eda24d | ||
|
|
9d732d4a48 | ||
|
|
5fa10a939b | ||
|
|
4be3ffe3a2 |
@@ -6,7 +6,7 @@ on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
environment:
|
||||
description: 'Deployment environment'
|
||||
description: "Deployment environment"
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
@@ -26,9 +26,9 @@ jobs:
|
||||
- name: Extract Environment
|
||||
run: |
|
||||
if [ ${EVENT} == "workflow_dispatch" ]; then
|
||||
echo "##[set-output name=environment;]$(echo ${DEPLOY_ENV})"
|
||||
echo "environment=${DEPLOY_ENV}" >> $GITHUB_OUTPUT
|
||||
elif [ ${GITHUB_REF} == "refs/heads/main" ]; then
|
||||
echo "##[set-output name=environment;]$(echo "prd")"
|
||||
echo "environment=prd" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
id: extract_environment
|
||||
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
new_release_version: ${{ (steps.semantic.outputs.new_release_published == 'true' && steps.semantic.outputs.new_release_version) || (github.event_name == 'workflow_dispatch' && '0.0.0') }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- if: github.event_name != 'workflow_dispatch'
|
||||
name: Semantic Release
|
||||
@@ -56,20 +56,26 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
deploy:
|
||||
if: ${{ github.event_name == 'workflow_dispatch' || needs.semantic_release.outputs.new_release_published == 'true' }}
|
||||
deploy-info:
|
||||
if: ${{ github.event_name == 'workflow_dispatch'}}
|
||||
needs: [extract_environment, semantic_release]
|
||||
runs-on:
|
||||
[self-hosted, '${{ needs.extract_environment.outputs.environment }}']
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Printing stats
|
||||
- name: Create summary
|
||||
env:
|
||||
EVENT: ${{ github.event_name }}
|
||||
IMAGE_TAG: ${{ needs.semantic_release.outputs.new_release_version }}
|
||||
ENV: ${{ needs.extract_environment.outputs.environment }}
|
||||
run: echo ${GITHUB_REF#refs/heads/}
|
||||
run: echo "### Deploy da branch \`$GITHUB_REF_NAME\` no ambiente **$ENV** :rocket:" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
deploy:
|
||||
if: ${{ github.event_name == 'workflow_dispatch' || needs.semantic_release.outputs.new_release_published == 'true' }}
|
||||
needs: [extract_environment, semantic_release]
|
||||
runs-on:
|
||||
[self-hosted, "${{ needs.extract_environment.outputs.environment }}"]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
@@ -90,7 +96,7 @@ jobs:
|
||||
python3 -m pip install awsebcli --upgrade
|
||||
|
||||
- name: Configure AWS Region
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
uses: aws-actions/configure-aws-credentials@v1-node16
|
||||
id: aws
|
||||
with:
|
||||
aws-region: us-east-1
|
||||
@@ -113,10 +119,12 @@ jobs:
|
||||
ENV: ${{ needs.extract_environment.outputs.environment }}
|
||||
IMAGE_TAG: ${{ needs.semantic_release.outputs.new_release_version }}
|
||||
ACCOUNT_ID: ${{ steps.aws.outputs.aws-account-id }}
|
||||
NODE_EXPORTER_URL: ${{needs.extract_environment.outputs.environment == 'prd' && '611330257153.dkr.ecr.us-east-1.amazonaws.com\/monitoring\/node_exporter:latest' || '468720548566.dkr.ecr.us-east-1.amazonaws.com\/monitoring\/node_exporter:latest'}}
|
||||
run: |
|
||||
sed -i -e "s/\${ENV}/$ENV/g" docker-compose.yml
|
||||
sed -i -e "s/\${IMAGE_TAG}/$IMAGE_TAG/g" docker-compose.yml
|
||||
sed -i -e "s/\${ACCOUNT_ID}/$ACCOUNT_ID/g" docker-compose.yml
|
||||
sed -i -e "s/\${NODE_EXPORTER_URL}/$NODE_EXPORTER_URL/g" docker-compose.yml
|
||||
zip deploy.zip docker-compose.yml -r .ebextensions
|
||||
|
||||
- name: Deploy AWS Beanstalk
|
||||
@@ -136,71 +144,47 @@ jobs:
|
||||
docker system df
|
||||
api_docs:
|
||||
needs: [extract_environment, semantic_release, deploy]
|
||||
runs-on:
|
||||
[self-hosted, '${{ needs.extract_environment.outputs.environment }}']
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Extract Docs PageId
|
||||
- name: Extract Docs BlockId and PageId
|
||||
env:
|
||||
ENV: ${{ needs.extract_environment.outputs.environment }}
|
||||
DEV_DOCS_BLOCK_ID: ${{ secrets.DEV_DOCS_BLOCK_ID }}
|
||||
DEV_DOCS_PAGE_ID: ${{ secrets.DEV_DOCS_PAGE_ID }}
|
||||
STG_DOCS_BLOCK_ID: ${{ secrets.STG_DOCS_BLOCK_ID }}
|
||||
STG_DOCS_PAGE_ID: ${{ secrets.STG_DOCS_PAGE_ID }}
|
||||
PRD_DOCS_BLOCK_ID: ${{ secrets.PRD_DOCS_BLOCK_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)"
|
||||
echo "block_id=$DEV_DOCS_BLOCK_ID" >> $GITHUB_OUTPUT
|
||||
echo "page_id=$DEV_DOCS_PAGE_ID" >> $GITHUB_OUTPUT
|
||||
elif [ $ENV == "stg" ]; then
|
||||
echo "##[set-output name=result;]$(echo $STG_DOCS_PAGE_ID)"
|
||||
echo "block_id=$STG_DOCS_BLOCK_ID" >> $GITHUB_OUTPUT
|
||||
echo "page_id=$STG_DOCS_PAGE_ID" >> $GITHUB_OUTPUT
|
||||
elif [ $ENV == "prd" ]; then
|
||||
echo "##[set-output name=result;]$(echo $PRD_DOCS_PAGE_ID)"
|
||||
echo "block_id=$PRD_DOCS_BLOCK_ID" >> $GITHUB_OUTPUT
|
||||
echo "page_id=$PRD_DOCS_PAGE_ID" >> $GITHUB_OUTPUT
|
||||
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
|
||||
id: extract_docs_info
|
||||
|
||||
- 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
|
||||
DOCS_PAGE_ID: ${{ steps.extract_docs_info.outputs.page_id }}
|
||||
DOCS_BLOCK_ID: ${{ steps.extract_docs_info.outputs.block_id }}
|
||||
EVENT: ${{ github.event_name }}
|
||||
RELEASE_VERSION: ${{ needs.semantic_release.outputs.new_release_version }}
|
||||
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)
|
||||
if [ ${EVENT} != "workflow_dispatch" ]; then
|
||||
sed -i -E "s/(\"title\": )\"Maestro.+\"/\1\"Maestro - $RELEASE_VERSION\"/g" docsfera.json
|
||||
fi
|
||||
sed -i -e "s/\${DOCS_API_TOKEN}/$DOCS_API_TOKEN/g" docsfera.json
|
||||
sed -i -e "s/\${DOCS_PAGE_ID}/$DOCS_PAGE_ID/g" docsfera.json
|
||||
sed -i -e "s/\${DOCS_BLOCK_ID}/$DOCS_BLOCK_ID/g" docsfera.json
|
||||
curl -X POST -H 'Content-Type: application/json' -d @docsfera.json $DOCS_URL
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ services:
|
||||
- .env
|
||||
|
||||
node_exporter:
|
||||
image: prom/node-exporter:v1.3.1
|
||||
image: ${NODE_EXPORTER_URL}
|
||||
container_name: node_exporter
|
||||
restart: always
|
||||
volumes:
|
||||
|
||||
+6159
File diff suppressed because it is too large
Load Diff
Generated
+62
-18
@@ -12,7 +12,7 @@
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-secrets-manager": "^3.112.0",
|
||||
"@dadosfera/dadosfera-logs": "^1.0.0-beta.4",
|
||||
"@dadosfera/protospack-v2": "3.18.8",
|
||||
"@dadosfera/protospack-v2": "3.19.4",
|
||||
"@grpc/grpc-js": "^1.6.7",
|
||||
"@grpc/proto-loader": "^0.6.13",
|
||||
"@nestjs/common": "^8.4.7",
|
||||
@@ -33,6 +33,7 @@
|
||||
"helmet": "^5.1.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"jwk-to-pem": "^2.0.5",
|
||||
"mixpanel": "^0.17.0",
|
||||
"passport": "^0.6.0",
|
||||
"passport-facebook": "^3.0.0",
|
||||
"passport-forcedotcom": "^0.1.5",
|
||||
@@ -1726,9 +1727,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@dadosfera/protospack-v2": {
|
||||
"version": "3.18.8",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.18.8.tgz",
|
||||
"integrity": "sha512-pzvuIzCrIf/ZG//lwMdCxtZ7w/ZhiLFBA3VWyN9uM7AjeqVl7LllHKV08Fw6YjNNGBmQF3DLJQTK8kMCQja4hA==",
|
||||
"version": "3.19.4",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.19.4.tgz",
|
||||
"integrity": "sha512-Vb6bdFgQKYHf0kDK9kuMtN+nt3nkaMhJZ3wNVaUmQNxsnpGyARWBL29R2n+YnxS8g23tRwuj331sjg+DY0Fnhg==",
|
||||
"dependencies": {
|
||||
"@grpc/grpc-js": "^1.6.7",
|
||||
"rxjs": "^7.5.5",
|
||||
@@ -3543,7 +3544,6 @@
|
||||
},
|
||||
"node_modules/agent-base": {
|
||||
"version": "6.0.2",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "4"
|
||||
@@ -8205,6 +8205,29 @@
|
||||
"version": "1.2.6",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/mixpanel": {
|
||||
"version": "0.17.0",
|
||||
"resolved": "https://registry.npmjs.org/mixpanel/-/mixpanel-0.17.0.tgz",
|
||||
"integrity": "sha512-DY5WeOy/hmkPrNiiZugJpWR0iMuOwuj1a3u0bgwB2eUFRV6oIew/pIahhpawdbNjb+Bye4a8ID3gefeNPvL81g==",
|
||||
"dependencies": {
|
||||
"https-proxy-agent": "5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mixpanel/node_modules/https-proxy-agent": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
|
||||
"integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
|
||||
"dependencies": {
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/mkdirp": {
|
||||
"version": "0.5.6",
|
||||
"license": "MIT",
|
||||
@@ -8229,8 +8252,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/moment-timezone": {
|
||||
"version": "0.5.34",
|
||||
"license": "MIT",
|
||||
"version": "0.5.38",
|
||||
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.38.tgz",
|
||||
"integrity": "sha512-nMIrzGah4+oYZPflDvLZUgoVUO4fvAqHstvG3xAUnMolWncuAiLDWNnJZj6EwJGMGfb1ZcuTFE6GI3hNOVWI/Q==",
|
||||
"dependencies": {
|
||||
"moment": ">= 2.9.0"
|
||||
},
|
||||
@@ -10337,9 +10361,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ts-proto": {
|
||||
"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==",
|
||||
"version": "1.131.0",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/ts-proto/-/ts-proto-1.131.0.tgz",
|
||||
"integrity": "sha512-oj/kWrDz3JkkPQwumQDKfwHroH9iNz2alvrbCYzNYJlb/2MAUzFNfh9T+SZUPDfoXXK6oJoW1hGCHznj67yHNg==",
|
||||
"dependencies": {
|
||||
"@types/object-hash": "^1.3.0",
|
||||
"dataloader": "^1.4.0",
|
||||
@@ -12306,9 +12330,9 @@
|
||||
}
|
||||
},
|
||||
"@dadosfera/protospack-v2": {
|
||||
"version": "3.18.8",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.18.8.tgz",
|
||||
"integrity": "sha512-pzvuIzCrIf/ZG//lwMdCxtZ7w/ZhiLFBA3VWyN9uM7AjeqVl7LllHKV08Fw6YjNNGBmQF3DLJQTK8kMCQja4hA==",
|
||||
"version": "3.19.4",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.19.4.tgz",
|
||||
"integrity": "sha512-Vb6bdFgQKYHf0kDK9kuMtN+nt3nkaMhJZ3wNVaUmQNxsnpGyARWBL29R2n+YnxS8g23tRwuj331sjg+DY0Fnhg==",
|
||||
"requires": {
|
||||
"@grpc/grpc-js": "^1.6.7",
|
||||
"rxjs": "^7.5.5",
|
||||
@@ -13555,7 +13579,6 @@
|
||||
},
|
||||
"agent-base": {
|
||||
"version": "6.0.2",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"debug": "4"
|
||||
}
|
||||
@@ -16719,6 +16742,25 @@
|
||||
"minimist": {
|
||||
"version": "1.2.6"
|
||||
},
|
||||
"mixpanel": {
|
||||
"version": "0.17.0",
|
||||
"resolved": "https://registry.npmjs.org/mixpanel/-/mixpanel-0.17.0.tgz",
|
||||
"integrity": "sha512-DY5WeOy/hmkPrNiiZugJpWR0iMuOwuj1a3u0bgwB2eUFRV6oIew/pIahhpawdbNjb+Bye4a8ID3gefeNPvL81g==",
|
||||
"requires": {
|
||||
"https-proxy-agent": "5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"https-proxy-agent": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
|
||||
"integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
|
||||
"requires": {
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.6",
|
||||
"requires": {
|
||||
@@ -16736,7 +16778,9 @@
|
||||
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
|
||||
},
|
||||
"moment-timezone": {
|
||||
"version": "0.5.34",
|
||||
"version": "0.5.38",
|
||||
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.38.tgz",
|
||||
"integrity": "sha512-nMIrzGah4+oYZPflDvLZUgoVUO4fvAqHstvG3xAUnMolWncuAiLDWNnJZj6EwJGMGfb1ZcuTFE6GI3hNOVWI/Q==",
|
||||
"requires": {
|
||||
"moment": ">= 2.9.0"
|
||||
}
|
||||
@@ -18131,9 +18175,9 @@
|
||||
}
|
||||
},
|
||||
"ts-proto": {
|
||||
"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==",
|
||||
"version": "1.131.0",
|
||||
"resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/ts-proto/-/ts-proto-1.131.0.tgz",
|
||||
"integrity": "sha512-oj/kWrDz3JkkPQwumQDKfwHroH9iNz2alvrbCYzNYJlb/2MAUzFNfh9T+SZUPDfoXXK6oJoW1hGCHznj67yHNg==",
|
||||
"requires": {
|
||||
"@types/object-hash": "^1.3.0",
|
||||
"dataloader": "^1.4.0",
|
||||
|
||||
+4
-2
@@ -10,13 +10,14 @@
|
||||
},
|
||||
"scripts": {
|
||||
"preinstall": "aws codeartifact login --tool npm --namespace @dadosfera --repository dadosfera-npm --domain dadosfera --domain-owner 611330257153 --region us-east-1",
|
||||
"proto-update": "npm i @dadosfera/protospack-v2@latest --save-exact",
|
||||
"prebuild": "rimraf dist",
|
||||
"build": "nest build",
|
||||
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
||||
"start": "nest start",
|
||||
"start:dev": "nest start --watch",
|
||||
"start:debug": "nest start --debug --watch",
|
||||
"start:prod": "node dist/main",
|
||||
"start:prod": "npm run build && node dist/main",
|
||||
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
|
||||
"test": "jest",
|
||||
"test:watch": "jest --watch",
|
||||
@@ -27,7 +28,7 @@
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-secrets-manager": "^3.112.0",
|
||||
"@dadosfera/dadosfera-logs": "^1.0.0-beta.4",
|
||||
"@dadosfera/protospack-v2": "3.18.8",
|
||||
"@dadosfera/protospack-v2": "3.19.4",
|
||||
"@grpc/grpc-js": "^1.6.7",
|
||||
"@grpc/proto-loader": "^0.6.13",
|
||||
"@nestjs/common": "^8.4.7",
|
||||
@@ -48,6 +49,7 @@
|
||||
"helmet": "^5.1.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"jwk-to-pem": "^2.0.5",
|
||||
"mixpanel": "^0.17.0",
|
||||
"passport": "^0.6.0",
|
||||
"passport-facebook": "^3.0.0",
|
||||
"passport-forcedotcom": "^0.1.5",
|
||||
|
||||
+6
-2
@@ -23,6 +23,8 @@ 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';
|
||||
import { MixpanelModule } from './modules/mixpanel/mixpanel.module';
|
||||
|
||||
@Module({
|
||||
controllers: [],
|
||||
@@ -37,14 +39,15 @@ import { PipelinesV2Module } from './modules/pipelinesV2/pipelines.module';
|
||||
ConfigModule.forRoot({
|
||||
isGlobal: true,
|
||||
}),
|
||||
ConnectorModule,
|
||||
AuthModule,
|
||||
ConnectorModule,
|
||||
PermissionsModule,
|
||||
TermsOfUseModule,
|
||||
ConnectionModule,
|
||||
NetworkConfigModule,
|
||||
ConnectionTestModule,
|
||||
PipelinesModule,
|
||||
PipelinesV2Module,
|
||||
TransformationsModule,
|
||||
HealthModule,
|
||||
CatalogModule,
|
||||
@@ -52,8 +55,9 @@ import { PipelinesV2Module } from './modules/pipelinesV2/pipelines.module';
|
||||
RolesModule,
|
||||
InputsModule,
|
||||
OauthModule,
|
||||
PipelinesV2Module,
|
||||
CatalogModule,
|
||||
ProductboardModule,
|
||||
MixpanelModule,
|
||||
],
|
||||
})
|
||||
export class AppModule {}
|
||||
|
||||
@@ -128,11 +128,11 @@ export const PERMISSIONS_GROUPS = {
|
||||
DELETE: {
|
||||
seqid: 38,
|
||||
claim: 'connection:delete',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
name: {
|
||||
'pt-br': 'Excluir Fonte',
|
||||
'en-us': 'Remove Source',
|
||||
'es-s': 'Eliminar Source',
|
||||
'es-es': 'Eliminar Source',
|
||||
},
|
||||
},
|
||||
UPDATE: {
|
||||
@@ -290,15 +290,15 @@ export const PERMISSIONS_GROUPS = {
|
||||
claim: 'GET /catalog',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
name: {
|
||||
'pt-br': 'Buscar data assets',
|
||||
'en-us': 'Search for data assets',
|
||||
'es-es': 'Buscar data assets',
|
||||
'pt-br': 'Acessar lista de Ativos e visualizar atributos',
|
||||
'en-us': 'Access Assets list and its attributes',
|
||||
'es-es': 'Acceda a la lista de Activos y vea los atributos',
|
||||
},
|
||||
},
|
||||
CREATE: {
|
||||
seqid: 19,
|
||||
claim: 'POST /catalog',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'Criar atributos no catálogo',
|
||||
'en-us': 'Create attributes',
|
||||
@@ -307,32 +307,33 @@ export const PERMISSIONS_GROUPS = {
|
||||
},
|
||||
UPDATE: {
|
||||
seqid: 25,
|
||||
claim: 'PUT /catalog',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
claim: 'catalog:edit',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
name: {
|
||||
'pt-br': 'Editar atributos no catálogo',
|
||||
'en-us': 'Edit attributes',
|
||||
'es-es': 'Editar atributos',
|
||||
'pt-br': 'Criar e editar atributos no catálogo',
|
||||
'en-us': 'Create and edit attributes on the catalog',
|
||||
'es-es': 'Crear y editar atributos en el catálogo',
|
||||
},
|
||||
},
|
||||
DELETE: {
|
||||
seqid: 1,
|
||||
claim: 'DELETE /catalog',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
claim: 'catalog:delete',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
name: {
|
||||
'pt-br': 'Excluir atributos no catálogo',
|
||||
'en-us': 'Remove attributes',
|
||||
'es-es': 'Eliminar atributos',
|
||||
'pt-br': 'Excluir Ativos do catálogo',
|
||||
'en-us': 'Remove Assets from the catalog',
|
||||
'es-es': 'Eliminar Activos del catálogo',
|
||||
},
|
||||
},
|
||||
DATA_MANAGER: {
|
||||
seqid: 42,
|
||||
claim: 'catalog:data_manager',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'Vizualizar todos os recursos do catálogo.',
|
||||
'en-us': 'View all data assets.',
|
||||
'es-es': 'Ver todos los activos de datos',
|
||||
'pt-br':
|
||||
'Gerente do catálogo. Consegue vizualizar e editar todos os ativos.',
|
||||
'en-us': 'Catalog manager. Able to view and edit all assets.',
|
||||
'es-es': 'Gestor de catálogos. Puede ver y editar todos los activos.',
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -448,11 +449,11 @@ export const PERMISSIONS_GROUPS = {
|
||||
},
|
||||
},
|
||||
|
||||
ORCHEST: {
|
||||
MODULES: {
|
||||
title: {
|
||||
'pt-br': 'Analisar | Inteligência',
|
||||
'en-us': 'Analyze | Intelligence',
|
||||
'es-es': 'Analizar | Inteligencia',
|
||||
'pt-br': 'Módulos da Dadosfera',
|
||||
'en-us': 'Dadosfera Modules',
|
||||
'es-es': 'Módulos de la Dadosfera',
|
||||
},
|
||||
permissions: {
|
||||
INTELLIGENCE: {
|
||||
@@ -460,9 +461,9 @@ export const PERMISSIONS_GROUPS = {
|
||||
claim: 'intelligence:open',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'Acessar Orchest',
|
||||
'en-us': 'Access Orchest',
|
||||
'es-s': 'Acceso Orchest',
|
||||
'pt-br': 'Acessar Módulo de Inteligência',
|
||||
'en-us': 'Access Intelligence Module',
|
||||
'es-s': 'Acceder Módulo de Inteligencia',
|
||||
},
|
||||
},
|
||||
APP_BUILDER: {
|
||||
@@ -472,7 +473,7 @@ export const PERMISSIONS_GROUPS = {
|
||||
name: {
|
||||
'pt-br': 'Acessar App Builder',
|
||||
'en-us': 'Access App Builder',
|
||||
'es-es': 'Acceso App Builder',
|
||||
'es-es': 'Acceder App Builder',
|
||||
},
|
||||
},
|
||||
MACHINE_LEARNING: {
|
||||
@@ -482,7 +483,17 @@ export const PERMISSIONS_GROUPS = {
|
||||
name: {
|
||||
'pt-br': 'Acessar Machine Learning',
|
||||
'en-us': 'Access Machine Learning',
|
||||
'es-es': 'Acceso Machine Learning',
|
||||
'es-es': 'Acceder Machine Learning',
|
||||
},
|
||||
},
|
||||
PROCESS: {
|
||||
seqid: 43,
|
||||
claim: 'process:open',
|
||||
usage: PermissionUsages.INTERNAL,
|
||||
name: {
|
||||
'pt-br': 'Acessar Módulo de Processamento',
|
||||
'en-us': 'Access Processing Module',
|
||||
'es-es': 'Acceder Módulo de Tramitación',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -3,7 +3,6 @@ import {
|
||||
Catch,
|
||||
ArgumentsHost,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
} from '@nestjs/common';
|
||||
import { Response } from 'express';
|
||||
|
||||
|
||||
+38
-9
@@ -6,6 +6,8 @@ import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
|
||||
import { AppModule } from './app.module';
|
||||
import { writeFileSync } from 'fs';
|
||||
import { execSync } from 'child_process';
|
||||
import { INestApplication } from '@nestjs/common';
|
||||
async function bootstrap() {
|
||||
DadosferaLogger.setupLogger({
|
||||
serviceName: 'maestro',
|
||||
@@ -24,26 +26,53 @@ async function bootstrap() {
|
||||
});
|
||||
|
||||
app.use(helmet());
|
||||
configureSwagger(app);
|
||||
|
||||
await app.listen(3333);
|
||||
}
|
||||
function configureSwagger(app: INestApplication) {
|
||||
const date = new Date();
|
||||
const swaggerVersion = `${date.getDate()}.${
|
||||
date.getMonth() + 1
|
||||
}.${date.getFullYear()} - ${date.getHours()}:${date.getMinutes()}`;
|
||||
|
||||
let branchName = '';
|
||||
try {
|
||||
branchName = execSync('git rev-parse --abbrev-ref HEAD')
|
||||
.toString()
|
||||
.replace('\n', '')
|
||||
.trim();
|
||||
} catch (error) {
|
||||
console.log("Can't get branch name", error);
|
||||
}
|
||||
const swaggerTitle = branchName ? `Maestro - ${branchName}` : 'Maestro';
|
||||
|
||||
const config = new DocumentBuilder()
|
||||
.setTitle('Maestro')
|
||||
.setTitle(swaggerTitle)
|
||||
.setDescription('Documentation for Maestro gateway')
|
||||
.setVersion(
|
||||
`${date.getDate()}.${
|
||||
date.getMonth() + 1
|
||||
}.${date.getFullYear()} - ${date.getHours()}:${date.getMinutes()}`,
|
||||
.setVersion(swaggerVersion)
|
||||
.addBearerAuth(
|
||||
{ type: 'http', scheme: 'bearer', bearerFormat: 'JWT' },
|
||||
'Authorization',
|
||||
)
|
||||
.addBearerAuth()
|
||||
.build();
|
||||
|
||||
const document = SwaggerModule.createDocument(app, config);
|
||||
|
||||
if (process.env.ENV === 'local') SwaggerModule.setup('api', app, document);
|
||||
|
||||
await writeFileSync('swagger.txt', JSON.stringify(JSON.stringify(document)));
|
||||
|
||||
await app.listen(3333);
|
||||
writeFileSync(
|
||||
'docsfera.json',
|
||||
JSON.stringify(
|
||||
{
|
||||
service: '${DOCS_API_TOKEN}',
|
||||
pageId: '${DOCS_PAGE_ID}',
|
||||
blockId: '${DOCS_BLOCK_ID}',
|
||||
schema: document,
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
);
|
||||
}
|
||||
bootstrap();
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import {
|
||||
AuthSignInRequest,
|
||||
AuthRefreshAccessTokenRequest,
|
||||
AuthChangePasswordRequest,
|
||||
AuthResetPasswordRequest,
|
||||
@@ -27,6 +26,8 @@ import { AuthClientService } from './auth.service';
|
||||
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';
|
||||
import { AuthSignInReq, AuthSignInRes } from './dtos/login';
|
||||
|
||||
@ApiTags('Auth')
|
||||
@UseFilters(new GrpcToHttpExceptionFilter())
|
||||
@@ -42,6 +43,18 @@ export class AuthController {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
|
||||
@Post('sign-in')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async signIn(
|
||||
@Body() { username, password, totp }: AuthSignInReq,
|
||||
@Headers('Dadosfera-Lang') language: string,
|
||||
): Promise<AuthSignInRes> {
|
||||
this.logger.info('/auth - SignIn');
|
||||
const metadata = new Metadata();
|
||||
metadata.add('language', language || 'pt-br');
|
||||
return this.authClient.signIn({ username, password, totp }, metadata);
|
||||
}
|
||||
|
||||
@Post('/sso/snowflake')
|
||||
@RequireAllPermissions(PERMISSIONS_GROUPS.SNOWFLAKE.permissions.OPEN)
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@@ -57,22 +70,17 @@ export class AuthController {
|
||||
});
|
||||
}
|
||||
|
||||
@Post('sign-in')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async signIn(@Body() { username, password, totp }: AuthSignInRequest) {
|
||||
this.logger.info('/auth - SignIn');
|
||||
|
||||
return this.authClient.signIn({ username, password, totp });
|
||||
}
|
||||
|
||||
@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')
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
AuthConfirmResetPasswordRequest,
|
||||
} 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 {
|
||||
@@ -51,19 +52,25 @@ export class AuthClientService implements OnModuleInit {
|
||||
return lastValueFrom(this.authService.AuthSnowflakeSignIn(input));
|
||||
}
|
||||
|
||||
async signIn({ username, password, totp }: AuthSignInRequest) {
|
||||
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),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import {
|
||||
AuthSignInRequest,
|
||||
AuthSignInResponse,
|
||||
} from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/messages';
|
||||
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||
|
||||
export class LoginDto {
|
||||
@ApiProperty()
|
||||
@@ -10,3 +14,86 @@ export class LoginDto {
|
||||
@ApiProperty({ required: false })
|
||||
totp: string;
|
||||
}
|
||||
export class AuthTokens {
|
||||
@ApiProperty()
|
||||
accessToken: string;
|
||||
@ApiProperty()
|
||||
refreshToken: string;
|
||||
@ApiPropertyOptional()
|
||||
termsOfUseToken: string;
|
||||
@ApiProperty({ deprecated: true })
|
||||
idToken: string;
|
||||
}
|
||||
export enum MfaStatuses {
|
||||
PENDING = 'pending',
|
||||
NONE = 'none',
|
||||
TOTP = 'totp',
|
||||
}
|
||||
|
||||
export enum TouStatuses {
|
||||
PENDING = 'pending',
|
||||
REQUIRED = 'required',
|
||||
OK = 'ok',
|
||||
}
|
||||
export class TermsOfUse {
|
||||
@ApiProperty()
|
||||
version: number;
|
||||
@ApiProperty()
|
||||
publicUrl: string;
|
||||
@ApiProperty()
|
||||
enforceDate: string;
|
||||
@ApiProperty()
|
||||
createdAt: string;
|
||||
}
|
||||
export class TermsOfUseStatus {
|
||||
@ApiProperty({ enum: TouStatuses })
|
||||
status: string;
|
||||
@ApiPropertyOptional()
|
||||
lastSigned?: TermsOfUse;
|
||||
@ApiPropertyOptional()
|
||||
next?: TermsOfUse;
|
||||
}
|
||||
export class AuthUser {
|
||||
@ApiProperty()
|
||||
id: string;
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
@ApiProperty()
|
||||
username: string;
|
||||
@ApiProperty()
|
||||
createdAt: string;
|
||||
}
|
||||
export class AuthCustomer {
|
||||
@ApiProperty()
|
||||
modules: string[];
|
||||
@ApiProperty()
|
||||
id: string;
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
@ApiProperty()
|
||||
tier: string;
|
||||
}
|
||||
|
||||
export class AuthSignInReq implements AuthSignInRequest {
|
||||
@ApiProperty()
|
||||
username: string;
|
||||
@ApiProperty()
|
||||
password: string;
|
||||
@ApiPropertyOptional()
|
||||
totp: string;
|
||||
}
|
||||
|
||||
export class AuthSignInRes implements AuthSignInResponse {
|
||||
@ApiProperty()
|
||||
permissions: string[];
|
||||
@ApiProperty({ enum: MfaStatuses })
|
||||
mfaStatus: string;
|
||||
@ApiPropertyOptional()
|
||||
customer?: AuthCustomer;
|
||||
@ApiPropertyOptional()
|
||||
user?: AuthUser;
|
||||
@ApiPropertyOptional()
|
||||
tokens?: AuthTokens;
|
||||
@ApiPropertyOptional()
|
||||
termsOfUse?: TermsOfUseStatus;
|
||||
}
|
||||
|
||||
@@ -3,37 +3,61 @@ import {
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Headers,
|
||||
HttpException,
|
||||
Inject,
|
||||
Param,
|
||||
Post,
|
||||
Put,
|
||||
Query,
|
||||
UnsupportedMediaTypeException,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { AuthenticateCondition } from '../../authentication/authentication.decorator';
|
||||
import {
|
||||
AuthenticateCondition,
|
||||
Authenticated,
|
||||
} from '../../authentication/authentication.decorator';
|
||||
import { PERMISSIONS_GROUPS } from '../../authentication/permissions.enum';
|
||||
import { CatalogService } from './catalog.service';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import { PackTheMetadata } from 'src/utils/ PackTheMetadata';
|
||||
import { RequestUser, User } from 'src/authentication/user.decorator';
|
||||
import {
|
||||
ICatalogAllResponse,
|
||||
IColumnsMetadataResponse,
|
||||
ICreateDataAsset,
|
||||
IDeleteComment,
|
||||
IDocsResponse,
|
||||
IMakeAComment,
|
||||
IOneDataAsset,
|
||||
IPreviewResponse,
|
||||
IUpdateDataRequest,
|
||||
} from './dtos';
|
||||
|
||||
const catalogPermissions = PERMISSIONS_GROUPS.CATALOG.permissions;
|
||||
@ApiTags('Catalog')
|
||||
@Controller('catalog')
|
||||
@AuthenticateCondition((req, user) => {
|
||||
let action;
|
||||
@Authenticated()
|
||||
@AuthenticateCondition((req, user: RequestUser) => {
|
||||
if (user.permissions.includes(catalogPermissions.DATA_MANAGER.seqid))
|
||||
return true;
|
||||
|
||||
if (req.path.includes('/manage-permissions')) return true;
|
||||
let action: keyof typeof catalogPermissions;
|
||||
|
||||
switch (req.method) {
|
||||
case 'POST':
|
||||
action = 'CREATE';
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
action = 'UPDATE';
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
if (req.path.includes('/comment')) action = 'UPDATE';
|
||||
else action = req.method;
|
||||
break;
|
||||
|
||||
default:
|
||||
action = req.method;
|
||||
action = req.method as 'GET';
|
||||
}
|
||||
|
||||
return user.permissions.includes(
|
||||
@@ -50,54 +74,15 @@ export class CatalogController {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
|
||||
@Put('manage_permissions/:id')
|
||||
async manageDataAssetPermissions(
|
||||
@Param('id') id: string,
|
||||
@Get()
|
||||
async catalogAll(
|
||||
@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(@User() user: RequestUser, @Body() body, @Query() params) {
|
||||
@Query() query,
|
||||
): Promise<ICatalogAllResponse> {
|
||||
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,
|
||||
this.logger.info(`/catalog - Catalog all data assets`, {
|
||||
user_id,
|
||||
customer_name,
|
||||
});
|
||||
|
||||
const is_data_manager = permissions.includes(
|
||||
@@ -116,378 +101,12 @@ export class CatalogController {
|
||||
});
|
||||
|
||||
const res = await this.catalogService.getAllOpenSearchDataAssets(
|
||||
params,
|
||||
query,
|
||||
metadata,
|
||||
customer_id,
|
||||
);
|
||||
|
||||
return res.data_assets;
|
||||
}
|
||||
|
||||
@Get('data_apps')
|
||||
async dataAppsAll(@Body() body) {
|
||||
this.logger.info(`/catalog - ON FIND ALL DATA APPS ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
});
|
||||
|
||||
const res = await this.catalogService.dataAppsAll(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Delete('data_apps/:id')
|
||||
async dataAppsOne(@Param() params, @Body() body) {
|
||||
this.logger.info(`/catalog - ON FIND ONE DATA APP ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
});
|
||||
const { id } = params;
|
||||
|
||||
const res = await this.catalogService.dataAppsOne(id, body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('dashboard-metabase')
|
||||
async getAllDashboardMetabase(@Body() body) {
|
||||
this.logger.info(`/catalog - ON GET ALL DASHBOARDS METABASE ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
});
|
||||
|
||||
const res = await this.catalogService.getAllDashboardMetabase(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('dashboard-metabase/:id')
|
||||
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 { 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,
|
||||
});
|
||||
|
||||
const user_roles = await this.catalogService.getUserRolesIds(user_id);
|
||||
|
||||
const res = await this.catalogService.getOneDashboardMetabase(
|
||||
id,
|
||||
body,
|
||||
metadata,
|
||||
customer_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,
|
||||
@User() user: RequestUser,
|
||||
) {
|
||||
this.logger.info(`/catalog - ON GET ALL TABLES METADATA ROUTE`, {
|
||||
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 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 HttpException(
|
||||
'You do not have permission to access this data asset.',
|
||||
403,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Delete('table-metadata/:id')
|
||||
async deleteOneTableMetadata(@Param() params, @Body() body) {
|
||||
const { id } = params;
|
||||
this.logger.info(`/catalog - ON DELETE ONE TABLE METADATA ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
});
|
||||
|
||||
const res = await this.catalogService.deleteOneTableMetadata(id, body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('column-metadata')
|
||||
async getOneColumnMetadata(@Body() body, @Query() params) {
|
||||
this.logger.info(`/catalog - ON GET ONE COLUMN METADATA ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
});
|
||||
|
||||
const res = await this.catalogService.getOneColumnMetadata(body, params);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Delete('column-metadata/:id')
|
||||
async deleteOneColumnMetadata(@Param() params, @Body() body) {
|
||||
this.logger.info(`/catalog - ON DELETE ONE COLUMN METADATA ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
});
|
||||
const { id } = params;
|
||||
|
||||
const res = await this.catalogService.deleteOneColumnMetadata(id, body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('data-preview')
|
||||
async getOneDataPreview(@Body() body, @Query() params) {
|
||||
this.logger.info(`/catalog - ON GET ONE DATAPREVIEW ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
});
|
||||
|
||||
const res = await this.catalogService.getOneDataPreview(body, params);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('data-status')
|
||||
async getDataStatus(@Body() body) {
|
||||
this.logger.info(`/catalog - ON GET DATA STATUS ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
});
|
||||
|
||||
const res = await this.catalogService.getDataStatus(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('data-status')
|
||||
async createDataStatus(@Body() body) {
|
||||
this.logger.info(`/catalog - ON CREATE DATA STATUS ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
});
|
||||
|
||||
const res = await this.catalogService.createDataStatus(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('data-description')
|
||||
async getDataDescription(@Body() body) {
|
||||
this.logger.info(`/catalog - ON GET DATA DESCRIPTION ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
});
|
||||
|
||||
const res = await this.catalogService.getDataDescription(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Post('data-description')
|
||||
async createDataDescription(@Body() body, @User() user: RequestUser) {
|
||||
this.logger.info(`/catalog - ON CREATE DATA DESCRIPTION ROUTE`, {
|
||||
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,
|
||||
});
|
||||
return await this.catalogService.createDataDescription(body, metadata);
|
||||
}
|
||||
|
||||
@Get('data-docs')
|
||||
async getDataDocs(@Body() body) {
|
||||
this.logger.info(`/catalog - ON GET DATA DOCS ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
});
|
||||
|
||||
const res = await this.catalogService.getDataDocs(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Post('data-docs')
|
||||
async createDataDocs(@Body() body) {
|
||||
this.logger.info(`/catalog - ON CREATE DATA DOCS ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
});
|
||||
|
||||
const res = await this.catalogService.createDataDocs(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('data-rating')
|
||||
async getDataRating(@Body() body) {
|
||||
this.logger.info(`/catalog - ON GET DATA RATING ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
});
|
||||
|
||||
const res = await this.catalogService.getDataRating(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Post('data-rating')
|
||||
async createDataRating(@Body() body) {
|
||||
this.logger.info(`/catalog - ON GET DATA RATING ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
});
|
||||
|
||||
const res = await this.catalogService.createDataRating(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('summary-rating/:id')
|
||||
async getSummaryRating() {
|
||||
this.logger.info(`/catalog - ON GET SUMMARY RATING ROUTE`);
|
||||
//const { id } = params;
|
||||
|
||||
//
|
||||
|
||||
//const res = await this.catalogService.getSummaryRating(id, body);
|
||||
|
||||
return {
|
||||
avg_rating: 0,
|
||||
rating_count: 0,
|
||||
};
|
||||
}
|
||||
|
||||
@Get('data-comment')
|
||||
async getDataComment(@Body() body) {
|
||||
this.logger.info(`/catalog - ON GET DATA COMMENT ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
});
|
||||
|
||||
const res = await this.catalogService.getDataComment(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Post('data-comment')
|
||||
async createDataComment(@Body() body) {
|
||||
this.logger.info(`/catalog - ON GET DATA COMMENT ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
});
|
||||
|
||||
const res = await this.catalogService.createDataComment(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('data-review')
|
||||
async getDataReview(@Body() body, @Query() params) {
|
||||
this.logger.info(`/catalog - ON GET DATA REVIEW ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
});
|
||||
|
||||
const res = await this.catalogService.getDataReview(body, params);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Post('tags')
|
||||
async createTags(@Body() body, @User() user: RequestUser) {
|
||||
this.logger.info(`/catalog - ON CREATE TAG ROUTE`, {
|
||||
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, metadata);
|
||||
|
||||
return res.data_assets;
|
||||
return { ...res };
|
||||
}
|
||||
|
||||
@Get('tags')
|
||||
@@ -509,89 +128,399 @@ export class CatalogController {
|
||||
return res;
|
||||
}
|
||||
|
||||
@Delete('tags/:id')
|
||||
async deleteTags(@Param() params, @Body() body) {
|
||||
this.logger.info(`/catalog - ON DELETE TAG ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
@Get('data-asset/:id')
|
||||
async getDataAsset(
|
||||
@User() user: RequestUser,
|
||||
@Headers() headers,
|
||||
@Param('id') id,
|
||||
) {
|
||||
const { username, user_id, customer_id, customer_name, permissions } = user;
|
||||
const [data_asset_type, data_asset_id] = id.split('-');
|
||||
|
||||
this.logger.info(`/catalog - ON GET ONE DASHBOARD METABASE ROUTE`, {
|
||||
username,
|
||||
customer_name,
|
||||
});
|
||||
const { id } = params;
|
||||
body.data_asset_id = id;
|
||||
const { user_id, customer, customer_id } = body.info;
|
||||
|
||||
const is_data_manager = permissions.includes(
|
||||
PERMISSIONS_GROUPS.CATALOG.permissions.DATA_MANAGER.seqid,
|
||||
);
|
||||
let has_permission = false;
|
||||
const metadata = PackTheMetadata({
|
||||
username,
|
||||
user_id: undefined,
|
||||
customer_id,
|
||||
customer_name,
|
||||
});
|
||||
|
||||
const user_roles = await this.catalogService.getUserRolesIds(user_id);
|
||||
|
||||
const { data_asset } = await this.catalogService.getOneDataAsset({
|
||||
customer_id,
|
||||
data_asset_id,
|
||||
data_asset_type,
|
||||
metadata,
|
||||
});
|
||||
|
||||
if (data_asset?.owner === username) has_permission = true;
|
||||
|
||||
for (const role of user_roles) {
|
||||
if (data_asset.p_roles.includes(role)) has_permission = true;
|
||||
}
|
||||
|
||||
if (data_asset.p_users.includes(user_id)) has_permission = true;
|
||||
|
||||
if (is_data_manager || has_permission) {
|
||||
delete data_asset.p_roles;
|
||||
delete data_asset.p_users;
|
||||
return { data_asset };
|
||||
}
|
||||
|
||||
throw new HttpException(
|
||||
'You do not have permission to access this data asset.',
|
||||
403,
|
||||
);
|
||||
}
|
||||
|
||||
@Get('data-asset/rls/:id')
|
||||
async getDataAssetRls(
|
||||
@User() user: RequestUser,
|
||||
@Headers() headers,
|
||||
@Param('id') id,
|
||||
) {
|
||||
const { username, user_id, customer_id, customer_name, permissions } = user;
|
||||
const [data_asset_type, data_asset_id] = id.split('-');
|
||||
|
||||
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: customer,
|
||||
});
|
||||
const res = await this.catalogService.deleteTags(body, metadata);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Post('table-tags')
|
||||
async createTableTags(@Body() body) {
|
||||
this.logger.info(`/catalog - ON CREATE TABLE TAG ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
customer_name,
|
||||
});
|
||||
|
||||
const res = await this.catalogService.createTableTags(body);
|
||||
const user_roles = await this.catalogService.getUserRolesIds(user_id);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@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 { user_id, customer, customer_id } = body.info;
|
||||
const metadata = PackTheMetadata({
|
||||
user_id,
|
||||
const { data_asset } = await this.catalogService.getOneDataAsset({
|
||||
customer_id,
|
||||
customer_name: customer,
|
||||
data_asset_id,
|
||||
data_asset_type,
|
||||
metadata,
|
||||
});
|
||||
|
||||
if (data_asset?.owner === username) has_permission = true;
|
||||
|
||||
for (const role of user_roles) {
|
||||
if (data_asset.p_roles.includes(role)) has_permission = true;
|
||||
}
|
||||
|
||||
if (data_asset.p_users.includes(user_id)) has_permission = true;
|
||||
|
||||
if (is_data_manager || has_permission) {
|
||||
delete data_asset.p_roles;
|
||||
delete data_asset.p_users;
|
||||
return { data_asset };
|
||||
}
|
||||
|
||||
throw new HttpException(
|
||||
'You do not have permission to access this data asset.',
|
||||
403,
|
||||
);
|
||||
}
|
||||
|
||||
@Get('data-asset/:id/columns-metadata')
|
||||
async getDataAssetColumnsMetadata(
|
||||
@User() user: RequestUser,
|
||||
@Headers('Dadosfera-Lang') language,
|
||||
@Param('id') id,
|
||||
): Promise<IColumnsMetadataResponse> {
|
||||
const { customer_name, customer_id, user_id, username } = user;
|
||||
const data_asset_type = id.split('-')[0];
|
||||
|
||||
const supported_data_assets = ['dataset'];
|
||||
|
||||
if (!supported_data_assets.includes(data_asset_type)) {
|
||||
throw new UnsupportedMediaTypeException(
|
||||
`${data_asset_type} does not have a preview function for the time being.`,
|
||||
);
|
||||
}
|
||||
|
||||
this.logger.info(`/catalog - ON GET DATA DOCS ROUTE`, {
|
||||
user_id,
|
||||
customer_name,
|
||||
});
|
||||
|
||||
const metadata = PackTheMetadata({
|
||||
customer_name,
|
||||
customer_id,
|
||||
user_id,
|
||||
username,
|
||||
language,
|
||||
});
|
||||
|
||||
const columns_metadata =
|
||||
await this.catalogService.getDatasetColumnsMetadata(id, metadata);
|
||||
|
||||
return { columns_metadata };
|
||||
}
|
||||
|
||||
@Get('data-asset/:id/preview')
|
||||
async getDataAssetPreview(
|
||||
@User() user: RequestUser,
|
||||
@Headers('Dadosfera-lang') language,
|
||||
@Param('id') id,
|
||||
): Promise<IPreviewResponse> {
|
||||
const { customer_name, customer_id, user_id, username } = user;
|
||||
const data_asset_type = id.split('-')[0];
|
||||
|
||||
const supported_data_assets = ['dataset'];
|
||||
|
||||
if (!supported_data_assets.includes(data_asset_type)) {
|
||||
throw new UnsupportedMediaTypeException(
|
||||
`${data_asset_type} does not have a preview function for the time being.`,
|
||||
);
|
||||
}
|
||||
|
||||
this.logger.info(`/catalog - ON GET DATA DOCS ROUTE`, {
|
||||
user_id,
|
||||
customer_name,
|
||||
});
|
||||
|
||||
const metadata = PackTheMetadata({
|
||||
customer_name,
|
||||
customer_id,
|
||||
user_id,
|
||||
username,
|
||||
language,
|
||||
});
|
||||
|
||||
const preview = await this.catalogService.getDatasetPreview(id, metadata);
|
||||
|
||||
return { preview };
|
||||
}
|
||||
|
||||
@Get('data-asset/:id/docs')
|
||||
async getDataAssetDocs(
|
||||
@User() user: RequestUser,
|
||||
@Headers('Dadosfera-Lang') language,
|
||||
@Param('id') id,
|
||||
): Promise<IDocsResponse> {
|
||||
const { customer_name, customer_id, user_id, username } = user;
|
||||
const data_asset_type = id.split('-')[0];
|
||||
|
||||
const supported_data_assets = ['dataset'];
|
||||
|
||||
if (!supported_data_assets.includes(data_asset_type)) {
|
||||
throw new UnsupportedMediaTypeException(
|
||||
`${data_asset_type} does not have a documentation function for the time being.`,
|
||||
);
|
||||
}
|
||||
|
||||
this.logger.info(`/catalog - ON GET DATA DOCS ROUTE`, {
|
||||
user_id,
|
||||
customer_name,
|
||||
});
|
||||
|
||||
const metadata = PackTheMetadata({
|
||||
customer_name,
|
||||
customer_id,
|
||||
user_id,
|
||||
username,
|
||||
language,
|
||||
});
|
||||
|
||||
const docs = await this.catalogService.getDataDocs(id, metadata);
|
||||
|
||||
return { docs };
|
||||
}
|
||||
|
||||
@Put('data-asset/:id')
|
||||
async updateDataAsset(
|
||||
@User() user: RequestUser,
|
||||
@Headers('Dadosfera-Lang') language,
|
||||
@Param('id') id,
|
||||
@Body() body: IUpdateDataRequest,
|
||||
): Promise<IOneDataAsset> {
|
||||
const { customer_id, customer_name, user_id, username } = user;
|
||||
const metadata = PackTheMetadata({
|
||||
customer_id,
|
||||
customer_name,
|
||||
user_id,
|
||||
username,
|
||||
language,
|
||||
});
|
||||
|
||||
const result = await this.catalogService.updateOneDataAsset({
|
||||
body,
|
||||
data_asset_id: id,
|
||||
customer_id,
|
||||
metadata,
|
||||
});
|
||||
|
||||
delete result.data_asset.p_roles;
|
||||
delete result.data_asset.p_users;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Post('data-asset/:id/docs')
|
||||
async manageDataAssetDocs(
|
||||
@User() user: RequestUser,
|
||||
@Headers() headers,
|
||||
@Param('id') data_asset_id,
|
||||
@Body('docs') docs: string,
|
||||
) {
|
||||
const { user_id, customer_name } = user;
|
||||
const [, id] = data_asset_id.split('-');
|
||||
|
||||
this.logger.info(`/catalog - ON GET DATA DOCS ROUTE`, {
|
||||
user_id,
|
||||
customer_name,
|
||||
});
|
||||
|
||||
const res = await this.catalogService.createDataDocs({
|
||||
table_id: id,
|
||||
docs,
|
||||
info: {
|
||||
customer: customer_name,
|
||||
},
|
||||
});
|
||||
const res = await this.catalogService.findAllTableTags(params, metadata);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Delete('table-tags/:id')
|
||||
async deleteTableTags(@Param() params, @Body() body) {
|
||||
this.logger.info(`/catalog - ON CREATE TABLE TAGS ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
@Put('data-asset/:id/manage-permissions')
|
||||
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 { id } = params;
|
||||
const response = await this.catalogService.managePermissions(
|
||||
{ ...body, id },
|
||||
metadata,
|
||||
);
|
||||
|
||||
const res = await this.catalogService.deleteTableTags(id, body);
|
||||
|
||||
return res;
|
||||
return { data_asset: JSON.parse(response.data_asset) };
|
||||
}
|
||||
|
||||
@Get('table-rules')
|
||||
async getTableRules(@Body() body) {
|
||||
this.logger.info(`/catalog - ON GET TABLE RULES ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
@Put('data-asset/:id/revoke-permissions')
|
||||
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,
|
||||
);
|
||||
|
||||
const res = await this.catalogService.getTableRules(body);
|
||||
|
||||
return res;
|
||||
return { message: response.message };
|
||||
}
|
||||
|
||||
@Delete('table-rules/:id')
|
||||
async deleteTableRules(@Param() params, @Body() body) {
|
||||
this.logger.info(`/catalog - ON DELETE TABLE RULES ROUTE`, {
|
||||
user: body.info.user_id,
|
||||
customer: body.info.customer,
|
||||
@Post()
|
||||
async createDataAsset(
|
||||
@User() user: RequestUser,
|
||||
@Body() body: ICreateDataAsset,
|
||||
) {
|
||||
const { customer_id, customer_name, user_id, username } = user;
|
||||
const metadata = PackTheMetadata({
|
||||
customer_id,
|
||||
customer_name,
|
||||
user_id,
|
||||
username,
|
||||
});
|
||||
const { id } = params;
|
||||
const { data_asset } = await this.catalogService.createDataAsset(
|
||||
body,
|
||||
metadata,
|
||||
);
|
||||
|
||||
const res = await this.catalogService.deleteTableRules(id, body);
|
||||
return { data_asset: JSON.parse(data_asset) };
|
||||
}
|
||||
|
||||
return res;
|
||||
@Post('data-asset/:id/comment')
|
||||
async commentOnDataAsset(
|
||||
@Param('id') id: string,
|
||||
@User() user: RequestUser,
|
||||
@Body() body: IMakeAComment,
|
||||
) {
|
||||
const { message } = 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.commentOnDataAsset(
|
||||
{ data_asset_id: id, username, message },
|
||||
metadata,
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Delete('data-asset/:id')
|
||||
async deleteDataAsset(
|
||||
@Param('id') data_asset_id: string,
|
||||
@User() user: RequestUser,
|
||||
) {
|
||||
const { customer_id, customer_name, user_id, username } = user;
|
||||
const metadata = PackTheMetadata({
|
||||
customer_id,
|
||||
customer_name,
|
||||
user_id,
|
||||
username,
|
||||
});
|
||||
|
||||
const [type, id] = data_asset_id.split('-');
|
||||
const response = await this.catalogService.deleteDataAsset(
|
||||
{ id, type },
|
||||
metadata,
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Delete('data-asset/:id/comment')
|
||||
async deleteComment(
|
||||
@Param('id') id: string,
|
||||
@User() user: RequestUser,
|
||||
@Body() body: IDeleteComment,
|
||||
) {
|
||||
const { customer_id, customer_name, user_id, username } = user;
|
||||
const metadata = PackTheMetadata({
|
||||
customer_id,
|
||||
customer_name,
|
||||
user_id,
|
||||
username,
|
||||
});
|
||||
const response = await this.catalogService.deleteComment(
|
||||
{ data_asset_id: id, comment: body.comment },
|
||||
metadata,
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
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 {
|
||||
WriteService,
|
||||
ReadService,
|
||||
ProtoServices,
|
||||
Messages,
|
||||
} from '@dadosfera/protospack-v2/dist/lib/Catalog';
|
||||
import {
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
@@ -15,6 +17,7 @@ import { lastValueFrom } from 'rxjs';
|
||||
import { CatalogClientConfiguration } from './catalog-client';
|
||||
import { UsersService } from '../users/users.service';
|
||||
import { RolesService } from '../roles/roles.service';
|
||||
import { Metadata } from '@grpc/grpc-js';
|
||||
|
||||
class CatalogService implements OnModuleInit {
|
||||
catalogReadService: ReadService.CatalogReadServices;
|
||||
@@ -55,6 +58,19 @@ class CatalogService implements OnModuleInit {
|
||||
)}.dadosfera.ai`;
|
||||
}
|
||||
|
||||
async createDataAsset(data: Messages.CreateDataAssetRequest, metadata) {
|
||||
this.logger.info('CatalogService - Manage Data assets permissions');
|
||||
|
||||
return lastValueFrom(
|
||||
this.catalogWriteService.CreateDataAsset(data, metadata),
|
||||
).catch((err) => {
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 404,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async managePermissions(data: Messages.ManagePermissionRequest, metadata) {
|
||||
this.logger.info('CatalogService - Manage Data assets permissions');
|
||||
|
||||
@@ -81,34 +97,43 @@ class CatalogService implements OnModuleInit {
|
||||
});
|
||||
}
|
||||
|
||||
async catalogAll(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(`${nimbusUrl}/api/catalog/all/`);
|
||||
async commentOnDataAsset(data: Messages.MakeACommentRequest, metadata) {
|
||||
this.logger.info('CatalogService - Manage Data assets permissions');
|
||||
|
||||
return data;
|
||||
return lastValueFrom(
|
||||
this.catalogWriteService.MakeAComment(data, metadata),
|
||||
).catch((err) => {
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 404,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async dataAppsAll(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(`${nimbusUrl}/api/catalog/data_apps/`);
|
||||
return data;
|
||||
async deleteComment(data: Messages.UpdateACommentRequest, metadata) {
|
||||
this.logger.info('CatalogService - Manage Data assets permissions');
|
||||
|
||||
return lastValueFrom(
|
||||
this.catalogWriteService.UpdateAComment(data, metadata),
|
||||
).catch((err) => {
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 404,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async dataAppsOne(id, body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(
|
||||
`${nimbusUrl}/api/catalog/data_apps/${id}/`,
|
||||
);
|
||||
async deleteDataAsset(data: Messages.DeleteDataAssetRequest, metadata) {
|
||||
this.logger.info('CatalogService - Manage Data assets permissions');
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async getAllDashboardMetabase(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(
|
||||
`${nimbusUrl}/api/catalog/dashboard-metabase/`,
|
||||
);
|
||||
return data;
|
||||
return lastValueFrom(
|
||||
this.catalogWriteService.DeleteDataAsset(data, metadata),
|
||||
).catch((err) => {
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 404,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async getUserRolesIds(userId: string) {
|
||||
@@ -145,15 +170,23 @@ class CatalogService implements OnModuleInit {
|
||||
return [customer_users, customer_roles];
|
||||
}
|
||||
|
||||
async getAllOpenSearchDataAssets(
|
||||
data: Messages.GetAllDataAssetsRequest,
|
||||
metadata,
|
||||
customer_id,
|
||||
) {
|
||||
async getAllOpenSearchDataAssets(query, metadata, customer_id) {
|
||||
this.logger.info('CatalogService - getAllOpenSearchDashboard');
|
||||
|
||||
const response = await lastValueFrom(
|
||||
this.catalogReadService.GetAllDataAssets(data, metadata),
|
||||
const { search, page, size, sort_by, order, ...filters } = query;
|
||||
|
||||
const { data_assets, total } = await lastValueFrom(
|
||||
this.catalogReadService.GetAllDataAssets(
|
||||
{
|
||||
search,
|
||||
page,
|
||||
size,
|
||||
sort_by,
|
||||
order,
|
||||
filters: JSON.stringify(filters),
|
||||
},
|
||||
metadata,
|
||||
),
|
||||
).catch((err) => {
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
@@ -161,12 +194,12 @@ class CatalogService implements OnModuleInit {
|
||||
);
|
||||
});
|
||||
|
||||
const data_assets = JSON.parse(response.data_assets);
|
||||
const result = JSON.parse(data_assets);
|
||||
|
||||
const [customer_users, customer_roles] =
|
||||
await this.getUsernamesAndRolesByCustomerId(customer_id);
|
||||
|
||||
for (const asset of data_assets.tables) {
|
||||
for (const asset of result.data_assets) {
|
||||
const condition =
|
||||
asset.owner && !asset.owner.includes('@') ? true : false;
|
||||
const result = condition
|
||||
@@ -198,30 +231,18 @@ class CatalogService implements OnModuleInit {
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
Object.assign(asset, { ...asset, owner });
|
||||
}
|
||||
|
||||
return { data_assets };
|
||||
return { data_assets: result.data_assets, total };
|
||||
}
|
||||
|
||||
async getOneDashboardMetabase(id, body, metadata, customer_id) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(
|
||||
`${nimbusUrl}/api/catalog/dashboard-metabase/${id}`,
|
||||
);
|
||||
|
||||
async getOneDataAsset({
|
||||
data_asset_id,
|
||||
data_asset_type,
|
||||
customer_id,
|
||||
metadata,
|
||||
}) {
|
||||
const { data_asset } = await lastValueFrom(
|
||||
this.catalogReadService.GetOneDataAsset(
|
||||
{ id, type: 'dashboard' },
|
||||
{ id: data_asset_id, type: data_asset_type },
|
||||
metadata,
|
||||
),
|
||||
);
|
||||
@@ -253,9 +274,7 @@ class CatalogService implements OnModuleInit {
|
||||
}
|
||||
}
|
||||
|
||||
Object.assign(data.dashboard, {
|
||||
tags: opensearchTable.tags,
|
||||
description: opensearchTable.description || null,
|
||||
Object.assign(opensearchTable, {
|
||||
p_roles: opensearchTable.roles,
|
||||
p_users: opensearchTable.users,
|
||||
roles,
|
||||
@@ -263,163 +282,94 @@ class CatalogService implements OnModuleInit {
|
||||
owner,
|
||||
});
|
||||
|
||||
return data;
|
||||
return { data_asset: opensearchTable };
|
||||
}
|
||||
|
||||
async getAllTableMetadata(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(
|
||||
`${nimbusUrl}/api/catalog/table-metadata/`,
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
async deleteOneTableMetadata(id, body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.delete(
|
||||
`${nimbusUrl}/api/catalog/table-metadata/${id}`,
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
async getOneColumnMetadata(body, params) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(
|
||||
`${nimbusUrl}/api/catalog/column-metadata/`,
|
||||
{ params: params },
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
async deleteOneColumnMetadata(id, body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.delete(
|
||||
`${nimbusUrl}/api/catalog/column-metadata/${id}/`,
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
async getOneDataPreview(body, params) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(`${nimbusUrl}/api/catalog/data-preview/`, {
|
||||
params: params,
|
||||
});
|
||||
return data;
|
||||
}
|
||||
|
||||
async getDataStatus(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(`${nimbusUrl}/api/catalog/data-status/`);
|
||||
return data;
|
||||
}
|
||||
|
||||
async createDataStatus(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.post(
|
||||
`${nimbusUrl}/api/catalog/data-status/`,
|
||||
body,
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
async getDataDescription(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(
|
||||
`${nimbusUrl}/api/catalog/data-description/`,
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
async createDataDescription(body, metadata) {
|
||||
const response = await lastValueFrom(
|
||||
async updateOneDataAsset({ data_asset_id, customer_id, body, metadata }) {
|
||||
const { data_asset } = await lastValueFrom(
|
||||
this.catalogWriteService.UpdateDataAsset(
|
||||
{
|
||||
id: `dataset-${body.table_id}`,
|
||||
description: body.description,
|
||||
tags: undefined,
|
||||
},
|
||||
{ id: data_asset_id, changes: JSON.stringify(body) },
|
||||
metadata,
|
||||
),
|
||||
);
|
||||
// {
|
||||
// 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,
|
||||
};
|
||||
|
||||
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(opensearchTable, {
|
||||
p_roles: opensearchTable.roles,
|
||||
p_users: opensearchTable.users,
|
||||
roles,
|
||||
users,
|
||||
owner,
|
||||
});
|
||||
|
||||
return { data_asset: opensearchTable };
|
||||
}
|
||||
|
||||
async getDataDocs(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(`${nimbusUrl}/api/catalog/data-docs/`);
|
||||
return data;
|
||||
async getDataDocs(data_asset_id: string, metadata: Metadata) {
|
||||
const [data_asset_type, id] = data_asset_id.split('-');
|
||||
|
||||
const { documentation } = await lastValueFrom(
|
||||
this.catalogReadService.GetDatasetDoc(
|
||||
{ id, type: data_asset_type },
|
||||
metadata,
|
||||
),
|
||||
);
|
||||
console.log(documentation);
|
||||
const docs = JSON.parse(documentation);
|
||||
return docs;
|
||||
}
|
||||
|
||||
async getDatasetPreview(data_asset_id: string, metadata: Metadata) {
|
||||
const [data_asset_type, id] = data_asset_id.split('-');
|
||||
|
||||
const { preview } = await lastValueFrom(
|
||||
this.catalogReadService.GetDatasetPreview(
|
||||
{ id, type: data_asset_type },
|
||||
metadata,
|
||||
),
|
||||
);
|
||||
const result = JSON.parse(preview);
|
||||
return result;
|
||||
}
|
||||
|
||||
async getDatasetColumnsMetadata(data_asset_id: string, metadata: Metadata) {
|
||||
const [data_asset_type, id] = data_asset_id.split('-');
|
||||
|
||||
const { columns_metadata } = await lastValueFrom(
|
||||
this.catalogReadService.GetDatasetColumnsMetadata(
|
||||
{ id, type: data_asset_type },
|
||||
metadata,
|
||||
),
|
||||
);
|
||||
const result = JSON.parse(columns_metadata);
|
||||
return result;
|
||||
}
|
||||
|
||||
async createDataDocs(body) {
|
||||
@@ -431,70 +381,6 @@ class CatalogService implements OnModuleInit {
|
||||
return data;
|
||||
}
|
||||
|
||||
async getDataRating(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(`${nimbusUrl}/api/catalog/data-rating/`);
|
||||
return data;
|
||||
}
|
||||
|
||||
async createDataRating(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.post(
|
||||
`${nimbusUrl}/api/catalog/data-rating/`,
|
||||
body,
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
async getSummaryRating(id, body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(
|
||||
`${nimbusUrl}/api/catalog/summary-rating/${id}`,
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
async getDataComment(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(`${nimbusUrl}/api/catalog/data-comment/`);
|
||||
return data;
|
||||
}
|
||||
|
||||
async createDataComment(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.post(
|
||||
`${nimbusUrl}/api/catalog/data-comment/`,
|
||||
body,
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
async getDataReview(body, params) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(`${nimbusUrl}/api/catalog/data-review/`, {
|
||||
params: params,
|
||||
});
|
||||
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(data, metadata) {
|
||||
this.logger.info('CatalogService - findAllCustomerTags');
|
||||
|
||||
@@ -512,76 +398,6 @@ class CatalogService implements OnModuleInit {
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
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(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) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.post(
|
||||
`${nimbusUrl}/api/catalog/table-tags/`,
|
||||
body,
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
async deleteTableTags(id, body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.delete(
|
||||
`${nimbusUrl}/api/catalog/table-tags/${id}`,
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
async getTableRules(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(
|
||||
`${nimbusUrl}/api/catalog/table-rules/`,
|
||||
body,
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
async deleteTableRules(id, body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.delete(
|
||||
`${nimbusUrl}/api/catalog/table-rules/${id}`,
|
||||
);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
export { CatalogService };
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||
import { CreateDataAssetRequest } from '@dadosfera/protospack-v2/dist/lib/Catalog/interfaces/messages';
|
||||
|
||||
export class IRole {
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
@ApiProperty()
|
||||
id: string;
|
||||
}
|
||||
|
||||
export class IUser {
|
||||
@ApiProperty()
|
||||
username: string;
|
||||
@ApiProperty()
|
||||
id: string;
|
||||
}
|
||||
|
||||
export class IComment {
|
||||
@ApiProperty()
|
||||
id: number;
|
||||
@ApiProperty()
|
||||
message: string;
|
||||
@ApiProperty()
|
||||
created_at: string;
|
||||
@ApiProperty()
|
||||
username: string;
|
||||
}
|
||||
|
||||
export class IDataAsset {
|
||||
@ApiProperty()
|
||||
id: number;
|
||||
@ApiPropertyOptional()
|
||||
database_name?: string;
|
||||
@ApiPropertyOptional()
|
||||
table_name?: string;
|
||||
@ApiPropertyOptional()
|
||||
num_columns?: number;
|
||||
@ApiPropertyOptional()
|
||||
location?: string;
|
||||
@ApiPropertyOptional()
|
||||
created_time?: string;
|
||||
@ApiPropertyOptional()
|
||||
table_type?: string;
|
||||
@ApiPropertyOptional()
|
||||
size_in_bytes?: number;
|
||||
@ApiPropertyOptional()
|
||||
num_files?: number;
|
||||
@ApiPropertyOptional()
|
||||
data_encrypted?: string;
|
||||
@ApiPropertyOptional()
|
||||
num_rows?: number;
|
||||
@ApiPropertyOptional()
|
||||
display_name?: string;
|
||||
@ApiProperty()
|
||||
pipeline_id: string;
|
||||
@ApiProperty()
|
||||
user_id: string;
|
||||
@ApiProperty()
|
||||
description: string;
|
||||
@ApiProperty()
|
||||
data_asset_type: string;
|
||||
@ApiProperty()
|
||||
tags: string[];
|
||||
@ApiProperty()
|
||||
owner: string;
|
||||
@ApiProperty({ type: [IRole] })
|
||||
roles: IRole[];
|
||||
@ApiProperty({ type: [IUser] })
|
||||
users: IUser[];
|
||||
@ApiPropertyOptional()
|
||||
dashboard_id?: number;
|
||||
@ApiPropertyOptional()
|
||||
name?: string;
|
||||
@ApiPropertyOptional()
|
||||
parameters?: string[];
|
||||
@ApiPropertyOptional()
|
||||
embedding_params?: object;
|
||||
@ApiPropertyOptional()
|
||||
created_at?: string;
|
||||
@ApiPropertyOptional()
|
||||
updated_at?: string;
|
||||
@ApiProperty({ type: [IComment] })
|
||||
comments: IComment[];
|
||||
}
|
||||
|
||||
export class IOneDataAsset {
|
||||
@ApiProperty()
|
||||
data_asset: IDataAsset;
|
||||
}
|
||||
|
||||
export class IMakeAComment {
|
||||
@ApiProperty()
|
||||
message: string;
|
||||
}
|
||||
|
||||
export class IDeleteComment {
|
||||
@ApiProperty()
|
||||
comment: IComment;
|
||||
}
|
||||
|
||||
export class ICatalogAllResponse {
|
||||
@ApiProperty({ type: [IDataAsset] })
|
||||
data_assets: IDataAsset[];
|
||||
@ApiProperty()
|
||||
total: number;
|
||||
}
|
||||
|
||||
export class IData {
|
||||
@ApiProperty()
|
||||
var: number;
|
||||
@ApiProperty()
|
||||
date: string;
|
||||
@ApiProperty()
|
||||
last: number;
|
||||
@ApiProperty()
|
||||
maximum: number;
|
||||
@ApiProperty()
|
||||
minimum: number;
|
||||
@ApiProperty()
|
||||
day_opening: number;
|
||||
}
|
||||
|
||||
export class IUpdateDataRequest {
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
@ApiProperty()
|
||||
description: string;
|
||||
@ApiProperty()
|
||||
tags: string[];
|
||||
}
|
||||
|
||||
export class ICreateDataAsset implements CreateDataAssetRequest {
|
||||
@ApiProperty()
|
||||
display_name: string;
|
||||
@ApiProperty()
|
||||
description: string;
|
||||
@ApiProperty()
|
||||
data_asset_type: string;
|
||||
@ApiProperty()
|
||||
external_url: string;
|
||||
@ApiProperty()
|
||||
location: string;
|
||||
}
|
||||
|
||||
export class IPreview {
|
||||
@ApiProperty()
|
||||
id: string;
|
||||
@ApiProperty()
|
||||
database_name: string;
|
||||
@ApiProperty()
|
||||
table_name: string;
|
||||
@ApiProperty({ type: [IData] })
|
||||
data: IData[];
|
||||
}
|
||||
|
||||
export class IDocs {
|
||||
@ApiProperty()
|
||||
id: string;
|
||||
@ApiProperty()
|
||||
docs: string;
|
||||
@ApiProperty()
|
||||
updated_at: string;
|
||||
@ApiProperty()
|
||||
table_id: string;
|
||||
}
|
||||
|
||||
export class IColumnMetadata {
|
||||
@ApiProperty()
|
||||
id: string;
|
||||
@ApiProperty()
|
||||
table_name: string;
|
||||
@ApiProperty()
|
||||
column_name: string;
|
||||
@ApiProperty()
|
||||
data_type: string;
|
||||
@ApiProperty()
|
||||
missing_count: string;
|
||||
@ApiProperty()
|
||||
min: string;
|
||||
@ApiProperty()
|
||||
max: string;
|
||||
@ApiProperty()
|
||||
count: string;
|
||||
@ApiProperty()
|
||||
histogram: string;
|
||||
@ApiProperty()
|
||||
mean: string;
|
||||
@ApiProperty()
|
||||
median: string;
|
||||
@ApiProperty()
|
||||
missing_rate: string;
|
||||
@ApiProperty()
|
||||
stddev: string;
|
||||
@ApiProperty()
|
||||
unique_count: string;
|
||||
@ApiProperty()
|
||||
unique_rate: string;
|
||||
@ApiProperty()
|
||||
analyzer_rules: string[];
|
||||
@ApiProperty()
|
||||
version: string;
|
||||
}
|
||||
|
||||
export class IPreviewResponse {
|
||||
@ApiProperty()
|
||||
preview: IPreview;
|
||||
}
|
||||
|
||||
export class IDocsResponse {
|
||||
@ApiProperty()
|
||||
docs: IDocs;
|
||||
}
|
||||
|
||||
export class IColumnsMetadataResponse {
|
||||
@ApiProperty({ type: [IColumnMetadata] })
|
||||
columns_metadata: IColumnMetadata[];
|
||||
}
|
||||
@@ -71,27 +71,176 @@ export class ConnectorClientService implements OnModuleInit {
|
||||
);
|
||||
}
|
||||
|
||||
async uploadConnectorsFile(uploadFile) {
|
||||
const connectors = JSON.parse(uploadFile.file.buffer.toString('utf8'));
|
||||
|
||||
const body = connectors.map((connector) => {
|
||||
return JSON.stringify(connector);
|
||||
});
|
||||
|
||||
const request = {
|
||||
connectors: body,
|
||||
};
|
||||
|
||||
return lastValueFrom(
|
||||
this.connectorServiceWrite.RegisterMultipleConnectorsWithoutImage(
|
||||
request,
|
||||
),
|
||||
async uploadConnectorsFile(uploadFile: Express.Multer.File) {
|
||||
const res = await lastValueFrom(
|
||||
this.connectorServiceWrite.RegisterMultipleConnectorsWithoutImage({
|
||||
connectors: uploadFile.buffer,
|
||||
}),
|
||||
).catch((err) => {
|
||||
throw new HttpException(
|
||||
err.details,
|
||||
err.code === 6 ? HttpStatus.CONFLICT : 400,
|
||||
);
|
||||
});
|
||||
const responseParsed = JSON.parse(res.message);
|
||||
const connectorErrors = responseParsed.items
|
||||
.filter((i) => i.update._index === 'connectors' && 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 === 'connectors' && 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 === 'connectors' && 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 === 'connectors' && 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) {
|
||||
@@ -116,13 +265,13 @@ export class ConnectorClientService implements OnModuleInit {
|
||||
});
|
||||
}
|
||||
|
||||
async getConnectorDetails(plugin: string, language: string) {
|
||||
async getConnectorDetails(connectorId: string, language: string) {
|
||||
const meta = new Metadata();
|
||||
meta.add('Language', language);
|
||||
return lastValueFrom(
|
||||
this.connectorServiceRead.GetConnectorDetails(
|
||||
{
|
||||
plugin,
|
||||
plugin: connectorId,
|
||||
},
|
||||
meta,
|
||||
),
|
||||
|
||||
@@ -19,7 +19,6 @@ import { ApiBearerAuth, ApiConsumes, ApiTags } from '@nestjs/swagger';
|
||||
import { ConnectorClientService } from './client.service';
|
||||
import { AddTagDto } from './dtos/add-tag';
|
||||
import { CreateConnectorDto } from './dtos/create-connector';
|
||||
import { UploadConnectorsFileDto } from './dtos/create-multiple-connector';
|
||||
import { DeleteConnectorDto } from './dtos/delete-connector';
|
||||
import { GetAllDto } from './dtos/get-all';
|
||||
import { RemoveTagDto } from './dtos/remove-tag';
|
||||
@@ -85,14 +84,10 @@ export class ConnectorController {
|
||||
@RequireAllPermissions(PERMISSIONS_GROUPS.CONNECTORS.permissions.CREATE)
|
||||
@ApiConsumes('multipart/form-data')
|
||||
@UseInterceptors(FileInterceptor('file'))
|
||||
async uploadConnectorsFile(@UploadedFile() file: UploadConnectorsFileDto) {
|
||||
async uploadConnectorsFile(@UploadedFile() file: Express.Multer.File) {
|
||||
this.logger.info(`/upload`, 'Upload Connector Route');
|
||||
|
||||
const response = await this.connectorClientService.uploadConnectorsFile({
|
||||
file,
|
||||
});
|
||||
|
||||
return response;
|
||||
return await this.connectorClientService.uploadConnectorsFile(file);
|
||||
}
|
||||
|
||||
@Get()
|
||||
|
||||
@@ -16,12 +16,12 @@ export class DucClient {
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
url: process.env.DUC_URL,
|
||||
package: ProtoPackages.WritePackage,
|
||||
package: [ProtoPackages.WritePackage, ProtoPackages.ReadPackage],
|
||||
credentials:
|
||||
process.env.LOCAL_ENV || process.env.ENV === 'local'
|
||||
? undefined
|
||||
: credentials.createSsl(),
|
||||
protoPath: ProtoPaths.WriteFilePath,
|
||||
protoPath: [ProtoPaths.WriteFilePath, ProtoPaths.ReadFilePath],
|
||||
loader: {
|
||||
keepCase: true,
|
||||
enums: String,
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
Param,
|
||||
Patch,
|
||||
Post,
|
||||
UseFilters,
|
||||
} from '@nestjs/common';
|
||||
import { InputsService } from './inputs.service';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
@@ -26,8 +27,11 @@ import {
|
||||
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';
|
||||
import ErrorBuilder from 'src/utils/ErrorBuilder';
|
||||
import ErrorCodes from 'src/utils/errorCodes';
|
||||
import { GrpcToHttpExceptionFilter } from 'src/error/grpc-to-http-exception.filter';
|
||||
|
||||
@ApiTags('inputs')
|
||||
@ApiTags('Inputs')
|
||||
@Controller('inputs')
|
||||
@AuthenticateCondition((req, user) => {
|
||||
switch (req.method) {
|
||||
@@ -38,7 +42,9 @@ import { Info } from '@dadosfera/protospack-v2/dist/lib/Input/interfaces/entitie
|
||||
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.UPDATE.seqid,
|
||||
)
|
||||
);
|
||||
|
||||
default:
|
||||
@@ -49,10 +55,13 @@ import { Info } from '@dadosfera/protospack-v2/dist/lib/Input/interfaces/entitie
|
||||
user.permissions.includes(
|
||||
PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE.seqid,
|
||||
) ||
|
||||
user.permissions.includes(PERMISSIONS_GROUPS.PIPELINE.permissions.GET.seqid)
|
||||
user.permissions.includes(
|
||||
PERMISSIONS_GROUPS.PIPELINE.permissions.GET.seqid,
|
||||
)
|
||||
);
|
||||
}
|
||||
})
|
||||
@UseFilters(new GrpcToHttpExceptionFilter())
|
||||
export class InputsController {
|
||||
logger: DadosferaLogger;
|
||||
constructor(
|
||||
@@ -90,6 +99,7 @@ export class InputsController {
|
||||
@Post('/test-connection/get-columns')
|
||||
@ApiOkResponse({ type: TestConnectionGetColumnsRes })
|
||||
async getColumns(@Body() data: TestConnectionGetColumnsReq) {
|
||||
throw new ErrorBuilder(ErrorCodes.NOT_IMPLEMENTED);
|
||||
this.logger.info(
|
||||
`/test-connection/get-columns - ON TEST CONNECTION GET COLUMNS ROUTE`,
|
||||
{
|
||||
|
||||
@@ -72,17 +72,6 @@ export class InputsService {
|
||||
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(
|
||||
@@ -91,14 +80,6 @@ export class InputsService {
|
||||
|
||||
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(
|
||||
@@ -239,17 +220,13 @@ export class InputsService {
|
||||
}
|
||||
|
||||
async findOne(idRequest: IIdRequest) {
|
||||
try {
|
||||
const findOneInputResponse: any = await this.OLD_inputClient.findOne(
|
||||
idRequest,
|
||||
);
|
||||
findOneInputResponse.input = this.adjustInputPayload(
|
||||
findOneInputResponse.input,
|
||||
);
|
||||
return findOneInputResponse;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
const findOneInputResponse: any = await lastValueFrom(
|
||||
this.inputReadService.InputFindOne(idRequest),
|
||||
);
|
||||
findOneInputResponse.input = this.adjustInputPayload(
|
||||
findOneInputResponse.input,
|
||||
);
|
||||
return findOneInputResponse;
|
||||
}
|
||||
|
||||
async update(id: string, data, info: Info) {
|
||||
@@ -271,13 +248,7 @@ export class InputsService {
|
||||
}
|
||||
|
||||
async remove(idRequest: IIdRequest) {
|
||||
try {
|
||||
const removeInputResponse = await this.OLD_inputClient.remove(idRequest);
|
||||
|
||||
return removeInputResponse;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
return lastValueFrom(this.inputWriteService.InputRemove(idRequest));
|
||||
}
|
||||
|
||||
@Timeout(60000 * 10) // Timeout set for 10 minutes
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Body, Controller, Inject, Param, Post } from '@nestjs/common';
|
||||
import { init } from 'mixpanel';
|
||||
import { Authenticated } from 'src/authentication/authentication.decorator';
|
||||
import { RequestUser, User } from 'src/authentication/user.decorator';
|
||||
|
||||
@Authenticated()
|
||||
@Controller('trackEvent')
|
||||
export class MixpanelController {
|
||||
constructor(
|
||||
@Inject('MIXPANEL_TOKEN')
|
||||
private readonly mixpanelToken: string,
|
||||
) {}
|
||||
@Post(':id')
|
||||
async trackEvent(@Param('id') id, @Body() body, @User() user: RequestUser) {
|
||||
delete body.info;
|
||||
const mixpanel = init(this.mixpanelToken);
|
||||
|
||||
await mixpanel.people.set(user.username, {
|
||||
$name: user.username,
|
||||
$email: user.username,
|
||||
customer_name: user.customer_name,
|
||||
});
|
||||
|
||||
await mixpanel.track(id, {
|
||||
distinct_id: user.username,
|
||||
customer: user.customer_name,
|
||||
env: process.env.ENV,
|
||||
...body,
|
||||
});
|
||||
|
||||
return { id, body, user: user.username };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { getSecreteFromSecreteManager } from 'src/utils/SecretManager';
|
||||
import { MixpanelController } from './mixpanel.controller';
|
||||
|
||||
@Module({
|
||||
controllers: [MixpanelController],
|
||||
providers: [
|
||||
{
|
||||
provide: 'MIXPANEL_TOKEN',
|
||||
useValue: getSecreteFromSecreteManager(
|
||||
`${process.env.ENV}/root/mixpanel_token`,
|
||||
),
|
||||
},
|
||||
],
|
||||
})
|
||||
export class MixpanelModule {}
|
||||
@@ -19,17 +19,18 @@ import { RequestUser, User } from 'src/authentication/user.decorator';
|
||||
import {
|
||||
CreateNetworkConfigReq,
|
||||
CreateNetworkConfigRes,
|
||||
DeleteNetworkConfigRes,
|
||||
FindAllNetworkConfigsRes,
|
||||
UpdateNetworkConfigReq,
|
||||
UpdateNetworkConfigRes,
|
||||
} from './dto/network-config';
|
||||
import { FileInterceptor } from '@nestjs/platform-express';
|
||||
import { PERMISSIONS_GROUPS } from 'src/authentication/permissions.enum';
|
||||
import { RequireAllPermissions } from 'src/authentication/authentication.decorator';
|
||||
import {
|
||||
Authenticated,
|
||||
RequireAllPermissions,
|
||||
} from 'src/authentication/authentication.decorator';
|
||||
|
||||
const networkConfigPermissions = PERMISSIONS_GROUPS.NETWORK_CONFIG.permissions;
|
||||
@ApiTags('Network Config')
|
||||
@Authenticated()
|
||||
@Controller('network-config')
|
||||
export class NetworkConfigController {
|
||||
logger: any;
|
||||
|
||||
@@ -17,13 +17,13 @@ export class OauthController {
|
||||
switch (process.env.ENV) {
|
||||
case 'dev':
|
||||
case 'stg':
|
||||
this.redirectUrl = `https://app.${process.env.ENV}.dadosfera.ai/coletix/auth-callback`;
|
||||
this.redirectUrl = `https://app.${process.env.ENV}.dadosfera.ai/collect/auth-callback`;
|
||||
break;
|
||||
case 'prd':
|
||||
this.redirectUrl = `https://app.dadosfera.ai/coletix/auth-callback`;
|
||||
this.redirectUrl = `https://app.dadosfera.ai/collect/auth-callback`;
|
||||
break;
|
||||
default:
|
||||
this.redirectUrl = `http://localhost:4200/coletix/auth-callback`;
|
||||
this.redirectUrl = `http://localhost:4200/collect/auth-callback`;
|
||||
}
|
||||
}
|
||||
@Get('hubspot')
|
||||
|
||||
@@ -1,20 +1,15 @@
|
||||
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 { Authenticated } from 'src/authentication/authentication.decorator';
|
||||
import { 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',
|
||||
@@ -22,7 +17,6 @@ import { PermissionsService } from './permissions.service';
|
||||
required: false,
|
||||
description: 'Defaults to pt-br',
|
||||
})
|
||||
@Authenticated()
|
||||
export class PermissionsController {
|
||||
logger: DadosferaLogger;
|
||||
|
||||
|
||||
@@ -1,21 +1,9 @@
|
||||
import {
|
||||
BadRequestException,
|
||||
ConflictException,
|
||||
Inject,
|
||||
InternalServerErrorException,
|
||||
OnModuleInit,
|
||||
} from '@nestjs/common';
|
||||
import { ClientGrpc, Payload } from '@nestjs/microservices';
|
||||
import { ConflictException, Inject, OnModuleInit } from '@nestjs/common';
|
||||
import { ClientGrpc } 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 { IIdRequest } from './interfaces';
|
||||
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import { PipelinesClientConfiguration } from './pipelines-client';
|
||||
@@ -39,91 +27,6 @@ export class PipelinesClientService implements OnModuleInit {
|
||||
);
|
||||
}
|
||||
|
||||
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');
|
||||
|
||||
|
||||
@@ -1,22 +1,16 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Inject,
|
||||
Param,
|
||||
Post,
|
||||
Put,
|
||||
} from '@nestjs/common';
|
||||
import { Body, Controller, Get, Inject, Param, Post } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { AuthenticateCondition } from 'src/authentication/authentication.decorator';
|
||||
import {
|
||||
AuthenticateCondition,
|
||||
Authenticated,
|
||||
} from 'src/authentication/authentication.decorator';
|
||||
import { PERMISSIONS_GROUPS } from '../../authentication/permissions.enum';
|
||||
import { PipelinesService } from './pipelines.service';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import { RequestUser, User } from 'src/authentication/user.decorator';
|
||||
|
||||
@ApiTags('Pipelines')
|
||||
@Controller('pipelines')
|
||||
@Authenticated()
|
||||
@AuthenticateCondition((req, user) => {
|
||||
let action;
|
||||
|
||||
@@ -82,84 +76,4 @@ export class PipelinesController {
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Get(':id/:details')
|
||||
async getPipelineLogs(@Param() params) {
|
||||
const { id, details } = params;
|
||||
this.logger.info(
|
||||
process.env.DEV_URL + `/pipeline/${id} - ON GET PIPELINE LOGS ROUTE`,
|
||||
{},
|
||||
);
|
||||
|
||||
const response = await this.pipelineService.getPipelineLogsMessages(
|
||||
id,
|
||||
details,
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Post()
|
||||
async create(@Body() createPipelineDto) {
|
||||
this.logger.info(process.env.DEV_URL + `/pipelines ON CREATE ROUTE`);
|
||||
|
||||
const response = await this.pipelineService.create(createPipelineDto);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Get()
|
||||
async findAll(@User() user: RequestUser) {
|
||||
this.logger.info(process.env.DEV_URL + `/pipeline ON Find All ROUTE`, {
|
||||
user: user.user_id,
|
||||
customer: user.customer_id,
|
||||
});
|
||||
|
||||
const { customer_id, user_id, customer_name } = user;
|
||||
|
||||
const response = await this.pipelineService.findAll({
|
||||
customer_name,
|
||||
customer_id,
|
||||
user_id,
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Get('/:id')
|
||||
async findOne(@Body() data, @Param() params) {
|
||||
const { id } = params;
|
||||
this.logger.info(process.env.DEV_URL + `/pipeline/${id} ON Find One ROUTE`);
|
||||
|
||||
const response = await this.pipelineService.findOne({ id, ...data });
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Put(':id')
|
||||
async update(@Body() updatePipelineDto, @Param() params) {
|
||||
const { id } = params;
|
||||
const { info } = updatePipelineDto;
|
||||
delete updatePipelineDto.info;
|
||||
|
||||
this.logger.info(process.env.DEV_URL + `/pipeline/${id} ON UPDATE ROUTE`);
|
||||
|
||||
const response = await this.pipelineService.update(
|
||||
id,
|
||||
updatePipelineDto,
|
||||
info,
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
async delete(@Body() data, @Param() params) {
|
||||
const { id } = params;
|
||||
this.logger.info(process.env.DEV_URL + `/pipeline/${id} ON DELETE ROUTE`);
|
||||
|
||||
const response = await this.pipelineService.remove({ id, ...data });
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||
import { DecodeGrpcStruct } from 'protospack';
|
||||
import { Info } from 'protospack/dist/lib/interfaces';
|
||||
import { PipelinesClientService } from './client.service';
|
||||
import { IIdRequest } from './interfaces';
|
||||
import { objectCamelToSnake } from 'src/utils/CaseConverter';
|
||||
@@ -9,91 +7,6 @@ import { objectCamelToSnake } from 'src/utils/CaseConverter';
|
||||
export class PipelinesService {
|
||||
constructor(private pipelineClient: PipelinesClientService) {}
|
||||
|
||||
adjustPayload(payload) {
|
||||
if (payload.input?.input_generic) {
|
||||
payload.input = DecodeGrpcStruct(payload.input?.input_generic);
|
||||
} else {
|
||||
payload.input = payload.input?.input_s3 || payload.input?.input_jdbc;
|
||||
}
|
||||
}
|
||||
|
||||
async create(createPipelineDto) {
|
||||
const createPipelineResponse = await this.pipelineClient.create(
|
||||
createPipelineDto,
|
||||
);
|
||||
|
||||
const pipeline = objectCamelToSnake(createPipelineResponse);
|
||||
this.adjustPayload(pipeline.pipeline);
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
async findOne(data: IIdRequest) {
|
||||
try {
|
||||
const findOnePipelineResponse = await this.pipelineClient.findOne(data);
|
||||
|
||||
const pipeline = objectCamelToSnake(findOnePipelineResponse);
|
||||
this.adjustPayload(pipeline.pipeline);
|
||||
|
||||
return pipeline;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
async findAll(data) {
|
||||
try {
|
||||
const { pipelines } = await this.pipelineClient.findAll({
|
||||
info: data,
|
||||
});
|
||||
if (pipelines)
|
||||
pipelines.forEach((pipeline) => {
|
||||
this.adjustPayload(pipeline);
|
||||
});
|
||||
return { pipelines: pipelines || [] };
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
async update(id: string, data, info: Info) {
|
||||
try {
|
||||
const updatePipelineResponse = await this.pipelineClient.update({
|
||||
id,
|
||||
info,
|
||||
...data,
|
||||
});
|
||||
|
||||
const pipeline = objectCamelToSnake(updatePipelineResponse);
|
||||
this.adjustPayload(pipeline);
|
||||
|
||||
return pipeline;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
async remove(data: IIdRequest) {
|
||||
try {
|
||||
const removePipelineResponse = await this.pipelineClient.remove(data);
|
||||
|
||||
return removePipelineResponse;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
async getPipelineLogsMessages(id: string, details: string) {
|
||||
try {
|
||||
const pipelineLogsResponse =
|
||||
await this.pipelineClient.getPipelineLogsMessages({ id, details });
|
||||
|
||||
return objectCamelToSnake(pipelineLogsResponse);
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
async getPipelineStatus(data: IIdRequest) {
|
||||
try {
|
||||
const pipelineStatusResponse =
|
||||
|
||||
@@ -9,8 +9,15 @@ import {
|
||||
Put,
|
||||
Headers,
|
||||
Query,
|
||||
UseFilters,
|
||||
HttpCode,
|
||||
HttpStatus,
|
||||
} from '@nestjs/common';
|
||||
import { ApiCreatedResponse, ApiTags } from '@nestjs/swagger';
|
||||
import {
|
||||
ApiCreatedResponse,
|
||||
ApiNoContentResponse,
|
||||
ApiTags,
|
||||
} from '@nestjs/swagger';
|
||||
import { AuthenticateCondition } from 'src/authentication/authentication.decorator';
|
||||
import { PERMISSIONS_GROUPS } from '../../authentication/permissions.enum';
|
||||
import { PipelinesService } from './pipelines.service';
|
||||
@@ -21,7 +28,10 @@ import { PackTheMetadata } from 'src/utils/ PackTheMetadata';
|
||||
|
||||
import { PipelinesService as OldPipelineService } from 'src/modules/pipelines/pipelines.service';
|
||||
import { ICreatePipelineV2Req, IPipelineV2 } from './interfaces';
|
||||
@ApiTags('Pipelines')
|
||||
import { GrpcToHttpExceptionFilter } from 'src/error/grpc-to-http-exception.filter';
|
||||
|
||||
@UseFilters(new GrpcToHttpExceptionFilter())
|
||||
@ApiTags('PipelinesV2')
|
||||
@Controller('pipelinesV2')
|
||||
@AuthenticateCondition((req, user) => {
|
||||
let action;
|
||||
@@ -61,7 +71,7 @@ export class PipelinesController {
|
||||
@User() user: RequestUser,
|
||||
@Body() createPipelineDto: ICreatePipelineV2Req,
|
||||
) {
|
||||
this.logger.info(process.env.DEV_URL + `/pipelines ON CREATE ROUTE`);
|
||||
this.logger.info('PipelinesController - create', { user });
|
||||
if (!language) language = 'en-us';
|
||||
const { customer_id, customer_name, username, user_id } = user;
|
||||
const metadata = PackTheMetadata({
|
||||
@@ -86,10 +96,7 @@ export class PipelinesController {
|
||||
@Headers('Dadosfera-Lang') language,
|
||||
@Query() data,
|
||||
) {
|
||||
this.logger.info(process.env.DEV_URL + `/pipeline ON Find All ROUTE`, {
|
||||
user: user.user_id,
|
||||
customer: user.customer_name,
|
||||
});
|
||||
this.logger.info('PipelinesController - findAll', { user });
|
||||
|
||||
if (!language) language = 'en-us';
|
||||
|
||||
@@ -103,24 +110,34 @@ export class PipelinesController {
|
||||
});
|
||||
|
||||
const response = await this.pipelinesClientService.findAll(data, metadata);
|
||||
const oldResponse = await this.oldPipelinesService.findAll({
|
||||
customer_name,
|
||||
user_id,
|
||||
customer_id,
|
||||
});
|
||||
|
||||
return {
|
||||
pipelines: [...response.pipelines, ...oldResponse.pipelines],
|
||||
pipelines: [...response.pipelines],
|
||||
};
|
||||
}
|
||||
|
||||
@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(process.env.DEV_URL + `/pipeline/${id} ON Find One ROUTE`);
|
||||
this.logger.info('PipelinesController - findOne', { user });
|
||||
|
||||
if (!language) language = 'en-us';
|
||||
|
||||
const { customer_id, customer_name, user_id, username } = user;
|
||||
@@ -136,37 +153,36 @@ export class PipelinesController {
|
||||
const result = await this.pipelinesClientService
|
||||
.findOne({ id }, metadata)
|
||||
.then((res) => {
|
||||
//{pipeline:{tables: {tables: [], input_id: ''}}}
|
||||
let tables = JSON.parse(res.pipeline.config.tables);
|
||||
if (tables?.tables) tables = tables.tables;
|
||||
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),
|
||||
tables,
|
||||
},
|
||||
properties: res.pipeline.properties
|
||||
? JSON.parse(res.pipeline.properties)
|
||||
: {},
|
||||
});
|
||||
return res;
|
||||
})
|
||||
.catch(async (err) => {
|
||||
this.logger.error(err);
|
||||
return await this.oldPipelinesService.findOne({
|
||||
id,
|
||||
info: { customer_id, customer: customer_name, user_id },
|
||||
});
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
@Put('/:id')
|
||||
async update(@Body() updatePipelineDto, @Param('id') id) {
|
||||
async update(
|
||||
@Body() updatePipelineDto,
|
||||
@Param('id') id,
|
||||
@User() user: RequestUser,
|
||||
) {
|
||||
this.logger.info('PipelinesController - findOne', { user });
|
||||
const { info } = updatePipelineDto;
|
||||
delete updatePipelineDto.info;
|
||||
|
||||
this.logger.info(process.env.DEV_URL + `/pipeline/${id} ON UPDATE ROUTE`);
|
||||
|
||||
const response = await this.pipelinesClientService.update({
|
||||
...updatePipelineDto,
|
||||
info,
|
||||
@@ -177,12 +193,17 @@ export class PipelinesController {
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
async delete(@Body() data, @Param() params) {
|
||||
@ApiNoContentResponse()
|
||||
@HttpCode(HttpStatus.NO_CONTENT)
|
||||
async delete(@Param() params, @User() user: RequestUser) {
|
||||
this.logger.info('PipelinesController - delete', { user });
|
||||
const { id } = params;
|
||||
this.logger.info(process.env.DEV_URL + `/pipeline/${id} ON DELETE ROUTE`);
|
||||
|
||||
const response = await this.pipelinesClientService.remove({ id, ...data });
|
||||
|
||||
return response;
|
||||
const metadata = PackTheMetadata({
|
||||
customer_id: user.customer_id,
|
||||
customer_name: user.customer_name,
|
||||
user_id: user.user_id,
|
||||
});
|
||||
await this.pipelinesClientService.remove({ id, metadata, user });
|
||||
this.logger.info('PipelinesController - delete: OK');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ 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';
|
||||
import { InputsModule } from '../inputs/inputs.module';
|
||||
import { TransformationsModule } from '../transformations/transformations.module';
|
||||
|
||||
const client = new PipelinesClientConfiguration();
|
||||
|
||||
@@ -15,6 +18,9 @@ const client = new PipelinesClientConfiguration();
|
||||
imports: [
|
||||
ClientsModule.register([client.providerOptions]),
|
||||
OldPipelineModule,
|
||||
ConnectorModule,
|
||||
InputsModule,
|
||||
TransformationsModule,
|
||||
],
|
||||
controllers: [PipelinesController],
|
||||
providers: [PipelinesService, DadosferaLogger],
|
||||
|
||||
@@ -17,6 +17,12 @@ 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';
|
||||
import { InputsService } from '../inputs/inputs.service';
|
||||
import { RequestUser } from 'src/authentication/user.decorator';
|
||||
import { TransformationsService } from '../transformations/transformations.service';
|
||||
import { getObjValueFromPath } from 'src/utils/ObjValueFromPath';
|
||||
|
||||
export class PipelinesService implements OnModuleInit {
|
||||
logger: DadosferaLogger;
|
||||
@@ -27,6 +33,9 @@ export class PipelinesService implements OnModuleInit {
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
@Inject(PipelinesClientConfiguration.name)
|
||||
private readonly grpcClient: ClientGrpc,
|
||||
private readonly connectorService: ConnectorClientService,
|
||||
private readonly inputsService: InputsService,
|
||||
private readonly transformationsService: TransformationsService,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
@@ -125,10 +134,7 @@ export class PipelinesService implements OnModuleInit {
|
||||
|
||||
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;
|
||||
@@ -139,34 +145,91 @@ export class PipelinesService implements OnModuleInit {
|
||||
|
||||
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);
|
||||
});
|
||||
);
|
||||
this.logger.info('Done');
|
||||
|
||||
return updatePipelineResponse;
|
||||
}
|
||||
|
||||
async remove(data: Messages.PipelineV2RemoveRequest) {
|
||||
this.logger.info('PipelinesClientService - Remove');
|
||||
async remove(data: { id: string; metadata: Metadata; user: RequestUser }) {
|
||||
const { id, metadata, user } = data;
|
||||
const info = {
|
||||
user_id: user.user_id,
|
||||
customer_id: user.customer_id,
|
||||
customer: user.customer_name,
|
||||
};
|
||||
const { pipeline } = await lastValueFrom(
|
||||
this.pipelineReadService.PipelineV2FindOne({ id }, metadata),
|
||||
);
|
||||
await lastValueFrom(
|
||||
this.pipelineWriteService.PipelineV2Remove({ id }, metadata),
|
||||
);
|
||||
|
||||
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);
|
||||
//{pipeline:{tables: {tables: [], input_id: ''}}}
|
||||
const input = pipeline.config.tables
|
||||
? JSON.parse(pipeline.config.tables)
|
||||
: null;
|
||||
if (input)
|
||||
await this.inputsService
|
||||
.remove({
|
||||
id: input.input_id,
|
||||
info,
|
||||
})
|
||||
.catch((error) =>
|
||||
this.logger.error('Could not delete input', {
|
||||
data: { input, error },
|
||||
}),
|
||||
);
|
||||
|
||||
const transformations: { id: string }[] = pipeline.transformations
|
||||
? JSON.parse(pipeline.transformations)
|
||||
: null;
|
||||
if (transformations && transformations.length)
|
||||
for (const transformation of transformations) {
|
||||
await this.transformationsService
|
||||
.remove({
|
||||
id: transformation.id,
|
||||
info,
|
||||
})
|
||||
.catch((error) =>
|
||||
this.logger.error('Could not delete transformation', {
|
||||
data: { transformation, error },
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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 config_control of config_controls) {
|
||||
const path: string = config_control.name;
|
||||
const default_value = getObjValueFromPath({
|
||||
object: { properties: pipelineProperties },
|
||||
path,
|
||||
});
|
||||
if (default_value != undefined)
|
||||
config_control.default_value = default_value;
|
||||
}
|
||||
|
||||
return removePipelineResponse;
|
||||
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 {}
|
||||
@@ -53,8 +53,8 @@ import { LanguageEnum } from 'src/utils/languages.enum';
|
||||
required: false,
|
||||
description: 'Defaults to pt-br',
|
||||
})
|
||||
@UseFilters(new GrpcToHttpExceptionFilter())
|
||||
@Authenticated()
|
||||
@UseFilters(new GrpcToHttpExceptionFilter())
|
||||
@Controller('roles')
|
||||
export class RolesController {
|
||||
logger: DadosferaLogger;
|
||||
|
||||
@@ -17,6 +17,7 @@ import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
|
||||
import { GrpcToHttpExceptionFilter } from '../../error/grpc-to-http-exception.filter';
|
||||
import { RequestUser, User } from '../../authentication/user.decorator';
|
||||
import { Metadata } from '@grpc/grpc-js';
|
||||
|
||||
@ApiTags('TermsOfUse')
|
||||
@UseFilters(new GrpcToHttpExceptionFilter())
|
||||
@@ -33,10 +34,15 @@ export class TermsOfUseController {
|
||||
}
|
||||
|
||||
@Get('token')
|
||||
async getToken(@User({ required: true }) user: RequestUser) {
|
||||
async getToken(
|
||||
@User({ required: true }) user: RequestUser,
|
||||
@Headers('Dadosfera-Lang') language: string,
|
||||
) {
|
||||
this.logger.info('/terms-of-use - get token');
|
||||
const metadata = new Metadata();
|
||||
metadata.add('language', language || 'pt-br');
|
||||
|
||||
return this.termsOfUseClient.getToken({ userId: user.user_id });
|
||||
return this.termsOfUseClient.getToken({ userId: user.user_id }, metadata);
|
||||
}
|
||||
|
||||
@Post('accept')
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
TermsOfUseAcceptRequest,
|
||||
} from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/messages';
|
||||
import { DucClient } from '../duc/client.config';
|
||||
import { Metadata } from '@grpc/grpc-js';
|
||||
|
||||
@Injectable()
|
||||
export class TermsOfUseClientService implements OnModuleInit {
|
||||
@@ -31,8 +32,10 @@ export class TermsOfUseClientService implements OnModuleInit {
|
||||
);
|
||||
}
|
||||
|
||||
async getToken(data: TermsOfUseGetTokenRequest) {
|
||||
return lastValueFrom(this.termsOfUseService.TermsOfUseGetToken(data));
|
||||
async getToken(data: TermsOfUseGetTokenRequest, metadata: Metadata) {
|
||||
return lastValueFrom(
|
||||
this.termsOfUseService.TermsOfUseGetToken(data, metadata),
|
||||
);
|
||||
}
|
||||
|
||||
async accept(data: TermsOfUseAcceptRequest) {
|
||||
|
||||
@@ -11,34 +11,19 @@ import {
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { TransformationsClientService } from './client.service';
|
||||
import { IIdRequest } from './interfaces';
|
||||
import { AuthenticateCondition } from 'src/authentication/authentication.decorator';
|
||||
import {
|
||||
AuthenticateCondition,
|
||||
Authenticated,
|
||||
RequireSomePermission,
|
||||
} from 'src/authentication/authentication.decorator';
|
||||
import { PERMISSIONS_GROUPS } from '../../authentication/permissions.enum';
|
||||
import { TransformationsService } from './transformations.service';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import { RequestUser, User } from 'src/authentication/user.decorator';
|
||||
|
||||
const pipelinePermissions = PERMISSIONS_GROUPS.PIPELINE.permissions;
|
||||
@ApiTags('Transformations')
|
||||
@Controller('transformations')
|
||||
@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.TRANSFORMATIONS.permissions[action].seqid,
|
||||
);
|
||||
})
|
||||
@Authenticated()
|
||||
export class TransformationsController {
|
||||
logger: DadosferaLogger;
|
||||
constructor(
|
||||
@@ -50,6 +35,7 @@ export class TransformationsController {
|
||||
}
|
||||
|
||||
@Post()
|
||||
@RequireSomePermission(pipelinePermissions.CREATE, pipelinePermissions.UPDATE)
|
||||
async create(@Body() createTransformationDto) {
|
||||
this.logger.info(`/transformation - ON CREATE ROUTE`, {
|
||||
user: createTransformationDto.info.user_id,
|
||||
@@ -67,6 +53,7 @@ export class TransformationsController {
|
||||
}
|
||||
|
||||
@Get()
|
||||
@RequireSomePermission(pipelinePermissions.GET)
|
||||
async findAll(@Body() data: IIdRequest) {
|
||||
this.logger.info(`/transformation - ON Find All ROUTE`, {
|
||||
user: data.info.user_id,
|
||||
@@ -82,6 +69,7 @@ export class TransformationsController {
|
||||
}
|
||||
|
||||
@Get('/:id')
|
||||
@RequireSomePermission(pipelinePermissions.GET)
|
||||
async findOne(@Body() data, @Param() params) {
|
||||
const { id } = params;
|
||||
this.logger.info(`/transformation/${id} - ON Find One ROUTE`, {
|
||||
@@ -98,6 +86,7 @@ export class TransformationsController {
|
||||
}
|
||||
|
||||
@Put(':id')
|
||||
@RequireSomePermission(pipelinePermissions.CREATE, pipelinePermissions.UPDATE)
|
||||
async update(
|
||||
@User() user: RequestUser,
|
||||
@Body() updateTransformationDto,
|
||||
@@ -120,6 +109,7 @@ export class TransformationsController {
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
@RequireSomePermission(pipelinePermissions.CREATE, pipelinePermissions.UPDATE)
|
||||
async delete(@Body() data, @Param() params) {
|
||||
const { id } = params;
|
||||
this.logger.info(`/transformation/${id} - ON DELETE ROUTE`, {
|
||||
|
||||
@@ -55,7 +55,10 @@ export class UserNoRoles extends OmitType(User, ['roles']) {}
|
||||
export class UserNoRolesAndCustomer extends OmitType(UserNoRoles, [
|
||||
'customer',
|
||||
]) {}
|
||||
export class UserByCustomer extends OmitType(User, ['customer']) {}
|
||||
export class IUserByCustomer extends OmitType(User, ['customer']) {
|
||||
@ApiPropertyOptional()
|
||||
permissions?: string[];
|
||||
}
|
||||
|
||||
export class CreateUserReq {
|
||||
@ApiPropertyOptional()
|
||||
@@ -111,11 +114,11 @@ export class UpdateUserReq {
|
||||
|
||||
export class UpdateUserRes {
|
||||
@ApiProperty()
|
||||
user: UserByCustomer;
|
||||
user: IUserByCustomer;
|
||||
}
|
||||
export class GetAllUsersByCustomerIdRes {
|
||||
@ApiProperty({ type: [UserByCustomer] })
|
||||
users: UserByCustomer[];
|
||||
@ApiProperty({ type: [IUserByCustomer] })
|
||||
users: IUserByCustomer[];
|
||||
@ApiProperty()
|
||||
departments: string[];
|
||||
@ApiProperty()
|
||||
@@ -153,7 +156,7 @@ export class SetUserRolesReq {
|
||||
|
||||
export class SetUserRolesRes {
|
||||
@ApiProperty()
|
||||
user: UserByCustomer;
|
||||
user: IUserByCustomer;
|
||||
}
|
||||
|
||||
export class SearchUserRes extends GetAllUsersByCustomerIdRes {}
|
||||
|
||||
@@ -21,7 +21,10 @@ import {
|
||||
ApiTags,
|
||||
} from '@nestjs/swagger';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import { RequireAllPermissions } from 'src/authentication/authentication.decorator';
|
||||
import {
|
||||
Authenticated,
|
||||
RequireAllPermissions,
|
||||
} from 'src/authentication/authentication.decorator';
|
||||
import { PERMISSIONS_GROUPS } from 'src/authentication/permissions.enum';
|
||||
import { RequestUser, User } from 'src/authentication/user.decorator';
|
||||
import { GrpcToHttpExceptionFilter } from 'src/error/grpc-to-http-exception.filter';
|
||||
@@ -42,10 +45,12 @@ import {
|
||||
UnassignRoleToUserReq,
|
||||
UpdateUserReq,
|
||||
UpdateUserRes,
|
||||
UserByCustomer,
|
||||
IUserByCustomer,
|
||||
} from './dtos/entities';
|
||||
import { UsersService } from './users.service';
|
||||
import { Metadata } from '@grpc/grpc-js';
|
||||
import ErrorBuilder from 'src/utils/ErrorBuilder';
|
||||
import ErrorCodes from 'src/utils/errorCodes';
|
||||
|
||||
// TODO GET de hierarquias e do PATCH em usuário
|
||||
@ApiTags('Users')
|
||||
@@ -56,6 +61,7 @@ import { Metadata } from '@grpc/grpc-js';
|
||||
required: false,
|
||||
description: 'Defaults to pt-br',
|
||||
})
|
||||
@Authenticated()
|
||||
@UseFilters(GrpcToHttpExceptionFilter)
|
||||
export class UsersController {
|
||||
logger: DadosferaLogger;
|
||||
@@ -119,9 +125,8 @@ export class UsersController {
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@RequireAllPermissions(PERMISSIONS_GROUPS.USERS.permissions.ADMIN)
|
||||
@ApiOkResponse({
|
||||
type: UserByCustomer,
|
||||
type: IUserByCustomer,
|
||||
})
|
||||
async findOneById(
|
||||
@User() user: RequestUser,
|
||||
@@ -130,6 +135,14 @@ export class UsersController {
|
||||
) {
|
||||
this.logger.info('findOneById', { user });
|
||||
this.userService.setLanguage(language);
|
||||
if (
|
||||
id !== user.user_id &&
|
||||
!user.permissions.includes(
|
||||
PERMISSIONS_GROUPS.USERS.permissions.ADMIN.seqid,
|
||||
)
|
||||
) {
|
||||
throw new ErrorBuilder(ErrorCodes.AUTH.FORBIDDEN);
|
||||
}
|
||||
return await this.userService.findOneById(id);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
BatchCreateUserReq,
|
||||
CreateUserReq,
|
||||
Hierarchy,
|
||||
IUserByCustomer,
|
||||
SetUserRolesReq,
|
||||
UpdateUserReq,
|
||||
} from './dtos/entities';
|
||||
@@ -77,11 +78,24 @@ export class UsersService implements OnModuleInit {
|
||||
};
|
||||
}
|
||||
|
||||
async findOneById(id: string) {
|
||||
async findOneById(id: string): Promise<{ user: IUserByCustomer }> {
|
||||
const { user } = await lastValueFrom(
|
||||
this.usersClientService.UserFindOneById({ id }),
|
||||
);
|
||||
return { user: this.adjustUsersPayload([user])[0] };
|
||||
const res: { user: IUserByCustomer } = {
|
||||
user: this.adjustUsersPayload([user])[0],
|
||||
};
|
||||
const { permissions } = await lastValueFrom(
|
||||
this.usersClientService.GetUserPermissions({ id }),
|
||||
).catch((error) => {
|
||||
this.logger.error('UsersService.findOneById - GetUserPermissions', {
|
||||
error,
|
||||
});
|
||||
const permissions: string[] = [];
|
||||
return { permissions };
|
||||
});
|
||||
res.user.permissions = permissions;
|
||||
return res;
|
||||
}
|
||||
|
||||
async createUser(req: CreateUserReq, meta?: Metadata) {
|
||||
|
||||
@@ -248,14 +248,48 @@ export function EnrichErrorCode(code: string) {
|
||||
code,
|
||||
};
|
||||
|
||||
case ErrorCodes.PIPELINE.NOT_FOUND:
|
||||
return {
|
||||
statusCode: HttpStatus.NOT_FOUND,
|
||||
error: 'Não encontramos a pipeline solicitada',
|
||||
message:
|
||||
'Tente realizar a ação novamente. Caso o erro persista, entre em contato com o suporte',
|
||||
code,
|
||||
};
|
||||
|
||||
case ErrorCodes.PIPELINE.PLATFORM_NOT_FOUND:
|
||||
case ErrorCodes.PIPELINE.PLATFORM_BAD_REQUEST:
|
||||
case ErrorCodes.PIPELINE.PLATFORM_UNKNOWN:
|
||||
return {
|
||||
statusCode: HttpStatus.BAD_GATEWAY,
|
||||
error: 'Oops... Não foi possível realizar sua ação',
|
||||
message:
|
||||
'Houve um erro interno ao buscar por sua pipeline. Caso o erro persista, entre em contato com o suporte',
|
||||
code,
|
||||
};
|
||||
case ErrorCodes.INPUT.NOT_FOUND:
|
||||
return {
|
||||
statusCode: HttpStatus.NOT_FOUND,
|
||||
error: 'Oops... O recurso que você buscou não está disponível',
|
||||
message:
|
||||
'Não encontramos o recurso buscado. Caso o erro persista, entre em contato com o suporte',
|
||||
code,
|
||||
};
|
||||
case ErrorCodes.NOT_IMPLEMENTED:
|
||||
return {
|
||||
statusCode: HttpStatus.NOT_FOUND,
|
||||
error: 'Oops... O serviço que você está tentando acessar não existe!',
|
||||
message: 'Caso o erro persista, entre em contato com o suporte',
|
||||
code,
|
||||
};
|
||||
case ErrorCodes.INTERNAL:
|
||||
case ErrorCodes.UNKNOWN:
|
||||
default:
|
||||
return {
|
||||
statusCode: HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
error: 'Desconhecido',
|
||||
error: 'Oops... Não foi possível realizar sua ação',
|
||||
message:
|
||||
'Erro desconhecido. Tente novamente ou entre em contato com o suporte',
|
||||
'Ocorreu um erro desconhecido. Caso o erro persista, entre em contato com o suporte',
|
||||
code: ErrorCodes.UNKNOWN,
|
||||
details: code,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
export function getObjValueFromPath<T>(data: { object: T; path: string }): T {
|
||||
const { object, path } = data;
|
||||
const keys = path.split('.');
|
||||
|
||||
let value = JSON.parse(JSON.stringify(object));
|
||||
for (const key of keys) {
|
||||
if (value != undefined) value = value[key];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import {
|
||||
SecretsManagerClient,
|
||||
GetSecretValueCommand,
|
||||
} from '@aws-sdk/client-secrets-manager';
|
||||
|
||||
export async function getSecreteFromSecreteManager(path: string) {
|
||||
const secretsManagerClient = new SecretsManagerClient({});
|
||||
|
||||
const getSecretComand = new GetSecretValueCommand({
|
||||
SecretId: `${path}`,
|
||||
});
|
||||
const res = await secretsManagerClient
|
||||
.send(getSecretComand)
|
||||
.catch(() => null);
|
||||
|
||||
return res?.SecretString;
|
||||
}
|
||||
+16
-1
@@ -51,17 +51,32 @@ const CONNECTION_TEST = {
|
||||
BAD_REQUEST: 'CONNECTION_TEST.BAD_REQUEST',
|
||||
UNKNOWN: 'CONNECTION_TEST.UNKNOWN',
|
||||
};
|
||||
|
||||
const PIPELINE = {
|
||||
NOT_FOUND: 'PIPELINE.NOT_FOUND',
|
||||
PLATFORM_NOT_FOUND: 'PIPELINE.PLATFORM_NOT_FOUND',
|
||||
PLATFORM_BAD_REQUEST: 'PIPELINE.PLATFORM_BAD_REQUEST',
|
||||
PLATFORM_UNKNOWN: 'PIPELINE.PLATFORM_UNKNOWN',
|
||||
};
|
||||
const INPUT = {
|
||||
NOT_FOUND: 'INPUT.NOT_FOUND',
|
||||
};
|
||||
const TRANSFORMATION = {
|
||||
NOT_FOUND: 'TRANSFORMATION.NOT_FOUND',
|
||||
};
|
||||
const ErrorCodes = {
|
||||
UNKNOWN: 'UNKNOWN',
|
||||
RATE_LIMIT: 'RATE_LIMIT',
|
||||
INTERNAL: 'INTERNAL',
|
||||
NOT_IMPLEMENTED: 'NOT_IMPLEMENTED',
|
||||
AUTH,
|
||||
ROLE,
|
||||
TERMS_OF_USE,
|
||||
USER,
|
||||
CUSTOMER,
|
||||
CONNECTION_TEST,
|
||||
PIPELINE,
|
||||
INPUT,
|
||||
TRANSFORMATION,
|
||||
};
|
||||
|
||||
export default ErrorCodes;
|
||||
|
||||
File diff suppressed because one or more lines are too long
+1
-1
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
|
||||
"exclude": ["node_modules", "test", "dist", "**/*spec.ts", "jest.config.ts"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user