From 59cb8150af76d71b7fa589d412f704990cc944bd Mon Sep 17 00:00:00 2001 From: Akiff Manji Date: Mon, 7 Oct 2024 17:21:59 +0000 Subject: [PATCH 01/15] feat: docker compose config for promtail, grafana and loki services Signed-off-by: Akiff Manji --- scripts/README.md | 2 +- scripts/configs/promtail.yml | 84 +++++++++++++++++++++++++++++++++ scripts/docker-compose.logs.yml | 62 ++++++++++++++++++++++++ scripts/docker-compose.yml | 16 +++++++ 4 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 scripts/configs/promtail.yml create mode 100644 scripts/docker-compose.logs.yml diff --git a/scripts/README.md b/scripts/README.md index bc4fd27bf..26512bfe2 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -129,7 +129,7 @@ docker build -f ./Dockerfile --tag traction:plugins-acapy .. cd ../../services/aca-py docker build -f ./Dockerfile.acapy --tag traction:traction-agent . cd ../../scripts -docker compose up +docker compose -f docker-compose.logs.yml -f docker-compose.yml up ``` If there are still errors, try turning buildkit off. In the terminal where you are running your builds: diff --git a/scripts/configs/promtail.yml b/scripts/configs/promtail.yml new file mode 100644 index 000000000..72d0111ea --- /dev/null +++ b/scripts/configs/promtail.yml @@ -0,0 +1,84 @@ +server: + http_listen_address: 0.0.0.0 + http_listen_port: 9080 + +positions: + filename: /tmp/positions.yaml + +clients: + - url: http://loki:3100/loki/api/v1/push + +scrape_configs: + - job_name: system + static_configs: + - targets: + - localhost + labels: + job: varlogs + __path__: /var/log/*log + + - job_name: journal + journal: + json: false + max_age: 12h + path: /var/log/journal + # matches: _syslog_identifier=dockerd + labels: + job: systemd-journal + relabel_configs: + - source_labels: + - __journal__systemd_unit + target_label: systemd_unit + - source_labels: + - __journal__hostname + target_label: hostname + - source_labels: + - __journal_syslog_identifier + target_label: syslog_identifier + - source_labels: + - __journal__transport + target_label: transport + + - job_name: containers + static_configs: + - targets: + - localhost + labels: + job: containerlogs + __path__: /var/lib/docker/containers/*/*log + + # --log-opt tag="{{.Name}}" + pipeline_stages: + + - json: + expressions: + stream: stream + attrs: attrs + tag: attrs.tag + + - regex: + expression: (?P(?:[^|]*[^|])) + source: "tag" + + - labels: + tag: + stream: + container_name: + + - job_name: flog_scrape + docker_sd_configs: + - host: unix:///var/run/docker.sock + refresh_interval: 5s + filters: + - name: name + values: [flog] + relabel_configs: + - source_labels: ['__meta_docker_container_name'] + regex: '/(.*)\.[0-9]\..*' + target_label: 'name' + - source_labels: ['__meta_docker_container_name'] + regex: '/(.*)\.[0-9a-z]*\..*' + target_label: 'name' + - source_labels: ['__meta_docker_container_name'] + regex: '/.*\.([0-9]{1,2})\..*' + target_label: 'replica' diff --git a/scripts/docker-compose.logs.yml b/scripts/docker-compose.logs.yml new file mode 100644 index 000000000..0c6756bca --- /dev/null +++ b/scripts/docker-compose.logs.yml @@ -0,0 +1,62 @@ +version: "3.9" + +x-logging: &default-logging + driver: loki + options: + loki-url: http://localhost:3100/loki/api/v1/push + loki-retries: 5 + loki-batch-size: 400 + +services: + loki: + image: grafana/loki:2.9.2 + ports: + - "3100:3100" + command: -config.file=/etc/loki/local-config.yaml + logging: *default-logging + networks: + - loki + + promtail: + image: grafana/promtail:2.9.2 + volumes: + - /var/log:/var/log + - /var/lib/docker/containers:/var/lib/docker/containers + - ./configs/promtail.yml:/etc/promtail/config.yml + command: -config.file=/etc/promtail/config.yml + networks: + - loki + + grafana: + environment: + - GF_PATHS_PROVISIONING=/etc/grafana/provisioning + - GF_AUTH_ANONYMOUS_ENABLED=true + - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin + logging: *default-logging + entrypoint: + - sh + - -euc + - | + mkdir -p /etc/grafana/provisioning/datasources + cat < /etc/grafana/provisioning/datasources/ds.yaml + apiVersion: 1 + datasources: + - name: Loki + type: loki + access: proxy + orgId: 1 + url: http://loki:3100 + basicAuth: false + isDefault: true + version: 1 + editable: false + EOF + /run.sh + image: grafana/grafana:latest + ports: + - "3000:3000" + networks: + - loki + +networks: + loki: \ No newline at end of file diff --git a/scripts/docker-compose.yml b/scripts/docker-compose.yml index 0f58e6837..86b1cde91 100755 --- a/scripts/docker-compose.yml +++ b/scripts/docker-compose.yml @@ -1,7 +1,15 @@ version: "3.12" +x-logging: &default-logging + driver: loki + options: + loki-url: http://localhost:3100/loki/api/v1/push + loki-retries: 5 + loki-batch-size: 400 + services: ngrok-traction-agent: image: ngrok/ngrok + logging: *default-logging environment: - NGROK_AUTHTOKEN=${NGROK_AUTHTOKEN} - TRACTION_ACAPY_HTTP_PORT=${TRACTION_ACAPY_HTTP_PORT} @@ -11,6 +19,7 @@ services: traction-acapy-image-builder: pull_policy: missing + logging: *default-logging build: context: ../plugins dockerfile: ./docker/Dockerfile @@ -24,6 +33,7 @@ services: context: ../services/aca-py dockerfile: Dockerfile.acapy image: traction:traction-agent + logging: *default-logging depends_on: traction-acapy-image-builder: condition: service_started @@ -95,6 +105,7 @@ services: traction-db: image: "postgres:14.5" + logging: *default-logging environment: - POSTGRES_USER=${POSTGRESQL_USER} - POSTGRES_PASSWORD=${POSTGRESQL_PASSWORD} @@ -113,6 +124,7 @@ services: tenant-ui: pull_policy: missing + logging: *default-logging build: context: ../services/tenant-ui dockerfile: Dockerfile @@ -146,6 +158,7 @@ services: tenant-proxy: pull_policy: missing + logging: *default-logging build: context: ../plugins dockerfile: ./docker/Dockerfile.tenant-proxy @@ -167,6 +180,7 @@ services: depends_on: endorser-db: condition: service_healthy + logging: *default-logging ports: - ${ACAPY_ENDORSER_ADMIN_PORT}:${ACAPY_ENDORSER_ADMIN_PORT} - ${ACAPY_ENDORSER_HTTP_PORT}:${ACAPY_ENDORSER_HTTP_PORT} @@ -209,6 +223,7 @@ services: depends_on: endorser-db: condition: service_healthy + logging: *default-logging ports: - ${ACAPY_ENDORSER_1_ADMIN_PORT}:${ACAPY_ENDORSER_1_ADMIN_PORT} - ${ACAPY_ENDORSER_1_HTTP_PORT}:${ACAPY_ENDORSER_1_HTTP_PORT} @@ -248,6 +263,7 @@ services: endorser-db: image: "postgres:14.5" + logging: *default-logging environment: - POSTGRES_USER=${POSTGRESQL_USER} - POSTGRES_PASSWORD=${POSTGRESQL_PASSWORD} From 61ee80303159d30c19674949d60fd90bf6fca6aa Mon Sep 17 00:00:00 2001 From: Akiff Manji Date: Mon, 7 Oct 2024 17:22:39 +0000 Subject: [PATCH 02/15] feat: websocket package Signed-off-by: Akiff Manji --- services/tenant-ui/package-lock.json | 48 +++++++++++++++++++++++++++- services/tenant-ui/package.json | 4 ++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/services/tenant-ui/package-lock.json b/services/tenant-ui/package-lock.json index 4ca5d97a4..78f77d86c 100644 --- a/services/tenant-ui/package-lock.json +++ b/services/tenant-ui/package-lock.json @@ -18,7 +18,8 @@ "express-oauth-jwt": "^2.0.2", "express-validator": "^7.2.0", "jose": "^5.8.0", - "nodemailer": "^6.9.15" + "nodemailer": "^6.9.15", + "ws": "^8.18.0" }, "devDependencies": { "@types/config": "^3.3.5", @@ -27,6 +28,7 @@ "@types/express": "^4.17.21", "@types/jest": "^29.5.13", "@types/node": "^22.7.2", + "@types/ws": "^8.5.12", "@types/nodemailer": "^6.4.16", "@typescript-eslint/eslint-plugin": "^8.7.0", "@typescript-eslint/parser": "^8.7.0", @@ -1863,6 +1865,15 @@ "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", "dev": true }, + "node_modules/@types/ws": { + "version": "8.5.12", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", + "integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/yargs": { "version": "17.0.24", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", @@ -6712,6 +6723,26 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -8242,6 +8273,15 @@ "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", "dev": true }, + "@types/ws": { + "version": "8.5.12", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", + "integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/yargs": { "version": "17.0.24", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", @@ -11643,6 +11683,12 @@ "signal-exit": "^3.0.7" } }, + "ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "requires": {} + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/services/tenant-ui/package.json b/services/tenant-ui/package.json index 9c19c2ab5..5f53cc1ff 100644 --- a/services/tenant-ui/package.json +++ b/services/tenant-ui/package.json @@ -24,7 +24,8 @@ "express-oauth-jwt": "^2.0.2", "express-validator": "^7.2.0", "jose": "^5.8.0", - "nodemailer": "^6.9.15" + "nodemailer": "^6.9.15", + "ws": "^8.18.0" }, "devDependencies": { "@types/config": "^3.3.5", @@ -34,6 +35,7 @@ "@types/jest": "^29.5.13", "@types/node": "^22.7.2", "@types/nodemailer": "^6.4.16", + "@types/ws": "^8.5.12", "@typescript-eslint/eslint-plugin": "^8.7.0", "@typescript-eslint/parser": "^8.7.0", "eslint": "^8.57.0", From 803955d17d0c23640bfaf22580ff85a20628c61b Mon Sep 17 00:00:00 2001 From: Akiff Manji Date: Mon, 7 Oct 2024 17:21:22 +0000 Subject: [PATCH 03/15] feat: API websocket support Signed-off-by: Akiff Manji --- services/tenant-ui/src/index.ts | 16 ++-- services/tenant-ui/src/services/log-stream.ts | 90 +++++++++++++++++++ 2 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 services/tenant-ui/src/services/log-stream.ts diff --git a/services/tenant-ui/src/index.ts b/services/tenant-ui/src/index.ts index f85869197..c9bac99d7 100644 --- a/services/tenant-ui/src/index.ts +++ b/services/tenant-ui/src/index.ts @@ -5,19 +5,21 @@ import path from "path"; import { router } from "./routes/router"; +import { configureLogStream } from "./services/log-stream"; + const PORT: number = parseInt(config.get("server.port") as string, 10); -const APIROOT: string = config.get("server.apiPath"); +const API_ROOT: string = config.get("server.apiPath"); const STATIC_FILES_PATH: string = config.get("server.staticFiles"); import history from "connect-history-api-fallback"; const app = express(); + app.use(history()); app.use(cors()); app.use(express.json()); app.use(express.urlencoded({ extended: true })); - // Host the static frontend assets app.use("/favicon.ico", (_, res) => { res.redirect("/favicon.ico"); @@ -46,8 +48,10 @@ app.use("/config", (_, res, next) => { }); // This service's api endpoints -app.use(APIROOT, router); +app.use(API_ROOT, router); -app.listen(PORT, () => { - console.log(`Listening on port ${PORT}`); -}); +configureLogStream( + app.listen(PORT, () => { + console.log(`Listening on port ${PORT}`); + }) +); diff --git a/services/tenant-ui/src/services/log-stream.ts b/services/tenant-ui/src/services/log-stream.ts new file mode 100644 index 000000000..8648c0885 --- /dev/null +++ b/services/tenant-ui/src/services/log-stream.ts @@ -0,0 +1,90 @@ +import { Server } from "http"; +import WebSocket from "ws"; + +const WEBSOCKET_URL = "ws://host.docker.internal:3100/loki/api/v1/tail"; + +const wss = new WebSocket.Server({ noServer: true }); + +const handleLokiWebSocket = (tenantId: string, ws: WebSocket) => { + const loki = new WebSocket( + `${WEBSOCKET_URL}?query={container_name="scripts-traction-agent-1"} |= \`${tenantId}\`` + ); + + loki.on("open", () => { + console.log(`Loki websocket established for Tenant ID: ${tenantId}`); + }); + + loki.on("message", (message) => { + if (ws?.readyState === WebSocket.OPEN) { + ws.send(message.toString()); + } + }); + + loki.on("error", (err) => { + console.error(`Loki websocket for Tenant ID: ${tenantId} error: ${err}`); + if (ws?.readyState === WebSocket.OPEN) { + ws.close(); + } + }); + + loki.on("close", () => { + console.log(`Loki websocket closed for Tenant ID: ${tenantId}`); + if (ws?.readyState === WebSocket.OPEN) { + ws.close(); + } + }); + + return loki; +}; + +const handleTenantWebSocket = ( + tenantId: string, + ws: WebSocket, + loki: WebSocket +): void => { + ws.on("open", () => { + console.log(`Tenant websocket established for Tenant ID: ${tenantId}`); + }); + + ws.on("error", (err) => { + console.error(`Tenant webSocket for Tenant ID: ${tenantId} error: ${err}`); + if (loki?.readyState === WebSocket.OPEN) { + loki.close(); + } + }); + + ws.on("close", () => { + console.log(`Tenant websocket closed for Tenant ID: ${tenantId}`); + if (loki?.readyState === WebSocket.OPEN) { + loki.close(); + } + }); +}; + +export const configureLogStream = (server: Server): void => { + server.on("upgrade", (req, socket, head) => { + socket.on("error", (err) => { + // Socket pre-error + console.error(`Socket error: ${err}`); + }); + + // TODO: Perform token auth here + + wss.handleUpgrade(req, socket, head, (ws) => { + socket.removeListener("error", (err) => { + // Socket post-error + console.error(`Socket error: ${err}`); + }); + + wss.emit("connection", ws, req); + }); + }); + + wss.on("connection", (ws, req) => { + // TODO: The Tenant ID should be extracted from the token + // const tenantId = req.headers["x-tenant-id"] as string; + const tenantId = "innkeeper"; + const loki = handleLokiWebSocket(tenantId, ws); + handleTenantWebSocket(tenantId, ws, loki); + }); +}; From d43478b148dabde48c34587646b5622af7e6fc1a Mon Sep 17 00:00:00 2001 From: Akiff Manji Date: Mon, 7 Oct 2024 17:22:25 +0000 Subject: [PATCH 04/15] update: vscode settings Signed-off-by: Akiff Manji --- services/tenant-ui/.vscode/launch.json | 17 ++++------------- services/tenant-ui/.vscode/settings.json | 2 +- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/services/tenant-ui/.vscode/launch.json b/services/tenant-ui/.vscode/launch.json index e377e1d13..bbbc3ce67 100644 --- a/services/tenant-ui/.vscode/launch.json +++ b/services/tenant-ui/.vscode/launch.json @@ -7,10 +7,7 @@ { "name": "backend - run dev", "request": "launch", - "runtimeArgs": [ - "run-script", - "dev" - ], + "runtimeArgs": ["run-script", "dev"], "runtimeExecutable": "npm", "skipFiles": [], "type": "node", @@ -19,11 +16,8 @@ { "name": "frontend - run dev", "request": "launch", - "cwd":"${workspaceFolder}/frontend", - "runtimeArgs": [ - "run-script", - "dev" - ], + "cwd": "${workspaceFolder}/frontend", + "runtimeArgs": ["run-script", "dev", "--", "--host"], "runtimeExecutable": "npm", "skipFiles": [], "type": "node", @@ -39,9 +33,6 @@ "sourceMapPathOverrides": { "webpack:///./src/*": "${webRoot}/*" } - }, - - - + } ] } diff --git a/services/tenant-ui/.vscode/settings.json b/services/tenant-ui/.vscode/settings.json index 3ac254036..8fa4bc8ab 100644 --- a/services/tenant-ui/.vscode/settings.json +++ b/services/tenant-ui/.vscode/settings.json @@ -1,7 +1,7 @@ { "editor.formatOnSave": true, "editor.codeActionsOnSave": { - "source.fixAll.eslint": true + "source.fixAll.eslint": "explicit" }, "prettier.enable": true, "[javascript]": { From bfddbb0b915f8e9cd1d37a6bfd7c555898f8bb4d Mon Sep 17 00:00:00 2001 From: Akiff Manji Date: Wed, 9 Oct 2024 14:58:41 +0000 Subject: [PATCH 05/15] feat: add jwonwebtoken package Signed-off-by: Akiff Manji --- services/tenant-ui/package-lock.json | 208 ++++++++++++++++++++++++++- services/tenant-ui/package.json | 2 + 2 files changed, 207 insertions(+), 3 deletions(-) diff --git a/services/tenant-ui/package-lock.json b/services/tenant-ui/package-lock.json index 78f77d86c..88de22182 100644 --- a/services/tenant-ui/package-lock.json +++ b/services/tenant-ui/package-lock.json @@ -18,6 +18,7 @@ "express-oauth-jwt": "^2.0.2", "express-validator": "^7.2.0", "jose": "^5.8.0", + "jsonwebtoken": "^9.0.2", "nodemailer": "^6.9.15", "ws": "^8.18.0" }, @@ -27,6 +28,7 @@ "@types/cors": "^2.8.17", "@types/express": "^4.17.21", "@types/jest": "^29.5.13", + "@types/jsonwebtoken": "^9.0.7", "@types/node": "^22.7.2", "@types/ws": "^8.5.12", "@types/nodemailer": "^6.4.16", @@ -1788,6 +1790,15 @@ "pretty-format": "^29.0.0" } }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.7.tgz", + "integrity": "sha512-ugo316mmTYBl2g81zDFnZ7cfxlut3o+/EQdaP7J8QN2kY6lJ22hmQYCK5EHcJHbrW+dkCGSCPgbG8JtYj6qSrg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/mime": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", @@ -2548,6 +2559,11 @@ "node-int64": "^0.4.0" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -3005,6 +3021,14 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -4946,6 +4970,51 @@ "node": ">=6" } }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -5012,6 +5081,36 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -5024,6 +5123,11 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -5923,7 +6027,6 @@ "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -8199,6 +8302,15 @@ "pretty-format": "^29.0.0" } }, + "@types/jsonwebtoken": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.7.tgz", + "integrity": "sha512-ugo316mmTYBl2g81zDFnZ7cfxlut3o+/EQdaP7J8QN2kY6lJ22hmQYCK5EHcJHbrW+dkCGSCPgbG8JtYj6qSrg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/mime": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", @@ -8738,6 +8850,11 @@ "node-int64": "^0.4.0" } }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -9052,6 +9169,14 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -10475,6 +10600,49 @@ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" }, + "jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "dependencies": { + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -10526,6 +10694,36 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -10538,6 +10736,11 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -11141,8 +11344,7 @@ "semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==" }, "send": { "version": "0.19.0", diff --git a/services/tenant-ui/package.json b/services/tenant-ui/package.json index 5f53cc1ff..8ca0c296d 100644 --- a/services/tenant-ui/package.json +++ b/services/tenant-ui/package.json @@ -24,6 +24,7 @@ "express-oauth-jwt": "^2.0.2", "express-validator": "^7.2.0", "jose": "^5.8.0", + "jsonwebtoken": "^9.0.2", "nodemailer": "^6.9.15", "ws": "^8.18.0" }, @@ -33,6 +34,7 @@ "@types/cors": "^2.8.17", "@types/express": "^4.17.21", "@types/jest": "^29.5.13", + "@types/jsonwebtoken": "^9.0.7", "@types/node": "^22.7.2", "@types/nodemailer": "^6.4.16", "@types/ws": "^8.5.12", From 504056ffb15a4403e562f4a3d1502e61db4f1f6d Mon Sep 17 00:00:00 2001 From: Akiff Manji Date: Wed, 9 Oct 2024 15:01:22 +0000 Subject: [PATCH 06/15] feat: API websocket token authentication Signed-off-by: Akiff Manji --- services/tenant-ui/src/routes/router.ts | 1 + services/tenant-ui/src/services/log-stream.ts | 91 ++++++++++++++----- 2 files changed, 71 insertions(+), 21 deletions(-) diff --git a/services/tenant-ui/src/routes/router.ts b/services/tenant-ui/src/routes/router.ts index 2a453f2de..9abd15ad6 100644 --- a/services/tenant-ui/src/routes/router.ts +++ b/services/tenant-ui/src/routes/router.ts @@ -83,6 +83,7 @@ router.post( } } ); + router.post( "/email/reservationStatus", body("contactEmail").isEmail(), diff --git a/services/tenant-ui/src/services/log-stream.ts b/services/tenant-ui/src/services/log-stream.ts index 8648c0885..0fd06da4d 100644 --- a/services/tenant-ui/src/services/log-stream.ts +++ b/services/tenant-ui/src/services/log-stream.ts @@ -1,10 +1,57 @@ -import { Server } from "http"; +import { IncomingMessage, Server } from "http"; +import axios from "axios"; +import config from "config"; +import jwt from "jsonwebtoken"; import WebSocket from "ws"; const WEBSOCKET_URL = "ws://host.docker.internal:3100/loki/api/v1/tail"; +// const TRACTION_URL: string = config.get("server.tractionUrl"); +const TRACTION_URL = "http://host.docker.internal:8032"; const wss = new WebSocket.Server({ noServer: true }); +const getTenant = async (token: string): Promise => { + const response = await axios.get(`${TRACTION_URL}/tenant`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }); + return response.data; +}; + +const parseToken = (url: URL): string | null => { + const token = url.searchParams.get("token"); + return token; +}; + +const authenticateTenant = async ( + req: IncomingMessage +): Promise => { + const token = parseToken( + new URL(req.url as string, `http://${req.headers.host}`) + ); + + if (!token) { + throw new Error("Unauthorized: No token provided"); + } + + const decodedToken = jwt.decode(token, { complete: true }); + if (!decodedToken) { + throw new Error("Unauthorized: Invalid token"); + } + + const tenant = await getTenant(token); + if (!tenant) { + throw new Error("Unauthorized: Tenant not found"); + } + + return tenant; +}; + +const logError = (err: Error) => { + console.error(`Error: ${err}`); +}; + const handleLokiWebSocket = (tenantId: string, ws: WebSocket) => { const loki = new WebSocket( `${WEBSOCKET_URL}?query={container_name="scripts-traction-agent-1"} |= \`${tenantId}\`` @@ -62,28 +109,30 @@ const handleTenantWebSocket = ( }; export const configureLogStream = (server: Server): void => { - server.on("upgrade", (req, socket, head) => { - socket.on("error", (err) => { - // Socket pre-error - console.error(`Socket error: ${err}`); - }); - - // TODO: Perform token auth here - - wss.handleUpgrade(req, socket, head, (ws) => { - socket.removeListener("error", (err) => { - // Socket post-error - console.error(`Socket error: ${err}`); + server.on( + "upgrade", + async (req: IncomingMessage & { tenant: any }, socket, head) => { + // Socket pre upgrade + socket.on("error", logError); + + try { + req.tenant = await authenticateTenant(req); + } catch (err: any | Error) { + socket.write(`HTTP/1.1 401 ${err.message}\r\n\r\n`); + socket.destroy(); + return; + } + + wss.handleUpgrade(req, socket, head, (ws) => { + // Socket post upgrade + socket.removeListener("error", logError); + wss.emit("connection", ws, req); }); + } + ); - wss.emit("connection", ws, req); - }); - }); - - wss.on("connection", (ws, req) => { - // TODO: The Tenant ID should be extracted from the token - // const tenantId = req.headers["x-tenant-id"] as string; - const tenantId = "innkeeper"; + wss.on("connection", (ws, req: IncomingMessage & { tenant: any }) => { + const { tenant_id: tenantId = null } = req.tenant; const loki = handleLokiWebSocket(tenantId, ws); handleTenantWebSocket(tenantId, ws, loki); }); From bbe65917cb6db2129d8678d889ce9e1617589c50 Mon Sep 17 00:00:00 2001 From: Akiff Manji Date: Wed, 9 Oct 2024 15:01:58 +0000 Subject: [PATCH 07/15] feat: log store and component Signed-off-by: Akiff Manji --- .../src/components/layout/Sidebar.vue | 6 ++ .../components/layout/innkeeper/Sidebar.vue | 5 + .../frontend/src/plugins/i18n/locales/en.json | 5 +- .../frontend/src/plugins/i18n/locales/fr.json | 3 + .../frontend/src/plugins/i18n/locales/ja.json | 3 + .../frontend/src/router/innkeeperRoutes.ts | 8 ++ .../frontend/src/router/tenantRoutes.ts | 9 ++ .../tenant-ui/frontend/src/store/index.ts | 4 + .../tenant-ui/frontend/src/store/logStore.ts | 97 +++++++++++++++++++ services/tenant-ui/frontend/src/views/Log.vue | 97 +++++++++++++++++++ 10 files changed, 236 insertions(+), 1 deletion(-) create mode 100644 services/tenant-ui/frontend/src/store/logStore.ts create mode 100644 services/tenant-ui/frontend/src/views/Log.vue diff --git a/services/tenant-ui/frontend/src/components/layout/Sidebar.vue b/services/tenant-ui/frontend/src/components/layout/Sidebar.vue index 053c41503..9b706fd22 100644 --- a/services/tenant-ui/frontend/src/components/layout/Sidebar.vue +++ b/services/tenant-ui/frontend/src/components/layout/Sidebar.vue @@ -103,5 +103,11 @@ const items = ref([ icon: 'pi pi-fw pi-question-circle', route: '/about', }, + + { + label: t('log.log'), + icon: 'pi pi-fw pi-file', + route: '/log', + }, ]); diff --git a/services/tenant-ui/frontend/src/components/layout/innkeeper/Sidebar.vue b/services/tenant-ui/frontend/src/components/layout/innkeeper/Sidebar.vue index 85d671f56..fb3f52565 100644 --- a/services/tenant-ui/frontend/src/components/layout/innkeeper/Sidebar.vue +++ b/services/tenant-ui/frontend/src/components/layout/innkeeper/Sidebar.vue @@ -59,6 +59,11 @@ const items = ref([ icon: 'pi pi-fw pi-question-circle', route: ROOT + 'about', }, + { + label: t('log.log'), + icon: 'pi pi-fw pi-file', + route: ROOT + 'log', + }, ]); From da4c6228e1d958c5a0f289c0dec2476a433c4a5d Mon Sep 17 00:00:00 2001 From: Akiff Manji Date: Wed, 9 Oct 2024 08:20:54 -0700 Subject: [PATCH 08/15] chore: update test snapshots Signed-off-by: Akiff Manji --- .../layout/__snapshots__/Sidebar.test.ts.snap | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/services/tenant-ui/frontend/test/components/layout/__snapshots__/Sidebar.test.ts.snap b/services/tenant-ui/frontend/test/components/layout/__snapshots__/Sidebar.test.ts.snap index b86b0a413..dbc722b41 100644 --- a/services/tenant-ui/frontend/test/components/layout/__snapshots__/Sidebar.test.ts.snap +++ b/services/tenant-ui/frontend/test/components/layout/__snapshots__/Sidebar.test.ts.snap @@ -160,6 +160,18 @@ exports[`Sidebar > mount matches snapshot with expected values 1`] = ` +
+ + + + +
" `; From 19b03fc0ce700123c44e324448b5cb74ca6eb137 Mon Sep 17 00:00:00 2001 From: Akiff Manji Date: Wed, 9 Oct 2024 15:58:50 +0000 Subject: [PATCH 09/15] chore: suppress unrelated ts build error Signed-off-by: Akiff Manji --- services/tenant-ui/src/routes/router.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/services/tenant-ui/src/routes/router.ts b/services/tenant-ui/src/routes/router.ts index 9abd15ad6..443373d56 100644 --- a/services/tenant-ui/src/routes/router.ts +++ b/services/tenant-ui/src/routes/router.ts @@ -22,6 +22,7 @@ router.use(express.json()); // For the secured innkeepr OIDC login request to verify the token and get a token from Traction router.get( "/innkeeperLogin", + // @ts-ignore secure(jwksService), async (req: any, res: Response, next: NextFunction) => { try { From 592789b2f64923fa1cb8341f85ed60b13038a44a Mon Sep 17 00:00:00 2001 From: Akiff Manji Date: Wed, 9 Oct 2024 16:22:29 +0000 Subject: [PATCH 10/15] chore: parameterize URLs Signed-off-by: Akiff Manji --- .../tenant-ui/config/custom-environment-variables.json | 3 ++- services/tenant-ui/config/default.json | 3 ++- services/tenant-ui/frontend/src/store/logStore.ts | 7 +++++-- services/tenant-ui/src/routes/router.ts | 2 +- services/tenant-ui/src/services/log-stream.ts | 7 +++---- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/services/tenant-ui/config/custom-environment-variables.json b/services/tenant-ui/config/custom-environment-variables.json index 3c7ae398a..f4a686d84 100644 --- a/services/tenant-ui/config/custom-environment-variables.json +++ b/services/tenant-ui/config/custom-environment-variables.json @@ -46,6 +46,7 @@ }, "server": { "tractionUrl": "SERVER_TRACTION_URL", + "lokiUrl": "SERVER_LOKI_URL", "oidc": { "jwksUri": "SERVER_OIDC_JWKS", "realm": "SERVER_OIDC_REALM", @@ -65,4 +66,4 @@ "innkeeperInbox": "SERVER_SMTP_INNKEEPER_INBOX" } } -} +} \ No newline at end of file diff --git a/services/tenant-ui/config/default.json b/services/tenant-ui/config/default.json index 09c920a78..ce1bd8ad3 100644 --- a/services/tenant-ui/config/default.json +++ b/services/tenant-ui/config/default.json @@ -54,6 +54,7 @@ "port": "8080", "staticFiles": "../../frontend/dist", "tractionUrl": "http://localhost:5100", + "lokiUrl": "ws://localhost:3100", "oidc": { "jwksUri": "https://dev.loginproxy.gov.bc.ca/auth/realms/digitaltrust-citz/protocol/openid-connect/certs", "realm": "digitaltrust-citz", @@ -73,4 +74,4 @@ "innkeeperInbox": "lucas.o'neil@gov.bc.ca" } } -} +} \ No newline at end of file diff --git a/services/tenant-ui/frontend/src/store/logStore.ts b/services/tenant-ui/frontend/src/store/logStore.ts index b1018a953..04aeab9a1 100644 --- a/services/tenant-ui/frontend/src/store/logStore.ts +++ b/services/tenant-ui/frontend/src/store/logStore.ts @@ -1,6 +1,6 @@ import { defineStore } from 'pinia'; import { Ref, ref } from 'vue'; -import { useTokenStore } from './tokenStore'; +import { useConfigStore, useTokenStore } from '@/store'; export enum LogStreamState { OPEN, @@ -13,6 +13,7 @@ export enum LogOrder { } export const useLogStore = defineStore('log', () => { + const { config } = useConfigStore(); const { token } = useTokenStore(); const logStream: Ref = ref(null); @@ -41,7 +42,9 @@ export const useLogStore = defineStore('log', () => { throw new Error('No token available to start log stream'); } if (!logStream.value) { - logStream.value = new WebSocket('ws://localhost:8080?token=' + token); + logStream.value = new WebSocket( + `${config.server.lokiUrl}?token=${token}` + ); logStream.value.onopen = () => { logStreamState.value = LogStreamState.OPEN; }; diff --git a/services/tenant-ui/src/routes/router.ts b/services/tenant-ui/src/routes/router.ts index 443373d56..b165062c8 100644 --- a/services/tenant-ui/src/routes/router.ts +++ b/services/tenant-ui/src/routes/router.ts @@ -22,7 +22,7 @@ router.use(express.json()); // For the secured innkeepr OIDC login request to verify the token and get a token from Traction router.get( "/innkeeperLogin", - // @ts-ignore + // @ts-expect-error: secure function is not typed correctly secure(jwksService), async (req: any, res: Response, next: NextFunction) => { try { diff --git a/services/tenant-ui/src/services/log-stream.ts b/services/tenant-ui/src/services/log-stream.ts index 0fd06da4d..1de7a9a3d 100644 --- a/services/tenant-ui/src/services/log-stream.ts +++ b/services/tenant-ui/src/services/log-stream.ts @@ -4,9 +4,8 @@ import config from "config"; import jwt from "jsonwebtoken"; import WebSocket from "ws"; -const WEBSOCKET_URL = "ws://host.docker.internal:3100/loki/api/v1/tail"; -// const TRACTION_URL: string = config.get("server.tractionUrl"); -const TRACTION_URL = "http://host.docker.internal:8032"; +const LOKI_URL: string = config.get("server.lokiUrl"); +const TRACTION_URL: string = config.get("server.tractionUrl"); const wss = new WebSocket.Server({ noServer: true }); @@ -54,7 +53,7 @@ const logError = (err: Error) => { const handleLokiWebSocket = (tenantId: string, ws: WebSocket) => { const loki = new WebSocket( - `${WEBSOCKET_URL}?query={container_name="scripts-traction-agent-1"} |= \`${tenantId}\`` + `${LOKI_URL}/loki/api/v1/tail?query={container_name="scripts-traction-agent-1"} |= \`${tenantId}\`` ); loki.on("open", () => { From 48818a4aac78e29bd9205cab6a0b13ffc5dee45f Mon Sep 17 00:00:00 2001 From: Akiff Manji Date: Wed, 16 Oct 2024 07:32:09 -0700 Subject: [PATCH 11/15] chore: suppress unrelated ts build error Signed-off-by: Akiff Manji --- services/tenant-ui/src/routes/router.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/services/tenant-ui/src/routes/router.ts b/services/tenant-ui/src/routes/router.ts index b165062c8..9abd15ad6 100644 --- a/services/tenant-ui/src/routes/router.ts +++ b/services/tenant-ui/src/routes/router.ts @@ -22,7 +22,6 @@ router.use(express.json()); // For the secured innkeepr OIDC login request to verify the token and get a token from Traction router.get( "/innkeeperLogin", - // @ts-expect-error: secure function is not typed correctly secure(jwksService), async (req: any, res: Response, next: NextFunction) => { try { From 2a94893fc8229b63e0b531cbb93f5a3fa70b3a4f Mon Sep 17 00:00:00 2001 From: Akiff Manji Date: Wed, 16 Oct 2024 07:57:02 -0700 Subject: [PATCH 12/15] chore: audit and update dependencies Signed-off-by: Akiff Manji --- services/tenant-ui/frontend/package-lock.json | 513 +++++++++++++----- services/tenant-ui/package-lock.json | 31 +- 2 files changed, 382 insertions(+), 162 deletions(-) diff --git a/services/tenant-ui/frontend/package-lock.json b/services/tenant-ui/frontend/package-lock.json index 725e216ac..a6ef31d8d 100644 --- a/services/tenant-ui/frontend/package-lock.json +++ b/services/tenant-ui/frontend/package-lock.json @@ -189,10 +189,9 @@ } }, "node_modules/@codemirror/commands": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.6.2.tgz", - "integrity": "sha512-Fq7eWOl1Rcbrfn6jD8FPCj9Auaxdm5nIK5RYOeW7ughnd/rY5AmPg6b+CfsG39ZHdwiwe8lde3q8uR7CF5S0yQ==", - "license": "MIT", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.7.0.tgz", + "integrity": "sha512-+cduIZ2KbesDhbykV02K25A5xIVrquSPz4UxxYBemRlAT2aW8dhwUgLDwej7q/RJUHKk4nALYcR1puecDvbdqw==", "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.4.0", @@ -253,10 +252,9 @@ "license": "MIT" }, "node_modules/@codemirror/view": { - "version": "6.34.0", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.34.0.tgz", - "integrity": "sha512-2vKJ79tOcVfgPYVJM2XjcL1BH5Bsl7/tgn9ilBj3XWeCS5kTRy/NE4FHEj4aMylOl/D3IPNsmZH0WPlB+DyIdA==", - "license": "MIT", + "version": "6.34.1", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.34.1.tgz", + "integrity": "sha512-t1zK/l9UiRqwUNPm+pdIT0qzJlzuVckbTEMVNFhfWkGiBQClstzg+78vedCvLSX0xJEZ6lwZbPpnljL7L6iwMQ==", "dependencies": { "@codemirror/state": "^6.4.0", "style-mod": "^4.1.0", @@ -1306,10 +1304,12 @@ } }, "node_modules/@jsonquerylang/jsonquery": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@jsonquerylang/jsonquery/-/jsonquery-3.0.5.tgz", - "integrity": "sha512-3BcOZEd6AYnoNcFEPwDlbZn2lZeCn3sh9FJzNzYamPzImfW/SPVuJ4TodPX3DoGShxOnh4q/ioYXOsBn5mA+eQ==", - "license": "ISC" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jsonquerylang/jsonquery/-/jsonquery-3.1.1.tgz", + "integrity": "sha512-P6Qo5egd3W8TBpqQsqaZtZ9lPO7oXBM21QdkYamCAYZHv9VCPXiI8NeIuSoXdoe5zKVZPUWmqaI14uacJLmcNw==", + "bin": { + "jsonquery": "bin/cli.js" + } }, "node_modules/@lezer/common": { "version": "1.2.1", @@ -1427,6 +1427,266 @@ "dev": true, "license": "MIT" }, + "node_modules/@parcel/watcher": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.4.1.tgz", + "integrity": "sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==", + "dependencies": { + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.4.1", + "@parcel/watcher-darwin-arm64": "2.4.1", + "@parcel/watcher-darwin-x64": "2.4.1", + "@parcel/watcher-freebsd-x64": "2.4.1", + "@parcel/watcher-linux-arm-glibc": "2.4.1", + "@parcel/watcher-linux-arm64-glibc": "2.4.1", + "@parcel/watcher-linux-arm64-musl": "2.4.1", + "@parcel/watcher-linux-x64-glibc": "2.4.1", + "@parcel/watcher-linux-x64-musl": "2.4.1", + "@parcel/watcher-win32-arm64": "2.4.1", + "@parcel/watcher-win32-ia32": "2.4.1", + "@parcel/watcher-win32-x64": "2.4.1" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.4.1.tgz", + "integrity": "sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.4.1.tgz", + "integrity": "sha512-ln41eihm5YXIY043vBrrHfn94SIBlqOWmoROhsMVTSXGh0QahKGy77tfEywQ7v3NywyxBBkGIfrWRHm0hsKtzA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.4.1.tgz", + "integrity": "sha512-yrw81BRLjjtHyDu7J61oPuSoeYWR3lDElcPGJyOvIXmor6DEo7/G2u1o7I38cwlcoBHQFULqF6nesIX3tsEXMg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.4.1.tgz", + "integrity": "sha512-TJa3Pex/gX3CWIx/Co8k+ykNdDCLx+TuZj3f3h7eOjgpdKM+Mnix37RYsYU4LHhiYJz3DK5nFCCra81p6g050w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.4.1.tgz", + "integrity": "sha512-4rVYDlsMEYfa537BRXxJ5UF4ddNwnr2/1O4MHM5PjI9cvV2qymvhwZSFgXqbS8YoTk5i/JR0L0JDs69BUn45YA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.4.1.tgz", + "integrity": "sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.4.1.tgz", + "integrity": "sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.4.1.tgz", + "integrity": "sha512-s9O3fByZ/2pyYDPoLM6zt92yu6P4E39a03zvO0qCHOTjxmt3GHRMLuRZEWhWLASTMSrrnVNWdVI/+pUElJBBBg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.4.1.tgz", + "integrity": "sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.4.1.tgz", + "integrity": "sha512-Uq2BPp5GWhrq/lcuItCHoqxjULU1QYEcyjSO5jqqOK8RNFDBQnenMMx4gAl3v8GiWa59E9+uDM7yZ6LxwUIfRg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.4.1.tgz", + "integrity": "sha512-maNRit5QQV2kgHFSYwftmPBxiuK5u4DXjbXx7q6eKjq5dsLXZ4FJiVvlcw35QXzk0KrUecJmuVFbj4uV9oYrcw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.4.1.tgz", + "integrity": "sha512-+DvS92F9ezicfswqrvIRM2njcYJbd5mb9CUgtrHCHmvn7pPPa+nMDRu1o1bYYz/l5IB2NVGNJWiH7h1E58IF2A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/@pinia/testing": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/@pinia/testing/-/testing-0.1.5.tgz", @@ -2052,11 +2312,10 @@ } }, "node_modules/@vitest/coverage-v8": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.1.tgz", - "integrity": "sha512-md/A7A3c42oTT8JUHSqjP5uKTWJejzUW4jalpvs+rZ27gsURsMU8DEb+8Jf8C6Kj2gwfSHJqobDNBuoqlm0cFw==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.3.tgz", + "integrity": "sha512-2OJ3c7UPoFSmBZwqD2VEkUw6A/tzPF0LmW0ZZhhB8PFxuc+9IBG/FaSM+RLEenc7ljzFvGN+G0nGQoZnh7sy2A==", "dev": true, - "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.3.0", "@bcoe/v8-coverage": "^0.2.3", @@ -2075,8 +2334,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "2.1.1", - "vitest": "2.1.1" + "@vitest/browser": "2.1.3", + "vitest": "2.1.3" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -2085,14 +2344,13 @@ } }, "node_modules/@vitest/expect": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.1.tgz", - "integrity": "sha512-YeueunS0HiHiQxk+KEOnq/QMzlUuOzbU1Go+PgAsHvvv3tUkJPm9xWt+6ITNTlzsMXUjmgm5T+U7KBPK2qQV6w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.3.tgz", + "integrity": "sha512-SNBoPubeCJhZ48agjXruCI57DvxcsivVDdWz+SSsmjTT4QN/DfHk3zB/xKsJqMs26bLZ/pNRLnCf0j679i0uWQ==", "dev": true, - "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.1", - "@vitest/utils": "2.1.1", + "@vitest/spy": "2.1.3", + "@vitest/utils": "2.1.3", "chai": "^5.1.1", "tinyrainbow": "^1.2.0" }, @@ -2101,13 +2359,12 @@ } }, "node_modules/@vitest/mocker": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.1.tgz", - "integrity": "sha512-LNN5VwOEdJqCmJ/2XJBywB11DLlkbY0ooDJW3uRX5cZyYCrc4PI/ePX0iQhE3BiEGiQmK4GE7Q/PqCkkaiPnrA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.3.tgz", + "integrity": "sha512-eSpdY/eJDuOvuTA3ASzCjdithHa+GIF1L4PqtEELl6Qa3XafdMLBpBlZCIUCX2J+Q6sNmjmxtosAG62fK4BlqQ==", "dev": true, - "license": "MIT", "dependencies": { - "@vitest/spy": "^2.1.0-beta.1", + "@vitest/spy": "2.1.3", "estree-walker": "^3.0.3", "magic-string": "^0.30.11" }, @@ -2115,7 +2372,7 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/spy": "2.1.1", + "@vitest/spy": "2.1.3", "msw": "^2.3.5", "vite": "^5.0.0" }, @@ -2133,17 +2390,15 @@ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", "dev": true, - "license": "MIT", "dependencies": { "@types/estree": "^1.0.0" } }, "node_modules/@vitest/pretty-format": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.1.tgz", - "integrity": "sha512-SjxPFOtuINDUW8/UkElJYQSFtnWX7tMksSGW0vfjxMneFqxVr8YJ979QpMbDW7g+BIiq88RAGDjf7en6rvLPPQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.3.tgz", + "integrity": "sha512-XH1XdtoLZCpqV59KRbPrIhFCOO0hErxrQCMcvnQete3Vibb9UeIOX02uFPfVn3Z9ZXsq78etlfyhnkmIZSzIwQ==", "dev": true, - "license": "MIT", "dependencies": { "tinyrainbow": "^1.2.0" }, @@ -2152,13 +2407,12 @@ } }, "node_modules/@vitest/runner": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.1.tgz", - "integrity": "sha512-uTPuY6PWOYitIkLPidaY5L3t0JJITdGTSwBtwMjKzo5O6RCOEncz9PUN+0pDidX8kTHYjO0EwUIvhlGpnGpxmA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.3.tgz", + "integrity": "sha512-JGzpWqmFJ4fq5ZKHtVO3Xuy1iF2rHGV4d/pdzgkYHm1+gOzNZtqjvyiaDGJytRyMU54qkxpNzCx+PErzJ1/JqQ==", "dev": true, - "license": "MIT", "dependencies": { - "@vitest/utils": "2.1.1", + "@vitest/utils": "2.1.3", "pathe": "^1.1.2" }, "funding": { @@ -2166,13 +2420,12 @@ } }, "node_modules/@vitest/snapshot": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.1.tgz", - "integrity": "sha512-BnSku1WFy7r4mm96ha2FzN99AZJgpZOWrAhtQfoxjUU5YMRpq1zmHRq7a5K9/NjqonebO7iVDla+VvZS8BOWMw==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.3.tgz", + "integrity": "sha512-qWC2mWc7VAXmjAkEKxrScWHWFyCQx/cmiZtuGqMi+WwqQJ2iURsVY4ZfAK6dVo6K2smKRU6l3BPwqEBvhnpQGg==", "dev": true, - "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.1", + "@vitest/pretty-format": "2.1.3", "magic-string": "^0.30.11", "pathe": "^1.1.2" }, @@ -2181,11 +2434,10 @@ } }, "node_modules/@vitest/spy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.1.tgz", - "integrity": "sha512-ZM39BnZ9t/xZ/nF4UwRH5il0Sw93QnZXd9NAZGRpIgj0yvVwPpLd702s/Cx955rGaMlyBQkZJ2Ir7qyY48VZ+g==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.3.tgz", + "integrity": "sha512-Nb2UzbcUswzeSP7JksMDaqsI43Sj5+Kry6ry6jQJT4b5gAK+NS9NED6mDb8FlMRCX8m5guaHCDZmqYMMWRy5nQ==", "dev": true, - "license": "MIT", "dependencies": { "tinyspy": "^3.0.0" }, @@ -2194,13 +2446,12 @@ } }, "node_modules/@vitest/utils": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.1.tgz", - "integrity": "sha512-Y6Q9TsI+qJ2CC0ZKj6VBb+T8UPz593N113nnUykqwANqhgf3QkZeHFlusgKLTqrnVHbj/XDKZcDHol+dxVT+rQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.3.tgz", + "integrity": "sha512-xpiVfDSg1RrYT0tX6czgerkpcKFmFOF/gCr30+Mve5V2kewCy4Prn1/NDMSRwaSmT7PRaOF83wu+bEtsY1wrvA==", "dev": true, - "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.1", + "@vitest/pretty-format": "2.1.3", "loupe": "^3.1.1", "tinyrainbow": "^1.2.0" }, @@ -2720,7 +2971,6 @@ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" } @@ -2796,7 +3046,6 @@ "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } @@ -2815,7 +3064,6 @@ "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz", "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==", "dev": true, - "license": "MIT", "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", @@ -2848,7 +3096,6 @@ "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", "dev": true, - "license": "MIT", "engines": { "node": ">= 16" } @@ -3193,7 +3440,6 @@ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } @@ -3212,6 +3458,17 @@ "node": ">=0.4.0" } }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/diff-sequences": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", @@ -3887,16 +4144,6 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/glob": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", @@ -4548,21 +4795,20 @@ } }, "node_modules/jsonpath-plus": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-9.0.0.tgz", - "integrity": "sha512-bqE77VIDStrOTV/czspZhTn+o27Xx9ZJRGVkdVShEtPoqsIx5yALv3lWVU6y+PqYvWPJNWE7ORCQheQkEe0DDA==", - "license": "MIT", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-10.0.1.tgz", + "integrity": "sha512-30DeH2QD4nL1IpDLPIFz09G5XyLvh+oNMUI2Zxf4tbrlsVHs0e3VPnwpOnSTFb4yM0dfQK2WGKLsSaAS8V62rw==", "dependencies": { "@jsep-plugin/assignment": "^1.2.1", "@jsep-plugin/regex": "^1.0.3", - "jsep": "^1.3.8" + "jsep": "^1.3.9" }, "bin": { "jsonpath": "bin/jsonpath-cli.js", "jsonpath-plus": "bin/jsonpath-cli.js" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0" } }, "node_modules/jsonrepair": { @@ -4634,14 +4880,10 @@ "dev": true }, "node_modules/loupe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.1.tgz", - "integrity": "sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-func-name": "^2.0.1" - } + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz", + "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==", + "dev": true }, "node_modules/lru-cache": { "version": "11.0.0", @@ -4791,12 +5033,11 @@ "license": "MIT" }, "node_modules/msw": { - "version": "2.4.9", - "resolved": "https://registry.npmjs.org/msw/-/msw-2.4.9.tgz", - "integrity": "sha512-1m8xccT6ipN4PTqLinPwmzhxQREuxaEJYdx4nIbggxP8aM7r1e71vE7RtOUSQoAm1LydjGfZKy7370XD/tsuYg==", + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/msw/-/msw-2.4.11.tgz", + "integrity": "sha512-TVEw9NOPTc6ufOQLJ53234S9NBRxQbu7xFMxs+OCP43JQcNEIOKiZHxEm2nDzYIrwccoIhUxUf8wr99SukD76A==", "dev": true, "hasInstallScript": true, - "license": "MIT", "dependencies": { "@bundled-es-modules/cookie": "^2.0.0", "@bundled-es-modules/statuses": "^1.0.1", @@ -4810,10 +5051,10 @@ "graphql": "^16.8.1", "headers-polyfill": "^4.0.2", "is-node-process": "^1.2.0", - "outvariant": "^1.4.2", + "outvariant": "^1.4.3", "path-to-regexp": "^6.3.0", "strict-event-emitter": "^0.5.1", - "type-fest": "^4.9.0", + "type-fest": "^4.26.1", "yargs": "^17.7.2" }, "bin": { @@ -4835,9 +5076,9 @@ } }, "node_modules/msw/node_modules/type-fest": { - "version": "4.10.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.10.3.tgz", - "integrity": "sha512-JLXyjizi072smKGGcZiAJDCNweT8J+AuRxmPZ1aG7TERg4ijx9REl8CNhbr36RV4qXqL1gO1FF9HL8OkVmmrsA==", + "version": "4.26.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz", + "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==", "dev": true, "engines": { "node": ">=16" @@ -4891,6 +5132,11 @@ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "license": "MIT" }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==" + }, "node_modules/nopt": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", @@ -5112,7 +5358,6 @@ "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", "dev": true, - "license": "MIT", "engines": { "node": ">= 14.16" } @@ -5544,12 +5789,11 @@ "dev": true }, "node_modules/sass": { - "version": "1.79.3", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.79.3.tgz", - "integrity": "sha512-m7dZxh0W9EZ3cw50Me5GOuYm/tVAJAn91SUnohLRo9cXBixGUOdvmryN+dXpwR831bhoY3Zv7rEFt85PUwTmzA==", - "dev": true, - "license": "MIT", + "version": "1.79.5", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.79.5.tgz", + "integrity": "sha512-W1h5kp6bdhqFh2tk3DsI771MoEJjvrSY/2ihJRJS4pjIyfJCw0nTsxqhnrUzaLMOJjFchj8rOvraI/YUVjtx5g==", "dependencies": { + "@parcel/watcher": "^2.4.1", "chokidar": "^4.0.0", "immutable": "^4.0.0", "source-map-js": ">=0.6.2 <2.0.0" @@ -5565,7 +5809,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", - "dev": true, "license": "MIT", "dependencies": { "readdirp": "^4.0.1" @@ -5581,7 +5824,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.1.tgz", "integrity": "sha512-GkMg9uOTpIWWKbSsgwb5fA4EavTR+SG/PMPoAY8hkhHfEEY0/vqljY+XHqtDf2cr2IJtoNRDbrrEpZUiZCkYRw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 14.16.0" @@ -6038,7 +6280,6 @@ "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=14.0.0" } @@ -6222,36 +6463,35 @@ "dev": true }, "node_modules/vanilla-jsoneditor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vanilla-jsoneditor/-/vanilla-jsoneditor-1.0.1.tgz", - "integrity": "sha512-mLvUbwARTsFFAK0o4/f4bl+jjACI42rXL+X8lXODccyAu3fbR7SxxK88i2dZ5IZyGmw+6PO0hWy/i3N2BJldWQ==", - "license": "ISC", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/vanilla-jsoneditor/-/vanilla-jsoneditor-1.0.8.tgz", + "integrity": "sha512-5tKODR6J3IbGoMeBv4DEEU/Dlam4bPunOarIJKfrd5xs4bUife59Lp8Psjf86Y8OAM9mvxkrwR275XsBnvtO9A==", "dependencies": { "@codemirror/autocomplete": "^6.18.1", - "@codemirror/commands": "^6.6.2", + "@codemirror/commands": "^6.7.0", "@codemirror/lang-json": "^6.0.1", "@codemirror/language": "^6.10.3", "@codemirror/lint": "^6.8.2", "@codemirror/search": "^6.5.6", "@codemirror/state": "^6.4.1", - "@codemirror/view": "^6.33.0", + "@codemirror/view": "^6.34.1", "@fortawesome/free-regular-svg-icons": "^6.6.0", "@fortawesome/free-solid-svg-icons": "^6.6.0", - "@jsonquerylang/jsonquery": "^3.0.5", + "@jsonquerylang/jsonquery": "^3.1.1", "@lezer/highlight": "^1.2.1", "@replit/codemirror-indentation-markers": "^6.5.3", "ajv": "^8.17.1", "codemirror-wrapped-line-indent": "^1.0.8", "diff-sequences": "^29.6.3", - "immutable-json-patch": "6.0.1", + "immutable-json-patch": "^6.0.1", "jmespath": "^0.16.0", "json-source-map": "^0.6.1", - "jsonpath-plus": "^9.0.0", + "jsonpath-plus": "^9.0.0 || ^10.0.0", "jsonrepair": "^3.8.1", "lodash-es": "^4.17.21", "memoize-one": "^6.0.0", "natural-compare-lite": "^1.4.0", - "sass": "1.78.0", + "sass": "^1.79.5", "svelte": "^4.0.0", "vanilla-picker": "^2.12.3" } @@ -6278,23 +6518,6 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "license": "MIT" }, - "node_modules/vanilla-jsoneditor/node_modules/sass": { - "version": "1.78.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.78.0.tgz", - "integrity": "sha512-AaIqGSrjo5lA2Yg7RvFZrlXDBCp3nV4XP73GrLGvdRWWwk+8H3l0SDvq/5bA4eF+0RFPLuWUk3E+P1U/YqnpsQ==", - "license": "MIT", - "dependencies": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/vanilla-picker": { "version": "2.12.3", "resolved": "https://registry.npmjs.org/vanilla-picker/-/vanilla-picker-2.12.3.tgz", @@ -6365,11 +6588,10 @@ } }, "node_modules/vite-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.1.tgz", - "integrity": "sha512-N/mGckI1suG/5wQI35XeR9rsMsPqKXzq1CdUndzVstBj/HvyxxGctwnK6WX43NGt5L3Z5tcRf83g4TITKJhPrA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.3.tgz", + "integrity": "sha512-I1JadzO+xYX887S39Do+paRePCKoiDrWRRjp9kkG5he0t7RXNvPAJPCQSJqbGN4uCrFFeS3Kj3sLqY8NMYBEdA==", "dev": true, - "license": "MIT", "dependencies": { "cac": "^6.7.14", "debug": "^4.3.6", @@ -6387,19 +6609,18 @@ } }, "node_modules/vitest": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.1.tgz", - "integrity": "sha512-97We7/VC0e9X5zBVkvt7SGQMGrRtn3KtySFQG5fpaMlS+l62eeXRQO633AYhSTC3z7IMebnPPNjGXVGNRFlxBA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.3.tgz", + "integrity": "sha512-Zrxbg/WiIvUP2uEzelDNTXmEMJXuzJ1kCpbDvaKByFA9MNeO95V+7r/3ti0qzJzrxdyuUw5VduN7k+D3VmVOSA==", "dev": true, - "license": "MIT", "dependencies": { - "@vitest/expect": "2.1.1", - "@vitest/mocker": "2.1.1", - "@vitest/pretty-format": "^2.1.1", - "@vitest/runner": "2.1.1", - "@vitest/snapshot": "2.1.1", - "@vitest/spy": "2.1.1", - "@vitest/utils": "2.1.1", + "@vitest/expect": "2.1.3", + "@vitest/mocker": "2.1.3", + "@vitest/pretty-format": "^2.1.3", + "@vitest/runner": "2.1.3", + "@vitest/snapshot": "2.1.3", + "@vitest/spy": "2.1.3", + "@vitest/utils": "2.1.3", "chai": "^5.1.1", "debug": "^4.3.6", "magic-string": "^0.30.11", @@ -6410,7 +6631,7 @@ "tinypool": "^1.0.0", "tinyrainbow": "^1.2.0", "vite": "^5.0.0", - "vite-node": "2.1.1", + "vite-node": "2.1.3", "why-is-node-running": "^2.3.0" }, "bin": { @@ -6425,8 +6646,8 @@ "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.1.1", - "@vitest/ui": "2.1.1", + "@vitest/browser": "2.1.3", + "@vitest/ui": "2.1.3", "happy-dom": "*", "jsdom": "*" }, diff --git a/services/tenant-ui/package-lock.json b/services/tenant-ui/package-lock.json index 88de22182..7c26fc32d 100644 --- a/services/tenant-ui/package-lock.json +++ b/services/tenant-ui/package-lock.json @@ -30,8 +30,8 @@ "@types/jest": "^29.5.13", "@types/jsonwebtoken": "^9.0.7", "@types/node": "^22.7.2", - "@types/ws": "^8.5.12", "@types/nodemailer": "^6.4.16", + "@types/ws": "^8.5.12", "@typescript-eslint/eslint-plugin": "^8.7.0", "@typescript-eslint/parser": "^8.7.0", "eslint": "^8.57.0", @@ -2820,9 +2820,9 @@ "dev": true }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "engines": { "node": ">= 0.6" } @@ -3400,17 +3400,16 @@ } }, "node_modules/express": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", - "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", - "license": "MIT", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -9025,9 +9024,9 @@ "dev": true }, "cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==" + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==" }, "cookie-signature": { "version": "1.0.6", @@ -9435,16 +9434,16 @@ } }, "express": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", - "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", "requires": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", From f3729c7c8bce8fddab3d458264b05a9fb7d4b896 Mon Sep 17 00:00:00 2001 From: Akiff Manji Date: Mon, 21 Oct 2024 13:38:36 -0700 Subject: [PATCH 13/15] chore: update env variables Signed-off-by: Akiff Manji --- scripts/.env-example | 2 ++ scripts/docker-compose.yml | 2 ++ scripts/manage | 7 ++++--- .../config/custom-environment-variables.json | 1 + services/tenant-ui/config/default.json | 5 +++-- services/tenant-ui/frontend/src/store/logStore.ts | 2 +- services/tenant-ui/frontend/vite.config.ts | 6 ++++++ services/tenant-ui/src/components/innkeeper.ts | 12 ++++++------ 8 files changed, 25 insertions(+), 12 deletions(-) diff --git a/scripts/.env-example b/scripts/.env-example index 11f8759a9..9629861ad 100644 --- a/scripts/.env-example +++ b/scripts/.env-example @@ -180,7 +180,9 @@ TENANT_UI_PORT=5101 # which traction api are we using? # naming convention follows what is used by the tenant ui config SERVER_TRACTION_URL=http://localhost:8032 +SERVER_LOKI_URL=ws://localhost:3100 FRONTEND_TENANT_PROXY_URL=http://localhost:8032 +FRONTEND_LOG_STREAM_URL=ws://localhost:5101/logStream IMAGE_BUILDTIME= IMAGE_TAG=scripts_tenant-ui:latest IMAGE_VERSION=latest diff --git a/scripts/docker-compose.yml b/scripts/docker-compose.yml index 86b1cde91..31580281c 100755 --- a/scripts/docker-compose.yml +++ b/scripts/docker-compose.yml @@ -134,7 +134,9 @@ services: condition: service_started environment: - SERVER_TRACTION_URL=${SERVER_TRACTION_URL} + - SERVER_LOKI_URL=${SERVER_LOKI_URL} - FRONTEND_TENANT_PROXY_URL=${FRONTEND_TENANT_PROXY_URL} + - FRONTEND_LOG_STREAM_URL=${FRONTEND_LOG_STREAM_URL} - IMAGE_BUILDTIME=${IMAGE_BUILDTIME} - IMAGE_TAG=${IMAGE_TAG} - IMAGE_VERSION=${IMAGE_VERSION} diff --git a/scripts/manage b/scripts/manage index c53eed9bb..9f3de1a2d 100755 --- a/scripts/manage +++ b/scripts/manage @@ -24,13 +24,14 @@ generate_traction_ascii_art() { # Global variable to hold Docker Compose command compose_cmd="" +compose_files_opt="-f docker-compose.logs.yml -f docker-compose.yml" # Function to determine the correct Docker Compose command get_docker_compose_command() { if command -v "docker" > /dev/null && docker compose version > /dev/null 2>&1; then - compose_cmd="docker compose" + compose_cmd="docker compose $compose_files_opt" elif command -v docker-compose > /dev/null 2>&1; then - compose_cmd="docker-compose" + compose_cmd="docker-compose $compose_files_opt" else echo "Error: Neither 'docker compose' nor 'docker-compose' is installed." >&2 exit 1 @@ -65,7 +66,7 @@ build_docker_images() { fi built_services="traction-acapy-image-builder tenant-ui tenant-proxy endorser-api endorser-api-1" - pulled_services="ngrok-traction-agent traction-db endorser-db endorser-db-1 maildev endorser-agent endorser-agent-1" + pulled_services="loki promtail grafana ngrok-traction-agent traction-db endorser-db endorser-db-1 maildev endorser-agent endorser-agent-1" $compose_cmd build $built_services --no-cache --parallel $compose_cmd pull $pulled_services } diff --git a/services/tenant-ui/config/custom-environment-variables.json b/services/tenant-ui/config/custom-environment-variables.json index f4a686d84..4a1a63e5e 100644 --- a/services/tenant-ui/config/custom-environment-variables.json +++ b/services/tenant-ui/config/custom-environment-variables.json @@ -1,6 +1,7 @@ { "frontend": { "tenantProxyPath": "FRONTEND_TENANT_PROXY_URL", + "logStreamUrl": "FRONTEND_LOG_STREAM_URL", "showInnkeeperReservationPassword": "FRONTEND_INNKEEPER_SHOW_RESERVATION_PASSWORD", "showInnkeeperAdminLogin": "FRONTEND_INNKEEPER_SHOW_ADMIN", "showWritableComponents": "FRONTEND_TENANT_SHOW_WRITABLE_COMPONENTS", diff --git a/services/tenant-ui/config/default.json b/services/tenant-ui/config/default.json index ce1bd8ad3..dcb89a0cd 100644 --- a/services/tenant-ui/config/default.json +++ b/services/tenant-ui/config/default.json @@ -1,6 +1,7 @@ { "frontend": { "tenantProxyPath": "http://localhost:8032", + "logStreamUrl": "ws://localhost:5101/logStream", "apiPath": "api/", "basePath": "/", "showDeveloper": true, @@ -53,8 +54,8 @@ "logLevel": "http", "port": "8080", "staticFiles": "../../frontend/dist", - "tractionUrl": "http://localhost:5100", - "lokiUrl": "ws://localhost:3100", + "tractionUrl": "http://host.docker.internal:8032", + "lokiUrl": "ws://host.docker.internal:3100", "oidc": { "jwksUri": "https://dev.loginproxy.gov.bc.ca/auth/realms/digitaltrust-citz/protocol/openid-connect/certs", "realm": "digitaltrust-citz", diff --git a/services/tenant-ui/frontend/src/store/logStore.ts b/services/tenant-ui/frontend/src/store/logStore.ts index 04aeab9a1..e3652a7c4 100644 --- a/services/tenant-ui/frontend/src/store/logStore.ts +++ b/services/tenant-ui/frontend/src/store/logStore.ts @@ -43,7 +43,7 @@ export const useLogStore = defineStore('log', () => { } if (!logStream.value) { logStream.value = new WebSocket( - `${config.server.lokiUrl}?token=${token}` + `${config.frontend.logStreamUrl}?token=${token}` ); logStream.value.onopen = () => { logStreamState.value = LogStreamState.OPEN; diff --git a/services/tenant-ui/frontend/vite.config.ts b/services/tenant-ui/frontend/vite.config.ts index 682bb7495..26c7f8cea 100644 --- a/services/tenant-ui/frontend/vite.config.ts +++ b/services/tenant-ui/frontend/vite.config.ts @@ -28,6 +28,12 @@ export default defineConfig({ }, server: { proxy: { + '/logStream': { + target: 'ws://localhost:8080', + ws: true, + changeOrigin: true, + rewrite: (path) => path.replace(/^\/logStream/, ''), + }, '/api': proxyObject, '/config': proxyObject, }, diff --git a/services/tenant-ui/src/components/innkeeper.ts b/services/tenant-ui/src/components/innkeeper.ts index 56099ad62..003418a53 100644 --- a/services/tenant-ui/src/components/innkeeper.ts +++ b/services/tenant-ui/src/components/innkeeper.ts @@ -1,8 +1,8 @@ import axios from "axios"; import config from "config"; -const TRACURL: string = config.get("server.tractionUrl"); -const INN_USER = config.get("server.innkeeper.user"); -const INN_PW = config.get("server.innkeeper.key"); +const TRACTION_URL: string = config.get("server.tractionUrl"); +const INNKEEPER_USER = config.get("server.innkeeper.user"); +const INNKEEPER_KEY = config.get("server.innkeeper.key"); /** * @function login @@ -10,8 +10,8 @@ const INN_PW = config.get("server.innkeeper.key"); * @returns {string} The inkeeper token */ export const login = async () => { - const loginUrl = `${TRACURL}/multitenancy/tenant/${INN_USER}/token`; - const payload = { wallet_key: INN_PW }; + const loginUrl = `${TRACTION_URL}/multitenancy/tenant/${INNKEEPER_USER}/token`; + const payload = { wallet_key: INNKEEPER_KEY }; const res = await axios({ method: "post", url: loginUrl, @@ -29,7 +29,7 @@ export const login = async () => { export const createReservation = async (req: any, token: string) => { try { const auth = `Bearer ${token}`; - const reservationUrl = `${TRACURL}/innkeeper/reservations`; + const reservationUrl = `${TRACTION_URL}/innkeeper/reservations`; const payload = req.body; const res = await axios({ From 57edbcfceb0d69eef2e88a1941d04e7b305efba0 Mon Sep 17 00:00:00 2001 From: Akiff Manji Date: Tue, 22 Oct 2024 07:09:17 -0700 Subject: [PATCH 14/15] update: chart values Signed-off-by: Akiff Manji --- charts/traction/templates/ui/configmap.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/charts/traction/templates/ui/configmap.yaml b/charts/traction/templates/ui/configmap.yaml index 6e586f013..a01d14119 100644 --- a/charts/traction/templates/ui/configmap.yaml +++ b/charts/traction/templates/ui/configmap.yaml @@ -19,6 +19,7 @@ data: FRONTEND_SESSION_TIMEOUT_SECONDS: {{ .Values.ui.oidc.session.timeoutSeconds | quote }} FRONTEND_SESSION_COUNTDOWN_SECONDS: {{ .Values.ui.oidc.session.countdownSeconds | quote }} FRONTEND_TENANT_PROXY_URL: https://{{ include "tenant_proxy.host" . }} + FRONTEND_LOG_STREAM_URL: wss://{{ include "tenant-ui.fullname" . }}:{{ .Values.tenant-ui.service.port }}/logStream SERVER_OIDC_JWKS: {{ .Values.ui.oidc.jwksUri | quote }} SERVER_OIDC_REALM: {{ .Values.ui.oidc.realm | quote }} SERVER_OIDC_ROLE: {{ .Values.ui.oidc.roleName | quote }} @@ -29,6 +30,7 @@ data: SERVER_SMTP_SECURE: {{ .Values.ui.smtp.secure | quote }} SERVER_SMTP_USER: {{ .Values.ui.smtp.user | quote }} SERVER_TRACTION_URL: http://{{ include "tenant_proxy.fullname" . }}:{{ .Values.tenant_proxy.service.port }} + SERVER_LOKI_URL: http://{{ include "loki.fullname" . }}:{{ .Values.loki.service.port }} UX_APP_INNKEEPER_TITLE: {{ .Values.ui.ux.appInnkeeperTitle | quote }} UX_APP_TITLE: {{ .Values.ui.ux.appTitle | quote }} UX_COPYRIGHT: {{ .Values.ui.ux.copyright | quote }} From 155a3404fd3bf1213525f735f1b89ed76cf5e6a8 Mon Sep 17 00:00:00 2001 From: Akiff Manji Date: Tue, 22 Oct 2024 07:24:22 -0700 Subject: [PATCH 15/15] update: chart values Signed-off-by: Akiff Manji --- charts/traction/templates/ui/configmap.yaml | 2 +- charts/traction/values.yaml | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/charts/traction/templates/ui/configmap.yaml b/charts/traction/templates/ui/configmap.yaml index a01d14119..bdddb30f7 100644 --- a/charts/traction/templates/ui/configmap.yaml +++ b/charts/traction/templates/ui/configmap.yaml @@ -19,7 +19,7 @@ data: FRONTEND_SESSION_TIMEOUT_SECONDS: {{ .Values.ui.oidc.session.timeoutSeconds | quote }} FRONTEND_SESSION_COUNTDOWN_SECONDS: {{ .Values.ui.oidc.session.countdownSeconds | quote }} FRONTEND_TENANT_PROXY_URL: https://{{ include "tenant_proxy.host" . }} - FRONTEND_LOG_STREAM_URL: wss://{{ include "tenant-ui.fullname" . }}:{{ .Values.tenant-ui.service.port }}/logStream + FRONTEND_LOG_STREAM_URL: wss://{{ include "tenant-ui.fullname" . }}:{{ .Values.ui.service.httpPort }}/logStream SERVER_OIDC_JWKS: {{ .Values.ui.oidc.jwksUri | quote }} SERVER_OIDC_REALM: {{ .Values.ui.oidc.realm | quote }} SERVER_OIDC_ROLE: {{ .Values.ui.oidc.roleName | quote }} diff --git a/charts/traction/values.yaml b/charts/traction/values.yaml index caaef7314..cc46db12c 100644 --- a/charts/traction/values.yaml +++ b/charts/traction/values.yaml @@ -591,6 +591,18 @@ tenant_proxy: ## tolerations: [] +## @section Loki configuration +## +loki: + ## Loki service configuration + ## + service: + ## @param loki.service.type Kubernetes Service type + ## + type: ClusterIP + ## @param loki.service.port Port to expose for http services + port: 3100 + ## @section Tenant-UI Configuration ## ui: