mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-23 17:08:34 +00:00
Merge branch 'main' into release/marketplace-sprint-12
This commit is contained in:
commit
3fe98ee4b2
94 changed files with 2203 additions and 638 deletions
197
.github/workflows/cypress-platform.yml
vendored
197
.github/workflows/cypress-platform.yml
vendored
|
|
@ -12,91 +12,106 @@ env:
|
|||
jobs:
|
||||
Cypress-Platform:
|
||||
runs-on: ubuntu-22.04
|
||||
if: contains(github.event.pull_request.labels.*.name, 'run-cypress') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-platform-ce') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-platform-ee') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-ce')
|
||||
if: contains(github.event.pull_request.labels.*.name, 'run-cypress') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-platform-ce') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-platform-ee') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-ce')
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
edition: >-
|
||||
${{
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress') && fromJson('["ce", "ee"]') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-ce') && fromJson('["ce"]') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-platform-ce') && fromJson('["ce"]') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-platform-ee') && fromJson('["ee"]') ||
|
||||
fromJson('[]')
|
||||
}}
|
||||
edition:
|
||||
- ${{ contains(github.event.pull_request.labels.*.name, 'run-cypress') && 'ce' || contains(github.event.pull_request.labels.*.name, 'run-cypress-platform-ce') && 'ce' || contains(github.event.pull_request.labels.*.name, 'run-cypress-ce') && 'ce' || '' }}
|
||||
- ${{ contains(github.event.pull_request.labels.*.name, 'run-cypress') && 'ee' || contains(github.event.pull_request.labels.*.name, 'run-cypress-platform-ee') && 'ee' || '' }}
|
||||
exclude:
|
||||
- edition: ""
|
||||
|
||||
steps:
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 18.18.2
|
||||
|
||||
- name: Set up Git authentication for private submodules
|
||||
- name: Debug labels and matrix edition
|
||||
run: |
|
||||
git config --global url."https://x-access-token:${{ secrets.CUSTOM_GITHUB_TOKEN }}@github.com/".insteadOf "https://github.com/"
|
||||
echo "Labels: ${{ toJSON(github.event.pull_request.labels.*.name) }}"
|
||||
echo "Matrix edition: ${{ matrix.edition }}"
|
||||
|
||||
- name: Checkout with Submodules
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.ref }}
|
||||
|
||||
- name: Checking out the correct branch for submodules EE
|
||||
# Create Docker Buildx builder with platform configuration
|
||||
- name: Set up Docker Buildx
|
||||
run: |
|
||||
mkdir -p ~/.docker/cli-plugins
|
||||
curl -SL https://github.com/docker/buildx/releases/download/v0.11.0/buildx-v0.11.0.linux-amd64 -o ~/.docker/cli-plugins/docker-buildx
|
||||
chmod a+x ~/.docker/cli-plugins/docker-buildx
|
||||
docker buildx create --name mybuilder --platform linux/arm64,linux/amd64
|
||||
docker buildx use mybuilder
|
||||
|
||||
- name: Set DOCKER_CLI_EXPERIMENTAL
|
||||
run: echo "DOCKER_CLI_EXPERIMENTAL=enabled" >> $GITHUB_ENV
|
||||
|
||||
- name: use mybuilder buildx
|
||||
run: docker buildx use mybuilder
|
||||
|
||||
- name: Docker Login
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Set SAFE_BRANCH_NAME
|
||||
run: echo "SAFE_BRANCH_NAME=$(echo ${{ env.BRANCH_NAME }} | tr '/' '-')" >> $GITHUB_ENV
|
||||
|
||||
- name: Build CE Docker image
|
||||
if: matrix.edition == 'ce'
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
file: docker/ce-production.Dockerfile
|
||||
push: true
|
||||
tags: tooljet/tj-osv:${{ env.SAFE_BRANCH_NAME }}-ce
|
||||
platforms: linux/amd64
|
||||
env:
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Build EE Docker image
|
||||
if: matrix.edition == 'ee'
|
||||
run: |
|
||||
git submodule update --init --recursive
|
||||
git submodule foreach --recursive '
|
||||
git checkout ${{ env.BRANCH_NAME }} 2>/dev/null || git checkout main'
|
||||
|
||||
- name: Set up Docker
|
||||
uses: docker-practice/actions-setup-docker@master
|
||||
|
||||
- name: Install and build dependencies
|
||||
run: |
|
||||
npm cache clean --force
|
||||
npm install
|
||||
npm install --prefix server
|
||||
npm install --prefix frontend
|
||||
npm run build:plugins
|
||||
|
||||
- name: Local development setup
|
||||
run: |
|
||||
sudo docker network create tooljet
|
||||
sudo docker run -d --name postgres -p 5432:5432 -e POSTGRES_PASSWORD=postgres -e POSTGRES_USER=postgres -e POSTGRES_PORT=5432 -d postgres:13
|
||||
|
||||
- name: Run PostgREST Docker Container
|
||||
run: |
|
||||
sudo docker run -d --name postgrest --network tooljet -p 3001:3000 \
|
||||
-e PGRST_DB_URI="postgres://postgres:postgres@localhost:5432/tooljet" \
|
||||
-e PGRST_DB_ANON_ROLE="postgres" \
|
||||
-e PGRST_JWT_SECRET="r9iMKoe5CRMgvJBBtp4HrqN7QiPpUToj" \
|
||||
-e PGRST_DB_PRE_CONFIG=postgrest.pre_config \
|
||||
postgrest/postgrest:v12.2.0
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
build-args: |
|
||||
CUSTOM_GITHUB_TOKEN=${{ secrets.CUSTOM_GITHUB_TOKEN }}
|
||||
BRANCH_NAME=${{ github.event.pull_request.head.ref }}
|
||||
file: cypress-tests/cypress.Dockerfile
|
||||
push: true
|
||||
tags: tooljet/tj-osv:${{ env.SAFE_BRANCH_NAME }}-ee
|
||||
platforms: linux/amd64
|
||||
env:
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Set up environment variables
|
||||
run: |
|
||||
echo "TOOLJET_EDITION=${{ matrix.edition == 'ee' && 'ee' || 'ce' }}" >> .env
|
||||
echo "TOOLJET_HOST=http://localhost:8082" >> .env
|
||||
echo "TOOLJET_EDITION=${{ matrix.edition }}" >> .env
|
||||
echo "TOOLJET_HOST=http://localhost:3000" >> .env
|
||||
echo "LOCKBOX_MASTER_KEY=cd97331a419c09387bef49787f7da8d2a81d30733f0de6bed23ad8356d2068b2" >> .env
|
||||
echo "SECRET_KEY_BASE=7073b9a35a15dd20914ae17e36a693093f25b74b96517a5fec461fc901c51e011cd142c731bee48c5081ec8bac321c1f259ef097ef2a16f25df17a3798c03426" >> .env
|
||||
echo "PG_DB=tooljet_development" >> .env
|
||||
echo "PG_USER=postgres" >> .env
|
||||
echo "PG_HOST=localhost" >> .env
|
||||
echo "PG_HOST=postgres" >> .env
|
||||
echo "PG_PASS=postgres" >> .env
|
||||
echo "PG_PORT=5432" >> .env
|
||||
echo "ENABLE_TOOLJET_DB=true" >> .env
|
||||
echo "TOOLJET_DB=tooljet_db" >> .env
|
||||
echo "TOOLJET_DB_USER=postgres" >> .env
|
||||
echo "TOOLJET_DB_HOST=localhost" >> .env
|
||||
echo "TOOLJET_DB_HOST=postgres" >> .env
|
||||
echo "TOOLJET_DB_PASS=postgres" >> .env
|
||||
echo "TOOLJET_DB_STATEMENT_TIMEOUT=60000" >> .env
|
||||
echo "TOOLJET_DB_RECONFIG=true" >> .env
|
||||
echo "PGRST_JWT_SECRET=r9iMKoe5CRMgvJBBtp4HrqN7QiPpUToj" >> .env
|
||||
echo "PGRST_HOST=localhost:3001" >> .env
|
||||
echo "PGRST_DB_PRE_CONFIG=postgrest.pre_config" >> .env
|
||||
echo "PGRST_DB_URI=postgres://postgres:postgres@localhost:5432/tooljet" >> .env
|
||||
echo "PGRST_DB_URI=postgres://postgres:postgres@postgres/tooljet_db" >> .env
|
||||
echo "ENABLE_MARKETPLACE_FEATURE=true" >> .env
|
||||
echo "ENABLE_MARKETPLACE_DEV_MODE=true" >> .env
|
||||
echo "ENABLE_PRIVATE_APP_EMBED=true" >> .env
|
||||
|
|
@ -105,29 +120,50 @@ jobs:
|
|||
echo "SSO_GIT_OAUTH2_CLIENT_ID=1234567890" >> .env
|
||||
echo "SSO_GIT_OAUTH2_CLIENT_SECRET=3346shfvkdjjsfkvxce32854e026a4531ed" >> .env
|
||||
|
||||
- name: Set up database
|
||||
run: |
|
||||
npm run --prefix server db:create
|
||||
npm run --prefix server db:reset
|
||||
sleep 5
|
||||
# Only add EE-specific env vars if edition is ee
|
||||
if [ "${{ matrix.edition }}" = "ee" ]; then
|
||||
echo "SSO_OPENID_NAME=tj-oidc-simulator" >> .env
|
||||
echo "SSO_OPENID_CLIENT_ID=${{ secrets.SSO_OPENID_CLIENT_ID }}" >> .env
|
||||
echo "SSO_OPENID_CLIENT_SECRET=${{ secrets.SSO_OPENID_CLIENT_SECRET }}" >> .env
|
||||
echo "SSO_OPENID_WELL_KNOWN_URL=http://34.66.166.236:8080/.well-known/openid-configuration" >> .env
|
||||
echo "LICENSE_KEY=${{ secrets.RENDER_LICENSE_KEY }}" >> .env
|
||||
fi
|
||||
|
||||
- name: Start services
|
||||
- name: Pulling the docker-compose file
|
||||
run: curl -LO https://tooljet-test.s3.us-west-1.amazonaws.com/docker-compose.yaml && mkdir postgres_data
|
||||
|
||||
- name: Update docker-compose file
|
||||
run: |
|
||||
cd plugins && npm start &
|
||||
cd server && npm run start:dev &
|
||||
cd frontend && npm start &
|
||||
# Update docker-compose.yaml with the appropriate image based on edition
|
||||
if [ "${{ matrix.edition }}" = "ce" ]; then
|
||||
sed -i '/^[[:space:]]*tooljet:/,/^$/ s|^\([[:space:]]*image:[[:space:]]*\).*|\1tooljet/tj-osv:${{ env.SAFE_BRANCH_NAME }}-ce|' docker-compose.yaml
|
||||
elif [ "${{ matrix.edition }}" = "ee" ]; then
|
||||
sed -i '/^[[:space:]]*tooljet:/,/^$/ s|^\([[:space:]]*image:[[:space:]]*\).*|\1tooljet/tj-osv:${{ env.SAFE_BRANCH_NAME }}-ee|' docker-compose.yaml
|
||||
fi
|
||||
|
||||
- name: Install Docker Compose
|
||||
run: |
|
||||
curl -L "https://github.com/docker/compose/releases/download/v2.10.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
|
||||
chmod +x /usr/local/bin/docker-compose
|
||||
|
||||
- name: Run docker-compose file
|
||||
run: docker-compose up -d
|
||||
|
||||
- name: Checking containers
|
||||
run: docker ps -a
|
||||
|
||||
- name: docker logs
|
||||
run: sudo docker logs Tooljet-app
|
||||
|
||||
- name: Wait for the server to be ready
|
||||
run: |
|
||||
timeout 300 bash -c '
|
||||
until curl --silent --fail http://localhost:8082; do
|
||||
timeout 500 bash -c '
|
||||
until curl --silent --fail http://localhost:3000; do
|
||||
sleep 5
|
||||
done'
|
||||
|
||||
- name: Postgres logs
|
||||
run: docker logs postgrest
|
||||
|
||||
- name: Create Cypress environment file
|
||||
- name: Create Cypress environment file for CE
|
||||
if: matrix.edition == 'ce'
|
||||
id: create-json
|
||||
uses: jsdaniell/create-json@1.1.2
|
||||
with:
|
||||
|
|
@ -135,13 +171,30 @@ jobs:
|
|||
json: ${{ secrets.CYPRESS_SECRETS }}
|
||||
dir: "./cypress-tests"
|
||||
|
||||
- name: Run Cypress tests
|
||||
- name: Run Cypress tests for CE
|
||||
if: matrix.edition == 'ce'
|
||||
uses: cypress-io/github-action@v6
|
||||
with:
|
||||
working-directory: ./cypress-tests
|
||||
config: "baseUrl=http://localhost:8082"
|
||||
config: "baseUrl=http://localhost:3000"
|
||||
config-file: cypress-platform.config.js
|
||||
|
||||
- name: Create Cypress environment file for EE
|
||||
if: matrix.edition == 'ee'
|
||||
uses: jsdaniell/create-json@1.1.2
|
||||
with:
|
||||
name: "cypress.env.json"
|
||||
json: ${{ secrets.CYPRESS_EE_SECRETS }}
|
||||
dir: "./cypress-tests"
|
||||
|
||||
- name: Run Cypress tests for EE
|
||||
if: matrix.edition == 'ee'
|
||||
uses: cypress-io/github-action@v6
|
||||
with:
|
||||
working-directory: ./cypress-tests
|
||||
config: "baseUrl=http://localhost:3000"
|
||||
config-file: cypress-ee-platform.config.js
|
||||
|
||||
- name: Capture Screenshots
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
|
|
|
|||
2
.version
2
.version
|
|
@ -1 +1 @@
|
|||
3.13.0
|
||||
3.14.0
|
||||
|
|
|
|||
114
cypress-tests/cypress-ee-platform.config.js
Normal file
114
cypress-tests/cypress-ee-platform.config.js
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
const { defineConfig } = require("cypress");
|
||||
const { rmdir } = require("fs");
|
||||
const fs = require("fs");
|
||||
const XLSX = require("node-xlsx");
|
||||
const pg = require("pg");
|
||||
const path = require("path");
|
||||
const pdf = require("pdf-parse");
|
||||
|
||||
const environments = {
|
||||
'run-cypress-platform': {
|
||||
baseUrl: "http://localhost:3000",
|
||||
configFile: "cypress-platform.config.js"
|
||||
},
|
||||
'run-cypress-platform-subpath': {
|
||||
baseUrl: "http://localhost:3000/apps",
|
||||
configFile: "cypress-platform.config.js"
|
||||
},
|
||||
'run-cypress-platform-proxy': {
|
||||
baseUrl: "http://localhost:4001",
|
||||
configFile: "cypress-platform.config.js"
|
||||
},
|
||||
'run-cypress-platform-proxy-subpath': {
|
||||
baseUrl: "http://localhost:4001/apps",
|
||||
configFile: "cypress-platform.config.js"
|
||||
}
|
||||
};
|
||||
|
||||
const githubLabel = process.env.GITHUB_LABEL || 'run-cypress-platform';
|
||||
const environment = environments[githubLabel];
|
||||
|
||||
module.exports = defineConfig({
|
||||
execTimeout: 1800000,
|
||||
defaultCommandTimeout: 30000,
|
||||
requestTimeout: 30000,
|
||||
pageLoadTimeout: 30000,
|
||||
responseTimeout: 30000,
|
||||
viewportWidth: 1440,
|
||||
viewportHeight: 960,
|
||||
chromeWebSecurity: false,
|
||||
trashAssetsBeforeRuns: true,
|
||||
e2e: {
|
||||
setupNodeEvents (on, config) {
|
||||
config.baseUrl = environment.baseUrl;
|
||||
|
||||
on("task", {
|
||||
readPdf (pathToPdf) {
|
||||
return new Promise((resolve) => {
|
||||
const pdfPath = path.resolve(pathToPdf);
|
||||
let dataBuffer = fs.readFileSync(pdfPath);
|
||||
pdf(dataBuffer).then(function ({ text }) {
|
||||
resolve(text);
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
on("task", {
|
||||
readXlsx (filePath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
let dataBuffer = fs.readFileSync(filePath);
|
||||
const jsonData = XLSX.parse(dataBuffer);
|
||||
resolve(jsonData[0]["data"].toString());
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
on("task", {
|
||||
deleteFolder (folderName) {
|
||||
return new Promise((resolve, reject) => {
|
||||
rmdir(folderName, { maxRetries: 10, recursive: true }, (err) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return reject(err);
|
||||
}
|
||||
resolve(null);
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
on("task", {
|
||||
dbConnection ({ dbconfig, sql }) {
|
||||
const client = new pg.Pool(dbconfig);
|
||||
return client.query(sql);
|
||||
},
|
||||
});
|
||||
|
||||
return require("./cypress/plugins/index.js")(on, config);
|
||||
},
|
||||
downloadsFolder: "cypress/downloads",
|
||||
experimentalRunAllSpecs: true,
|
||||
experimentalModfyObstructiveThirdPartyCode: true,
|
||||
baseUrl: environment.baseUrl,
|
||||
configFile: environment.configFile,
|
||||
specPattern: [
|
||||
"cypress/e2e/happyPath/platform/firstUser/firstUserOnboarding.cy.js",
|
||||
"cypress/e2e/happyPath/platform/commonTestcases/**/*.cy.js",
|
||||
"cypress/e2e/happyPath/platform/eeTestcases/**/*.cy.js",
|
||||
],
|
||||
numTestsKeptInMemory: 1,
|
||||
redirectionLimit: 15,
|
||||
experimentalMemoryManagement: true,
|
||||
video: false,
|
||||
videoUploadOnPasses: false,
|
||||
retries: {
|
||||
runMode: 2,
|
||||
openMode: 0,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
@ -8,7 +8,7 @@ const pdf = require("pdf-parse");
|
|||
|
||||
const environments = {
|
||||
'run-cypress-platform': {
|
||||
baseUrl: "http://localhost:8082",
|
||||
baseUrl: "http://localhost:3000",
|
||||
configFile: "cypress-platform.config.js"
|
||||
},
|
||||
'run-cypress-platform-subpath': {
|
||||
|
|
|
|||
189
cypress-tests/cypress.Dockerfile
Normal file
189
cypress-tests/cypress.Dockerfile
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
FROM node:18.18.2-buster AS builder
|
||||
# Fix for JS heap limit allocation issue
|
||||
ENV NODE_OPTIONS="--max-old-space-size=4096"
|
||||
|
||||
RUN mkdir -p /app
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
ARG CUSTOM_GITHUB_TOKEN
|
||||
ARG BRANCH_NAME
|
||||
|
||||
# Clone and checkout the frontend repositorys
|
||||
RUN git config --global url."https://x-access-token:${CUSTOM_GITHUB_TOKEN}@github.com/".insteadOf "https://github.com/"
|
||||
|
||||
RUN git config --global http.version HTTP/1.1
|
||||
RUN git config --global http.postBuffer 524288000
|
||||
RUN git clone https://github.com/ToolJet/ToolJet.git .
|
||||
|
||||
# The branch name needs to be changed the branch with modularisation in CE repo
|
||||
RUN git checkout ${BRANCH_NAME}
|
||||
|
||||
RUN git submodule update --init --recursive
|
||||
|
||||
# Checkout the same branch in submodules if it exists, otherwise stay on default branch
|
||||
RUN git submodule foreach 'git checkout ${BRANCH_NAME} || true'
|
||||
|
||||
# Scripts for building
|
||||
COPY ./package.json ./package.json
|
||||
|
||||
# Build plugins
|
||||
COPY ./plugins/package.json ./plugins/package-lock.json ./plugins/
|
||||
RUN npm --prefix plugins install
|
||||
COPY ./plugins/ ./plugins/
|
||||
RUN NODE_ENV=production npm --prefix plugins run build
|
||||
RUN npm --prefix plugins prune --production
|
||||
|
||||
ENV TOOLJET_EDITION=ee
|
||||
|
||||
# Build frontend
|
||||
COPY ./frontend/package.json ./frontend/package-lock.json ./frontend/
|
||||
RUN npm --prefix frontend install
|
||||
COPY ./frontend/ ./frontend/
|
||||
RUN npm --prefix frontend run build --production
|
||||
RUN npm --prefix frontend prune --production
|
||||
|
||||
ENV NODE_ENV=production
|
||||
ENV TOOLJET_EDITION=ee
|
||||
|
||||
# Build server
|
||||
COPY ./server/package.json ./server/package-lock.json ./server/
|
||||
RUN npm --prefix server install
|
||||
COPY ./server/ ./server/
|
||||
RUN npm install -g @nestjs/cli
|
||||
RUN npm --prefix server run build
|
||||
|
||||
FROM node:18.18.2-bullseye
|
||||
|
||||
RUN apt-get update -yq \
|
||||
&& apt-get install curl wget gnupg zip -yq \
|
||||
&& apt-get install -yq build-essential \
|
||||
&& apt -y install redis \
|
||||
&& apt-get clean -y
|
||||
|
||||
# copy postgrest executable
|
||||
COPY --from=postgrest/postgrest:v12.2.0 /bin/postgrest /bin
|
||||
|
||||
ENV NODE_ENV=production
|
||||
ENV TOOLJET_EDITION=ee
|
||||
ENV NODE_OPTIONS="--max-old-space-size=4096"
|
||||
RUN apt-get update && apt-get install -y freetds-dev libaio1 wget supervisor
|
||||
|
||||
# Install Instantclient Basic Light Oracle and Dependencies
|
||||
WORKDIR /opt/oracle
|
||||
RUN wget https://tooljet-plugins-production.s3.us-east-2.amazonaws.com/marketplace-assets/oracledb/instantclients/instantclient-basiclite-linuxx64.zip && \
|
||||
wget https://tooljet-plugins-production.s3.us-east-2.amazonaws.com/marketplace-assets/oracledb/instantclients/instantclient-basiclite-linux.x64-11.2.0.4.0.zip && \
|
||||
unzip instantclient-basiclite-linuxx64.zip && rm -f instantclient-basiclite-linuxx64.zip && \
|
||||
unzip instantclient-basiclite-linux.x64-11.2.0.4.0.zip && rm -f instantclient-basiclite-linux.x64-11.2.0.4.0.zip && \
|
||||
cd /opt/oracle/instantclient_21_10 && rm -f *jdbc* *occi* *mysql* *mql1* *ipc1* *jar uidrvci genezi adrci && \
|
||||
cd /opt/oracle/instantclient_11_2 && rm -f *jdbc* *occi* *mysql* *mql1* *ipc1* *jar uidrvci genezi adrci && \
|
||||
echo /opt/oracle/instantclient* > /etc/ld.so.conf.d/oracle-instantclient.conf && ldconfig
|
||||
# Set the Instant Client library paths
|
||||
ENV LD_LIBRARY_PATH="/opt/oracle/instantclient_11_2:/opt/oracle/instantclient_21_10:${LD_LIBRARY_PATH}"
|
||||
|
||||
WORKDIR /
|
||||
|
||||
# copy npm scripts
|
||||
COPY --from=builder /app/package.json ./app/package.json
|
||||
# copy plugins dependencies
|
||||
COPY --from=builder /app/plugins/dist ./app/plugins/dist
|
||||
COPY --from=builder /app/plugins/client.js ./app/plugins/client.js
|
||||
COPY --from=builder /app/plugins/node_modules ./app/plugins/node_modules
|
||||
COPY --from=builder /app/plugins/packages/common ./app/plugins/packages/common
|
||||
COPY --from=builder /app/plugins/package.json ./app/plugins/package.json
|
||||
# copy frontend build
|
||||
COPY --from=builder /app/frontend/build ./app/frontend/build
|
||||
# copy server build
|
||||
COPY --from=builder /app/server/package.json ./app/server/package.json
|
||||
COPY --from=builder /app/server/.version ./app/server/.version
|
||||
COPY --from=builder /app/server/ee/keys ./app/server/ee/keys
|
||||
COPY --from=builder /app/server/node_modules ./app/server/node_modules
|
||||
COPY --from=builder /app/server/templates ./app/server/templates
|
||||
COPY --from=builder /app/server/scripts ./app/server/scripts
|
||||
COPY --from=builder /app/server/dist ./app/server/dist
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install PostgreSQL
|
||||
USER root
|
||||
RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
|
||||
RUN echo "deb http://apt.postgresql.org/pub/repos/apt/ bullseye-pgdg main" | tee /etc/apt/sources.list.d/pgdg.list
|
||||
RUN apt update && apt -y install postgresql-13 postgresql-client-13 supervisor --fix-missing
|
||||
|
||||
|
||||
# Explicitly create PG main directory with correct ownership
|
||||
RUN mkdir -p /var/lib/postgresql/13/main && \
|
||||
chown -R postgres:postgres /var/lib/postgresql
|
||||
|
||||
RUN mkdir -p /var/log/supervisor /var/run/postgresql && \
|
||||
chown -R postgres:postgres /var/run/postgresql /var/log/supervisor
|
||||
|
||||
# Remove existing data and create directory with proper ownership
|
||||
RUN rm -rf /var/lib/postgresql/13/main && \
|
||||
mkdir -p /var/lib/postgresql/13/main && \
|
||||
chown -R postgres:postgres /var/lib/postgresql
|
||||
|
||||
# Initialize PostgreSQL
|
||||
RUN su - postgres -c "/usr/lib/postgresql/13/bin/initdb -D /var/lib/postgresql/13/main"
|
||||
|
||||
# Configure Supervisor to manage PostgREST, ToolJet, and Redis
|
||||
RUN echo "[supervisord] \n" \
|
||||
"nodaemon=true \n" \
|
||||
"user=root \n" \
|
||||
"\n" \
|
||||
"[program:redis] \n" \
|
||||
"command=redis-server /etc/redis/redis.conf \n" \
|
||||
"user=redis \n" \
|
||||
"autostart=true \n" \
|
||||
"autorestart=true \n" \
|
||||
"stderr_logfile=/var/log/redis/redis-server.log \n" \
|
||||
"stdout_logfile=/var/log/redis/redis-server.log \n" \
|
||||
"\n" \
|
||||
"[program:postgrest] \n" \
|
||||
"command=/bin/postgrest \n" \
|
||||
"autostart=true \n" \
|
||||
"autorestart=true \n" \
|
||||
"\n" \
|
||||
"[program:tooljet] \n" \
|
||||
"user=root \n" \
|
||||
"command=/bin/bash -c '/app/server/scripts/boot.sh' \n" \
|
||||
"autostart=true \n" \
|
||||
"autorestart=true \n" \
|
||||
"stderr_logfile=/dev/stdout \n" \
|
||||
"stderr_logfile_maxbytes=0 \n" \
|
||||
"stdout_logfile=/dev/stdout \n" \
|
||||
"stdout_logfile_maxbytes=0 \n" | sed 's/ //' > /etc/supervisor/conf.d/supervisord.conf
|
||||
|
||||
# ENV defaults
|
||||
ENV TOOLJET_HOST=http://localhost \
|
||||
PORT=3000 \
|
||||
NODE_ENV=production \
|
||||
LOCKBOX_MASTER_KEY=replace_with_lockbox_master_key \
|
||||
SECRET_KEY_BASE=replace_with_secret_key_base \
|
||||
PG_DB=tooljet_production \
|
||||
PG_USER=postgres \
|
||||
PG_PASS=postgres \
|
||||
PG_HOST=localhost \
|
||||
ENABLE_TOOLJET_DB=true \
|
||||
TOOLJET_DB_HOST=localhost \
|
||||
TOOLJET_DB_USER=postgres \
|
||||
TOOLJET_DB_PASS=postgres \
|
||||
TOOLJET_DB=tooljet_db \
|
||||
PGRST_HOST=http://localhost:3001 \
|
||||
PGRST_SERVER_PORT=3001 \
|
||||
PGRST_DB_URI=postgres://postgres:postgres@localhost/tooljet_db \
|
||||
PGRST_JWT_SECRET=r9iMKoe5CRMgvJBBtp4HrqN7QiPpUToj \
|
||||
PGRST_DB_PRE_CONFIG=postgrest.pre_config \
|
||||
REDIS_HOST=localhost \
|
||||
REDIS_PORT=6379 \
|
||||
REDIS_USER= \
|
||||
REDIS_PASSWORD= \
|
||||
ORM_LOGGING=true \
|
||||
DEPLOYMENT_PLATFORM=docker:local \
|
||||
HOME=/home/appuser \
|
||||
TERM=xterm
|
||||
|
||||
|
||||
RUN chmod +x ./server/scripts/preview.sh
|
||||
# Set the entrypoint
|
||||
ENTRYPOINT ["./server/scripts/preview.sh"]
|
||||
|
|
@ -226,9 +226,9 @@ Cypress.Commands.add(
|
|||
.invoke("text")
|
||||
.then((text) => {
|
||||
cy.wrap(subject).realType(createBackspaceText(text)),
|
||||
{
|
||||
delay: 0,
|
||||
};
|
||||
{
|
||||
delay: 0,
|
||||
};
|
||||
});
|
||||
}
|
||||
);
|
||||
|
|
@ -429,7 +429,6 @@ Cypress.Commands.add("visitSlug", ({ actualUrl }) => {
|
|||
});
|
||||
});
|
||||
|
||||
|
||||
Cypress.Commands.add("releaseApp", () => {
|
||||
if (Cypress.env("environment") !== "Community") {
|
||||
cy.get(commonEeSelectors.promoteButton).click();
|
||||
|
|
@ -549,7 +548,7 @@ Cypress.Commands.add("installMarketplacePlugin", (pluginName) => {
|
|||
}
|
||||
});
|
||||
|
||||
function installPlugin (pluginName) {
|
||||
function installPlugin(pluginName) {
|
||||
cy.get('[data-cy="-list-item"]').eq(1).click();
|
||||
cy.wait(1000);
|
||||
|
||||
|
|
@ -605,3 +604,20 @@ Cypress.Commands.add("uninstallMarketplacePlugin", (pluginName) => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add(
|
||||
"verifyRequiredFieldValidation",
|
||||
(fieldName, expectedColor) => {
|
||||
cy.get(commonSelectors.textField(fieldName)).should(
|
||||
"have.css",
|
||||
"border-color",
|
||||
expectedColor
|
||||
);
|
||||
cy.get(commonSelectors.labelFieldValidation(fieldName))
|
||||
.should("be.visible")
|
||||
.and("have.text", `${fieldName} is required`);
|
||||
cy.get(commonSelectors.labelFieldAlert(fieldName))
|
||||
.should("be.visible")
|
||||
.and("have.text", `${fieldName} is required`);
|
||||
}
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
export const cyParamName = (paramName = "") => {
|
||||
return paramName.toLowerCase().replace(/\s+/g, "-");
|
||||
return String(paramName).toLowerCase().replace(/\s+/g, "-");
|
||||
};
|
||||
|
||||
export const commonSelectors = {
|
||||
|
|
@ -278,6 +278,16 @@ export const commonSelectors = {
|
|||
defaultModalTitle: '[data-cy="modal-title"]',
|
||||
workspaceConstantsIcon: '[data-cy="icon-workspace-constants"]',
|
||||
confirmationButton: '[data-cy="confirmation-button"]',
|
||||
|
||||
textField: (fieldName) => {
|
||||
return `[data-cy="${cyParamName(fieldName)}-text-field"]`;
|
||||
},
|
||||
labelFieldValidation: (fieldName) => {
|
||||
return `[data-cy="${cyParamName(fieldName)}-is-required-validation-label"]`;
|
||||
},
|
||||
labelFieldAlert: (fieldName) => {
|
||||
return `[data-cy="${cyParamName(fieldName)}-is-required-field-alert-text"]`;
|
||||
},
|
||||
};
|
||||
|
||||
export const commonWidgetSelector = {
|
||||
|
|
|
|||
|
|
@ -101,6 +101,8 @@ export const dataSourceSelector = {
|
|||
unSavedModalTitle: '[data-cy="unsaved-changes-title"]',
|
||||
eventQuerySelectionField: '[data-cy="query-selection-field"]',
|
||||
connectionAlertText: '[data-cy="connection-alert-text"]',
|
||||
requiredIndicator: '[data-cy="required-indicator"]',
|
||||
informationIcon: '[data-cy="information-icon"]',
|
||||
deleteDSButton: (datasourceName) => {
|
||||
return `[data-cy="${cyParamName(datasourceName)}-delete-button"]`;
|
||||
},
|
||||
|
|
@ -110,4 +112,37 @@ export const dataSourceSelector = {
|
|||
dataSourceNameButton: (dataSourceName) => {
|
||||
return `[data-cy="${cyParamName(dataSourceName)}-button"]`;
|
||||
},
|
||||
dropdownLabel: (label) => {
|
||||
return `[data-cy="${cyParamName(label)}-dropdown-label"]`;
|
||||
},
|
||||
textField: (fieldName) => {
|
||||
return `[data-cy="${cyParamName(fieldName)}-text-field"]`;
|
||||
},
|
||||
subSection: (header) => {
|
||||
return `[data-cy="${cyParamName(header)}-section"]`;
|
||||
},
|
||||
toggleInput: (toggleName) => {
|
||||
return `[data-cy="${cyParamName(toggleName)}-toggle-input"]`;
|
||||
},
|
||||
button: (buttonName) => {
|
||||
return `[data-cy="button-${cyParamName(buttonName)}"]`;
|
||||
},
|
||||
keyInputField: (header, index) => {
|
||||
return `[data-cy="${cyParamName(header)}-key-input-field-${cyParamName(index)}"]`;
|
||||
},
|
||||
valueInputField: (header, index) => {
|
||||
return `[data-cy="${cyParamName(header)}-value-input-field-${cyParamName(index)}"]`;
|
||||
},
|
||||
deleteButton: (header, index) => {
|
||||
return `[data-cy="${cyParamName(header)}-delete-button-${cyParamName(index)}"]`;
|
||||
},
|
||||
addMoreButton: (header) => {
|
||||
return `[data-cy="${cyParamName(header)}-add-button"]`;
|
||||
},
|
||||
dropdownField: (fieldName) => {
|
||||
return `[data-cy="${cyParamName(fieldName)}-select-dropdown"]`;
|
||||
},
|
||||
labelFieldValidation: (fieldName) => {
|
||||
return `[data-cy="${cyParamName(fieldName)}-is-required-validation-label"]`;
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -87,6 +87,8 @@ export const postgreSqlSelector = {
|
|||
recordsInputField: '[data-cy="records-input-field"]',
|
||||
|
||||
eventQuerySelectionField: '[data-cy="query-selection-field"]',
|
||||
sslToggleInput: '[data-cy="ssl-enabled-toggle-input"]',
|
||||
labelEncryptedText: '[data-cy="encrypted-text"]',
|
||||
};
|
||||
|
||||
export const airTableSelector = {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
export const airtableText = {
|
||||
airtable: "Airtable",
|
||||
cypressairtable: "cypress-Airtable",
|
||||
ApiKey: "Personal access token",
|
||||
apikeyPlaceholder: "**************",
|
||||
};
|
||||
airtable: "Airtable",
|
||||
cypressairtable: "cypress-Airtable",
|
||||
ApiKey: "Personal access token",
|
||||
apikeyPlaceholder: "**************",
|
||||
invalidAccessToken: "Authentication failed: Invalid personal access token",
|
||||
};
|
||||
|
|
|
|||
|
|
@ -17,13 +17,17 @@ export const postgreSqlText = {
|
|||
allCloudStorage: "Cloud Storages (4)",
|
||||
|
||||
postgreSQL: "PostgreSQL",
|
||||
labelConnectionType: "Connection type",
|
||||
manualConnectionOption: "Manual connection",
|
||||
connectionStringOption: "Connection string",
|
||||
labelHost: "Host",
|
||||
labelPort: "Port",
|
||||
labelSSL: "SSL",
|
||||
labelDbName: "Database name",
|
||||
labelUserName: "Username",
|
||||
labelPassword: "Password",
|
||||
label: "Encrypted",
|
||||
labelEncrypted: "Encrypted",
|
||||
labelConnectionOptions: "Connection options",
|
||||
sslCertificate: "SSL certificate",
|
||||
whiteListIpText:
|
||||
"Please white-list our IP address if the data source is not publicly accessible",
|
||||
|
|
@ -74,6 +78,8 @@ export const postgreSqlText = {
|
|||
|
||||
guiOptionBulkUpdate: "Bulk update using primary key",
|
||||
buttonTextTestConnection: "Test connection",
|
||||
editButtonText: "Edit",
|
||||
unableAcquireConnectionAlertText: "Unable to acquire a connection",
|
||||
|
||||
tabAdvanced: "Advanced",
|
||||
labelNoEventhandler: "No event handlers",
|
||||
|
|
|
|||
|
|
@ -3,24 +3,15 @@ import { postgreSqlSelector, airTableSelector } from "Selectors/postgreSql";
|
|||
import { postgreSqlText } from "Texts/postgreSql";
|
||||
import { airtableText } from "Texts/airTable";
|
||||
import { commonSelectors } from "Selectors/common";
|
||||
import { commonText } from "Texts/common";
|
||||
|
||||
import {
|
||||
fillDataSourceTextField,
|
||||
selectAndAddDataSource,
|
||||
} from "Support/utils/postgreSql";
|
||||
|
||||
import {
|
||||
deleteDatasource,
|
||||
closeDSModal,
|
||||
deleteAppandDatasourceAfterExecution,
|
||||
} from "Support/utils/dataSource";
|
||||
|
||||
import { closeDSModal } from "Support/utils/dataSource";
|
||||
import { dataSourceSelector } from "../../../../../constants/selectors/dataSource";
|
||||
|
||||
const data = {};
|
||||
|
||||
data.queryName = fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", "");
|
||||
const airTable_apiKey = Cypress.env("airTable_apikey");
|
||||
const airTable_baseId = Cypress.env("airtabelbaseId");
|
||||
const airTable_tableName = Cypress.env("airtable_tableName");
|
||||
const airTable_recordID = Cypress.env("airtable_recordId");
|
||||
|
||||
describe("Data source Airtable", () => {
|
||||
beforeEach(() => {
|
||||
|
|
@ -54,18 +45,71 @@ describe("Data source Airtable", () => {
|
|||
postgreSqlText.allCloudStorage
|
||||
);
|
||||
|
||||
selectAndAddDataSource("databases", airtableText.airtable, data.dsName);
|
||||
|
||||
cy.get(postgreSqlSelector.buttonSave).verifyVisibleElement(
|
||||
cy.apiCreateGDS(
|
||||
`${Cypress.env("server_host")}/api/data-sources`,
|
||||
`cypress-${data.dsName}-airtable`,
|
||||
"airtable",
|
||||
[
|
||||
{
|
||||
key: "personal_access_token",
|
||||
value: `${Cypress.env("airTable_apikey")}`,
|
||||
encrypted: true,
|
||||
},
|
||||
]
|
||||
);
|
||||
cy.reload();
|
||||
cy.get(
|
||||
dataSourceSelector.dataSourceNameButton(`cypress-${data.dsName}-airtable`)
|
||||
)
|
||||
.should("be.visible")
|
||||
.click();
|
||||
cy.get(
|
||||
dataSourceSelector.labelFieldName(airtableText.ApiKey)
|
||||
).verifyVisibleElement("have.text", `${airtableText.ApiKey}*`);
|
||||
cy.get(postgreSqlSelector.labelEncryptedText).verifyVisibleElement(
|
||||
"have.text",
|
||||
postgreSqlText.buttonTextSave
|
||||
postgreSqlText.labelEncrypted
|
||||
);
|
||||
cy.get(dataSourceSelector.button(postgreSqlText.editButtonText)).should(
|
||||
"be.visible"
|
||||
);
|
||||
cy.get(dataSourceSelector.button(postgreSqlText.editButtonText)).click();
|
||||
cy.verifyRequiredFieldValidation(airtableText.ApiKey, "rgb(226, 99, 103)");
|
||||
cy.get(dataSourceSelector.textField(airtableText.ApiKey)).should(
|
||||
"be.visible"
|
||||
);
|
||||
cy.get(postgreSqlSelector.labelIpWhitelist).verifyVisibleElement(
|
||||
"have.text",
|
||||
postgreSqlText.whiteListIpText
|
||||
);
|
||||
cy.get(postgreSqlSelector.buttonCopyIp).verifyVisibleElement(
|
||||
"have.text",
|
||||
postgreSqlText.textCopy
|
||||
);
|
||||
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
postgreSqlText.toastDSSaved
|
||||
cy.get(postgreSqlSelector.linkReadDocumentation).verifyVisibleElement(
|
||||
"have.text",
|
||||
postgreSqlText.readDocumentation
|
||||
);
|
||||
deleteDatasource(`cypress-${data.dsName}-airtable`);
|
||||
cy.get(postgreSqlSelector.buttonTestConnection)
|
||||
.verifyVisibleElement(
|
||||
"have.text",
|
||||
postgreSqlText.buttonTextTestConnection
|
||||
)
|
||||
.click();
|
||||
cy.get(postgreSqlSelector.connectionFailedText).verifyVisibleElement(
|
||||
"have.text",
|
||||
postgreSqlText.couldNotConnect
|
||||
);
|
||||
cy.get(postgreSqlSelector.buttonSave)
|
||||
.verifyVisibleElement("have.text", postgreSqlText.buttonTextSave)
|
||||
.and("be.disabled");
|
||||
cy.get(dataSourceSelector.connectionAlertText).verifyVisibleElement(
|
||||
"have.text",
|
||||
airtableText.invalidAccessToken
|
||||
);
|
||||
|
||||
cy.apiDeleteGDS(`cypress-${data.dsName}-airtable`);
|
||||
});
|
||||
|
||||
it("Should verify the functionality of AirTable connection form.", () => {
|
||||
|
|
@ -95,7 +139,7 @@ describe("Data source Airtable", () => {
|
|||
|
||||
cy.get(dataSourceSelector.connectionAlertText).verifyVisibleElement(
|
||||
"have.text",
|
||||
"Authentication failed: Invalid personal access token"
|
||||
airtableText.invalidAccessToken
|
||||
);
|
||||
cy.reload();
|
||||
cy.apiUpdateGDS({
|
||||
|
|
@ -123,11 +167,6 @@ describe("Data source Airtable", () => {
|
|||
});
|
||||
|
||||
it("Should able to run the query with valid conection", () => {
|
||||
const airTable_apiKey = Cypress.env("airTable_apikey");
|
||||
const airTable_baseId = Cypress.env("airtabelbaseId");
|
||||
const airTable_tableName = Cypress.env("airtable_tableName");
|
||||
const airTable_recordID = Cypress.env("airtable_recordId");
|
||||
|
||||
cy.apiCreateGDS(
|
||||
`${Cypress.env("server_host")}/api/data-sources`,
|
||||
`cypress-${data.dsName}-airtable`,
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ describe("Data sources", () => {
|
|||
.replaceAll("[^A-Za-z]", "");
|
||||
});
|
||||
|
||||
it.skip("Should verify elements on connection form", () => {
|
||||
it("Should verify elements on connection form with validation", () => {
|
||||
cy.log(process.env.NODE_ENV);
|
||||
cy.log(postgreSqlText.allDatabase());
|
||||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
||||
|
|
@ -81,30 +81,147 @@ describe("Data sources", () => {
|
|||
`cypress-${data.dataSourceName}-postgresql`
|
||||
);
|
||||
|
||||
cy.get(postgreSqlSelector.labelHost).verifyVisibleElement(
|
||||
cy.get(
|
||||
dataSourceSelector.dropdownLabel(postgreSqlText.labelConnectionType)
|
||||
).verifyVisibleElement("have.text", postgreSqlText.labelConnectionType);
|
||||
cy.get(dataSourceSelector.dropdownField(postgreSqlText.labelConnectionType))
|
||||
.should("be.visible")
|
||||
.click();
|
||||
cy.contains(
|
||||
`[id*="react-select-"]`,
|
||||
postgreSqlText.connectionStringOption
|
||||
).click();
|
||||
|
||||
cy.get(
|
||||
dataSourceSelector.dropdownField(postgreSqlText.labelConnectionType)
|
||||
).should("be.visible");
|
||||
cy.get(
|
||||
dataSourceSelector.labelFieldName(postgreSqlText.connectionStringOption)
|
||||
).verifyVisibleElement(
|
||||
"have.text",
|
||||
postgreSqlText.labelHost
|
||||
`${postgreSqlText.connectionStringOption}*`
|
||||
);
|
||||
cy.get(postgreSqlSelector.labelPort).verifyVisibleElement(
|
||||
cy.get(postgreSqlSelector.labelEncryptedText).verifyVisibleElement(
|
||||
"have.text",
|
||||
postgreSqlText.labelPort
|
||||
postgreSqlText.labelEncrypted
|
||||
);
|
||||
cy.get(dataSourceSelector.button(postgreSqlText.editButtonText)).should(
|
||||
"be.visible"
|
||||
);
|
||||
cy.get(dataSourceSelector.button(postgreSqlText.editButtonText)).click();
|
||||
cy.verifyRequiredFieldValidation(
|
||||
postgreSqlText.connectionStringOption,
|
||||
"rgb(226, 99, 103)"
|
||||
);
|
||||
cy.get(
|
||||
dataSourceSelector.textField(postgreSqlText.connectionStringOption)
|
||||
).should("be.visible");
|
||||
cy.get(postgreSqlSelector.labelIpWhitelist).verifyVisibleElement(
|
||||
"have.text",
|
||||
postgreSqlText.whiteListIpText
|
||||
);
|
||||
cy.get(postgreSqlSelector.buttonCopyIp).verifyVisibleElement(
|
||||
"have.text",
|
||||
postgreSqlText.textCopy
|
||||
);
|
||||
|
||||
cy.get(postgreSqlSelector.linkReadDocumentation).verifyVisibleElement(
|
||||
"have.text",
|
||||
postgreSqlText.readDocumentation
|
||||
);
|
||||
cy.get(postgreSqlSelector.buttonTestConnection)
|
||||
.verifyVisibleElement(
|
||||
"have.text",
|
||||
postgreSqlText.buttonTextTestConnection
|
||||
)
|
||||
.click();
|
||||
cy.get(postgreSqlSelector.connectionFailedText).verifyVisibleElement(
|
||||
"have.text",
|
||||
postgreSqlText.couldNotConnect
|
||||
);
|
||||
cy.get(postgreSqlSelector.buttonSave)
|
||||
.verifyVisibleElement("have.text", postgreSqlText.buttonTextSave)
|
||||
.and("be.disabled");
|
||||
cy.get(dataSourceSelector.connectionAlertText).verifyVisibleElement(
|
||||
"have.text",
|
||||
postgreSqlText.unableAcquireConnectionAlertText
|
||||
);
|
||||
|
||||
cy.get(dataSourceSelector.dropdownField(postgreSqlText.labelConnectionType))
|
||||
.should("be.visible")
|
||||
.click();
|
||||
cy.contains(
|
||||
`[id*="react-select-"]`,
|
||||
postgreSqlText.manualConnectionOption
|
||||
).click();
|
||||
|
||||
cy.get(
|
||||
dataSourceSelector.dropdownField(postgreSqlText.labelConnectionType)
|
||||
).should("be.visible");
|
||||
|
||||
const requiredFields = [
|
||||
postgreSqlText.labelHost,
|
||||
postgreSqlText.labelPort,
|
||||
postgreSqlText.labelUserName,
|
||||
postgreSqlText.labelPassword,
|
||||
];
|
||||
const sections = [
|
||||
postgreSqlText.labelHost,
|
||||
postgreSqlText.labelPort,
|
||||
postgreSqlText.labelDbName,
|
||||
postgreSqlText.labelUserName,
|
||||
postgreSqlText.labelPassword,
|
||||
postgreSqlText.labelConnectionOptions,
|
||||
];
|
||||
sections.forEach((section) => {
|
||||
if (section === postgreSqlText.labelConnectionOptions) {
|
||||
cy.get(dataSourceSelector.keyInputField(section, 0)).should(
|
||||
"be.visible"
|
||||
);
|
||||
cy.get(dataSourceSelector.valueInputField(section, 0)).should(
|
||||
"be.visible"
|
||||
);
|
||||
cy.get(dataSourceSelector.deleteButton(section, 0)).should(
|
||||
"be.visible"
|
||||
);
|
||||
cy.get(dataSourceSelector.addMoreButton(section)).should("be.visible");
|
||||
} else if (requiredFields.includes(section)) {
|
||||
cy.get(dataSourceSelector.labelFieldName(section)).verifyVisibleElement(
|
||||
"have.text",
|
||||
`${section}*`
|
||||
);
|
||||
cy.get(dataSourceSelector.textField(section)).should("be.visible");
|
||||
if (section === postgreSqlText.labelPassword) {
|
||||
cy.get(
|
||||
dataSourceSelector.button(postgreSqlText.editButtonText)
|
||||
).click();
|
||||
cy.verifyRequiredFieldValidation(section, "rgb(215, 45, 57)");
|
||||
} else {
|
||||
cy.get(dataSourceSelector.textField(section)).click();
|
||||
cy.get(commonSelectors.textField(section)).should(
|
||||
"have.css",
|
||||
"border-color",
|
||||
"rgba(0, 0, 0, 0)"
|
||||
);
|
||||
cy.get(dataSourceSelector.textField(section))
|
||||
.type("123")
|
||||
.clear()
|
||||
.blur();
|
||||
cy.verifyRequiredFieldValidation(section, "rgb(215, 45, 57)");
|
||||
}
|
||||
} else {
|
||||
cy.get(dataSourceSelector.labelFieldName(section)).verifyVisibleElement(
|
||||
"have.text",
|
||||
section
|
||||
);
|
||||
cy.get(dataSourceSelector.textField(section)).should("be.visible");
|
||||
}
|
||||
});
|
||||
cy.get(postgreSqlSelector.labelSsl).verifyVisibleElement(
|
||||
"have.text",
|
||||
postgreSqlText.labelSSL
|
||||
);
|
||||
cy.get(postgreSqlSelector.labelDbName).verifyVisibleElement(
|
||||
"have.text",
|
||||
postgreSqlText.labelDbName
|
||||
);
|
||||
cy.get(postgreSqlSelector.labelUserName).verifyVisibleElement(
|
||||
"have.text",
|
||||
postgreSqlText.labelUserName
|
||||
);
|
||||
cy.get(postgreSqlSelector.labelPassword).verifyVisibleElement(
|
||||
"have.text",
|
||||
postgreSqlText.labelPassword
|
||||
);
|
||||
cy.get(postgreSqlSelector.sslToggleInput).should("be.visible");
|
||||
cy.get(postgreSqlSelector.labelSSLCertificate).verifyVisibleElement(
|
||||
"have.text",
|
||||
postgreSqlText.sslCertificate
|
||||
|
|
@ -132,72 +249,85 @@ describe("Data sources", () => {
|
|||
"have.text",
|
||||
postgreSqlText.couldNotConnect
|
||||
);
|
||||
cy.get(postgreSqlSelector.buttonSave).verifyVisibleElement(
|
||||
cy.get(postgreSqlSelector.buttonSave)
|
||||
.verifyVisibleElement("have.text", postgreSqlText.buttonTextSave)
|
||||
.and("be.disabled");
|
||||
cy.get(dataSourceSelector.connectionAlertText).verifyVisibleElement(
|
||||
"have.text",
|
||||
postgreSqlText.buttonTextSave
|
||||
"connect ECONNREFUSED 127.0.0.1:5432"
|
||||
);
|
||||
cy.get(dataSourceSelector.connectionAlertText).should("be.visible");
|
||||
deleteDatasource(`cypress-${data.dataSourceName}-postgresql`);
|
||||
|
||||
cy.apiDeleteGDS(`cypress-${data.dataSourceName}-postgresql`);
|
||||
});
|
||||
|
||||
it.skip("Should verify the functionality of PostgreSQL connection form.", () => {
|
||||
selectAndAddDataSource(
|
||||
"databases",
|
||||
postgreSqlText.postgreSQL,
|
||||
data.dataSourceName
|
||||
it("Should verify the functionality of PostgreSQL connection form.", () => {
|
||||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
||||
cy.apiCreateGDS(
|
||||
`${Cypress.env("server_host")}/api/data-sources`,
|
||||
`cypress-${data.dataSourceName}-manual-pgsql`,
|
||||
"postgresql",
|
||||
[
|
||||
{ key: "connection_type", value: "manual", encrypted: false },
|
||||
{ key: "host", value: `${Cypress.env("pg_host")}`, encrypted: false },
|
||||
{ key: "port", value: 5432, encrypted: false },
|
||||
{ key: "ssl_enabled", value: false, encrypted: false },
|
||||
{ key: "database", value: "postgres", encrypted: false },
|
||||
{ key: "ssl_certificate", value: "none", encrypted: false },
|
||||
{
|
||||
key: "username",
|
||||
value: `${Cypress.env("pg_user")}`,
|
||||
encrypted: false,
|
||||
},
|
||||
{
|
||||
key: "password",
|
||||
value: `${Cypress.env("pg_password")}`,
|
||||
encrypted: true,
|
||||
},
|
||||
{ key: "ca_cert", value: null, encrypted: true },
|
||||
{ key: "client_key", value: null, encrypted: true },
|
||||
{ key: "client_cert", value: null, encrypted: true },
|
||||
{ key: "root_cert", value: null, encrypted: true },
|
||||
{ key: "connection_string", value: null, encrypted: true },
|
||||
]
|
||||
);
|
||||
|
||||
fillDataSourceTextField(
|
||||
postgreSqlText.labelHost,
|
||||
postgreSqlText.placeholderEnterHost,
|
||||
Cypress.env("pg_host")
|
||||
);
|
||||
fillDataSourceTextField(
|
||||
postgreSqlText.labelPort,
|
||||
postgreSqlText.placeholderEnterPort,
|
||||
"5432"
|
||||
);
|
||||
cy.get('[data-cy="-toggle-input"]').then(($el) => {
|
||||
if ($el.is(":checked")) {
|
||||
cy.get('[data-cy="-toggle-input"]').uncheck();
|
||||
}
|
||||
});
|
||||
fillDataSourceTextField(
|
||||
postgreSqlText.labelDbName,
|
||||
postgreSqlText.placeholderNameOfDB,
|
||||
"postgres"
|
||||
);
|
||||
fillDataSourceTextField(
|
||||
postgreSqlText.labelUserName,
|
||||
postgreSqlText.placeholderEnterUserName,
|
||||
"postgres"
|
||||
);
|
||||
fillDataSourceTextField(
|
||||
postgreSqlText.labelPassword,
|
||||
"**************",
|
||||
Cypress.env("pg_password")
|
||||
);
|
||||
|
||||
cy.get(
|
||||
dataSourceSelector.dataSourceNameButton(
|
||||
`cypress-${data.dataSourceName}-manual-pgsql`
|
||||
)
|
||||
)
|
||||
.should("be.visible")
|
||||
.click();
|
||||
cy.get(postgreSqlSelector.buttonTestConnection).click();
|
||||
cy.get(postgreSqlSelector.textConnectionVerified, {
|
||||
timeout: 10000,
|
||||
}).should("have.text", postgreSqlText.labelConnectionVerified);
|
||||
cy.get(postgreSqlSelector.buttonSave).click();
|
||||
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
postgreSqlText.toastDSSaved
|
||||
cy.apiDeleteGDS(`cypress-${data.dataSourceName}-manual-pgsql`);
|
||||
cy.reload();
|
||||
cy.apiCreateGDS(
|
||||
`${Cypress.env("server_host")}/api/data-sources`,
|
||||
`cypress-${data.dataSourceName}-string-pgsql`,
|
||||
"postgresql",
|
||||
[
|
||||
{ key: "connection_type", value: "string", encrypted: false },
|
||||
{
|
||||
key: "connection_string",
|
||||
value: `${Cypress.env("pg_string")}`,
|
||||
encrypted: true,
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
||||
cy.get(
|
||||
`[data-cy="cypress-${data.dataSourceName}-postgresql-button"]`
|
||||
).verifyVisibleElement(
|
||||
"have.text",
|
||||
`cypress-${data.dataSourceName}-postgresql`
|
||||
);
|
||||
|
||||
deleteDatasource(`cypress-${data.dataSourceName}-postgresql`);
|
||||
dataSourceSelector.dataSourceNameButton(
|
||||
`cypress-${data.dataSourceName}-string-pgsql`
|
||||
)
|
||||
)
|
||||
.should("be.visible")
|
||||
.click();
|
||||
cy.get(postgreSqlSelector.buttonTestConnection).click();
|
||||
cy.get(postgreSqlSelector.textConnectionVerified, {
|
||||
timeout: 10000,
|
||||
}).should("have.text", postgreSqlText.labelConnectionVerified);
|
||||
cy.apiDeleteGDS(`cypress-${data.dataSourceName}-string-pgsql`);
|
||||
});
|
||||
|
||||
it.skip("Should verify elements of the Query section.", () => {
|
||||
|
|
|
|||
|
|
@ -426,6 +426,7 @@ describe("Data source Rest API", () => {
|
|||
});
|
||||
}
|
||||
);
|
||||
cy.apiDeleteApp(`${fake.companyName}-restAPI-CURD-App`);
|
||||
cy.apiDeleteGDS(`cypress-${data.dataSourceName}-restapi`);
|
||||
});
|
||||
it("Should verify response for basic authentication type connection", () => {
|
||||
|
|
@ -488,6 +489,7 @@ describe("Data source Rest API", () => {
|
|||
method: "GET",
|
||||
urlSuffix: "/basic-auth/invaliduser/invalidpass",
|
||||
});
|
||||
cy.apiDeleteApp(`${fake.companyName}-restAPI-Basic-App`);
|
||||
cy.apiDeleteGDS(`cypress-${data.dataSourceName}-restapi`);
|
||||
});
|
||||
it("Should verify response for bearer authentication type connection", () => {
|
||||
|
|
@ -545,6 +547,7 @@ describe("Data source Rest API", () => {
|
|||
urlSuffix: "/bearer",
|
||||
expectedResponseShape: { authenticated: true, token: "my-token-123" },
|
||||
});
|
||||
cy.apiDeleteApp(`${fake.companyName}-restAPI-Bearer-App`);
|
||||
cy.intercept("GET", "api/data_sources?**").as("datasource");
|
||||
cy.apiCreateGDS(
|
||||
`${Cypress.env("server_host")}/api/data-sources`,
|
||||
|
|
@ -597,6 +600,7 @@ describe("Data source Rest API", () => {
|
|||
method: "GET",
|
||||
urlSuffix: "/bearer",
|
||||
});
|
||||
cy.apiDeleteApp(`${fake.companyName}-restAPI-Bearer-invalid`);
|
||||
cy.apiDeleteGDS(`cypress-${data.dataSourceName}-restapi`);
|
||||
});
|
||||
it.skip("Should verify response for authentication code grant type connection", () => {
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ export const resolveHost = () => {
|
|||
const baseUrl = Cypress.config("baseUrl");
|
||||
|
||||
const urlMapping = {
|
||||
"http://localhost:8082": "http://localhost:8082",
|
||||
"http://localhost:3000": "http://localhost:3000",
|
||||
"http://localhost:3000/apps": "http://localhost:3000/apps",
|
||||
"http://localhost:4001": "http://localhost:3000",
|
||||
"http://localhost:4001/apps": "http://localhost:3000/apps",
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
3.13.0
|
||||
3.14.0
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 777446d71e78e5941d34353606a12d982820438f
|
||||
Subproject commit 4ca98b6bb66d1d9845f8b326100945a969488f94
|
||||
|
|
@ -1,12 +1,13 @@
|
|||
import React from 'react';
|
||||
import cx from 'classnames';
|
||||
import { pluginsService, marketplaceService } from '@/_services';
|
||||
import { pluginsService, marketplaceService, globalDatasourceService } from '@/_services';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import Spinner from '@/_ui/Spinner';
|
||||
import { capitalizeFirstLetter, useTagsByPluginId } from './utils';
|
||||
import { ConfirmDialog } from '@/_components';
|
||||
import Icon from '@/_ui/Icon/SolidIcons';
|
||||
import config from 'config';
|
||||
import Modal from '@/HomePage/Modal';
|
||||
|
||||
export const InstalledPlugins = () => {
|
||||
const [allPlugins, setAllPlugins] = React.useState([]);
|
||||
|
|
@ -81,6 +82,7 @@ const InstalledPluginCard = ({ plugin, marketplacePlugin, fetchPlugins, isDevMod
|
|||
const [updating, setUpdating] = React.useState(false);
|
||||
const [isDeleteModalVisible, setDeleteModalVisibility] = React.useState(false);
|
||||
const [isDeletingPlugin, setDeletingPlugin] = React.useState(false);
|
||||
const [showDependentQueriesInfo, setShowDependentQueriesInfo] = React.useState(false);
|
||||
|
||||
const darkMode = localStorage.getItem('darkMode') === 'true';
|
||||
const { id, name, pluginId } = plugin;
|
||||
|
|
@ -140,6 +142,21 @@ const InstalledPluginCard = ({ plugin, marketplacePlugin, fetchPlugins, isDevMod
|
|||
toast.success(`${capitalizeFirstLetter(name)} reloaded`);
|
||||
};
|
||||
|
||||
const getQueriesLinkedToMarketplacePlugin = (plugin) => {
|
||||
globalDatasourceService
|
||||
.getQueriesLinkedToMarketplacePlugin(plugin.id)
|
||||
.then((data) => {
|
||||
if (data?.dependent_queries) {
|
||||
setShowDependentQueriesInfo(true);
|
||||
} else {
|
||||
setDeleteModalVisibility(true);
|
||||
}
|
||||
})
|
||||
.catch(({ error }) => {
|
||||
toast.error(error);
|
||||
});
|
||||
};
|
||||
|
||||
const pluginDeleteMessage = (
|
||||
<>
|
||||
Deleting <strong>{capitalizeFirstLetter(name)}</strong> plugin will result in the permanent removal of all
|
||||
|
|
@ -150,6 +167,15 @@ const InstalledPluginCard = ({ plugin, marketplacePlugin, fetchPlugins, isDevMod
|
|||
|
||||
return (
|
||||
<>
|
||||
<Modal
|
||||
title="Dependent queries found!"
|
||||
show={showDependentQueriesInfo}
|
||||
closeModal={() => setShowDependentQueriesInfo(false)}
|
||||
>
|
||||
<div className="mt-3 mb-3">
|
||||
Cannot delete the <b>{plugin?.name}</b> plugin as it is used in the apps
|
||||
</div>
|
||||
</Modal>
|
||||
<ConfirmDialog
|
||||
title={'Delete plugin'}
|
||||
show={isDeleteModalVisible}
|
||||
|
|
@ -238,7 +264,7 @@ const InstalledPluginCard = ({ plugin, marketplacePlugin, fetchPlugins, isDevMod
|
|||
<div className="col-auto">
|
||||
<div
|
||||
className={cx('cursor-pointer link-primary', { disabled: updating })}
|
||||
onClick={() => setDeleteModalVisibility(true)}
|
||||
onClick={() => getQueriesLinkedToMarketplacePlugin(plugin)}
|
||||
>
|
||||
Remove
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -17,6 +17,11 @@ export const MarketplaceCard = ({ id, name, repo, description, version, isInstal
|
|||
}, [isInstalled]);
|
||||
|
||||
const installPlugin = async () => {
|
||||
if (installed) {
|
||||
toast.error(`${capitalizeFirstLetter(name)} is already installed.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const body = {
|
||||
id,
|
||||
name,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useEffect, useState, useLayoutEffect, useRef } from 'react';
|
||||
import { openapiService } from '@/_services';
|
||||
import Select from '@/_ui/Select';
|
||||
import { queryManagerSelectComponentStyle } from '@/_ui/Select/styles';
|
||||
|
|
@ -110,7 +110,7 @@ const ApiEndpointInput = (props) => {
|
|||
if (isEmpty(paths)) return [];
|
||||
|
||||
const pathGroups = Object.keys(paths).reduce((acc, path) => {
|
||||
const operations = Object.keys(paths[path]);
|
||||
const operations = Object.keys(paths[path]).filter((op) => Object.keys(operationColorMapping).includes(op));
|
||||
const category = path.split('/')[2];
|
||||
operations.forEach((operation) => categorizeOperations(operation, path, acc, category));
|
||||
return acc;
|
||||
|
|
@ -135,7 +135,7 @@ const ApiEndpointInput = (props) => {
|
|||
{loadingSpec && (
|
||||
<div className="p-3">
|
||||
<div className="spinner-border spinner-border-sm text-azure mx-2" role="status"></div>
|
||||
{props.t('stripe', 'Please wait while we load the OpenAPI specification.')}
|
||||
<span>Please wait while we load the OpenAPI specification.</span>
|
||||
</div>
|
||||
)}
|
||||
{options && !loadingSpec && (
|
||||
|
|
@ -227,57 +227,64 @@ const RenderParameterFields = ({ parameters, type, label, options, changeParam,
|
|||
}
|
||||
|
||||
const paramLabelWithDescription = (param) => {
|
||||
const label = type === 'request' ? param : param.name;
|
||||
const description = type === 'request' ? parameters[param]?.description : param.description;
|
||||
|
||||
return (
|
||||
<ToolTip message={type === 'request' ? DOMPurify.sanitize(parameters[param].description) : param.description}>
|
||||
<div className="cursor-help">
|
||||
<input
|
||||
type="text"
|
||||
value={type === 'request' ? param : param.name}
|
||||
className="form-control form-control-underline"
|
||||
placeholder="key"
|
||||
disabled
|
||||
/>
|
||||
<ToolTip message={DOMPurify.sanitize(description)}>
|
||||
<div className="cursor-help d-flex align-items-center">
|
||||
<AutoWidthText value={label} className="form-control form-control-underline" />
|
||||
</div>
|
||||
</ToolTip>
|
||||
);
|
||||
};
|
||||
|
||||
const paramLabelWithoutDescription = (param) => {
|
||||
return (
|
||||
<input
|
||||
type="text"
|
||||
value={type === 'request' ? param : param.name}
|
||||
className="form-control"
|
||||
placeholder="key"
|
||||
disabled
|
||||
/>
|
||||
);
|
||||
};
|
||||
const label = type === 'request' ? param : param.name;
|
||||
|
||||
const paramType = (param) => {
|
||||
return (
|
||||
<div className="p-2 text-muted">
|
||||
{type === 'query' &&
|
||||
param?.schema?.anyOf &&
|
||||
param?.schema?.anyOf.map((type, i) =>
|
||||
i < param.schema?.anyOf.length - 1
|
||||
? type.type.substring(0, 3).toUpperCase() + '|'
|
||||
: type.type.substring(0, 3).toUpperCase()
|
||||
)}
|
||||
{(type === 'path' || (type === 'query' && !param?.schema?.anyOf)) &&
|
||||
param?.schema?.type?.substring(0, 3).toUpperCase()}
|
||||
{type === 'request' && parameters[param].type?.substring(0, 3).toUpperCase()}
|
||||
<div className="d-flex align-items-center" style={{ gap: '4px' }}>
|
||||
<AutoWidthText value={label} className="form-control" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const paramType = (param) => {
|
||||
let paramTypeValue;
|
||||
|
||||
if (type === 'query') {
|
||||
if (param?.schema?.anyOf) {
|
||||
return (
|
||||
<div className="p-2 text-muted">
|
||||
{param.schema.anyOf.map((typeObj, i) =>
|
||||
i < param.schema.anyOf.length - 1
|
||||
? (typeObj.type || '').toString().substring(0, 3).toUpperCase() + '|'
|
||||
: (typeObj.type || '').toString().substring(0, 3).toUpperCase()
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
paramTypeValue = param?.schema?.type;
|
||||
} else if (type === 'path') {
|
||||
paramTypeValue = param?.schema?.type;
|
||||
} else if (type === 'request') {
|
||||
paramTypeValue = parameters[param]?.type;
|
||||
}
|
||||
|
||||
const displayType = Array.isArray(paramTypeValue) ? paramTypeValue[0] : paramTypeValue;
|
||||
|
||||
return <div className="p-2 text-muted">{displayType?.toString().substring(0, 3).toUpperCase() || ''}</div>;
|
||||
};
|
||||
|
||||
const paramDetails = (param) => {
|
||||
return (
|
||||
<div className="col-auto d-flex field field-width-179 align-items-center">
|
||||
{(type === 'request' && parameters[param].description) || param?.description
|
||||
? paramLabelWithDescription(param)
|
||||
: paramLabelWithoutDescription(param)}
|
||||
{param.required && <span className="text-danger fw-bold">*</span>}
|
||||
<div className="col-auto d-flex field field-width-179 align-items-center justify-content-between">
|
||||
<div className="d-inline-flex align-items-center gap-3">
|
||||
{(type === 'request' && parameters[param].description) || param?.description
|
||||
? paramLabelWithDescription(param)
|
||||
: paramLabelWithoutDescription(param)}
|
||||
{param.required && <span className="text-danger fw-bold">*</span>}
|
||||
</div>
|
||||
{paramType(param)}
|
||||
</div>
|
||||
);
|
||||
|
|
@ -359,3 +366,34 @@ RenderParameterFields.propTypes = {
|
|||
removeParam: PropTypes.func,
|
||||
darkMode: PropTypes.bool,
|
||||
};
|
||||
|
||||
const AutoWidthText = ({ value, className }) => {
|
||||
const spanRef = useRef(null);
|
||||
const [width, setWidth] = useState(0);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (spanRef.current) {
|
||||
setWidth(spanRef.current.offsetWidth);
|
||||
}
|
||||
}, [value]);
|
||||
|
||||
return (
|
||||
<div className={className} style={{ display: 'inline-block', width: width ? `${width}px` : 'auto' }}>
|
||||
<span
|
||||
ref={spanRef}
|
||||
style={{
|
||||
position: 'absolute',
|
||||
visibility: 'hidden',
|
||||
whiteSpace: 'pre',
|
||||
fontSize: '12px',
|
||||
fontFamily: 'inherit',
|
||||
fontWeight: 400,
|
||||
lineHeight: '20px',
|
||||
}}
|
||||
>
|
||||
{value}
|
||||
</span>
|
||||
{value}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ const DynamicForm = ({
|
|||
encrypted,
|
||||
placeholders = {},
|
||||
editorType = 'basic',
|
||||
specUrl = '',
|
||||
spec_url = '',
|
||||
disabled = false,
|
||||
buttonText,
|
||||
text,
|
||||
|
|
@ -486,7 +486,7 @@ const DynamicForm = ({
|
|||
};
|
||||
case 'react-component-api-endpoint':
|
||||
return {
|
||||
specUrl: specUrl,
|
||||
specUrl: spec_url,
|
||||
optionsChanged,
|
||||
options,
|
||||
darkMode,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { datasourceService } from '@/_services';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { toast } from 'react-hot-toast';
|
||||
|
|
@ -15,8 +15,16 @@ const Slack = ({
|
|||
isDisabled,
|
||||
}) => {
|
||||
const [authStatus, setAuthStatus] = useState(null);
|
||||
const whiteLabelText = retrieveWhiteLabelText();
|
||||
const [whiteLabelText, setWhiteLabelText] = useState('');
|
||||
const plugin_id = selectedDataSource?.plugin?.id;
|
||||
const { t } = useTranslation();
|
||||
useEffect(() => {
|
||||
async function fetchLabel() {
|
||||
const text = await retrieveWhiteLabelText();
|
||||
setWhiteLabelText(text);
|
||||
}
|
||||
fetchLabel();
|
||||
}, []);
|
||||
|
||||
function authGoogle() {
|
||||
const provider = 'slack';
|
||||
|
|
@ -29,7 +37,7 @@ const Slack = ({
|
|||
}
|
||||
|
||||
datasourceService
|
||||
.fetchOauth2BaseUrl(provider)
|
||||
.fetchOauth2BaseUrl(provider, plugin_id, {})
|
||||
.then((data) => {
|
||||
const authUrl = `${data.url}&scope=${scope}&access_type=offline&prompt=select_account`;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Input from '@/_ui/Input';
|
||||
|
|
@ -18,17 +18,26 @@ const Zendesk = ({
|
|||
isDisabled,
|
||||
optionsChanged,
|
||||
}) => {
|
||||
const [whiteLabelText, setWhiteLabelText] = useState('');
|
||||
const [authStatus, setAuthStatus] = useState(null);
|
||||
const whiteLabelText = retrieveWhiteLabelText();
|
||||
useEffect(() => {
|
||||
async function fetchLabel() {
|
||||
const text = await retrieveWhiteLabelText();
|
||||
setWhiteLabelText(text);
|
||||
}
|
||||
fetchLabel();
|
||||
}, []);
|
||||
|
||||
function authZendesk() {
|
||||
const provider = 'zendesk';
|
||||
setAuthStatus('waiting_for_url');
|
||||
|
||||
const scope = options?.access_type?.value === 'read' ? 'read' : 'read%20write';
|
||||
const subDomain = options?.subdomain?.value;
|
||||
const client_id = options?.client_id?.value;
|
||||
|
||||
try {
|
||||
const authUrl = `https://${options?.subdomain?.value}.zendesk.com/oauth/authorizations/new?response_type=code&client_id=${options?.client_id?.value}&redirect_uri=${window.location.origin}/oauth2/authorize&scope=${scope}`;
|
||||
const authUrl = `https://${subDomain}.zendesk.com/oauth/authorizations/new?response_type=code&client_id=${client_id}&redirect_uri=${window.location.origin}/oauth2/authorize&scope=${scope}`;
|
||||
localStorage.setItem('sourceWaitingForOAuth', 'newSource');
|
||||
localStorage.setItem('currentAppEnvironmentIdForOauth', currentAppEnvironmentId);
|
||||
optionchanged('provider', provider).then(() => {
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ function setOauth2Token(dataSourceId, body, current_organization_id) {
|
|||
function fetchOauth2BaseUrl(provider, plugin_id = null, source_options = {}) {
|
||||
const payload = { provider, ...(plugin_id && { plugin_id }), ...(source_options && { source_options }) };
|
||||
const requestOptions = {
|
||||
method: 'GET',
|
||||
method: 'POST',
|
||||
headers: authHeader(),
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(payload),
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ export const globalDatasourceService = {
|
|||
convertToGlobal,
|
||||
getDataSourceByEnvironmentId,
|
||||
getForApp,
|
||||
getQueriesLinkedToDatasource,
|
||||
getQueriesLinkedToMarketplacePlugin,
|
||||
};
|
||||
|
||||
function getForApp(organizationId, appVersionId, environmentId) {
|
||||
|
|
@ -68,3 +70,15 @@ function getDataSourceByEnvironmentId(dataSourceId, environmentId) {
|
|||
handleResponse
|
||||
);
|
||||
}
|
||||
|
||||
function getQueriesLinkedToMarketplacePlugin(pluginId) {
|
||||
const requestOptions = { method: 'GET', headers: authHeader(), credentials: 'include' };
|
||||
return fetch(`${config.apiUrl}/data-sources/dependent-queries/marketplace-plugin/${pluginId}`, requestOptions).then(
|
||||
handleResponse
|
||||
);
|
||||
}
|
||||
|
||||
function getQueriesLinkedToDatasource(dataSourceId) {
|
||||
const requestOptions = { method: 'GET', headers: authHeader(), credentials: 'include' };
|
||||
return fetch(`${config.apiUrl}/data-sources/dependent-queries/${dataSourceId}`, requestOptions).then(handleResponse);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ export const userService = {
|
|||
getAvatar,
|
||||
updateAvatar,
|
||||
updateUserType,
|
||||
updateUserTypeInstance,
|
||||
getUserLimits,
|
||||
changeUserPassword,
|
||||
generateUserPassword,
|
||||
|
|
@ -80,6 +81,16 @@ function updateUserType(userUpdateBody) {
|
|||
return fetch(`${config.apiUrl}/users/user-type`, requestOptions).then(handleResponse);
|
||||
}
|
||||
|
||||
function updateUserTypeInstance(userUpdateBody) {
|
||||
const requestOptions = {
|
||||
method: 'PATCH',
|
||||
headers: authHeader(),
|
||||
body: JSON.stringify(userUpdateBody),
|
||||
credentials: 'include',
|
||||
};
|
||||
return fetch(`${config.apiUrl}/users/user-type/instance`, requestOptions).then(handleResponse);
|
||||
}
|
||||
|
||||
function changePassword(currentPassword, newPassword) {
|
||||
const body = { currentPassword, newPassword };
|
||||
const requestOptions = { method: 'PATCH', headers: authHeader(), credentials: 'include', body: JSON.stringify(body) };
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import config from 'config';
|
|||
import { capitalize, isEmpty } from 'lodash';
|
||||
import { Card } from '@/_ui/Card';
|
||||
import { withTranslation, useTranslation } from 'react-i18next';
|
||||
import { camelizeKeys, decamelizeKeys } from 'humps';
|
||||
import { camelizeKeys, decamelizeKeys, decamelize } from 'humps';
|
||||
import { ButtonSolid } from '@/_ui/AppButton/AppButton';
|
||||
import SolidIcon from '@/_ui/Icon/SolidIcons';
|
||||
import { useAppVersionStore } from '@/_stores/appVersionStore';
|
||||
|
|
@ -249,14 +249,26 @@ class DataSourceManagerComponent extends React.Component {
|
|||
const scope = this.state?.scope || selectedDataSource?.scope;
|
||||
|
||||
const parsedOptions = Object?.keys(options)?.map((key) => {
|
||||
const keyMeta = dataSourceMeta.options[key];
|
||||
let keyMeta = dataSourceMeta.options[key];
|
||||
let isEncrypted = false;
|
||||
if (keyMeta) {
|
||||
isEncrypted = keyMeta.encrypted;
|
||||
}
|
||||
|
||||
// to resolve any casing mis-match
|
||||
if (decamelize(key) !== key) {
|
||||
const newKey = decamelize(key);
|
||||
isEncrypted = dataSourceMeta.options[newKey]?.encrypted;
|
||||
}
|
||||
|
||||
return {
|
||||
key: key,
|
||||
value: options[key].value,
|
||||
encrypted: keyMeta ? keyMeta.encrypted : false,
|
||||
encrypted: isEncrypted,
|
||||
...(!options[key]?.value && { credential_id: options[key]?.credential_id }),
|
||||
};
|
||||
});
|
||||
|
||||
if (OAuthDs.includes(kind)) {
|
||||
const value = localStorage.getItem('OAuthCode');
|
||||
parsedOptions.push({ key: 'code', value, encrypted: false });
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import SolidIcon from '@/_ui/Icon/SolidIcons';
|
|||
import { SearchBox } from '@/_components/SearchBox';
|
||||
import { DATA_SOURCE_TYPE } from '@/_helpers/constants';
|
||||
import FolderSkeleton from '@/_ui/FolderSkeleton/FolderSkeleton';
|
||||
import Modal from '@/HomePage/Modal';
|
||||
|
||||
export const List = ({ updateSelectedDatasource }) => {
|
||||
const {
|
||||
|
|
@ -28,6 +29,7 @@ export const List = ({ updateSelectedDatasource }) => {
|
|||
const [isDeleteModalVisible, setDeleteModalVisibility] = React.useState(false);
|
||||
const [filteredData, setFilteredData] = useState(dataSources);
|
||||
const [showInput, setShowInput] = useState(false);
|
||||
const [showDependentQueriesInfo, setShowDependentQueriesInfo] = useState(false);
|
||||
|
||||
const darkMode = localStorage.getItem('darkMode') === 'true';
|
||||
|
||||
|
|
@ -50,7 +52,7 @@ export const List = ({ updateSelectedDatasource }) => {
|
|||
setCurrentEnvironment(environments[0]);
|
||||
toggleDataSourceManagerModal(true);
|
||||
updateSelectedDatasource(selectedSource?.name);
|
||||
setDeleteModalVisibility(true);
|
||||
getQueriesLinkedToDatasource(selectedSource);
|
||||
};
|
||||
|
||||
const executeDataSourceDeletion = () => {
|
||||
|
|
@ -74,6 +76,21 @@ export const List = ({ updateSelectedDatasource }) => {
|
|||
});
|
||||
};
|
||||
|
||||
const getQueriesLinkedToDatasource = (selectedSource) => {
|
||||
globalDatasourceService
|
||||
.getQueriesLinkedToDatasource(selectedSource.id)
|
||||
.then((data) => {
|
||||
if (data?.dependent_queries) {
|
||||
setShowDependentQueriesInfo(true);
|
||||
} else {
|
||||
setDeleteModalVisibility(true);
|
||||
}
|
||||
})
|
||||
.catch(({ error }) => {
|
||||
toast.error(error);
|
||||
});
|
||||
};
|
||||
|
||||
const cancelDeleteDataSource = () => {
|
||||
setDeleteModalVisibility(false);
|
||||
};
|
||||
|
|
@ -171,6 +188,16 @@ export const List = ({ updateSelectedDatasource }) => {
|
|||
)}
|
||||
</div>
|
||||
</div>
|
||||
<Modal
|
||||
title="Dependent queries found!"
|
||||
show={showDependentQueriesInfo}
|
||||
closeModal={() => setShowDependentQueriesInfo(false)}
|
||||
>
|
||||
<div className="mt-3 mb-3">
|
||||
Cannot delete <b>{selectedDataSource?.name ? selectedDataSource.name : 'datasource'}</b> as it is used in the
|
||||
apps
|
||||
</div>
|
||||
</Modal>
|
||||
<ConfirmDialog
|
||||
show={isDeleteModalVisible}
|
||||
message={'You will lose all the queries created from this data source. Do you really want to delete?'}
|
||||
|
|
|
|||
544
marketplace/package-lock.json
generated
544
marketplace/package-lock.json
generated
|
|
@ -200,23 +200,23 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-cognito-identity": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.812.0.tgz",
|
||||
"integrity": "sha512-LWkP+Vb2f6aNaway06XvFZG3altSXltAClzCz9cTFuOfKG6V2X+0VWsW9cnFRV4+MFFJW3iQAaPMQ1fBO9Rusg==",
|
||||
"version": "3.817.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.817.0.tgz",
|
||||
"integrity": "sha512-MNGwOJDQU0jpvsLLPSuPQDhPtDzFTc/k7rLmiKoPrIlgb3Y8pSF4crpJ+ZH3+xod2NWyyOVMEMQeMaKFFdMaKw==",
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha256-browser": "5.2.0",
|
||||
"@aws-crypto/sha256-js": "5.2.0",
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/credential-provider-node": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/credential-provider-node": "3.817.0",
|
||||
"@aws-sdk/middleware-host-header": "3.804.0",
|
||||
"@aws-sdk/middleware-logger": "3.804.0",
|
||||
"@aws-sdk/middleware-recursion-detection": "3.804.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.812.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.816.0",
|
||||
"@aws-sdk/region-config-resolver": "3.808.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@aws-sdk/util-endpoints": "3.808.0",
|
||||
"@aws-sdk/util-user-agent-browser": "3.804.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.812.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.816.0",
|
||||
"@smithy/config-resolver": "^4.1.2",
|
||||
"@smithy/core": "^3.3.3",
|
||||
"@smithy/fetch-http-handler": "^5.0.2",
|
||||
|
|
@ -318,22 +318,22 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/client-sso": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.812.0.tgz",
|
||||
"integrity": "sha512-O//smQRj1+RXELB7xX54s5pZB0V69KHXpUZmz8V+8GAYO1FKTHfbpUgK+zyMNb+lFZxG9B69yl8pWPZ/K8bvxA==",
|
||||
"version": "3.817.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.817.0.tgz",
|
||||
"integrity": "sha512-fCh5rUHmWmWDvw70NNoWpE5+BRdtNi45kDnIoeoszqVg7UKF79SlG+qYooUT52HKCgDNHqgbWaXxMOSqd2I/OQ==",
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha256-browser": "5.2.0",
|
||||
"@aws-crypto/sha256-js": "5.2.0",
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/middleware-host-header": "3.804.0",
|
||||
"@aws-sdk/middleware-logger": "3.804.0",
|
||||
"@aws-sdk/middleware-recursion-detection": "3.804.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.812.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.816.0",
|
||||
"@aws-sdk/region-config-resolver": "3.808.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@aws-sdk/util-endpoints": "3.808.0",
|
||||
"@aws-sdk/util-user-agent-browser": "3.804.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.812.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.816.0",
|
||||
"@smithy/config-resolver": "^4.1.2",
|
||||
"@smithy/core": "^3.3.3",
|
||||
"@smithy/fetch-http-handler": "^5.0.2",
|
||||
|
|
@ -366,9 +366,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/core": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.812.0.tgz",
|
||||
"integrity": "sha512-myWA9oHMBVDObKrxG+puAkIGs8igcWInQ1PWCRTS/zN4BkhUMFjjh/JPV/4Vzvtvj5E36iujq2WtlrDLl1PpOw==",
|
||||
"version": "3.816.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.816.0.tgz",
|
||||
"integrity": "sha512-Lx50wjtyarzKpMFV6V+gjbSZDgsA/71iyifbClGUSiNPoIQ4OCV0KVOmAAj7mQRVvGJqUMWKVM+WzK79CjbjWA==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/core": "^3.3.3",
|
||||
|
|
@ -387,11 +387,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/credential-provider-env": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.812.0.tgz",
|
||||
"integrity": "sha512-Ge7IEu06ANurGBZx39q9CNN/ncqb1K8lpKZCY969uNWO0/7YPhnplrRJGMZYIS35nD2mBm3ortEKjY/wMZZd5g==",
|
||||
"version": "3.816.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.816.0.tgz",
|
||||
"integrity": "sha512-wUJZwRLe+SxPxRV9AENYBLrJZRrNIo+fva7ZzejsC83iz7hdfq6Rv6B/aHEdPwG/nQC4+q7UUvcRPlomyrpsBA==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
"@smithy/types": "^4.2.0",
|
||||
|
|
@ -402,11 +402,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/credential-provider-http": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.812.0.tgz",
|
||||
"integrity": "sha512-Vux2U42vPGXeE407Lp6v3yVA65J7hBO9rB67LXshyGVi7VZLAYWc4mrZxNJNqabEkjcDEmMQQakLPT6zc5SvFw==",
|
||||
"version": "3.816.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.816.0.tgz",
|
||||
"integrity": "sha512-gcWGzMQ7yRIF+ljTkR8Vzp7727UY6cmeaPrFQrvcFB8PhOqWpf7g0JsgOf5BSaP8CkkSQcTQHc0C5ZYAzUFwPg==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/fetch-http-handler": "^5.0.2",
|
||||
"@smithy/node-http-handler": "^4.0.4",
|
||||
|
|
@ -422,17 +422,17 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/credential-provider-ini": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.812.0.tgz",
|
||||
"integrity": "sha512-oltqGvQ488xtPY5wrNjbD+qQYYkuCjn30IDE1qKMxJ58EM6UVTQl3XV44Xq07xfF5gKwVJQkfIyOkRAguOVybg==",
|
||||
"version": "3.817.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.817.0.tgz",
|
||||
"integrity": "sha512-kyEwbQyuXE+phWVzloMdkFv6qM6NOon+asMXY5W0fhDKwBz9zQLObDRWBrvQX9lmqq8BbDL1sCfZjOh82Y+RFw==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/credential-provider-env": "3.812.0",
|
||||
"@aws-sdk/credential-provider-http": "3.812.0",
|
||||
"@aws-sdk/credential-provider-process": "3.812.0",
|
||||
"@aws-sdk/credential-provider-sso": "3.812.0",
|
||||
"@aws-sdk/credential-provider-web-identity": "3.812.0",
|
||||
"@aws-sdk/nested-clients": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/credential-provider-env": "3.816.0",
|
||||
"@aws-sdk/credential-provider-http": "3.816.0",
|
||||
"@aws-sdk/credential-provider-process": "3.816.0",
|
||||
"@aws-sdk/credential-provider-sso": "3.817.0",
|
||||
"@aws-sdk/credential-provider-web-identity": "3.817.0",
|
||||
"@aws-sdk/nested-clients": "3.817.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/credential-provider-imds": "^4.0.4",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
|
|
@ -445,16 +445,16 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/credential-provider-node": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.812.0.tgz",
|
||||
"integrity": "sha512-SnvSWBP6cr9nqx784eETnL2Zl7ZnMB/oJgFVEG1aejAGbT1H9gTpMwuUsBXk4u/mEYe3f1lh1Wqo+HwDgNkfrg==",
|
||||
"version": "3.817.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.817.0.tgz",
|
||||
"integrity": "sha512-b5mz7av0Lhavs1Bz3Zb+jrs0Pki93+8XNctnVO0drBW98x1fM4AR38cWvGbM/w9F9Q0/WEH3TinkmrMPrP4T/w==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/credential-provider-env": "3.812.0",
|
||||
"@aws-sdk/credential-provider-http": "3.812.0",
|
||||
"@aws-sdk/credential-provider-ini": "3.812.0",
|
||||
"@aws-sdk/credential-provider-process": "3.812.0",
|
||||
"@aws-sdk/credential-provider-sso": "3.812.0",
|
||||
"@aws-sdk/credential-provider-web-identity": "3.812.0",
|
||||
"@aws-sdk/credential-provider-env": "3.816.0",
|
||||
"@aws-sdk/credential-provider-http": "3.816.0",
|
||||
"@aws-sdk/credential-provider-ini": "3.817.0",
|
||||
"@aws-sdk/credential-provider-process": "3.816.0",
|
||||
"@aws-sdk/credential-provider-sso": "3.817.0",
|
||||
"@aws-sdk/credential-provider-web-identity": "3.817.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/credential-provider-imds": "^4.0.4",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
|
|
@ -467,11 +467,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/credential-provider-process": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.812.0.tgz",
|
||||
"integrity": "sha512-YI8bb153XeEOb59F9KtTZEwDAc14s2YHZz58+OFiJ2udnKsPV87mNiFhJPW6ba9nmOLXVat5XDcwtVT1b664wg==",
|
||||
"version": "3.816.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.816.0.tgz",
|
||||
"integrity": "sha512-9Tm+AxMoV2Izvl5b9tyMQRbBwaex8JP06HN7ZeCXgC5sAsSN+o8dsThnEhf8jKN+uBpT6CLWKN1TXuUMrAmW1A==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
"@smithy/shared-ini-file-loader": "^4.0.2",
|
||||
|
|
@ -483,13 +483,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/credential-provider-sso": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.812.0.tgz",
|
||||
"integrity": "sha512-ODsPcNhgiO6GOa82TVNskM97mml9rioe9Cbhemz48lkfDQPv1u06NaCR0o3FsvprX1sEhMvJTR3sE1fyEOzvJQ==",
|
||||
"version": "3.817.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.817.0.tgz",
|
||||
"integrity": "sha512-gFUAW3VmGvdnueK1bh6TOcRX+j99Xm0men1+gz3cA4RE+rZGNy1Qjj8YHlv0hPwI9OnTPZquvPzA5fkviGREWg==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-sso": "3.812.0",
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/token-providers": "3.812.0",
|
||||
"@aws-sdk/client-sso": "3.817.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/token-providers": "3.817.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
"@smithy/shared-ini-file-loader": "^4.0.2",
|
||||
|
|
@ -501,12 +501,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/credential-provider-web-identity": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.812.0.tgz",
|
||||
"integrity": "sha512-E9Bmiujvm/Hp9DM/Vc1S+D0pQbx8/x4dR/zyAEZU9EoRq0duQOQ1reWYWbebYmL1OklcVpTfKV0a/VCwuAtGSg==",
|
||||
"version": "3.817.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.817.0.tgz",
|
||||
"integrity": "sha512-A2kgkS9g6NY0OMT2f2EdXHpL17Ym81NhbGnQ8bRXPqESIi7TFypFD2U6osB2VnsFv+MhwM+Ke4PKXSmLun22/A==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/nested-clients": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/nested-clients": "3.817.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
"@smithy/types": "^4.2.0",
|
||||
|
|
@ -558,11 +558,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/middleware-user-agent": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.812.0.tgz",
|
||||
"integrity": "sha512-r+HFwtSvnAs6Fydp4mijylrTX0og9p/xfxOcKsqhMuk3HpZAIcf9sSjRQI6MBusYklg7pnM4sGEnPAZIrdRotA==",
|
||||
"version": "3.816.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.816.0.tgz",
|
||||
"integrity": "sha512-bHRSlWZ0xDsFR8E2FwDb//0Ff6wMkVx4O+UKsfyNlAbtqCiiHRt5ANNfKPafr95cN2CCxLxiPvFTFVblQM5TsQ==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@aws-sdk/util-endpoints": "3.808.0",
|
||||
"@smithy/core": "^3.3.3",
|
||||
|
|
@ -591,11 +591,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/token-providers": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.812.0.tgz",
|
||||
"integrity": "sha512-dbVBaKxrxE708ub5uH3w+cmKIeRQas+2Xf6rpckhohYY+IiflGOdK6aLrp3T6dOQgr/FJ37iQtcYNonAG+yVBQ==",
|
||||
"version": "3.817.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.817.0.tgz",
|
||||
"integrity": "sha512-CYN4/UO0VaqyHf46ogZzNrVX7jI3/CfiuktwKlwtpKA6hjf2+ivfgHSKzPpgPBcSEfiibA/26EeLuMnB6cpSrQ==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/nested-clients": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/nested-clients": "3.817.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
"@smithy/shared-ini-file-loader": "^4.0.2",
|
||||
|
|
@ -644,11 +645,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/util-user-agent-node": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.812.0.tgz",
|
||||
"integrity": "sha512-8pt+OkHhS2U0LDwnzwRnFxyKn8sjSe752OIZQCNv263odud8jQu9pYO2pKqb2kRBk9h9szynjZBDLXfnvSQ7Bg==",
|
||||
"version": "3.816.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.816.0.tgz",
|
||||
"integrity": "sha512-Q6dxmuj4hL7pudhrneWEQ7yVHIQRBFr0wqKLF1opwOi1cIePuoEbPyJ2jkel6PDEv1YMfvsAKaRshp6eNA8VHg==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/middleware-user-agent": "3.812.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.816.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/node-config-provider": "^4.1.1",
|
||||
"@smithy/types": "^4.2.0",
|
||||
|
|
@ -2818,23 +2819,23 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-sagemaker": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sagemaker/-/client-sagemaker-3.812.0.tgz",
|
||||
"integrity": "sha512-KX+/Iu8Cde32low/0c+MGx03CShRJ9PB57qJtPtG6qgz0PeZc8e+t6lBjyZt33iUKZ25/Mt9277tXaSmxGpktw==",
|
||||
"version": "3.817.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sagemaker/-/client-sagemaker-3.817.0.tgz",
|
||||
"integrity": "sha512-ziLmZu31SLUfBU+L43mTKJbxO7GyezHvAFVrk0GIZslHNBBwIsImv5j1aAqkOlvn36twH2n5CXJZPrEt0nH0+A==",
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha256-browser": "5.2.0",
|
||||
"@aws-crypto/sha256-js": "5.2.0",
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/credential-provider-node": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/credential-provider-node": "3.817.0",
|
||||
"@aws-sdk/middleware-host-header": "3.804.0",
|
||||
"@aws-sdk/middleware-logger": "3.804.0",
|
||||
"@aws-sdk/middleware-recursion-detection": "3.804.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.812.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.816.0",
|
||||
"@aws-sdk/region-config-resolver": "3.808.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@aws-sdk/util-endpoints": "3.808.0",
|
||||
"@aws-sdk/util-user-agent-browser": "3.804.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.812.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.816.0",
|
||||
"@smithy/config-resolver": "^4.1.2",
|
||||
"@smithy/core": "^3.3.3",
|
||||
"@smithy/fetch-http-handler": "^5.0.2",
|
||||
|
|
@ -2939,22 +2940,22 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-sagemaker/node_modules/@aws-sdk/client-sso": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.812.0.tgz",
|
||||
"integrity": "sha512-O//smQRj1+RXELB7xX54s5pZB0V69KHXpUZmz8V+8GAYO1FKTHfbpUgK+zyMNb+lFZxG9B69yl8pWPZ/K8bvxA==",
|
||||
"version": "3.817.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.817.0.tgz",
|
||||
"integrity": "sha512-fCh5rUHmWmWDvw70NNoWpE5+BRdtNi45kDnIoeoszqVg7UKF79SlG+qYooUT52HKCgDNHqgbWaXxMOSqd2I/OQ==",
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha256-browser": "5.2.0",
|
||||
"@aws-crypto/sha256-js": "5.2.0",
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/middleware-host-header": "3.804.0",
|
||||
"@aws-sdk/middleware-logger": "3.804.0",
|
||||
"@aws-sdk/middleware-recursion-detection": "3.804.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.812.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.816.0",
|
||||
"@aws-sdk/region-config-resolver": "3.808.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@aws-sdk/util-endpoints": "3.808.0",
|
||||
"@aws-sdk/util-user-agent-browser": "3.804.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.812.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.816.0",
|
||||
"@smithy/config-resolver": "^4.1.2",
|
||||
"@smithy/core": "^3.3.3",
|
||||
"@smithy/fetch-http-handler": "^5.0.2",
|
||||
|
|
@ -2987,9 +2988,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-sagemaker/node_modules/@aws-sdk/core": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.812.0.tgz",
|
||||
"integrity": "sha512-myWA9oHMBVDObKrxG+puAkIGs8igcWInQ1PWCRTS/zN4BkhUMFjjh/JPV/4Vzvtvj5E36iujq2WtlrDLl1PpOw==",
|
||||
"version": "3.816.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.816.0.tgz",
|
||||
"integrity": "sha512-Lx50wjtyarzKpMFV6V+gjbSZDgsA/71iyifbClGUSiNPoIQ4OCV0KVOmAAj7mQRVvGJqUMWKVM+WzK79CjbjWA==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/core": "^3.3.3",
|
||||
|
|
@ -3008,11 +3009,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-sagemaker/node_modules/@aws-sdk/credential-provider-env": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.812.0.tgz",
|
||||
"integrity": "sha512-Ge7IEu06ANurGBZx39q9CNN/ncqb1K8lpKZCY969uNWO0/7YPhnplrRJGMZYIS35nD2mBm3ortEKjY/wMZZd5g==",
|
||||
"version": "3.816.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.816.0.tgz",
|
||||
"integrity": "sha512-wUJZwRLe+SxPxRV9AENYBLrJZRrNIo+fva7ZzejsC83iz7hdfq6Rv6B/aHEdPwG/nQC4+q7UUvcRPlomyrpsBA==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
"@smithy/types": "^4.2.0",
|
||||
|
|
@ -3023,11 +3024,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-sagemaker/node_modules/@aws-sdk/credential-provider-http": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.812.0.tgz",
|
||||
"integrity": "sha512-Vux2U42vPGXeE407Lp6v3yVA65J7hBO9rB67LXshyGVi7VZLAYWc4mrZxNJNqabEkjcDEmMQQakLPT6zc5SvFw==",
|
||||
"version": "3.816.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.816.0.tgz",
|
||||
"integrity": "sha512-gcWGzMQ7yRIF+ljTkR8Vzp7727UY6cmeaPrFQrvcFB8PhOqWpf7g0JsgOf5BSaP8CkkSQcTQHc0C5ZYAzUFwPg==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/fetch-http-handler": "^5.0.2",
|
||||
"@smithy/node-http-handler": "^4.0.4",
|
||||
|
|
@ -3043,17 +3044,17 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-sagemaker/node_modules/@aws-sdk/credential-provider-ini": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.812.0.tgz",
|
||||
"integrity": "sha512-oltqGvQ488xtPY5wrNjbD+qQYYkuCjn30IDE1qKMxJ58EM6UVTQl3XV44Xq07xfF5gKwVJQkfIyOkRAguOVybg==",
|
||||
"version": "3.817.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.817.0.tgz",
|
||||
"integrity": "sha512-kyEwbQyuXE+phWVzloMdkFv6qM6NOon+asMXY5W0fhDKwBz9zQLObDRWBrvQX9lmqq8BbDL1sCfZjOh82Y+RFw==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/credential-provider-env": "3.812.0",
|
||||
"@aws-sdk/credential-provider-http": "3.812.0",
|
||||
"@aws-sdk/credential-provider-process": "3.812.0",
|
||||
"@aws-sdk/credential-provider-sso": "3.812.0",
|
||||
"@aws-sdk/credential-provider-web-identity": "3.812.0",
|
||||
"@aws-sdk/nested-clients": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/credential-provider-env": "3.816.0",
|
||||
"@aws-sdk/credential-provider-http": "3.816.0",
|
||||
"@aws-sdk/credential-provider-process": "3.816.0",
|
||||
"@aws-sdk/credential-provider-sso": "3.817.0",
|
||||
"@aws-sdk/credential-provider-web-identity": "3.817.0",
|
||||
"@aws-sdk/nested-clients": "3.817.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/credential-provider-imds": "^4.0.4",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
|
|
@ -3066,16 +3067,16 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-sagemaker/node_modules/@aws-sdk/credential-provider-node": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.812.0.tgz",
|
||||
"integrity": "sha512-SnvSWBP6cr9nqx784eETnL2Zl7ZnMB/oJgFVEG1aejAGbT1H9gTpMwuUsBXk4u/mEYe3f1lh1Wqo+HwDgNkfrg==",
|
||||
"version": "3.817.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.817.0.tgz",
|
||||
"integrity": "sha512-b5mz7av0Lhavs1Bz3Zb+jrs0Pki93+8XNctnVO0drBW98x1fM4AR38cWvGbM/w9F9Q0/WEH3TinkmrMPrP4T/w==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/credential-provider-env": "3.812.0",
|
||||
"@aws-sdk/credential-provider-http": "3.812.0",
|
||||
"@aws-sdk/credential-provider-ini": "3.812.0",
|
||||
"@aws-sdk/credential-provider-process": "3.812.0",
|
||||
"@aws-sdk/credential-provider-sso": "3.812.0",
|
||||
"@aws-sdk/credential-provider-web-identity": "3.812.0",
|
||||
"@aws-sdk/credential-provider-env": "3.816.0",
|
||||
"@aws-sdk/credential-provider-http": "3.816.0",
|
||||
"@aws-sdk/credential-provider-ini": "3.817.0",
|
||||
"@aws-sdk/credential-provider-process": "3.816.0",
|
||||
"@aws-sdk/credential-provider-sso": "3.817.0",
|
||||
"@aws-sdk/credential-provider-web-identity": "3.817.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/credential-provider-imds": "^4.0.4",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
|
|
@ -3088,11 +3089,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-sagemaker/node_modules/@aws-sdk/credential-provider-process": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.812.0.tgz",
|
||||
"integrity": "sha512-YI8bb153XeEOb59F9KtTZEwDAc14s2YHZz58+OFiJ2udnKsPV87mNiFhJPW6ba9nmOLXVat5XDcwtVT1b664wg==",
|
||||
"version": "3.816.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.816.0.tgz",
|
||||
"integrity": "sha512-9Tm+AxMoV2Izvl5b9tyMQRbBwaex8JP06HN7ZeCXgC5sAsSN+o8dsThnEhf8jKN+uBpT6CLWKN1TXuUMrAmW1A==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
"@smithy/shared-ini-file-loader": "^4.0.2",
|
||||
|
|
@ -3104,13 +3105,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-sagemaker/node_modules/@aws-sdk/credential-provider-sso": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.812.0.tgz",
|
||||
"integrity": "sha512-ODsPcNhgiO6GOa82TVNskM97mml9rioe9Cbhemz48lkfDQPv1u06NaCR0o3FsvprX1sEhMvJTR3sE1fyEOzvJQ==",
|
||||
"version": "3.817.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.817.0.tgz",
|
||||
"integrity": "sha512-gFUAW3VmGvdnueK1bh6TOcRX+j99Xm0men1+gz3cA4RE+rZGNy1Qjj8YHlv0hPwI9OnTPZquvPzA5fkviGREWg==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-sso": "3.812.0",
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/token-providers": "3.812.0",
|
||||
"@aws-sdk/client-sso": "3.817.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/token-providers": "3.817.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
"@smithy/shared-ini-file-loader": "^4.0.2",
|
||||
|
|
@ -3122,12 +3123,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-sagemaker/node_modules/@aws-sdk/credential-provider-web-identity": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.812.0.tgz",
|
||||
"integrity": "sha512-E9Bmiujvm/Hp9DM/Vc1S+D0pQbx8/x4dR/zyAEZU9EoRq0duQOQ1reWYWbebYmL1OklcVpTfKV0a/VCwuAtGSg==",
|
||||
"version": "3.817.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.817.0.tgz",
|
||||
"integrity": "sha512-A2kgkS9g6NY0OMT2f2EdXHpL17Ym81NhbGnQ8bRXPqESIi7TFypFD2U6osB2VnsFv+MhwM+Ke4PKXSmLun22/A==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/nested-clients": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/nested-clients": "3.817.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
"@smithy/types": "^4.2.0",
|
||||
|
|
@ -3179,11 +3180,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-sagemaker/node_modules/@aws-sdk/middleware-user-agent": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.812.0.tgz",
|
||||
"integrity": "sha512-r+HFwtSvnAs6Fydp4mijylrTX0og9p/xfxOcKsqhMuk3HpZAIcf9sSjRQI6MBusYklg7pnM4sGEnPAZIrdRotA==",
|
||||
"version": "3.816.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.816.0.tgz",
|
||||
"integrity": "sha512-bHRSlWZ0xDsFR8E2FwDb//0Ff6wMkVx4O+UKsfyNlAbtqCiiHRt5ANNfKPafr95cN2CCxLxiPvFTFVblQM5TsQ==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@aws-sdk/util-endpoints": "3.808.0",
|
||||
"@smithy/core": "^3.3.3",
|
||||
|
|
@ -3212,11 +3213,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-sagemaker/node_modules/@aws-sdk/token-providers": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.812.0.tgz",
|
||||
"integrity": "sha512-dbVBaKxrxE708ub5uH3w+cmKIeRQas+2Xf6rpckhohYY+IiflGOdK6aLrp3T6dOQgr/FJ37iQtcYNonAG+yVBQ==",
|
||||
"version": "3.817.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.817.0.tgz",
|
||||
"integrity": "sha512-CYN4/UO0VaqyHf46ogZzNrVX7jI3/CfiuktwKlwtpKA6hjf2+ivfgHSKzPpgPBcSEfiibA/26EeLuMnB6cpSrQ==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/nested-clients": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/nested-clients": "3.817.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
"@smithy/shared-ini-file-loader": "^4.0.2",
|
||||
|
|
@ -3265,11 +3267,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-sagemaker/node_modules/@aws-sdk/util-user-agent-node": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.812.0.tgz",
|
||||
"integrity": "sha512-8pt+OkHhS2U0LDwnzwRnFxyKn8sjSe752OIZQCNv263odud8jQu9pYO2pKqb2kRBk9h9szynjZBDLXfnvSQ7Bg==",
|
||||
"version": "3.816.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.816.0.tgz",
|
||||
"integrity": "sha512-Q6dxmuj4hL7pudhrneWEQ7yVHIQRBFr0wqKLF1opwOi1cIePuoEbPyJ2jkel6PDEv1YMfvsAKaRshp6eNA8VHg==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/middleware-user-agent": "3.812.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.816.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/node-config-provider": "^4.1.1",
|
||||
"@smithy/types": "^4.2.0",
|
||||
|
|
@ -5245,11 +5247,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-provider-cognito-identity": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.812.0.tgz",
|
||||
"integrity": "sha512-SrEGXP1zs2Cy3jjOwM8eh+UZkr28z7rvjF+cgV4bpOti5F/mzPyVoIxDkG8BQ2sZdAwa9rgEhhOl4CcKjoJoTA==",
|
||||
"version": "3.817.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.817.0.tgz",
|
||||
"integrity": "sha512-+dzgWGmdmMNDdeSF+VvONN+hwqoGKX5A6Z3+siMO4CIoKWN7u5nDOx/JLjTGdVQji3522pJjJ+o9veQJNWOMRg==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-cognito-identity": "3.812.0",
|
||||
"@aws-sdk/client-cognito-identity": "3.817.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
"@smithy/types": "^4.2.0",
|
||||
|
|
@ -5427,21 +5429,21 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-providers": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.812.0.tgz",
|
||||
"integrity": "sha512-hT7Kr8Ao+NS9b8KCB/U8cmpr0DcWOZNZNRBGAOc4eq65JpsRv177QmSqjh75vhM9BzchH3VymcP4GeMoy4SuvA==",
|
||||
"version": "3.817.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.817.0.tgz",
|
||||
"integrity": "sha512-i6Q2MyktWHG4YG+EmLlnXTgNVjW9/yeNHSKzF55GTho5fjqfU+t9beJfuMWclanRCifamm3N5e5OCm52rVDdTQ==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-cognito-identity": "3.812.0",
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/credential-provider-cognito-identity": "3.812.0",
|
||||
"@aws-sdk/credential-provider-env": "3.812.0",
|
||||
"@aws-sdk/credential-provider-http": "3.812.0",
|
||||
"@aws-sdk/credential-provider-ini": "3.812.0",
|
||||
"@aws-sdk/credential-provider-node": "3.812.0",
|
||||
"@aws-sdk/credential-provider-process": "3.812.0",
|
||||
"@aws-sdk/credential-provider-sso": "3.812.0",
|
||||
"@aws-sdk/credential-provider-web-identity": "3.812.0",
|
||||
"@aws-sdk/nested-clients": "3.812.0",
|
||||
"@aws-sdk/client-cognito-identity": "3.817.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/credential-provider-cognito-identity": "3.817.0",
|
||||
"@aws-sdk/credential-provider-env": "3.816.0",
|
||||
"@aws-sdk/credential-provider-http": "3.816.0",
|
||||
"@aws-sdk/credential-provider-ini": "3.817.0",
|
||||
"@aws-sdk/credential-provider-node": "3.817.0",
|
||||
"@aws-sdk/credential-provider-process": "3.816.0",
|
||||
"@aws-sdk/credential-provider-sso": "3.817.0",
|
||||
"@aws-sdk/credential-provider-web-identity": "3.817.0",
|
||||
"@aws-sdk/nested-clients": "3.817.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/config-resolver": "^4.1.2",
|
||||
"@smithy/core": "^3.3.3",
|
||||
|
|
@ -5501,22 +5503,22 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/client-sso": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.812.0.tgz",
|
||||
"integrity": "sha512-O//smQRj1+RXELB7xX54s5pZB0V69KHXpUZmz8V+8GAYO1FKTHfbpUgK+zyMNb+lFZxG9B69yl8pWPZ/K8bvxA==",
|
||||
"version": "3.817.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.817.0.tgz",
|
||||
"integrity": "sha512-fCh5rUHmWmWDvw70NNoWpE5+BRdtNi45kDnIoeoszqVg7UKF79SlG+qYooUT52HKCgDNHqgbWaXxMOSqd2I/OQ==",
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha256-browser": "5.2.0",
|
||||
"@aws-crypto/sha256-js": "5.2.0",
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/middleware-host-header": "3.804.0",
|
||||
"@aws-sdk/middleware-logger": "3.804.0",
|
||||
"@aws-sdk/middleware-recursion-detection": "3.804.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.812.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.816.0",
|
||||
"@aws-sdk/region-config-resolver": "3.808.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@aws-sdk/util-endpoints": "3.808.0",
|
||||
"@aws-sdk/util-user-agent-browser": "3.804.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.812.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.816.0",
|
||||
"@smithy/config-resolver": "^4.1.2",
|
||||
"@smithy/core": "^3.3.3",
|
||||
"@smithy/fetch-http-handler": "^5.0.2",
|
||||
|
|
@ -5561,9 +5563,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/core": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.812.0.tgz",
|
||||
"integrity": "sha512-myWA9oHMBVDObKrxG+puAkIGs8igcWInQ1PWCRTS/zN4BkhUMFjjh/JPV/4Vzvtvj5E36iujq2WtlrDLl1PpOw==",
|
||||
"version": "3.816.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.816.0.tgz",
|
||||
"integrity": "sha512-Lx50wjtyarzKpMFV6V+gjbSZDgsA/71iyifbClGUSiNPoIQ4OCV0KVOmAAj7mQRVvGJqUMWKVM+WzK79CjbjWA==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/core": "^3.3.3",
|
||||
|
|
@ -5582,11 +5584,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/credential-provider-env": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.812.0.tgz",
|
||||
"integrity": "sha512-Ge7IEu06ANurGBZx39q9CNN/ncqb1K8lpKZCY969uNWO0/7YPhnplrRJGMZYIS35nD2mBm3ortEKjY/wMZZd5g==",
|
||||
"version": "3.816.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.816.0.tgz",
|
||||
"integrity": "sha512-wUJZwRLe+SxPxRV9AENYBLrJZRrNIo+fva7ZzejsC83iz7hdfq6Rv6B/aHEdPwG/nQC4+q7UUvcRPlomyrpsBA==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
"@smithy/types": "^4.2.0",
|
||||
|
|
@ -5597,11 +5599,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/credential-provider-http": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.812.0.tgz",
|
||||
"integrity": "sha512-Vux2U42vPGXeE407Lp6v3yVA65J7hBO9rB67LXshyGVi7VZLAYWc4mrZxNJNqabEkjcDEmMQQakLPT6zc5SvFw==",
|
||||
"version": "3.816.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.816.0.tgz",
|
||||
"integrity": "sha512-gcWGzMQ7yRIF+ljTkR8Vzp7727UY6cmeaPrFQrvcFB8PhOqWpf7g0JsgOf5BSaP8CkkSQcTQHc0C5ZYAzUFwPg==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/fetch-http-handler": "^5.0.2",
|
||||
"@smithy/node-http-handler": "^4.0.4",
|
||||
|
|
@ -5617,17 +5619,17 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/credential-provider-ini": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.812.0.tgz",
|
||||
"integrity": "sha512-oltqGvQ488xtPY5wrNjbD+qQYYkuCjn30IDE1qKMxJ58EM6UVTQl3XV44Xq07xfF5gKwVJQkfIyOkRAguOVybg==",
|
||||
"version": "3.817.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.817.0.tgz",
|
||||
"integrity": "sha512-kyEwbQyuXE+phWVzloMdkFv6qM6NOon+asMXY5W0fhDKwBz9zQLObDRWBrvQX9lmqq8BbDL1sCfZjOh82Y+RFw==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/credential-provider-env": "3.812.0",
|
||||
"@aws-sdk/credential-provider-http": "3.812.0",
|
||||
"@aws-sdk/credential-provider-process": "3.812.0",
|
||||
"@aws-sdk/credential-provider-sso": "3.812.0",
|
||||
"@aws-sdk/credential-provider-web-identity": "3.812.0",
|
||||
"@aws-sdk/nested-clients": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/credential-provider-env": "3.816.0",
|
||||
"@aws-sdk/credential-provider-http": "3.816.0",
|
||||
"@aws-sdk/credential-provider-process": "3.816.0",
|
||||
"@aws-sdk/credential-provider-sso": "3.817.0",
|
||||
"@aws-sdk/credential-provider-web-identity": "3.817.0",
|
||||
"@aws-sdk/nested-clients": "3.817.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/credential-provider-imds": "^4.0.4",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
|
|
@ -5640,16 +5642,16 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/credential-provider-node": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.812.0.tgz",
|
||||
"integrity": "sha512-SnvSWBP6cr9nqx784eETnL2Zl7ZnMB/oJgFVEG1aejAGbT1H9gTpMwuUsBXk4u/mEYe3f1lh1Wqo+HwDgNkfrg==",
|
||||
"version": "3.817.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.817.0.tgz",
|
||||
"integrity": "sha512-b5mz7av0Lhavs1Bz3Zb+jrs0Pki93+8XNctnVO0drBW98x1fM4AR38cWvGbM/w9F9Q0/WEH3TinkmrMPrP4T/w==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/credential-provider-env": "3.812.0",
|
||||
"@aws-sdk/credential-provider-http": "3.812.0",
|
||||
"@aws-sdk/credential-provider-ini": "3.812.0",
|
||||
"@aws-sdk/credential-provider-process": "3.812.0",
|
||||
"@aws-sdk/credential-provider-sso": "3.812.0",
|
||||
"@aws-sdk/credential-provider-web-identity": "3.812.0",
|
||||
"@aws-sdk/credential-provider-env": "3.816.0",
|
||||
"@aws-sdk/credential-provider-http": "3.816.0",
|
||||
"@aws-sdk/credential-provider-ini": "3.817.0",
|
||||
"@aws-sdk/credential-provider-process": "3.816.0",
|
||||
"@aws-sdk/credential-provider-sso": "3.817.0",
|
||||
"@aws-sdk/credential-provider-web-identity": "3.817.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/credential-provider-imds": "^4.0.4",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
|
|
@ -5662,11 +5664,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/credential-provider-process": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.812.0.tgz",
|
||||
"integrity": "sha512-YI8bb153XeEOb59F9KtTZEwDAc14s2YHZz58+OFiJ2udnKsPV87mNiFhJPW6ba9nmOLXVat5XDcwtVT1b664wg==",
|
||||
"version": "3.816.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.816.0.tgz",
|
||||
"integrity": "sha512-9Tm+AxMoV2Izvl5b9tyMQRbBwaex8JP06HN7ZeCXgC5sAsSN+o8dsThnEhf8jKN+uBpT6CLWKN1TXuUMrAmW1A==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
"@smithy/shared-ini-file-loader": "^4.0.2",
|
||||
|
|
@ -5678,13 +5680,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/credential-provider-sso": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.812.0.tgz",
|
||||
"integrity": "sha512-ODsPcNhgiO6GOa82TVNskM97mml9rioe9Cbhemz48lkfDQPv1u06NaCR0o3FsvprX1sEhMvJTR3sE1fyEOzvJQ==",
|
||||
"version": "3.817.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.817.0.tgz",
|
||||
"integrity": "sha512-gFUAW3VmGvdnueK1bh6TOcRX+j99Xm0men1+gz3cA4RE+rZGNy1Qjj8YHlv0hPwI9OnTPZquvPzA5fkviGREWg==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-sso": "3.812.0",
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/token-providers": "3.812.0",
|
||||
"@aws-sdk/client-sso": "3.817.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/token-providers": "3.817.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
"@smithy/shared-ini-file-loader": "^4.0.2",
|
||||
|
|
@ -5696,12 +5698,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/credential-provider-web-identity": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.812.0.tgz",
|
||||
"integrity": "sha512-E9Bmiujvm/Hp9DM/Vc1S+D0pQbx8/x4dR/zyAEZU9EoRq0duQOQ1reWYWbebYmL1OklcVpTfKV0a/VCwuAtGSg==",
|
||||
"version": "3.817.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.817.0.tgz",
|
||||
"integrity": "sha512-A2kgkS9g6NY0OMT2f2EdXHpL17Ym81NhbGnQ8bRXPqESIi7TFypFD2U6osB2VnsFv+MhwM+Ke4PKXSmLun22/A==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/nested-clients": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/nested-clients": "3.817.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
"@smithy/types": "^4.2.0",
|
||||
|
|
@ -5753,11 +5755,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/middleware-user-agent": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.812.0.tgz",
|
||||
"integrity": "sha512-r+HFwtSvnAs6Fydp4mijylrTX0og9p/xfxOcKsqhMuk3HpZAIcf9sSjRQI6MBusYklg7pnM4sGEnPAZIrdRotA==",
|
||||
"version": "3.816.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.816.0.tgz",
|
||||
"integrity": "sha512-bHRSlWZ0xDsFR8E2FwDb//0Ff6wMkVx4O+UKsfyNlAbtqCiiHRt5ANNfKPafr95cN2CCxLxiPvFTFVblQM5TsQ==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@aws-sdk/util-endpoints": "3.808.0",
|
||||
"@smithy/core": "^3.3.3",
|
||||
|
|
@ -5786,11 +5788,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/token-providers": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.812.0.tgz",
|
||||
"integrity": "sha512-dbVBaKxrxE708ub5uH3w+cmKIeRQas+2Xf6rpckhohYY+IiflGOdK6aLrp3T6dOQgr/FJ37iQtcYNonAG+yVBQ==",
|
||||
"version": "3.817.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.817.0.tgz",
|
||||
"integrity": "sha512-CYN4/UO0VaqyHf46ogZzNrVX7jI3/CfiuktwKlwtpKA6hjf2+ivfgHSKzPpgPBcSEfiibA/26EeLuMnB6cpSrQ==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/nested-clients": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/nested-clients": "3.817.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
"@smithy/shared-ini-file-loader": "^4.0.2",
|
||||
|
|
@ -5839,11 +5842,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/util-user-agent-node": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.812.0.tgz",
|
||||
"integrity": "sha512-8pt+OkHhS2U0LDwnzwRnFxyKn8sjSe752OIZQCNv263odud8jQu9pYO2pKqb2kRBk9h9szynjZBDLXfnvSQ7Bg==",
|
||||
"version": "3.816.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.816.0.tgz",
|
||||
"integrity": "sha512-Q6dxmuj4hL7pudhrneWEQ7yVHIQRBFr0wqKLF1opwOi1cIePuoEbPyJ2jkel6PDEv1YMfvsAKaRshp6eNA8VHg==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/middleware-user-agent": "3.812.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.816.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/node-config-provider": "^4.1.1",
|
||||
"@smithy/types": "^4.2.0",
|
||||
|
|
@ -6827,22 +6830,22 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/nested-clients": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.812.0.tgz",
|
||||
"integrity": "sha512-FS/fImbEpJU3cXtBGR9fyVd+CP51eNKlvTMi3f4/6lSk3RmHjudNC9yEF/og3jtpT3O+7vsNOUW9mHco5IjdQQ==",
|
||||
"version": "3.817.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.817.0.tgz",
|
||||
"integrity": "sha512-vQ2E06A48STJFssueJQgxYD8lh1iGJoLJnHdshRDWOQb8gy1wVQR+a7MkPGhGR6lGoS0SCnF/Qp6CZhnwLsqsQ==",
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha256-browser": "5.2.0",
|
||||
"@aws-crypto/sha256-js": "5.2.0",
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/middleware-host-header": "3.804.0",
|
||||
"@aws-sdk/middleware-logger": "3.804.0",
|
||||
"@aws-sdk/middleware-recursion-detection": "3.804.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.812.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.816.0",
|
||||
"@aws-sdk/region-config-resolver": "3.808.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@aws-sdk/util-endpoints": "3.808.0",
|
||||
"@aws-sdk/util-user-agent-browser": "3.804.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.812.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.816.0",
|
||||
"@smithy/config-resolver": "^4.1.2",
|
||||
"@smithy/core": "^3.3.3",
|
||||
"@smithy/fetch-http-handler": "^5.0.2",
|
||||
|
|
@ -6944,9 +6947,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/core": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.812.0.tgz",
|
||||
"integrity": "sha512-myWA9oHMBVDObKrxG+puAkIGs8igcWInQ1PWCRTS/zN4BkhUMFjjh/JPV/4Vzvtvj5E36iujq2WtlrDLl1PpOw==",
|
||||
"version": "3.816.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.816.0.tgz",
|
||||
"integrity": "sha512-Lx50wjtyarzKpMFV6V+gjbSZDgsA/71iyifbClGUSiNPoIQ4OCV0KVOmAAj7mQRVvGJqUMWKVM+WzK79CjbjWA==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/core": "^3.3.3",
|
||||
|
|
@ -7006,11 +7009,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/middleware-user-agent": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.812.0.tgz",
|
||||
"integrity": "sha512-r+HFwtSvnAs6Fydp4mijylrTX0og9p/xfxOcKsqhMuk3HpZAIcf9sSjRQI6MBusYklg7pnM4sGEnPAZIrdRotA==",
|
||||
"version": "3.816.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.816.0.tgz",
|
||||
"integrity": "sha512-bHRSlWZ0xDsFR8E2FwDb//0Ff6wMkVx4O+UKsfyNlAbtqCiiHRt5ANNfKPafr95cN2CCxLxiPvFTFVblQM5TsQ==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "3.812.0",
|
||||
"@aws-sdk/core": "3.816.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@aws-sdk/util-endpoints": "3.808.0",
|
||||
"@smithy/core": "^3.3.3",
|
||||
|
|
@ -7076,11 +7079,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/util-user-agent-node": {
|
||||
"version": "3.812.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.812.0.tgz",
|
||||
"integrity": "sha512-8pt+OkHhS2U0LDwnzwRnFxyKn8sjSe752OIZQCNv263odud8jQu9pYO2pKqb2kRBk9h9szynjZBDLXfnvSQ7Bg==",
|
||||
"version": "3.816.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.816.0.tgz",
|
||||
"integrity": "sha512-Q6dxmuj4hL7pudhrneWEQ7yVHIQRBFr0wqKLF1opwOi1cIePuoEbPyJ2jkel6PDEv1YMfvsAKaRshp6eNA8VHg==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/middleware-user-agent": "3.812.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.816.0",
|
||||
"@aws-sdk/types": "3.804.0",
|
||||
"@smithy/node-config-provider": "^4.1.1",
|
||||
"@smithy/types": "^4.2.0",
|
||||
|
|
@ -8992,14 +8995,6 @@
|
|||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@fastify/busboy": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz",
|
||||
"integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@gar/promisify": {
|
||||
"version": "1.1.3",
|
||||
"dev": true,
|
||||
|
|
@ -10075,9 +10070,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@mistralai/mistralai": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@mistralai/mistralai/-/mistralai-1.6.0.tgz",
|
||||
"integrity": "sha512-PQwGV3+n7FbE7Dp3Vnd8DAa3ffx6WuVV966Gfmf4QvzwcO3Mvxpz0SnJ/PjaZcsCwApBCZpNyQzvarAKEQLKeQ==",
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@mistralai/mistralai/-/mistralai-1.7.0.tgz",
|
||||
"integrity": "sha512-yM12kf1mGxSBCZWVvSA8gMvLG1lZ+MilvHUJskU4QWVWc+uYOgupZPRgDarPerzEp6/jm9XDR/rCO7U3ElNAOg==",
|
||||
"dependencies": {
|
||||
"zod-to-json-schema": "^3.24.1"
|
||||
},
|
||||
|
|
@ -11639,16 +11634,16 @@
|
|||
"integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="
|
||||
},
|
||||
"node_modules/@qdrant/js-client-rest": {
|
||||
"version": "1.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@qdrant/js-client-rest/-/js-client-rest-1.14.0.tgz",
|
||||
"integrity": "sha512-2sM2g17FSkN2sNCSeAfqxHRr+SPEVnUQLXBjVv/whm4YQ4JjZ53Jiy1iShk95G+xBf3hKBhJdj8itRnor03IYw==",
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@qdrant/js-client-rest/-/js-client-rest-1.14.1.tgz",
|
||||
"integrity": "sha512-CkCCTDc4gCXq+hhjB3yDw9Hs/PxCJ0bKqk/LjAAmuL9+nDm/RPue4C/tGOIMlzouTQ2l6J6t+JPeM//j38VFug==",
|
||||
"dependencies": {
|
||||
"@qdrant/openapi-typescript-fetch": "1.2.6",
|
||||
"@sevinf/maybe": "0.5.0",
|
||||
"undici": "~5.28.5"
|
||||
"undici": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0",
|
||||
"node": ">=18.17.0",
|
||||
"pnpm": ">=8"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
|
@ -12565,6 +12560,10 @@
|
|||
"resolved": "plugins/azurerepos",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@tooljet-marketplace/clickup": {
|
||||
"resolved": "plugins/clickup",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@tooljet-marketplace/cohere": {
|
||||
"resolved": "plugins/cohere",
|
||||
"link": true
|
||||
|
|
@ -23425,14 +23424,11 @@
|
|||
"integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g=="
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "5.28.5",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz",
|
||||
"integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==",
|
||||
"dependencies": {
|
||||
"@fastify/busboy": "^2.0.0"
|
||||
},
|
||||
"version": "6.21.3",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz",
|
||||
"integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==",
|
||||
"engines": {
|
||||
"node": ">=14.0"
|
||||
"node": ">=18.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
|
|
@ -23970,9 +23966,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/zod": {
|
||||
"version": "3.25.13",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.13.tgz",
|
||||
"integrity": "sha512-Q8mvk2iWi7rTDfpQBsu4ziE7A6AxgzJ5hzRyRYQkoV3A3niYsXVwDaP1Kbz3nWav6S+VZ6k2OznFn8ZyDHvIrg==",
|
||||
"version": "3.25.30",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.30.tgz",
|
||||
"integrity": "sha512-VolhdEtu6TJr/fzGuHA/SZ5ixvXqA6ADOG9VRcQ3rdOKmF5hkmcJbyaQjUH5BgmpA9gej++zYRX7zjSmdReIwA==",
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
|
|
@ -23987,7 +23983,6 @@
|
|||
}
|
||||
},
|
||||
"plugins/anthropic": {
|
||||
"name": "@tooljet-marketplace/anthropic",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@anthropic-ai/sdk": "^0.32.1",
|
||||
|
|
@ -24022,7 +24017,6 @@
|
|||
}
|
||||
},
|
||||
"plugins/azurerepos": {
|
||||
"name": "@tooljet-marketplace/azurerepos",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@tooljet-marketplace/common": "^1.0.0",
|
||||
|
|
@ -24033,8 +24027,17 @@
|
|||
"typescript": "^4.7.4"
|
||||
}
|
||||
},
|
||||
"plugins/clickup": {
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@tooljet-marketplace/common": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vercel/ncc": "^0.34.0",
|
||||
"typescript": "^4.7.4"
|
||||
}
|
||||
},
|
||||
"plugins/cohere": {
|
||||
"name": "@tooljet-marketplace/cohere",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@tooljet-marketplace/common": "^1.0.0",
|
||||
|
|
@ -24065,7 +24068,6 @@
|
|||
}
|
||||
},
|
||||
"plugins/gemini": {
|
||||
"name": "@tooljet-marketplace/gemini",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@google/generative-ai": "^0.21.0",
|
||||
|
|
@ -24101,7 +24103,6 @@
|
|||
}
|
||||
},
|
||||
"plugins/hugging_face": {
|
||||
"name": "@tooljet-marketplace/huggingface",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@tooljet-marketplace/common": "^1.0.0"
|
||||
|
|
@ -24121,7 +24122,6 @@
|
|||
}
|
||||
},
|
||||
"plugins/mistral_ai": {
|
||||
"name": "@tooljet-marketplace/mistral",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@mistralai/mistralai": "^1.4.0",
|
||||
|
|
@ -24206,7 +24206,6 @@
|
|||
}
|
||||
},
|
||||
"plugins/qdrant": {
|
||||
"name": "@tooljet-marketplace/qdrant",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@qdrant/js-client-rest": "^1.12.0",
|
||||
|
|
@ -24287,7 +24286,6 @@
|
|||
}
|
||||
},
|
||||
"plugins/weaviate": {
|
||||
"name": "@tooljet-marketplace/weaviate",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@tooljet-marketplace/common": "^1.0.0",
|
||||
|
|
@ -24299,4 +24297,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
5
marketplace/plugins/clickup/.gitignore
vendored
Normal file
5
marketplace/plugins/clickup/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
node_modules
|
||||
lib/*.d.*
|
||||
lib/*.js
|
||||
lib/*.js.map
|
||||
dist/*
|
||||
4
marketplace/plugins/clickup/README.md
Normal file
4
marketplace/plugins/clickup/README.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
# ClickUp
|
||||
|
||||
Documentation on: https://docs.tooljet.com/docs/data-sources/clickup
|
||||
7
marketplace/plugins/clickup/__tests__/index.js
Normal file
7
marketplace/plugins/clickup/__tests__/index.js
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const clickup = require('../lib');
|
||||
|
||||
describe('clickup', () => {
|
||||
it.todo('needs tests');
|
||||
});
|
||||
19
marketplace/plugins/clickup/lib/icon.svg
Normal file
19
marketplace/plugins/clickup/lib/icon.svg
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_485_45)">
|
||||
<path d="M4 16.5435L6.88198 14.3135C8.41315 16.332 10.0399 17.2624 11.8507 17.2624C13.6518 17.2624 15.2326 16.343 16.6947 14.3403L19.6179 16.5166C17.5081 19.4044 14.8864 20.9302 11.8507 20.9302C8.82468 20.9302 6.17753 19.4142 4 16.5435Z" fill="url(#paint0_linear_485_45)"/>
|
||||
<path d="M11.8415 6.85133L6.71177 11.3163L4.34058 8.53855L11.8524 2.00004L19.3048 8.5434L16.9228 11.3114L11.8415 6.85133Z" fill="url(#paint1_linear_485_45)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_485_45" x1="4" y1="22.1219" x2="19.6179" y2="22.1219" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#7612FA"/>
|
||||
<stop offset="1" stop-color="#40DDFF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_485_45" x1="4.34058" y1="12.9942" x2="19.3048" y2="12.9942" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FA12E3"/>
|
||||
<stop offset="1" stop-color="#FFD700"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_485_45">
|
||||
<rect width="16" height="20" fill="white" transform="translate(4 2)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
114
marketplace/plugins/clickup/lib/index.ts
Normal file
114
marketplace/plugins/clickup/lib/index.ts
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
import { QueryError, QueryResult, QueryService, ConnectionTestResult } from '@tooljet-marketplace/common';
|
||||
import { SourceOptions } from './types';
|
||||
import got, { Headers } from 'got';
|
||||
|
||||
export default class Clickup implements QueryService {
|
||||
authHeader(token: string): Headers {
|
||||
return { Authorization: token };
|
||||
}
|
||||
|
||||
async run(sourceOptions: SourceOptions, queryOptions: any, dataSourceId: string): Promise<QueryResult> {
|
||||
const operation = queryOptions.operation;
|
||||
const apiKey = sourceOptions.apiKey;
|
||||
const baseUrl = 'https://api.clickup.com/api';
|
||||
const path = queryOptions['path'];
|
||||
|
||||
const pathParams = queryOptions['params']['path'];
|
||||
const queryParams = queryOptions['params']['query'];
|
||||
const bodyParams = queryOptions['params']['request'];
|
||||
|
||||
// Replace path params in URL
|
||||
let modifiedPath = path;
|
||||
for (const param of Object.keys(pathParams)) {
|
||||
modifiedPath = modifiedPath.replace(`{${param}}`, pathParams[param]);
|
||||
}
|
||||
|
||||
const url = `${baseUrl}${modifiedPath}`;
|
||||
|
||||
try {
|
||||
let response;
|
||||
|
||||
if (operation === 'get' || operation === 'delete') {
|
||||
response = await got(url, {
|
||||
method: operation,
|
||||
headers: this.authHeader(apiKey),
|
||||
searchParams: queryParams,
|
||||
});
|
||||
} else {
|
||||
// post, put, patch operations
|
||||
const resolvedBodyParams = this.resolveBodyparams(bodyParams);
|
||||
response = await got(url, {
|
||||
method: operation,
|
||||
headers: this.authHeader(apiKey),
|
||||
json: resolvedBodyParams,
|
||||
searchParams: queryParams,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'ok',
|
||||
data: JSON.parse(response.body),
|
||||
};
|
||||
} catch (err) {
|
||||
const errorMessage = err.message || 'An unknown error occurred';
|
||||
const errorDetails: any = {};
|
||||
|
||||
if (err.response) {
|
||||
const { statusCode, body } = err.response;
|
||||
errorDetails.statusCode = statusCode;
|
||||
|
||||
try {
|
||||
const parsedBody = JSON.parse(body);
|
||||
errorDetails.error = parsedBody.err || null;
|
||||
errorDetails.code = parsedBody.ECODE || null;
|
||||
} catch (parseError) {
|
||||
errorDetails.rawBody = body;
|
||||
}
|
||||
}
|
||||
|
||||
throw new QueryError('Query could not be completed', errorMessage, errorDetails);
|
||||
}
|
||||
}
|
||||
|
||||
async testConnection(sourceOptions: SourceOptions): Promise<ConnectionTestResult> {
|
||||
const apiKey = sourceOptions.apiKey;
|
||||
|
||||
try {
|
||||
const response = await got('https://api.clickup.com/api/v2/user', {
|
||||
headers: this.authHeader(apiKey),
|
||||
});
|
||||
|
||||
const data = JSON.parse(response.body);
|
||||
|
||||
if (data?.user?.id) {
|
||||
return {
|
||||
status: 'ok',
|
||||
};
|
||||
} else {
|
||||
throw new QueryError('User information not found', 'Invalid API key or insufficient permissions', {});
|
||||
}
|
||||
} catch (error) {
|
||||
throw new QueryError('Connection could not be established', error.response?.body || error.message, {});
|
||||
}
|
||||
}
|
||||
|
||||
private resolveBodyparams(bodyParams: object): object {
|
||||
if (typeof bodyParams === 'string') {
|
||||
return bodyParams;
|
||||
}
|
||||
|
||||
const expectedResult = {};
|
||||
|
||||
for (const key of Object.keys(bodyParams)) {
|
||||
if (typeof bodyParams[key] === 'object') {
|
||||
for (const subKey of Object.keys(bodyParams[key])) {
|
||||
expectedResult[`${key}[${subKey}]`] = bodyParams[key][subKey];
|
||||
}
|
||||
} else {
|
||||
expectedResult[key] = bodyParams[key];
|
||||
}
|
||||
}
|
||||
|
||||
return expectedResult;
|
||||
}
|
||||
}
|
||||
33
marketplace/plugins/clickup/lib/manifest.json
Normal file
33
marketplace/plugins/clickup/lib/manifest.json
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"$schema": "https://raw.githubusercontent.com/ToolJet/ToolJet/develop/plugins/schemas/manifest.schema.json",
|
||||
"title": "ClickUp datasource",
|
||||
"description": "Clickup plugin for task, list, and doc management",
|
||||
"type": "api",
|
||||
"source": {
|
||||
"name": "ClickUp",
|
||||
"kind": "clickup",
|
||||
"exposedVariables": {
|
||||
"isLoading": false,
|
||||
"data": {},
|
||||
"rawData": {}
|
||||
},
|
||||
"options": {
|
||||
"apiKey": {
|
||||
"type": "string",
|
||||
"encrypted": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaults": {},
|
||||
"properties": {
|
||||
"apiKey": {
|
||||
"label": "API Key",
|
||||
"key": "apiKey",
|
||||
"type": "password",
|
||||
"description": "Enter your Personal API Token"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"apiKey"
|
||||
]
|
||||
}
|
||||
16
marketplace/plugins/clickup/lib/operations.json
Normal file
16
marketplace/plugins/clickup/lib/operations.json
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"$schema": "https://raw.githubusercontent.com/ToolJet/ToolJet/develop/plugins/schemas/operations.schema.json",
|
||||
"title": "ClickUp datasource",
|
||||
"description": "A schema defining ClickUp datasource",
|
||||
"type": "api",
|
||||
"defaults": {},
|
||||
"properties": {
|
||||
"operation": {
|
||||
"label": "",
|
||||
"key": "clickup_operation",
|
||||
"type": "react-component-api-endpoint",
|
||||
"description": "Single select dropdown for operation",
|
||||
"spec_url": "https://developer.clickup.com/openapi/673cf4cfdca96a0019533cad"
|
||||
}
|
||||
}
|
||||
}
|
||||
3
marketplace/plugins/clickup/lib/types.ts
Normal file
3
marketplace/plugins/clickup/lib/types.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
export type SourceOptions = {
|
||||
apiKey: string;
|
||||
};
|
||||
26
marketplace/plugins/clickup/package.json
Normal file
26
marketplace/plugins/clickup/package.json
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "@tooljet-marketplace/clickup",
|
||||
"version": "1.0.0",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"directories": {
|
||||
"lib": "lib",
|
||||
"test": "__tests__"
|
||||
},
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "echo \"Error: run tests from root\" && exit 1",
|
||||
"build": "ncc build lib/index.ts -o dist",
|
||||
"watch": "ncc build lib/index.ts -o dist --watch"
|
||||
},
|
||||
"homepage": "https://github.com/tooljet/tooljet#readme",
|
||||
"dependencies": {
|
||||
"@tooljet-marketplace/common": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^4.7.4",
|
||||
"@vercel/ncc": "^0.34.0"
|
||||
}
|
||||
}
|
||||
11
marketplace/plugins/clickup/tsconfig.json
Normal file
11
marketplace/plugins/clickup/tsconfig.json
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "lib"
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist"
|
||||
]
|
||||
}
|
||||
|
|
@ -15,6 +15,9 @@
|
|||
"options": {
|
||||
"url": {
|
||||
"type": "string"
|
||||
},
|
||||
"personal_token": {
|
||||
"encrypted": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -57,11 +60,12 @@
|
|||
"key": "personal_token",
|
||||
"type": "password",
|
||||
"description": "Enter your api token",
|
||||
"hint": "You can generate a personal access token from your Jira account 'Manage account'."
|
||||
"hint": "You can generate a personal access token from your Jira account 'Manage account'.",
|
||||
"encrypted": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"url"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -146,7 +146,7 @@
|
|||
"height": "36px"
|
||||
},
|
||||
"withPayload": {
|
||||
"label": "Include metadata",
|
||||
"label": "Include payload",
|
||||
"key": "withPayload",
|
||||
"type": "codehinter",
|
||||
"description": "Whether to return payload values.",
|
||||
|
|
@ -163,4 +163,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,16 @@ export default class Supabase implements QueryService {
|
|||
}
|
||||
|
||||
if (error) {
|
||||
throw new QueryError('Query could not be completed', error, {});
|
||||
const errorMessage = error?.message || "An unknown error occurred.";
|
||||
let errorDetails: any = {};
|
||||
|
||||
const supabaseError = error as any;
|
||||
const { code, hint } = supabaseError;
|
||||
|
||||
errorDetails.code = code;
|
||||
errorDetails.hint = hint;
|
||||
|
||||
throw new QueryError('Query could not be completed', errorMessage, errorDetails);
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -57,7 +57,18 @@ export default class FirestoreQueryService implements QueryService {
|
|||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
throw new QueryError('Query could not be completed', error.message, {});
|
||||
const errorMessage = error.message || "An unknown error occurred.";
|
||||
let errorDetails: any = {};
|
||||
|
||||
if (error && error instanceof Error) {
|
||||
const firestoreError = error as any;
|
||||
const { code, name } = firestoreError;
|
||||
|
||||
errorDetails.code = code as string;
|
||||
errorDetails.name = name;
|
||||
}
|
||||
|
||||
throw new QueryError('Query could not be completed', errorMessage, errorDetails);
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -46,8 +46,17 @@ export default class GRPC implements QueryService {
|
|||
metadata.add(sourceOptions.grpc_apikey_key, sourceOptions.grpc_apikey_value);
|
||||
}
|
||||
|
||||
let jsonMessage = {};
|
||||
if (queryOptions.jsonMessage) {
|
||||
try {
|
||||
jsonMessage = JSON.parse(queryOptions.jsonMessage);
|
||||
} catch (e) {
|
||||
throw new QueryError('Invalid JSON message', {}, {});
|
||||
}
|
||||
}
|
||||
|
||||
const result = await new Promise((resolve, reject) => {
|
||||
clientStub[rpc]({}, metadata, (err: any, response: any) => {
|
||||
clientStub[rpc](jsonMessage, metadata, (err: any, response: any) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,5 +11,6 @@ export type SourceOptions = {
|
|||
export type QueryOptions = {
|
||||
operation: string;
|
||||
serviceName: string;
|
||||
jsonMessage: string;
|
||||
rpc: string;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@
|
|||
"type": "string"
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"encrypted": true
|
||||
},
|
||||
"connectionLimit": {
|
||||
"type": "string"
|
||||
|
|
@ -83,7 +84,8 @@
|
|||
"label": "Password",
|
||||
"key": "password",
|
||||
"type": "password",
|
||||
"description": "Enter password"
|
||||
"description": "Enter password",
|
||||
"encrypted": true
|
||||
},
|
||||
"connectionLimit": {
|
||||
"label": "Connection Limit",
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
{
|
||||
"$schema": "https://raw.githubusercontent.com/ToolJet/ToolJet/develop/plugins/schemas/operations.schema.json",
|
||||
"title": "Stripe datasource",
|
||||
"description": "A schema defining stripe datasource",
|
||||
"type": "api",
|
||||
"defaults": {},
|
||||
"properties": {
|
||||
"operation": {
|
||||
"label": "",
|
||||
"key": "stripe_operation",
|
||||
"type": "react-component-api-endpoint",
|
||||
"description": "Single select dropdown for operation",
|
||||
"specUrl": "https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.json"
|
||||
}
|
||||
"$schema": "https://raw.githubusercontent.com/ToolJet/ToolJet/develop/plugins/schemas/operations.schema.json",
|
||||
"title": "Stripe datasource",
|
||||
"description": "A schema defining stripe datasource",
|
||||
"type": "api",
|
||||
"defaults": {},
|
||||
"properties": {
|
||||
"operation": {
|
||||
"label": "",
|
||||
"key": "stripe_operation",
|
||||
"type": "react-component-api-endpoint",
|
||||
"description": "Single select dropdown for operation",
|
||||
"spec_url": "https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
3
plugins/packages/woocommerce/.gitignore
vendored
3
plugins/packages/woocommerce/.gitignore
vendored
|
|
@ -1,5 +1,4 @@
|
|||
node_modules
|
||||
lib/*.d.*
|
||||
lib/*.js
|
||||
lib/*.js.map
|
||||
lib/operations.json
|
||||
lib/*.js.map
|
||||
105
plugins/packages/woocommerce/lib/operations.json
Normal file
105
plugins/packages/woocommerce/lib/operations.json
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
{
|
||||
"title": "Woocommerce datasource",
|
||||
"description": "A schema defining Woocommerce datasource",
|
||||
"type": "api",
|
||||
"defaults": {},
|
||||
"properties": {
|
||||
"resource": {
|
||||
"label": "Resource",
|
||||
"key": "resource",
|
||||
"className": "col-md-4",
|
||||
"type": "dropdown-component-flip",
|
||||
"description": "Resource select",
|
||||
"list": [
|
||||
{ "value": "product", "name": "Product" },
|
||||
{ "value": "customer", "name": "Customer" },
|
||||
{ "value": "order", "name": "Order" },
|
||||
{ "value": "coupon", "name": "Coupon" }
|
||||
]
|
||||
},
|
||||
"customer": {
|
||||
"operation": {
|
||||
"label": "Operation",
|
||||
"key": "operation",
|
||||
"type": "dropdown-component-flip",
|
||||
"description": "Single select dropdown for operation",
|
||||
"list": [
|
||||
{ "value": "list_customer", "name": "List all customers" },
|
||||
{ "value": "update_customer", "name": "Update a customer" },
|
||||
{ "value": "delete_customer", "name": "Delete a customer" },
|
||||
{ "value": "batch_update_customer", "name": "Batch update customers" },
|
||||
{ "value": "create_customer", "name": "Create a customer" },
|
||||
{ "value": "retrieve_customer", "name": "Retrieve a customer" }
|
||||
]
|
||||
},
|
||||
"list_customer": {
|
||||
"page": {
|
||||
"label": "Page",
|
||||
"key": "page",
|
||||
"type": "codehinter",
|
||||
"description": "Enter page",
|
||||
"width": "320px",
|
||||
"height": "36px",
|
||||
"className": "codehinter-plugins",
|
||||
"placeholder": "",
|
||||
"lineNumbers": false
|
||||
},
|
||||
"context": {
|
||||
"label": "Context",
|
||||
"key": "context",
|
||||
"type": "codehinter",
|
||||
"description": "Enter context",
|
||||
"width": "320px",
|
||||
"height": "36px",
|
||||
"className": "codehinter-plugins",
|
||||
"placeholder": "",
|
||||
"lineNumbers": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"product": {
|
||||
"operation": {
|
||||
"label": "Operation",
|
||||
"key": "operation",
|
||||
"type": "dropdown-component-flip",
|
||||
"description": "Single select dropdown for operation",
|
||||
"list": [
|
||||
{ "value": "list_product", "name": "List all products" },
|
||||
{ "value": "update_product", "name": "Update a product" },
|
||||
{ "value": "delete_product", "name": "Delete a product" },
|
||||
{ "value": "batch_update_product", "name": "Batch update products" },
|
||||
{ "value": "create_product", "name": "Create a product" },
|
||||
{ "value": "retrieve_product", "name": "Retrieve a product" }
|
||||
]
|
||||
}
|
||||
},
|
||||
"order": {
|
||||
"operation": {
|
||||
"label": "Operation",
|
||||
"key": "operation",
|
||||
"type": "dropdown-component-flip",
|
||||
"description": "Single select dropdown for operation",
|
||||
"list": [
|
||||
{ "value": "list_order", "name": "List all orders" },
|
||||
{ "value": "update_order", "name": "Update an order" },
|
||||
{ "value": "delete_order", "name": "Delete an order" },
|
||||
{ "value": "batch_update_order", "name": "Batch update orders" },
|
||||
{ "value": "create_order", "name": "Create an order" },
|
||||
{ "value": "retrieve_order", "name": "Retrieve an order" }
|
||||
]
|
||||
}
|
||||
},
|
||||
"coupon": {
|
||||
"operation": {
|
||||
"label": "Operation",
|
||||
"key": "operation",
|
||||
"type": "dropdown-component-flip",
|
||||
"description": "Single select dropdown for operation",
|
||||
"list": [
|
||||
{ "value": "list_coupon", "name": "List all coupons" },
|
||||
{ "value": "create_coupon", "name": "Create a coupon" }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +1 @@
|
|||
3.13.0
|
||||
3.14.0
|
||||
|
|
|
|||
16
server/migrations/1746520805456-AddResourceDataAudit.ts
Normal file
16
server/migrations/1746520805456-AddResourceDataAudit.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import { MigrationInterface, QueryRunner, TableColumn } from 'typeorm';
|
||||
|
||||
export class AddResourceDataAudit1746520805456 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.addColumn(
|
||||
'audit_logs',
|
||||
new TableColumn({
|
||||
name: 'resource_data',
|
||||
type: 'json',
|
||||
isNullable: true,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import { MigrationInterface, QueryRunner, TableUnique } from "typeorm";
|
||||
|
||||
export class AddPluginIdUniqueConstraint1747133448781 implements MigrationInterface {
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.createUniqueConstraint(
|
||||
"plugins",
|
||||
new TableUnique({
|
||||
name: "UQ_plugin_pluginId",
|
||||
columnNames: ["plugin_id"],
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.dropUniqueConstraint(
|
||||
"plugins",
|
||||
"UQ_plugin_pluginId"
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
redis-server /etc/redis/redis.conf &
|
||||
|
||||
# Fix ownership and permissions
|
||||
chown -R postgres:postgres /var/lib/postgresql /var/run/postgresql
|
||||
chmod 0700 /var/lib/postgresql/13/main
|
||||
|
|
|
|||
|
|
@ -221,5 +221,13 @@
|
|||
"id": "azurerepos",
|
||||
"author": "Tooljet",
|
||||
"timestamp": "Mon, 23 Dec 2024 11:57:30 GMT"
|
||||
},
|
||||
{
|
||||
"name": "ClickUp",
|
||||
"description": "ClickUp plugin for task, list, and doc management",
|
||||
"version": "1.0.0",
|
||||
"id": "clickup",
|
||||
"author": "Tooljet",
|
||||
"timestamp": "Wed, 16 Apr 2025 15:31:38 GMT"
|
||||
}
|
||||
]
|
||||
|
|
@ -23,6 +23,9 @@ export class AuditLog extends BaseEntity {
|
|||
@Column({ name: 'resource_type', type: 'enum', enum: MODULES })
|
||||
resourceType: MODULES;
|
||||
|
||||
@Column('simple-json', { name: 'resource_data' })
|
||||
resourceData;
|
||||
|
||||
@Column({ name: 'action_type' })
|
||||
actionType: string;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,9 +6,11 @@ import {
|
|||
OneToOne,
|
||||
PrimaryGeneratedColumn,
|
||||
UpdateDateColumn,
|
||||
Unique
|
||||
} from 'typeorm';
|
||||
import { File } from 'src/entities/file.entity';
|
||||
|
||||
@Unique(['pluginId'])
|
||||
@Entity({ name: 'plugins' })
|
||||
export class Plugin {
|
||||
@PrimaryGeneratedColumn()
|
||||
|
|
|
|||
|
|
@ -7,6 +7,6 @@ export interface IAuditLogService {
|
|||
perform(
|
||||
{ userId, organizationId, resourceId, resourceType, actionType, resourceName, metadata }: AuditLogFields,
|
||||
manager?: EntityManager
|
||||
): Promise<AuditLog>;
|
||||
): Promise<AuditLog[]>;
|
||||
findPerPage(user: User, query: AuditLogsQuery): Promise<any>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,10 +18,12 @@ export interface AuditLogFields {
|
|||
organizationId: string;
|
||||
resourceId: string;
|
||||
resourceType: MODULES;
|
||||
resourceData?: object;
|
||||
actionType: string;
|
||||
resourceName?: string;
|
||||
ipAddress?: string;
|
||||
metadata?: object;
|
||||
organizationIds?: Array<string>;
|
||||
}
|
||||
|
||||
export interface Features {
|
||||
|
|
|
|||
|
|
@ -28,12 +28,15 @@ export const FEATURES: FeaturesConfig = {
|
|||
},
|
||||
[FEATURE_KEY.FORGOT_PASSWORD]: {
|
||||
isPublic: true,
|
||||
auditLogsKey: 'USER_PASSWORD_FORGOT',
|
||||
},
|
||||
[FEATURE_KEY.RESET_PASSWORD]: {
|
||||
isPublic: true,
|
||||
auditLogsKey: 'USER_PASSWORD_RESET',
|
||||
},
|
||||
[FEATURE_KEY.OAUTH_SIGN_IN]: {
|
||||
isPublic: true,
|
||||
auditLogsKey: 'USER_LOGIN',
|
||||
},
|
||||
[FEATURE_KEY.OAUTH_OPENID_CONFIGS]: {
|
||||
isPublic: true,
|
||||
|
|
@ -43,6 +46,7 @@ export const FEATURES: FeaturesConfig = {
|
|||
},
|
||||
[FEATURE_KEY.OAUTH_COMMON_SIGN_IN]: {
|
||||
isPublic: true,
|
||||
auditLogsKey: 'USER_LOGIN',
|
||||
},
|
||||
[FEATURE_KEY.OAUTH_SAML_RESPONSE]: {
|
||||
isPublic: true,
|
||||
|
|
|
|||
|
|
@ -124,6 +124,9 @@ export class AuthService implements IAuthService {
|
|||
organizationId: organization.id,
|
||||
resourceId: user.id,
|
||||
resourceName: user.email,
|
||||
resourceData: {
|
||||
auth_method: 'password',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -184,6 +187,13 @@ export class AuthService implements IAuthService {
|
|||
forgotPasswordToken: null,
|
||||
passwordRetryCount: 0,
|
||||
});
|
||||
const auditLogEntry = {
|
||||
userId: user.id,
|
||||
organizationId: user.defaultOrganizationId,
|
||||
resourceId: user.id,
|
||||
resourceName: user.email,
|
||||
};
|
||||
RequestContext.setLocals(AUDIT_LOGS_REQUEST_CONTEXT_KEY, auditLogEntry);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -195,6 +205,13 @@ export class AuthService implements IAuthService {
|
|||
}
|
||||
const forgotPasswordToken = uuid.v4();
|
||||
await this.userRepository.updateOne(user.id, { forgotPasswordToken });
|
||||
const auditLogEntry = {
|
||||
userId: user.id,
|
||||
organizationId: user.defaultOrganizationId,
|
||||
resourceId: user.id,
|
||||
resourceName: user.email,
|
||||
};
|
||||
RequestContext.setLocals(AUDIT_LOGS_REQUEST_CONTEXT_KEY, auditLogEntry);
|
||||
this.eventEmitter.emit('emailEvent', {
|
||||
type: EMAIL_EVENTS.SEND_PASSWORD_RESET_EMAIL,
|
||||
payload: {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { UserAllPermissions } from '@modules/app/types';
|
|||
import { FEATURE_KEY } from '../constants';
|
||||
import { DataSource } from '@entities/data_source.entity';
|
||||
import { MODULES } from '@modules/app/constants/modules';
|
||||
import { getTooljetEdition } from '@helpers/utils.helper';
|
||||
|
||||
type Subjects = InferSubjects<typeof DataSource> | 'all';
|
||||
export type FeatureAbility = Ability<[FEATURE_KEY, Subjects]>;
|
||||
|
|
@ -33,10 +34,13 @@ export class FeatureAbilityFactory extends AbilityFactory<FEATURE_KEY, Subjects>
|
|||
const isAllViewable = !!resourcePermissions?.isAllUsable;
|
||||
|
||||
const dataSourceId = request?.tj_resource_id;
|
||||
|
||||
const toolJetEdition = getTooljetEdition();
|
||||
// Oauth end points available to all
|
||||
can(FEATURE_KEY.GET_OAUTH2_BASE_URL, DataSource);
|
||||
can(FEATURE_KEY.AUTHORIZE, DataSource);
|
||||
if ((toolJetEdition == 'ee' && superAdmin) || (toolJetEdition !== 'ee' && isAdmin)) {
|
||||
can(FEATURE_KEY.QUERIES_DATASOURCE_LINKED_TO_MARKETPLACE_PLUGIN, DataSource);
|
||||
}
|
||||
|
||||
if (isBuilder) {
|
||||
// Only builder can do scope change, Get call is there on app builder
|
||||
|
|
@ -56,6 +60,7 @@ export class FeatureAbilityFactory extends AbilityFactory<FEATURE_KEY, Subjects>
|
|||
FEATURE_KEY.TEST_CONNECTION,
|
||||
FEATURE_KEY.SCOPE_CHANGE,
|
||||
FEATURE_KEY.GET_FOR_APP,
|
||||
FEATURE_KEY.QUERIES_LINKED_TO_DATASOURCE,
|
||||
],
|
||||
DataSource
|
||||
);
|
||||
|
|
@ -70,7 +75,7 @@ export class FeatureAbilityFactory extends AbilityFactory<FEATURE_KEY, Subjects>
|
|||
);
|
||||
|
||||
if (isCanDelete) {
|
||||
can(FEATURE_KEY.DELETE, DataSource);
|
||||
can([FEATURE_KEY.DELETE, FEATURE_KEY.QUERIES_LINKED_TO_DATASOURCE], DataSource);
|
||||
}
|
||||
if (isCanCreate) {
|
||||
can(FEATURE_KEY.CREATE, DataSource);
|
||||
|
|
|
|||
|
|
@ -20,5 +20,7 @@ export const FEATURES: FeaturesConfig = {
|
|||
[FEATURE_KEY.GET_OAUTH2_BASE_URL]: {},
|
||||
[FEATURE_KEY.AUTHORIZE]: {},
|
||||
[FEATURE_KEY.GET_FOR_APP]: {},
|
||||
[FEATURE_KEY.QUERIES_LINKED_TO_DATASOURCE]: {},
|
||||
[FEATURE_KEY.QUERIES_DATASOURCE_LINKED_TO_MARKETPLACE_PLUGIN]: {},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ export enum FEATURE_KEY {
|
|||
TEST_CONNECTION = 'TEST_CONNECTION',
|
||||
GET_OAUTH2_BASE_URL = 'GET_OAUTH2_BASE_URL',
|
||||
AUTHORIZE = 'AUTHORIZE',
|
||||
QUERIES_LINKED_TO_DATASOURCE = 'QUERIES_LINKED_TO_DATASOURCE',
|
||||
QUERIES_DATASOURCE_LINKED_TO_MARKETPLACE_PLUGIN = 'QUERIES_DATASOURCE_LINKED_TO_MARKETPLACE_PLUGIN',
|
||||
}
|
||||
|
||||
export enum DataSourceTypes {
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ export class DataSourcesController implements IDataSourcesController {
|
|||
|
||||
@InitFeature(FEATURE_KEY.GET_OAUTH2_BASE_URL)
|
||||
@UseGuards(FeatureAbilityGuard)
|
||||
@Get('fetch-oauth2-base-url')
|
||||
@Post('fetch-oauth2-base-url')
|
||||
getAuthUrl(@Body() getDataSourceOauthUrlDto: GetDataSourceOauthUrlDto) {
|
||||
return this.dataSourcesService.getAuthUrl(getDataSourceOauthUrlDto);
|
||||
}
|
||||
|
|
@ -129,6 +129,20 @@ export class DataSourcesController implements IDataSourcesController {
|
|||
return;
|
||||
}
|
||||
|
||||
@InitFeature(FEATURE_KEY.QUERIES_DATASOURCE_LINKED_TO_MARKETPLACE_PLUGIN)
|
||||
@UseGuards(FeatureAbilityGuard)
|
||||
@Get('dependent-queries/marketplace-plugin/:plugin_id')
|
||||
async findDatasourcesAndQueriesOfMarketplacePlugin(@User() user: UserEntity, @Param('plugin_id') pluginId) {
|
||||
return await this.dataSourcesService.findDatasourcesAndQueriesOfMarketplacePlugin(pluginId);
|
||||
}
|
||||
|
||||
@InitFeature(FEATURE_KEY.QUERIES_LINKED_TO_DATASOURCE)
|
||||
@UseGuards(FeatureAbilityGuard)
|
||||
@Get('dependent-queries/:datasource_id')
|
||||
async findQueriesLinkedToDatasource(@User() user: UserEntity, @Param('datasource_id') datasourceId: string) {
|
||||
return await this.dataSourcesService.findQueriesLinkedToDatasource(datasourceId);
|
||||
}
|
||||
|
||||
@InitFeature(FEATURE_KEY.AUTHORIZE)
|
||||
@UseGuards(FeatureAbilityGuard)
|
||||
@Post('decrypt')
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { InstanceSettingsModule } from '@modules/instance-settings/module';
|
|||
import { VersionRepository } from '@modules/versions/repository';
|
||||
import { AppsRepository } from '@modules/apps/repository';
|
||||
import { TooljetDbModule } from '@modules/tooljet-db/module';
|
||||
import { OrganizationRepository } from '@modules/organizations/repository';
|
||||
import { SessionModule } from '@modules/session/module';
|
||||
import { SampleDBScheduler } from './schedulers/sample-db.scheduler';
|
||||
|
||||
|
|
@ -21,6 +22,7 @@ export class DataSourcesModule {
|
|||
const { DataSourcesUtilService } = await import(`${importPath}/data-sources/util.service`);
|
||||
const { PluginsServiceSelector } = await import(`${importPath}/data-sources/services/plugin-selector.service`);
|
||||
const { SampleDataSourceService } = await import(`${importPath}/data-sources/services/sample-ds.service`);
|
||||
const { OrganizationsService } = await import(`${importPath}/organizations/service`);
|
||||
|
||||
return {
|
||||
module: DataSourcesModule,
|
||||
|
|
@ -42,6 +44,8 @@ export class DataSourcesModule {
|
|||
PluginsRepository,
|
||||
SampleDataSourceService,
|
||||
FeatureAbilityFactory,
|
||||
OrganizationsService,
|
||||
OrganizationRepository,
|
||||
SampleDBScheduler,
|
||||
],
|
||||
controllers: [DataSourcesController],
|
||||
|
|
|
|||
|
|
@ -168,4 +168,26 @@ export class DataSourcesRepository extends Repository<DataSource> {
|
|||
});
|
||||
}, manager || this.manager);
|
||||
}
|
||||
|
||||
getDatasourceByPluginId(pluginId: string) {
|
||||
return dbTransactionWrap((manager: EntityManager) => {
|
||||
return manager.find(DataSource, {
|
||||
where: {
|
||||
pluginId: pluginId,
|
||||
},
|
||||
relations: ['dataQueries'],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getQueriesByDatasourceId(datasourceId) {
|
||||
return dbTransactionWrap((manager: EntityManager) => {
|
||||
return manager.find(DataSource, {
|
||||
where: {
|
||||
id: datasourceId,
|
||||
},
|
||||
relations: ['dataQueries'],
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ import { GetQueryVariables, UpdateOptions } from './types';
|
|||
import { DataSource } from '@entities/data_source.entity';
|
||||
import { PluginsServiceSelector } from './services/plugin-selector.service';
|
||||
import { IDataSourcesService } from './interfaces/IService';
|
||||
// import { FEATURE_KEY } from './constants';
|
||||
import { OrganizationsService } from '@modules/organizations/service';
|
||||
import { RequestContext } from '@modules/request-context/service';
|
||||
import { AUDIT_LOGS_REQUEST_CONTEXT_KEY } from '@modules/app/constants';
|
||||
|
||||
|
|
@ -30,7 +32,8 @@ export class DataSourcesService implements IDataSourcesService {
|
|||
protected readonly dataSourcesUtilService: DataSourcesUtilService,
|
||||
protected readonly abilityService: AbilityService,
|
||||
protected readonly appEnvironmentsUtilService: AppEnvironmentUtilService,
|
||||
protected readonly pluginsServiceSelector: PluginsServiceSelector
|
||||
protected readonly pluginsServiceSelector: PluginsServiceSelector,
|
||||
protected readonly organizationsService: OrganizationsService
|
||||
) {}
|
||||
|
||||
async getForApp(query: GetQueryVariables, user: User): Promise<{ data_sources: object[] }> {
|
||||
|
|
@ -43,7 +46,6 @@ export class DataSourcesService implements IDataSourcesService {
|
|||
const dataSources = await this.dataSourcesRepository.allGlobalDS(userPermissions, user.organizationId, query ?? {});
|
||||
let staticDataSources = await this.dataSourcesRepository.getAllStaticDataSources(query.appVersionId);
|
||||
|
||||
|
||||
if (!shouldIncludeWorkflows) {
|
||||
// remove workflowsdefault data source from static data sources
|
||||
staticDataSources = staticDataSources.filter((dataSource) => dataSource.kind !== 'workflows');
|
||||
|
|
@ -176,6 +178,12 @@ export class DataSourcesService implements IDataSourcesService {
|
|||
if (dataSource.type === DataSourceTypes.SAMPLE) {
|
||||
throw new BadRequestException('Cannot delete sample data source');
|
||||
}
|
||||
|
||||
const result = await this.findQueriesLinkedToDatasource(dataSourceId);
|
||||
if (result.dependent_queries) {
|
||||
throw new BadRequestException(`Datasource can't be deleted, queries are in use`);
|
||||
}
|
||||
|
||||
await this.dataSourcesRepository.delete(dataSourceId);
|
||||
|
||||
// Setting data for audit logs
|
||||
|
|
@ -243,4 +251,30 @@ export class DataSourcesService implements IDataSourcesService {
|
|||
await this.dataSourcesUtilService.authorizeOauth2(dataSource, code, user.id, environmentId, user.organizationId);
|
||||
return;
|
||||
}
|
||||
|
||||
async findQueriesLinkedToDatasource(datasourceId: string) {
|
||||
const dataSourceDetails = await this.dataSourcesRepository.getQueriesByDatasourceId(datasourceId);
|
||||
if (dataSourceDetails.length == 0) return { datasources: 0, dependent_queries: 0 };
|
||||
|
||||
const queries = [];
|
||||
dataSourceDetails.forEach((datasourceDetail) => {
|
||||
const { dataQueries = [] } = datasourceDetail;
|
||||
if (dataQueries.length) queries.push(...dataQueries);
|
||||
});
|
||||
|
||||
return { datasources: dataSourceDetails.length, dependent_queries: queries.length };
|
||||
}
|
||||
|
||||
async findDatasourcesAndQueriesOfMarketplacePlugin(pluginId: string) {
|
||||
const dataSourcesByMarketplacePlugin = await this.dataSourcesRepository.getDatasourceByPluginId(pluginId);
|
||||
if (!dataSourcesByMarketplacePlugin.length) return { dependent_queries: 0 };
|
||||
|
||||
const queries = [];
|
||||
dataSourcesByMarketplacePlugin?.forEach((datasource) => {
|
||||
if (datasource.dataQueries.length) queries.push(...datasource.dataQueries);
|
||||
});
|
||||
return {
|
||||
dependent_queries: queries.length,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ interface Features {
|
|||
[FEATURE_KEY.GET_OAUTH2_BASE_URL]: FeatureConfig;
|
||||
[FEATURE_KEY.AUTHORIZE]: FeatureConfig;
|
||||
[FEATURE_KEY.GET_FOR_APP]: FeatureConfig;
|
||||
[FEATURE_KEY.QUERIES_LINKED_TO_DATASOURCE]: FeatureConfig;
|
||||
[FEATURE_KEY.QUERIES_DATASOURCE_LINKED_TO_MARKETPLACE_PLUGIN]: FeatureConfig;
|
||||
}
|
||||
|
||||
export interface FeaturesConfig {
|
||||
|
|
|
|||
|
|
@ -189,17 +189,16 @@ export class DataSourcesUtilService implements IDataSourcesUtilService {
|
|||
/*
|
||||
Basic plan customer. lets update all environment options.
|
||||
this will help us to run the queries successfully when the user buys enterprise plan
|
||||
*/
|
||||
await Promise.all(
|
||||
allEnvs.map(async (envToUpdate) => {
|
||||
dataSource.options = (
|
||||
await this.appEnvironmentUtilService.getOptions(dataSourceId, organizationId, envToUpdate.id)
|
||||
).options;
|
||||
*/
|
||||
|
||||
const newOptions = await this.parseOptionsForUpdate(dataSource, options, manager);
|
||||
await this.appEnvironmentUtilService.updateOptions(newOptions, envToUpdate.id, dataSource.id, manager);
|
||||
})
|
||||
);
|
||||
const newOptions = await this.parseOptionsForUpdate(dataSource, options, manager);
|
||||
for (const env of allEnvs) {
|
||||
dataSource.options = (
|
||||
await this.appEnvironmentUtilService.getOptions(dataSourceId, organizationId, env.id)
|
||||
).options;
|
||||
|
||||
await this.appEnvironmentUtilService.updateOptions(newOptions, env.id, dataSource.id, manager);
|
||||
}
|
||||
}
|
||||
const updatableParams = {
|
||||
id: dataSourceId,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ export const FEATURES: FeaturesConfig = {
|
|||
[MODULES.ONBOARDING]: {
|
||||
[FEATURE_KEY.ACTIVATE_ACCOUNT]: {
|
||||
isPublic: true,
|
||||
auditLogsKey: 'USER_SIGNUP',
|
||||
}, // Account Activation
|
||||
[FEATURE_KEY.SETUP_SUPER_ADMIN]: {
|
||||
isPublic: true,
|
||||
|
|
@ -15,6 +16,7 @@ export const FEATURES: FeaturesConfig = {
|
|||
}, // Signup
|
||||
[FEATURE_KEY.ACCEPT_INVITE]: {
|
||||
isPublic: true,
|
||||
auditLogsKey: 'USER_INVITE_REDEEM',
|
||||
}, // Accept Invitation
|
||||
[FEATURE_KEY.RESEND_INVITE]: {
|
||||
isPublic: true,
|
||||
|
|
@ -27,6 +29,7 @@ export const FEATURES: FeaturesConfig = {
|
|||
}, // Verify Organization Token
|
||||
[FEATURE_KEY.SETUP_ACCOUNT_FROM_TOKEN]: {
|
||||
isPublic: true,
|
||||
auditLogsKey: 'USER_SIGNUP',
|
||||
}, // Setup Account From Token
|
||||
[FEATURE_KEY.CHECK_WORKSPACE_UNIQUENESS]: {
|
||||
isPublic: true,
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ export class OnboardingService implements IOnboardingService {
|
|||
const userParams = { email, password, firstName, lastName };
|
||||
|
||||
// Find the default workspace
|
||||
const defaultWorkspace = await this.organizationRepository. getDefaultWorkspaceOfInstance();
|
||||
const defaultWorkspace = await this.organizationRepository.getDefaultWorkspaceOfInstance();
|
||||
|
||||
if (existingUser) {
|
||||
// Handling instance and workspace level signup for existing user
|
||||
|
|
@ -133,7 +133,7 @@ export class OnboardingService implements IOnboardingService {
|
|||
manager
|
||||
);
|
||||
} else {
|
||||
if(defaultWorkspace && !signingUpOrganization) {
|
||||
if (defaultWorkspace && !signingUpOrganization) {
|
||||
return await this.onboardingUtilService.createUserInDefaultWorkspace(
|
||||
userParams,
|
||||
defaultWorkspace,
|
||||
|
|
@ -263,7 +263,8 @@ export class OnboardingService implements IOnboardingService {
|
|||
throw new BadRequestException('Please enter password');
|
||||
}
|
||||
|
||||
const activateDefaultWorkspace = (defaultWorkspace && defaultWorkspace.id === user.defaultOrganizationId) || allowPersonalWorkspace;
|
||||
const activateDefaultWorkspace =
|
||||
(defaultWorkspace && defaultWorkspace.id === user.defaultOrganizationId) || allowPersonalWorkspace;
|
||||
if (activateDefaultWorkspace) {
|
||||
// Getting default workspace
|
||||
const defaultOrganizationUser: OrganizationUser = user.organizationUsers.find(
|
||||
|
|
@ -277,11 +278,11 @@ export class OnboardingService implements IOnboardingService {
|
|||
// Activate default workspace
|
||||
await this.organizationUsersUtilService.activateOrganization(defaultOrganizationUser, manager);
|
||||
|
||||
if(defaultWorkspace && defaultWorkspace.id === user.defaultOrganizationId){
|
||||
if (defaultWorkspace && defaultWorkspace.id === user.defaultOrganizationId) {
|
||||
const personalWorkspaces = await this.organizationUsersUtilService.personalWorkspaces(user.id);
|
||||
for(const personalWorkspace of personalWorkspaces){
|
||||
for (const personalWorkspace of personalWorkspaces) {
|
||||
// if any personal workspace left. activate those
|
||||
await this.organizationUsersUtilService.activateOrganization(personalWorkspace, manager);
|
||||
await this.organizationUsersUtilService.activateOrganization(personalWorkspace, manager);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -362,6 +363,9 @@ export class OnboardingService implements IOnboardingService {
|
|||
organizationId: organization?.id,
|
||||
resourceId: user.id,
|
||||
resourceName: user.email,
|
||||
resourceData: {
|
||||
signup_method: 'self-signup',
|
||||
},
|
||||
});
|
||||
|
||||
await this.licenseUserService.validateUser(manager);
|
||||
|
|
@ -421,6 +425,13 @@ export class OnboardingService implements IOnboardingService {
|
|||
}
|
||||
const isWorkspaceSignup = organizationUser.source === WORKSPACE_USER_SOURCE.SIGNUP;
|
||||
await this.licenseUserService.validateUser(manager);
|
||||
const auditLogEntry = {
|
||||
userId: user.id,
|
||||
organizationId: organization.id,
|
||||
resourceId: user.id,
|
||||
resourceName: user.email,
|
||||
};
|
||||
RequestContext.setLocals(AUDIT_LOGS_REQUEST_CONTEXT_KEY, auditLogEntry);
|
||||
return this.sessionUtilService.generateLoginResultPayload(
|
||||
response,
|
||||
user,
|
||||
|
|
@ -534,6 +545,16 @@ export class OnboardingService implements IOnboardingService {
|
|||
Till now user doesn't have an organization.
|
||||
*/
|
||||
await this.licenseUserService.validateUser(manager);
|
||||
const auditLogsData = {
|
||||
userId: signupUser.id,
|
||||
organizationId: signupUser.organizationUsers[0].organizationId,
|
||||
resourceId: signupUser.id,
|
||||
resourceName: signupUser.email,
|
||||
resourceData: {
|
||||
signup_method: 'invite-redemption',
|
||||
},
|
||||
};
|
||||
RequestContext.setLocals(AUDIT_LOGS_REQUEST_CONTEXT_KEY, auditLogsData);
|
||||
return this.onboardingUtilService.processOrganizationSignup(
|
||||
response,
|
||||
signupUser,
|
||||
|
|
@ -566,7 +587,6 @@ export class OnboardingService implements IOnboardingService {
|
|||
if (user.status !== USER_STATUS.ACTIVE) {
|
||||
throw new BadRequestException(getUserErrorMessages(user.status));
|
||||
}
|
||||
|
||||
RequestContext.setLocals(AUDIT_LOGS_REQUEST_CONTEXT_KEY, {
|
||||
userId: user.id,
|
||||
organizationId: organizationUser.organizationId,
|
||||
|
|
|
|||
|
|
@ -6,12 +6,27 @@ export const FEATURES: FeaturesConfig = {
|
|||
[MODULES.ORGANIZATION_USER]: {
|
||||
[FEATURE_KEY.SUGGEST_USERS]: {},
|
||||
[FEATURE_KEY.VIEW_ALL_USERS]: {},
|
||||
[FEATURE_KEY.USER_ARCHIVE_ALL]: {},
|
||||
[FEATURE_KEY.USER_ARCHIVE]: {},
|
||||
[FEATURE_KEY.USER_INVITE]: {},
|
||||
[FEATURE_KEY.USER_ARCHIVE_ALL]: {
|
||||
isPublic: true,
|
||||
auditLogsKey: 'USER_ARCHIVE',
|
||||
},
|
||||
[FEATURE_KEY.USER_ARCHIVE]: {
|
||||
isPublic: true,
|
||||
auditLogsKey: 'USER_ARCHIVE',
|
||||
},
|
||||
[FEATURE_KEY.USER_INVITE]: {
|
||||
isPublic: true,
|
||||
auditLogsKey: 'USER_INVITE',
|
||||
},
|
||||
[FEATURE_KEY.USER_BULK_UPLOAD]: {},
|
||||
[FEATURE_KEY.USER_UNARCHIVE]: {},
|
||||
[FEATURE_KEY.USER_UNARCHIVE_ALL]: {},
|
||||
[FEATURE_KEY.USER_UNARCHIVE]: {
|
||||
isPublic: true,
|
||||
auditLogsKey: 'USER_UNARCHIVE',
|
||||
},
|
||||
[FEATURE_KEY.USER_UNARCHIVE_ALL]: {
|
||||
isPublic: true,
|
||||
auditLogsKey: 'USER_UNARCHIVE',
|
||||
},
|
||||
[FEATURE_KEY.USER_UPDATE]: {},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -90,14 +90,14 @@ export class OrganizationUsersController implements IOrganizationUsersController
|
|||
if (user.id === userId) {
|
||||
throw new NotAcceptableException('Self archive not allowed');
|
||||
}
|
||||
await this.organizationUsersService.archiveFromAll(userId);
|
||||
await this.organizationUsersService.archiveFromAll(userId, user);
|
||||
return;
|
||||
}
|
||||
|
||||
@InitFeature(FEATURE_KEY.USER_UNARCHIVE_ALL)
|
||||
@Post(':userId/unarchive-all')
|
||||
async unarchiveAll(@User() user: UserEntity, @Param('userId') userId: string) {
|
||||
await this.organizationUsersService.unarchiveUser(userId);
|
||||
await this.organizationUsersService.unarchiveUser(userId, user);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import { UpdateOrgUserDto } from '../dto';
|
|||
export interface IOrganizationUsersService {
|
||||
updateOrgUser(organizationUserId: string, user: User, updateOrgUserDto: UpdateOrgUserDto): Promise<void>;
|
||||
archive(id: string, organizationId: string, user?: User): Promise<void>;
|
||||
archiveFromAll(userId: string): Promise<void>;
|
||||
unarchiveUser(userId: string): Promise<void>;
|
||||
archiveFromAll(userId: string, user: User): Promise<void>;
|
||||
unarchiveUser(userId: string, user: User): Promise<void>;
|
||||
unarchive(user: User, id: string, organizationId: string): Promise<void>;
|
||||
inviteNewUser(currentUser: User, inviteNewUserDto: InviteNewUserDto): Promise<void>;
|
||||
bulkUploadUsers(currentUser: User, fileStream: any, res: Response): Promise<void>;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ import { Response } from 'express';
|
|||
import { UserCsvRow } from './interfaces';
|
||||
import { IOrganizationUsersService } from './interfaces/IService';
|
||||
import { UpdateOrgUserDto } from './dto';
|
||||
import { RequestContext } from '@modules/request-context/service';
|
||||
import { AUDIT_LOGS_REQUEST_CONTEXT_KEY } from '@modules/app/constants';
|
||||
import { Organization } from '@entities/organization.entity';
|
||||
@Injectable()
|
||||
export class OrganizationUsersService implements IOrganizationUsersService {
|
||||
constructor(
|
||||
|
|
@ -38,7 +41,6 @@ export class OrganizationUsersService implements IOrganizationUsersService {
|
|||
|
||||
async updateOrgUser(organizationUserId: string, user: User, updateOrgUserDto: UpdateOrgUserDto) {
|
||||
const { firstName, lastName, addGroups, role, userMetadata } = updateOrgUserDto;
|
||||
|
||||
const organizationUser = await this.organizationUsersRepository.findOne({
|
||||
where: { id: organizationUserId, organizationId: user.organizationId },
|
||||
});
|
||||
|
|
@ -81,35 +83,84 @@ export class OrganizationUsersService implements IOrganizationUsersService {
|
|||
}
|
||||
|
||||
async archive(id: string, organizationId: string, user?: User): Promise<void> {
|
||||
const organizationUser = await this.organizationUsersRepository.findOneOrFail({
|
||||
where: { id, organizationId },
|
||||
relations: ['user'],
|
||||
});
|
||||
await dbTransactionWrap(async (manager: EntityManager) => {
|
||||
const organizationUser = await manager.findOneOrFail(OrganizationUser, {
|
||||
where: { id, organizationId },
|
||||
relations: ['user'],
|
||||
});
|
||||
|
||||
await this.organizationUsersUtilService.throwErrorIfUserIsLastActiveAdmin(organizationUser?.user, organizationId);
|
||||
await this.organizationUsersRepository.update(id, {
|
||||
status: WORKSPACE_USER_STATUS.ARCHIVED,
|
||||
invitationToken: null,
|
||||
await this.organizationUsersUtilService.throwErrorIfUserIsLastActiveAdmin(organizationUser?.user, organizationId);
|
||||
await manager.update(OrganizationUser, id, {
|
||||
status: WORKSPACE_USER_STATUS.ARCHIVED,
|
||||
invitationToken: null,
|
||||
});
|
||||
const organization = await manager.findOne(Organization, {
|
||||
where: { id: organizationUser.organizationId },
|
||||
});
|
||||
const auditLogEntry = {
|
||||
userId: user.id,
|
||||
organizationId: user.defaultOrganizationId,
|
||||
resourceId: user.id,
|
||||
resourceName: organizationUser.user.email,
|
||||
resourceData: {
|
||||
archived_user: {
|
||||
id: organizationUser.userId,
|
||||
email: organizationUser.user.email,
|
||||
first_name: organizationUser.user.firstName,
|
||||
last_name: organizationUser.user.lastName,
|
||||
},
|
||||
archived_user_workspace: {
|
||||
workspace_name: organization.name,
|
||||
workspace_id: organization.id,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
RequestContext.setLocals(AUDIT_LOGS_REQUEST_CONTEXT_KEY, auditLogEntry);
|
||||
});
|
||||
}
|
||||
|
||||
async archiveFromAll(userId: string): Promise<void> {
|
||||
async archiveFromAll(userId: string, user: User): Promise<void> {
|
||||
await dbTransactionWrap(async (manager: EntityManager) => {
|
||||
const archivedUserWorkspaces = await manager.find(OrganizationUser, {
|
||||
where: { userId },
|
||||
relations: ['user'],
|
||||
});
|
||||
await manager.update(
|
||||
OrganizationUser,
|
||||
{ userId },
|
||||
{ status: WORKSPACE_USER_STATUS.ARCHIVED, invitationToken: null }
|
||||
);
|
||||
await this.organizationUsersUtilService.updateUserStatus(userId, USER_STATUS.ARCHIVED, manager);
|
||||
const organizationIds = archivedUserWorkspaces.map((user) => user.organizationId);
|
||||
const auditLogEntry = {
|
||||
userId: user.id,
|
||||
organizationIds: organizationIds,
|
||||
resourceId: user.id,
|
||||
resourceName: archivedUserWorkspaces[0].user.email,
|
||||
resourceData: {
|
||||
archived_user: {
|
||||
id: archivedUserWorkspaces[0].userId,
|
||||
email: archivedUserWorkspaces[0].user.email,
|
||||
first_name: archivedUserWorkspaces[0].user.firstName,
|
||||
last_name: archivedUserWorkspaces[0].user.lastName,
|
||||
},
|
||||
},
|
||||
};
|
||||
RequestContext.setLocals(AUDIT_LOGS_REQUEST_CONTEXT_KEY, auditLogEntry);
|
||||
});
|
||||
}
|
||||
|
||||
async unarchiveUser(userId: string): Promise<void> {
|
||||
async unarchiveUser(userId: string, user: User): Promise<void> {
|
||||
await dbTransactionWrap(async (manager: EntityManager) => {
|
||||
const targetUser = await manager.findOneOrFail(User, {
|
||||
where: { id: userId },
|
||||
select: ['id', 'status', 'invitationToken', 'source'],
|
||||
});
|
||||
const unarchivedUserWorkspaces = await manager.find(OrganizationUser, {
|
||||
where: { userId },
|
||||
relations: ['user'],
|
||||
});
|
||||
const { status, invitationToken } = targetUser;
|
||||
/* Special case. what if the user is archived when the status is invited. we were changing status to active before */
|
||||
const updatedStatus =
|
||||
|
|
@ -117,6 +168,22 @@ export class OrganizationUsersService implements IOrganizationUsersService {
|
|||
await this.organizationUsersUtilService.updateUserStatus(userId, updatedStatus, manager);
|
||||
await this.licenseUserService.validateUser(manager);
|
||||
await this.licenseOrganizationService.validateOrganization(manager);
|
||||
const organizationIds = unarchivedUserWorkspaces.map((user) => user.organizationId);
|
||||
const auditLogEntry = {
|
||||
userId: user.id,
|
||||
organizationIds: organizationIds,
|
||||
resourceId: user.id,
|
||||
resourceName: unarchivedUserWorkspaces[0].user.email,
|
||||
resourceData: {
|
||||
unarchived_user: {
|
||||
id: unarchivedUserWorkspaces[0].userId,
|
||||
email: unarchivedUserWorkspaces[0].user.email,
|
||||
first_name: unarchivedUserWorkspaces[0].user.firstName,
|
||||
last_name: unarchivedUserWorkspaces[0].user.lastName,
|
||||
},
|
||||
},
|
||||
};
|
||||
RequestContext.setLocals(AUDIT_LOGS_REQUEST_CONTEXT_KEY, auditLogEntry);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -144,6 +211,29 @@ export class OrganizationUsersService implements IOrganizationUsersService {
|
|||
|
||||
await this.licenseUserService.validateUser(manager);
|
||||
await this.licenseOrganizationService.validateOrganization(manager);
|
||||
const organization = await manager.findOne(Organization, {
|
||||
where: { id: organizationUser.organizationId },
|
||||
});
|
||||
const auditLogEntry = {
|
||||
userId: user.id,
|
||||
organizationId: user.defaultOrganizationId,
|
||||
resourceId: user.id,
|
||||
resourceName: organizationUser.user.email,
|
||||
resourceData: {
|
||||
unarchived_user: {
|
||||
id: organizationUser.userId,
|
||||
email: organizationUser.user.email,
|
||||
first_name: organizationUser.user.firstName,
|
||||
last_name: organizationUser.user.lastName,
|
||||
},
|
||||
unarchived_user_workspace: {
|
||||
workspace_name: organization.name,
|
||||
workspace_id: organization.id,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
RequestContext.setLocals(AUDIT_LOGS_REQUEST_CONTEXT_KEY, auditLogEntry);
|
||||
});
|
||||
|
||||
if (organizationUser.user.invitationToken) {
|
||||
|
|
@ -160,6 +250,7 @@ export class OrganizationUsersService implements IOrganizationUsersService {
|
|||
sender: user.firstName,
|
||||
},
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { User } from '@entities/user.entity';
|
||||
import { dbTransactionWrap } from '@helpers/database.helper';
|
||||
import { fullName, generateNextNameAndSlug } from '@helpers/utils.helper';
|
||||
import { EntityManager } from 'typeorm';
|
||||
import { EntityManager, In } from 'typeorm';
|
||||
import {
|
||||
getUserStatusAndSource,
|
||||
lifecycleEvents,
|
||||
|
|
@ -31,8 +31,6 @@ import { UserDetailsService } from './services/user-details.service';
|
|||
import { FetchUserResponse, InvitedUserType, RoleUpdate, UserFilterOptions } from './types';
|
||||
import { GroupPermissionsRepository } from '@modules/group-permissions/repository';
|
||||
import { ERROR_HANDLER, ERROR_HANDLER_TITLE } from '@modules/organizations/constants';
|
||||
import { MODULE_INFO } from '@modules/app/constants/module-info';
|
||||
import { MODULES } from '@modules/app/constants/modules';
|
||||
import { INSTANCE_USER_SETTINGS } from '@modules/instance-settings/constants';
|
||||
import { OrganizationRepository } from '@modules/organizations/repository';
|
||||
import * as uuid from 'uuid';
|
||||
|
|
@ -512,11 +510,33 @@ export class OrganizationUsersUtilService implements IOrganizationUsersUtilServi
|
|||
!user || !!user.invitationToken
|
||||
);
|
||||
|
||||
const groupsArray = [];
|
||||
if (inviteNewUserDto.groups && inviteNewUserDto.groups.length > 0) {
|
||||
const groupQuery = {
|
||||
organizationId: currentOrganization.id,
|
||||
id: In(inviteNewUserDto.groups),
|
||||
};
|
||||
const orgGroupPermissions = await this.groupPermissionsRepository.find({
|
||||
where: groupQuery,
|
||||
select: ['id', 'name'],
|
||||
});
|
||||
groupsArray.push(...orgGroupPermissions.map((group) => group.name));
|
||||
}
|
||||
RequestContext.setLocals(AUDIT_LOGS_REQUEST_CONTEXT_KEY, {
|
||||
userId: currentUser.id,
|
||||
organizationId: currentOrganization.id,
|
||||
resourceId: currentOrganization.id,
|
||||
resourceId: updatedUser.id,
|
||||
resourceName: updatedUser.email,
|
||||
resourceData: {
|
||||
invited_user: {
|
||||
id: updatedUser.id,
|
||||
email: updatedUser.email,
|
||||
first_name: updatedUser.firstName,
|
||||
last_name: updatedUser.lastName,
|
||||
role: inviteNewUserDto.role,
|
||||
group: groupsArray,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return organizationUser;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { AbilityFactory } from '@modules/app/ability-factory';
|
|||
import { UserAllPermissions } from '@modules/app/types';
|
||||
import { FEATURE_KEY } from '../constants';
|
||||
import { Plugin } from '@entities/plugin.entity';
|
||||
import { getTooljetEdition } from '@helpers/utils.helper';
|
||||
|
||||
type Subjects = InferSubjects<typeof Plugin> | 'all';
|
||||
export type FeatureAbility = Ability<[FEATURE_KEY, Subjects]>;
|
||||
|
|
@ -16,17 +17,14 @@ export class FeatureAbilityFactory extends AbilityFactory<FEATURE_KEY, Subjects>
|
|||
|
||||
protected defineAbilityFor(can: AbilityBuilder<FeatureAbility>['can'], UserAllPermissions: UserAllPermissions): void {
|
||||
const { superAdmin, isAdmin, isBuilder } = UserAllPermissions;
|
||||
const toolJetEdition = getTooljetEdition();
|
||||
if ((toolJetEdition == 'ee' && superAdmin) || (toolJetEdition !== 'ee' && isAdmin)) {
|
||||
can([FEATURE_KEY.UNINSTALL_PLUGINS, FEATURE_KEY.DELETE], Plugin);
|
||||
}
|
||||
|
||||
if (superAdmin || isAdmin || isBuilder) {
|
||||
// Admin, super admin and Builder can do all operations
|
||||
can(
|
||||
[
|
||||
FEATURE_KEY.INSTALL,
|
||||
FEATURE_KEY.UPDATE,
|
||||
FEATURE_KEY.DELETE,
|
||||
FEATURE_KEY.INSTALL_DEPENDENT_PLUGINS,
|
||||
FEATURE_KEY.UNINSTALL_PLUGINS,
|
||||
FEATURE_KEY.DEPENDENT_PLUGINS,
|
||||
],
|
||||
[FEATURE_KEY.INSTALL, FEATURE_KEY.UPDATE, FEATURE_KEY.INSTALL_DEPENDENT_PLUGINS, FEATURE_KEY.DEPENDENT_PLUGINS],
|
||||
Plugin
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { FilesRepository } from '@modules/files/repository';
|
|||
import { getImportPath } from '@modules/app/constants';
|
||||
import { DynamicModule } from '@nestjs/common';
|
||||
import { FeatureAbilityFactory } from './ability';
|
||||
import { DataSourcesRepository } from '@modules/data-sources/repository';
|
||||
|
||||
export class PluginsModule {
|
||||
static async register(configs: { IS_GET_CONTEXT: boolean }): Promise<DynamicModule> {
|
||||
|
|
@ -13,7 +14,7 @@ export class PluginsModule {
|
|||
return {
|
||||
module: PluginsModule,
|
||||
controllers: [PluginsController],
|
||||
providers: [PluginsService, FilesRepository, PluginsUtilService, FeatureAbilityFactory],
|
||||
providers: [PluginsService, FilesRepository, PluginsUtilService, FeatureAbilityFactory, DataSourcesRepository],
|
||||
exports: [PluginsUtilService],
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { InternalServerErrorException, NotFoundException } from '@nestjs/common';
|
||||
import { BadRequestException, InternalServerErrorException, NotFoundException } from '@nestjs/common';
|
||||
import { CreatePluginDto, UpdatePluginDto } from './dto';
|
||||
import { PluginsUtilService } from './util.service';
|
||||
import { dbTransactionWrap } from '@helpers/database.helper';
|
||||
|
|
@ -10,17 +10,25 @@ import { FilesRepository } from '@modules/files/repository';
|
|||
import { IPluginsService } from './interfaces/IService';
|
||||
import * as path from 'path';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { DataSourcesRepository } from '@modules/data-sources/repository';
|
||||
const fs = require('fs');
|
||||
|
||||
@Injectable()
|
||||
export class PluginsService implements IPluginsService {
|
||||
constructor(
|
||||
protected readonly pluginsUtilService: PluginsUtilService,
|
||||
protected readonly fileRepository: FilesRepository
|
||||
protected readonly fileRepository: FilesRepository,
|
||||
protected readonly dataSourcesRepository: DataSourcesRepository
|
||||
) {}
|
||||
|
||||
async install(body: CreatePluginDto) {
|
||||
const { id, repo } = body;
|
||||
const { id, repo, name } = body;
|
||||
|
||||
const existingPlugin = await dbTransactionWrap((manager: EntityManager) => {
|
||||
return manager.findOne(Plugin, { where: { pluginId: id } });
|
||||
});
|
||||
if (existingPlugin) throw new BadRequestException(`Plugin '${name}' is already installed.`);
|
||||
|
||||
const [index, operations, icon, manifest, version] = await this.pluginsUtilService.fetchPluginFiles(id, repo);
|
||||
let shouldCreate = false;
|
||||
|
||||
|
|
@ -47,7 +55,7 @@ export class PluginsService implements IPluginsService {
|
|||
|
||||
async findOne(id: string) {
|
||||
return dbTransactionWrap((manager: EntityManager) => {
|
||||
return manager.find(Plugin, { where: { id } });
|
||||
return manager.findOne(Plugin, { where: { id } });
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -57,7 +65,18 @@ export class PluginsService implements IPluginsService {
|
|||
return await this.pluginsUtilService.upgrade(id, body, version, { index, operations, icon, manifest });
|
||||
}
|
||||
|
||||
remove(id: string) {
|
||||
async remove(id: string) {
|
||||
const dataSourcesByMarketplacePlugin = await this.dataSourcesRepository.getDatasourceByPluginId(id);
|
||||
if (dataSourcesByMarketplacePlugin.length) {
|
||||
const queries = [];
|
||||
dataSourcesByMarketplacePlugin?.forEach((datasource) => {
|
||||
if (datasource.dataQueries.length) queries.push(...datasource.dataQueries);
|
||||
});
|
||||
if (queries.length) {
|
||||
throw new InternalServerErrorException(`Plugin can't be removed, queries of plugin are in use`);
|
||||
}
|
||||
}
|
||||
|
||||
return dbTransactionWrap((manager: EntityManager) => {
|
||||
return manager.delete(Plugin, id);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,9 +4,18 @@ import { FeaturesConfig } from '../types';
|
|||
|
||||
export const FEATURES: FeaturesConfig = {
|
||||
[MODULES.PROFILE]: {
|
||||
[FEATURE_KEY.UPDATE_AVATAR]: {},
|
||||
[FEATURE_KEY.UPDATE_AVATAR]: {
|
||||
isPublic: true,
|
||||
auditLogsKey: 'USER_PROFILE_UPDATE',
|
||||
},
|
||||
[FEATURE_KEY.GET]: {},
|
||||
[FEATURE_KEY.UPDATE]: {},
|
||||
[FEATURE_KEY.UPDATE_PASSWORD]: {},
|
||||
[FEATURE_KEY.UPDATE]: {
|
||||
isPublic: true,
|
||||
auditLogsKey: 'USER_PROFILE_UPDATE',
|
||||
},
|
||||
[FEATURE_KEY.UPDATE_PASSWORD]: {
|
||||
isPublic: true,
|
||||
auditLogsKey: 'USER_PASSWORD_UPDATE',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import { ProfileUtilService } from '@modules/profile/util.service';
|
|||
import { User } from '@entities/user.entity';
|
||||
import { IProfileService } from '@modules/profile/interfaces/IService';
|
||||
import { File } from '@entities/file.entity';
|
||||
import { RequestContext } from '@modules/request-context/service';
|
||||
import { AUDIT_LOGS_REQUEST_CONTEXT_KEY } from '@modules/app/constants';
|
||||
|
||||
@Injectable()
|
||||
export class ProfileService implements IProfileService {
|
||||
|
|
@ -25,19 +27,76 @@ export class ProfileService implements IProfileService {
|
|||
|
||||
async addAvatar(userId: string, imageBuffer: Buffer, filename: string): Promise<File> {
|
||||
return dbTransactionWrap(async (manager: EntityManager) => {
|
||||
return this.serviceUtils.addAvatar(userId, imageBuffer, filename, manager);
|
||||
const user = await this.userRepository.getUser({
|
||||
id: userId,
|
||||
});
|
||||
const avatar = await this.serviceUtils.addAvatar(userId, imageBuffer, filename, manager);
|
||||
const auditLogData = {
|
||||
userId: user.id,
|
||||
organizationId: user.defaultOrganizationId,
|
||||
resourceId: user.id,
|
||||
resourceName: user.email,
|
||||
resourceData: {
|
||||
previous_user_details: {
|
||||
avatar_id: user.avatarId,
|
||||
},
|
||||
updated_user_details: {
|
||||
avatar_id: avatar.id,
|
||||
},
|
||||
},
|
||||
};
|
||||
RequestContext.setLocals(AUDIT_LOGS_REQUEST_CONTEXT_KEY, auditLogData);
|
||||
return avatar;
|
||||
});
|
||||
}
|
||||
|
||||
async updateUserPassword(userId: string, password: string): Promise<void> {
|
||||
await this.userRepository.updateOne(userId, {
|
||||
password,
|
||||
passwordRetryCount: 0,
|
||||
return dbTransactionWrap(async (manager: EntityManager) => {
|
||||
const user = await manager.findOneOrFail(User, {
|
||||
where: { id: userId },
|
||||
});
|
||||
await this.userRepository.updateOne(
|
||||
userId,
|
||||
{
|
||||
password,
|
||||
passwordRetryCount: 0,
|
||||
},
|
||||
manager
|
||||
);
|
||||
const auditLogEntry = {
|
||||
userId: user.id,
|
||||
organizationId: user.defaultOrganizationId,
|
||||
resourceId: user.id,
|
||||
resourceName: user.email,
|
||||
};
|
||||
RequestContext.setLocals(AUDIT_LOGS_REQUEST_CONTEXT_KEY, auditLogEntry);
|
||||
});
|
||||
}
|
||||
|
||||
async updateUserName(userId: string, updateUserDto: ProfileUpdateDto): Promise<void> {
|
||||
const { first_name: firstName, last_name: lastName } = updateUserDto;
|
||||
await this.userRepository.updateOne(userId, { firstName, lastName });
|
||||
return dbTransactionWrap(async (manager: EntityManager) => {
|
||||
const user = await manager.findOneOrFail(User, {
|
||||
where: { id: userId },
|
||||
});
|
||||
const { first_name: firstName, last_name: lastName } = updateUserDto;
|
||||
await this.userRepository.updateOne(userId, { firstName, lastName }, manager);
|
||||
const auditLogData = {
|
||||
userId: user.id,
|
||||
organizationId: user.defaultOrganizationId,
|
||||
resourceId: user.id,
|
||||
resourceName: user.email,
|
||||
resourceData: {
|
||||
previous_user_details: {
|
||||
first_name: user.firstName,
|
||||
last_name: user.lastName,
|
||||
},
|
||||
updated_user_details: {
|
||||
first_name: firstName,
|
||||
last_name: lastName,
|
||||
},
|
||||
},
|
||||
};
|
||||
RequestContext.setLocals(AUDIT_LOGS_REQUEST_CONTEXT_KEY, auditLogData);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import { CreateFileDto } from '@modules/files/dto/index';
|
|||
|
||||
@Injectable()
|
||||
export class ProfileUtilService implements IProfileUtilService {
|
||||
constructor(protected readonly filesRepository: FilesRepository, protected userRepository: UserRepository) {}
|
||||
constructor(protected readonly filesRepository: FilesRepository, protected readonly userRepository: UserRepository) {}
|
||||
|
||||
async addAvatar(userId: string, imageBuffer: Buffer, filename: string, manager?: EntityManager): Promise<File> {
|
||||
const user = await this.userRepository.getUser({
|
||||
|
|
@ -31,6 +31,7 @@ export class ProfileUtilService implements IProfileUtilService {
|
|||
if (currentAvatarId) {
|
||||
await this.filesRepository.removeOne(currentAvatarId, manager);
|
||||
}
|
||||
|
||||
return avatar;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,10 @@ import { FeaturesConfig } from '../types';
|
|||
|
||||
export const FEATURES: FeaturesConfig = {
|
||||
[MODULES.SESSION]: {
|
||||
[FEATURE_KEY.LOG_OUT]: {},
|
||||
[FEATURE_KEY.LOG_OUT]: {
|
||||
isPublic: true,
|
||||
auditLogsKey: 'USER_LOGOUT',
|
||||
},
|
||||
[FEATURE_KEY.GET_INVITED_USER_SESSION]: {
|
||||
isPublic: true,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ import { OrganizationRepository } from '@modules/organizations/repository';
|
|||
import { OrganizationUsersRepository } from '@modules/organization-users/repository';
|
||||
import { fullName, generateOrgInviteURL, isSuperAdmin } from '@helpers/utils.helper';
|
||||
import { decamelizeKeys } from 'humps';
|
||||
import { RequestContext } from '@modules/request-context/service';
|
||||
import { AUDIT_LOGS_REQUEST_CONTEXT_KEY } from '@modules/app/constants';
|
||||
|
||||
@Injectable()
|
||||
export class SessionService {
|
||||
|
|
@ -34,6 +36,17 @@ export class SessionService {
|
|||
response.clearCookie('tj_auth_token');
|
||||
await dbTransactionWrap(async (manager: EntityManager) => {
|
||||
await manager.delete(UserSessions, { id: sessionId, userId });
|
||||
const user = await manager.findOneOrFail(User, {
|
||||
where: { id: userId },
|
||||
});
|
||||
|
||||
const auditLogData = {
|
||||
userId: user.id,
|
||||
organizationId: user.defaultOrganizationId,
|
||||
resourceId: user.id,
|
||||
resourceName: user.email,
|
||||
};
|
||||
RequestContext.setLocals(AUDIT_LOGS_REQUEST_CONTEXT_KEY, auditLogData);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ export class SessionUtilService {
|
|||
protected readonly encryptionService: EncryptionService,
|
||||
protected readonly jwtService: JwtService
|
||||
) {}
|
||||
|
||||
async terminateAllSessions(userId: string): Promise<void> {
|
||||
await dbTransactionWrap(async (manager: EntityManager) => {
|
||||
await manager.delete(UserSessions, { userId });
|
||||
|
|
@ -333,7 +334,7 @@ export class SessionUtilService {
|
|||
})
|
||||
: null;
|
||||
|
||||
const noWorkspaceAttachedInTheSession = await this.checkUserWorkspaceStatus(user.id) && !isSuperAdmin(user);
|
||||
const noWorkspaceAttachedInTheSession = (await this.checkUserWorkspaceStatus(user.id)) && !isSuperAdmin(user);
|
||||
const isAllWorkspacesArchived = await this.#isAllWorkspacesArchivedBySuperAdmin(user.id);
|
||||
const onboardingFlags = await this.#onboardingFlags(user);
|
||||
const metadata = await this.metadataUtilService.fetchMetadata();
|
||||
|
|
@ -367,7 +368,7 @@ export class SessionUtilService {
|
|||
|
||||
async #onboardingFlags(user: User) {
|
||||
let isFirstUserOnboardingCompleted = true;
|
||||
let isOnboardingCompleted = true;
|
||||
const isOnboardingCompleted = true;
|
||||
// const isOnboardingQuestionsEnabled =
|
||||
// this.configService.get<string>('ENABLE_ONBOARDING_QUESTIONS_FOR_ALL_SIGN_UPS') === 'true';
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,21 @@ import { FeaturesConfig } from '../types';
|
|||
export const FEATURES: FeaturesConfig = {
|
||||
[MODULES.USER]: {
|
||||
[FEATURE_KEY.GET_ALL_USERS]: {},
|
||||
[FEATURE_KEY.UPDATE_USER_TYPE]: {},
|
||||
[FEATURE_KEY.AUTO_UPDATE_USER_PASSWORD]: {},
|
||||
[FEATURE_KEY.CHANGE_USER_PASSWORD]: {},
|
||||
[FEATURE_KEY.UPDATE_USER_TYPE]: {
|
||||
isPublic: true,
|
||||
auditLogsKey: 'USER_DETAILS_UPDATE',
|
||||
},
|
||||
[FEATURE_KEY.UPDATE_USER_TYPE_INSTANCE]: {
|
||||
isPublic: true,
|
||||
auditLogsKey: 'SET_AS_SUPERADMIN',
|
||||
},
|
||||
[FEATURE_KEY.AUTO_UPDATE_USER_PASSWORD]: {
|
||||
isPublic: true,
|
||||
auditLogsKey: 'USER_PASSWORD_RESET',
|
||||
},
|
||||
[FEATURE_KEY.CHANGE_USER_PASSWORD]: {
|
||||
isPublic: true,
|
||||
auditLogsKey: 'USER_PASSWORD_RESET',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,4 +3,5 @@ export enum FEATURE_KEY {
|
|||
UPDATE_USER_TYPE = 'UPDATE_USER_TYPE',
|
||||
AUTO_UPDATE_USER_PASSWORD = 'AUTO_UPDATE_USER_PASSWORD',
|
||||
CHANGE_USER_PASSWORD = 'CHANGE_USER_PASSWORD',
|
||||
UPDATE_USER_TYPE_INSTANCE = 'UPDATE_USER_TYPE_INSTANCE',
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,19 +2,20 @@ import { Controller, NotFoundException } from '@nestjs/common';
|
|||
import { UpdateUserTypeDto } from '@modules/onboarding/dto/user.dto';
|
||||
import { IUserController } from './interfaces/IController';
|
||||
import { ChangePasswordDto } from './dto';
|
||||
import { User } from '@entities/user.entity';
|
||||
|
||||
@Controller('users')
|
||||
export class UsersController implements IUserController {
|
||||
getAllUsers(query: { page?: number; searchText?: string; status?: string }): Promise<any> {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
updateUserType(updateUserTypeDto: UpdateUserTypeDto): Promise<any> {
|
||||
updateUserType(updateUserTypeDto: UpdateUserTypeDto, user: User): Promise<any> {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
autoUpdateUserPassword(userId: string): Promise<{ newPassword: string }> {
|
||||
autoUpdateUserPassword(userId: string, user: User): Promise<{ newPassword: string }> {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
changeUserPassword(userId: string, changePasswordDto: ChangePasswordDto): Promise<void> {
|
||||
changeUserPassword(userId: string, changePasswordDto: ChangePasswordDto, user: User): Promise<void> {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,12 +11,6 @@ export class UpdateUserTypeDto {
|
|||
@MaxLength(100)
|
||||
userId: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
@Transform(({ value }) => sanitizeInput(value))
|
||||
@MaxLength(100)
|
||||
userType: USER_TYPE;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@Transform(({ value }) => sanitizeInput(value))
|
||||
|
|
@ -27,6 +21,19 @@ export class UpdateUserTypeDto {
|
|||
@Transform(({ value }) => sanitizeInput(value))
|
||||
lastName: string;
|
||||
}
|
||||
export class UpdateUserTypeInstanceDto {
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
@Transform(({ value }) => sanitizeInput(value))
|
||||
@MaxLength(100)
|
||||
userId: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
@Transform(({ value }) => sanitizeInput(value))
|
||||
@MaxLength(100)
|
||||
userType: USER_TYPE;
|
||||
}
|
||||
|
||||
@Exclude()
|
||||
export class AllUserResponse {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import { User } from '@entities/user.entity';
|
||||
import { UpdateUserTypeDto, ChangePasswordDto } from '../dto';
|
||||
|
||||
export interface IUserController {
|
||||
getAllUsers(query: { page?: number; searchText?: string; status?: string }): Promise<any>;
|
||||
|
||||
updateUserType(updateUserTypeDto: UpdateUserTypeDto): Promise<any>;
|
||||
updateUserType(updateUserTypeDto: UpdateUserTypeDto, user: User): Promise<any>;
|
||||
|
||||
autoUpdateUserPassword(userId: string): Promise<{ newPassword: string }>;
|
||||
autoUpdateUserPassword(userId: string, user: User): Promise<{ newPassword: string }>;
|
||||
|
||||
changeUserPassword(userId: string, changePasswordDto: ChangePasswordDto): Promise<void>;
|
||||
changeUserPassword(userId: string, changePasswordDto: ChangePasswordDto, user: User): Promise<void>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { User } from '@entities/user.entity';
|
||||
import { AllUserResponse, UpdateUserTypeDto } from '@modules/onboarding/dto/user.dto';
|
||||
|
||||
export interface IUsersService {
|
||||
|
|
@ -6,9 +7,9 @@ export interface IUsersService {
|
|||
users: AllUserResponse[];
|
||||
}>;
|
||||
|
||||
updateUserType(updateUserTypeDto: UpdateUserTypeDto): Promise<void>;
|
||||
updateUserType(updateUserTypeDto: UpdateUserTypeDto, user: User): Promise<void>;
|
||||
|
||||
updatePassword(userId: string, password: string): Promise<void>;
|
||||
updatePassword(userId: string, user: User, password: string): Promise<void>;
|
||||
|
||||
autoUpdateUserPassword(userId: string): Promise<string>;
|
||||
autoUpdateUserPassword(userId: string, user: User): Promise<string>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { DynamicModule } from '@nestjs/common';
|
|||
import { UserRepository } from './repository';
|
||||
import { SessionModule } from '@modules/session/module';
|
||||
import { FeatureAbilityFactory } from './ability';
|
||||
import { OrganizationUsersRepository } from '@modules/organization-users/repository';
|
||||
|
||||
export class UsersModule {
|
||||
static async register(configs?: { IS_GET_CONTEXT: boolean }): Promise<DynamicModule> {
|
||||
|
|
@ -15,7 +16,7 @@ export class UsersModule {
|
|||
module: UsersModule,
|
||||
imports: [await SessionModule.register(configs)],
|
||||
controllers: [UsersController],
|
||||
providers: [UsersService, UserRepository, UsersUtilService, FeatureAbilityFactory],
|
||||
providers: [UsersService, UserRepository, UsersUtilService, FeatureAbilityFactory, OrganizationUsersRepository],
|
||||
exports: [UsersUtilService],
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { AllUserResponse, UpdateUserTypeDto } from '@modules/onboarding/dto/user.dto';
|
||||
import { IUsersService } from '@modules/users/interfaces/IService';
|
||||
import { User } from '@entities/user.entity';
|
||||
|
||||
@Injectable()
|
||||
export class UsersService implements IUsersService {
|
||||
|
|
@ -9,13 +10,13 @@ export class UsersService implements IUsersService {
|
|||
): Promise<{ meta: { total_pages: number; total_count: number; current_page: number }; users: AllUserResponse[] }> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
updateUserType(updateUserTypeDto: UpdateUserTypeDto): Promise<void> {
|
||||
updateUserType(updateUserTypeDto: UpdateUserTypeDto, user: User): Promise<void> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
updatePassword(userId: string, password: string): Promise<void> {
|
||||
updatePassword(userId: string, user: User, password: string): Promise<void> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
autoUpdateUserPassword(userId: string): Promise<string> {
|
||||
autoUpdateUserPassword(userId: string, user: User): Promise<string> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ interface Features {
|
|||
[FEATURE_KEY.UPDATE_USER_TYPE]: FeatureConfig;
|
||||
[FEATURE_KEY.AUTO_UPDATE_USER_PASSWORD]: FeatureConfig;
|
||||
[FEATURE_KEY.CHANGE_USER_PASSWORD]: FeatureConfig;
|
||||
[FEATURE_KEY.UPDATE_USER_TYPE_INSTANCE]: FeatureConfig;
|
||||
}
|
||||
|
||||
export interface FeaturesConfig {
|
||||
|
|
|
|||
Loading…
Reference in a new issue