mirror of
https://github.com/dadosfera/maestro.git
synced 2026-09-04 13:44:49 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce0362217c | ||
|
|
9e0a58b4b7 | ||
|
|
3ddbfcebeb | ||
|
|
0eef0713df | ||
|
|
17d629b430 | ||
|
|
5362a99b24 | ||
|
|
1566efc490 | ||
|
|
89b571d7f8 | ||
|
|
7776d61f82 | ||
|
|
9bf7cc660e | ||
|
|
d6552678a8 | ||
|
|
a42ec164c3 | ||
|
|
6abc2595cb | ||
|
|
b850596d64 | ||
|
|
da3b7f3096 | ||
|
|
ff2b8fae6f | ||
|
|
4df23c917a | ||
|
|
6c3eef7181 | ||
|
|
072a9fee8e | ||
|
|
8c91551cdc | ||
|
|
668c5fe6a5 | ||
|
|
d057495b2e | ||
|
|
2f1c71eefe | ||
|
|
3bb014e714 | ||
|
|
2ff2aa049f | ||
|
|
f6c7420f59 | ||
|
|
abbe88f45b | ||
|
|
383741f48c | ||
|
|
ff663e7166 | ||
|
|
305daeeeab | ||
|
|
852ddbf88b | ||
|
|
4dfe6c3870 | ||
|
|
2710159a73 | ||
|
|
1ab5d49908 | ||
|
|
43372b5a0f | ||
|
|
0ac2dd2de7 | ||
|
|
0342386a76 | ||
|
|
28e55f8fd9 | ||
|
|
4e2e296442 | ||
|
|
d89573bc79 | ||
|
|
03ed4d88a0 | ||
|
|
329bbf2e4d | ||
|
|
ae069a0e00 | ||
|
|
d3bcbdc43c | ||
|
|
4e2e6787a4 | ||
|
|
50da33b766 | ||
|
|
bb72cfce45 | ||
|
|
03d17758ae | ||
|
|
b7e76a6d3f | ||
|
|
c920eb27b9 | ||
|
|
c25d2427c2 | ||
|
|
0f13d0c590 | ||
|
|
7781298e6e | ||
|
|
2c00d3249a | ||
|
|
cd7c7d538f | ||
|
|
e496d42776 | ||
|
|
a07247d538 | ||
|
|
153ba1a98b | ||
|
|
46519323f8 | ||
|
|
a51d52d68e | ||
|
|
555ff2eda9 | ||
|
|
5d1a54a720 | ||
|
|
8399a0e4c1 | ||
|
|
cf54cb0bc2 | ||
|
|
4eba099390 | ||
|
|
08fa269ce0 | ||
|
|
e52af6844b | ||
|
|
2344e4dba3 | ||
|
|
d686753f25 | ||
|
|
c1498f8f1b | ||
|
|
0b3cb581c4 | ||
|
|
97a6e05812 | ||
|
|
356d438404 | ||
|
|
cf870cff14 | ||
|
|
26c6a289eb | ||
|
|
8d27e42fcd | ||
|
|
c44e557b11 | ||
|
|
25d06ab4c5 | ||
|
|
31bb795d23 | ||
|
|
a2e25eb737 | ||
|
|
6be53bebaf | ||
|
|
741f009723 | ||
|
|
45477b5750 | ||
|
|
36de53dfd3 | ||
|
|
cd8fe2fbf6 | ||
|
|
c4a2bee69c | ||
|
|
e48d11153d | ||
|
|
c7e4de7d65 | ||
|
|
b2e7870cc5 | ||
|
|
1e239026a3 | ||
|
|
bc108d43e3 | ||
|
|
1c5b929c1b | ||
|
|
3e21c308f6 | ||
|
|
f4a5f91cbb | ||
|
|
c8aeb7f3db | ||
|
|
b9453b11cf | ||
|
|
a69752332e | ||
|
|
09c7cc79ee | ||
|
|
65f6f03e55 | ||
|
|
a54300f600 | ||
|
|
5ef85f79d3 | ||
|
|
a8a429977f | ||
|
|
692a9de0af | ||
|
|
7dc669ca44 | ||
|
|
e897da1ef0 | ||
|
|
b366e786ba | ||
|
|
24d56c7a58 | ||
|
|
d7f205901b | ||
|
|
7212c5249c | ||
|
|
827c7b1bf1 | ||
|
|
8d89b747b4 | ||
|
|
4f18328603 | ||
|
|
a68d312447 | ||
|
|
7f677f0376 | ||
|
|
bb2c0ab23e | ||
|
|
feec48114c | ||
|
|
7bee8d83a9 | ||
|
|
84b2dbd178 | ||
|
|
36706ff3dd | ||
|
|
0164e6978a | ||
|
|
7d371926f5 | ||
|
|
75e9e97f04 | ||
|
|
b5f58b99fd | ||
|
|
503293439f | ||
|
|
eed57ff039 | ||
|
|
ef2a24a0c3 | ||
|
|
8a31e11445 | ||
|
|
2013e97e20 | ||
|
|
dd271205ba | ||
|
|
a1f9f14897 | ||
|
|
b7efa2f58d | ||
|
|
395e36581d | ||
|
|
97a54f9267 | ||
|
|
00b0e00bd0 | ||
|
|
9188536161 | ||
|
|
1ae8151184 | ||
|
|
3d77980dd2 | ||
|
|
849b979e63 | ||
|
|
28580782b1 | ||
|
|
fc784e2d6d | ||
|
|
c997e91912 | ||
|
|
22f493d48a | ||
|
|
035213824b | ||
|
|
1ffa9ade51 | ||
|
|
c91aa57344 | ||
|
|
077a95cdbd | ||
|
|
f39108772b | ||
|
|
cdd8beee8f | ||
|
|
14331ed229 | ||
|
|
5f3db0cb43 | ||
|
|
28f304c47c | ||
|
|
0c1b62b2aa | ||
|
|
13f7e9d812 | ||
|
|
841dcfef06 | ||
|
|
f41ddc1483 | ||
|
|
0a2c7c0a38 | ||
|
|
87f4c17ca2 | ||
|
|
a89625c1e6 | ||
|
|
44211d5658 | ||
|
|
d4e11b1935 | ||
|
|
5c5e940cf7 | ||
|
|
2b162bd0a7 | ||
|
|
829f7611e2 | ||
|
|
b986cf3281 | ||
|
|
75c7602e13 | ||
|
|
710105a4a8 | ||
|
|
30b048f776 | ||
|
|
845b95b112 | ||
|
|
6d6b024884 | ||
|
|
a4282a0dc5 | ||
|
|
4672ecb6b3 | ||
|
|
6160107d75 | ||
|
|
589a1f9d51 | ||
|
|
cb929d9b60 | ||
|
|
678bebef7e | ||
|
|
b6d7d54f9c | ||
|
|
5df8b2834c | ||
|
|
76d9571f02 | ||
|
|
0c51014ec9 | ||
|
|
7f1d8e4b2a | ||
|
|
92b78ff19d | ||
|
|
1b328b9915 | ||
|
|
e653aeea3c | ||
|
|
b49633cbc2 | ||
|
|
4d956e55c6 | ||
|
|
735703bf3b | ||
|
|
93cdc3f030 | ||
|
|
12b8b5926c | ||
|
|
1643096d47 | ||
|
|
8a519ac217 | ||
|
|
ffa69a0cf5 | ||
|
|
7722e380e3 | ||
|
|
ecdc7b4eb6 | ||
|
|
7d14080ac1 | ||
|
|
7e7deba2ab | ||
|
|
e425e90eeb | ||
|
|
45f35b4e39 | ||
|
|
d450acd007 | ||
|
|
e9c1dfc320 | ||
|
|
67484cbef8 | ||
|
|
740be1d98b | ||
|
|
b9989d86c1 | ||
|
|
9b3a127f6a | ||
|
|
55028c4b83 | ||
|
|
7d5dee4b0c | ||
|
|
708bf2f585 | ||
|
|
1d53226540 | ||
|
|
5f6ae5d512 | ||
|
|
c51092260a | ||
|
|
3add8b026e | ||
|
|
42726b805b | ||
|
|
8d8c5c000e | ||
|
|
b7f608f246 | ||
|
|
e513689f4a | ||
|
|
761a00c6a6 | ||
|
|
ef9cff601f | ||
|
|
a3ba9c743f | ||
|
|
9dd3ec4579 | ||
|
|
8b19da9217 | ||
|
|
238de920dc | ||
|
|
fe1a426e2b | ||
|
|
1f85d3f502 | ||
|
|
c68207728b | ||
|
|
c431867814 | ||
|
|
ca7f9855b1 | ||
|
|
7a95ec537f | ||
|
|
25d99089db | ||
|
|
e336f31fda | ||
|
|
2bdb06494a | ||
|
|
f94416200a | ||
|
|
3bbd48894b | ||
|
|
1f1660cdf2 | ||
|
|
3a7f392e8b | ||
|
|
04584df44d | ||
|
|
26ec0b3dfb | ||
|
|
44d4b8e08c | ||
|
|
63fa756c9b | ||
|
|
91236dde86 | ||
|
|
a39ea091ee | ||
|
|
8787aa05c2 | ||
|
|
1523c6b4d1 | ||
|
|
e15a680b9f | ||
|
|
363bc8b350 | ||
|
|
2f8d9b9550 | ||
|
|
e729e1f0f4 | ||
|
|
a20ff87b27 | ||
|
|
abf5c71c08 | ||
|
|
6b991bce7d | ||
|
|
e007c2c49c |
@@ -0,0 +1,3 @@
|
||||
container_commands:
|
||||
01setup_swap:
|
||||
command: "bash .ebextensions/setup_swap.sh"
|
||||
@@ -0,0 +1,7 @@
|
||||
Resources:
|
||||
AWSEBAutoScalingLaunchConfiguration:
|
||||
Properties:
|
||||
MetadataOptions:
|
||||
HttpEndpoint: enabled
|
||||
HttpPutResponseHopLimit: 2
|
||||
HttpTokens: required
|
||||
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
SWAPFILE=/var/swapfile
|
||||
SWAP_MEGABYTES=1024
|
||||
|
||||
if [ -f $SWAPFILE ]; then
|
||||
echo "Swapfile $SWAPFILE found, assuming already setup"
|
||||
exit;
|
||||
fi
|
||||
|
||||
/bin/dd if=/dev/zero of=$SWAPFILE bs=1M count=$SWAP_MEGABYTES
|
||||
/bin/chmod 600 $SWAPFILE
|
||||
/sbin/mkswap $SWAPFILE
|
||||
/sbin/swapon $SWAPFILE
|
||||
@@ -0,0 +1,19 @@
|
||||
branch-defaults:
|
||||
alpha:
|
||||
environment: null
|
||||
global:
|
||||
application_name: maestro
|
||||
branch: null
|
||||
default_ec2_keyname: null
|
||||
default_platform: Docker running on 64bit Amazon Linux 2
|
||||
default_region: us-east-1
|
||||
include_git_submodules: true
|
||||
instance_profile: null
|
||||
platform_name: null
|
||||
platform_version: null
|
||||
profile: null
|
||||
repository: null
|
||||
sc: git
|
||||
workspace_type: Application
|
||||
deploy:
|
||||
artifact: deploy.zip
|
||||
@@ -0,0 +1,140 @@
|
||||
name: Deploy
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
environment:
|
||||
description: 'Deployment environment'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- dev
|
||||
- stg
|
||||
- prd
|
||||
|
||||
jobs:
|
||||
extract_environment:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
environment: ${{ steps.extract_environment.outputs.environment }}
|
||||
env:
|
||||
EVENT: ${{ github.event_name }}
|
||||
DEPLOY_ENV: ${{ github.event.inputs.environment }}
|
||||
steps:
|
||||
- name: Extract Environment
|
||||
run: |
|
||||
if [ ${EVENT} == "workflow_dispatch" ]; then
|
||||
echo "##[set-output name=environment;]$(echo ${DEPLOY_ENV})"
|
||||
elif [ ${GITHUB_REF} == "refs/heads/main" ]; then
|
||||
echo "##[set-output name=environment;]$(echo "prd")"
|
||||
fi
|
||||
id: extract_environment
|
||||
|
||||
semantic_release:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
#new_release_published: ${{ steps.semantic.outputs.last_release_version != steps.semantic.outputs.new_release_version }}
|
||||
new_release_published: ${{ steps.semantic.outputs.new_release_published }}
|
||||
#new_release_version: ${{ steps.semantic.outputs.new_release_version }}
|
||||
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
|
||||
|
||||
- if: github.event_name != 'workflow_dispatch'
|
||||
name: Semantic Release
|
||||
uses: cycjimmy/semantic-release-action@v2
|
||||
id: semantic
|
||||
with:
|
||||
semantic_version: 16
|
||||
extra_plugins: |
|
||||
conventional-changelog-eslint
|
||||
branches: |
|
||||
[
|
||||
'main'
|
||||
]
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
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: Printing stats
|
||||
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/}
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Update Pip
|
||||
run: |
|
||||
python3 -m pip install --upgrade pip
|
||||
|
||||
- name: Install Docker Compose
|
||||
run: |
|
||||
python3 -m pip install docker-compose --upgrade
|
||||
|
||||
- name: Install AWS CLI
|
||||
run: |
|
||||
python3 -m pip install awscli --upgrade
|
||||
|
||||
- name: Install AWS Elastic Beanstalk CLI
|
||||
run: |
|
||||
python3 -m pip install awsebcli --upgrade
|
||||
|
||||
- name: Configure AWS Region
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
id: aws
|
||||
with:
|
||||
aws-region: us-east-1
|
||||
|
||||
- name: Login to AWS ECR
|
||||
id: login_ecr
|
||||
uses: aws-actions/amazon-ecr-login@v1
|
||||
|
||||
- name: Build, Tag, and Push Image to AWS ECR
|
||||
env:
|
||||
ENV: ${{ needs.extract_environment.outputs.environment }}
|
||||
IMAGE_TAG: ${{ needs.semantic_release.outputs.new_release_version }}
|
||||
ACCOUNT_ID: ${{ steps.aws.outputs.aws-account-id }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
run: |
|
||||
docker-compose -f build.docker-compose.yml build --build-arg NPM_TOKEN=${NPM_TOKEN}
|
||||
docker-compose -f build.docker-compose.yml push
|
||||
|
||||
- name: Create ZIP file to Deploy AWS Beanstalk
|
||||
env:
|
||||
ENV: ${{ needs.extract_environment.outputs.environment }}
|
||||
IMAGE_TAG: ${{ needs.semantic_release.outputs.new_release_version }}
|
||||
ACCOUNT_ID: ${{ steps.aws.outputs.aws-account-id }}
|
||||
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
|
||||
zip deploy.zip docker-compose.yml -r .ebextensions
|
||||
|
||||
- name: Deploy AWS Beanstalk
|
||||
env:
|
||||
ENV: ${{ needs.extract_environment.outputs.environment }}
|
||||
AWS_REGION: us-east-1
|
||||
APP_NAME: ${{ github.event.repository.name }}
|
||||
run: |
|
||||
eb use $APP_NAME-$ENV
|
||||
echo -e "deploy:\n artifact: deploy.zip" >> .elasticbeanstalk/config.yml
|
||||
eb deploy
|
||||
|
||||
- name: Remove Docker's Trash
|
||||
if: always()
|
||||
run: |
|
||||
docker system prune --volumes -a -f
|
||||
docker system df
|
||||
@@ -1,111 +0,0 @@
|
||||
name: Deploy
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- alpha
|
||||
- beta
|
||||
- main
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: self-hosted
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Semantic Release
|
||||
uses: cycjimmy/semantic-release-action@v2
|
||||
id: semantic
|
||||
with:
|
||||
semantic_version: 16
|
||||
extra_plugins: |
|
||||
@saithodev/semantic-release-backmerge
|
||||
conventional-changelog-eslint
|
||||
branches: |
|
||||
[
|
||||
'main',
|
||||
{
|
||||
name: 'alpha',
|
||||
prerelease: true
|
||||
},
|
||||
{
|
||||
name: 'beta',
|
||||
prerelease: true
|
||||
}
|
||||
]
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Update Pip
|
||||
if: steps.semantic.outputs.new_release_published == 'true'
|
||||
run: |
|
||||
python3 -m pip install --upgrade pip
|
||||
|
||||
- name: Install Docker Compose
|
||||
if: steps.semantic.outputs.new_release_published == 'true'
|
||||
run: |
|
||||
python3 -m pip install docker-compose --upgrade
|
||||
|
||||
- name: Install AWS CLI
|
||||
if: steps.semantic.outputs.new_release_published == 'true'
|
||||
run: |
|
||||
python3 -m pip install awscli --upgrade
|
||||
|
||||
- name: Install AWS Elastic Beanstalk CLI
|
||||
if: steps.semantic.outputs.new_release_published == 'true'
|
||||
run: |
|
||||
python3 -m pip install awsebcli --upgrade
|
||||
|
||||
- name: Configure AWS Region
|
||||
if: steps.semantic.outputs.new_release_published == 'true'
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-region: us-east-1
|
||||
|
||||
- name: Extract Environment
|
||||
if: steps.semantic.outputs.new_release_published == 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
if [ ${GITHUB_REF} == "refs/heads/main" ]; then
|
||||
echo "##[set-output name=result;]$(echo "production")"
|
||||
else
|
||||
echo "##[set-output name=result;]$(echo ${GITHUB_REF#refs/heads/})"
|
||||
fi
|
||||
id: extract_environment
|
||||
|
||||
- name: Login to AWS ECR
|
||||
if: steps.semantic.outputs.new_release_published == 'true'
|
||||
id: login_ecr
|
||||
uses: aws-actions/amazon-ecr-login@v1
|
||||
|
||||
- name: Build, Tag, and Push Image to AWS ECR
|
||||
if: steps.semantic.outputs.new_release_published == 'true'
|
||||
env:
|
||||
ENV: ${{ steps.extract_environment.outputs.result }}
|
||||
IMAGE_TAG: ${{ steps.semantic.outputs.new_release_version }}
|
||||
run: |
|
||||
docker-compose -f build.docker-compose.yml build
|
||||
docker-compose -f build.docker-compose.yml push
|
||||
|
||||
- name: Create ZIP file to Deploy AWS Beanstalk
|
||||
if: steps.semantic.outputs.new_release_published == 'true'
|
||||
env:
|
||||
ENV: ${{ steps.extract_environment.outputs.result }}
|
||||
IMAGE_TAG: ${{ steps.semantic.outputs.new_release_version }}
|
||||
run: |
|
||||
sed -i -e "s/\${ENV}/$ENV/g" docker-compose.yml
|
||||
sed -i -e "s/\${IMAGE_TAG}/$IMAGE_TAG/g" docker-compose.yml
|
||||
zip deploy.zip docker-compose.yml
|
||||
|
||||
- name: Deploy AWS Beanstalk
|
||||
if: steps.semantic.outputs.new_release_published == 'true'
|
||||
env:
|
||||
ENV: ${{ steps.extract_environment.outputs.result }}
|
||||
AWS_REGION: us-east-1
|
||||
APP_NAME: maestro
|
||||
run: |
|
||||
[[ -d .elasticbeanstalk/ ]] && rm -R .elasticbeanstalk/
|
||||
printf "1\nn" | eb init $APP_NAME --region $AWS_REGION
|
||||
eb use $APP_NAME-$ENV
|
||||
echo -e "deploy:\n artifact: deploy.zip" >> .elasticbeanstalk/config.yml
|
||||
eb deploy
|
||||
@@ -21,14 +21,26 @@ jobs:
|
||||
env:
|
||||
ENV: test
|
||||
IMAGE_TAG: test
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
run: |
|
||||
export ENV=test
|
||||
docker-compose -f build.docker-compose.yml build
|
||||
export IMAGE_TAG=test
|
||||
export ACCOUNT_ID=test
|
||||
docker-compose -f build.docker-compose.yml build --build-arg NPM_TOKEN=${NPM_TOKEN}
|
||||
|
||||
- name: Run Test
|
||||
env:
|
||||
ENV: test
|
||||
IMAGE_TAG: test
|
||||
ACCOUNT_ID: test
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
run: |
|
||||
export ENV=test
|
||||
docker-compose run --rm --entrypoint="npm run test" maestro
|
||||
export IMAGE_TAG=test
|
||||
docker-compose -f build.docker-compose.yml run -e NPM_TOKEN=${NPM_TOKEN} --rm --entrypoint="npm run test" maestro
|
||||
|
||||
- name: Remove Docker's Trash
|
||||
if: always()
|
||||
run: |
|
||||
docker system prune --volumes -a -f
|
||||
docker system df
|
||||
|
||||
+2
-5
@@ -29,7 +29,7 @@ lerna-debug.log*
|
||||
|
||||
# IDE - VSCode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
#!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
@@ -37,7 +37,4 @@ lerna-debug.log*
|
||||
# Ignore .env files
|
||||
*.env
|
||||
|
||||
# Elastic Beanstalk Files
|
||||
.elasticbeanstalk/*
|
||||
!.elasticbeanstalk/*.cfg.yml
|
||||
!.elasticbeanstalk/*.global.yml
|
||||
.env
|
||||
+12
-18
@@ -5,18 +5,18 @@
|
||||
{
|
||||
"preset": "eslint",
|
||||
"releaseRules": [
|
||||
{ "tag": "Fix", "release": "patch" },
|
||||
{ "tag": "Feat", "release": "minor" },
|
||||
{ "tag": "Update", "release": "minor" },
|
||||
{ "tag": "Upgrade", "release": "minor" },
|
||||
{ "tag": "Breaking", "release": "major" },
|
||||
{ "tag": "Docs", "release": "patch" },
|
||||
{ "tag": "Chore", "release": "minor" },
|
||||
{ "tag": "Build", "release": "patch" },
|
||||
{ "tag": "Refactor", "release": "minor" },
|
||||
{ "tag": "Test", "release": "patch" },
|
||||
{ "tag": "FIX", "release": "patch" },
|
||||
{ "tag": "FEAT", "release": "minor" },
|
||||
{ "tag": "UPDATE", "release": "minor" },
|
||||
{ "tag": "UPGRADE", "release": "minor" },
|
||||
{ "tag": "BREAKING", "release": "major" },
|
||||
{ "tag": "DOCS", "release": "patch" },
|
||||
{ "tag": "CHORE", "release": "minor" },
|
||||
{ "tag": "BUILD", "release": "patch" },
|
||||
{ "tag": "REFACTOR", "release": "minor" },
|
||||
{ "tag": "TEST", "release": "patch" },
|
||||
{ "tag": "CI", "release": "patch" },
|
||||
{ "tag": "Perf", "release": "minor" }
|
||||
{ "tag": "PERF", "release": "minor" }
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -26,13 +26,7 @@
|
||||
"preset": "eslint"
|
||||
}
|
||||
],
|
||||
[
|
||||
"@saithodev/semantic-release-backmerge",
|
||||
{
|
||||
"branches": ["alpha", "beta"],
|
||||
"backmergeStrategy": "merge"
|
||||
}
|
||||
],
|
||||
"@semantic-release/npm",
|
||||
"@semantic-release/github"
|
||||
]
|
||||
}
|
||||
|
||||
+8
-3
@@ -1,12 +1,17 @@
|
||||
FROM node:14 as packages
|
||||
FROM node:18.3.0-alpine3.15 as packages
|
||||
WORKDIR /packages
|
||||
ARG NPM_TOKEN
|
||||
COPY package.json .
|
||||
COPY package-lock.json .
|
||||
COPY .npmrc .
|
||||
RUN npm install
|
||||
RUN rm -f ./.npmrc
|
||||
|
||||
FROM node:alpine
|
||||
FROM node:14.15.4-alpine3.12
|
||||
WORKDIR /app
|
||||
COPY . /app/
|
||||
ARG NPM_TOKEN
|
||||
COPY --from=packages /packages/node_modules /app/node_modules
|
||||
RUN npm run build
|
||||
EXPOSE 3333
|
||||
ENTRYPOINT npm run start
|
||||
ENTRYPOINT npm run start
|
||||
@@ -1,73 +1,50 @@
|
||||
# Maestro
|
||||
<p align="center">
|
||||
<a href="http://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo_text.svg" width="320" alt="Nest Logo" /></a>
|
||||
</p>
|
||||
<image src="./assets/maestro.svg" style="width:10rem">
|
||||
<h1 align="center">Maestro</h1>
|
||||
</p>
|
||||
This is the Dadosfera´s gateway repository, it´s responsable for the communication between frontend application and Dadosfera´s mirosservices.
|
||||
|
||||
[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
|
||||
[circleci-url]: https://circleci.com/gh/nestjs/nest
|
||||
## 💻 Requirements
|
||||
|
||||
<p align="center">A progressive <a href="http://nodejs.org" target="_blank">Node.js</a> framework for building efficient and scalable server-side applications.</p>
|
||||
<p align="center">
|
||||
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
|
||||
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
|
||||
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/dm/@nestjs/common.svg" alt="NPM Downloads" /></a>
|
||||
<a href="https://circleci.com/gh/nestjs/nest" target="_blank"><img src="https://img.shields.io/circleci/build/github/nestjs/nest/master" alt="CircleCI" /></a>
|
||||
<a href="https://coveralls.io/github/nestjs/nest?branch=master" target="_blank"><img src="https://coveralls.io/repos/github/nestjs/nest/badge.svg?branch=master#9" alt="Coverage" /></a>
|
||||
<a href="https://discord.gg/G7Qnnhy" target="_blank"><img src="https://img.shields.io/badge/discord-online-brightgreen.svg" alt="Discord"/></a>
|
||||
<a href="https://opencollective.com/nest#backer" target="_blank"><img src="https://opencollective.com/nest/backers/badge.svg" alt="Backers on Open Collective" /></a>
|
||||
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://opencollective.com/nest/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
|
||||
<a href="https://paypal.me/kamilmysliwiec" target="_blank"><img src="https://img.shields.io/badge/Donate-PayPal-ff3f59.svg"/></a>
|
||||
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://img.shields.io/badge/Support%20us-Open%20Collective-41B883.svg" alt="Support us"></a>
|
||||
<a href="https://twitter.com/nestframework" target="_blank"><img src="https://img.shields.io/twitter/follow/nestframework.svg?style=social&label=Follow"></a>
|
||||
</p>
|
||||
<!--[](https://opencollective.com/nest#backer)
|
||||
[](https://opencollective.com/nest#sponsor)-->
|
||||
Before you start, make sure you have done the following steps:
|
||||
|
||||
## Description
|
||||
* Installed Nodejs version 16.14.2
|
||||
* Installed latest NPM version
|
||||
|
||||
[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
$ npm install
|
||||
## 🚀 Installing Maestro
|
||||
|
||||
First of all clone the repository:
|
||||
* SSH:
|
||||
```
|
||||
git clone git@github.com:dadosfera/maestro.git
|
||||
```
|
||||
* HTTPS:
|
||||
```
|
||||
git clone git@github.com:dadosfera/maestro.git
|
||||
```
|
||||
|
||||
## Running the app
|
||||
## Enviroment variables
|
||||
|
||||
```bash
|
||||
# development
|
||||
$ npm run start
|
||||
Here is a list of enviroment variables needed in order to run the application correctly.
|
||||
|
||||
# watch mode
|
||||
$ npm run start:dev
|
||||
|
||||
# production mode
|
||||
$ npm run start:prod
|
||||
```
|
||||
ENV=
|
||||
DUC_URL=
|
||||
INFACTORY_URL=
|
||||
TRFACTORY_URL=
|
||||
OTFACTORY_URL=
|
||||
PIFACTORY_URL=
|
||||
JWT_PRIVATE_KEY=
|
||||
AWS_IDENTITY_POOL_ID=
|
||||
```
|
||||
|
||||
## Test
|
||||
## Running Maestro
|
||||
|
||||
```bash
|
||||
# unit tests
|
||||
$ npm run test
|
||||
|
||||
# e2e tests
|
||||
$ npm run test:e2e
|
||||
|
||||
# test coverage
|
||||
$ npm run test:cov
|
||||
In order to run Maestro just run the following command:
|
||||
```
|
||||
|
||||
## Support
|
||||
|
||||
Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
|
||||
|
||||
## Stay in touch
|
||||
|
||||
- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
|
||||
- Website - [https://nestjs.com](https://nestjs.com/)
|
||||
- Twitter - [@nestframework](https://twitter.com/nestframework)
|
||||
|
||||
## License
|
||||
|
||||
Nest is [MIT licensed](LICENSE).
|
||||
npm run start:dev
|
||||
```
|
||||
If everything is fine the Maestro will start and be ready to receive HTTP requests
|
||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 13 KiB |
@@ -2,4 +2,4 @@ version: "3.8"
|
||||
services:
|
||||
maestro:
|
||||
build: .
|
||||
image: 468720548566.dkr.ecr.us-east-1.amazonaws.com/microservices/maestro_${ENV}:${IMAGE_TAG}
|
||||
image: ${ACCOUNT_ID}.dkr.ecr.us-east-1.amazonaws.com/microservices/maestro_${ENV}:${IMAGE_TAG}
|
||||
|
||||
+3
-1
@@ -1,11 +1,13 @@
|
||||
version: "3.8"
|
||||
services:
|
||||
maestro:
|
||||
image: 468720548566.dkr.ecr.us-east-1.amazonaws.com/microservices/maestro_${ENV}:${IMAGE_TAG}
|
||||
image: ${ACCOUNT_ID}.dkr.ecr.us-east-1.amazonaws.com/microservices/maestro_${ENV}:${IMAGE_TAG}
|
||||
container_name: maestro
|
||||
restart: always
|
||||
ports:
|
||||
- 3333:3333
|
||||
env_file:
|
||||
- .env
|
||||
|
||||
node_exporter:
|
||||
image: prom/node-exporter:v1.3.1
|
||||
|
||||
+7
-2
@@ -2,7 +2,12 @@
|
||||
"collection": "@nestjs/schematics",
|
||||
"sourceRoot": "src",
|
||||
"compilerOptions": {
|
||||
"assets": ["**/*.proto"],
|
||||
"assets": [
|
||||
"**/*.proto"
|
||||
],
|
||||
"plugins": [
|
||||
"@nestjs/swagger"
|
||||
],
|
||||
"watchAssets": true
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+13150
-2154
File diff suppressed because it is too large
Load Diff
+41
-24
@@ -5,6 +5,9 @@
|
||||
"author": "",
|
||||
"private": true,
|
||||
"license": "UNLICENSED",
|
||||
"engines": {
|
||||
"node": "18.3.0"
|
||||
},
|
||||
"scripts": {
|
||||
"prebuild": "rimraf dist",
|
||||
"build": "nest build",
|
||||
@@ -21,48 +24,62 @@
|
||||
"test:e2e": "jest --config ./test/jest-e2e.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@grpc/grpc-js": "^1.5.0",
|
||||
"@aws-sdk/client-secrets-manager": "^3.112.0",
|
||||
"@grpc/grpc-js": "^1.5.10",
|
||||
"@grpc/proto-loader": "^0.6.9",
|
||||
"@nestjs/common": "^8.0.0",
|
||||
"@nestjs/core": "^8.0.0",
|
||||
"@nestjs/common": "^8.4.3",
|
||||
"@nestjs/config": "^1.2.1",
|
||||
"@nestjs/core": "^8.4.3",
|
||||
"@nestjs/mapped-types": "*",
|
||||
"@nestjs/microservices": "^8.2.4",
|
||||
"@nestjs/platform-express": "^8.0.0",
|
||||
"@nestjs/swagger": "^5.1.5",
|
||||
"@nestjs/microservices": "^8.4.3",
|
||||
"@nestjs/passport": "^8.2.2",
|
||||
"@nestjs/platform-express": "^8.4.3",
|
||||
"@nestjs/schedule": "^1.1.0",
|
||||
"@nestjs/swagger": "^5.2.1",
|
||||
"@victorradael/protospack": "2.5.0",
|
||||
"@victorradael/protospack-v2": "1.1.1",
|
||||
"axios": "^0.25.0",
|
||||
"cron-parser": "^4.4.0",
|
||||
"dotenv": "^14.2.0",
|
||||
"grpc": "^1.24.11",
|
||||
"helmet": "^5.0.2",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"jwk-to-pem": "^2.0.5",
|
||||
"passport": "^0.6.0",
|
||||
"passport-hubspot": "^0.1.0",
|
||||
"passport-hubspot-oauth2": "^1.0.3",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"rxjs": "^7.2.0",
|
||||
"rxjs": "^7.5.5",
|
||||
"swagger-ui-express": "^4.3.0"
|
||||
},
|
||||
"overrides": {
|
||||
"multer": "1.4.5-lts.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/cli": "^8.0.0",
|
||||
"@nestjs/schematics": "^8.0.0",
|
||||
"@nestjs/testing": "^8.0.0",
|
||||
"@nestjs/cli": "^8.2.4",
|
||||
"@nestjs/schematics": "^8.0.8",
|
||||
"@nestjs/testing": "^8.4.3",
|
||||
"@types/express": "^4.17.13",
|
||||
"@types/jest": "27.0.2",
|
||||
"@types/jsonwebtoken": "^8.5.8",
|
||||
"@types/jwk-to-pem": "^2.0.1",
|
||||
"@types/node": "^16.0.0",
|
||||
"@types/supertest": "^2.0.11",
|
||||
"@typescript-eslint/eslint-plugin": "^5.0.0",
|
||||
"@typescript-eslint/parser": "^5.0.0",
|
||||
"eslint": "^8.0.1",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"@types/node": "^16.11.26",
|
||||
"@types/supertest": "^2.0.12",
|
||||
"@typescript-eslint/eslint-plugin": "^5.17.0",
|
||||
"@typescript-eslint/parser": "^5.17.0",
|
||||
"eslint": "^8.12.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"jest": "^27.2.5",
|
||||
"prettier": "^2.3.2",
|
||||
"jest": "^27.5.1",
|
||||
"nock": "^13.2.4",
|
||||
"prettier": "^2.6.1",
|
||||
"source-map-support": "^0.5.20",
|
||||
"supertest": "^6.1.3",
|
||||
"ts-jest": "^27.0.3",
|
||||
"ts-loader": "^9.2.3",
|
||||
"ts-node": "^10.0.0",
|
||||
"tsconfig-paths": "^3.10.1",
|
||||
"typescript": "^4.3.5"
|
||||
"ts-jest": "^27.1.4",
|
||||
"ts-loader": "^9.2.7",
|
||||
"ts-node": "^10.7.0",
|
||||
"tsconfig-paths": "^3.14.1",
|
||||
"typescript": "^4.6.3"
|
||||
},
|
||||
"jest": {
|
||||
"moduleFileExtensions": [
|
||||
|
||||
+100
-40
@@ -1,44 +1,104 @@
|
||||
import { MiddlewareConsumer, Module, NestModule, RequestMethod } from '@nestjs/common';
|
||||
import { InputGrpcClientModule } from './inputs/input-grpc-client.module';
|
||||
import { UsersGrpcClientModule } from './users-grpc-client/users-grpc-client.module';
|
||||
import { OutputsModule } from './outputs/outputs.module';
|
||||
import { EnrichmentModule } from './enrichment/enrichment.module';
|
||||
import { TransformationsModule } from './transformations/transformations.module';
|
||||
import { PipelinesModule } from './pipelines/pipelines.module';
|
||||
import { RestInputsModule } from './rest/rest-inputs/rest-inputs.module';
|
||||
import { RestOutputsModule } from './rest/rest-outputs/rest-outputs.module';
|
||||
import { RestEnrichmentsModule } from './rest/rest-enrichments/rest-enrichments.module';
|
||||
import { RestTransformationsModule } from './rest/rest-transformations/rest-transformations.module';
|
||||
import { RestPipelinesModule } from './rest/rest-pipelines/rest-pipelines.module';
|
||||
import { RestUserModule } from './rest/rest-user/rest-user.module';
|
||||
import { RestFactoryModule } from './rest/rest-factory/rest-factory.module';
|
||||
import { LoggerMiddleware } from './middlewares/authentication';
|
||||
import { RestInputsController } from './rest/rest-inputs/rest-inputs.controller';
|
||||
import { RestOutputsController } from './rest/rest-outputs/rest-outputs.controller';
|
||||
import { RestTransformationsController } from './rest/rest-transformations/rest-transformations.controller';
|
||||
import { RestPipelinesController } from './rest/rest-pipelines/rest-pipelines.controller';
|
||||
import { RestEnrichmentsController } from './rest/rest-enrichments/rest-enrichments.controller';
|
||||
import { RestFactoryController } from './rest/rest-factory/rest-factory.controller';
|
||||
import { HealthModule } from './health/health.module';
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ClientsModule } from '@nestjs/microservices';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
|
||||
import { InputsController } from './modules/inputs/inputs.controller';
|
||||
import { TransformationsController } from './modules/transformations/transformations.controller';
|
||||
import { OutputsController } from './modules/outputs/outputs.controllers';
|
||||
import { PipelinesController } from './modules/pipelines/pipelines.controller';
|
||||
import { AuthController } from './modules/auth/auth.controller';
|
||||
import { HealthController } from './modules/health/health.controller';
|
||||
|
||||
import { InputsService } from './modules/inputs/inputs.service';
|
||||
import { TransformationsService } from './modules/transformations/transformations.service';
|
||||
import { OutputsService } from './modules/outputs/outputs.service';
|
||||
import { PipelinesService } from './modules/pipelines/pipelines.service';
|
||||
import { HealthService } from './modules/health/health.service';
|
||||
|
||||
import { AuthClientService } from './clients/auth/client.service';
|
||||
import { InputsClientService } from './clients/inputs/client.service';
|
||||
import { TransformationsClientService } from './clients/transformations/client.service';
|
||||
import { OutputsClientService } from './clients/outputs/client.service';
|
||||
import { PipelinesClientService } from './clients/pipelines/client.service';
|
||||
import { PermissionsClientService } from './clients/permissions/client.service';
|
||||
|
||||
import { OutputsClientConfiguration } from './clients/outputs/client.config';
|
||||
import { TransformationsClientConfiguration } from './clients/transformations/client.config';
|
||||
import { DucClient } from './clients/duc/client.config';
|
||||
import { InputsClientConfiguration } from './clients/inputs/client.config';
|
||||
import { PipelinesClientConfiguration } from './clients/pipelines/client.config';
|
||||
import { CatalogController } from './modules/catalog/catalog.controller';
|
||||
import { CatalogService } from './modules/catalog/catalog.service';
|
||||
import { HubspotStrategy } from './modules/oauth/passport-strategies/hubspot';
|
||||
import { OauthController } from './modules/oauth/oauth.controller';
|
||||
import { getOauthSecrets } from './utils/OauthSecrets';
|
||||
import { AuthenticationGuard } from './authentication/authentication.guard';
|
||||
import { APP_GUARD } from '@nestjs/core';
|
||||
|
||||
const ducClient = new DucClient();
|
||||
const inputClient = new InputsClientConfiguration();
|
||||
const outputClient = new OutputsClientConfiguration();
|
||||
const pipelineClient = new PipelinesClientConfiguration();
|
||||
const transformationClient = new TransformationsClientConfiguration();
|
||||
|
||||
@Module({
|
||||
controllers: [
|
||||
InputsController,
|
||||
TransformationsController,
|
||||
OutputsController,
|
||||
PipelinesController,
|
||||
AuthController,
|
||||
HealthController,
|
||||
CatalogController,
|
||||
OauthController,
|
||||
],
|
||||
providers: [
|
||||
{ provide: 'OAUTH_SECRETS', useValue: getOauthSecrets() },
|
||||
InputsService,
|
||||
TransformationsService,
|
||||
OutputsService,
|
||||
PipelinesService,
|
||||
HealthService,
|
||||
InputsClientService,
|
||||
TransformationsClientService,
|
||||
OutputsClientService,
|
||||
PipelinesClientService,
|
||||
AuthClientService,
|
||||
PermissionsClientService,
|
||||
CatalogService,
|
||||
HubspotStrategy,
|
||||
{
|
||||
provide: APP_GUARD,
|
||||
useClass: AuthenticationGuard,
|
||||
},
|
||||
],
|
||||
imports: [
|
||||
RestInputsModule, RestOutputsModule, RestEnrichmentsModule, RestTransformationsModule, RestPipelinesModule, RestUserModule, RestFactoryModule, HealthModule,
|
||||
// InputGrpcClientModule,
|
||||
//OutputsModule,
|
||||
//EnrichmentModule,
|
||||
//TransformationsModule,
|
||||
//PipelinesModule
|
||||
ConfigModule.forRoot({
|
||||
isGlobal: true,
|
||||
}),
|
||||
|
||||
ClientsModule.register([
|
||||
{
|
||||
name: 'INPUTS_PACKAGE',
|
||||
...inputClient.config(),
|
||||
},
|
||||
{
|
||||
name: 'TRANSFORMATIONS_PACKAGE',
|
||||
...transformationClient.config(),
|
||||
},
|
||||
{
|
||||
name: 'OUTPUTS_PACKAGE',
|
||||
...outputClient.config(),
|
||||
},
|
||||
{
|
||||
name: 'DUC_PACKAGE',
|
||||
...ducClient.config(),
|
||||
},
|
||||
{
|
||||
name: 'PIPELINES_PACKAGE',
|
||||
...pipelineClient.config(),
|
||||
},
|
||||
]),
|
||||
],
|
||||
controllers: [],
|
||||
providers: [],
|
||||
})
|
||||
export class AppModule implements NestModule{
|
||||
|
||||
configure(consumer: MiddlewareConsumer) {
|
||||
consumer
|
||||
.apply(LoggerMiddleware)
|
||||
.forRoutes(RestInputsController,RestOutputsController,RestTransformationsController,RestPipelinesController,RestEnrichmentsController,RestFactoryController)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
export class AppModule {}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { SetMetadata, applyDecorators } from '@nestjs/common';
|
||||
import { Request } from 'express';
|
||||
import { Permission } from './permissions.enum';
|
||||
|
||||
export const PERMISSIONS_KEY = '__PERMISSIONS__';
|
||||
export const MUST_BE_AUTHENTICATED_KEY = '__MUST_BE_AUTHENTICATED__';
|
||||
export const CUSTOM_AUTHENTICATION_FUNCTION_KEY =
|
||||
'__CUSTOM_AUTHENTICATION_FUNCTION__';
|
||||
|
||||
export type AuthenticationFunction = (req: Request, user: any) => boolean;
|
||||
|
||||
export function RequirePermissions(...permissions: Permission[]) {
|
||||
return applyDecorators(
|
||||
SetMetadata(PERMISSIONS_KEY, permissions),
|
||||
SetMetadata(MUST_BE_AUTHENTICATED_KEY, true),
|
||||
);
|
||||
}
|
||||
|
||||
export function AuthenticateCondition(func: AuthenticationFunction) {
|
||||
return applyDecorators(
|
||||
SetMetadata(CUSTOM_AUTHENTICATION_FUNCTION_KEY, func),
|
||||
SetMetadata(MUST_BE_AUTHENTICATED_KEY, true),
|
||||
);
|
||||
}
|
||||
|
||||
export function Authenticated() {
|
||||
return SetMetadata(MUST_BE_AUTHENTICATED_KEY, true);
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
import {
|
||||
Injectable,
|
||||
CanActivate,
|
||||
OnApplicationBootstrap,
|
||||
ExecutionContext,
|
||||
Logger,
|
||||
} from '@nestjs/common';
|
||||
import { Reflector } from '@nestjs/core';
|
||||
import assert from 'assert';
|
||||
import jwt from 'jsonwebtoken';
|
||||
|
||||
import { AuthClientService } from '../clients/auth/client.service';
|
||||
import { Permission } from './permissions.enum';
|
||||
import {
|
||||
AuthenticationFunction,
|
||||
PERMISSIONS_KEY,
|
||||
CUSTOM_AUTHENTICATION_FUNCTION_KEY,
|
||||
MUST_BE_AUTHENTICATED_KEY,
|
||||
} from './authentication.decorator';
|
||||
import ErrorBuilder from '../utils/ErrorBuilder';
|
||||
import ErrorCodes from '../utils/errorCodes';
|
||||
|
||||
@Injectable()
|
||||
export class AuthenticationGuard
|
||||
implements CanActivate, OnApplicationBootstrap
|
||||
{
|
||||
private readonly logger = new Logger(AuthenticationGuard.name);
|
||||
|
||||
pems: Map<string, string>;
|
||||
|
||||
constructor(
|
||||
private reflector: Reflector,
|
||||
private authClient: AuthClientService,
|
||||
) {
|
||||
this.pems = new Map();
|
||||
}
|
||||
|
||||
async onApplicationBootstrap() {
|
||||
return this.loadDucJWKS();
|
||||
}
|
||||
|
||||
async loadDucJWKS() {
|
||||
const { keys } = await this.authClient.getPublicKeys();
|
||||
|
||||
keys.forEach((key) => {
|
||||
this.pems.set(key.kid, key.pem);
|
||||
});
|
||||
}
|
||||
|
||||
canActivate(ctx: ExecutionContext): boolean {
|
||||
const requiredPermissions = this.reflector.getAllAndOverride<Permission[]>(
|
||||
PERMISSIONS_KEY,
|
||||
[ctx.getHandler(), ctx.getClass()],
|
||||
);
|
||||
const customAuthenticationFunction =
|
||||
this.reflector.getAllAndOverride<AuthenticationFunction>(
|
||||
CUSTOM_AUTHENTICATION_FUNCTION_KEY,
|
||||
[ctx.getHandler(), ctx.getClass()],
|
||||
);
|
||||
const mustBeAuthenticated = this.reflector.getAllAndOverride<boolean>(
|
||||
MUST_BE_AUTHENTICATED_KEY,
|
||||
[ctx.getHandler(), ctx.getClass()],
|
||||
);
|
||||
|
||||
const request = ctx.switchToHttp().getRequest();
|
||||
const accessToken = this.verifyToken(request, mustBeAuthenticated);
|
||||
|
||||
if (!accessToken) {
|
||||
// couldn't load valid token
|
||||
|
||||
if (!mustBeAuthenticated) {
|
||||
// no need to be authenticated
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new ErrorBuilder(ErrorCodes.AUTH.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
if (
|
||||
typeof customAuthenticationFunction === 'function' &&
|
||||
!customAuthenticationFunction(request, request.user)
|
||||
) {
|
||||
// custom authentication function forbidden this request
|
||||
throw new ErrorBuilder(ErrorCodes.AUTH.FORBIDDEN);
|
||||
}
|
||||
|
||||
if (
|
||||
Array.isArray(requiredPermissions) &&
|
||||
requiredPermissions.length > 0 &&
|
||||
!this.matchPermissions(requiredPermissions, accessToken.permissions)
|
||||
) {
|
||||
// couldn't match permissions
|
||||
throw new ErrorBuilder(ErrorCodes.AUTH.FORBIDDEN);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private verifyToken(request, mustBeAuthenticated: boolean) {
|
||||
const accessToken = request.get('Authorization');
|
||||
let accessTokenPayload;
|
||||
|
||||
// If the user isn't authenticated, an error will occurr anywhere here.
|
||||
// Fancy error avoidance isn't performed by purpose, such as avoiding to access null values.
|
||||
try {
|
||||
const accessTokenDecoded: any = jwt.decode(accessToken, {
|
||||
complete: true,
|
||||
});
|
||||
|
||||
/*assert(
|
||||
accessTokenDecoded.payload.iss === 'duc',
|
||||
'token should be issued by DUC',
|
||||
);*/
|
||||
|
||||
assert(
|
||||
accessTokenDecoded.payload.token_use === 'access',
|
||||
'should be an access token',
|
||||
);
|
||||
|
||||
const { kid } = accessTokenDecoded.header;
|
||||
const pemValue: string = this.pems.get(kid);
|
||||
|
||||
jwt.verify(accessToken, pemValue);
|
||||
accessTokenPayload = accessTokenDecoded.payload;
|
||||
} catch (err) {
|
||||
// log errors if authentication is required
|
||||
if (mustBeAuthenticated) {
|
||||
this.logger.log('Unable to verify duc access token\n' + err.stack);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
request.accessTokenPayload = accessTokenPayload;
|
||||
request.user = {
|
||||
user_id: accessTokenPayload.user_id,
|
||||
username: accessTokenPayload.username,
|
||||
permissions: accessTokenPayload.permissions,
|
||||
customer_id: accessTokenPayload.customer_id,
|
||||
customer_name: accessTokenPayload.customer_name,
|
||||
customer_tier: accessTokenPayload.customer_tier,
|
||||
};
|
||||
// TODO: for backwards compatibility. remove in the future
|
||||
request.body.info = {
|
||||
user_id: accessTokenPayload.user_id,
|
||||
customer_id: accessTokenPayload.customer_id,
|
||||
customer: accessTokenPayload.customer_name,
|
||||
customer_tier: accessTokenPayload.customer_tier,
|
||||
};
|
||||
|
||||
return accessTokenPayload;
|
||||
}
|
||||
|
||||
private matchPermissions(
|
||||
requiredPermissions: Permission[],
|
||||
userPermissions: number[],
|
||||
) {
|
||||
return requiredPermissions.some((permission) =>
|
||||
userPermissions.includes(permission.seqid),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
import { Logger } from '@nestjs/common';
|
||||
import assert from 'assert';
|
||||
|
||||
const logger = new Logger();
|
||||
|
||||
export enum PermissionUsages {
|
||||
PUBLIC = 'public',
|
||||
INTERNAL = 'internal',
|
||||
}
|
||||
|
||||
export interface Permission {
|
||||
seqid: number;
|
||||
claim: string;
|
||||
usage: PermissionUsages;
|
||||
}
|
||||
|
||||
/*
|
||||
- like field numbers in gRPC, avoid to change (or reuse previously used) seqids once its deployed to DUC
|
||||
- it is possible to update claim and usage, not seqid
|
||||
*/
|
||||
|
||||
/*export const Permissions: {
|
||||
[P in keyof any]: { [Q in keyof any]: Permission };
|
||||
} = {*/
|
||||
export const Permissions = {
|
||||
AUTH: {
|
||||
CREATE: {
|
||||
seqid: 18,
|
||||
claim: 'POST /auth',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
},
|
||||
|
||||
PIPELINE: {
|
||||
CREATE: {
|
||||
seqid: 23,
|
||||
claim: 'POST /pipelines',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
GET: {
|
||||
seqid: 13,
|
||||
claim: 'GET /pipelines',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
UPDATE: {
|
||||
seqid: 29,
|
||||
claim: 'PUT /pipelines',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
DELETE: {
|
||||
seqid: 5,
|
||||
claim: 'DELETE /pipelines',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
},
|
||||
|
||||
INPUT: {
|
||||
CREATE: {
|
||||
seqid: 21,
|
||||
claim: 'POST /inputs',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
GET: {
|
||||
seqid: 9,
|
||||
claim: 'GET /inputs',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
UPDATE: {
|
||||
seqid: 27,
|
||||
claim: 'PUT /inputs',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
UPDATE_PARTIAL: {
|
||||
seqid: 17,
|
||||
claim: 'PATCH /inputs',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
DELETE: {
|
||||
seqid: 3,
|
||||
claim: 'DELETE /inputs',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
GET_ENTITIES: {
|
||||
seqid: 10,
|
||||
claim: 'GET /inputs/available-entities',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
},
|
||||
|
||||
OUTPUT: {
|
||||
CREATE: {
|
||||
seqid: 22,
|
||||
claim: 'POST /outputs',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
GET: {
|
||||
seqid: 12,
|
||||
claim: 'GET /outputs',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
UPDATE: {
|
||||
seqid: 28,
|
||||
claim: 'PUT /outputs',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
DELETE: {
|
||||
seqid: 4,
|
||||
claim: 'DELETE /outputs',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
},
|
||||
|
||||
TRANSFORMATIONS: {
|
||||
CREATE: {
|
||||
seqid: 24,
|
||||
claim: 'POST /transformations',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
GET: {
|
||||
seqid: 15,
|
||||
claim: 'GET /transformations',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
UPDATE: {
|
||||
seqid: 30,
|
||||
claim: 'PUT /transformations',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
DELETE: {
|
||||
seqid: 6,
|
||||
claim: 'DELETE /transformations',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
},
|
||||
|
||||
CATALOG: {
|
||||
CREATE: {
|
||||
seqid: 19,
|
||||
claim: 'POST /catalog',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
GET: {
|
||||
seqid: 7,
|
||||
claim: 'GET /catalog',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
UPDATE: {
|
||||
seqid: 25,
|
||||
claim: 'PUT /catalog',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
DELETE: {
|
||||
seqid: 1,
|
||||
claim: 'DELETE /catalog',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
},
|
||||
|
||||
CONNECTORS: {
|
||||
CREATE: {
|
||||
seqid: 20,
|
||||
claim: 'POST /connectors',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
GET: {
|
||||
seqid: 8,
|
||||
claim: 'GET /connectors',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
UPDATE: {
|
||||
seqid: 26,
|
||||
claim: 'PUT /connectors',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
DELETE: {
|
||||
seqid: 2,
|
||||
claim: 'DELETE /connectors',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
},
|
||||
|
||||
SNOWFLAKE: {
|
||||
OPEN: {
|
||||
seqid: 14,
|
||||
claim: 'GET /snowflake',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
},
|
||||
|
||||
ZENDESK: {
|
||||
OPEN: {
|
||||
seqid: 16,
|
||||
claim: 'GET /zendesk',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
},
|
||||
|
||||
METABASE: {
|
||||
OPEN: {
|
||||
seqid: 11,
|
||||
claim: 'GET /metabase',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
},
|
||||
|
||||
ORCHEST: {
|
||||
INTELLIGENCE: {
|
||||
seqid: 31,
|
||||
claim: 'intelligence:open',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
APP_BUILDER: {
|
||||
seqid: 32,
|
||||
claim: 'app-builder:open',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
MACHINE_LEARNING: {
|
||||
seqid: 33,
|
||||
claim: 'machine-learning:open',
|
||||
usage: PermissionUsages.PUBLIC,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// traverses the object searching for duplicate seqids or claims (executes at runtime)
|
||||
let nextAvailableSeqid = 0;
|
||||
const seqids = Object.values(Permissions).flatMap((namespace) =>
|
||||
Object.values(namespace).map(({ seqid }) => seqid),
|
||||
);
|
||||
const claims = Object.values(Permissions).flatMap((namespace) =>
|
||||
Object.values(namespace).map(({ claim }) => claim),
|
||||
);
|
||||
Object.values(Permissions).map((namespace) =>
|
||||
Object.values(namespace).map(({ seqid, claim }) => {
|
||||
const seqidsCount = seqids.filter((x) => x === seqid).length;
|
||||
assert(seqidsCount === 1, `seqid ${seqid} count is not 1`);
|
||||
|
||||
const claimsCount = claims.filter((x) => x === claim).length;
|
||||
assert(claimsCount === 1, `claim '${claim}' count is not 1`);
|
||||
nextAvailableSeqid = Math.max(nextAvailableSeqid, seqid);
|
||||
}),
|
||||
);
|
||||
|
||||
logger.log(`next available seqid ${nextAvailableSeqid + 1}`);
|
||||
@@ -0,0 +1,23 @@
|
||||
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
|
||||
|
||||
import ErrorBuilder from '../utils/ErrorBuilder';
|
||||
import ErrorCodes from '../utils/errorCodes';
|
||||
|
||||
export interface RequestUser {
|
||||
user_id: string;
|
||||
username: string;
|
||||
permissions: string;
|
||||
customer_id: string;
|
||||
customer_name: string;
|
||||
customer_tier: string;
|
||||
}
|
||||
|
||||
export const User = createParamDecorator((data: any, ctx: ExecutionContext) => {
|
||||
const request = ctx.switchToHttp().getRequest();
|
||||
|
||||
if (!request.user && data?.required) {
|
||||
throw new ErrorBuilder(ErrorCodes.AUTH.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
return request.user;
|
||||
});
|
||||
@@ -0,0 +1,150 @@
|
||||
import { Logger, OnModuleInit, Inject } from '@nestjs/common';
|
||||
import { ClientGrpc } from '@nestjs/microservices';
|
||||
|
||||
import { ProtoServices } from '@victorradael/protospack-v2/dist/lib/Duc';
|
||||
import { AuthProtoService as AuthServiceInterface } from '@victorradael/protospack-v2/dist/lib/Duc/interfaces/write-service';
|
||||
import {
|
||||
AuthGetPublicKeysResponse,
|
||||
AuthSignInRequest,
|
||||
AuthSignInResponse,
|
||||
AuthRefreshAccessTokenRequest,
|
||||
AuthRefreshAccessTokenResponse,
|
||||
AuthEnableTotpMfaRequest,
|
||||
AuthEnableTotpMfaResponse,
|
||||
AuthDisableTotpMfaRequest,
|
||||
AuthDisableTotpMfaResponse,
|
||||
AuthDismissTotpMfaRequest,
|
||||
AuthDismissTotpMfaResponse,
|
||||
AuthVerifyTotpMfaRequest,
|
||||
AuthVerifyTotpMfaResponse,
|
||||
AuthChangePasswordRequest,
|
||||
AuthChangePasswordResponse,
|
||||
AuthResetPasswordRequest,
|
||||
AuthResetPasswordResponse,
|
||||
AuthVerifyResetPasswordCodeRequest,
|
||||
AuthVerifyResetPasswordCodeResponse,
|
||||
AuthConfirmResetPasswordRequest,
|
||||
AuthConfirmResetPasswordResponse,
|
||||
} from '@victorradael/protospack-v2/dist/lib/Duc/interfaces/messages';
|
||||
|
||||
import grpcHandler from '../../utils/grpcHandler';
|
||||
|
||||
export class AuthClientService implements OnModuleInit {
|
||||
private readonly logger = new Logger(AuthClientService.name);
|
||||
|
||||
private authService: AuthServiceInterface;
|
||||
constructor(@Inject('DUC_PACKAGE') private readonly grpcClient: ClientGrpc) {}
|
||||
|
||||
onModuleInit() {
|
||||
this.authService = this.grpcClient.getService<AuthServiceInterface>(
|
||||
ProtoServices.AuthProtoService,
|
||||
);
|
||||
}
|
||||
|
||||
async getPublicKeys() {
|
||||
this.logger.log('GetPublicKeys');
|
||||
|
||||
return grpcHandler<AuthGetPublicKeysResponse>(
|
||||
this.authService.AuthGetPublicKeys({}),
|
||||
);
|
||||
}
|
||||
|
||||
async signIn({ username, password, totp }: AuthSignInRequest) {
|
||||
this.logger.log('SignIn');
|
||||
|
||||
return grpcHandler<AuthSignInResponse>(
|
||||
this.authService.AuthSignIn({ username, password, totp }),
|
||||
);
|
||||
}
|
||||
|
||||
async refreshAccessToken({ refreshToken }: AuthRefreshAccessTokenRequest) {
|
||||
this.logger.log('RefreshAccessToken');
|
||||
|
||||
return grpcHandler<AuthRefreshAccessTokenResponse>(
|
||||
this.authService.AuthRefreshAccessToken({ refreshToken }),
|
||||
);
|
||||
}
|
||||
|
||||
async changePassword({
|
||||
accessToken,
|
||||
oldPassword,
|
||||
newPassword,
|
||||
}: AuthChangePasswordRequest) {
|
||||
this.logger.log('ChangePassword');
|
||||
|
||||
return grpcHandler<AuthChangePasswordResponse>(
|
||||
this.authService.AuthChangePassword({
|
||||
accessToken,
|
||||
oldPassword,
|
||||
newPassword,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
async resetPassword({ username }: AuthResetPasswordRequest) {
|
||||
this.logger.log('resetPassword');
|
||||
|
||||
return grpcHandler<AuthResetPasswordResponse>(
|
||||
this.authService.AuthResetPassword({ username }),
|
||||
);
|
||||
}
|
||||
|
||||
async verifyResetPasswordCode({
|
||||
username,
|
||||
code,
|
||||
}: AuthVerifyResetPasswordCodeRequest) {
|
||||
this.logger.log('verifyResetPasswordCode');
|
||||
|
||||
return grpcHandler<AuthVerifyResetPasswordCodeResponse>(
|
||||
this.authService.AuthVerifyResetPasswordCode({ username, code }),
|
||||
);
|
||||
}
|
||||
|
||||
async confirmResetPassword({
|
||||
username,
|
||||
code,
|
||||
newPassword,
|
||||
}: AuthConfirmResetPasswordRequest) {
|
||||
this.logger.log('confirmResetPassword');
|
||||
|
||||
return grpcHandler<AuthConfirmResetPasswordResponse>(
|
||||
this.authService.AuthConfirmResetPassword({
|
||||
username,
|
||||
code,
|
||||
newPassword,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
async enableTotpMFA({ accessToken, password }: AuthEnableTotpMfaRequest) {
|
||||
this.logger.log('enableTotpMFA');
|
||||
|
||||
return grpcHandler<AuthEnableTotpMfaResponse>(
|
||||
this.authService.AuthEnableTotpMfa({ accessToken, password }),
|
||||
);
|
||||
}
|
||||
|
||||
async disableTotpMFA({ accessToken, password }: AuthDisableTotpMfaRequest) {
|
||||
this.logger.log('disableTotpMFA');
|
||||
|
||||
return grpcHandler<AuthDisableTotpMfaResponse>(
|
||||
this.authService.AuthDisableTotpMfa({ accessToken, password }),
|
||||
);
|
||||
}
|
||||
|
||||
async dismissTotpMFA({ accessToken }: AuthDismissTotpMfaRequest) {
|
||||
this.logger.log('dismissTotpMFA');
|
||||
|
||||
return grpcHandler<AuthDismissTotpMfaResponse>(
|
||||
this.authService.AuthDismissTotpMfa({ accessToken }),
|
||||
);
|
||||
}
|
||||
|
||||
async verifyTotp({ accessToken, totp }: AuthVerifyTotpMfaRequest) {
|
||||
this.logger.log('disableTotpMFA');
|
||||
|
||||
return grpcHandler<AuthVerifyTotpMfaResponse>(
|
||||
this.authService.AuthVerifyTotpMfa({ accessToken, totp }),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { credentials } from '@grpc/grpc-js';
|
||||
import { ClientOptions, Transport } from '@nestjs/microservices';
|
||||
import {
|
||||
ProtoPackages,
|
||||
ProtoPaths,
|
||||
} from '@victorradael/protospack-v2/dist/lib/Duc';
|
||||
|
||||
export class DucClient {
|
||||
config(): ClientOptions {
|
||||
return {
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
url: process.env.DUC_URL,
|
||||
package: ProtoPackages.WritePackage,
|
||||
credentials: process.env.LOCAL_ENV
|
||||
? undefined
|
||||
: credentials.createSsl(),
|
||||
protoPath: ProtoPaths.WriteFilePath,
|
||||
loader: {
|
||||
keepCase: true,
|
||||
enums: String,
|
||||
objects: true,
|
||||
arrays: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { credentials } from '@grpc/grpc-js';
|
||||
import { ClientOptions, Transport } from '@nestjs/microservices';
|
||||
|
||||
import { InputPackages, InputProtoFilePath } from '@victorradael/protospack';
|
||||
|
||||
export class InputsClientConfiguration {
|
||||
config(): ClientOptions {
|
||||
return {
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
url: process.env.INFACTORY_URL,
|
||||
package: InputPackages,
|
||||
credentials: process.env.LOCAL_ENV
|
||||
? undefined
|
||||
: credentials.createSsl(),
|
||||
protoPath: InputProtoFilePath,
|
||||
loader: {
|
||||
enums: String,
|
||||
objects: true,
|
||||
arrays: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,290 @@
|
||||
import {
|
||||
OnModuleInit,
|
||||
Inject,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
NotFoundException,
|
||||
InternalServerErrorException,
|
||||
} from '@nestjs/common';
|
||||
import { ClientGrpc } from '@nestjs/microservices';
|
||||
import {
|
||||
DecodeGrpcStruct,
|
||||
EncodeJsonToGrpcStruct,
|
||||
InputCreateS3Request,
|
||||
InputNewCreateRequest,
|
||||
InputService,
|
||||
TestConnectionGetColumnsRequest,
|
||||
TestConnectionRequest,
|
||||
} from '@victorradael/protospack';
|
||||
import axios, { AxiosRequestConfig } from 'axios';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import { InputModel } from 'src/modules/inputs/dtos/input.model';
|
||||
import {
|
||||
objectCamelToSnake,
|
||||
objectSnakeToCamel,
|
||||
} from 'src/utils/CaseConverter';
|
||||
import { mustache } from 'src/utils/mustache';
|
||||
import { OauthSecrets } from 'src/utils/OauthSecrets';
|
||||
import { URLSearchParams } from 'url';
|
||||
import { IIdRequest, UpdateInputRequest } from './interfaces';
|
||||
|
||||
export class InputsClientService implements OnModuleInit {
|
||||
private inputService: InputService;
|
||||
constructor(
|
||||
@Inject('INPUTS_PACKAGE') private readonly grpcClient: ClientGrpc,
|
||||
@Inject('OAUTH_SECRETS') private readonly oauthSecrets: OauthSecrets,
|
||||
) {}
|
||||
|
||||
async onModuleInit() {
|
||||
this.inputService =
|
||||
this.grpcClient.getService<InputService>('InputService');
|
||||
}
|
||||
|
||||
async newCreate(createInputDto: InputNewCreateRequest) {
|
||||
console.log('InputClientService', 'Create');
|
||||
|
||||
const input = await lastValueFrom(
|
||||
this.inputService.NewCreate(objectSnakeToCamel(createInputDto)),
|
||||
);
|
||||
objectCamelToSnake(input);
|
||||
return input;
|
||||
}
|
||||
|
||||
async createGeneric(createInputGeneric) {
|
||||
console.log('InputClientService', 'Create');
|
||||
const { info, ...data } = createInputGeneric;
|
||||
// data.credentials = await this.getInputTokens(data);
|
||||
if (data.options) delete data.options;
|
||||
if (data.credentials.oauth_code) delete data.credentials.oauth_code;
|
||||
const grpcPayload = {
|
||||
input: EncodeJsonToGrpcStruct(data),
|
||||
info,
|
||||
};
|
||||
objectSnakeToCamel(grpcPayload);
|
||||
|
||||
const structReturn = await lastValueFrom(
|
||||
this.inputService.Create(grpcPayload),
|
||||
).catch((err) => {
|
||||
if (err.details === 'Item Not found!') {
|
||||
throw new NotFoundException('Input not found');
|
||||
}
|
||||
throw new InternalServerErrorException(err.details);
|
||||
});
|
||||
objectCamelToSnake(structReturn);
|
||||
const inputCreated = DecodeGrpcStruct(structReturn.input);
|
||||
return { input: inputCreated };
|
||||
}
|
||||
|
||||
async createS3Inputs(createInputDto: InputCreateS3Request) {
|
||||
console.log('InputClientService', 'Create');
|
||||
objectSnakeToCamel(createInputDto);
|
||||
const createInputResponse = await lastValueFrom(
|
||||
this.inputService.CreateS3(createInputDto),
|
||||
).catch((e) => {
|
||||
throw new HttpException(e.details, 500);
|
||||
});
|
||||
console.log('done');
|
||||
objectCamelToSnake(createInputResponse);
|
||||
return createInputResponse;
|
||||
}
|
||||
|
||||
async findOne(data: IIdRequest) {
|
||||
console.log('InputClientService', 'FindOne');
|
||||
const findOneInputResponse = await lastValueFrom(
|
||||
this.inputService.FindOne(objectSnakeToCamel(data)),
|
||||
).catch((e) => {
|
||||
throw new HttpException(e.details, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
});
|
||||
objectCamelToSnake(findOneInputResponse);
|
||||
return findOneInputResponse;
|
||||
}
|
||||
|
||||
async findAll(data) {
|
||||
console.log('InputClientService', 'FindAll');
|
||||
const findAllInputResponse = await lastValueFrom(
|
||||
this.inputService.FindAll(objectSnakeToCamel(data)),
|
||||
).catch((e) => {
|
||||
throw new HttpException(e.details, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
});
|
||||
findAllInputResponse.inputs.forEach((input) => objectCamelToSnake(input));
|
||||
|
||||
return findAllInputResponse;
|
||||
}
|
||||
|
||||
async update(updateInputDTO: UpdateInputRequest) {
|
||||
console.log('InputClientService', 'Update');
|
||||
const updateInputResponse = await new Promise((resolve, reject) => {
|
||||
this.inputService.Update(objectSnakeToCamel(updateInputDTO)).subscribe({
|
||||
next(x) {
|
||||
resolve(objectCamelToSnake(x));
|
||||
},
|
||||
error(err) {
|
||||
console.log('Observable Error');
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => res)
|
||||
.catch((err) => {
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return updateInputResponse;
|
||||
}
|
||||
|
||||
async remove(idRequest: IIdRequest) {
|
||||
console.log('InputClientService', 'Remove');
|
||||
|
||||
const removeInputResponse = await new Promise((resolve, reject) => {
|
||||
this.inputService.Remove(objectSnakeToCamel(idRequest)).subscribe({
|
||||
next(x) {
|
||||
resolve(objectCamelToSnake(x));
|
||||
},
|
||||
error(err) {
|
||||
console.log('Observable Error');
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => res)
|
||||
.catch((err) => {
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return removeInputResponse;
|
||||
}
|
||||
|
||||
async testConnection(data: TestConnectionRequest) {
|
||||
console.log('InputClientService', 'TestConnection');
|
||||
const testConnectionResponse = await new Promise((resolve, reject) => {
|
||||
this.inputService.NewTestConnection(objectSnakeToCamel(data)).subscribe({
|
||||
next(x) {
|
||||
resolve(objectCamelToSnake(x));
|
||||
},
|
||||
error(err) {
|
||||
console.log('Observable Error');
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => res)
|
||||
.catch((err) => {
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return testConnectionResponse;
|
||||
}
|
||||
|
||||
async getColumns(data: TestConnectionGetColumnsRequest) {
|
||||
console.log('InputClientService', 'TestConnection/Get-Columns');
|
||||
const getColumnsResponse = await new Promise((resolve, reject) => {
|
||||
this.inputService.GetColumns(objectSnakeToCamel(data)).subscribe({
|
||||
next(x) {
|
||||
resolve(objectCamelToSnake(x));
|
||||
},
|
||||
error(err) {
|
||||
console.log('Observable Error');
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => res)
|
||||
.catch((err) => {
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return getColumnsResponse;
|
||||
}
|
||||
async getAuthSecrets(plugin) {
|
||||
switch (plugin) {
|
||||
case 'hubspot':
|
||||
return {
|
||||
client_id: this.oauthSecrets.hubspot.client_id || '',
|
||||
client_secret: this.oauthSecrets.hubspot.client_secret || '',
|
||||
};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
async getInputTokens(input: InputModel) {
|
||||
const { credentials } = input;
|
||||
let credentialsTokens = {};
|
||||
switch (credentials.connection_type) {
|
||||
case 'oauth':
|
||||
credentialsTokens = await this.getOauthTokens(input);
|
||||
break;
|
||||
}
|
||||
return { ...credentials, ...credentialsTokens };
|
||||
}
|
||||
async getOauthTokens(input: InputModel) {
|
||||
const tokens: Record<string, any> = {};
|
||||
const { options, credentials } = input;
|
||||
const { oauth } = options;
|
||||
const { get_tokens_url_params, get_tokens_set_response } = oauth;
|
||||
const secrets = await this.getAuthSecrets(input.plugin);
|
||||
const get_tokens_url_params_string = mustache(get_tokens_url_params, {
|
||||
...secrets,
|
||||
...credentials,
|
||||
});
|
||||
let get_tokens_url_params_obj: Record<string, any> = {};
|
||||
try {
|
||||
get_tokens_url_params_obj = JSON.parse(get_tokens_url_params_string);
|
||||
} catch (error) {
|
||||
throw new HttpException('Erro transformando get_tokens_url_params', 400);
|
||||
}
|
||||
let params = {};
|
||||
switch (oauth.content_type) {
|
||||
case 'application/x-www-form-urlencoded':
|
||||
params = new URLSearchParams(get_tokens_url_params_obj);
|
||||
params = params.toString();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
const axiosRequestConfig: AxiosRequestConfig = {
|
||||
url: oauth.get_tokens_url,
|
||||
method: oauth.get_tokens_method || 'POST',
|
||||
data: params,
|
||||
headers: { 'content-type': oauth.content_type || 'application/json' },
|
||||
};
|
||||
|
||||
const { data } = await axios(axiosRequestConfig).catch((err) => {
|
||||
console.log(err.response.data);
|
||||
throw new HttpException(err.response.data.message, err.response.status);
|
||||
});
|
||||
for (const key in get_tokens_set_response) {
|
||||
const responseKey = get_tokens_set_response[key];
|
||||
tokens[key] = data[responseKey];
|
||||
}
|
||||
const { redirect_uri } = get_tokens_url_params_obj;
|
||||
tokens.redirect_uri = redirect_uri;
|
||||
return tokens;
|
||||
}
|
||||
|
||||
async getAvailableEntities(data) {
|
||||
console.log('InputClientService', 'GetAvailableEntities');
|
||||
objectSnakeToCamel(data);
|
||||
const response = await lastValueFrom(
|
||||
this.inputService.GetAvailableEntities(data),
|
||||
).catch((err) => {
|
||||
console.log(err);
|
||||
if (err.details && err.details.includes('400'))
|
||||
throw new HttpException('Plugin inválido', HttpStatus.BAD_REQUEST);
|
||||
throw new HttpException(err.details, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
});
|
||||
objectCamelToSnake(response);
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
Vendored
+62
@@ -0,0 +1,62 @@
|
||||
interface Values {
|
||||
jdbc_user: string;
|
||||
jdbc_password: string;
|
||||
database: string;
|
||||
endpoint: string;
|
||||
tables: string[];
|
||||
port: string;
|
||||
engine: string;
|
||||
schema: string;
|
||||
}
|
||||
|
||||
interface Cron {
|
||||
hours: string[];
|
||||
hour_interval: boolean;
|
||||
hour_resourse: boolean;
|
||||
hour_resourse_value: number;
|
||||
month_day: string[];
|
||||
month_day_interval: boolean;
|
||||
month_day_resourse: boolean;
|
||||
month_day_resourse_value: number;
|
||||
month: string[];
|
||||
month_interval: boolean;
|
||||
month_resourse: boolean;
|
||||
month_resourse_value: number;
|
||||
week_days: string[];
|
||||
week_days_interval: boolean;
|
||||
week_days_resourse: boolean;
|
||||
week_days_resourse_value: number;
|
||||
}
|
||||
|
||||
export interface Info {
|
||||
costumer_id: string;
|
||||
user_id: string;
|
||||
}
|
||||
|
||||
export interface ICreateInputRequest {
|
||||
cron: string;
|
||||
name: string;
|
||||
plugin: string;
|
||||
values: Values;
|
||||
operation: string;
|
||||
info: Info;
|
||||
}
|
||||
export interface IIdRequest {
|
||||
id: string;
|
||||
info: Info;
|
||||
}
|
||||
|
||||
export interface UpdateInputRequest {
|
||||
id: string;
|
||||
cron: string;
|
||||
name: string;
|
||||
plugin: string;
|
||||
values: Values;
|
||||
operation: string;
|
||||
info: Info;
|
||||
}
|
||||
|
||||
export interface ITestConnectionRequest {
|
||||
plugin: string;
|
||||
values: Values;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { OutputPackages, OutputProtoFilePath } from '@victorradael/protospack';
|
||||
import { ClientOptions, Transport } from '@nestjs/microservices';
|
||||
import { credentials } from '@grpc/grpc-js';
|
||||
|
||||
export class OutputsClientConfiguration {
|
||||
config(): ClientOptions {
|
||||
return {
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
url: process.env.OTFACTORY_URL,
|
||||
package: OutputPackages,
|
||||
credentials: process.env.LOCAL_ENV
|
||||
? undefined
|
||||
: credentials.createSsl(),
|
||||
protoPath: OutputProtoFilePath,
|
||||
loader: {
|
||||
enums: String,
|
||||
objects: true,
|
||||
arrays: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
import { Controller, Inject, OnModuleInit } from '@nestjs/common';
|
||||
import { ClientGrpc, Payload } from '@nestjs/microservices';
|
||||
import {
|
||||
OutputServicesNames,
|
||||
OutputsServiceInterface,
|
||||
} from '@victorradael/protospack';
|
||||
import {
|
||||
objectCamelToSnake,
|
||||
objectSnakeToCamel,
|
||||
} from 'src/utils/CaseConverter';
|
||||
import {
|
||||
ICreateOutputRequest,
|
||||
IIdRequest,
|
||||
IOutputUpdateRequest,
|
||||
} from './interfaces';
|
||||
|
||||
@Controller('output')
|
||||
export class OutputsClientService implements OnModuleInit {
|
||||
private outputService: OutputsServiceInterface;
|
||||
constructor(
|
||||
@Inject('OUTPUTS_PACKAGE') private readonly grpcClient: ClientGrpc,
|
||||
) {}
|
||||
|
||||
onModuleInit() {
|
||||
this.outputService = this.grpcClient.getService<OutputsServiceInterface>(
|
||||
OutputServicesNames.OutputService,
|
||||
);
|
||||
}
|
||||
|
||||
async create(@Payload() createOutputDto: ICreateOutputRequest) {
|
||||
console.log('OutputClientService', 'Create');
|
||||
|
||||
const createOutputResponse = await new Promise((resolve, reject) => {
|
||||
this.outputService.Create(objectSnakeToCamel(createOutputDto)).subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
console.log('Observable Error');
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => res)
|
||||
.catch((err) => {
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
const convertedItem = objectCamelToSnake(createOutputResponse['output']);
|
||||
createOutputResponse['output'] = convertedItem;
|
||||
return createOutputResponse;
|
||||
}
|
||||
|
||||
async findAll(data) {
|
||||
console.log('OutputClientService', 'FindAll');
|
||||
|
||||
const findAllOutputResponse = await new Promise((resolve, reject) => {
|
||||
this.outputService.FindAll(objectSnakeToCamel(data)).subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
console.log('Observable Error');
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => res)
|
||||
.catch((err) => {
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
const convertedOutputs = findAllOutputResponse['outputs'].map((ot) => {
|
||||
return objectCamelToSnake(ot);
|
||||
});
|
||||
|
||||
return { outputs: convertedOutputs };
|
||||
}
|
||||
|
||||
async findOne(data: IIdRequest) {
|
||||
console.log('OutputClientService', 'FindOne');
|
||||
|
||||
const findOneOutputResponse = await new Promise((resolve, reject) => {
|
||||
this.outputService.FindOne(objectSnakeToCamel(data)).subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
console.log('Observable Error');
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => res)
|
||||
.catch((err) => {
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return objectCamelToSnake(findOneOutputResponse);
|
||||
}
|
||||
|
||||
async update(updateOutPutDTO: IOutputUpdateRequest) {
|
||||
console.log('OutputClientService', 'Update');
|
||||
|
||||
const updateOutputResponse = await new Promise((resolve, reject) => {
|
||||
this.outputService.Update(objectSnakeToCamel(updateOutPutDTO)).subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
console.log('Observable Error');
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => res)
|
||||
.catch((err) => {
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return objectCamelToSnake(updateOutputResponse);
|
||||
}
|
||||
|
||||
async remove(data: IIdRequest) {
|
||||
console.log('OutputClientService', 'Remove');
|
||||
|
||||
const removeOutputResponse = await new Promise((resolve, reject) => {
|
||||
this.outputService.Remove(objectSnakeToCamel(data)).subscribe({
|
||||
next(x) {
|
||||
resolve(objectCamelToSnake(x));
|
||||
},
|
||||
error(err) {
|
||||
console.log('Observable Error');
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => res)
|
||||
.catch((err) => {
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return removeOutputResponse;
|
||||
}
|
||||
}
|
||||
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
export interface ICreateOutputRequest {
|
||||
operation: string;
|
||||
name: string;
|
||||
plugin: string;
|
||||
values: Values;
|
||||
}
|
||||
|
||||
export interface Values {
|
||||
prefix: string;
|
||||
}
|
||||
|
||||
interface Info {
|
||||
user_id: string;
|
||||
customer_id: string;
|
||||
}
|
||||
|
||||
export interface IIdRequest {
|
||||
id: string;
|
||||
info: Info;
|
||||
}
|
||||
|
||||
export interface IOutputUpdateRequest {
|
||||
id: string;
|
||||
operation: string;
|
||||
values: Values;
|
||||
plugin: string;
|
||||
name: string;
|
||||
info: Info;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Logger, OnModuleInit, Inject } from '@nestjs/common';
|
||||
import { ClientGrpc } from '@nestjs/microservices';
|
||||
|
||||
import { ProtoServices } from '@victorradael/protospack-v2/dist/lib/Duc';
|
||||
import { PermissionsProtoService as PermissionsServiceInterface } from '@victorradael/protospack-v2/dist/lib/Duc/interfaces/write-service';
|
||||
import {
|
||||
Empty,
|
||||
InjectPermissionsRequest,
|
||||
} from '@victorradael/protospack-v2/dist/lib/Duc/interfaces/messages';
|
||||
|
||||
import grpcHandler from '../../utils/grpcHandler';
|
||||
|
||||
export class PermissionsClientService implements OnModuleInit {
|
||||
private readonly logger = new Logger(PermissionsClientService.name);
|
||||
|
||||
private permissionsService: PermissionsServiceInterface;
|
||||
constructor(@Inject('DUC_PACKAGE') private readonly grpcClient: ClientGrpc) {}
|
||||
|
||||
onModuleInit() {
|
||||
this.permissionsService =
|
||||
this.grpcClient.getService<PermissionsServiceInterface>(
|
||||
ProtoServices.PermissionsProtoService,
|
||||
);
|
||||
}
|
||||
|
||||
async injectPermissions({ permissions }: InjectPermissionsRequest) {
|
||||
this.logger.log('InjectPermissions');
|
||||
|
||||
return grpcHandler<Empty>(
|
||||
this.permissionsService.InjectPermissions({ permissions }),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { ClientOptions, Transport } from '@nestjs/microservices';
|
||||
import {
|
||||
PipelinePackages,
|
||||
PipelineProtoFilePath,
|
||||
} from '@victorradael/protospack';
|
||||
import { credentials } from '@grpc/grpc-js';
|
||||
|
||||
export class PipelinesClientConfiguration {
|
||||
config(): ClientOptions {
|
||||
return {
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
url: process.env.PIFACTORY_URL,
|
||||
package: PipelinePackages,
|
||||
credentials: process.env.LOCAL_ENV
|
||||
? undefined
|
||||
: credentials.createSsl(),
|
||||
protoPath: PipelineProtoFilePath,
|
||||
loader: {
|
||||
enums: String,
|
||||
objects: true,
|
||||
arrays: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,252 @@
|
||||
import { HttpException, Inject, OnModuleInit } from '@nestjs/common';
|
||||
import { ClientGrpc, Payload } from '@nestjs/microservices';
|
||||
import {
|
||||
PipelineServicesNames,
|
||||
PipelinesServiceInterface,
|
||||
} from '@victorradael/protospack';
|
||||
import {
|
||||
objectCamelToSnake,
|
||||
objectSnakeToCamel,
|
||||
} from 'src/utils/CaseConverter';
|
||||
import {
|
||||
ICreatePipelineDto,
|
||||
IGetPipelineLogsRequest,
|
||||
IIdRequest,
|
||||
IUpdatePipelineRequest,
|
||||
} from './interfaces';
|
||||
|
||||
export class PipelinesClientService implements OnModuleInit {
|
||||
private pipelineService: PipelinesServiceInterface;
|
||||
constructor(
|
||||
@Inject('PIPELINES_PACKAGE') private readonly grpcClient: ClientGrpc,
|
||||
) {}
|
||||
|
||||
onModuleInit() {
|
||||
this.pipelineService =
|
||||
this.grpcClient.getService<PipelinesServiceInterface>(
|
||||
PipelineServicesNames.PipelineService,
|
||||
);
|
||||
}
|
||||
|
||||
async create(@Payload() createPipelineDto: ICreatePipelineDto) {
|
||||
console.log('PipelinesClientService', 'Create');
|
||||
|
||||
const createPipelineResponse = await new Promise((resolve, reject) => {
|
||||
this.pipelineService
|
||||
.Create(objectSnakeToCamel(createPipelineDto))
|
||||
.subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
console.log('Observable Error');
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => res)
|
||||
.catch((err) => {
|
||||
if (err.details == 'Invalid Request') {
|
||||
throw new HttpException(err.details, 400);
|
||||
}
|
||||
throw new HttpException(err.details, 500);
|
||||
});
|
||||
|
||||
return createPipelineResponse;
|
||||
}
|
||||
|
||||
async findAll(data: IIdRequest) {
|
||||
console.log('PipelinesClientService', 'FindAll');
|
||||
|
||||
const findAllPipelineResponse = await new Promise((resolve, reject) => {
|
||||
this.pipelineService.FindAll(objectSnakeToCamel(data)).subscribe({
|
||||
next(x) {
|
||||
resolve(x.pipelines);
|
||||
},
|
||||
error(err) {
|
||||
console.log('Observable Error');
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => res)
|
||||
.catch((err) => {
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return findAllPipelineResponse;
|
||||
}
|
||||
|
||||
async findOne(data: IIdRequest) {
|
||||
console.log('PipelinesClientService', 'FindOne');
|
||||
|
||||
const findOnePipelineResponse = await new Promise((resolve, reject) => {
|
||||
this.pipelineService.FindOne(objectSnakeToCamel(data)).subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
console.log('Observable Error');
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => res)
|
||||
.catch((err) => {
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return findOnePipelineResponse;
|
||||
}
|
||||
|
||||
async update(UpdatePipelineRequest: IUpdatePipelineRequest) {
|
||||
console.log('PipelinesClientService', 'Update');
|
||||
|
||||
const updatePipelineResponse = await new Promise((resolve, reject) => {
|
||||
this.pipelineService
|
||||
.Update(objectSnakeToCamel(UpdatePipelineRequest))
|
||||
.subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
console.log('Observable Error');
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => res)
|
||||
.catch((err) => {
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return updatePipelineResponse;
|
||||
}
|
||||
|
||||
async remove(data: IIdRequest) {
|
||||
console.log('PipelinesClientService', 'Remove');
|
||||
|
||||
const removePipelineResponse = await new Promise((resolve, reject) => {
|
||||
this.pipelineService.remove(objectSnakeToCamel(data)).subscribe({
|
||||
next(x) {
|
||||
resolve(objectCamelToSnake(x));
|
||||
},
|
||||
error(err) {
|
||||
console.log('Observable Error');
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => res)
|
||||
.catch((err) => {
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return removePipelineResponse;
|
||||
}
|
||||
|
||||
async getPipelineLogsMessages(data: IGetPipelineLogsRequest) {
|
||||
console.log('PipelinesClientService', 'GetPipelineLogsMessages');
|
||||
|
||||
const logsPipelineResponse = await new Promise((resolve, reject) => {
|
||||
this.pipelineService.getPipelineLogs(data).subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
console.log('Observable Error');
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => res)
|
||||
.catch((err) => {
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return logsPipelineResponse;
|
||||
}
|
||||
|
||||
async getPipelineStatus(data) {
|
||||
console.log('PipelinesClientService', 'GetPipelineStatus');
|
||||
|
||||
const statusPipelineResponse = await new Promise((resolve, reject) => {
|
||||
this.pipelineService
|
||||
.getPipelineStatus(objectSnakeToCamel(data))
|
||||
.subscribe({
|
||||
next(x) {
|
||||
const statusArray = x.status.sort((a, b) => {
|
||||
if (a.id < b.id) {
|
||||
return 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
});
|
||||
resolve({ status: statusArray });
|
||||
},
|
||||
error(err) {
|
||||
console.log('Observable Error');
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => res)
|
||||
.catch((err) => {
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return statusPipelineResponse;
|
||||
}
|
||||
|
||||
async runPipeline({ id, info }: IIdRequest) {
|
||||
console.log('PipelinesClientService', 'RunPipeline');
|
||||
const statusPipelineResponse = await new Promise((resolve, reject) => {
|
||||
this.pipelineService
|
||||
.triggerPipeline(objectSnakeToCamel({ id, info }))
|
||||
.subscribe({
|
||||
next(x) {
|
||||
if (x.status == false) {
|
||||
reject(
|
||||
'This pipeline is not ready yet to execute, Try again later!',
|
||||
);
|
||||
}
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
console.log('Observable Error');
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
console.log('done');
|
||||
},
|
||||
});
|
||||
})
|
||||
.then((res) => res)
|
||||
.catch((err) => {
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return statusPipelineResponse;
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
export interface ICreatePipelineDto {
|
||||
input: IdRequest;
|
||||
transformations: IdRequest[];
|
||||
output: IdRequest;
|
||||
tags: string[];
|
||||
name: string;
|
||||
description: string;
|
||||
info: Info;
|
||||
}
|
||||
|
||||
export interface Info {
|
||||
customer_id: sting;
|
||||
user_id: string;
|
||||
}
|
||||
|
||||
export interface IdRequest {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface IIdRequest {
|
||||
id: string;
|
||||
info: Info;
|
||||
}
|
||||
|
||||
export interface IUpdatePipelineRequest {
|
||||
input: IdRequest;
|
||||
transformations: IdRequest[];
|
||||
output: IdRequest;
|
||||
tags: string[];
|
||||
name: string;
|
||||
description: string;
|
||||
id: string;
|
||||
info: Info;
|
||||
}
|
||||
|
||||
export interface IGetPipelineLogsRequest {
|
||||
id: string;
|
||||
details: string;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ClientOptions, Transport } from '@nestjs/microservices';
|
||||
import {
|
||||
TransformationPackages,
|
||||
TransformationProtoFilePath,
|
||||
} from '@victorradael/protospack';
|
||||
import { credentials } from '@grpc/grpc-js';
|
||||
|
||||
export class TransformationsClientConfiguration {
|
||||
config(): ClientOptions {
|
||||
return {
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
url: process.env.INFACTORY_URL,
|
||||
package: TransformationPackages,
|
||||
credentials: credentials.createSsl(),
|
||||
protoPath: TransformationProtoFilePath,
|
||||
loader: {
|
||||
enums: String,
|
||||
objects: true,
|
||||
arrays: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
import { Controller, Inject, OnModuleInit, Post } from '@nestjs/common';
|
||||
import { ClientGrpc } from '@nestjs/microservices';
|
||||
import { TransformationsServiceInterface } from '@victorradael/protospack';
|
||||
import {
|
||||
objectCamelToSnake,
|
||||
objectSnakeToCamel,
|
||||
} from 'src/utils/CaseConverter';
|
||||
import { ICreateTransformationsRequest, IIdRequest } from './interfaces';
|
||||
|
||||
@Controller('transformation')
|
||||
export class TransformationsClientService implements OnModuleInit {
|
||||
private transformationService: TransformationsServiceInterface;
|
||||
constructor(
|
||||
@Inject('TRANSFORMATIONS_PACKAGE') private readonly grpcClient: ClientGrpc,
|
||||
) {}
|
||||
|
||||
onModuleInit() {
|
||||
this.transformationService =
|
||||
this.grpcClient.getService<TransformationsServiceInterface>(
|
||||
'TransformationService',
|
||||
);
|
||||
}
|
||||
|
||||
@Post()
|
||||
async create(createTransformationsDto: ICreateTransformationsRequest) {
|
||||
console.log('TransformationClientService', 'Create');
|
||||
|
||||
const createTransformationResponse = await new Promise(
|
||||
(resolve, reject) => {
|
||||
this.transformationService
|
||||
.Create(objectSnakeToCamel(createTransformationsDto))
|
||||
.subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
console.log('Observable Error');
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
console.log('done');
|
||||
},
|
||||
});
|
||||
},
|
||||
)
|
||||
.then((res) => res)
|
||||
.catch((err) => {
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
const convertedTransforms = createTransformationResponse[
|
||||
'transformations'
|
||||
].map((tr) => {
|
||||
return objectCamelToSnake(tr);
|
||||
});
|
||||
|
||||
return { transformations: convertedTransforms };
|
||||
}
|
||||
|
||||
async findAll(data) {
|
||||
console.log('TransformationClientService', 'FindAll');
|
||||
|
||||
const findAllTransformationResponse = await new Promise(
|
||||
(resolve, reject) => {
|
||||
this.transformationService.FindAll(objectSnakeToCamel(data)).subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
console.log('Observable Error');
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
console.log('done');
|
||||
},
|
||||
});
|
||||
},
|
||||
)
|
||||
.then((res) => res)
|
||||
.catch((err) => {
|
||||
throw new Error(err);
|
||||
});
|
||||
const convertedTransforms = findAllTransformationResponse[
|
||||
'transformations'
|
||||
].map((tr) => {
|
||||
return objectCamelToSnake(tr);
|
||||
});
|
||||
return { transformations: convertedTransforms };
|
||||
}
|
||||
|
||||
async findOne(data: IIdRequest) {
|
||||
console.log('TransformationClientService', 'FindOne');
|
||||
|
||||
const findOneTransformationResponse = await new Promise(
|
||||
(resolve, reject) => {
|
||||
this.transformationService.FindOne(objectSnakeToCamel(data)).subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
console.log('Observable Error');
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
console.log('done');
|
||||
},
|
||||
});
|
||||
},
|
||||
)
|
||||
.then((res) => res)
|
||||
.catch((err) => {
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return objectCamelToSnake(findOneTransformationResponse);
|
||||
}
|
||||
|
||||
async update(updateTransformationDTO) {
|
||||
console.log('TransformationClientService', 'Update');
|
||||
|
||||
const updateTransformationResponse = await new Promise(
|
||||
(resolve, reject) => {
|
||||
this.transformationService
|
||||
.Update(objectSnakeToCamel(updateTransformationDTO))
|
||||
.subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
console.log('Observable Error');
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
console.log('done');
|
||||
},
|
||||
});
|
||||
},
|
||||
)
|
||||
.then((res) => res)
|
||||
.catch((err) => {
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return objectCamelToSnake(updateTransformationResponse);
|
||||
}
|
||||
|
||||
async remove(data: IIdRequest) {
|
||||
console.log('TransformationClientService', 'Remove');
|
||||
|
||||
const removeTransformationResponse = await new Promise(
|
||||
(resolve, reject) => {
|
||||
this.transformationService.Remove(objectSnakeToCamel(data)).subscribe({
|
||||
next(x) {
|
||||
resolve(x);
|
||||
},
|
||||
error(err) {
|
||||
console.log('Observable Error');
|
||||
reject(err);
|
||||
},
|
||||
complete() {
|
||||
console.log('done');
|
||||
},
|
||||
});
|
||||
},
|
||||
)
|
||||
.then((res) => res)
|
||||
.catch((err) => {
|
||||
throw new Error(err);
|
||||
});
|
||||
|
||||
return objectCamelToSnake(removeTransformationResponse);
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
export interface ICreateTransformationsRequest {
|
||||
transformations: Transformation[];
|
||||
info: Info;
|
||||
}
|
||||
interface Param {
|
||||
base_column: string;
|
||||
column_name: string;
|
||||
n_digits: number;
|
||||
start_index: number;
|
||||
randbelow: number;
|
||||
const: string;
|
||||
}
|
||||
|
||||
export interface Info {
|
||||
customer_id: string;
|
||||
user_id: string;
|
||||
}
|
||||
|
||||
interface Transformation {
|
||||
created_at: string;
|
||||
id: string;
|
||||
client_id: string;
|
||||
type: string;
|
||||
params: Param[];
|
||||
input_source: string;
|
||||
table: string;
|
||||
}
|
||||
|
||||
export interface IIdRequest {
|
||||
id: string;
|
||||
info: Info;
|
||||
}
|
||||
|
||||
export interface IUpdateTransformationRequest {
|
||||
transformation: Transformation;
|
||||
info: Info;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import { join } from 'path';
|
||||
import { ClientOptions, Transport } from '@nestjs/microservices';
|
||||
|
||||
export const GrpcClientConfiguration: ClientOptions = {
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
//url: `${process.env.USERS_SVC_URL}:${process.env.USERS_SVC_PORT}`,
|
||||
url: `127.0.0.1:50053`,
|
||||
package: 'enrichment',
|
||||
protoPath: join(__dirname, '..', 'proto', 'enrichment.proto'),
|
||||
loader: {
|
||||
enums: String,
|
||||
objects: true,
|
||||
arrays: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,6 +0,0 @@
|
||||
export class CreateEnrichmentDto {
|
||||
|
||||
type:string;
|
||||
|
||||
columns:string[]
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
import { PartialType } from '@nestjs/mapped-types';
|
||||
import { CreateEnrichmentDto } from './create-enrichment.dto';
|
||||
|
||||
export class UpdateEnrichmentDto extends PartialType(CreateEnrichmentDto) {
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { EnrichmentController } from './enrichment.controller';
|
||||
import { EnrichmentsService } from './enrichment.service';
|
||||
|
||||
describe('EnrichmentController', () => {
|
||||
let controller: EnrichmentController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [EnrichmentController],
|
||||
providers: [EnrichmentsService],
|
||||
}).compile();
|
||||
|
||||
controller = module.get<EnrichmentController>(EnrichmentController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -1,60 +0,0 @@
|
||||
import {
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
OnModuleInit,
|
||||
Param,
|
||||
Post,
|
||||
Put,
|
||||
} from '@nestjs/common';
|
||||
import { Client, ClientGrpc, Payload } from '@nestjs/microservices';
|
||||
import { EnrichmentsService } from './enrichment.service';
|
||||
import { CreateEnrichmentDto } from './dto/create-enrichment.dto';
|
||||
import { UpdateEnrichmentDto } from './dto/update-enrichment.dto';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { GrpcClientConfiguration } from './config/grpc-client';
|
||||
|
||||
@ApiTags('enrichments')
|
||||
@Controller('enrichment')
|
||||
export class EnrichmentController implements OnModuleInit {
|
||||
|
||||
@Client(GrpcClientConfiguration)
|
||||
private enrichmentServiceClient: ClientGrpc;
|
||||
|
||||
private enrichmentService: EnrichmentsService;
|
||||
|
||||
onModuleInit() {
|
||||
this.enrichmentService =
|
||||
this.enrichmentServiceClient.getService<EnrichmentsService>(
|
||||
'EnrichmentService',
|
||||
);
|
||||
}
|
||||
|
||||
@Post()
|
||||
create(@Payload() createEnrichmentDto: CreateEnrichmentDto) {
|
||||
return this.enrichmentService.create(createEnrichmentDto);
|
||||
}
|
||||
|
||||
@Get()
|
||||
list() {
|
||||
return this.enrichmentService.list();
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
show(@Param() id: string) {
|
||||
return this.enrichmentService.show(id);
|
||||
}
|
||||
|
||||
@Put(':id')
|
||||
update(
|
||||
@Param() id: string,
|
||||
@Payload() updateEnrichmentDto: UpdateEnrichmentDto,
|
||||
) {
|
||||
return this.enrichmentService.update(id, updateEnrichmentDto);
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
remove(@Param() id: string) {
|
||||
return this.enrichmentService.remove(id);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { EnrichmentsService } from './enrichment.service';
|
||||
import { EnrichmentController } from './enrichment.controller';
|
||||
|
||||
@Module({
|
||||
controllers: [EnrichmentController],
|
||||
providers: [EnrichmentsService],
|
||||
})
|
||||
export class EnrichmentModule {}
|
||||
@@ -1,18 +0,0 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { EnrichmentsService } from './enrichment.service';
|
||||
|
||||
describe('EnrichmentService', () => {
|
||||
let service: EnrichmentsService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [EnrichmentsService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<EnrichmentsService>(EnrichmentsService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -1,26 +0,0 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { CreateEnrichmentDto } from './dto/create-enrichment.dto';
|
||||
import { UpdateEnrichmentDto } from './dto/update-enrichment.dto';
|
||||
|
||||
@Injectable()
|
||||
export class EnrichmentsService {
|
||||
create(createEnrichmentDto: CreateEnrichmentDto) {
|
||||
return 'This action adds a new enrichment';
|
||||
}
|
||||
|
||||
list() {
|
||||
return `This action returns all enrichment`;
|
||||
}
|
||||
|
||||
show(id: string) {
|
||||
return `This action returns a #${id} enrichment`;
|
||||
}
|
||||
|
||||
update(id: string, updateEnrichmentDto: UpdateEnrichmentDto) {
|
||||
return `This action updates a #${id} enrichment`;
|
||||
}
|
||||
|
||||
remove(id: string) {
|
||||
return `This action removes a #${id} enrichment`;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
export class Enrichment {
|
||||
|
||||
id:string;
|
||||
|
||||
type:string;
|
||||
|
||||
columns:string[]
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package enrichment;
|
||||
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
|
||||
|
||||
service EnrichmentService {
|
||||
rpc Create(CreateEnrichmentRequest) returns (Enrichment) {}
|
||||
rpc Show(IdRequest) returns (Enrichment) {}
|
||||
rpc List(Empty) returns (ListResponse){}
|
||||
rpc Update(UpdateEnrichmentRequest) returns (Enrichment){}
|
||||
rpc Remove(IdRequest) returns (Empty){}
|
||||
}
|
||||
|
||||
message Empty {}
|
||||
|
||||
message IdRequest{
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
message UpdateEnrichmentRequest{
|
||||
string id = 1;
|
||||
string type = 2;
|
||||
repeated string columns = 3;
|
||||
}
|
||||
|
||||
message Enrichment {
|
||||
string id = 1;
|
||||
string type = 2;
|
||||
repeated string columns = 3;
|
||||
}
|
||||
|
||||
message CreateEnrichmentRequest {
|
||||
string type = 1;
|
||||
repeated string columns = 2;
|
||||
}
|
||||
|
||||
message ListResponse {
|
||||
repeated Enrichment enrichments = 2;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import { HttpExceptionFilter } from './http-exception.filter';
|
||||
|
||||
describe('HttpExceptionFilter', () => {
|
||||
it('should be defined', () => {
|
||||
expect(new HttpExceptionFilter()).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
import {
|
||||
ExceptionFilter,
|
||||
Catch,
|
||||
ArgumentsHost,
|
||||
HttpException,
|
||||
} from '@nestjs/common';
|
||||
import { Request, Response } from 'express';
|
||||
|
||||
@Catch(HttpException)
|
||||
export class HttpExceptionFilter implements ExceptionFilter {
|
||||
catch(exception: HttpException, host: ArgumentsHost) {
|
||||
const ctx = host.switchToHttp();
|
||||
const response = ctx.getResponse<Response>();
|
||||
const request = ctx.getRequest<Request>();
|
||||
const status = exception.getStatus();
|
||||
|
||||
response.status(status).json({
|
||||
status_code: status,
|
||||
timestamp: new Date().toISOString(),
|
||||
path: request.url,
|
||||
method: request.method,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export class Health {}
|
||||
@@ -1,9 +0,0 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { HealthService } from './health.service';
|
||||
import { HealthController } from './health.controller';
|
||||
|
||||
@Module({
|
||||
controllers: [HealthController],
|
||||
providers: [HealthService],
|
||||
})
|
||||
export class HealthModule {}
|
||||
@@ -1,17 +0,0 @@
|
||||
import { join } from 'path';
|
||||
import { ClientOptions, Transport } from '@nestjs/microservices';
|
||||
|
||||
export const GrpcClientConfiguration: ClientOptions = {
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
//url: `${process.env.USERS_SVC_URL}:${process.env.USERS_SVC_PORT}`,
|
||||
url: `127.0.0.1:50052`,
|
||||
package: 'input',
|
||||
protoPath: join(__dirname, '..', 'proto', 'input.proto'),
|
||||
loader: {
|
||||
enums: String,
|
||||
objects: true,
|
||||
arrays: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,13 +0,0 @@
|
||||
|
||||
export class CreateInputGrpcClientDto {
|
||||
|
||||
cron:string;
|
||||
|
||||
name:string;
|
||||
|
||||
plugin:string;
|
||||
|
||||
values:string;
|
||||
|
||||
operation:string;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
export class TestConnectionDTO{
|
||||
|
||||
values:string;
|
||||
plugin:string;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
import { PartialType } from '@nestjs/mapped-types';
|
||||
import { CreateInputGrpcClientDto } from './create-input-grpc-client.dto';
|
||||
|
||||
export class UpdateInputGrpcClientDto extends PartialType(
|
||||
CreateInputGrpcClientDto,
|
||||
) {}
|
||||
@@ -1,14 +0,0 @@
|
||||
export class InputGrpcClient {
|
||||
|
||||
id:string;
|
||||
|
||||
cron:string;
|
||||
|
||||
name:string;
|
||||
|
||||
plugin:string;
|
||||
|
||||
values:string;
|
||||
|
||||
operation:string;
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
import {
|
||||
Get,
|
||||
Post,
|
||||
Controller,
|
||||
Delete,
|
||||
OnModuleInit,
|
||||
Put,
|
||||
Param
|
||||
} from '@nestjs/common';
|
||||
import { Client, ClientGrpc, Payload } from '@nestjs/microservices';
|
||||
import { CreateInputGrpcClientDto } from './dto/create-input-grpc-client.dto';
|
||||
import { UpdateInputGrpcClientDto } from './dto/update-input-grpc-client.dto';
|
||||
import { InputGrpcClientService } from './input-grpc-client.service';
|
||||
import { GrpcClientConfiguration } from './config/grpc-client';
|
||||
import { TestConnectionDTO } from './dto/test-connection-grpc-client.dto';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
|
||||
@Controller('grpc/input')
|
||||
export class InputGrpcClientController implements OnModuleInit {
|
||||
@Client(GrpcClientConfiguration)
|
||||
private inputServiceClient: ClientGrpc;
|
||||
|
||||
private inputService: InputGrpcClientService;
|
||||
|
||||
onModuleInit() {
|
||||
this.inputService =
|
||||
this.inputServiceClient.getService<InputGrpcClientService>('InputService');
|
||||
}
|
||||
|
||||
@Post()
|
||||
async create(@Payload() createInputDto: CreateInputGrpcClientDto) {
|
||||
return this.inputService.create(createInputDto);
|
||||
}
|
||||
|
||||
@Get()
|
||||
list() {
|
||||
return this.inputService.list();
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
show(@Param() id: string) {
|
||||
return this.inputService.show(id);
|
||||
}
|
||||
|
||||
@Put(':id')
|
||||
update(
|
||||
@Payload() updateInputDto: UpdateInputGrpcClientDto,
|
||||
@Param() id: string,
|
||||
) {
|
||||
return this.inputService.update(id, updateInputDto);
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
remove(@Param() id: string) {
|
||||
return this.inputService.remove(id);
|
||||
}
|
||||
|
||||
@Get('/test-connection')
|
||||
testConnection(@Payload() testConnectionDTO:TestConnectionDTO){
|
||||
|
||||
return this.inputService.testConnection(testConnectionDTO)
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { InputGrpcClientService } from './input-grpc-client.service';
|
||||
import { InputGrpcClientController } from './input-grpc-client.controller';
|
||||
// import { InputRestClientController } from './input-rest-client.controller';
|
||||
|
||||
@Module({
|
||||
controllers: [
|
||||
InputGrpcClientController,
|
||||
// InputRestClientController
|
||||
],
|
||||
providers: [InputGrpcClientService],
|
||||
})
|
||||
export class InputGrpcClientModule {}
|
||||
@@ -1,18 +0,0 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { InputGrpcClientService } from './input-grpc-client.service';
|
||||
|
||||
describe('InputGrcpClientService', () => {
|
||||
let service: InputGrpcClientService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [InputGrpcClientService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<InputGrpcClientService>(InputGrpcClientService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -1,31 +0,0 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { CreateInputGrpcClientDto } from './dto/create-input-grpc-client.dto';
|
||||
import { TestConnectionDTO } from './dto/test-connection-grpc-client.dto';
|
||||
import { UpdateInputGrpcClientDto } from './dto/update-input-grpc-client.dto';
|
||||
|
||||
@Injectable()
|
||||
export class InputGrpcClientService {
|
||||
create(createInputGrcpClientDto: CreateInputGrpcClientDto) {
|
||||
return 'This action adds a new InputGrcpClient';
|
||||
}
|
||||
|
||||
list() {
|
||||
return `This action returns all InputGrcpClient`;
|
||||
}
|
||||
|
||||
show(id: string) {
|
||||
return `This action returns a #${id} InputGrcpClient`;
|
||||
}
|
||||
|
||||
update(id: string, updateInputGrcpClientDto: UpdateInputGrpcClientDto) {
|
||||
return `This action updates a #${id} InputGrcpClient`;
|
||||
}
|
||||
|
||||
remove(id: string) {
|
||||
return `This action removes a #${id} InputGrcpClient`;
|
||||
}
|
||||
|
||||
testConnection(testConnectionDTO:TestConnectionDTO){
|
||||
return `This action tests a given connection`;
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
import { Body, Controller, Delete, Get, Param, Post, Put, Redirect } from '@nestjs/common';
|
||||
import { Payload } from '@nestjs/microservices';
|
||||
import axios from 'axios';
|
||||
import { Console } from 'console';
|
||||
import { CreateInputGrpcClientDto } from './dto/create-input-grpc-client.dto';
|
||||
import { UpdateInputGrpcClientDto } from './dto/update-input-grpc-client.dto';
|
||||
|
||||
@Controller('input')
|
||||
export class InputRestClientController {
|
||||
|
||||
|
||||
@Get('/test-connection/')
|
||||
async testConnection(){
|
||||
console.log(process.env.DEV_URL+`/test-connection`, "ON TEST CONNECTION ROUTE")
|
||||
await axios.get(process.env.DEV_URL+`/test-connection`).then( (response) => {
|
||||
return response
|
||||
})
|
||||
}
|
||||
|
||||
@Post()
|
||||
async create(@Body() createInputDto: CreateInputGrpcClientDto){
|
||||
console.log(createInputDto)
|
||||
console.log(process.env.DEV_URL+`/input`, "ON CREATE ROUTE")
|
||||
|
||||
await axios.post(process.env.DEV_URL+'/input',createInputDto).then( (response) => {
|
||||
return response
|
||||
})
|
||||
}
|
||||
|
||||
@Get()
|
||||
async list(){
|
||||
console.log(process.env.DEV_URL+`/input`, "ON GET ROUTE")
|
||||
await axios.get(process.env.DEV_URL+`/input`).then( (response) => {
|
||||
return response
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@Get('/:id')
|
||||
async show(@Param() id: string){
|
||||
console.log(process.env.DEV_URL+`/input/${id}`, "ON SHOW ROUTE")
|
||||
await axios.get(process.env.DEV_URL+`/input/${id}`).then( (response) => {
|
||||
return response
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@Put(':id')
|
||||
async update(
|
||||
@Payload() updateInputDto: UpdateInputGrpcClientDto,
|
||||
@Param() id: string,
|
||||
){
|
||||
console.log(process.env.DEV_URL+`/input/${id}`, "ON UPDATE ROUTE")
|
||||
await axios.put(process.env.DEV_URL+`input/${id}`,updateInputDto).then( (response) => {
|
||||
return response
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@Delete(':id')
|
||||
async delete(@Param() id: string){
|
||||
console.log(process.env.DEV_URL+`/input/${id}`, "ON DELETE ROUTE")
|
||||
|
||||
await axios.delete(process.env.DEV_URL+`/input/${id}`).then( (response) => {
|
||||
return response
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package input;
|
||||
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
|
||||
|
||||
service InputService {
|
||||
rpc Create(CreateInputRequest) returns (Input) {}
|
||||
rpc Show(IdRequest) returns (Input) {}
|
||||
rpc List(Empty) returns (ListResponse){}
|
||||
rpc Update(UpdateInputRequest) returns (Input){}
|
||||
rpc Remove(IdRequest) returns (Empty){}
|
||||
rpc TestConnection(TestConnectionRequest) returns (TestConnectionResponse){}
|
||||
}
|
||||
|
||||
message Empty {}
|
||||
|
||||
message IdRequest{
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
message UpdateInputRequest{
|
||||
string id = 1;
|
||||
string cron = 2;
|
||||
string name = 3;
|
||||
string plugin = 4;
|
||||
string values = 5;
|
||||
string operation = 6;
|
||||
}
|
||||
|
||||
message Input {
|
||||
string id = 1;
|
||||
string cronFormated = 2;
|
||||
string name = 3;
|
||||
string plugin = 4;
|
||||
string values = 5;
|
||||
string operation = 6;
|
||||
}
|
||||
|
||||
message CreateInputRequest {
|
||||
string cron = 1;
|
||||
string name = 2;
|
||||
string plugin = 3;
|
||||
string values = 4;
|
||||
string operation = 5;
|
||||
}
|
||||
|
||||
message ListResponse {
|
||||
repeated Input inputs = 1;
|
||||
}
|
||||
|
||||
message TestConnectionRequest{
|
||||
string values = 1;
|
||||
string plugin = 2;
|
||||
}
|
||||
|
||||
message TestConnectionResponse{
|
||||
|
||||
// nao sei como vai ser a resposta
|
||||
bool respose = 1;
|
||||
|
||||
}
|
||||
+14
-4
@@ -1,12 +1,21 @@
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
||||
import { writeFileSync } from 'fs';
|
||||
import helmet from 'helmet';
|
||||
|
||||
import { AppModule } from './app.module';
|
||||
import { config } from 'dotenv';
|
||||
config();
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.create(AppModule);
|
||||
const app = await NestFactory.create(AppModule, {
|
||||
cors: {
|
||||
origin: '*',
|
||||
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
|
||||
preflightContinue: false,
|
||||
optionsSuccessStatus: 204,
|
||||
},
|
||||
});
|
||||
|
||||
app.use(helmet());
|
||||
|
||||
const config = new DocumentBuilder()
|
||||
.setTitle('Maestro Grpc Documentation')
|
||||
@@ -17,7 +26,8 @@ async function bootstrap() {
|
||||
|
||||
const document = SwaggerModule.createDocument(app, config);
|
||||
writeFileSync('./swagger.json', JSON.stringify(document));
|
||||
SwaggerModule.setup('api', app, document);
|
||||
if (process.env.ENV != 'stg' && process.env.ENV != 'prd')
|
||||
SwaggerModule.setup('api', app, document);
|
||||
|
||||
await app.listen(3333);
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
import { Request, Response, NextFunction } from 'express';
|
||||
import axios from 'axios';
|
||||
import { NestMiddleware } from '@nestjs/common';
|
||||
|
||||
export class LoggerMiddleware implements NestMiddleware{
|
||||
|
||||
|
||||
use = async (
|
||||
request: Request,
|
||||
response: Response,
|
||||
next: NextFunction
|
||||
) => {
|
||||
|
||||
try {
|
||||
const verify_response = await axios.post(
|
||||
`${process.env.DEV_URL}/user/verify`,
|
||||
{ "token":request.get('Authorization')}
|
||||
).then(response =>{
|
||||
if(response.data.message == "Success"){
|
||||
next()
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
} catch (error) {
|
||||
response.status(401).send({ message: 'Authentication Failed!' });
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
import {
|
||||
Logger,
|
||||
Body,
|
||||
Controller,
|
||||
Headers,
|
||||
Post,
|
||||
HttpCode,
|
||||
HttpStatus,
|
||||
OnApplicationBootstrap,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import {
|
||||
AuthSignInRequest,
|
||||
AuthRefreshAccessTokenRequest,
|
||||
AuthChangePasswordRequest,
|
||||
AuthResetPasswordRequest,
|
||||
AuthVerifyResetPasswordCodeRequest,
|
||||
AuthConfirmResetPasswordRequest,
|
||||
AuthEnableTotpMfaRequest,
|
||||
AuthDisableTotpMfaRequest,
|
||||
AuthVerifyTotpMfaRequest,
|
||||
} from '@victorradael/protospack-v2/dist/lib/Duc/interfaces/messages';
|
||||
|
||||
import { AuthClientService } from '../../clients/auth/client.service';
|
||||
import { PermissionsClientService } from '../../clients/permissions/client.service';
|
||||
import { Permissions } from '../../authentication/permissions.enum';
|
||||
|
||||
import ErrorBuilder from '../../utils/ErrorBuilder';
|
||||
|
||||
@ApiTags('Auth')
|
||||
@Controller('auth')
|
||||
export class AuthController implements OnApplicationBootstrap {
|
||||
private readonly logger = new Logger(AuthController.name);
|
||||
|
||||
constructor(
|
||||
private authClient: AuthClientService,
|
||||
private permissionsClient: PermissionsClientService,
|
||||
) {}
|
||||
|
||||
// internally used to send permissions to duc on microservice startup
|
||||
async onApplicationBootstrap() {
|
||||
this.logger.log('sending permissions to DUC...');
|
||||
|
||||
const permissions = Object.values(Permissions).flatMap((namespace) =>
|
||||
Object.values(namespace),
|
||||
);
|
||||
|
||||
return this.permissionsClient
|
||||
.injectPermissions({ permissions })
|
||||
.catch((err: ErrorBuilder) => {
|
||||
if (
|
||||
err.code === 'No connection established' &&
|
||||
process.env.LOCAL_ENV === 'true'
|
||||
) {
|
||||
return this.logger.log(
|
||||
"couldn't connect to DUC. suppresing in local env",
|
||||
);
|
||||
}
|
||||
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
@Post('sign-in')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async signIn(@Body() { username, password, totp }: AuthSignInRequest) {
|
||||
this.logger.log(`/auth`, 'SignIn');
|
||||
|
||||
return this.authClient.signIn({ username, password, totp });
|
||||
}
|
||||
|
||||
@Post('refresh-access-token')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async refreshAccessToken(
|
||||
@Body() { refreshToken }: AuthRefreshAccessTokenRequest,
|
||||
) {
|
||||
this.logger.log(`/auth`, 'RefreshAccessToken');
|
||||
|
||||
return this.authClient.refreshAccessToken({ refreshToken });
|
||||
}
|
||||
|
||||
@Post('change-password')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async changePassword(
|
||||
@Body() body: AuthChangePasswordRequest,
|
||||
@Headers() headers,
|
||||
) {
|
||||
this.logger.log(`/auth`, 'change-password');
|
||||
|
||||
const { oldPassword, newPassword } = body;
|
||||
const { authorization: accessToken } = headers;
|
||||
|
||||
return this.authClient.changePassword({
|
||||
accessToken,
|
||||
oldPassword,
|
||||
newPassword,
|
||||
});
|
||||
}
|
||||
|
||||
@Post('reset-password')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async resetPassword(@Body() body: AuthResetPasswordRequest) {
|
||||
this.logger.log(`/auth`, 'reset-password');
|
||||
|
||||
const { username } = body;
|
||||
|
||||
return this.authClient.resetPassword({ username });
|
||||
}
|
||||
|
||||
@Post('verify-reset-password-code')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async verifyResetPasswordCode(
|
||||
@Body() body: AuthVerifyResetPasswordCodeRequest,
|
||||
) {
|
||||
this.logger.log(`/auth`, 'verify-reset-password-code');
|
||||
|
||||
const { username, code } = body;
|
||||
|
||||
return this.authClient.verifyResetPasswordCode({ username, code });
|
||||
}
|
||||
|
||||
@Post('confirm-reset-password')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async confirmResetPassword(@Body() body: AuthConfirmResetPasswordRequest) {
|
||||
this.logger.log(`/auth`, 'confirm-reset-password');
|
||||
|
||||
const { username, code, newPassword } = body;
|
||||
|
||||
return this.authClient.confirmResetPassword({
|
||||
username,
|
||||
code,
|
||||
newPassword,
|
||||
});
|
||||
}
|
||||
|
||||
@Post('enable-totp')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async enableTotpMFA(
|
||||
@Body() body: AuthEnableTotpMfaRequest,
|
||||
@Headers() headers,
|
||||
) {
|
||||
this.logger.log(`/auth`, 'enable-totp');
|
||||
|
||||
const { password } = body;
|
||||
const { authorization: accessToken } = headers;
|
||||
|
||||
return this.authClient.enableTotpMFA({ accessToken, password });
|
||||
}
|
||||
|
||||
@Post('disable-totp')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async disableTotpMFA(
|
||||
@Body() body: AuthDisableTotpMfaRequest,
|
||||
@Headers() headers,
|
||||
) {
|
||||
this.logger.log(`/auth`, 'disable-totp');
|
||||
|
||||
const { password } = body;
|
||||
const { authorization: accessToken } = headers;
|
||||
|
||||
return this.authClient.disableTotpMFA({ accessToken, password });
|
||||
}
|
||||
|
||||
@Post('dismiss-totp')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async dismissTotpMFA(@Headers() headers) {
|
||||
this.logger.log(`/auth`, 'disable-totp');
|
||||
|
||||
const { authorization: accessToken } = headers;
|
||||
|
||||
return this.authClient.dismissTotpMFA({ accessToken });
|
||||
}
|
||||
|
||||
@Post('verify-totp')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async verifyTotp(@Body() body: AuthVerifyTotpMfaRequest, @Headers() headers) {
|
||||
this.logger.log(`/auth`, 'enable-totp');
|
||||
|
||||
const { totp } = body;
|
||||
const { authorization: accessToken } = headers;
|
||||
|
||||
return this.authClient.verifyTotp({ accessToken, totp });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,324 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Param,
|
||||
Post,
|
||||
Query,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { AuthenticateCondition } from '../../authentication/authentication.decorator';
|
||||
import { Permissions } from '../../authentication/permissions.enum';
|
||||
import { CatalogService } from './catalog.service';
|
||||
|
||||
@ApiTags('Catalog')
|
||||
@Controller('catalog')
|
||||
@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.CATALOG[action].seqid);
|
||||
})
|
||||
export class CatalogController {
|
||||
constructor(private catalogService: CatalogService) {}
|
||||
|
||||
@Get('all')
|
||||
async catalogAll(@Body() body) {
|
||||
console.log(`/catalog`, 'ON CATALOG ALL ROUTE');
|
||||
|
||||
const res = await this.catalogService.catalogAll(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('data_apps')
|
||||
async dataAppsAll(@Body() body) {
|
||||
console.log(`/catalog`, 'ON FIND ALL DATA APPS ROUTE');
|
||||
|
||||
const res = await this.catalogService.dataAppsAll(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Delete('data_apps/:id')
|
||||
async dataAppsOne(@Param() params, @Body() body) {
|
||||
console.log(`/catalog`, 'ON FIND ONE DATA APP ROUTE');
|
||||
const { id } = params;
|
||||
|
||||
const res = await this.catalogService.dataAppsOne(id, body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('dashboard-metabase')
|
||||
async getAllDashboardMetabase(@Body() body) {
|
||||
console.log(`/catalog`, 'ON GET ALL DASHBOARDS METABASE ROUTE');
|
||||
|
||||
const res = await this.catalogService.getAllDashboardMetabase(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('dashboard-metabase/:id')
|
||||
async getOneDashboardMetabase(@Body() body, @Param() params) {
|
||||
const { id } = params;
|
||||
console.log(`/catalog`, 'ON GET ONE DASHBOARD METABASE ROUTE');
|
||||
|
||||
const res = await this.catalogService.getOneDashboardMetabase(id, body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('table-metadata')
|
||||
async getAllTableMetadata(@Body() body, @Query() query) {
|
||||
console.log(`/catalog`, 'ON GET ALL TABLES METADATA ROUTE');
|
||||
|
||||
if (!query) {
|
||||
const res = await this.catalogService.getAllTableMetadata(body);
|
||||
return res;
|
||||
} else {
|
||||
const res = await this.catalogService.getOneTableMetadata(body, query);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
@Delete('table-metadata/:id')
|
||||
async deleteOneTableMetadata(@Param() params, @Body() body) {
|
||||
const { id } = params;
|
||||
console.log(`/catalog`, 'ON DELETE ONE TABLE METADATA ROUTE');
|
||||
|
||||
const res = await this.catalogService.deleteOneTableMetadata(id, body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('column-metadata')
|
||||
async getOneColumnMetadata(@Body() body, @Query() params) {
|
||||
console.log(`/catalog`, 'ON GET ONE COLUMN METADATA ROUTE');
|
||||
|
||||
const res = await this.catalogService.getOneColumnMetadata(body, params);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Delete('column-metadata/:id')
|
||||
async deleteOneColumnMetadata(@Param() params, @Body() body) {
|
||||
console.log(`/catalog`, 'ON DELETE ONE COLUMN METADATA ROUTE');
|
||||
const { id } = params;
|
||||
|
||||
const res = await this.catalogService.deleteOneColumnMetadata(id, body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('data-preview')
|
||||
async getOneDataPreview(@Body() body, @Query() params) {
|
||||
console.log(`/catalog`, 'ON GET ONE DATAPREVIEW ROUTE');
|
||||
|
||||
const res = await this.catalogService.getOneDataPreview(body, params);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('data-status')
|
||||
async getDataStatus(@Body() body) {
|
||||
console.log(`/catalog`, 'ON GET DATA STATUS ROUTE');
|
||||
|
||||
const res = await this.catalogService.getDataStatus(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('data-status')
|
||||
async createDataStatus(@Body() body) {
|
||||
console.log(`/catalog`, 'ON CREATE DATA STATUS ROUTE');
|
||||
|
||||
const res = await this.catalogService.createDataStatus(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('data-description')
|
||||
async getDataDescription(@Body() body) {
|
||||
console.log(`/catalog`, 'ON GET DATA DESCRIPTION ROUTE');
|
||||
|
||||
const res = await this.catalogService.getDataDescription(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Post('data-description')
|
||||
async createDataDescription(@Body() body) {
|
||||
console.log(`/catalog`, 'ON CREATE DATA DESCRIPTION ROUTE');
|
||||
|
||||
const res = await this.catalogService.createDataDescription(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('data-docs')
|
||||
async getDataDocs(@Body() body) {
|
||||
console.log(`/catalog`, 'ON GET DATA DOCS ROUTE');
|
||||
|
||||
const res = await this.catalogService.getDataDocs(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Post('data-docs')
|
||||
async createDataDocs(@Body() body) {
|
||||
console.log(`/catalog`, 'ON CREATE DATA DOCS ROUTE');
|
||||
|
||||
const res = await this.catalogService.createDataDocs(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('data-rating')
|
||||
async getDataRating(@Body() body) {
|
||||
console.log(`/catalog`, 'ON GET DATA RATING ROUTE');
|
||||
|
||||
const res = await this.catalogService.getDataRating(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Post('data-rating')
|
||||
async createDataRating(@Body() body) {
|
||||
console.log(`/catalog`, 'ON GET DATA RATING ROUTE');
|
||||
|
||||
const res = await this.catalogService.createDataRating(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('summary-rating/:id')
|
||||
async getSummaryRating() {
|
||||
console.log(`/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) {
|
||||
console.log(`/catalog`, 'ON GET DATA COMMENT ROUTE');
|
||||
|
||||
const res = await this.catalogService.getDataComment(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Post('data-comment')
|
||||
async createDataComment(@Body() body) {
|
||||
console.log(`/catalog`, 'ON GET DATA COMMENT ROUTE');
|
||||
|
||||
const res = await this.catalogService.createDataComment(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('data-review')
|
||||
async getDataReview(@Body() body, @Query() params) {
|
||||
console.log(`/catalog`, 'ON GET DATA REVIEW ROUTE');
|
||||
|
||||
const res = await this.catalogService.getDataReview(body, params);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Post('tags')
|
||||
async createTags(@Body() body) {
|
||||
console.log(`/catalog`, 'ON CREATE TAG ROUTE');
|
||||
|
||||
const res = await this.catalogService.createTags(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('tags')
|
||||
async findAllTags(@Body() body) {
|
||||
console.log(`/catalog`, 'ON FIND ALL TAGS ROUTE');
|
||||
|
||||
const res = await this.catalogService.findAllTags(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Delete('tags/:id')
|
||||
async deleteTags(@Param() params, @Body() body) {
|
||||
console.log(`/catalog`, 'ON DELETE TAG ROUTE');
|
||||
const { id } = params;
|
||||
|
||||
const res = await this.catalogService.deleteTags(id, body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Post('table-tags')
|
||||
async createTableTags(@Body() body) {
|
||||
console.log(`/catalog`, 'ON CREATE TABLE TAG ROUTE');
|
||||
|
||||
const res = await this.catalogService.createTableTags(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('table-tags')
|
||||
async getAllTableTags(@Body() body) {
|
||||
console.log(`/catalog`, 'ON GET ALL TABLE TAGS ROUTE');
|
||||
|
||||
const res = await this.catalogService.findAllTableTags(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Delete('table-tags/:id')
|
||||
async deleteTableTags(@Param() params, @Body() body) {
|
||||
console.log(`/catalog`, 'ON CREATE TABLE TAGS ROUTE');
|
||||
const { id } = params;
|
||||
|
||||
const res = await this.catalogService.deleteTableTags(id, body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Get('table-rules')
|
||||
async getTableRules(@Body() body) {
|
||||
console.log(`/catalog`, 'ON GET TABLE RULES ROUTE');
|
||||
|
||||
const res = await this.catalogService.getTableRules(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Delete('table-rules/:id')
|
||||
async deleteTableRules(@Param() params, @Body() body) {
|
||||
console.log(`/catalog`, 'ON DELETE TABLE RULES ROUTE');
|
||||
const { id } = params;
|
||||
|
||||
const res = await this.catalogService.deleteTableRules(id, body);
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
import axios from 'axios';
|
||||
|
||||
class CatalogService {
|
||||
_getNimbusUrl(body) {
|
||||
const customer = body.info.customer.toLowerCase();
|
||||
|
||||
if (process.env.ENV === 'prd') {
|
||||
return `https://nimbus-${customer}.dadosfera.ai`;
|
||||
}
|
||||
|
||||
return `https://nimbus-${customer}.${process.env.ENV}.dadosfera.ai`;
|
||||
}
|
||||
|
||||
async catalogAll(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(`${nimbusUrl}/api/catalog/all/`);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async dataAppsAll(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(`${nimbusUrl}/api/catalog/data_apps/`);
|
||||
return data;
|
||||
}
|
||||
|
||||
async dataAppsOne(id, body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(
|
||||
`${nimbusUrl}/api/catalog/data_apps/${id}/`,
|
||||
);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async getAllDashboardMetabase(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(
|
||||
`${nimbusUrl}/api/catalog/dashboard-metabase/`,
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
async getOneDashboardMetabase(id, body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(
|
||||
`${nimbusUrl}/api/catalog/dashboard-metabase/${id}`,
|
||||
);
|
||||
console.log(data);
|
||||
|
||||
// const [, path] = data.iframe_url.split('.dadosfera');
|
||||
// const host = `httpss://metabase-${body.info.customer.toLowerCase()}.dadosfera.ai`;
|
||||
// data.iframe_url = host + path;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async getAllTableMetadata(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(
|
||||
`${nimbusUrl}/api/catalog/table-metadata/`,
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
async getOneTableMetadata(body, params) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(
|
||||
`${nimbusUrl}/api/catalog/table-metadata/`,
|
||||
{ params: params },
|
||||
);
|
||||
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) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.post(
|
||||
`${nimbusUrl}/api/catalog/data-description/`,
|
||||
body,
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
async getDataDocs(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(`${nimbusUrl}/api/catalog/data-docs/`);
|
||||
return data;
|
||||
}
|
||||
|
||||
async createDataDocs(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.post(
|
||||
`${nimbusUrl}/api/catalog/data-docs/`,
|
||||
body,
|
||||
);
|
||||
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(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.post(`${nimbusUrl}/api/catalog/tags/`, body);
|
||||
return data;
|
||||
}
|
||||
|
||||
async findAllTags(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(`${nimbusUrl}/api/catalog/tags/`, body);
|
||||
return data;
|
||||
}
|
||||
|
||||
async findAllTableTags(body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.get(
|
||||
`${nimbusUrl}/api/catalog/table-tags/`,
|
||||
body,
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
async deleteTags(id, body) {
|
||||
const nimbusUrl = this._getNimbusUrl(body);
|
||||
const { data } = await axios.delete(`${nimbusUrl}/api/catalog/tags/${id}`);
|
||||
return data;
|
||||
}
|
||||
|
||||
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 };
|
||||
@@ -1,12 +1,15 @@
|
||||
import { Controller, Get } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { HealthService } from './health.service';
|
||||
|
||||
@ApiTags('Health')
|
||||
@Controller('health')
|
||||
export class HealthController {
|
||||
constructor(private readonly healthService: HealthService) {}
|
||||
|
||||
@Get()
|
||||
check() {
|
||||
console.log(`/health`, 'check');
|
||||
return this.healthService.check();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
describe('PipelinesGrpcServerService', () => {
|
||||
it('should be defined', () => {
|
||||
expect(2 + 2).toBe(4);
|
||||
});
|
||||
});
|
||||
@@ -3,6 +3,7 @@ import { Injectable } from '@nestjs/common';
|
||||
@Injectable()
|
||||
export class HealthService {
|
||||
check() {
|
||||
console.log('HEALTH');
|
||||
return { message: 'Ok' };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||
import { Method } from 'axios';
|
||||
|
||||
export class InputModel {
|
||||
category: string;
|
||||
plugin: string;
|
||||
name: string;
|
||||
cron?: string;
|
||||
credentials?: {
|
||||
connection_type: string;
|
||||
oauth: string;
|
||||
oauth_code: string;
|
||||
start_date: string;
|
||||
};
|
||||
options?: {
|
||||
oauth?: {
|
||||
get_tokens_url: string;
|
||||
get_tokens_method?: Method;
|
||||
get_tokens_url_params: string;
|
||||
get_tokens_set_response: Record<string, string>;
|
||||
content_type: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
class GoogleAnalyticsClientSecrets {
|
||||
@ApiProperty()
|
||||
type: string;
|
||||
@ApiProperty()
|
||||
project_id: string;
|
||||
@ApiProperty()
|
||||
private_key_id: string;
|
||||
@ApiProperty()
|
||||
private_key: string;
|
||||
@ApiProperty()
|
||||
client_email: string;
|
||||
@ApiProperty()
|
||||
client_id: string;
|
||||
@ApiProperty()
|
||||
auth_uri: string;
|
||||
@ApiProperty()
|
||||
token_uri: string;
|
||||
@ApiProperty()
|
||||
auth_provider_x509_cert_url: string;
|
||||
@ApiProperty()
|
||||
client_x509_cert_url: string;
|
||||
}
|
||||
class OauthObject {
|
||||
@ApiPropertyOptional()
|
||||
get_tokens_url: string;
|
||||
@ApiPropertyOptional()
|
||||
get_tokens_url_params: string;
|
||||
@ApiPropertyOptional()
|
||||
get_tokens_set_response: Record<string, any>;
|
||||
@ApiPropertyOptional()
|
||||
content_type: string;
|
||||
}
|
||||
class InputOptions {
|
||||
@ApiPropertyOptional()
|
||||
oauth: OauthObject;
|
||||
@ApiPropertyOptional()
|
||||
skip_select_columns: true;
|
||||
@ApiPropertyOptional()
|
||||
skip_select_entities: false;
|
||||
@ApiPropertyOptional()
|
||||
skip_transformation: true;
|
||||
}
|
||||
|
||||
class CredentialsJdbc {
|
||||
@ApiPropertyOptional()
|
||||
jdbc_user: string;
|
||||
@ApiPropertyOptional()
|
||||
jdbc_password: string;
|
||||
@ApiPropertyOptional()
|
||||
database: string;
|
||||
@ApiPropertyOptional()
|
||||
endpoint: string;
|
||||
@ApiPropertyOptional()
|
||||
port: string;
|
||||
@ApiPropertyOptional()
|
||||
engine: string;
|
||||
@ApiPropertyOptional()
|
||||
schema: string;
|
||||
}
|
||||
class FileFormatParams {
|
||||
@ApiPropertyOptional()
|
||||
file_format: string;
|
||||
@ApiPropertyOptional()
|
||||
encoding: string;
|
||||
}
|
||||
|
||||
class Credentials extends CredentialsJdbc {
|
||||
@ApiProperty()
|
||||
connection_type: string;
|
||||
|
||||
@ApiPropertyOptional()
|
||||
client_aws_access_key_id: string;
|
||||
@ApiPropertyOptional()
|
||||
client_aws_secret_access_key: string;
|
||||
@ApiPropertyOptional()
|
||||
client_bucket: string;
|
||||
@ApiPropertyOptional()
|
||||
file_to_extract: string;
|
||||
@ApiPropertyOptional()
|
||||
file_format_params: FileFormatParams;
|
||||
|
||||
@ApiPropertyOptional()
|
||||
view_id: string;
|
||||
@ApiPropertyOptional()
|
||||
client_secrets: GoogleAnalyticsClientSecrets;
|
||||
@ApiPropertyOptional()
|
||||
start_date: string;
|
||||
@ApiPropertyOptional()
|
||||
end_date: string;
|
||||
|
||||
@ApiPropertyOptional()
|
||||
oauth_code: string;
|
||||
}
|
||||
class Column {
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
@ApiProperty()
|
||||
type: string;
|
||||
}
|
||||
class TableColumns {
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
@ApiProperty()
|
||||
columns: Column[];
|
||||
@ApiProperty()
|
||||
references: Column[];
|
||||
}
|
||||
export class GetAvailableEntitiesReq {
|
||||
@ApiProperty()
|
||||
plugin: string;
|
||||
}
|
||||
|
||||
export class GetAvailableEntitiesRes {
|
||||
@ApiProperty()
|
||||
entities: string[];
|
||||
}
|
||||
|
||||
export class TestConnectionGetColumnsReq {
|
||||
@ApiProperty()
|
||||
plugin: string;
|
||||
@ApiProperty()
|
||||
tables: string[];
|
||||
@ApiPropertyOptional()
|
||||
credentials: CredentialsJdbc;
|
||||
@ApiPropertyOptional()
|
||||
id: string;
|
||||
}
|
||||
export class TestConnectionGetColumnsRes {
|
||||
@ApiProperty()
|
||||
tables: TableColumns[];
|
||||
}
|
||||
|
||||
export class TestConnectionReq {
|
||||
@ApiProperty()
|
||||
plugin: string;
|
||||
@ApiProperty()
|
||||
credentials: CredentialsJdbc;
|
||||
}
|
||||
export class TestConnectionRes {
|
||||
@ApiProperty()
|
||||
connection_state: boolean;
|
||||
@ApiProperty()
|
||||
total_entities: number;
|
||||
@ApiProperty()
|
||||
database_tables: string[];
|
||||
}
|
||||
export class CreateInputReq {
|
||||
@ApiPropertyOptional()
|
||||
id: string;
|
||||
@ApiProperty()
|
||||
plugin: string;
|
||||
@ApiProperty()
|
||||
category: string;
|
||||
@ApiProperty()
|
||||
credentials: Credentials;
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
@ApiPropertyOptional()
|
||||
options: InputOptions;
|
||||
}
|
||||
|
||||
export class Input {
|
||||
@ApiProperty()
|
||||
id: string;
|
||||
@ApiProperty()
|
||||
category: string;
|
||||
@ApiProperty()
|
||||
plugin: string;
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
@ApiProperty()
|
||||
cron: string;
|
||||
@ApiProperty()
|
||||
credentials: Credentials;
|
||||
@ApiProperty()
|
||||
client_id: string;
|
||||
@ApiProperty()
|
||||
created_at: string;
|
||||
@ApiProperty()
|
||||
updated_at: string;
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Param,
|
||||
Patch,
|
||||
Post,
|
||||
} from '@nestjs/common';
|
||||
import { InputsService } from './inputs.service';
|
||||
import { InputsClientService } from 'src/clients/inputs/client.service';
|
||||
import { UpdateInputRequest } from 'src/clients/inputs/interfaces';
|
||||
import { InputNewCreateRequest } from '@victorradael/protospack';
|
||||
import { Permissions } from '../../authentication/permissions.enum';
|
||||
import { AuthenticateCondition } from 'src/authentication/authentication.decorator';
|
||||
import { ApiOkResponse, ApiTags } from '@nestjs/swagger';
|
||||
import {
|
||||
CreateInputReq,
|
||||
GetAvailableEntitiesReq,
|
||||
GetAvailableEntitiesRes,
|
||||
Input,
|
||||
TestConnectionGetColumnsReq,
|
||||
TestConnectionGetColumnsRes,
|
||||
TestConnectionReq,
|
||||
TestConnectionRes,
|
||||
} from './dtos/input.model';
|
||||
|
||||
@ApiTags('inputs')
|
||||
@Controller('inputs')
|
||||
@AuthenticateCondition((req, user) => {
|
||||
let action;
|
||||
|
||||
switch (req.method) {
|
||||
case 'POST':
|
||||
action = 'CREATE';
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
action = 'UPDATE';
|
||||
break;
|
||||
|
||||
case 'PATCH':
|
||||
action = 'UPDATE_PARTIAL';
|
||||
break;
|
||||
|
||||
default:
|
||||
action = req.method;
|
||||
}
|
||||
|
||||
if (
|
||||
`${req.method} ${req.route.path}` ===
|
||||
'GET /inputs/available-entities/:plugin'
|
||||
) {
|
||||
action = 'GET_ENTITIES';
|
||||
}
|
||||
|
||||
return user.permissions.includes(Permissions.INPUT[action].seqid);
|
||||
})
|
||||
export class InputsController {
|
||||
inputService: InputsService;
|
||||
constructor(private inputsClientService: InputsClientService) {
|
||||
this.inputService = new InputsService(this.inputsClientService);
|
||||
}
|
||||
|
||||
@Get('available-entities/:plugin')
|
||||
@ApiOkResponse({ type: GetAvailableEntitiesRes })
|
||||
async getAvailableEntities(
|
||||
@Body() body,
|
||||
@Param() params: GetAvailableEntitiesReq,
|
||||
) {
|
||||
const { info } = body;
|
||||
const { plugin } = params;
|
||||
return await this.inputService.getAvailableEntities({ info, plugin });
|
||||
}
|
||||
|
||||
@Post('/test-connection')
|
||||
@ApiOkResponse({ type: TestConnectionRes })
|
||||
async testConnection(@Body() data: TestConnectionReq) {
|
||||
console.log(`/test-connection`, 'ON TEST CONNECTION ROUTE');
|
||||
|
||||
const response = await this.inputService.testConnection(data);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Post('/test-connection/get-columns')
|
||||
@ApiOkResponse({ type: TestConnectionGetColumnsRes })
|
||||
async getColumns(@Body() data: TestConnectionGetColumnsReq) {
|
||||
console.log(
|
||||
`/test-connection/get-columns`,
|
||||
'ON TEST CONNECTION GET COLUMNS ROUTE',
|
||||
);
|
||||
|
||||
const response = await this.inputService.getColumns(data);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Post()
|
||||
@ApiOkResponse({ type: Input })
|
||||
async create(@Body() createInputDto: CreateInputReq) {
|
||||
console.log(`/input`, 'ON CREATE ROUTE');
|
||||
|
||||
const response = await this.inputService.create(createInputDto);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Post(':id')
|
||||
@ApiOkResponse({ type: Input })
|
||||
async reCreate(@Param('id') id: string, @Body() input: CreateInputReq) {
|
||||
if (!input.id) input.id = id;
|
||||
console.log(`POST /${input.id}`, 'ON RECREATE ROUTE');
|
||||
|
||||
const response = await this.inputService.reCreate(input);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Get()
|
||||
async findAll(@Body() body) {
|
||||
console.log(`/input`, 'ON FIND ALL ROUTE');
|
||||
|
||||
const response = await this.inputService.findAll(body);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Get('/:id')
|
||||
async findOne(@Body() body, @Param() params) {
|
||||
const { id } = params;
|
||||
console.log(`/input/${id}`, 'ON FIND ONE ROUTE');
|
||||
|
||||
const response = await this.inputService.findOne({ id, ...body });
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Patch(':id')
|
||||
async update(@Body() updateInputDto: UpdateInputRequest, @Param() params) {
|
||||
const { id } = params;
|
||||
const { info } = updateInputDto;
|
||||
delete updateInputDto.info;
|
||||
|
||||
console.log(`/input/${id}`, 'ON UPDATE ROUTE');
|
||||
|
||||
const response = await this.inputService.update(id, updateInputDto, info);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
async delete(@Body() data, @Param() params) {
|
||||
const { id } = params;
|
||||
|
||||
console.log(`/input/${id}`, 'ON DELETE ROUTE');
|
||||
|
||||
const response = await this.inputService.remove({ id, ...data });
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
describe('PipelinesGrpcServerService', () => {
|
||||
it('should be defined', () => {
|
||||
expect(2 + 2).toBe(4);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,194 @@
|
||||
import { Body, HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||
import { Timeout } from '@nestjs/schedule';
|
||||
import { DecodeGrpcStruct } from '@victorradael/protospack';
|
||||
import CronParser, { CronExpression } from 'cron-parser';
|
||||
import { InputsClientService } from 'src/clients/inputs/client.service';
|
||||
import { IIdRequest, Info } from 'src/clients/inputs/interfaces';
|
||||
|
||||
@Injectable()
|
||||
export class InputsService {
|
||||
constructor(private inputClient: InputsClientService) {}
|
||||
secondsInADay = 60 * 60 * 24;
|
||||
secondsInAnHour = 60 * 60;
|
||||
|
||||
adjustInputPayload(payload) {
|
||||
if (payload?.input_generic) return DecodeGrpcStruct(payload.input_generic);
|
||||
if (!payload.input_s3 && !payload.input_jdbc) return payload;
|
||||
return payload?.input_s3 || payload?.input_jdbc;
|
||||
}
|
||||
getDifferenceInSeconds(date1: Date, date2: Date) {
|
||||
const diffInMs = Math.abs(date2.getTime() - date1.getTime());
|
||||
return diffInMs / 1000;
|
||||
}
|
||||
validateCron(data) {
|
||||
const { info, cron } = data;
|
||||
const { customer_tier } = info;
|
||||
if (!cron) return;
|
||||
let interval: CronExpression;
|
||||
try {
|
||||
interval = CronParser.parseExpression(cron);
|
||||
} catch (error) {
|
||||
throw new HttpException(
|
||||
'Intervalo de tempo inválido',
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
}
|
||||
const nextDate = interval.next().toDate();
|
||||
const afterNextDate = interval.next().toDate();
|
||||
const secondsApart = this.getDifferenceInSeconds(nextDate, afterNextDate);
|
||||
if (customer_tier === 'BASIC' && secondsApart < this.secondsInADay) {
|
||||
throw new HttpException(
|
||||
'Intervalo de tempo não pode ser inferior a um dia.',
|
||||
HttpStatus.FORBIDDEN,
|
||||
);
|
||||
} else if (secondsApart < this.secondsInAnHour) {
|
||||
throw new HttpException(
|
||||
'Intervalo de tempo não pode ser inferior a uma hora.',
|
||||
HttpStatus.FORBIDDEN,
|
||||
);
|
||||
}
|
||||
}
|
||||
async create(@Body() data) {
|
||||
this.validateCron(data);
|
||||
let response;
|
||||
switch (data.plugin.toLowerCase()) {
|
||||
case 'csv':
|
||||
case 'json':
|
||||
case 'parquet':
|
||||
const { info, ...input } = data;
|
||||
const inputPayload = this.generateInputS3Payload(input);
|
||||
response = await this.inputClient.createS3Inputs({
|
||||
input: inputPayload,
|
||||
info,
|
||||
});
|
||||
break;
|
||||
case 'oracle':
|
||||
case 'mysql':
|
||||
case 'postgresql':
|
||||
case 'sqlserver':
|
||||
response = await this.inputClient.newCreate(data);
|
||||
break;
|
||||
default:
|
||||
response = await this.inputClient.createGeneric(data);
|
||||
break;
|
||||
}
|
||||
const adjustedInput = this.adjustInputPayload(response.input);
|
||||
return { ...response, input: adjustedInput };
|
||||
}
|
||||
async reCreate(data) {
|
||||
const { info, cron } = data;
|
||||
if (cron) this.validateCron({ info, cron });
|
||||
const response = await this.inputClient.createGeneric(data);
|
||||
const adjustedInput = this.adjustInputPayload(response.input);
|
||||
return { ...response, input: adjustedInput };
|
||||
}
|
||||
async getAvailableEntities(data): Promise<{ entities: string[] }> {
|
||||
return await this.inputClient.getAvailableEntities(data);
|
||||
}
|
||||
async findAll(body) {
|
||||
try {
|
||||
const findAllInputResponse: any = await this.inputClient.findAll(body);
|
||||
if (findAllInputResponse?.inputs?.length) {
|
||||
findAllInputResponse.inputs = findAllInputResponse.inputs.map((input) =>
|
||||
this.adjustInputPayload(input),
|
||||
);
|
||||
}
|
||||
return findAllInputResponse;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
async findOne(idRequest: IIdRequest) {
|
||||
try {
|
||||
const findOneInputResponse: any = await this.inputClient.findOne(
|
||||
idRequest,
|
||||
);
|
||||
findOneInputResponse.input = this.adjustInputPayload(
|
||||
findOneInputResponse.input,
|
||||
);
|
||||
return findOneInputResponse;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
async update(id: string, data, info: Info) {
|
||||
this.validateCron({ ...data, info });
|
||||
try {
|
||||
const updateInputResponse: any = await this.inputClient.update({
|
||||
id,
|
||||
info,
|
||||
...data,
|
||||
});
|
||||
|
||||
updateInputResponse.input = this.adjustInputPayload(
|
||||
updateInputResponse?.input,
|
||||
);
|
||||
return updateInputResponse;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
async remove(idRequest: IIdRequest) {
|
||||
try {
|
||||
const removeInputResponse = await this.inputClient.remove(idRequest);
|
||||
|
||||
return removeInputResponse;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
@Timeout(60000 * 10) // Timeout set for 10 minutes
|
||||
async testConnection(data) {
|
||||
try {
|
||||
const testConnectionInputResponse = await this.inputClient.testConnection(
|
||||
data,
|
||||
);
|
||||
|
||||
return testConnectionInputResponse;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
async getColumns(data) {
|
||||
try {
|
||||
const testConnectionGetColumnsResponse =
|
||||
await this.inputClient.getColumns(data);
|
||||
|
||||
return testConnectionGetColumnsResponse;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
generateInputS3Payload(payload) {
|
||||
const { credentials, plugin, cron } = payload;
|
||||
if (!credentials) return payload;
|
||||
|
||||
const {
|
||||
client_aws_access_key_id,
|
||||
client_aws_secret_access_key,
|
||||
file_format_params,
|
||||
format_file_params,
|
||||
client_bucket,
|
||||
file_to_extract,
|
||||
} = credentials;
|
||||
|
||||
const formatedPayload = {
|
||||
plugin,
|
||||
cron,
|
||||
source_bucket: client_bucket,
|
||||
source_prefix: file_to_extract,
|
||||
auth_parameters: {
|
||||
aws_access_key_id: client_aws_access_key_id,
|
||||
aws_secret_access_key: client_aws_secret_access_key,
|
||||
},
|
||||
file_format_params: file_format_params || format_file_params,
|
||||
};
|
||||
return formatedPayload;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import {
|
||||
BadRequestException,
|
||||
Controller,
|
||||
Get,
|
||||
Query,
|
||||
Redirect,
|
||||
Req,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
import { InputsClientService } from 'src/clients/inputs/client.service';
|
||||
import { InputsService } from '../inputs/inputs.service';
|
||||
|
||||
@ApiTags('oauth')
|
||||
@Controller('oauth')
|
||||
export class OauthController {
|
||||
inputService: InputsService;
|
||||
frontendRedirectUri = '';
|
||||
constructor(private inputsClientService: InputsClientService) {
|
||||
this.inputService = new InputsService(this.inputsClientService);
|
||||
switch (process.env.ENV) {
|
||||
case 'dev':
|
||||
case 'stg':
|
||||
this.frontendRedirectUri = `https://app.${process.env.ENV}.dadosfera.ai/coletix/auth-callback`;
|
||||
break;
|
||||
case 'prd':
|
||||
this.frontendRedirectUri = `https://app.dadosfera.ai/coletix/auth-callback`;
|
||||
break;
|
||||
default:
|
||||
this.frontendRedirectUri = `http://localhost:4200/coletix/auth-callback`;
|
||||
}
|
||||
}
|
||||
@Get('hubspot')
|
||||
@UseGuards(AuthGuard('hubspot'))
|
||||
async oauthHubspot() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Get('hubspot/callback')
|
||||
@UseGuards(AuthGuard('hubspot'))
|
||||
@Redirect()
|
||||
async oauthHubspotCallback(@Req() req, @Query('state') customer_id) {
|
||||
const { authInfo } = req;
|
||||
if (!authInfo) throw new BadRequestException('Oauth tokens not found');
|
||||
const { accessToken, refreshToken } = authInfo;
|
||||
const response = await this.inputService.create({
|
||||
info: { customer_id, customer: 'customer', user_id: 'empty' },
|
||||
plugin: 'hubspot',
|
||||
credentials: { access_token: accessToken, refresh_token: refreshToken },
|
||||
});
|
||||
return { url: `${this.frontendRedirectUri}?input_id=${response.input.id}` };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Strategy } from 'passport-hubspot-oauth2';
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { OauthSecrets } from 'src/utils/OauthSecrets';
|
||||
|
||||
@Injectable()
|
||||
export class HubspotStrategy extends PassportStrategy(Strategy) {
|
||||
constructor(
|
||||
@Inject('OAUTH_SECRETS')
|
||||
private readonly oauthSecrets: OauthSecrets,
|
||||
) {
|
||||
super(
|
||||
{
|
||||
clientID: oauthSecrets.hubspot.client_id,
|
||||
clientSecret: oauthSecrets.hubspot.client_secret,
|
||||
callbackURL: oauthSecrets.hubspot.redirect_uri,
|
||||
redirectUri: oauthSecrets.hubspot.redirect_uri,
|
||||
scope:
|
||||
'automation business-intelligence oauth forms integration-sync sales-email-read crm.lists.read crm.objects.contacts.read crm.schemas.contacts.read crm.objects.companies.read crm.objects.deals.read crm.schemas.companies.read crm.schemas.deals.read crm.objects.owners.read crm.objects.quotes.read crm.schemas.quotes.read crm.objects.line_items.read crm.schemas.line_items.read',
|
||||
passReqToCallback: true,
|
||||
},
|
||||
(accessToken, refreshToken, tokenInfo, profile, done) => {
|
||||
return done(null, profile, { accessToken, refreshToken, tokenInfo });
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
authenticate(req, options) {
|
||||
const { customer_id } = req.query;
|
||||
options.state = customer_id;
|
||||
super.authenticate(req, options);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Param,
|
||||
Post,
|
||||
Put,
|
||||
} from '@nestjs/common';
|
||||
import { Payload } from '@nestjs/microservices';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { OutputsClientService } from 'src/clients/outputs/client.service';
|
||||
import { AuthenticateCondition } from 'src/authentication/authentication.decorator';
|
||||
import { Permissions } from '../../authentication/permissions.enum';
|
||||
import { OutputsService } from './outputs.service';
|
||||
|
||||
@ApiTags('Outputs')
|
||||
@Controller('outputs')
|
||||
@AuthenticateCondition((req, user) => {
|
||||
let action;
|
||||
|
||||
switch (req.method) {
|
||||
case 'POST':
|
||||
action = 'CREATE';
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
action = 'UPDATE';
|
||||
break;
|
||||
|
||||
default:
|
||||
action = req.method;
|
||||
}
|
||||
|
||||
return user.permissions.includes(Permissions.OUTPUT[action].seqid);
|
||||
})
|
||||
export class OutputsController {
|
||||
constructor(private outputsClientService: OutputsClientService) { }
|
||||
|
||||
@Post()
|
||||
async create(@Body() createOutputDto) {
|
||||
console.log(process.env.DEV_URL + `/output`, 'ON CREATE ROUTE');
|
||||
|
||||
const outputService = new OutputsService(this.outputsClientService);
|
||||
const response = await outputService.create(createOutputDto);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Get()
|
||||
async findAll(@Body() data) {
|
||||
console.log(process.env.DEV_URL + `/output`, 'ON Find All ROUTE');
|
||||
|
||||
const outputService = new OutputsService(this.outputsClientService);
|
||||
const response = await outputService.findAll(data);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Get('/:id')
|
||||
async findOne(@Body() data, @Param() params) {
|
||||
const { id } = params;
|
||||
console.log(process.env.DEV_URL + `/output/${id}`, 'ON Find One ROUTE');
|
||||
|
||||
const outputService = new OutputsService(this.outputsClientService);
|
||||
const response = await outputService.findOne({ id, ...data });
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Put(':id')
|
||||
async update(@Payload() updateOutputDto, @Param() params) {
|
||||
const { id } = params;
|
||||
const { info } = updateOutputDto;
|
||||
delete updateOutputDto.info;
|
||||
|
||||
console.log(process.env.DEV_URL + `/output/${id}`, 'ON UPDATE ROUTE');
|
||||
|
||||
const outputService = new OutputsService(this.outputsClientService);
|
||||
const response = await outputService.update(id, updateOutputDto, info);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
async delete(@Body() data, @Param() params) {
|
||||
const { id } = params;
|
||||
console.log(process.env.DEV_URL + `/output/${id}`, 'ON DELETE ROUTE');
|
||||
|
||||
const outputService = new OutputsService(this.outputsClientService);
|
||||
const response = await outputService.remove({ id, ...data });
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
describe('PipelinesGrpcServerService', () => {
|
||||
it('should be defined', () => {
|
||||
expect(2 + 2).toBe(4);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,63 @@
|
||||
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||
import { IIdRequest, Info } from 'src/clients/outputs/interfaces';
|
||||
import { OutputsClientService } from 'src/clients/outputs/client.service';
|
||||
|
||||
@Injectable()
|
||||
export class OutputsService {
|
||||
constructor(private outputClient: OutputsClientService) {}
|
||||
|
||||
async create(createOutputDto) {
|
||||
try {
|
||||
const createOutputResponse = await this.outputClient.create(
|
||||
createOutputDto,
|
||||
);
|
||||
|
||||
return createOutputResponse;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
async findOne(data: IIdRequest) {
|
||||
try {
|
||||
const findOneOutputResponse = await this.outputClient.findOne(data);
|
||||
return findOneOutputResponse;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
async findAll(data) {
|
||||
try {
|
||||
const findAllOutputResponse = await this.outputClient.findAll(data);
|
||||
|
||||
return findAllOutputResponse;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
async update(id: string, data, info: Info) {
|
||||
try {
|
||||
const updateOutputResponse = await this.outputClient.update({
|
||||
id,
|
||||
info,
|
||||
...data,
|
||||
});
|
||||
|
||||
return updateOutputResponse;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
async remove(data: IIdRequest) {
|
||||
try {
|
||||
const removeOutputResponse = await this.outputClient.remove(data);
|
||||
|
||||
return removeOutputResponse;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Param,
|
||||
Post,
|
||||
Put,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { PipelinesClientService } from 'src/clients/pipelines/client.service';
|
||||
import { AuthenticateCondition } from 'src/authentication/authentication.decorator';
|
||||
import { Permissions } from '../../authentication/permissions.enum';
|
||||
import { PipelinesService } from './pipelines.service';
|
||||
|
||||
@ApiTags('Pipelines')
|
||||
@Controller('pipelines')
|
||||
@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.PIPELINE[action].seqid);
|
||||
})
|
||||
export class PipelinesController {
|
||||
constructor(private pipelinesClientService: PipelinesClientService) {}
|
||||
|
||||
@Post('start/:id')
|
||||
async activate(@Param() params, @Body() body) {
|
||||
const { id } = params;
|
||||
const { info } = body;
|
||||
|
||||
console.log(
|
||||
process.env.DEV_URL + `/pipeline/start/${id}`,
|
||||
'ON START PIPELINE ROUTE',
|
||||
);
|
||||
|
||||
const pipelineService = new PipelinesService(this.pipelinesClientService);
|
||||
const response = await pipelineService.runPipeline({ id, info });
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Get(':id/status')
|
||||
async getPipelineStatus(@Body() body, @Param() params) {
|
||||
const { id } = params;
|
||||
body.id = id;
|
||||
|
||||
console.log(
|
||||
process.env.DEV_URL + `/pipeline/${id}`,
|
||||
'ON GET PIPELINE STATUS ROUTE',
|
||||
);
|
||||
|
||||
const pipelineService = new PipelinesService(this.pipelinesClientService);
|
||||
const response = await pipelineService.getPipelineStatus(body);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Get(':id/:details')
|
||||
async getPipelineLogs(@Param() params) {
|
||||
const { id, details } = params;
|
||||
console.log(
|
||||
process.env.DEV_URL + `/pipeline/${id}`,
|
||||
'ON GET PIPELINE LOGS ROUTE',
|
||||
);
|
||||
|
||||
const pipelineService = new PipelinesService(this.pipelinesClientService);
|
||||
const response = await pipelineService.getPipelineLogsMessages(id, details);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Post()
|
||||
async create(@Body() createPipelineDto) {
|
||||
console.log(process.env.DEV_URL + `/pipelines`, 'ON CREATE ROUTE');
|
||||
|
||||
const pipelineService = new PipelinesService(this.pipelinesClientService);
|
||||
const response = await pipelineService.create(createPipelineDto);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Get()
|
||||
async findAll(@Body() data) {
|
||||
console.log(process.env.DEV_URL + `/pipeline`, 'ON Find All ROUTE');
|
||||
|
||||
const pipelineService = new PipelinesService(this.pipelinesClientService);
|
||||
const response = await pipelineService.findAll(data);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Get('/:id')
|
||||
async findOne(@Body() data, @Param() params) {
|
||||
const { id } = params;
|
||||
console.log(process.env.DEV_URL + `/pipeline/${id}`, 'ON Find One ROUTE');
|
||||
|
||||
const pipelineService = new PipelinesService(this.pipelinesClientService);
|
||||
const response = await pipelineService.findOne({ id, ...data });
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Put(':id')
|
||||
async update(@Body() updatePipelineDto, @Param() params) {
|
||||
const { id } = params;
|
||||
const { info } = updatePipelineDto;
|
||||
delete updatePipelineDto.info;
|
||||
|
||||
console.log(process.env.DEV_URL + `/pipeline/${id}`, 'ON UPDATE ROUTE');
|
||||
|
||||
const pipelineService = new PipelinesService(this.pipelinesClientService);
|
||||
const response = await pipelineService.update(id, updatePipelineDto, info);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
async delete(@Body() data, @Param() params) {
|
||||
const { id } = params;
|
||||
console.log(process.env.DEV_URL + `/pipeline/${id}`, 'ON DELETE ROUTE');
|
||||
|
||||
const pipelineService = new PipelinesService(this.pipelinesClientService);
|
||||
const response = await pipelineService.remove({ id, ...data });
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
describe('PipelinesGrpcServerService', () => {
|
||||
it('should be defined', () => {
|
||||
expect(2 + 2).toBe(4);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,123 @@
|
||||
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||
import { DecodeGrpcStruct } from '@victorradael/protospack';
|
||||
import { PipelinesClientService } from 'src/clients/pipelines/client.service';
|
||||
import { IIdRequest, Info } from 'src/clients/pipelines/interfaces';
|
||||
import { objectCamelToSnake } from 'src/utils/CaseConverter';
|
||||
|
||||
@Injectable()
|
||||
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) {
|
||||
try {
|
||||
const createPipelineResponse = await this.pipelineClient.create(
|
||||
createPipelineDto,
|
||||
);
|
||||
|
||||
const pipeline = objectCamelToSnake(createPipelineResponse);
|
||||
this.adjustPayload(pipeline.pipeline);
|
||||
|
||||
return pipeline;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
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 findAllPipelineResponse = await this.pipelineClient.findAll(data);
|
||||
|
||||
const pipelines = objectCamelToSnake(findAllPipelineResponse);
|
||||
pipelines.forEach((pipeline) => {
|
||||
this.adjustPayload(pipeline);
|
||||
});
|
||||
return { 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 =
|
||||
await this.pipelineClient.getPipelineStatus(data);
|
||||
|
||||
return objectCamelToSnake(pipelineStatusResponse);
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
async runPipeline({ id, info }: IIdRequest) {
|
||||
try {
|
||||
const triggerPipelineResponse = await this.pipelineClient.runPipeline({
|
||||
id,
|
||||
info,
|
||||
});
|
||||
|
||||
return objectCamelToSnake(triggerPipelineResponse);
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Param,
|
||||
Post,
|
||||
Put,
|
||||
} from '@nestjs/common';
|
||||
import { Payload } from '@nestjs/microservices';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { TransformationsClientService } from 'src/clients/transformations/client.service';
|
||||
import { IIdRequest } from 'src/clients/transformations/interfaces';
|
||||
import { AuthenticateCondition } from 'src/authentication/authentication.decorator';
|
||||
import { Permissions } from '../../authentication/permissions.enum';
|
||||
import { TransformationsService } from './transformations.service';
|
||||
|
||||
@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.TRANSFORMATIONS[action].seqid);
|
||||
})
|
||||
export class TransformationsController {
|
||||
constructor(
|
||||
private transformationsClientService: TransformationsClientService,
|
||||
) {}
|
||||
|
||||
@Post()
|
||||
async create(@Body() createTransformationDto) {
|
||||
console.log(process.env.DEV_URL + `/transformation`, 'ON CREATE ROUTE');
|
||||
|
||||
const transformationService = new TransformationsService(
|
||||
this.transformationsClientService,
|
||||
);
|
||||
const response = await transformationService.create(
|
||||
createTransformationDto,
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Get()
|
||||
async findAll(@Body() data: IIdRequest) {
|
||||
console.log(process.env.DEV_URL + `/transformation`, 'ON Find All ROUTE');
|
||||
|
||||
const transformationService = new TransformationsService(
|
||||
this.transformationsClientService,
|
||||
);
|
||||
const response = await transformationService.findAll(data);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Get('/:id')
|
||||
async findOne(@Body() data, @Param() params) {
|
||||
const { id } = params;
|
||||
console.log(
|
||||
process.env.DEV_URL + `/transformation/${id}`,
|
||||
'ON Find One ROUTE',
|
||||
);
|
||||
|
||||
const transformationService = new TransformationsService(
|
||||
this.transformationsClientService,
|
||||
);
|
||||
const response = await transformationService.findOne({ id, ...data });
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Put(':id')
|
||||
async update(@Payload() updateTransformationDto, @Param() params) {
|
||||
const { id } = params;
|
||||
console.log(
|
||||
process.env.DEV_URL + `/transformation/${id}`,
|
||||
'ON UPDATE ROUTE',
|
||||
);
|
||||
|
||||
const transformationService = new TransformationsService(
|
||||
this.transformationsClientService,
|
||||
);
|
||||
const response = await transformationService.update(
|
||||
id,
|
||||
updateTransformationDto,
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
async delete(@Body() data, @Param() params) {
|
||||
const { id } = params;
|
||||
console.log(
|
||||
process.env.DEV_URL + `/transformation/${id}`,
|
||||
'ON DELETE ROUTE',
|
||||
);
|
||||
|
||||
const transformationService = new TransformationsService(
|
||||
this.transformationsClientService,
|
||||
);
|
||||
const response = await transformationService.remove({ id, ...data });
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
describe('PipelinesGrpcServerService', () => {
|
||||
it('should be defined', () => {
|
||||
expect(2 + 2).toBe(4);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,79 @@
|
||||
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||
import { TransformationsClientService } from 'src/clients/transformations/client.service';
|
||||
import {
|
||||
ICreateTransformationsRequest,
|
||||
IIdRequest,
|
||||
} from 'src/clients/transformations/interfaces';
|
||||
import { trSnakeToCamel } from 'src/utils/CaseConverter';
|
||||
|
||||
@Injectable()
|
||||
export class TransformationsService {
|
||||
constructor(private transformationClient: TransformationsClientService) {}
|
||||
|
||||
async create(createTransformationDto: ICreateTransformationsRequest) {
|
||||
const { transformations, info } = createTransformationDto;
|
||||
|
||||
if (!transformations || transformations.length == 0) {
|
||||
throw new HttpException('Missing transformations field.', 400);
|
||||
}
|
||||
|
||||
try {
|
||||
const convertedDTO = transformations.map((tr) => {
|
||||
return trSnakeToCamel(tr);
|
||||
});
|
||||
const createTransformationResponse =
|
||||
await this.transformationClient.create({
|
||||
transformations: convertedDTO,
|
||||
info: info,
|
||||
});
|
||||
|
||||
return createTransformationResponse;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
async findOne(data: IIdRequest) {
|
||||
try {
|
||||
const findOneTransformationResponse =
|
||||
await this.transformationClient.findOne(data);
|
||||
return findOneTransformationResponse;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
async findAll(data) {
|
||||
try {
|
||||
const findAllTransformationResponse =
|
||||
await this.transformationClient.findAll(data);
|
||||
|
||||
return findAllTransformationResponse;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
async update(id: string, data) {
|
||||
try {
|
||||
data.transformation['id'] = id;
|
||||
const updateTransformationResponse =
|
||||
await this.transformationClient.update({ ...data });
|
||||
|
||||
return updateTransformationResponse;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
async remove(data: IIdRequest) {
|
||||
try {
|
||||
const removeTransformationResponse =
|
||||
await this.transformationClient.remove(data);
|
||||
|
||||
return removeTransformationResponse;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import { join } from 'path';
|
||||
import { ClientOptions, Transport } from '@nestjs/microservices';
|
||||
|
||||
export const GrpcClientConfiguration: ClientOptions = {
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
//url: `${process.env.USERS_SVC_URL}:${process.env.USERS_SVC_PORT}`,
|
||||
url: `127.0.0.1:50053`,
|
||||
package: 'output',
|
||||
protoPath: join(__dirname, '..', 'proto', 'output.proto'),
|
||||
loader: {
|
||||
enums: String,
|
||||
objects: true,
|
||||
arrays: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,7 +0,0 @@
|
||||
export class CreateOutputDto {
|
||||
|
||||
name:string;
|
||||
plugin:string;
|
||||
values:string;
|
||||
operation:string;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
import { PartialType } from '@nestjs/mapped-types';
|
||||
import { CreateOutputDto } from './create-output.dto';
|
||||
|
||||
export class UpdateOutputDto extends PartialType(CreateOutputDto) {
|
||||
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
export class Output {
|
||||
|
||||
id:string;
|
||||
name:string;
|
||||
plugin:string;
|
||||
values:string;
|
||||
operation:string;
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { OutputsController } from './outputs.controller';
|
||||
import { OutputsService } from './outputs.service';
|
||||
|
||||
describe('OutputsController', () => {
|
||||
let controller: OutputsController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [OutputsController],
|
||||
providers: [OutputsService],
|
||||
}).compile();
|
||||
|
||||
controller = module.get<OutputsController>(OutputsController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -1,57 +0,0 @@
|
||||
import {
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
OnModuleInit,
|
||||
Param,
|
||||
Post,
|
||||
Put,
|
||||
} from '@nestjs/common';
|
||||
import {
|
||||
Client,
|
||||
ClientGrpc,
|
||||
MessagePattern,
|
||||
Payload,
|
||||
} from '@nestjs/microservices';
|
||||
import { OutputsService } from './outputs.service';
|
||||
import { CreateOutputDto } from './dto/create-output.dto';
|
||||
import { UpdateOutputDto } from './dto/update-output.dto';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { GrpcClientConfiguration } from './config/grpc-client';
|
||||
|
||||
@Controller('output')
|
||||
export class OutputsController implements OnModuleInit {
|
||||
@Client(GrpcClientConfiguration)
|
||||
private outputServiceClient: ClientGrpc;
|
||||
|
||||
private outputService: OutputsService;
|
||||
|
||||
onModuleInit() {
|
||||
this.outputService =
|
||||
this.outputServiceClient.getService<OutputsService>('OutputService');
|
||||
}
|
||||
@Post()
|
||||
create(@Payload() createOutputDto: CreateOutputDto) {
|
||||
return this.outputService.create(createOutputDto);
|
||||
}
|
||||
|
||||
@Get()
|
||||
list() {
|
||||
return this.outputService.list();
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
show(@Param() id: string) {
|
||||
return this.outputService.show(id);
|
||||
}
|
||||
|
||||
@Put(':id')
|
||||
update(@Param() id: string, @Payload() updateOutputDto: UpdateOutputDto) {
|
||||
return this.outputService.update(id, updateOutputDto);
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
remove(@Param() id: string) {
|
||||
return this.outputService.remove(id);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { OutputsService } from './outputs.service';
|
||||
import { OutputsController } from './outputs.controller';
|
||||
|
||||
@Module({
|
||||
controllers: [OutputsController],
|
||||
providers: [OutputsService],
|
||||
})
|
||||
export class OutputsModule {}
|
||||
@@ -1,18 +0,0 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { OutputsService } from './outputs.service';
|
||||
|
||||
describe('OutputsService', () => {
|
||||
let service: OutputsService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [OutputsService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<OutputsService>(OutputsService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -1,26 +0,0 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { CreateOutputDto } from './dto/create-output.dto';
|
||||
import { UpdateOutputDto } from './dto/update-output.dto';
|
||||
|
||||
@Injectable()
|
||||
export class OutputsService {
|
||||
create(createOutputDto: CreateOutputDto) {
|
||||
return 'This action adds a new output';
|
||||
}
|
||||
|
||||
list() {
|
||||
return `This action returns all outputs`;
|
||||
}
|
||||
|
||||
show(id: string) {
|
||||
return `This action returns a #${id} output`;
|
||||
}
|
||||
|
||||
update(id: string, updateOutputDto: UpdateOutputDto) {
|
||||
return `This action updates a #${id} output`;
|
||||
}
|
||||
|
||||
remove(id: string) {
|
||||
return `This action removes a #${id} output`;
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package output;
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
|
||||
service OutputService{
|
||||
rpc Create(CreateOutputRequest) returns (Output) {}
|
||||
rpc Show(IdRequest) returns (Output) {}
|
||||
rpc List(Empty) returns (ListResponse){}
|
||||
rpc Update(UpdateOutputRequest) returns (Output){}
|
||||
rpc Remove(IdRequest) returns (Empty){}
|
||||
}
|
||||
|
||||
|
||||
message Empty {}
|
||||
|
||||
message IdRequest{
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
message Output {
|
||||
string id = 1;
|
||||
string name = 2;
|
||||
string plugin = 3;
|
||||
string values = 4;
|
||||
string operation = 5;
|
||||
}
|
||||
|
||||
message CreateOutputRequest {
|
||||
string name = 1;
|
||||
string plugin = 2;
|
||||
string values = 3;
|
||||
string operation = 4;
|
||||
}
|
||||
|
||||
message UpdateOutputRequest{
|
||||
string id = 1;
|
||||
string name = 3;
|
||||
string plugin = 4;
|
||||
string values = 5;
|
||||
string operation = 6;
|
||||
}
|
||||
|
||||
message ListResponse {
|
||||
repeated Output outputs = 1;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import { join } from 'path';
|
||||
import { ClientOptions, Transport } from '@nestjs/microservices';
|
||||
|
||||
export const GrpcClientConfiguration: ClientOptions = {
|
||||
transport: Transport.GRPC,
|
||||
options: {
|
||||
//url: `${process.env.USERS_SVC_URL}:${process.env.USERS_SVC_PORT}`,
|
||||
url: `127.0.0.1:50054`,
|
||||
package: 'pipeline',
|
||||
protoPath: join(__dirname, '..', 'proto', 'pipeline.proto'),
|
||||
loader: {
|
||||
enums: String,
|
||||
objects: true,
|
||||
arrays: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,12 +0,0 @@
|
||||
import { InputGrpcClient } from "src/inputs/entities/input-grcp-client.entity";
|
||||
import { Output } from "src/outputs/entities/output.entity";
|
||||
import { Transformation } from "src/transformations/entities/transformation.entity";
|
||||
|
||||
export class CreatePipelineDto {
|
||||
input:InputGrpcClient;
|
||||
output:Output;
|
||||
transformations:Transformation;
|
||||
tags:string[];
|
||||
name:string;
|
||||
description:string;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
import { PartialType } from '@nestjs/mapped-types';
|
||||
import { CreatePipelineDto } from './create-pipeline.dto';
|
||||
|
||||
export class UpdatePipelineDto extends PartialType(CreatePipelineDto) {
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user