├── oada ├── libs │ ├── models │ │ ├── README.md │ │ ├── tsconfig.json │ │ ├── package.json │ │ └── src │ │ │ ├── decorators.ts │ │ │ ├── authorization.ts │ │ │ └── client.ts │ ├── pino-debug │ │ ├── .gitignore │ │ ├── .vim │ │ │ └── coc-settings.json │ │ ├── tsconfig.json │ │ ├── src │ │ │ └── types.d.ts │ │ ├── package.json │ │ └── README.md │ ├── lib-kafka │ │ ├── .vscode │ │ │ └── settings.json │ │ ├── .vim │ │ │ └── coc-settings.json │ │ ├── tsconfig.json │ │ ├── test │ │ │ └── tsconfig.json │ │ ├── src │ │ │ ├── index.ts │ │ │ ├── init.ts │ │ │ ├── ReResponder.ts │ │ │ ├── config.ts │ │ │ └── Kafka.ts │ │ └── package.json │ ├── lib-arangodb │ │ ├── README.md │ │ ├── .vim │ │ │ └── coc-settings.json │ │ ├── tsconfig.json │ │ ├── test │ │ │ ├── tsconfig.json │ │ │ ├── resources.test.ts │ │ │ └── token.test.ts │ │ ├── .gitignore │ │ ├── src │ │ │ ├── libs │ │ │ │ ├── exampledocs │ │ │ │ │ ├── putBodies.ts │ │ │ │ │ ├── codes.ts │ │ │ │ │ ├── changeEdges.ts │ │ │ │ │ └── edges.ts │ │ │ │ ├── putBodies.ts │ │ │ │ ├── clients.ts │ │ │ │ ├── codes.ts │ │ │ │ └── deviceCodes.ts │ │ │ ├── index.ts │ │ │ └── util.ts │ │ └── package.json │ ├── lib-config │ │ ├── .vim │ │ │ └── coc-settings.json │ │ ├── tsconfig.json │ │ ├── .gitignore │ │ └── package.json │ └── lib-prom │ │ ├── .vim │ │ └── coc-settings.json │ │ ├── tsconfig.json │ │ ├── src │ │ ├── types.d.ts │ │ └── config.ts │ │ ├── README.md │ │ └── package.json ├── services │ ├── http-handler │ │ ├── .gitignore │ │ ├── .vim │ │ │ └── coc-settings.json │ │ ├── tsconfig.json │ │ └── src │ │ │ ├── healthcheck.ts │ │ │ ├── requester.ts │ │ │ ├── types.d.ts │ │ │ └── tokenLookup.ts │ ├── auth │ │ ├── public │ │ │ └── .gitignore │ │ ├── domains │ │ │ └── localhost │ │ │ │ ├── auth-www │ │ │ │ └── logo.png │ │ │ │ ├── public_key.jwk │ │ │ │ ├── public_key.pem │ │ │ │ ├── private_key.pem │ │ │ │ ├── unsigned_software_statement.mjs │ │ │ │ ├── config.mjs │ │ │ │ └── signed_software_statement.mjs │ │ ├── .vim │ │ │ └── coc-settings.json │ │ ├── tsconfig.json │ │ ├── src │ │ │ ├── db │ │ │ │ ├── flat │ │ │ │ │ ├── codes.ts │ │ │ │ │ ├── clients.ts │ │ │ │ │ ├── tokens.ts │ │ │ │ │ └── users.ts │ │ │ │ ├── arango │ │ │ │ │ ├── codes.ts │ │ │ │ │ ├── clients.ts │ │ │ │ │ ├── deviceCodes.ts │ │ │ │ │ ├── tokens.ts │ │ │ │ │ └── users.ts │ │ │ │ ├── models │ │ │ │ │ ├── client.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── token.ts │ │ │ │ └── jwt │ │ │ │ │ └── tokens.ts │ │ │ ├── init.ts │ │ │ └── keys.ts │ │ └── test │ │ │ ├── private.jwk.json │ │ │ └── istantestd.sh │ ├── permissions-handler │ │ ├── scopes │ │ │ └── additional-scopes │ │ │ │ └── .gitkeep │ │ ├── .vim │ │ │ └── coc-settings.json │ │ ├── tsconfig.json │ │ ├── src │ │ │ ├── types.d.ts │ │ │ └── config.ts │ │ └── package.json │ ├── write-handler │ │ ├── .vscode │ │ │ └── settings.json │ │ ├── .vim │ │ │ └── coc-settings.json │ │ ├── test │ │ │ └── tsconfig.json │ │ ├── tsconfig.json │ │ ├── src │ │ │ ├── types.d.ts │ │ │ └── config.ts │ │ └── package.json │ ├── shares │ │ ├── .vim │ │ │ └── coc-settings.json │ │ ├── tsconfig.json │ │ ├── src │ │ │ └── config.ts │ │ └── package.json │ ├── startup │ │ ├── .vim │ │ │ └── coc-settings.json │ │ ├── tsconfig.json │ │ ├── package.json │ │ └── src │ │ │ └── index.ts │ ├── users │ │ ├── .vim │ │ │ └── coc-settings.json │ │ ├── tsconfig.json │ │ ├── src │ │ │ └── config.ts │ │ └── package.json │ ├── sync-handler │ │ ├── .vim │ │ │ └── coc-settings.json │ │ ├── tsconfig.json │ │ ├── src │ │ │ └── config.ts │ │ └── package.json │ ├── webhooks │ │ ├── .vim │ │ │ └── coc-settings.json │ │ ├── tsconfig.json │ │ ├── src │ │ │ └── config.ts │ │ └── package.json │ ├── well-known │ │ ├── .vim │ │ │ └── coc-settings.json │ │ ├── tsconfig.json │ │ ├── src │ │ │ └── types.d.ts │ │ └── package.json │ └── rev-graph-update │ │ ├── .vim │ │ └── coc-settings.json │ │ ├── test │ │ └── tsconfig.json │ │ ├── tsconfig.json │ │ ├── src │ │ └── config.ts │ │ └── package.json ├── tests │ ├── config.defaults.js │ ├── entrypoint.sh │ ├── .gitignore │ ├── clearDocker.sh │ ├── config.js │ ├── Dockerfile │ ├── server │ │ └── index.js │ ├── README.md │ ├── test │ │ ├── get.js │ │ └── batch-rev-graph-updates.js │ ├── package.json │ ├── .yarnrc.yml │ ├── selftest │ │ └── index.js │ ├── restartall.ps1 │ └── test-host-level │ │ ├── containersAlive.js │ │ └── alwaysRestart.js ├── lerna.json ├── biome.json ├── .vscode │ ├── extensions.json │ ├── tasks.json │ └── settings.json ├── .vim │ └── coc-settings.json ├── .gitignore ├── utils │ └── entrypoint.sh ├── tsconfig.json ├── .dockerignore ├── README.md ├── package.json └── .yarnrc.yml ├── .pino-prettyrc ├── support └── proxy │ ├── http.d │ ├── brotli.conf │ ├── gzip.conf │ └── ratelimit.conf │ ├── proxy-confs │ ├── auth.subfolder.conf │ └── well-known.subfolder.conf │ ├── Dockerfile │ ├── default │ └── selfsigned │ ├── fullchain.pem │ └── privkey.pem ├── .github ├── dependabot.yml └── workflows │ ├── validate-codeowners.yml │ ├── helm-chart.yml │ ├── git-cliff-release.yml │ └── semgrep-analysis.yml ├── release ├── .env └── make.sh ├── .gitignore ├── .vscode ├── extensions.json └── settings.json ├── .editorconfig ├── charts └── oada │ ├── .helmignore │ ├── templates │ ├── NOTES.txt │ ├── binary-data.yaml │ ├── tests │ │ ├── well-known.yaml │ │ └── bookmarks.yaml │ ├── issuer.yaml │ ├── grafana.yaml │ ├── service-account.yaml │ ├── arangodb.yaml │ └── well-known.yaml │ ├── Chart.yaml │ └── README.md ├── notes_on_making_client_certificates.md ├── .gitattributes ├── biome.json ├── common.yml └── CODEOWNERS /oada/libs/models/README.md: -------------------------------------------------------------------------------- 1 | # models 2 | -------------------------------------------------------------------------------- /oada/libs/pino-debug/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | -------------------------------------------------------------------------------- /oada/services/http-handler/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | -------------------------------------------------------------------------------- /oada/services/auth/public/.gitignore: -------------------------------------------------------------------------------- 1 | domains/* 2 | -------------------------------------------------------------------------------- /oada/services/permissions-handler/scopes/additional-scopes/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /oada/tests/config.defaults.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // IsTest: true 3 | }; 4 | -------------------------------------------------------------------------------- /oada/services/write-handler/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.codeActionsOnSave.rules": null 3 | } 4 | -------------------------------------------------------------------------------- /oada/lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "npmClient": "yarn", 3 | "useWorkspaces": true, 4 | "version": "independent" 5 | } 6 | -------------------------------------------------------------------------------- /oada/libs/lib-kafka/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": ["kafkajs", "ksuid", "mesg", "rtracer"] 3 | } 4 | -------------------------------------------------------------------------------- /oada/libs/lib-arangodb/README.md: -------------------------------------------------------------------------------- 1 | # @oada/lib-arangodb 2 | 3 | All arango code for oada-srvc\* services in one place 4 | -------------------------------------------------------------------------------- /oada/biome.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://biomejs.dev/schemas/2.2.4/schema.json", 3 | "root": false, 4 | "extends": "//" 5 | } 6 | -------------------------------------------------------------------------------- /.pino-prettyrc: -------------------------------------------------------------------------------- 1 | { 2 | "colorize": true, 3 | "levelFirst": true, 4 | "translateTime": "SYS:standard", 5 | "ignore": "pid,hostname" 6 | } 7 | -------------------------------------------------------------------------------- /support/proxy/http.d/brotli.conf: -------------------------------------------------------------------------------- 1 | brotli on; 2 | brotli_comp_level 6; 3 | brotli_static on; 4 | brotli_types *; 5 | brotli_min_length 256; 6 | -------------------------------------------------------------------------------- /oada/tests/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | cd /code/tests/oada-srvc-tests || exit #&& \ 4 | #npm run start -- --config=/oada-srvc-docker-config.js 5 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | directory: / 5 | schedule: 6 | interval: daily 7 | -------------------------------------------------------------------------------- /oada/services/auth/domains/localhost/auth-www/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OADA/server/HEAD/oada/services/auth/domains/localhost/auth-www/logo.png -------------------------------------------------------------------------------- /oada/libs/lib-config/.vim/coc-settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workspace.workspaceFolderCheckCwd": false, 3 | "tsserver.tsdk": "../../.yarn/sdks/typescript/lib" 4 | } 5 | -------------------------------------------------------------------------------- /oada/libs/lib-kafka/.vim/coc-settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workspace.workspaceFolderCheckCwd": false, 3 | "tsserver.tsdk": "../../.yarn/sdks/typescript/lib" 4 | } 5 | -------------------------------------------------------------------------------- /oada/libs/lib-prom/.vim/coc-settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workspace.workspaceFolderCheckCwd": false, 3 | "tsserver.tsdk": "../../.yarn/sdks/typescript/lib" 4 | } 5 | -------------------------------------------------------------------------------- /oada/libs/pino-debug/.vim/coc-settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workspace.workspaceFolderCheckCwd": false, 3 | "tsserver.tsdk": "../../.yarn/sdks/typescript/lib" 4 | } 5 | -------------------------------------------------------------------------------- /oada/services/auth/.vim/coc-settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workspace.workspaceFolderCheckCwd": false, 3 | "tsserver.tsdk": "../../.yarn/sdks/typescript/lib" 4 | } 5 | -------------------------------------------------------------------------------- /oada/services/shares/.vim/coc-settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workspace.workspaceFolderCheckCwd": false, 3 | "tsserver.tsdk": "../../.yarn/sdks/typescript/lib" 4 | } 5 | -------------------------------------------------------------------------------- /oada/services/startup/.vim/coc-settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workspace.workspaceFolderCheckCwd": false, 3 | "tsserver.tsdk": "../../.yarn/sdks/typescript/lib" 4 | } 5 | -------------------------------------------------------------------------------- /oada/services/users/.vim/coc-settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workspace.workspaceFolderCheckCwd": false, 3 | "tsserver.tsdk": "../../.yarn/sdks/typescript/lib" 4 | } 5 | -------------------------------------------------------------------------------- /oada/libs/lib-arangodb/.vim/coc-settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workspace.workspaceFolderCheckCwd": false, 3 | "tsserver.tsdk": "../../.yarn/sdks/typescript/lib" 4 | } 5 | -------------------------------------------------------------------------------- /oada/services/http-handler/.vim/coc-settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workspace.workspaceFolderCheckCwd": false, 3 | "tsserver.tsdk": "../../.yarn/sdks/typescript/lib" 4 | } 5 | -------------------------------------------------------------------------------- /oada/services/sync-handler/.vim/coc-settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workspace.workspaceFolderCheckCwd": false, 3 | "tsserver.tsdk": "../../.yarn/sdks/typescript/lib" 4 | } 5 | -------------------------------------------------------------------------------- /oada/services/webhooks/.vim/coc-settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workspace.workspaceFolderCheckCwd": false, 3 | "tsserver.tsdk": "../../.yarn/sdks/typescript/lib" 4 | } 5 | -------------------------------------------------------------------------------- /oada/services/well-known/.vim/coc-settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workspace.workspaceFolderCheckCwd": false, 3 | "tsserver.tsdk": "../../.yarn/sdks/typescript/lib" 4 | } 5 | -------------------------------------------------------------------------------- /oada/services/rev-graph-update/.vim/coc-settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workspace.workspaceFolderCheckCwd": false, 3 | "tsserver.tsdk": "../../.yarn/sdks/typescript/lib" 4 | } 5 | -------------------------------------------------------------------------------- /oada/services/write-handler/.vim/coc-settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workspace.workspaceFolderCheckCwd": false, 3 | "tsserver.tsdk": "../../.yarn/sdks/typescript/lib" 4 | } 5 | -------------------------------------------------------------------------------- /oada/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "arcanis.vscode-zipfs", 4 | "dbaeumer.vscode-eslint", 5 | "esbenp.prettier-vscode" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /oada/services/permissions-handler/.vim/coc-settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workspace.workspaceFolderCheckCwd": false, 3 | "tsserver.tsdk": "../../.yarn/sdks/typescript/lib" 4 | } 5 | -------------------------------------------------------------------------------- /release/.env: -------------------------------------------------------------------------------- 1 | DEBUG=* 2 | NODE_ENV=production 3 | NODE_TLS_REJECT_UNAUTHORIZED= 4 | OIDC_ISSUER=${DOMAIN} 5 | PINO_LEVEL=info 6 | PINO_TRANSPORT= 7 | REDPANDA_MODE=production 8 | -------------------------------------------------------------------------------- /support/proxy/http.d/gzip.conf: -------------------------------------------------------------------------------- 1 | gzip_vary on; 2 | gzip_proxied any; 3 | gzip_comp_level 6; 4 | gzip_buffers 16 8k; 5 | gzip_http_version 1.1; 6 | gzip_types *; 7 | gzip_min_length 256; 8 | -------------------------------------------------------------------------------- /oada/libs/pino-debug/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "dist" 6 | }, 7 | "include": ["src"] 8 | } 9 | -------------------------------------------------------------------------------- /oada/.vim/coc-settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workspace.workspaceFolderCheckCwd": false, 3 | "tsserver.tsdk": ".yarn/sdks/typescript/lib", 4 | "eslint.packageManager": "yarn", 5 | "eslint.nodePath": ".yarn/sdks" 6 | } 7 | -------------------------------------------------------------------------------- /oada/.gitignore: -------------------------------------------------------------------------------- 1 | # ts build stuff 2 | dist/ 3 | .test/ 4 | *.tsbuildinfo 5 | 6 | # yarn 3 stuff 7 | /.yarn/* 8 | !/.yarn/patches/ 9 | !/.yarn/releases/ 10 | !/.yarn/plugins/ 11 | !/.yarn/versions/ 12 | .pnp.* 13 | -------------------------------------------------------------------------------- /oada/libs/models/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | "compilerOptions": { 4 | "composite": true, 5 | "rootDir": "src", 6 | "outDir": "dist" 7 | }, 8 | "include": ["src"] 9 | } 10 | -------------------------------------------------------------------------------- /oada/tests/.gitignore: -------------------------------------------------------------------------------- 1 | # ts build stuff 2 | dist/ 3 | .test/ 4 | *.tsbuildinfo 5 | 6 | # yarn 3 stuff 7 | /.yarn/* 8 | !/.yarn/patches/ 9 | !/.yarn/releases/ 10 | !/.yarn/plugins/ 11 | !/.yarn/versions/ 12 | .pnp.* 13 | -------------------------------------------------------------------------------- /oada/libs/lib-kafka/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "dist" 6 | }, 7 | "include": ["src"], 8 | "references": [{ "path": "../lib-config" }] 9 | } 10 | -------------------------------------------------------------------------------- /oada/libs/lib-prom/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "dist" 6 | }, 7 | "include": ["src"], 8 | "references": [{ "path": "../lib-config" }] 9 | } 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package.lock 3 | *.log 4 | .DS_Store 5 | .dccache 6 | 7 | .history 8 | 9 | # local env file 10 | /.env 11 | # local override file 12 | /docker-compose.override.yml 13 | 14 | # Ignore act stuff? 15 | .actrc 16 | act/ 17 | -------------------------------------------------------------------------------- /oada/libs/lib-arangodb/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "dist" 6 | }, 7 | "include": ["src"], 8 | "references": [{ "path": "../models" }, { "path": "../lib-config" }] 9 | } 10 | -------------------------------------------------------------------------------- /oada/libs/lib-config/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | "compilerOptions": { 4 | "composite": true, 5 | "rootDir": "src", 6 | "outDir": "dist" 7 | }, 8 | "include": ["src"], 9 | "references": [{ "path": "../pino-debug" }] 10 | } 11 | -------------------------------------------------------------------------------- /oada/libs/lib-arangodb/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "rootDir": ".", 6 | "outDir": "../.test" 7 | }, 8 | "include": ["."], 9 | "references": [ 10 | { 11 | "path": "../" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /oada/libs/lib-kafka/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "rootDir": ".", 6 | "outDir": "../.test" 7 | }, 8 | "include": ["."], 9 | "references": [ 10 | { 11 | "path": "../" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "arcanis.vscode-zipfs", 4 | "esbenp.prettier-vscode", 5 | "dbaeumer.vscode-eslint", 6 | "gamunu.vscode-yarn", 7 | "editorconfig.editorconfig", 8 | "ms-azuretools.vscode-docker", 9 | "loiane.ts-extension-pack" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /oada/services/write-handler/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "rootDir": ".", 6 | "outDir": "../.test" 7 | }, 8 | "include": ["."], 9 | "references": [ 10 | { 11 | "path": "../" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /oada/services/rev-graph-update/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "rootDir": ".", 6 | "outDir": "../.test" 7 | }, 8 | "include": ["."], 9 | "references": [ 10 | { 11 | "path": "../" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /oada/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "npm", 6 | "script": "build", 7 | "group": { 8 | "kind": "build", 9 | "isDefault": true 10 | }, 11 | "problemMatcher": [], 12 | "label": "npm: build", 13 | "detail": "yarn build" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | indent_style = space 8 | indent_size = 2 9 | tab_width = 2 10 | end_of_line = lf 11 | charset = utf-8 12 | trim_trailing_whitespace = true 13 | insert_final_newline = true 14 | max_line_length = 80 15 | spelling_language = en-US -------------------------------------------------------------------------------- /oada/services/startup/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "dist" 6 | }, 7 | "include": ["src"], 8 | "references": [ 9 | { "path": "../../libs/pino-debug" }, 10 | { "path": "../../libs/lib-arangodb" }, 11 | { "path": "../../libs/lib-kafka" } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /oada/services/well-known/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "dist" 6 | }, 7 | "include": ["src"], 8 | "references": [ 9 | { "path": "../../libs/pino-debug" }, 10 | { "path": "../../libs/lib-prom" }, 11 | { "path": "../../libs/lib-config" } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /oada/services/auth/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "dist" 6 | }, 7 | "include": ["src"], 8 | "references": [ 9 | { "path": "../../libs/pino-debug" }, 10 | { "path": "../../libs/lib-config" }, 11 | { "path": "../../libs/lib-arangodb" }, 12 | { "path": "../../libs/lib-prom" } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /oada/services/sync-handler/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "dist" 6 | }, 7 | "include": ["src"], 8 | "references": [ 9 | { "path": "../../libs/pino-debug" }, 10 | { "path": "../../libs/lib-prom" }, 11 | { "path": "../../libs/lib-arangodb" }, 12 | { "path": "../write-handler" } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /oada/services/auth/domains/localhost/public_key.jwk: -------------------------------------------------------------------------------- 1 | {"kty":"RSA","n":"6A2weV9xDaIarahSvCSpQjt-4oB5eQXIctmkgz7A83PJ4VCB16DfnOG0U0WalvGpV2xpKzFDfc5PTT9PcI_pVh0LCKV7aofhmDzjmfZwiGZzho25XvtwvADUt91Bfpw6hJ867gXmFbOpaXEnYbO2MBow0m2aKkPyE2iFn9hQQl6q3XtbAaejiYYKxb1nLQhpcbLXX6wj5nR62M7wy5cNBPTtUmpJhKMmyp43-3BI4X4z0wezUXG9vlaHi9PHCtmCWh6yEMBMZlYLh2awfIQox6JQhR3NEJ1tTW9gE7i0Dw6xlN4vdmj3EiX6nKUaXof3nvBSYV--WMXmjpH7qoOBkQ","e":"AQAB"} 2 | -------------------------------------------------------------------------------- /oada/services/permissions-handler/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "dist" 6 | }, 7 | "include": ["src"], 8 | "references": [ 9 | { "path": "../../libs/pino-debug" }, 10 | { "path": "../../libs/lib-prom" }, 11 | { "path": "../../libs/lib-config" }, 12 | { "path": "../../libs/lib-kafka" } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /oada/services/shares/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "dist" 6 | }, 7 | "include": ["src"], 8 | "references": [ 9 | { "path": "../../libs/pino-debug" }, 10 | { "path": "../../libs/lib-prom" }, 11 | { "path": "../../libs/lib-kafka" }, 12 | { "path": "../../libs/lib-arangodb" }, 13 | { "path": "../write-handler" } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /oada/tests/clearDocker.sh: -------------------------------------------------------------------------------- 1 | echo "----------------------" 2 | echo "Stopping containers..." 3 | echo "" 4 | docker stop $(docker ps -aq) 5 | echo "----------------------" 6 | echo "Removing containers..." 7 | echo "" 8 | docker rm $(docker ps -aq) 9 | echo "----------------------" 10 | echo "Removing volumes..." 11 | echo "" 12 | docker volume rm $(docker volume ls -q) 13 | echo "----------------------" 14 | echo "Done! 15 | echo "----------------------" 16 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "oada": true, 4 | "k8s": true, 5 | "charts": true 6 | }, 7 | "search.exclude": { 8 | "oada": true, 9 | "k8s": true, 10 | "charts": true 11 | }, 12 | "prettier.prettierPath": "oada/.yarn/sdks/prettier/index.js", 13 | "typescript.tsdk": "oada/.yarn/sdks/typescript/lib", 14 | "typescript.enablePromptUseWorkspaceTsdk": true, 15 | "eslint.nodePath": "oada/.yarn/sdks" 16 | } 17 | -------------------------------------------------------------------------------- /oada/services/rev-graph-update/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "dist" 6 | }, 7 | "include": ["src"], 8 | "references": [ 9 | { "path": "../../libs/pino-debug" }, 10 | { "path": "../../libs/lib-prom" }, 11 | { "path": "../../libs/lib-config" }, 12 | { "path": "../../libs/lib-arangodb" }, 13 | { "path": "../write-handler" } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /oada/services/write-handler/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "dist" 6 | }, 7 | "include": ["src"], 8 | "references": [ 9 | { "path": "../../libs/pino-debug" }, 10 | { "path": "../../libs/lib-config" }, 11 | { "path": "../../libs/lib-prom" }, 12 | { "path": "../../libs/lib-kafka" }, 13 | { "path": "../../libs/lib-arangodb" } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /oada/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "libs": true, 4 | "services": true 5 | }, 6 | "search.exclude": { 7 | "libs": true, 8 | "services": true, 9 | "**/.yarn": true, 10 | "**/.pnp.*": true 11 | }, 12 | "prettier.prettierPath": ".yarn/sdks/prettier/index.cjs", 13 | "eslint.nodePath": ".yarn/sdks", 14 | "typescript.tsdk": ".yarn/sdks/typescript/lib", 15 | "typescript.enablePromptUseWorkspaceTsdk": true 16 | } 17 | -------------------------------------------------------------------------------- /charts/oada/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /oada/services/users/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "dist" 6 | }, 7 | "include": ["src"], 8 | "references": [ 9 | { "path": "../../libs/models" }, 10 | { "path": "../../libs/pino-debug" }, 11 | { "path": "../../libs/lib-config" }, 12 | { "path": "../../libs/lib-prom" }, 13 | { "path": "../../libs/lib-kafka" }, 14 | { "path": "../../libs/lib-arangodb" } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /oada/services/webhooks/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "dist" 6 | }, 7 | "include": ["src"], 8 | "references": [ 9 | { "path": "../../libs/pino-debug" }, 10 | { "path": "../../libs/lib-config" }, 11 | { "path": "../../libs/lib-prom" }, 12 | { "path": "../../libs/lib-kafka" }, 13 | { "path": "../../libs/lib-arangodb" }, 14 | { "path": "../write-handler" } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /oada/services/auth/domains/localhost/public_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6A2weV9xDaIarahSvCSp 3 | Qjt+4oB5eQXIctmkgz7A83PJ4VCB16DfnOG0U0WalvGpV2xpKzFDfc5PTT9PcI/p 4 | Vh0LCKV7aofhmDzjmfZwiGZzho25XvtwvADUt91Bfpw6hJ867gXmFbOpaXEnYbO2 5 | MBow0m2aKkPyE2iFn9hQQl6q3XtbAaejiYYKxb1nLQhpcbLXX6wj5nR62M7wy5cN 6 | BPTtUmpJhKMmyp43+3BI4X4z0wezUXG9vlaHi9PHCtmCWh6yEMBMZlYLh2awfIQo 7 | x6JQhR3NEJ1tTW9gE7i0Dw6xlN4vdmj3EiX6nKUaXof3nvBSYV++WMXmjpH7qoOB 8 | kQIDAQAB 9 | -----END PUBLIC KEY----- 10 | -------------------------------------------------------------------------------- /support/proxy/proxy-confs/auth.subfolder.conf: -------------------------------------------------------------------------------- 1 | # Redirect oadaauth to the auth service 2 | 3 | location ^~ /oadaauth/ { 4 | include /config/nginx/proxy.conf; 5 | resolver 127.0.0.11 valid=30s; 6 | set $upstream_app auth; 7 | set $upstream_port 8080; 8 | set $upstream_proto http; 9 | proxy_pass $upstream_proto://$upstream_app:$upstream_port; # nosemgrep: generic.nginx.security.missing-internal.missing-internal, generic.nginx.security.dynamic-proxy-host.dynamic-proxy-host, generic.nginx.security.dynamic-proxy-scheme.dynamic-proxy-scheme 10 | } 11 | -------------------------------------------------------------------------------- /oada/services/http-handler/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "dist" 6 | }, 7 | "include": ["src"], 8 | "references": [ 9 | { "path": "../../libs/pino-debug" }, 10 | { "path": "../../libs/lib-config" }, 11 | { "path": "../../libs/lib-kafka" }, 12 | { "path": "../../libs/lib-arangodb" }, 13 | { "path": "../../libs/lib-prom" }, 14 | { "path": "../permissions-handler" }, 15 | { "path": "../auth" }, 16 | { "path": "../write-handler" } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /support/proxy/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch as configs 2 | 3 | # Copy in our edited nginx config? 4 | COPY ./nginx.conf /config/nginx/ 5 | 6 | # Copy our configs in? 7 | COPY ./http.d/*.conf /etc/nginx/http.d/ 8 | 9 | # Proxy to services 10 | COPY ./proxy-confs/* /config/nginx/proxy-confs/ 11 | 12 | FROM linuxserver/nginx:1.20.2 as http-only 13 | 14 | ENV DOCKER_MODS=linuxserver/mods:nginx-proxy-confs 15 | 16 | COPY --from=configs / / 17 | 18 | # Disable https 19 | COPY ./default /config/nginx/site-confs/ 20 | 21 | FROM linuxserver/swag:version-1.15.0 as https 22 | 23 | COPY --from=configs / / -------------------------------------------------------------------------------- /support/proxy/proxy-confs/well-known.subfolder.conf: -------------------------------------------------------------------------------- 1 | # Redirect .well-known to the well-known service 2 | 3 | location ^~ /.well-known/ { 4 | include /config/nginx/proxy.conf; 5 | resolver 127.0.0.11 valid=30s; 6 | set $upstream_app well-known; 7 | set $upstream_port 8080; 8 | set $upstream_proto http; 9 | proxy_pass $upstream_proto://$upstream_app:$upstream_port; # nosemgrep: generic.nginx.security.missing-internal.missing-internal, generic.nginx.security.dynamic-proxy-host.dynamic-proxy-host, generic.nginx.security.dynamic-proxy-scheme.dynamic-proxy-scheme 10 | } 11 | -------------------------------------------------------------------------------- /oada/utils/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Use yarn workspace as "entry point" 4 | CMD="corepack yarn workspace @oada/${OADA_SERVICE} run $*" 5 | 6 | # Wait for startup, then run CMD. 7 | ([ "${OADA_SERVICE}" = "startup" ] || /wait-for startup:8080 -q -t 0) && 8 | if [ ! -t 1 ] && [ -n "${PINO_TRANSPORT}" ]; then 9 | # Only pipe if PINO_TRANSPORT set and non-interactive 10 | FIFO=/tmp/pino-fifo 11 | rm -f "${FIFO}" 12 | mkfifo "${FIFO}" 13 | ${PINO_TRANSPORT} <"${FIFO}" & 14 | exec ${CMD} >"${FIFO}" 15 | else 16 | # Interactive or no transport set? 17 | exec ${CMD} 18 | fi -------------------------------------------------------------------------------- /charts/oada/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | Thank you for installing {{ .Chart.Name }}. 2 | 3 | Your release is named {{ .Release.Name }}. 4 | 5 | It is serving the domain {{ .Values.oada.domain }}. 6 | 7 | To learn more about the release, try: 8 | 9 | $ helm status {{ .Release.Name }} 10 | $ helm get all {{ .Release.Name }} 11 | {{- if .Values.global.development }} 12 | 13 | ################################################################################## 14 | ### WARNING: This chart is running in development mode! NOT FOR PRODUCTION USE ### 15 | ################################################################################## 16 | {{- end }} -------------------------------------------------------------------------------- /oada/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/node22", 3 | "compilerOptions": { 4 | "module": "nodenext", 5 | "moduleResolution": "nodenext", 6 | "allowSyntheticDefaultImports": true, 7 | "removeComments": true, 8 | "importHelpers": true, 9 | "composite": true, 10 | "strict": true, 11 | "alwaysStrict": true, 12 | "verbatimModuleSyntax": false, 13 | "noUncheckedIndexedAccess": true, 14 | "noUnusedLocals": true, 15 | "noUnusedParameters": true, 16 | "noImplicitThis": true, 17 | "noImplicitAny": true, 18 | "noImplicitOverride": true, 19 | "noErrorTruncation": true, 20 | "sourceMap": true, 21 | "declaration": true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /oada/libs/lib-arangodb/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | -------------------------------------------------------------------------------- /oada/libs/lib-config/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | -------------------------------------------------------------------------------- /support/proxy/http.d/ratelimit.conf: -------------------------------------------------------------------------------- 1 | limit_req_zone $binary_remote_addr zone=read_zone:10m rate=20r/s; 2 | limit_req zone=read_zone burst=400 delay=40; 3 | 4 | # Only limit writes 5 | map $request_method $write_limit { 6 | OPTIONS ''; 7 | HEAD ''; 8 | GET ''; 9 | default $binary_remote_addr; 10 | } 11 | limit_req_zone $write_limit zone=write_zone:10m rate=5r/s; 12 | limit_req zone=write_zone burst=50 delay=10; 13 | 14 | # Use 429 (Too Many Requests) for rate limit responses 15 | limit_req_status 429; 16 | limit_conn_status 429; 17 | 18 | # Tell clients to retry later 19 | map $status $retry_after { 20 | default ''; 21 | # Time (in seconds) client should wait before retry 22 | 429 '120'; 23 | } 24 | add_header Retry-After $retry_after always; 25 | -------------------------------------------------------------------------------- /oada/tests/config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | module.exports = require("@oada/lib-config")(require("./config.defaults.js")); 18 | -------------------------------------------------------------------------------- /oada/tests/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM oada/docker-base-node 2 | 3 | COPY ./entrypoint.sh /entrypoint.sh 4 | RUN chmod u+x /entrypoint.sh 5 | 6 | WORKDIR /code/tests 7 | # ---------------- 8 | 9 | # ----------------------------- 10 | # Ubuntu with nodejs and docker 11 | # ----------------------------- 12 | # FROM ubuntu:14.04 13 | # 14 | # COPY ./entrypoint.sh /entrypoint.sh 15 | # RUN chmod u+x /entrypoint.sh 16 | # 17 | # WORKDIR /code/tests 18 | # 19 | # RUN apt-get update 20 | # 21 | # # Install Node.js 22 | # RUN apt-get -qq install --yes curl 23 | # RUN curl --silent --location https://deb.nodesource.com/setup_4.x | sudo bash - 24 | # RUN apt-get -qq install --yes nodejs 25 | # 26 | # # Install docker 27 | # RUN apt-get -qq install --yes docker.io 28 | # ----------------------------- 29 | 30 | CMD /entrypoint.sh 31 | -------------------------------------------------------------------------------- /notes_on_making_client_certificates.md: -------------------------------------------------------------------------------- 1 | # Making client certificates - some notes from trying to do it 9-15-2017 2 | 3 | - There is a library to create them in OADA: oada-dyn-reg-metadata 4 | 5 | - There is some simple code written to use that library to sign them. 6 | It is not in github anywhere, but probably should be. Instead, 7 | it only exists on client.oada-dev.com at ~/make-registration. 8 | 9 | - node makeReg.js will read the keys from identity.oada-dev.com since 10 | they are served on the same machine, so it can just read them from the 11 | filesystem. These are served from identity.oada-dev.com/certs via the 12 | standard oada-ref-auth-js library. 13 | 14 | - You have to sign the software statement with a key that is listed at 15 | identity.oada-dev.com, otherwise it will not be a valid key. 16 | -------------------------------------------------------------------------------- /oada/libs/lib-arangodb/src/libs/exampledocs/putBodies.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | export default [{ _id: "putBodies/default:putbody123", bodystr: "{}" }]; 19 | -------------------------------------------------------------------------------- /charts/oada/Chart.yaml: -------------------------------------------------------------------------------- 1 | # vim: set ft=helm : 2 | apiVersion: v2 3 | name: oada 4 | description: A Helm chart for the OADA API server 5 | sources: 6 | - https://github.com/OADA/server 7 | icon: https://avatars.githubusercontent.com/u/6750653 8 | maintainers: 9 | - name: awlayton 10 | email: alex@layton.in 11 | type: application 12 | keywords: 13 | - api 14 | - oauth 2.0 15 | - oidc 16 | - oada 17 | version: 5.0.5 18 | appVersion: 4.0.0 19 | annotations: 20 | artifacthub.io/recommendations: | 21 | - url: https://artifacthub.io/packages/helm/cert-manager/cert-manager 22 | - url: https://artifacthub.io/packages/helm/redpanda-data/operator 23 | - url: https://github.com/arangodb/kube-arangodb#installation-of-latest-release-using-helm 24 | - url: https://artifacthub.io/packages/helm/ingress-nginx/ingress-nginx 25 | -------------------------------------------------------------------------------- /oada/services/permissions-handler/src/types.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | declare module "es-main" { 19 | function esMain(meta: unknown): boolean; 20 | export = esMain; 21 | } 22 | -------------------------------------------------------------------------------- /oada/.dockerignore: -------------------------------------------------------------------------------- 1 | # Don't copy host node_modules into images 2 | **/node_modules 3 | 4 | # Don't copy in git history? 5 | **/.git* 6 | 7 | # Don't copy tests into images? 8 | **/test 9 | **/tests 10 | **/__test__ 11 | **/__tests__ 12 | **/*.spec.* 13 | **/*.test.* 14 | 15 | **/*.log 16 | **/.DS_Store 17 | 18 | # Docker stuff 19 | **/Dockerfile 20 | **/.dockerignore 21 | 22 | # Editor junk 23 | **/tags* 24 | **/GTAGS 25 | **/GPATH 26 | **/GRTAGS 27 | **/.session* 28 | **/.undodir 29 | **/.history 30 | **/.vim 31 | **/.vscode 32 | **/.eslintignore 33 | **/.eslintrc.* 34 | **/.prettierignore 35 | **/commitlint.config.* 36 | 37 | **/README.* 38 | 39 | # Built TS etc. 40 | **/dist 41 | **/.test 42 | **/*.tsbuildinfo 43 | 44 | # yarn 3 stuff 45 | .yarn/* 46 | !.yarn/patches 47 | !.yarn/releases 48 | !.yarn/plugins 49 | !.yarn/versions 50 | .pnp.* 51 | # ignore sdk stuff 52 | .vim 53 | -------------------------------------------------------------------------------- /oada/services/http-handler/src/healthcheck.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /** 19 | * Checks the health endpoint and return success or failure. 20 | * 21 | * @packageDocumentation 22 | */ 23 | 24 | import "fastify-healthcheck/src/healthcheck"; 25 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | 3 | # 4 | # The above will handle all files NOT found below 5 | # https://help.github.com/articles/dealing-with-line-endings/ 6 | # https://github.com/Danimoth/gitattributes/blob/master/Web.gitattributes 7 | # Also taken from: https://gist.github.com/ajdruff/16427061a41ca8c08c05992a6c74f59e 8 | 9 | # These files are text and should be normalized (Convert crlf => lf) 10 | *.css text eol=lf 11 | *.js text eol=lf 12 | *.json text eol=lf 13 | *.htm text eol=lf 14 | *.html text eol=lf 15 | *.txt text eol=lf 16 | *.sh text eol=lf 17 | 18 | # These files are binary and should be left untouched 19 | # (binary is a macro for -text -diff) 20 | *.png binary 21 | *.jpg binary 22 | *.jpeg binary 23 | *.gif binary 24 | *.ico binary 25 | *.mov binary 26 | *.mp4 binary 27 | *.mp3 binary 28 | *.flv binary 29 | *.fla binary 30 | *.swf binary 31 | *.gz binary 32 | *.zip binary 33 | *.7z binary 34 | *.ttf binary 35 | *.pyc binary 36 | -------------------------------------------------------------------------------- /oada/tests/server/index.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const debug = require("debug"); 3 | const error = debug("oada-srvc-tests:server:error"); 4 | const info = debug("oada-srvc-tests:server:info"); 5 | 6 | const port = process.env.PORT || 80; 7 | const ip = process.env.IP || "localhost"; 8 | const app = (module.exports = express()); 9 | 10 | // Echo. 11 | const echo = "/echo"; 12 | app.get(echo, (request, res) => { 13 | info("Echo request recieved!"); 14 | const attachedToken = request.headers.authorization; 15 | info(` - Attached token info: ${attachedToken}`); 16 | res.send(`Echo page received request: ${request}`); 17 | }); 18 | 19 | // Run the server. 20 | app.listen(port, ip, function onStart(error_) { 21 | if (error_) { 22 | error(error_); 23 | } 24 | 25 | info( 26 | "==> 🌎 Listening on port %s. Open up http://%s:%s/ in your browser.", 27 | port, 28 | ip, 29 | port, 30 | ); 31 | }); 32 | -------------------------------------------------------------------------------- /oada/services/write-handler/src/types.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | declare module "timed-cache" { 19 | export = class Cache { 20 | constructor(options: { defaultTtl: number }); 21 | 22 | get(key: string): T; 23 | 24 | put(key: string, value: T): void; 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /oada/services/sync-handler/src/config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import libConfig from "@oada/lib-config"; 19 | 20 | export const { config, schema } = await libConfig({ 21 | kafka: { 22 | topics: { 23 | default: { 24 | httpResponse: "http_response", 25 | }, 26 | }, 27 | }, 28 | }); 29 | -------------------------------------------------------------------------------- /oada/tests/README.md: -------------------------------------------------------------------------------- 1 | Tests in this module generate dummy queries to test different oada-srvc micro services. 2 | 3 | ### Folder Structure 4 | 5 | - `selftest` (which requires `server`) 6 | - A test independent of all other OADA components to make sure the test module is able to issue valid HTTP requests. 7 | - The Express server in `server` should be running before the self-test. 8 | - `test` 9 | - Default Mocha tests which mimic the behaviors of a client (without worrying about what exactly goes on in OADA) and check whether the HTTP requests are as expected. 10 | - `test-lower-level` 11 | - Tests that also monitor the inside of the OADA (mainly Kafka) to make sure events happen as expected. 12 | - `test-host-level` 13 | - **_TODO_**: complete these tests if necessary. 14 | - Plan to write tests to kill containers and check whether they go back to life after some reasonable delay. 15 | 16 | ### TODO: 17 | 18 | - A (valid) token generation /request function / lib. 19 | -------------------------------------------------------------------------------- /oada/README.md: -------------------------------------------------------------------------------- 1 | # OADA micro-services 2 | 3 | This is a [yarn 3 monorepo][] using [pnp][]. 4 | It contains all the core "OADA" micro-services of the reference implementation, 5 | as well as some libraries for said services. 6 | 7 | ## Architecture 8 | 9 | The services are all JavaScript/TypeScript which runs in [Node.js][]. 10 | 11 | Messages between services are communicated via [kafka][], 12 | and the underlying database used is [arangodb][]. 13 | 14 | ## Administration commands 15 | 16 | Any `bin`s available in the `package.json` 17 | will be exposed as an administration CLI command (not via the OADA API). 18 | For example, the [`users`][] service has an `add` command 19 | (see [here](services/users/package.json)). 20 | 21 | [`users`]: services/users 22 | [yarn 3 monorepo]: https://yarnpkg.com/features/workspaces 23 | [pnp]: https://yarnpkg.com/features/pnp 24 | [node.js]: https://nodejs.org/en/ 25 | [arangodb]: https://www.arangodb.com 26 | [kafka]: https://kafka.apache.org 27 | -------------------------------------------------------------------------------- /biome.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": false, 3 | "$schema": "https://biomejs.dev/schemas/2.2.4/schema.json", 4 | "root": true, 5 | "vcs": { 6 | "enabled": true, 7 | "clientKind": "git", 8 | "useIgnoreFile": true 9 | }, 10 | "files": { 11 | "ignoreUnknown": false, 12 | "includes": ["**"] 13 | }, 14 | "formatter": { 15 | "enabled": true, 16 | "useEditorconfig": true 17 | }, 18 | "assist": { "actions": { "source": { "organizeImports": "on" } } }, 19 | "linter": { 20 | "enabled": true, 21 | "rules": { 22 | "recommended": true, 23 | "style": { 24 | "noParameterAssign": "error", 25 | "useAsConstAssertion": "error", 26 | "useDefaultParameterLast": "error", 27 | "useEnumInitializers": "error", 28 | "useSelfClosingElements": "error", 29 | "useSingleVarDeclarator": "error", 30 | "noUnusedTemplateLiteral": "error", 31 | "useNumberNamespace": "error", 32 | "noInferrableTypes": "error", 33 | "noUselessElse": "error" 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /oada/services/webhooks/src/config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import libConfig from "@oada/lib-config"; 19 | 20 | export const { config, schema } = await libConfig({ 21 | kafka: { 22 | topics: { 23 | httpResponse: { 24 | format: String, 25 | default: "http_response", 26 | }, 27 | }, 28 | }, 29 | }); 30 | -------------------------------------------------------------------------------- /oada/services/http-handler/src/requester.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import { Requester } from "@oada/lib-kafka"; 19 | 20 | import { config } from "./config.js"; 21 | 22 | // TODO: Is it better to have one requester per topic? 23 | const requester = new Requester({ 24 | consumeTopic: config.get("kafka.topics.httpResponse"), 25 | group: "http-handlers", 26 | }); 27 | 28 | export default requester; 29 | -------------------------------------------------------------------------------- /oada/services/rev-graph-update/src/config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | // TODO: Publish this to npm instead? 19 | import libConfig from "@oada/lib-config"; 20 | 21 | export const { config, schema } = await libConfig({ 22 | kafka: { 23 | topics: { 24 | default: { 25 | writeRequest: "write_request", 26 | httpResponse: "http_response", 27 | } as Record, 28 | }, 29 | }, 30 | }); 31 | -------------------------------------------------------------------------------- /oada/services/shares/src/config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import libConfig from "@oada/lib-config"; 19 | 20 | export const { config, schema } = await libConfig({ 21 | kafka: { 22 | topics: { 23 | writeRequest: { 24 | format: String, 25 | default: "write_request", 26 | }, 27 | httpResponse: { 28 | format: String, 29 | default: "http_response", 30 | }, 31 | }, 32 | }, 33 | }); 34 | -------------------------------------------------------------------------------- /oada/services/write-handler/src/config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import libConfig from "@oada/lib-config"; 19 | 20 | export const { config, schema } = await libConfig({ 21 | kafka: { 22 | topics: { 23 | writeRequest: { 24 | format: String, 25 | default: "write_request", 26 | }, 27 | httpResponse: { 28 | format: String, 29 | default: "http_response", 30 | }, 31 | }, 32 | }, 33 | }); 34 | -------------------------------------------------------------------------------- /oada/libs/lib-prom/src/types.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2022 Open Ag Data Alliance 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | declare module "nstats" { 18 | import type { Server as HTTPServer } from "node:http"; 19 | 20 | import type { Plugin } from "fastify-plugin"; 21 | import type { Server as WSServer } from "ws"; 22 | 23 | export interface NStats { 24 | fastify(): Plugin; 25 | toPrometheus(): string; 26 | } 27 | 28 | function nstats(ws?: WSServer, http?: HTTPServer, semver?: string): NStats; 29 | 30 | export = nstats; 31 | } 32 | -------------------------------------------------------------------------------- /oada/services/well-known/src/types.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2022 Open Ag Data Alliance 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | declare module "nstats" { 18 | import type { Server as HTTPServer } from "node:http"; 19 | 20 | import type { Plugin } from "fastify-plugin"; 21 | import type { Server as WSServer } from "ws"; 22 | 23 | export interface NStats { 24 | fastify(): Plugin; 25 | toPrometheus(): string; 26 | } 27 | 28 | function nstats(ws?: WSServer, http?: HTTPServer, semver?: string): NStats; 29 | 30 | export = nstats; 31 | } 32 | -------------------------------------------------------------------------------- /support/proxy/default: -------------------------------------------------------------------------------- 1 | ## Version 2020/12/11 - Changelog: https://github.com/linuxserver/docker-mods/blob/nginx-proxy-confs/root/defaults/nginx.conf 2 | 3 | server { 4 | listen 80 default_server; 5 | #listen 443 ssl; 6 | server_name _; 7 | 8 | root /config/www; 9 | 10 | index index.html index.htm index.php; 11 | 12 | # enable subfolder method reverse proxy confs 13 | include /config/nginx/proxy-confs/*.subfolder.conf; 14 | 15 | #ssl_certificate /config/keys/cert.crt; 16 | #ssl_certificate_key /config/keys/cert.key; 17 | 18 | 19 | client_max_body_size 0; 20 | 21 | location / { 22 | try_files $uri $uri/ /index.html /index.php?$args =404; 23 | } 24 | 25 | location ~ \.php$ { 26 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 27 | fastcgi_pass 127.0.0.1:9000; 28 | fastcgi_index index.php; 29 | include /etc/nginx/fastcgi_params; 30 | } 31 | 32 | } 33 | 34 | # enable subdomain method reverse proxy confs 35 | include /config/nginx/proxy-confs/*.subdomain.conf; 36 | # enable proxy cache for auth 37 | proxy_cache_path cache/ keys_zone=auth_cache:10m; -------------------------------------------------------------------------------- /oada/libs/lib-kafka/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | // @ts-expect-error the types are not correct 19 | export { KafkaJSError as KafkaError } from "kafkajs/src/errors.js"; 20 | export type { KafkaBase } from "./Base.js"; 21 | export * as init from "./init.js"; 22 | export { Requester } from "./Requester.js"; 23 | export { ReResponder } from "./ReResponder.js"; 24 | export { Responder } from "./Responder.js"; 25 | export { ResponderRequester } from "./ResponderRequester.js"; 26 | -------------------------------------------------------------------------------- /oada/libs/pino-debug/src/types.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | declare module "pino-debug" { 19 | export type { Logger } from "pino"; 20 | 21 | export interface Options { 22 | /** 23 | * @default {} 24 | */ 25 | map?: Record; 26 | /** 27 | * @default true 28 | */ 29 | auto?: boolean; 30 | skip?: readonly string[]; 31 | } 32 | 33 | function pinoDebug(logger: Logger, options: Options); 34 | 35 | export = pinoDebug; 36 | } 37 | -------------------------------------------------------------------------------- /oada/services/auth/src/db/flat/codes.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2022 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import type { Code } from "../models/code.js"; 19 | // @ts-expect-error IDEK 20 | import codes from "./codes.json"; 21 | 22 | const database = new Map(Object.entries(codes)); 23 | 24 | export function findByCode(code: string) { 25 | return structuredClone(database.get(code)); 26 | } 27 | 28 | export function save(code: Code) { 29 | database.set(code.code, structuredClone(code)); 30 | return findByCode(code.code); 31 | } 32 | -------------------------------------------------------------------------------- /oada/services/shares/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@oada/shares", 3 | "version": "4.0.0", 4 | "type": "module", 5 | "description": "", 6 | "author": "", 7 | "license": "Apache-2.0", 8 | "main": "dist/server.js", 9 | "engines": { 10 | "node": ">=20.0.0" 11 | }, 12 | "files": [ 13 | "src/**/*", 14 | "dist/**/*" 15 | ], 16 | "scripts": { 17 | "build": "yarn g:tsc", 18 | "clean": "yarn run build --clean", 19 | "start": "node ${INSPECT} --enable-source-maps --unhandled-rejections=strict dist/server.js", 20 | "test": "mocha" 21 | }, 22 | "mocha": { 23 | "require": "ts-node/register", 24 | "extension": [ 25 | "ts" 26 | ] 27 | }, 28 | "dependencies": { 29 | "@oada/lib-arangodb": "workspace:^", 30 | "@oada/lib-config": "workspace:^", 31 | "@oada/lib-kafka": "workspace:^", 32 | "@oada/lib-prom": "workspace:^", 33 | "@oada/pino-debug": "workspace:^", 34 | "debug": "^4.4.3", 35 | "tslib": "2.8.1" 36 | }, 37 | "devDependencies": { 38 | "@oada/write-handler": "workspace:^", 39 | "@types/debug": "^4.1.12" 40 | }, 41 | "volta": { 42 | "node": "22.5.1" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /oada/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@oada/server", 3 | "private": true, 4 | "workspaces": [ 5 | "services/*", 6 | "libs/*" 7 | ], 8 | "scripts": { 9 | "build": "yarn workspaces foreach -Apt run build", 10 | "clean": "yarn build --clean", 11 | "g:tsc": "cd $INIT_CWD && tsc -b", 12 | "g:pino-pretty": "pino-pretty" 13 | }, 14 | "devDependencies": { 15 | "@biomejs/biome": "^2.2.4", 16 | "@commitlint/cli": "^20.0.0", 17 | "@commitlint/config-conventional": "^20.0.0", 18 | "@tsconfig/node22": "^22.0.2", 19 | "@types/mocha": "^10.0.10", 20 | "@types/node": "^24.6.0", 21 | "@yarnpkg/sdks": "^3.2.3", 22 | "browserslist": "^4.26.2", 23 | "c8": "^10.1.3", 24 | "get-port": "^7.1.0", 25 | "tslib": "2.8.1", 26 | "typescript": "5.9.2", 27 | "update-browserslist-db": "^1.1.3", 28 | "zx": "^8.8.4" 29 | }, 30 | "dependencies": { 31 | "pino-pretty": "^13.1.1" 32 | }, 33 | "resolutions": { 34 | "superagent": "^10.0.0", 35 | "type-fest": "^5.0.1" 36 | }, 37 | "engines": { 38 | "node": ">=20.0.0" 39 | }, 40 | "volta": { 41 | "node": "22.5.1" 42 | }, 43 | "packageManager": "yarn@4.10.3" 44 | } 45 | -------------------------------------------------------------------------------- /oada/libs/pino-debug/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@oada/pino-debug", 3 | "version": "4.0.1", 4 | "description": "OADA pino-debug wrapper", 5 | "main": "dist/index.js", 6 | "type": "module", 7 | "engines": { 8 | "node": ">=20.0.0" 9 | }, 10 | "files": [ 11 | "src/**/*", 12 | "dist/**/*" 13 | ], 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/OADA/@oada/pino-debug.git" 17 | }, 18 | "scripts": { 19 | "build": "yarn g:tsc", 20 | "clean": "yarn run build --clean", 21 | "start": "node --enable-source-maps -r pino-debug dist/server.js" 22 | }, 23 | "author": "Alex Layton ", 24 | "license": "ISC", 25 | "dependencies": { 26 | "cls-rtracer": "^2.6.3", 27 | "is-interactive": "^2.0.0", 28 | "pino": "^9.12.0", 29 | "pino-caller": "^4.0.0", 30 | "pino-debug": "^3.0.0", 31 | "pino-loki": "^2.6.0", 32 | "pino-pretty": "^13.1.1", 33 | "tslib": "2.8.1" 34 | }, 35 | "devDependencies": { 36 | "@types/debug": "^4.1.12", 37 | "@types/node": "^24.6.0" 38 | }, 39 | "peerDependencies": { 40 | "debug": "*" 41 | }, 42 | "volta": { 43 | "node": "22.5.1" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /oada/services/users/src/config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import libConfig from "@oada/lib-config"; 19 | 20 | export const { config, schema } = await libConfig({ 21 | kafka: { 22 | topics: { 23 | userRequest: { 24 | format: String, 25 | default: "user_request", 26 | }, 27 | writeRequest: { 28 | format: String, 29 | default: "write_request", 30 | }, 31 | httpResponse: { 32 | format: String, 33 | default: "http_response", 34 | }, 35 | }, 36 | }, 37 | }); 38 | -------------------------------------------------------------------------------- /oada/libs/lib-arangodb/src/libs/exampledocs/codes.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import type { Code, CodeID } from "../codes.js"; 19 | 20 | export default [ 21 | { 22 | _id: "codes/default:codes_xyz_123" as CodeID, 23 | code: "xyz", 24 | scope: [], 25 | nonce: "", 26 | user: "users/123frank", 27 | createTime: 1_413_831_649_937, 28 | expiresIn: 60, 29 | redeemed: true, 30 | clientId: "jf93caauf3uzud7f308faesf3@provider.oada-dev.com", 31 | redirectUri: "http://client.oada-dev.com/redirect", 32 | }, 33 | ] as const satisfies Code[]; 34 | -------------------------------------------------------------------------------- /oada/libs/models/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@oada/models", 3 | "version": "4.0.0", 4 | "description": "OADA model", 5 | "type": "module", 6 | "engines": { 7 | "node": ">=20.0.0" 8 | }, 9 | "exports": { 10 | "./user": "./dist/user.js", 11 | "./client": "./dist/client.js", 12 | "./authorization": "./dist/authorization.js", 13 | "./decorators": "./dist/decorators.js" 14 | }, 15 | "files": [ 16 | "src/**/*", 17 | "dist/**/*" 18 | ], 19 | "scripts": { 20 | "build": "yarn g:tsc", 21 | "clean": "yarn run build --clean", 22 | "test": "echo \"Error: no test specified\" && exit 1" 23 | }, 24 | "keywords": [ 25 | "oada", 26 | "lib" 27 | ], 28 | "author": "Alex Layton (https://github.com/awlayton)", 29 | "license": "Apache-2.0", 30 | "dependencies": { 31 | "@oada/types": "^4.0.0", 32 | "@qlever-llc/interface2class": "^1.1.0", 33 | "tslib": "2.8.1", 34 | "type-fest": "^5.0.1", 35 | "xksuid": "^0.0.4" 36 | }, 37 | "peerDependencies": { 38 | "type-fest": "*" 39 | }, 40 | "volta": { 41 | "node": "22.5.1" 42 | }, 43 | "devDependencies": { 44 | "@types/node": "^24.6.0", 45 | "jose": "^6.1.0" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /oada/services/auth/src/db/flat/clients.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2022 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import type { Client, IClients } from "../models/client.js"; 19 | 20 | // @ts-expect-error IDEK 21 | import clients from "./clients.json"; 22 | 23 | const database = new Map(Object.entries(clients as Record)); 24 | 25 | export const findById = ((id: string) => 26 | structuredClone(database.get(id)) ?? 27 | undefined) satisfies IClients["findById"]; 28 | 29 | export const save = ((client: Client) => { 30 | database.set(client.client_id, client); 31 | }) satisfies IClients["save"]; 32 | -------------------------------------------------------------------------------- /oada/services/permissions-handler/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@oada/permissions-handler", 3 | "description": "", 4 | "version": "4.0.0", 5 | "type": "module", 6 | "author": "", 7 | "license": "Apache-2.0", 8 | "main": "dist/server.js", 9 | "engines": { 10 | "node": ">=20.0.0" 11 | }, 12 | "files": [ 13 | "src/**/*", 14 | "dist/**/*" 15 | ], 16 | "scripts": { 17 | "build": "yarn g:tsc", 18 | "clean": "yarn run build --clean", 19 | "start": "node ${INSPECT} --enable-source-maps --unhandled-rejections=strict dist/server.js", 20 | "test": "mocha" 21 | }, 22 | "mocha": { 23 | "require": "ts-node/register", 24 | "extension": [ 25 | "ts" 26 | ] 27 | }, 28 | "dependencies": { 29 | "@oada/lib-config": "workspace:^", 30 | "@oada/lib-kafka": "workspace:^", 31 | "@oada/lib-prom": "workspace:^", 32 | "@oada/pino-debug": "workspace:^", 33 | "debug": "^4.4.3", 34 | "es-main": "^1.4.0", 35 | "tslib": "2.8.1", 36 | "type-is": "^2.0.1" 37 | }, 38 | "devDependencies": { 39 | "@types/debug": "^4.1.12", 40 | "@types/node": "^24.6.0", 41 | "@types/type-is": "^1.6.7" 42 | }, 43 | "volta": { 44 | "node": "22.5.1" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /oada/services/webhooks/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@oada/webhooks", 3 | "version": "4.0.0", 4 | "type": "module", 5 | "description": "", 6 | "main": "dist/server.js", 7 | "engines": { 8 | "node": ">=20.0.0" 9 | }, 10 | "files": [ 11 | "src/**/*", 12 | "dist/**/*" 13 | ], 14 | "scripts": { 15 | "build": "yarn g:tsc", 16 | "clean": "yarn run build --clean", 17 | "start": "node ${INSPECT} --enable-source-maps --unhandled-rejections=strict dist/server.js", 18 | "test": "mocha" 19 | }, 20 | "mocha": { 21 | "require": "ts-node/register", 22 | "extension": [ 23 | "ts" 24 | ] 25 | }, 26 | "author": "", 27 | "license": "Apache-2.0", 28 | "dependencies": { 29 | "@oada/lib-arangodb": "workspace:^", 30 | "@oada/lib-config": "workspace:^", 31 | "@oada/lib-kafka": "workspace:^", 32 | "@oada/lib-prom": "workspace:^", 33 | "@oada/pino-debug": "workspace:^", 34 | "debug": "^4.4.3", 35 | "got": "^14.4.9", 36 | "tslib": "2.8.1" 37 | }, 38 | "devDependencies": { 39 | "@oada/types": "^4.0.0", 40 | "@oada/write-handler": "workspace:^", 41 | "@types/debug": "^4.1.12" 42 | }, 43 | "volta": { 44 | "node": "22.5.1" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /oada/services/http-handler/src/types.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | declare module "es-main" { 19 | export default function esMain(meta: unknown): boolean; 20 | } 21 | 22 | declare module "nstats" { 23 | import type { Server as HTTPServer } from "node:http"; 24 | 25 | import type { Plugin } from "fastify-plugin"; 26 | import type { Server as WSServer } from "ws"; 27 | 28 | export interface NStats { 29 | fastify(): Plugin; 30 | toPrometheus(): string; 31 | } 32 | 33 | function nstats(ws?: WSServer, http?: HTTPServer, semver?: string): NStats; 34 | 35 | export = nstats; 36 | } 37 | -------------------------------------------------------------------------------- /oada/services/permissions-handler/src/config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import libConfig from "@oada/lib-config"; 19 | 20 | export const { config, schema } = await libConfig({ 21 | kafka: { 22 | topics: { 23 | permissionsRequest: { 24 | format: String, 25 | default: "permissions_request", 26 | }, 27 | httpResponse: { 28 | format: String, 29 | default: "http_response", 30 | }, 31 | writeRequest: { 32 | format: String, 33 | default: "write_request", 34 | }, 35 | }, 36 | groupId: "permissions", 37 | }, 38 | }); 39 | -------------------------------------------------------------------------------- /oada/libs/lib-kafka/src/init.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2022 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import { config } from "./config.js"; 19 | 20 | import Kafka from "./Kafka.js"; 21 | 22 | /** 23 | * Ensure our Kafka topics exist 24 | */ 25 | export async function run(): Promise { 26 | const kafka = new Kafka(); 27 | const topics = config.get("kafka.topics"); 28 | 29 | const admin = kafka.admin(); 30 | await admin.connect(); 31 | try { 32 | await admin.createTopics({ 33 | waitForLeaders: false, 34 | topics: Object.values(topics).map((topic) => ({ topic })), 35 | }); 36 | } finally { 37 | await admin.disconnect(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /oada/services/users/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@oada/users", 3 | "version": "4.0.0", 4 | "type": "module", 5 | "description": "", 6 | "author": "Alex Layton ", 7 | "license": "Apache-2.0", 8 | "main": "dist/server.js", 9 | "module": "lib/server.ts", 10 | "engines": { 11 | "node": ">=20.0.0" 12 | }, 13 | "files": [ 14 | "src/**/*", 15 | "dist/**/*" 16 | ], 17 | "scripts": { 18 | "build": "yarn g:tsc", 19 | "clean": "yarn run build --clean", 20 | "start": "node ${INSPECT} --enable-source-maps --unhandled-rejections=strict dist/server.js" 21 | }, 22 | "bin": { 23 | "add": "./dist/cli/useradd.js" 24 | }, 25 | "dependencies": { 26 | "@oada/lib-arangodb": "workspace:^", 27 | "@oada/lib-config": "workspace:^", 28 | "@oada/lib-kafka": "workspace:^", 29 | "@oada/lib-prom": "workspace:^", 30 | "@oada/models": "workspace:^", 31 | "@oada/pino-debug": "workspace:^", 32 | "chalk": "^5.6.2", 33 | "cmd-ts": "^0.14.2", 34 | "debug": "^4.4.3", 35 | "es-main": "^1.4.0", 36 | "ksuid": "^3.0.0", 37 | "tslib": "2.8.1" 38 | }, 39 | "devDependencies": { 40 | "@types/debug": "^4.1.12", 41 | "type-fest": "^5.0.1" 42 | }, 43 | "volta": { 44 | "node": "22.5.1" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /oada/libs/lib-kafka/src/ReResponder.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import ksuid from "ksuid"; 19 | import { DATA, REQ_ID_KEY } from "./Base.js"; 20 | import { Responder } from "./Responder.js"; 21 | 22 | // Class for generate new requests in response to others 23 | // (without needing the answer) 24 | export class ReResponder extends Responder { 25 | constructor(...rest: ConstructorParameters) { 26 | super(...rest); 27 | 28 | // Make everything look like a new request 29 | super.on(DATA, (request: Record) => { 30 | request[REQ_ID_KEY] = ksuid.randomSync().string; 31 | }); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /oada/tests/test/get.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | const axios = require("axios"); 18 | const { expect } = require("chai"); 19 | process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; 20 | 21 | describe("testing a simple GET request", () => { 22 | it("will have a valid response", () => 23 | axios({ 24 | url: "https://proxy/bookmarks", 25 | method: "get", 26 | headers: { 27 | Authorization: "Bearer abc", 28 | }, 29 | }) 30 | .then((response) => { 31 | expect(response.status).to.equal(200); 32 | }) 33 | .catch((error) => { 34 | console.log("the get failed", error); 35 | throw error; 36 | })); 37 | }); 38 | -------------------------------------------------------------------------------- /oada/services/auth/src/db/flat/tokens.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2024 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import type { ITokens, Token } from "../models/token.js"; 19 | // @ts-expect-error IDEK 20 | import tokens from "./tokens.json"; 21 | 22 | const database = new Map(Object.entries(tokens as Record)); 23 | 24 | export const verify = ((token: string) => { 25 | const found = structuredClone(database.get(token)); 26 | if (!found) { 27 | throw new Error("Token not found"); 28 | } 29 | 30 | return found; 31 | }) satisfies ITokens["verify"]; 32 | 33 | export const create = ((token: Token) => { 34 | database.set(token.jti, token); 35 | return token.jti; 36 | }) satisfies ITokens["create"]; 37 | -------------------------------------------------------------------------------- /charts/oada/templates/binary-data.yaml: -------------------------------------------------------------------------------- 1 | {{/* vim: set ft=helm : */}} 2 | {{/* 3 | * Copyright 2022 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */}} 17 | {{- $name := print "binary-data-" $.Release.Name -}} 18 | {{- if empty (lookup "v1" "PersistentVolumeClaim" $.Release.Namespace $name) }} 19 | apiVersion: v1 20 | kind: PersistentVolumeClaim 21 | metadata: 22 | annotations: 23 | helm.sh/resource-policy: keep 24 | namespace: {{ .Release.Namespace }} 25 | name: {{ $name }} 26 | labels: 27 | app.kubernetes.io/component: binary-data 28 | {{- include "oada.chart.labels" . | nindent 4 }} 29 | spec: 30 | accessModes: 31 | - ReadWriteOnce 32 | resources: 33 | requests: 34 | storage: 100Mi 35 | {{- end -}} 36 | 37 | -------------------------------------------------------------------------------- /oada/libs/lib-arangodb/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | export { db as arango } from "./db.js"; 19 | 20 | export * as init from "./init.js"; 21 | export * as authorizations from "./libs/authorizations.js"; 22 | export * as changes from "./libs/changes.js"; 23 | export * as clients from "./libs/clients.js"; 24 | export * as codes from "./libs/codes.js"; 25 | export * as deviceCodes from "./libs/deviceCodes.js"; 26 | export { ArangoError, ArangoErrorCode } from "./libs/errors.js"; 27 | export * as putBodies from "./libs/putBodies.js"; 28 | export * as remoteResources from "./libs/remoteResources.js"; 29 | export * as resources from "./libs/resources.js"; 30 | export * as users from "./libs/users.js"; 31 | -------------------------------------------------------------------------------- /oada/services/auth/src/db/flat/users.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2022 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import type { IUsers, User } from "../models/user.js"; 19 | 20 | // @ts-expect-error IDEK 21 | import users from "./users.json"; 22 | 23 | const database = new Map(Object.entries(users as Record)); 24 | 25 | export const findByUsername = ((username: string) => 26 | structuredClone(database.get(username)) ?? 27 | undefined) satisfies IUsers["findByUsername"]; 28 | 29 | export const findByUsernamePassword = ((username: string, password: string) => { 30 | const user = database.get(username); 31 | return user?.password === password ? structuredClone(user) : undefined; 32 | }) satisfies IUsers["findByUsernamePassword"]; 33 | -------------------------------------------------------------------------------- /charts/oada/templates/tests/well-known.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | * Copyright 2022 Open Ag Data Alliance 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */}} 16 | {{- range tuple "oada-configuration" "openid-configuration" -}} 17 | --- 18 | apiVersion: v1 19 | kind: Pod 20 | metadata: 21 | name: test-{{ . }}-{{ $.Release.Name }} 22 | labels: 23 | app.kubernetes.io/component: test-{{ . }} 24 | {{- include "oada.chart.labels" $ | nindent 4 }} 25 | annotations: 26 | "helm.sh/hook": test 27 | spec: 28 | containers: 29 | - name: {{ . }} 30 | image: curlimages/curl 31 | args: 32 | {{- if $.Values.global.development }} 33 | - --verbose 34 | {{- end }} 35 | - http://well-known-{{ $.Release.Name }}/.well-known/{{ . }} 36 | restartPolicy: Never 37 | {{- end -}} -------------------------------------------------------------------------------- /oada/libs/lib-prom/README.md: -------------------------------------------------------------------------------- 1 | # OADA Prometheus client 2 | 3 | [![Version](https://img.shields.io/npm/v/@oada/lib-prom.svg)](https://npmjs.org/package/@oada/lib-prom) 4 | [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier) 5 | [![License](https://img.shields.io/github/license/OADA/server)](LICENSE) 6 | 7 | A high-level Prometheus client using [prom-client][]. 8 | It automatically handles initializing a client for you and exposing the metrics over HTTP. 9 | 10 | Default metrics recommended by Prometheus are automatically registered. 11 | You can, and likely should, register your own additional [metrics][]. 12 | 13 | ## Usage 14 | 15 | ```typescript 16 | // See prom-client README for details on available metric types 17 | import { Counter, Gauge, Histogram, Summary } from '@oada/lib-prom'; 18 | 19 | // Create metric(s) of your own 20 | const counter = new client.Counter({ 21 | name: 'metric_name', 22 | help: 'metric_help', 23 | }); 24 | 25 | // ...Your code here... 26 | 27 | // Update your metrics as needed 28 | counter.inc(); // e.g., increment a counter 29 | 30 | // ...Your code here... 31 | 32 | // Any metrics you create will be exported over HTTP for Prometheus to scrape 33 | ``` 34 | 35 | [prom-client]: https://github.com/siimon/prom-client 36 | [metrics]: https://github.com/siimon/prom-client#custom-metrics 37 | -------------------------------------------------------------------------------- /oada/libs/pino-debug/README.md: -------------------------------------------------------------------------------- 1 | # @oada/pino-debug 2 | 3 | [![Version](https://img.shields.io/npm/v/@oada/pino-debug.svg)](https://npmjs.org/package/@oada/pino-debug) 4 | [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier) 5 | [![License](https://img.shields.io/github/license/OADA/server)](LICENSE) 6 | 7 | A library for handle making 8 | [debug.js][] work automatically with [pino][]. 9 | 10 | ## Usage 11 | 12 | Import this library, 13 | then just use [debug.js][] as normal. 14 | 15 | ```typescript 16 | // You probably want this to be your first import in your main file 17 | import '@oada/pino-debug'; 18 | 19 | // Then just use debug.js as normal 20 | import debug from 'debug'; 21 | 22 | const info = debug('example:info'); 23 | 24 | // Pass a context object and a message string 25 | info({/* ...context */});, 'Hello world!'); 26 | ``` 27 | 28 | ### Advanced Usage 29 | 30 | The [pino][] API can still be accessed too. 31 | 32 | ```typescript 33 | // If you want to access pino, it is exported by this lib 34 | import { pino } from '@oada/pino-debug'; 35 | 36 | /** 37 | * See the pino API for what you can do 38 | * !!! DO NOT import pino directly !!! 39 | */ 40 | const logger = pino({ 41 | /* ...options */ 42 | }); 43 | ``` 44 | 45 | [debug.js]: https://github.com/debug-js/debug 46 | [pino]: https://github.com/pinojs/pino 47 | -------------------------------------------------------------------------------- /oada/libs/lib-prom/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@oada/lib-prom", 3 | "version": "4.0.2", 4 | "description": "OADA Prometheus library", 5 | "main": "./dist/index.js", 6 | "type": "module", 7 | "engines": { 8 | "node": ">=20.0.0" 9 | }, 10 | "files": [ 11 | "src/**/*", 12 | "dist/**/*" 13 | ], 14 | "scripts": { 15 | "build": "yarn g:tsc", 16 | "clean": "yarn run build --clean", 17 | "test": "yarn run build test && ava" 18 | }, 19 | "ava": { 20 | "typescript": { 21 | "extensions": [ 22 | "ts" 23 | ], 24 | "rewritePaths": { 25 | "src/": "dist/", 26 | "test/": ".test/" 27 | }, 28 | "compile": false 29 | } 30 | }, 31 | "repository": { 32 | "type": "git", 33 | "url": "git+https://github.com/OADA/@oada/lib-kafka.git" 34 | }, 35 | "author": "Alex Layton ", 36 | "license": "Apache-2.0", 37 | "dependencies": { 38 | "@oada/lib-config": "workspace:^", 39 | "prom-client": "^15.1.3", 40 | "tslib": "2.8.1" 41 | }, 42 | "devDependencies": { 43 | "@ava/typescript": "^6.0.0", 44 | "@types/convict": "^6.1.6", 45 | "@types/node": "^24.6.0", 46 | "@types/ws": "^8.18.1", 47 | "ava": "6.4.1", 48 | "fastify-plugin": "^5.1.0" 49 | }, 50 | "volta": { 51 | "node": "22.5.1" 52 | }, 53 | "optionalDependencies": { 54 | "nstats": "^7.0.0" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /oada/services/auth/src/db/arango/codes.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import { codes } from "@oada/lib-arangodb"; 19 | import debug from "debug"; 20 | 21 | import type { ICode } from "../models/code.js"; 22 | 23 | const trace = debug("arango:codes:trace"); 24 | 25 | export async function findByCode(code: string): Promise { 26 | trace("findByCode: searching for code %s", code); 27 | const found = await codes.findByCode(code); 28 | if (!found) { 29 | return found; 30 | } 31 | 32 | const { _id, ...c } = found; 33 | return { ...c, id: _id, user: c.user }; 34 | } 35 | 36 | export async function save(code: ICode) { 37 | const { id, user, ...c } = code; 38 | return codes.save({ 39 | ...c, 40 | _id: id, 41 | user, 42 | }); 43 | } 44 | -------------------------------------------------------------------------------- /oada/services/sync-handler/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@oada/sync-handler", 3 | "version": "4.0.0", 4 | "type": "module", 5 | "description": "", 6 | "main": "dist/server.js", 7 | "engines": { 8 | "node": ">=20.0.0" 9 | }, 10 | "files": [ 11 | "src/**/*", 12 | "dist/**/*" 13 | ], 14 | "scripts": { 15 | "build": "yarn g:tsc", 16 | "clean": "yarn run build --clean", 17 | "start": "node ${INSPECT} --enable-source-maps --unhandled-rejections=strict dist/server.js", 18 | "test": "mocha" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "git+ssh://git@github.com/OADA/oada-srvc-sync-handler.git" 23 | }, 24 | "author": "awlayton", 25 | "license": "Apache-2.0", 26 | "bugs": { 27 | "url": "https://github.com/OADA/oada-srvc-sync-handler/issues" 28 | }, 29 | "homepage": "https://github.com/OADA/oada-srvc-sync-handler#readme", 30 | "dependencies": { 31 | "@oada/lib-arangodb": "workspace:^", 32 | "@oada/lib-config": "workspace:^", 33 | "@oada/lib-kafka": "workspace:^", 34 | "@oada/lib-prom": "workspace:^", 35 | "@oada/pino-debug": "workspace:^", 36 | "debug": "^4.4.3", 37 | "got": "^14.4.9", 38 | "tslib": "2.8.1" 39 | }, 40 | "devDependencies": { 41 | "@oada/write-handler": "workspace:^", 42 | "@types/debug": "^4.1.12", 43 | "@types/node": "^24.6.0" 44 | }, 45 | "volta": { 46 | "node": "22.5.1" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /oada/services/startup/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@oada/startup", 3 | "version": "4.0.0", 4 | "type": "module", 5 | "description": "Handles startup of services for docker in OADA docker implementation.", 6 | "main": "dist/index.js", 7 | "engines": { 8 | "node": ">=20.0.0" 9 | }, 10 | "files": [ 11 | "src/**/*", 12 | "dist/**/*" 13 | ], 14 | "scripts": { 15 | "build": "yarn g:tsc", 16 | "clean": "yarn run build --clean", 17 | "start": "node ${INSPECT} --enable-source-maps --unhandled-rejections=strict dist/index.js", 18 | "test": "echo \"Error: no test specified\" && exit 1" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "git+https://github.com/oada/oada-srvc-startup.git" 23 | }, 24 | "keywords": [ 25 | "oada", 26 | "startup", 27 | "docker" 28 | ], 29 | "author": "Aaron Ault", 30 | "license": "Apache-2.0", 31 | "bugs": { 32 | "url": "https://github.com/oada/oada-srvc-startup/issues" 33 | }, 34 | "homepage": "https://github.com/oada/oada-srvc-startup#readme", 35 | "dependencies": { 36 | "@oada/lib-arangodb": "workspace:^", 37 | "@oada/lib-kafka": "workspace:^", 38 | "@oada/pino-debug": "workspace:^", 39 | "debug": "^4.4.3", 40 | "tslib": "2.8.1" 41 | }, 42 | "devDependencies": { 43 | "@types/debug": "^4.1.12", 44 | "@types/node": "^24.6.0" 45 | }, 46 | "volta": { 47 | "node": "22.5.1" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /oada/libs/lib-prom/src/config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2022 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import libConfig from "@oada/lib-config"; 19 | 20 | export const { config, schema } = await libConfig({ 21 | prometheus: { 22 | port: { 23 | doc: "Port for exposing metrics endpoint", 24 | format: "port", 25 | default: 3000, 26 | env: "PROM_PORT", 27 | arg: "prom-port", 28 | }, 29 | endpoint: { 30 | doc: "Endpoint for exposing metrics", 31 | format: String, 32 | default: "/metrics", 33 | env: "PROM_ENDPOINT", 34 | arg: "prom-endpoint", 35 | }, 36 | host: { 37 | doc: "Bind host for exposing metrics endpoint", 38 | format: String, 39 | default: "0.0.0.0", 40 | env: "PROM_HOST", 41 | arg: "prom-host", 42 | }, 43 | }, 44 | }); 45 | -------------------------------------------------------------------------------- /support/proxy/selfsigned/fullchain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDtTCCAp2gAwIBAgIUMzFcNPbywSHjGdlZE1saKh7L7MkwDQYJKoZIhvcNAQEL 3 | BQAwajELMAkGA1UEBhMCVVMxDzANBgNVBAgMBk9yZWdvbjERMA8GA1UEBwwIUG9y 4 | dGxhbmQxFTATBgNVBAoMDENvbXBhbnkgTmFtZTEMMAoGA1UECwwDT3JnMRIwEAYD 5 | VQQDDAlsb2NhbGhvc3QwHhcNMjEwMjEyMjAyODQzWhcNMjIwMjEyMjAyODQzWjBq 6 | MQswCQYDVQQGEwJVUzEPMA0GA1UECAwGT3JlZ29uMREwDwYDVQQHDAhQb3J0bGFu 7 | ZDEVMBMGA1UECgwMQ29tcGFueSBOYW1lMQwwCgYDVQQLDANPcmcxEjAQBgNVBAMM 8 | CWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9DAXVe 9 | Xp/noZslZmSg2alqPGGGcwZ6ujTOn8mTKyZ0r4G/7HcRNjFwQ6XP0k/yPaAuZLOW 10 | WoCXq9l+qRm/qRlF5sG/NHE/nQkIlGVZAFBTiBshJ0ILckrHmmHLz9AefZGtDyRp 11 | Yyl3PGH0tyEqy9/n6F5YJZNzJ/oUKQKP8oqOcEEln1PAzia5304bKjhOYaBAZA5X 12 | 6eMTRPn5CeG8rvyIfmJzl91axCgUf86vwbrtf4tFM/EzNK1fQ3aWkcoC6JYpr2kr 13 | Q0K13tFkzn2/NlucFlzs+M0oyFRqm2Ups+0ICQU2IL1ACnrNanlltt8YysUOKoWM 14 | pKqty7PyEbqvG1kCAwEAAaNTMFEwHQYDVR0OBBYEFFsmC1Euz8ia1GDGmY10EfLC 15 | +8mBMB8GA1UdIwQYMBaAFFsmC1Euz8ia1GDGmY10EfLC+8mBMA8GA1UdEwEB/wQF 16 | MAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFv09KOIvCZ3kmYpPb+p0vzbS11oNS8E 17 | tcgU3C+4P5lec6bmew8bxmZ79mW5cb+Taa6Z/ddGb8UsDzhRwT8ibzDkxuSF3VSZ 18 | Qz99B5HO8mhiNTWOwFHLsMXp8nkLcpP2GrGkbqnaMZzTCt9BK1kcQxsbgAjyoe1Q 19 | 4p3sErTPch85H9S3h8hk953izccwBilXsqo3ypLDjgMrbMYUHlbGw31HYeVOpZeG 20 | 85hUvpMDX1Gb5DlQq6IlAHfeQMt2GNCk4+ZJBESayl70JJ1h89g1uyySz11y2Sfz 21 | ja71aAOdYNCgNOR5ZSVBfY0812JAo/3ri50GbIF0ol/CS7EAxfZrAMU= 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /oada/services/auth/src/db/arango/clients.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import { clients } from "@oada/lib-arangodb"; 19 | import debug from "debug"; 20 | 21 | import type { Client, IClients } from "../models/client.js"; 22 | 23 | const trace = debug("arango:client:trace"); 24 | 25 | export const findById = (async (id: string) => { 26 | trace('Retrieving client { client_id: "%s" }', id); 27 | const found = await clients.findById(id); 28 | if (!found) { 29 | return found; 30 | } 31 | 32 | const { _id, ...client } = found; 33 | return { ...client, id: _id as string }; 34 | }) satisfies IClients["findById"]; 35 | 36 | export const save = (async (client: Client) => { 37 | trace("Saving clientId %s", client.client_id); 38 | await clients.save(client); 39 | }) satisfies IClients["save"]; 40 | -------------------------------------------------------------------------------- /oada/libs/lib-arangodb/test/resources.test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import test from "ava"; 19 | 20 | import { init, resources } from "../dist/index.js"; 21 | 22 | test.before(async () => { 23 | await init.run(); 24 | }); 25 | 26 | test.after(async () => { 27 | await init.cleanup(); 28 | }); 29 | 30 | test("should find parents based on resource id", async (t) => { 31 | const p = await resources.getParents("/resources:default:resources_rock_123"); 32 | t.plan(3); 33 | 34 | // eslint-disable-next-line no-unreachable-loop 35 | for await (const parent of p) { 36 | t.is(parent.path, "/rocks-index/90j2klfdjss"); 37 | t.is(parent.resource_id, "resources/default:resources_rocks_123"); 38 | t.is(parent.contentType, "application/vnd.oada.rocks.1+json"); 39 | break; 40 | } 41 | }); 42 | -------------------------------------------------------------------------------- /oada/tests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@oada/tests", 3 | "version": "4.0.0", 4 | "type": "module", 5 | "description": "Generate dummy messages to test different oada microservices.", 6 | "main": "", 7 | "engines": { 8 | "node": ">=20.0.0" 9 | }, 10 | "files": [ 11 | "src/**/*", 12 | "dist/**/*" 13 | ], 14 | "dependencies": { 15 | "@oada/tests": "file:", 16 | "axios": "^1.8.3", 17 | "bluebird": "^3.7.2", 18 | "chai": "^5.2.0", 19 | "debug": "^4.4.0", 20 | "kafka-node": "^5.0.0", 21 | "md5": "^2.3.0", 22 | "mocha": "^11.1.0", 23 | "node-exec-promise": "^1.0.2", 24 | "uuid": "^11.1.0", 25 | "validator": "^13.12.0", 26 | "ws": "^8.18.1" 27 | }, 28 | "devDependencies": { 29 | "express": "^4.21.2" 30 | }, 31 | "scripts": { 32 | "selftestserver": "IP=localhost PORT=80 node server", 33 | "selftest": "NODE_ENV=selftest DEBUG='*' mocha selftest", 34 | "debughost": "DEBUG='tests:*' isTest=true mocha 'test-host-level/*.js'", 35 | "debuglow": "DEBUG='tests:*' isTest=true mocha 'test-lower-level/*.js'", 36 | "debug": "DEBUG='tests:*' isTest=true mocha 'test/*.js'", 37 | "start": "NODE_ENV=production isTest=true mocha 'test/*.js'" 38 | }, 39 | "mocha": { 40 | "ui": "bdd", 41 | "exit": true 42 | }, 43 | "author": "Yaguang Zhang", 44 | "license": "Apache-2.0", 45 | "volta": { 46 | "node": "22.5.1" 47 | }, 48 | "packageManager": "yarn@4.7.0" 49 | } 50 | -------------------------------------------------------------------------------- /oada/libs/lib-kafka/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@oada/lib-kafka", 3 | "version": "4.0.0", 4 | "description": "OADA Kafka library", 5 | "main": "./dist/index.js", 6 | "type": "module", 7 | "engines": { 8 | "node": ">=20.0.0" 9 | }, 10 | "files": [ 11 | "src/**/*", 12 | "dist/**/*" 13 | ], 14 | "scripts": { 15 | "build": "yarn g:tsc", 16 | "clean": "yarn run build --clean", 17 | "test": "yarn run build test && ava" 18 | }, 19 | "ava": { 20 | "typescript": { 21 | "extensions": [ 22 | "ts" 23 | ], 24 | "rewritePaths": { 25 | "src/": "dist/", 26 | "test/": ".test/" 27 | }, 28 | "compile": false 29 | } 30 | }, 31 | "repository": { 32 | "type": "git", 33 | "url": "git+https://github.com/OADA/@oada/lib-kafka.git" 34 | }, 35 | "author": "Alex Layton ", 36 | "license": "Apache-2.0", 37 | "dependencies": { 38 | "@oada/lib-config": "workspace:^", 39 | "cls-rtracer": "^2.6.3", 40 | "debug": "^4.4.3", 41 | "eventemitter3": "^5.0.1", 42 | "kafkajs": "^2.2.4", 43 | "ksuid": "^3.0.0", 44 | "tslib": "2.8.1", 45 | "uuid": "^13.0.0" 46 | }, 47 | "devDependencies": { 48 | "@ava/typescript": "^6.0.0", 49 | "@types/convict": "^6.1.6", 50 | "@types/debug": "^4.1.12", 51 | "@types/node": "^24.6.0", 52 | "@types/uuid": "^11.0.0", 53 | "ava": "6.4.1" 54 | }, 55 | "volta": { 56 | "node": "22.5.1" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /.github/workflows/validate-codeowners.yml: -------------------------------------------------------------------------------- 1 | name: Validate Codeowners file 2 | 3 | permissions: read-all 4 | 5 | on: 6 | push: 7 | branches: 8 | - '**' 9 | tags-ignore: 10 | - '**' 11 | pull_request: 12 | branches: 13 | - '**' 14 | 15 | jobs: 16 | validate-codeowners: 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | # Check out repo to be validated in enxt stop 21 | - uses: actions/checkout@v5 22 | 23 | # Ensure that the owners file is valid 24 | # https://github.com/marketplace/actions/github-codeowners-validator 25 | - name: GitHub CODEOWNERS Validator 26 | uses: mszostok/codeowners-validator@v0.7.1 27 | with: 28 | # Explanation of checks 29 | # files: Reports if codeowners file contains a filepath that does not exist in the repo 30 | # owners Reports if codeowners file contains an invaid owner 31 | # The check to see if an owner is part of the organization does not appear to work, 32 | # so we will not be using it for now 33 | # duppaterns: Reports if codeowners file contains duplicated lines 34 | # syntax: Reports if file contains an invalid syntax definition 35 | checks: files,owners,duppatterns,syntax 36 | experimental_checks: notowned,avoid-shadowing 37 | 38 | # GitHub access token is required only if the `owners` check is enabled 39 | github_access_token: ${{ secrets.GITHUB_TOKEN }} 40 | -------------------------------------------------------------------------------- /common.yml: -------------------------------------------------------------------------------- 1 | services: 2 | # Common configuration for all of our core uservices 3 | oada-uservice: 4 | build: 5 | context: ./oada 6 | target: ${TARGET-} 7 | restart: unless-stopped 8 | networks: 9 | startup_net: {} 10 | kafka_net: {} 11 | arango_net: {} 12 | volumes: 13 | - ./oada/oada.config.mjs:/oada.config.mjs # for debug? 14 | environment: 15 | # Default to loading packaged default config? 16 | CONFIG: ${OADA_CONFIG-/oada.config.mjs} 17 | # Default to development 18 | NODE_ENV: ${NODE_ENV-development} 19 | NODE_OPTIONS: $$INSPECT --enable-source-maps --unhandled-rejections=strict 20 | INSPECT: ${INSPECT---inspect=0.0.0.0:9229} 21 | DEBUG: ${DEBUG-*} 22 | PINO_LEVEL: ${PINO_LEVEL-debug} 23 | PINO_LOKI: ~ 24 | PINO_LOKI_LEVEL: ~ 25 | PROM_HOST: '::' 26 | DEBUG_HIDE_DATE: ~ 27 | DEBUG_COLORS: ~ 28 | DEBUG_DEPTH: ~ 29 | DEBUG_SHOW_HIDDEN: ~ 30 | # Should just be an external script someone can run on their instance? 31 | arangodb__ensureDefaults: 'true' 32 | DOMAIN: ${DOMAIN:-localhost} 33 | OIDC_ISSUER: ~ 34 | NODE_TLS_REJECT_UNAUTHORIZED: ~ 35 | PINO_TRANSPORT: ~ 36 | PROFILE_AQL: ~ 37 | # Allow changing arangodb URL (e.g., to use external arango) 38 | ARANGODB_URL: ${ARANGODB_URL-http://arangodb:8529} 39 | # Allow changing kafka brokers (e.g., to use external kafka) 40 | KAFKA_BROKERS: ${KAFKA_BROKERS-kafka:9092} 41 | -------------------------------------------------------------------------------- /oada/libs/lib-arangodb/src/libs/putBodies.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import { config } from "../config.js"; 19 | import { db as database } from "../db.js"; 20 | 21 | const collection = database.collection<{ body: unknown }>( 22 | config.get("arangodb.collections.putBodies.name"), 23 | ); 24 | 25 | /** 26 | * Give string of JSON rather than object 27 | */ 28 | export async function savePutBody(body: string): Promise<{ _id: string }> { 29 | // @ts-expect-error HACK: send body without parsing it 30 | const { _id } = await collection.save(`{"body":${body}}`); 31 | return { _id }; 32 | } 33 | 34 | export async function getPutBody(id: string): Promise { 35 | const { body } = await collection.document(id); 36 | return body; 37 | } 38 | 39 | export async function removePutBody(id: string): Promise { 40 | await collection.remove(id); 41 | } 42 | -------------------------------------------------------------------------------- /oada/libs/lib-arangodb/src/util.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import type { Except } from "type-fest"; 19 | 20 | export type Selector = T extends { _id?: infer I } ? I | { _id: I } : never; 21 | 22 | /** 23 | * @todo clean up this mess 24 | */ 25 | export function sanitizeResult( 26 | result: T, 27 | ): Except< 28 | T & { _rev?: number; _key?: unknown; _oada_rev?: unknown }, 29 | "_key" | "_oada_rev" 30 | > { 31 | if (!(result && typeof result === "object")) { 32 | // @ts-expect-error nonsense 33 | return result; 34 | } 35 | 36 | const { _key, _oada_rev, _rev, ...rest } = result as { 37 | _key?: string; 38 | _oada_rev?: number; 39 | _rev?: number; 40 | }; 41 | 42 | const rev = _oada_rev ?? _rev; 43 | return (rev ? { _rev: rev, ...rest } : rest) as unknown as Except< 44 | T & { _rev?: number; _key?: unknown; _oada_rev?: unknown }, 45 | "_key" | "_oada_rev" 46 | >; 47 | } 48 | -------------------------------------------------------------------------------- /charts/oada/templates/issuer.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | * Copyright 2022 Open Ag Data Alliance 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */}} 16 | {{- if .Values.ingress.enabled }} 17 | apiVersion: cert-manager.io/v1 18 | kind: Issuer 19 | metadata: 20 | namespace: {{ .Release.Namespace }} 21 | name: letsencrypt-{{ .Release.Name }} 22 | labels: 23 | app.kubernetes.io/component: letsencrypt 24 | {{- include "oada.chart.labels" . | nindent 4 }} 25 | spec: 26 | {{/* Self-sign if running without any domains */}} 27 | {{ if empty .Values.oada.domains -}} 28 | selfSigned: {} 29 | {{- else -}} 30 | acme: 31 | server: 32 | https://acme{{ .Values.global.development | ternary "-staging-" "-" }}v02.api.letsencrypt.org/directory 33 | email: info@{{ include "oada.domain" . }} 34 | privateKeySecretRef: 35 | name: issuer-oada-{{ .Release.Name }} 36 | solvers: 37 | - http01: 38 | ingress: 39 | class: {{ .Values.ingress.className }} 40 | {{- end }} 41 | {{- end }} 42 | -------------------------------------------------------------------------------- /charts/oada/templates/grafana.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | * Copyright 2022 Open Ag Data Alliance 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */}} 16 | {{- if .Values.grafana.enabled }} 17 | {{/* Load all the grafana dashboards */}} 18 | {{- range $path, $_ := .Files.Glob "grafana/*-dashboard.json" -}} 19 | {{- $name := base $path -}} 20 | {{- $json := $.Files.Get $path | fromJson -}} 21 | apiVersion: v1 22 | kind: ConfigMap 23 | metadata: 24 | namespace: {{ $.Release.Namespace }} 25 | name: {{ $.Chart.Name }}-{{ $name }}-{{ $.Release.Name }} 26 | labels: 27 | app.kubernetes.io/component: {{ $.Chart.Name }}-{{ $name }} 28 | # This ConfigMap is a grafana dashboard 29 | {{ $.Values.grafana.dashboards.label }}: {{ $.Values.grafana.dashboards.value | quote }} 30 | {{- include "oada.chart.labels" $ | nindent 4 }} 31 | annotations: 32 | k8s-sidecar-target-directory: {{ $.Release.Name }} 33 | data: 34 | {{ $name }}: |- 35 | {{- include "oada.dashboard" $json | nindent 4 }} 36 | --- 37 | {{ end -}} 38 | {{ end -}} 39 | -------------------------------------------------------------------------------- /oada/libs/lib-config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@oada/lib-config", 3 | "version": "4.0.0", 4 | "description": "Config wrapper", 5 | "main": "dist/index.js", 6 | "type": "module", 7 | "engines": { 8 | "node": ">=20.0.0" 9 | }, 10 | "files": [ 11 | "src/**/*", 12 | "dist/**/*" 13 | ], 14 | "scripts": { 15 | "build": "yarn g:tsc", 16 | "clean": "yarn run build --clean", 17 | "test": "echo \"Error: no test specified\" && exit 1" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/oada/@oada/lib-config.git" 22 | }, 23 | "keywords": [ 24 | "oada", 25 | "lib", 26 | "config", 27 | "convict" 28 | ], 29 | "author": "Alex Layton (https://github.com/awlayton)", 30 | "license": "Apache-2.0", 31 | "bugs": { 32 | "url": "https://github.com/oada/@oada/lib-config/issues" 33 | }, 34 | "homepage": "https://github.com/oada/@oada/lib-config#readme", 35 | "dependencies": { 36 | "@oada/pino-debug": "workspace:^", 37 | "convict": "^6.2.4", 38 | "convict-format-with-moment": "^6.2.0", 39 | "convict-format-with-validator": "^6.2.0", 40 | "debug": "^4.4.3", 41 | "dotenv": "^17.2.2", 42 | "json5": "^2.2.3", 43 | "tslib": "2.8.1", 44 | "yaml": "^2.8.1" 45 | }, 46 | "devDependencies": { 47 | "@types/convict": "^6.1.6", 48 | "@types/convict-format-with-validator": "^6.0.5", 49 | "@types/debug": "^4.1.12" 50 | }, 51 | "volta": { 52 | "node": "22.5.1" 53 | }, 54 | "peerDependenciesMeta": { 55 | "jose": { 56 | "optional": true 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /oada/tests/.yarnrc.yml: -------------------------------------------------------------------------------- 1 | checksumBehavior: reset 2 | 3 | compressionLevel: mixed 4 | 5 | enableGlobalCache: false 6 | 7 | ignorePath: true 8 | 9 | packageExtensions: 10 | "@fastify/accepts@*": 11 | peerDependencies: 12 | fastify: "*" 13 | "@fastify/auth@*": 14 | peerDependencies: 15 | fastify: "*" 16 | "@fastify/bearer-auth@*": 17 | peerDependencies: 18 | fastify: "*" 19 | "@fastify/cors@*": 20 | peerDependencies: 21 | fastify: "*" 22 | "@fastify/formbody@*": 23 | peerDependencies: 24 | fastify: "*" 25 | "@fastify/helmet@*": 26 | peerDependencies: 27 | fastify: "*" 28 | "@fastify/passport@*": 29 | peerDependencies: 30 | fastify: "*" 31 | "@fastify/rate-limit@*": 32 | peerDependencies: 33 | fastify: "*" 34 | "@fastify/request-context@*": 35 | peerDependencies: 36 | fastify: "*" 37 | "@fastify/secure-session@*": 38 | peerDependencies: 39 | fastify: "*" 40 | "@fastify/sensible@*": 41 | peerDependencies: 42 | fastify: "*" 43 | "@fastify/static@*": 44 | peerDependencies: 45 | fastify: "*" 46 | "@fastify/view@*": 47 | peerDependencies: 48 | fastify: "*" 49 | "@fastify/websocket@*": 50 | peerDependencies: 51 | "@types/ws": "*" 52 | fastify: "*" 53 | fastify-graceful-shutdown@*: 54 | peerDependencies: 55 | fastify: "*" 56 | fastify-healthcheck@*: 57 | peerDependencies: 58 | fastify: "*" 59 | oauth2orize-openid@*: 60 | dependencies: 61 | oauth2orize: "*" 62 | oauth2orize-pkce@*: 63 | peerDependencies: 64 | oauth2orize: "*" 65 | -------------------------------------------------------------------------------- /release/make.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Find directory where this file is 4 | SCRIPT=$(readlink -f "$0") 5 | SCRIPTPATH=$(dirname "${SCRIPT}") 6 | 7 | OVERRIDES=${SCRIPTPATH}/docker-compose.override.yml 8 | 9 | if [ -z "${RELEASE_VERSION}" ]; then 10 | RELEASE_VERSION=${OADA_VERSION} 11 | fi 12 | 13 | # Pull desired version of images 14 | docker-compose pull 15 | 16 | # Add comment with version? 17 | echo "# OADA release ${RELEASE_VERSION} compose file ($(date))\n" 18 | 19 | # Load config, clean anything potentially not fit for release, merge overrides 20 | docker-compose \ 21 | --env-file="${SCRIPTPATH}/.env" \ 22 | -f "${SCRIPTPATH}/../docker-compose.yml" \ 23 | -f "${OVERRIDES}" \ 24 | config --resolve-image-digests | { 25 | # Remove build info 26 | yq 'del(.. | select(has("build")).build)' 27 | } | { 28 | # Remove dev volumes? 29 | yq 'del(.. | select(has("volumes")).volumes)' 30 | } | { 31 | # Remove dev environments? 32 | yq 'del(.. | select(has("environment")).environment)' 33 | } | { 34 | # Remove dev ports? 35 | yq 'del(.. | select(has("ports")).ports)' 36 | } | { 37 | # Remove name 38 | yq 'del(.name)' 39 | } | { 40 | # Merge in release settings 41 | yq "load(\"${OVERRIDES}\") *n ." 42 | } | { 43 | # Explode anchors 44 | # They are technically valid yaml but they were giving me issues 45 | yq 'explode(.)' 46 | } | { 47 | # Remove x-release 48 | yq 'del(.x-release)' 49 | } | { 50 | # Sort the output by key 51 | yq 'sortKeys(..)' 52 | } | { 53 | # Allow pulling our images by tag OADA_VERSION, or default to this digest 54 | sed "s/image: oada\/\(.*\)\(@.*\)/image: oada\/\1:\${OADA_VERSION:-${OADA_VERSION}\2}/" 55 | } 56 | -------------------------------------------------------------------------------- /oada/services/rev-graph-update/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@oada/rev-graph-update", 3 | "version": "4.0.0", 4 | "type": "module", 5 | "description": "", 6 | "author": "", 7 | "license": "Apache-2.0", 8 | "main": "dist/index.js", 9 | "engines": { 10 | "node": ">=20.0.0" 11 | }, 12 | "files": [ 13 | "src/**/*", 14 | "dist/**/*" 15 | ], 16 | "scripts": { 17 | "test": "yarn run build test && ava", 18 | "build": "yarn g:tsc", 19 | "clean": "yarn run build --clean", 20 | "start": "node ${INSPECT} --enable-source-maps --unhandled-rejections=strict dist/index.js" 21 | }, 22 | "ava": { 23 | "files": [ 24 | "**/*.test.ts" 25 | ], 26 | "typescript": { 27 | "extensions": [ 28 | "ts" 29 | ], 30 | "rewritePaths": { 31 | "src/": "dist/", 32 | "test/": ".test/" 33 | }, 34 | "compile": false 35 | } 36 | }, 37 | "dependencies": { 38 | "@oada/lib-arangodb": "workspace:^", 39 | "@oada/lib-config": "workspace:^", 40 | "@oada/lib-kafka": "workspace:^", 41 | "@oada/lib-prom": "workspace:^", 42 | "@oada/pino-debug": "workspace:^", 43 | "ajv": "^8.17.1", 44 | "debug": "^4.4.3", 45 | "p-queue": "^8.1.1", 46 | "randomstring": "^1.3.1", 47 | "tslib": "2.8.1" 48 | }, 49 | "devDependencies": { 50 | "@ava/typescript": "^6.0.0", 51 | "@oada/client": "^5.3.0", 52 | "@oada/write-handler": "workspace:^", 53 | "@types/debug": "^4.1.12", 54 | "@types/node": "^24.6.0", 55 | "@types/randomstring": "^1.3.0", 56 | "ava": "6.4.1", 57 | "type-fest": "^5.0.1" 58 | }, 59 | "volta": { 60 | "node": "22.5.1" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /oada/.yarnrc.yml: -------------------------------------------------------------------------------- 1 | checksumBehavior: reset 2 | 3 | compressionLevel: mixed 4 | 5 | enableGlobalCache: false 6 | 7 | ignorePath: true 8 | 9 | packageExtensions: 10 | "pino-caller@*": 11 | peerDependencies: 12 | "pino": "*" 13 | "@fastify/accepts@*": 14 | peerDependencies: 15 | fastify: "*" 16 | "@fastify/auth@*": 17 | peerDependencies: 18 | fastify: "*" 19 | "@fastify/bearer-auth@*": 20 | peerDependencies: 21 | fastify: "*" 22 | "@fastify/cors@*": 23 | peerDependencies: 24 | fastify: "*" 25 | "@fastify/formbody@*": 26 | peerDependencies: 27 | fastify: "*" 28 | "@fastify/helmet@*": 29 | peerDependencies: 30 | fastify: "*" 31 | "@fastify/passport@*": 32 | peerDependencies: 33 | fastify: "*" 34 | "@fastify/rate-limit@*": 35 | peerDependencies: 36 | fastify: "*" 37 | "@fastify/request-context@*": 38 | peerDependencies: 39 | fastify: "*" 40 | "@fastify/secure-session@*": 41 | peerDependencies: 42 | fastify: "*" 43 | "@fastify/sensible@*": 44 | peerDependencies: 45 | fastify: "*" 46 | "@fastify/static@*": 47 | peerDependencies: 48 | fastify: "*" 49 | "@fastify/view@*": 50 | peerDependencies: 51 | fastify: "*" 52 | "@fastify/websocket@*": 53 | peerDependencies: 54 | "@types/ws": "*" 55 | fastify: "*" 56 | fastify-graceful-shutdown@*: 57 | peerDependencies: 58 | fastify: "*" 59 | fastify-healthcheck@*: 60 | peerDependencies: 61 | fastify: "*" 62 | oauth2orize-openid@*: 63 | dependencies: 64 | oauth2orize: "*" 65 | oauth2orize-pkce@*: 66 | peerDependencies: 67 | oauth2orize: "*" 68 | -------------------------------------------------------------------------------- /.github/workflows/helm-chart.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Open Ag Data Alliance 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | name: Release Helm charts 16 | 17 | permissions: read-all 18 | 19 | on: 20 | push: 21 | branches: 22 | - main 23 | 24 | jobs: 25 | release: 26 | permissions: 27 | contents: write 28 | runs-on: ubuntu-latest 29 | steps: 30 | - name: Checkout 31 | uses: actions/checkout@v5 32 | with: 33 | fetch-depth: 0 34 | 35 | - name: Configure Git 36 | run: | 37 | git config user.name "$GITHUB_ACTOR" 38 | git config user.email "$GITHUB_ACTOR@users.noreply.github.com" 39 | 40 | - name: Install Helm 41 | uses: azure/setup-helm@v4 42 | env: 43 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 44 | with: 45 | version: v3.8.1 46 | 47 | - name: Run chart-releaser 48 | uses: helm/chart-releaser-action@v1.7.0 49 | env: 50 | CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 51 | CR_RELEASE_NAME_TEMPLATE: "{{ .Name }}-chart-v{{ .Version }}" 52 | CR_MAKE_RELEASE_LATEST: false 53 | -------------------------------------------------------------------------------- /oada/libs/models/src/decorators.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2024 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import type { Class, Constructor } from "type-fest"; 19 | 20 | /** 21 | * Class decorator for automagically destructuring the constructor argument 22 | * 23 | * @experimental 24 | */ 25 | export function destructure( 26 | // eslint-disable-next-line @typescript-eslint/naming-convention 27 | Klass: Constructor, ...R] | [Partial | undefined]>, 28 | _context?: unknown, 29 | ): Class]> { 30 | const properties = Object.getOwnPropertyNames( 31 | new Klass({}), 32 | ) as unknown as Array; 33 | // biome-ignore format: type bs 34 | return class 35 | extends // @ts-expect-error classes as variables nonsense 36 | Klass 37 | { 38 | constructor(argument: Partial = {}) { 39 | const a = []; 40 | for (const property of properties) { 41 | a.push(argument[property]); 42 | } 43 | 44 | super(argument, ...a); 45 | } 46 | } as unknown as Class]>; 47 | } 48 | -------------------------------------------------------------------------------- /oada/services/auth/test/private.jwk.json: -------------------------------------------------------------------------------- 1 | { 2 | "kid": "123abc", 3 | "kty": "RSA", 4 | "n": "vt2YToE3YDQS43Dhn4MPF41J8RRyue43rJ5SbK1JizjiJM0A2gB59PxGfVmsNmPEMuJFm_q0wVN77QR0Bhz3O-lJey1ATNbxTx6qePH-TuYebDV6r1QobOwbqTwQFoC_Ic8SzEmazu-MxAPEdjwqyrW3tx5a_50RoHvbNFFkGAna6msNvb9TyxVvN3K2vqxQrzKQqOTEHK6UGv1Bv3_LmWjGv-L6l7H0INwkxOrqGsVAuLY0ntVwES-4_VWsyltxummv0zdFJpeJSj61nIUUE4vvAwE9EdAEfOI5HYDkZBKZm-EC0xcVPOCZbDqab-qg6qcLJ32QAJmcA0YM4-Mq9Q", 5 | "e": "AQAB", 6 | "d": "aduFKaVJDTZUc4ib2lhZ-noGVIs-xhh1EGwO0u-ZJno6EqcQndg9y75Pah5eARx8KKyOZuA5eC_RP7eEkg9mn_fXJVYHn5Zm57beXY35udCvdtyCWtOWSDL7dHU3hwOI_jtW9a6tCbCapexg_iKIqTz307wmRDbdG-EVxoKNvTZj-YEwL1Op75jA5VI02_e1gRMMa_ib6PYV79sWFQvPCz8Wzrw4Cdr9v5xRDdedrO2NFCZD0N1JDK6oadaZMW-FbOk76Dv1OdHZG-ASXpEprdaVMCosWkjtDEGj4ERmASx7gvYQEtSFusL4WVSjgcVPftU5JfNwUoDwXV-XCDPBgQ", 7 | "p": "8Ll06eI5SI9L7sHqMO2upcmmhQ8TipkKt9JA6SizJuPZLBnAItNbYJgONDkkcMZXRKgPg8STpIxXrk2u59uxMkPFVQyC8GawLAf_xmChY1LsTJNrwKdribCmwr5WYHZE6yaEATmZ3dZdbSN6u5eIilC36FTK3y6hH01P-OznyJk", 8 | "q": "yvovy-aKO43OLMX4k3brrvKr3ohJds5BAyXhLniHeu_HFrTDqGxV2LwlzcQzBkVkI3AL6dnToOio5u6muEEtFlRA2E0AeFGILaLBU9Fm8U1BxZp-m0n8TcxwT_WwEDcIjm5Aum42antFM1pvQ6DLN7sPOWUMSknHHAH_g0Y14r0", 9 | "dp": "pSo6A3dKYnSfXtQCAUwzNmEjNcxgVgonhnRmQRPBx_8xNMb-Q2bNHXt203IZhJ8xpVPCQWCRBKeeSWPXjBH6hEhnjrEk7hkm6y8Z2VzXnrR4mRnVJrw4VqKz6I576Xd8VfN5QvXokoLQW1-qiCeycWRsqqXzBCqUNkvvgRXa-pE", 10 | "dq": "I8ssxJM6Czh9hC3BIRgWhbprjomQEvBaTJjQdeZxVb-U5y8nVbsNBHRhYkDYEqIH_6vRngJ4rGZ66oZpRhLQRaDD8qDZlV4jWpDZ8NL7iU_ralJNQ0svv_RuVdtomeNqkdtldLrcw7hLQrwO5OklDQXisGdeXHdYMlsz2M130S0", 11 | "qi": "d629O2rf24ya8Hll9_x3P41YLKjqNtPtJDNR087-J-uNXT2_aTqPedOALINivZc3aj10fT0q5AoBsbkO9cFIpZJCCakvjl3NATo5B5PPk7Yhs5s2Lpmpuxc6LywBnHsacBybVqSFGdC_nSgck96jrniPwGYnI1RsB4e3WUu3nvA" 12 | } 13 | -------------------------------------------------------------------------------- /charts/oada/templates/tests/bookmarks.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | * Copyright 2022 Open Ag Data Alliance 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */}} 16 | {{- $user := first .Values.oada.users -}} 17 | --- 18 | apiVersion: v1 19 | kind: Pod 20 | metadata: 21 | name: test-bookmarks-{{ .Release.Name }} 22 | labels: 23 | app.kubernetes.io/component: test-bookmarks 24 | {{- include "oada.chart.labels" . | nindent 4 }} 25 | annotations: 26 | "helm.sh/hook": test 27 | spec: 28 | volumes: 29 | - name: header-volume 30 | secret: 31 | secretName: {{ print "user-" $user.name "-" .Release.Name }} 32 | items: 33 | - key: header 34 | path: header 35 | containers: 36 | - name: bookmarks 37 | image: curlimages/curl 38 | volumeMounts: 39 | - name: header-volume 40 | mountPath: /secrets 41 | readOnly: true 42 | args: 43 | {{- if .Values.global.development }} 44 | - --verbose 45 | {{- end }} 46 | - --header 47 | - '@/secrets/header' 48 | - http://http-handler-{{ .Release.Name }}/bookmarks/ 49 | restartPolicy: Never 50 | -------------------------------------------------------------------------------- /oada/libs/lib-arangodb/src/libs/clients.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import type { Client } from "@oada/models/client"; 19 | import { aql } from "arangojs"; 20 | import type { Opaque } from "type-fest"; 21 | import { config } from "../config.js"; 22 | import { db as database } from "../db.js"; 23 | import { sanitizeResult } from "../util.js"; 24 | 25 | export type DBClientID = Opaque; 26 | export type DBClient = { 27 | _id: DBClientID; 28 | } & Client; 29 | 30 | const clients = database.collection( 31 | config.get("arangodb.collections.clients.name"), 32 | ); 33 | 34 | export async function findById(id: string): Promise { 35 | const cursor = await database.query( 36 | aql` 37 | FOR c IN ${clients} 38 | FILTER c.client_id == ${id} 39 | RETURN c`, 40 | ); 41 | const client = await cursor.next(); 42 | return client ? sanitizeResult(client) : undefined; 43 | } 44 | 45 | export async function save(client: Client): Promise { 46 | const { _id } = await clients.save(client); 47 | return _id as DBClientID; 48 | } 49 | -------------------------------------------------------------------------------- /oada/services/auth/src/init.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | // whenever you call `npm run init`. It's intended to be used to ensure 19 | // your database exists, has proper indexes, and has any required or initial 20 | // data in it. 21 | // 22 | // Be sure to write your init function such that it doesn't wipe out 23 | // your entire database if it gets run over and over again. That way 24 | // it will work as a default script to run on every startup. 25 | 26 | import debug from "debug"; 27 | import { config } from "./config.js"; 28 | 29 | const log = debug("init"); 30 | 31 | const initPath = config.get("auth.init"); 32 | if (initPath) { 33 | const { default: init } = (await import(initPath)) as { 34 | default: (argument: typeof config) => Promise; 35 | }; // Nosemgrep: javascript.lang.security.detect-non-literal-require.detect-non-literal-require 36 | 37 | if (typeof init === "function") { 38 | log("running init function from %s", initPath); 39 | await init(config); 40 | log("initialization complete."); 41 | } else { 42 | log("No initialization function available"); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /oada/services/auth/domains/localhost/private_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEogIBAAKCAQEA6A2weV9xDaIarahSvCSpQjt+4oB5eQXIctmkgz7A83PJ4VCB 3 | 16DfnOG0U0WalvGpV2xpKzFDfc5PTT9PcI/pVh0LCKV7aofhmDzjmfZwiGZzho25 4 | XvtwvADUt91Bfpw6hJ867gXmFbOpaXEnYbO2MBow0m2aKkPyE2iFn9hQQl6q3Xtb 5 | AaejiYYKxb1nLQhpcbLXX6wj5nR62M7wy5cNBPTtUmpJhKMmyp43+3BI4X4z0wez 6 | UXG9vlaHi9PHCtmCWh6yEMBMZlYLh2awfIQox6JQhR3NEJ1tTW9gE7i0Dw6xlN4v 7 | dmj3EiX6nKUaXof3nvBSYV++WMXmjpH7qoOBkQIDAQABAoIBAFW3OMiciJYQmuoq 8 | kuUMZbkhYO0pp7Ucfb5uxmX0eDF1Q80Gf++2bOL2PDXGMCQxf+vbD730pImD+6b9 9 | C8r4XaiBceHvvnbLWnlxhGEKtuarcWDyWNbM6geIBwsjn121N6hlaM8jPqolgx5/ 10 | vZxJVbLO+dnAwoF6N6ETqsgwjvT0buFxG06ZMfrdKM+CZS1bU68OkbnErLHjrApE 11 | BBIljZyoPUwq75ZRRwv21q4212jXtUHPvqvCkpX5hPjyHCYAgwpI6IYAOv/0+A/Y 12 | iyPa5VYJ5ao1WB9skvhDwbuQv3atOVM7TVkd0A4gLD2p3GcNm0H8k5KtKC4YHe/7 13 | uuf+9AECgYEA+6gOWbeN8ANhWMamnxP5IMk32BjAweC6JdhqPARF1Z6USRVSS1Qo 14 | NB3+qs0y7u2v2lgxTlDqXHN5NN+0nDl1WpLYT8JxRJeGKfOyaGJOS/3p0mQcIWEy 15 | sSQRLHeIh8xsqtpWmC+iFQWr7WU5g4K1fNB/+Pf8Y0GEyjXmqZD4S1kCgYEA7A8E 16 | eUFsbx/JSc3nBIFIH8Vjzvd/MhG8uQVMsoOJDhd34svPyg/8E1vv5MXeii2DPqVA 17 | /FCMIpkThTy2jDEGUqQfxtKH3wdTQ9TXBU5t8JMTvLCKh20Kb0sjC4ROATR0guqz 18 | 6k6cfGb/GkSNqUq2MuaNOUWCiwZUx6kbN1Ok+PkCgYBV3EjJI28x7HVSLLS8obvm 19 | C8EZ4ZgijeH095mHUI3jDG/bX4LsYJI29eTlsY0nJ8FP5bcs2T6cvGkmOQ0OICyB 20 | 8ogK7nRmyqvjtFmyc5fzJXaZab6PRPJerceOPFpAuuZ4hHX3BoluUrkODfNJg1cY 21 | dqqy7ykVVE1SEIHaaLPOQQKBgB9/rYAkm7yESE7B2+a8/YvHwha27dEXjtA9hct4 22 | Q8yOkx+/RH3Y/jDzHqKvSI+1nQK5+F7yvJBNTs6DmHRCgm56mgbkxt6a0qCFgR+j 23 | JIZqicKu5/1ELpVFOGrr/6CniDiD6vgD/1uWPsoZhbGmV4OZQhT3UoEMmjl+NjR+ 24 | w8+5AoGAAZIhmr84UTcoupP4btMUqc/DmwW6usrw3plJYjWUyARkr4nbdKr99M36 25 | 8osRvy6KOUcOBPKJP/zDnkksRg1QD6faxkpNsOoM0zkXoEpl1xZMa0rEZS7j8mbu 26 | ikwJ67rw0QT8hUN43yurFprdv8aw2qxappXqW6JX/2QJEkx2UDE= 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /oada/services/auth/src/db/arango/deviceCodes.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import { deviceCodes } from "@oada/lib-arangodb"; 19 | import debug from "debug"; 20 | 21 | import type { DeviceCode, IDeviceCodes } from "../models/deviceCode.js"; 22 | 23 | const trace = debug("arango:deviceCodes:trace"); 24 | 25 | export const findByDeviceCode = (async (deviceCode) => { 26 | trace("findByCode: searching for code %s", deviceCode); 27 | return deviceCodes.findByDeviceCode(deviceCode); 28 | }) satisfies IDeviceCodes["findByDeviceCode"]; 29 | 30 | export const findByUserCode = (async (userCode) => { 31 | trace("findByCode: searching for code %s", userCode); 32 | return deviceCodes.findByUserCode(userCode); 33 | }) satisfies IDeviceCodes["findByUserCode"]; 34 | 35 | export const save = (async (deviceCode: C) => 36 | (await deviceCodes.save(deviceCode)) as C) satisfies IDeviceCodes["save"]; 37 | 38 | export const redeem = (async (deviceCode) => { 39 | const { redeemed, code } = await deviceCodes.redeem(deviceCode); 40 | return { 41 | redeemed, 42 | code: code as DeviceCode, 43 | }; 44 | }) satisfies IDeviceCodes["redeem"]; 45 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Code Owners Declaration 2 | # This file defines the code owners for files in this repository 3 | # See documentation here: https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners 4 | 5 | # Default group of people? 6 | * @awlayton @abalmos @aultac 7 | 8 | .gitattributes @aultac 9 | 10 | # VS Code 11 | .vscode @awlayton 12 | *.code-workspace @awlayton 13 | 14 | # biome 15 | **/biome.json @awlayton 16 | 17 | # TypeScript 18 | **/tsconfig.* @awlayton 19 | 20 | # docker 21 | oada/.dockerignore @awlayton 22 | oada/Dockerfile @abalmos @awlayton 23 | docker-compose.yml @abalmos @awlayton 24 | common.yml @abalmos 25 | 26 | # Alex made swag based proxy 27 | support/proxy @awlayton 28 | 29 | oada/lerna.json @awlayton 30 | 31 | oada/libs/lib-kafka @awlayton 32 | oada/libs/pino-debug @awlayton 33 | #oada/libs/oada-lib-arangodb 34 | oada/libs/lib-config @awlayton 35 | 36 | # Service authors? 37 | oada/services/auth @abalmos 38 | oada/services/http-handler @awlayton 39 | #oada/services/permissions-handler 40 | #oada/services/rev-graph-update @wang701 41 | #oada/services/shares 42 | oada/services/startup @aultac 43 | oada/services/sync-handler @awlayton 44 | oada/services/users @aultac 45 | oada/services/webhooks @awlayton 46 | oada/services/well-known @awlayton 47 | oada/services/write-handler @awlayton 48 | 49 | # Yaguang wrote the tests 50 | #oada/tests @YaguangZhang 51 | 52 | # Alex made the release nonsense 53 | release @awlayton 54 | 55 | # Helm stuff 56 | charts @awlayton 57 | 58 | # Andrew intially created all the files in .github with some additions by Aaron 59 | .github @abalmos 60 | #.github/workflows/validate-codeowners.yml @aaron97neu 61 | .github/workflows/build-and-push-services.yml @abalmos @awlayton 62 | .github/workflows/semgrep-analysis.yml @awlayton 63 | -------------------------------------------------------------------------------- /oada/services/startup/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import "@oada/pino-debug"; 19 | 20 | import http from "node:http"; 21 | 22 | import { init as initArangoDB } from "@oada/lib-arangodb"; 23 | import { init as initKafka } from "@oada/lib-kafka"; 24 | 25 | import debug from "debug"; 26 | 27 | const trace = debug("startup:trace"); 28 | const info = debug("startup:info"); 29 | 30 | const port = process.env.PORT ?? 8080; 31 | const exit = process.env.EXIT ?? false; 32 | 33 | try { 34 | info("Startup is initializing ArangoDB and Kafka"); 35 | await Promise.all([initArangoDB.run(), initKafka.run()]); 36 | info("Initialization complete"); 37 | 38 | if (exit) { 39 | // eslint-disable-next-line unicorn/no-process-exit, n/no-process-exit 40 | process.exit(0); 41 | } 42 | 43 | const server = http.createServer((request, response) => { 44 | trace(request, "Request received"); 45 | response.write("Hello"); 46 | response.end(); 47 | }); 48 | server.on("listening", () => { 49 | info(server.address(), "Startup finished, listening"); 50 | }); 51 | 52 | server.listen(port); 53 | } catch (error: unknown) { 54 | throw error; 55 | } 56 | -------------------------------------------------------------------------------- /oada/services/well-known/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@oada/well-known", 3 | "version": "4.0.0", 4 | "type": "module", 5 | "description": "Microservice for serving well-known at an OADA cloud. Plays nicely with oada-ref-auth-js.", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/oada/oada-srvc-well-known.git" 9 | }, 10 | "keywords": [ 11 | "oada", 12 | "well-known" 13 | ], 14 | "author": "", 15 | "license": "Apache-2.0", 16 | "bugs": { 17 | "url": "https://github.com/oada/oada-srvc-well-known/issues" 18 | }, 19 | "homepage": "https://github.com/oada/oada-srvc-well-known#readme", 20 | "main": "dist/index.js", 21 | "engines": { 22 | "node": ">=20.0.0" 23 | }, 24 | "files": [ 25 | "src/**/*", 26 | "dist/**/*" 27 | ], 28 | "scripts": { 29 | "build": "yarn g:tsc", 30 | "clean": "yarn run build --clean", 31 | "start": "node ${INSPECT} --enable-source-maps --unhandled-rejections=strict dist/index.js", 32 | "test": "echo \"Error: no test specified\" && exit 1" 33 | }, 34 | "dependencies": { 35 | "@fastify/accepts": "^5.0.3", 36 | "@fastify/cors": "^11.1.0", 37 | "@fastify/helmet": "^13.0.2", 38 | "@oada/formats-server": "^4.0.0", 39 | "@oada/lib-config": "workspace:^", 40 | "@oada/lib-prom": "workspace:^", 41 | "@oada/pino-debug": "workspace:^", 42 | "@oada/well-known-json": "^4.0.2", 43 | "allow-methods": "^7.1.0", 44 | "cors": "^2.8.5", 45 | "debug": "^4.4.3", 46 | "fastify": "^5.6.1", 47 | "got": "^14.4.9", 48 | "openid-client": "^5.7.1", 49 | "tslib": "2.8.1" 50 | }, 51 | "devDependencies": { 52 | "@types/cors": "^2.8.19", 53 | "@types/debug": "^4.1.12", 54 | "fastify-plugin": "^5.1.0" 55 | }, 56 | "volta": { 57 | "node": "22.5.1" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /support/proxy/selfsigned/privkey.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC/QwF1Xl6f56Gb 3 | JWZkoNmpajxhhnMGero0zp/JkysmdK+Bv+x3ETYxcEOlz9JP8j2gLmSzllqAl6vZ 4 | fqkZv6kZRebBvzRxP50JCJRlWQBQU4gbISdCC3JKx5phy8/QHn2RrQ8kaWMpdzxh 5 | 9LchKsvf5+heWCWTcyf6FCkCj/KKjnBBJZ9TwM4mud9OGyo4TmGgQGQOV+njE0T5 6 | +QnhvK78iH5ic5fdWsQoFH/Or8G67X+LRTPxMzStX0N2lpHKAuiWKa9pK0NCtd7R 7 | ZM59vzZbnBZc7PjNKMhUaptlKbPtCAkFNiC9QAp6zWp5ZbbfGMrFDiqFjKSqrcuz 8 | 8hG6rxtZAgMBAAECggEAXJFqmEqnU49BGRzd1OBA2I0RUkZHT6CAlORYU7BF1yPs 9 | ecjRAsOyzfS+2PafnI/qoacyl/SyMsC1rNtvroWjqxa425bWI+Wc9G1RnUeZLkdv 10 | fWnrXTy7AVRf9Os21kybi7ENvhq/oqcR83sEUyoqaGEOhvL0pMu8Un4FZzcSNVpq 11 | vciPB6zKReb8JTo3C2xCRbOHQnsFUruMqBjTOqGT7wg04kGg5IbZ7HxtWfY8odD8 12 | ePEwba44RjoL+TyPEgSQdtaT/09fhh2RWIwiqt0vXiohxmOeYO5k9kJHE/FFgVuG 13 | R9JFogEZcFr8adWXBzNK3urtSx7YKtf7a/ZFJevSAQKBgQDmccZwYLYAKMCyRX8D 14 | smb+luUjXyBZsy8tvb6Mf3r5mn2nYF0f2/gy7CQ7GZd3SP4nYKsPRe9tmYcXS4P8 15 | gEM69CuMir7DdMdjWHTb7JocLXX9C0BtpJYRahjwO/3ANor6nSrrr8rNAsWRoynN 16 | 3EkXjmfPq7K61fd0BXGgIWuEGQKBgQDUeNmBzZY0huTDqJqhhq0cC6RiFvdBkAhA 17 | 0bq7ukVmgm37r8CuqPyg6cIScFm7kvS5r/W6f2sl0WDRoH3NXi/obQPiTYIhaWA2 18 | nF1Sf1Nc1bREjv5JibEWCIjQbBnBs11lrIlsh45o2q1wYIMjAozry/JKwd0M90dT 19 | VPdJVOE5QQKBgHwrWCKbadYCH3qvibYDPg32XrdFfZf3vfcmo3LvCeNOxGAYw3T0 20 | QPOnXApgSsYilZfANcwAAfgLXshFj3PR5OfyQzjyVcHZvcohEq6h+ZQvRsE3e9rY 21 | cWgmxBNGL/+PJCnP4B2o1lzLHovP4CmlhdjkiblTqfWUb0ab3FLNTzKZAoGAd75w 22 | HuaFm67WaKqyEwx6rU6mYx28Vbfd3uIUUk6FZGNnpqwDdKwKTInRdWDaQYtt3uSb 23 | IXNEKLkazqmbnM1TRLODt9uk1j20GrL/KUpW6gAKq4THLRyrr9Y5fPUfgvoaTf3y 24 | KTcwfEmZ67aI0YdTcmSrdZRSh0cpbH57K1np4MECgYBPFGBfuKCM0E0jz5G0Wqwy 25 | X+aUopqZ4SJl9S9+l/ewmUjn2mkzRfyscqF188d2W1e8rmlsLROzCeCZ4CQCpgWu 26 | 73gB7Lj5jQAxuJapDzexK8Aj+BzL1S+WNCRP6q5PN/IuxmVcSRozSEzVFQCbiF7Z 27 | 2qQTbN1GLxjKLRiPzt5E7A== 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /oada/services/auth/test/istantestd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright 2014 Open Ag Data Alliance 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the 'License'); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an 'AS IS' BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | 18 | function check_success { 19 | if (($? > 0)); then echo "Unable to prepare test environment.." && exit 1; fi 20 | } 21 | SIGINT=2 22 | NPM=npm 23 | PORT=8443 24 | cd ../ 25 | ROOTPATH=$(pwd) 26 | ${NPM} run clean 27 | check_success 28 | #$NPM install 29 | echo "Cloning test.." 30 | git clone -b authorization https://github.com/OADA/oada-compliance.git test/oada-compliance 31 | check_success 32 | cd test/oada-compliance && ${NPM} install 33 | cd "${ROOTPATH}" || exit 34 | echo "Starting instrumented server.." 35 | PORT=${PORT} istanbul cover -x "*gulpfile.js*" --include-all-sources --handle-sigint index.js -- ./config.js & 36 | PID=$! 37 | echo "PID " "${PID}" 38 | 39 | while true; do 40 | echo "Waiting for server to start" 41 | curl --insecure https://localhost:"${PORT}" 42 | if (($? == 0)); then 43 | break 44 | fi 45 | sleep 1 46 | done 47 | 48 | # Run the test here 49 | echo "Running testcases.." 50 | cd test/oada-compliance || exit 51 | ECODE=0 52 | ./test authorization 53 | if (($? > 0)); then 54 | echo "Test failed! Log below" 55 | ECODE=1 56 | fi 57 | kill -"${SIGINT}" "${PID}" 58 | wait "${PID}" 59 | exit "${ECODE}" 60 | -------------------------------------------------------------------------------- /charts/oada/README.md: -------------------------------------------------------------------------------- 1 | 16 | 17 | # OADA Helm chart 18 | 19 | [![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/oada)](https://artifacthub.io/packages/helm/oada/oada) 20 | 21 | Helm chart for installing the OADA server in a k8s cluster. 22 | Supports multiple release installs and non-default namespace. 23 | 24 | ## Prerequisites 25 | 26 | - [Cert manager][] 27 | - [Redpanda operator][] 28 | - [ArangoDB operator][] and [CRDs][arangodb crd] 29 | - At least one ingress controller (e.g., [ingress-nginx][]) 30 | 31 | ## Installation 32 | 33 | Add our helm chart repo 34 | `helm repo add oada https://charts.openag.io/` 35 | 36 | Install the Helm chart: 37 | `helm install my-oada oada/oada` 38 | 39 | See the [default values](values.yaml) for various configuration options. 40 | 41 | [cert manager]: https://artifacthub.io/packages/helm/cert-manager/cert-manager 42 | [redpanda operator]: https://artifacthub.io/packages/helm/redpanda/redpanda-operator 43 | [arangodb operator]: https://artifacthub.io/packages/helm/source-field/kube-arangodb 44 | [arangodb crd]: https://artifacthub.io/packages/helm/source-field/kube-arangodb-crd 45 | [ingress-nginx]: https://artifacthub.io/packages/helm/ingress-nginx/ingress-nginx 46 | -------------------------------------------------------------------------------- /oada/services/auth/domains/localhost/unsigned_software_statement.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | export default { 19 | redirect_uris: ["https://localhost/oadaauth/id-redirect"], 20 | token_endpoint_auth_method: 21 | "urn:ietf:params:oauth:client-assertion-type:jwt-bearer", 22 | grant_types: ["authorization_code"], 23 | response_types: [ 24 | "token", 25 | "code", 26 | "id_token", 27 | "id_token token", 28 | "code id_token", 29 | "code token", 30 | "code id_token token", 31 | ], 32 | client_name: "Localhost", 33 | client_uri: "https://localhost", 34 | contacts: ["Aaron Ault "], 35 | jwks: { 36 | keys: [ 37 | { 38 | kid: "90D00A997B774AD4B3B4EEB0E84DC6CF", 39 | kty: "RSA", 40 | // eslint-disable-next-line no-secrets/no-secrets 41 | n: "6A2weV9xDaIarahSvCSpQjt-4oB5eQXIctmkgz7A83PJ4VCB16DfnOG0U0WalvGpV2xpKzFDfc5PTT9PcI_pVh0LCKV7aofhmDzjmfZwiGZzho25XvtwvADUt91Bfpw6hJ867gXmFbOpaXEnYbO2MBow0m2aKkPyE2iFn9hQQl6q3XtbAaejiYYKxb1nLQhpcbLXX6wj5nR62M7wy5cNBPTtUmpJhKMmyp43-3BI4X4z0wezUXG9vlaHi9PHCtmCWh6yEMBMZlYLh2awfIQox6JQhR3NEJ1tTW9gE7i0Dw6xlN4vdmj3EiX6nKUaXof3nvBSYV--WMXmjpH7qoOBkQ", 42 | e: "AQAB", 43 | }, 44 | ], 45 | }, 46 | }; 47 | -------------------------------------------------------------------------------- /oada/tests/test/batch-rev-graph-updates.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; // Tests run inside docker and all certs are self-signed 2 | 3 | describe("rev-graph-updates should be batched", async () => { 4 | const debug = require("debug"); 5 | const trace = debug("tests:trace"); 6 | const error = debug("tests:error"); 7 | 8 | const axiosLib = require("axios"); 9 | const Promise = require("bluebird"); 10 | 11 | const axios = axiosLib.create({ 12 | headers: { 13 | Authorization: "Bearer xyz", 14 | "content-type": "oada.rock.1+json", 15 | }, 16 | }); 17 | const baseurl = "http://proxy"; // Use proxy domain name inside docker 18 | const parentid = "resources/test-rev-graph-batch-parent"; 19 | const child1id = "resources/test-rev-graph-batch-child1"; 20 | const child2id = "resources/test-rev-graph-batch-child2"; 21 | 22 | // ------------------------------------------------------------- 23 | // To begin, create a resource that links to another resource 24 | // so we can track batched changes 25 | before(async () => { 26 | trace("Creating resource linked to a parent resource using default token"); 27 | await Promise.all([ 28 | axios.put(`${baseurl}/${child1id}`, { test: "batch-rev-graph-update" }), 29 | axios.put(`${baseurl}/${child2id}`, { test: "batch-rev-graph-update" }), 30 | axios.put(`${baseurl}/${parentid}`, { 31 | test: "batch-rev-graph-update", 32 | child1: { _id: child1id, _rev: 0 }, 33 | child2: { _id: child2id, _rev: 0 }, 34 | }), 35 | ]).catch((error_) => 36 | error("before: Failed one of the setup put's. err = ", error_), 37 | ); 38 | const res = await axios.get(`${baseurl}/${parentid}`); 39 | console.log("the parent get request result is:", res); 40 | }); 41 | 42 | it("should update the parent only once with two parallel child changes", async () => {}); 43 | }); 44 | -------------------------------------------------------------------------------- /charts/oada/templates/service-account.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | * Copyright 2022 Open Ag Data Alliance 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */}} 16 | apiVersion: v1 17 | kind: ServiceAccount 18 | metadata: 19 | namespace: {{ .Release.Namespace }} 20 | name: service-account-{{ .Release.Name }} 21 | labels: 22 | {{- include "oada.chart.labels" . | nindent 4 }} 23 | --- 24 | apiVersion: rbac.authorization.k8s.io/v1 25 | kind: Role 26 | metadata: 27 | namespace: {{ .Release.Namespace }} 28 | name: role-{{ .Release.Name }} 29 | labels: 30 | {{- include "oada.chart.labels" . | nindent 4 }} 31 | rules: 32 | - apiGroups: [""] 33 | resources: 34 | - pods 35 | - services 36 | verbs: 37 | - get 38 | - list 39 | - watch 40 | - apiGroups: ["batch"] 41 | resources: 42 | - jobs 43 | verbs: 44 | - get 45 | - list 46 | - watch 47 | --- 48 | apiVersion: rbac.authorization.k8s.io/v1 49 | kind: RoleBinding 50 | metadata: 51 | namespace: {{ .Release.Namespace }} 52 | name: role-binding-{{ .Release.Name }} 53 | labels: 54 | {{- include "oada.chart.labels" . | nindent 4 }} 55 | roleRef: 56 | apiGroup: rbac.authorization.k8s.io 57 | kind: Role 58 | name: role-{{ .Release.Name }} 59 | subjects: 60 | - kind: ServiceAccount 61 | name: service-account-{{ .Release.Name }} -------------------------------------------------------------------------------- /.github/workflows/git-cliff-release.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Open Ag Data Alliance 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | name: Generate Release Changelog 16 | 17 | on: 18 | release: 19 | types: 20 | - published 21 | 22 | permissions: 23 | contents: write 24 | 25 | jobs: 26 | changelog: 27 | name: Generate release changes 28 | runs-on: ubuntu-latest 29 | outputs: 30 | release_body: ${{ steps.git-cliff.outputs.content }} 31 | steps: 32 | - name: Checkout 33 | uses: actions/checkout@v5 34 | with: 35 | fetch-depth: 0 36 | 37 | - name: Install typos-cli from crates.io 38 | uses: baptiste0928/cargo-install@v3.3.2 39 | with: 40 | crate: typos-cli 41 | version: "^1.37.2" # optional semver range (defaults to latest) 42 | 43 | - name: Generate changelog file 44 | uses: orhun/git-cliff-action@v4 45 | id: git-cliff 46 | with: 47 | config: cliff.toml 48 | args: -vv --latest --strip header 49 | env: 50 | OUTPUT: CHANGES.md 51 | GITHUB_REPO: ${{ github.repository }} 52 | 53 | - name: Update release body 54 | id: update_release 55 | uses: tubone24/update_release@v1.3.1 56 | env: 57 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 58 | with: 59 | body_path: CHANGES.md 60 | is_append_body: true 61 | -------------------------------------------------------------------------------- /charts/oada/templates/arangodb.yaml: -------------------------------------------------------------------------------- 1 | {{/* vim: set ft=helm : */}} 2 | {{/* 3 | * Copyright 2022 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */}} 17 | {{- if eq (include "oada.arango.deploy" .) "true" }} 18 | apiVersion: database.arangodb.com/v1 19 | kind: ArangoDeployment 20 | metadata: 21 | namespace: {{ .Release.Namespace }} 22 | name: arangodb-{{ .Release.Name }} 23 | labels: 24 | app.kubernetes.io/component: arangodb 25 | {{- include "oada.chart.labels" . | nindent 4 }} 26 | spec: 27 | image: {{ .Values.arangodb.image }}:{{ .Values.arangodb.tag }} 28 | mode: Single 29 | single: 30 | volumeClaimTemplate: 31 | metadata: 32 | annotations: 33 | helm.sh/resource-policy: keep 34 | resources: 35 | {{- toYaml .Values.oada.resources | nindent 6 }} 36 | environment: {{ .Values.global.development | ternary "Development" "Production" }} 37 | metrics: 38 | enabled: {{ include "oada.prometheus" . }} 39 | externalAccess: 40 | {{- /* Disable external access for Production */}} 41 | type: {{ .Values.global.development | ternary "Auto" "None" }} 42 | tls: 43 | caSecretName: None 44 | {{- if not .Values.global.development }} 45 | {{- /* Create root password for Production */}} 46 | bootstrap: 47 | passwordSecretNames: 48 | root: {{ include "oada.arango.rootPassword" . }} 49 | {{- end }} 50 | {{- end }} -------------------------------------------------------------------------------- /oada/services/http-handler/src/tokenLookup.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import { authorizations } from "@oada/lib-arangodb"; 19 | import Authorization from "@oada/models/authorization"; 20 | import debug from "debug"; 21 | 22 | const warn = debug("token-lookup:warn"); 23 | 24 | export interface TokenRequest { 25 | token: string; 26 | } 27 | 28 | export default async function tokenLookup( 29 | request: TokenRequest, 30 | ): Promise { 31 | // Get token from db. 32 | // FIXME: We should speed this up by getting everything in one query. 33 | const found = await authorizations.findByToken( 34 | request.token.trim().replace(/^Bearer /, ""), 35 | ); 36 | 37 | if (!found) { 38 | warn("Token %s does not exist.", request.token); 39 | return; 40 | } 41 | 42 | const { 43 | _id: _, 44 | token: t, 45 | clientId, 46 | user: { 47 | sub, 48 | // @ts-expect-error deprecated key 49 | _id, 50 | ...user 51 | }, 52 | scope, 53 | createTime, 54 | expiresIn, 55 | ...rest 56 | } = found; 57 | 58 | return new Authorization({ 59 | jti: t, 60 | client_id: clientId, 61 | scope: scope.join(" "), 62 | iat: createTime, 63 | exp: expiresIn, 64 | sub: sub ?? _id, 65 | ...user, 66 | ...rest, 67 | }); 68 | } 69 | -------------------------------------------------------------------------------- /oada/services/write-handler/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@oada/write-handler", 3 | "version": "4.0.0", 4 | "type": "module", 5 | "description": "", 6 | "engines": { 7 | "node": ">=20.0.0" 8 | }, 9 | "files": [ 10 | "src/**/*", 11 | "dist/**/*" 12 | ], 13 | "repository": { 14 | "type": "git", 15 | "url": "git+ssh://git@github.com/OADA/oada-srvc-write-handler.git" 16 | }, 17 | "author": "awlayton", 18 | "license": "Apache-2.0", 19 | "bugs": { 20 | "url": "https://github.com/OADA/oada-srvc-write-handler/issues" 21 | }, 22 | "homepage": "https://github.com/OADA/oada-srvc-write-handler#readme", 23 | "main": "dist/index.js", 24 | "scripts": { 25 | "test": "yarn run build test && ava", 26 | "build": "yarn g:tsc", 27 | "clean": "yarn run build --clean", 28 | "start": "node ${INSPECT} --enable-source-maps --expose-gc --unhandled-rejections=strict dist/index.js" 29 | }, 30 | "ava": { 31 | "files": [ 32 | "**/*.test.ts" 33 | ], 34 | "typescript": { 35 | "extensions": [ 36 | "ts" 37 | ], 38 | "rewritePaths": { 39 | "src/": "dist/", 40 | "test/": ".test/" 41 | }, 42 | "compile": false 43 | } 44 | }, 45 | "dependencies": { 46 | "@oada/lib-arangodb": "workspace:^", 47 | "@oada/lib-config": "workspace:^", 48 | "@oada/lib-kafka": "workspace:^", 49 | "@oada/lib-prom": "workspace:^", 50 | "@oada/pino-debug": "workspace:^", 51 | "debug": "^4.4.3", 52 | "json-ptr": "^3.1.1", 53 | "object-assign-deep": "^0.4.0", 54 | "timed-cache": "^2.0.0", 55 | "tslib": "2.8.1" 56 | }, 57 | "devDependencies": { 58 | "@ava/typescript": "^6.0.0", 59 | "@oada/client": "^5.3.0", 60 | "@oada/types": "^4.0.0", 61 | "@types/debug": "^4.1.12", 62 | "@types/json-pointer": "^1.0.34", 63 | "@types/node": "^24.6.0", 64 | "@types/object-assign-deep": "^0.4.3", 65 | "ava": "6.4.1" 66 | }, 67 | "volta": { 68 | "node": "22.5.1" 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /oada/libs/lib-kafka/src/config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | // TODO: Publish this to npm instead? 19 | import libConfig from "@oada/lib-config"; 20 | 21 | export const { config, schema } = await libConfig({ 22 | kafka: { 23 | healthInterval: { 24 | format: "duration", 25 | default: 5 * 60 * 1000, // Ms 26 | }, 27 | producer: { 28 | pollInterval: { 29 | format: "duration", 30 | default: 500, // Ms 31 | }, 32 | }, 33 | broker: { 34 | doc: "Kafka broker(s) to use", 35 | format: Array, 36 | default: ["kafka:9092"], 37 | env: "KAFKA_BROKERS", 38 | arg: "brokers", 39 | }, 40 | timeouts: { 41 | doc: "Mapping of topic to timeouts (ms)", 42 | 43 | default: { 44 | default: 5000, 45 | writeRequest: 45_000, 46 | websocketsRequest: Number.POSITIVE_INFINITY, 47 | } as Record, 48 | }, 49 | topics: { 50 | doc: "Kafka topic names to use", 51 | 52 | default: { 53 | tokenRequest: "token_request", 54 | graphRequest: "graph_request", 55 | writeRequest: "write_request", 56 | websocketsRequest: "websockets_request", 57 | permissionsRequest: "permissions_request", 58 | permissionsResponse: "permissions_response", 59 | httpResponse: "http_response", 60 | } as Record, 61 | }, 62 | }, 63 | }); 64 | -------------------------------------------------------------------------------- /oada/libs/lib-arangodb/src/libs/codes.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import { aql } from "arangojs"; 19 | import type { Opaque } from "type-fest"; 20 | 21 | import { config } from "../config.js"; 22 | import { db as database } from "../db.js"; 23 | import { sanitizeResult } from "../util.js"; 24 | 25 | export type CodeID = Opaque; 26 | export interface Code { 27 | _id?: CodeID; 28 | _rev?: number; 29 | code: string; 30 | scope: readonly string[]; 31 | nonce?: string; 32 | user: string; 33 | createTime: number; 34 | expiresIn: number; 35 | redeemed: boolean; 36 | clientId: string; 37 | redirectUri: string; 38 | } 39 | export type DBCode = { 40 | _id: CodeID; 41 | _rev: number; 42 | } & Code; 43 | 44 | const codes = database.collection( 45 | config.get("arangodb.collections.codes.name"), 46 | ); 47 | 48 | export async function findByCode(code: string): Promise { 49 | const cursor = await database.query( 50 | aql` 51 | FOR c IN ${codes} 52 | FILTER c.code == ${code} 53 | RETURN c`, 54 | ); 55 | 56 | const c = await cursor.next(); 57 | return c ? sanitizeResult(c) : undefined; 58 | } 59 | 60 | export async function save( 61 | code: Partial & { code: string }, 62 | ): Promise { 63 | await database.query(aql` 64 | UPSERT { code: ${code.code} } 65 | INSERT ${code} 66 | UPDATE ${code} 67 | IN ${codes} 68 | `); 69 | 70 | return findByCode(code.code); 71 | } 72 | -------------------------------------------------------------------------------- /oada/libs/models/src/authorization.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2024 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import { randomBytes } from "node:crypto"; 19 | import { makeClass } from "@qlever-llc/interface2class"; 20 | import type { JWTPayload } from "jose"; 21 | import type { OmitIndexSignature, Opaque } from "type-fest"; 22 | 23 | import { destructure } from "./decorators.js"; 24 | import type { Claims } from "./oidc.js"; 25 | 26 | export type AuthorizationID = Opaque; 27 | 28 | /** 29 | * Our representation of an Authorization (e.g., an OAuth2.0 bearer token) 30 | * and associated information 31 | */ 32 | export 33 | @destructure 34 | class Authorization extends makeClass< 35 | OmitIndexSignature 36 | >() { 37 | // @ts-expect-error HACK 38 | constructor(authorization?: Partial); 39 | 40 | constructor( 41 | // biome-ignore lint/style/useDefaultParameterLast: 42 | rest: Partial = {}, 43 | override readonly sub: string, 44 | override readonly jti = randomBytes(16).toString("hex"), 45 | // Readonly _id = `authorizations/${generate()}` as AuthorizationID, 46 | override readonly scope = "", 47 | override readonly roles: readonly string[] = [], 48 | override readonly iat = Date.now() / 1000, 49 | // TODO: Config for default expiration? 50 | override readonly exp = Number.MAX_VALUE, 51 | readonly revoked?: boolean, 52 | ) { 53 | super({ sub, ...rest }); 54 | } 55 | } 56 | 57 | export default Authorization; 58 | -------------------------------------------------------------------------------- /oada/services/auth/domains/localhost/config.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2022 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import fs from "node:fs/promises"; 19 | import path from "node:path"; 20 | import url from "node:url"; 21 | 22 | import signed from "./signed_software_statement.mjs"; 23 | import unsigned from "./unsigned_software_statement.mjs"; 24 | 25 | export default { 26 | domain: "localhost", // Just here for informational purposes 27 | baseuri: "https://localhost/", // Just here for informational purposes 28 | logo: "logo.png", 29 | name: "Open Ag Data Alliance", 30 | tagline: "", 31 | color: "#FFFFFF", 32 | hint: { 33 | username: "frank", 34 | password: "test", 35 | }, 36 | idService: { 37 | shortname: "OADA", 38 | longname: "Open Ag Data Alliance", 39 | }, 40 | 41 | // To generate keys: 42 | // 1: create key pair: openssl genrsa -out private_key.pem 2048 43 | // 2: extract public key: openssl rsa -pubout -in private_key.pem -out public_key.pem 44 | keys: { 45 | public: "public_key.pem", 46 | private: { 47 | // Use the first (and only) key in software statement: 48 | kid: unsigned.jwks.keys[0].kid, 49 | // Read the private key from the private key file: 50 | // @eslint-disable-next-line security/detect-non-literal-fs-filename 51 | pem: await fs.readFile( 52 | `${path.dirname(url.fileURLToPath(import.meta.url))}/private_key.pem`, 53 | ), 54 | }, 55 | }, 56 | unsigned_software_statement: unsigned, 57 | software_statement: signed, 58 | }; 59 | -------------------------------------------------------------------------------- /oada/tests/selftest/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | Testing script 0: 3 | - A simple self test (for express, axios and chai). 4 | */ 5 | 6 | const { expect } = require("chai"); 7 | const axios = require("axios"); 8 | const Promise = require("bluebird"); 9 | 10 | // Self test needs the express server. It will verify both axios and chai work 11 | // as expected. 12 | const isSelfTesting = process.env.NODE_ENV === "selftest"; 13 | 14 | if (isSelfTesting) { 15 | const FOO_INVALID_TOKEN = "foo-invalid-token-tests"; 16 | 17 | describe("SelfTest", () => { 18 | let serverResHeader = ""; 19 | let serverResToken = ""; 20 | 21 | before(() => { 22 | // Embed the token for all HTTP request. 23 | axios.interceptors.request.use( 24 | (config) => { 25 | const token = FOO_INVALID_TOKEN; // Cookie.get(__TOKEN_KEY__); 26 | 27 | if (token != undefined) { 28 | config.headers.Authorization = `Bearer ${token}`; 29 | } 30 | 31 | return config; 32 | }, 33 | (errorEmbedToken) => Promise.reject(errorEmbedToken), 34 | ); 35 | 36 | // Self tests. 37 | return axios 38 | .get("http://localhost/echo", { 39 | params: { 40 | ID: 12_345, 41 | }, 42 | }) 43 | .then((response) => { 44 | serverResHeader = response.data.slice(0, 4); 45 | serverResToken = response.config.headers.Authorization; 46 | }) 47 | .catch((error) => { 48 | error("FAILED sending HTTP GET using axios!"); 49 | error(error); 50 | return Promise.reject(error); 51 | }); 52 | }); 53 | 54 | // -------------------------------------------------- 55 | // The tests! 56 | // -------------------------------------------------- 57 | describe("SelfTestSever", () => { 58 | it("should be an echo server", (done) => { 59 | expect(serverResHeader).to.equal("Echo"); 60 | done(); 61 | }); 62 | it("should respond with correct token", (done) => { 63 | expect(serverResToken).to.equal(`Bearer ${FOO_INVALID_TOKEN}`); 64 | done(); 65 | }); 66 | }); 67 | 68 | after(() => {}); 69 | }); 70 | } 71 | -------------------------------------------------------------------------------- /oada/services/auth/src/db/models/client.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import { Codes, OADAError } from "@oada/error"; 19 | import { Client } from "@oada/models/client"; 20 | import type { Except, Promisable } from "type-fest"; 21 | import { config } from "../../config.js"; 22 | 23 | import { getDataStores, type Store, tryDataStores } from "./index.js"; 24 | 25 | export { Client } from "@oada/models/client"; 26 | 27 | export interface IClients extends Store { 28 | findById(id: string): Promisable; 29 | save(client: Except): Promisable; 30 | } 31 | 32 | const dataStores = await getDataStores( 33 | config.get("auth.client.dataStore"), 34 | "clients", 35 | ); 36 | 37 | export async function findById(id: string) { 38 | async function findClientById(dataStore: IClients) { 39 | const c = await dataStore.findById(id); 40 | return c ? new Client(c) : undefined; 41 | } 42 | 43 | return tryDataStores(dataStores, findClientById); 44 | } 45 | 46 | export async function save(c: Partial>) { 47 | const client = new Client(c); 48 | if (await findById(client.client_id)) { 49 | throw new OADAError( 50 | "Client Id already exists", 51 | Codes.BadRequest, 52 | "There was a problem durring the login", 53 | ); 54 | } 55 | 56 | // ???: Should it only save to first datastore? 57 | await dataStores[0]!.save(client); 58 | const saved = await findById(client.client_id); 59 | if (!saved) { 60 | throw new Error("Could not save client"); 61 | } 62 | 63 | return saved; 64 | } 65 | -------------------------------------------------------------------------------- /oada/services/auth/src/db/models/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2024 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * https://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import path from "node:path"; 19 | import url from "node:url"; 20 | 21 | const dirname = path.dirname(url.fileURLToPath(import.meta.url)); 22 | 23 | export interface Store { 24 | name: string; 25 | } 26 | 27 | export async function getDataStores( 28 | stores: string | readonly string[], 29 | item: string, 30 | ): Promise { 31 | const array = Array.isArray(stores) ? stores : [stores]; 32 | const promises = array.map(async (dataStore) => { 33 | const store: unknown = await import( 34 | path.join(dirname, "..", dataStore, `${item}.js`) 35 | ); 36 | return { 37 | name: dataStore, 38 | // @ts-expect-error stuff 39 | ...store, 40 | } as T; 41 | }); 42 | 43 | return Promise.all(promises); 44 | } 45 | 46 | /** 47 | * Try `queryFun` against all configured data stores in order 48 | */ 49 | export async function tryDataStores( 50 | stores: readonly T[], 51 | queryFun: (store: T) => Promise, 52 | ) { 53 | const errors: Error[] = []; 54 | for await (const store of stores) { 55 | try { 56 | const value = await queryFun(store); 57 | if (value) { 58 | return value; 59 | } 60 | } catch (cError: unknown) { 61 | errors.push(cError as Error); 62 | } 63 | } 64 | 65 | if (errors.length === 0) { 66 | return; 67 | } 68 | 69 | const names = stores.map(({ name }) => name); 70 | throw new Error(`${queryFun.name} failed to find result(s) among ${names}`, { 71 | cause: errors, 72 | }); 73 | } 74 | -------------------------------------------------------------------------------- /oada/services/auth/src/db/arango/tokens.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2024 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import { authorizations } from "@oada/lib-arangodb"; 19 | import debug from "debug"; 20 | 21 | import type { ITokens, Token } from "../models/token.js"; 22 | 23 | const trace = debug("arango:token:trace"); 24 | 25 | export const verify = (async (token: string) => { 26 | trace("findByToken: searching for token %s", token); 27 | const found = await authorizations.findByToken(token); 28 | if (!found) { 29 | throw new Error("Token not found"); 30 | } 31 | 32 | const { 33 | _id: _, 34 | token: t, 35 | clientId, 36 | user: { 37 | sub, 38 | // @ts-expect-error deprecated key 39 | _id, 40 | ...user 41 | }, 42 | scope, 43 | createTime, 44 | expiresIn, 45 | ...rest 46 | } = found; 47 | 48 | return { 49 | jti: t, 50 | client_id: clientId, 51 | scope: scope.join(" "), 52 | iat: createTime, 53 | exp: expiresIn, 54 | sub: sub ?? _id, 55 | ...user, 56 | ...rest, 57 | }; 58 | }) satisfies ITokens["verify"]; 59 | 60 | export const create = (async ({ 61 | jti, 62 | client_id, 63 | sub, 64 | scope, 65 | iat, 66 | exp, 67 | ...rest 68 | }: Token) => { 69 | const t = { 70 | ...rest, 71 | token: jti, 72 | clientId: client_id!, 73 | user: { 74 | sub, 75 | _id: sub, 76 | }, 77 | scope: scope.split(" "), 78 | createTime: iat, 79 | expiresIn: exp, 80 | }; 81 | trace(t, "save: saving token"); 82 | const { token } = await authorizations.save(t); 83 | return token; 84 | }) satisfies ITokens["create"]; 85 | -------------------------------------------------------------------------------- /oada/services/auth/src/db/models/token.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2024 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import { Authorization as Token } from "@oada/models/authorization"; 19 | 20 | import debug from "debug"; 21 | import type { Promisable } from "type-fest"; 22 | import { config } from "../../config.js"; 23 | 24 | import { getDataStores, type Store, tryDataStores } from "./index.js"; 25 | 26 | const log = debug("model-tokens"); 27 | 28 | export interface ITokens extends Store { 29 | /** 30 | * Verify a token and return the associated claims 31 | */ 32 | verify(token: string, issuer?: string): Promisable>; 33 | /** 34 | * Create and persist (save to db, sign, etc.) a new token 35 | */ 36 | create(token: Token): Promisable; 37 | revoke(token: Token): Promisable; 38 | } 39 | 40 | const dataStores = await getDataStores( 41 | config.get("auth.token.dataStore"), 42 | "tokens", 43 | ); 44 | 45 | export async function verify(token: string, issuer?: string) { 46 | async function verifyToken(dataStore: ITokens) { 47 | const t = await dataStore.verify(token, issuer); 48 | return t ? new Token(t) : undefined; 49 | } 50 | 51 | return tryDataStores(dataStores, verifyToken); 52 | } 53 | 54 | export async function create(t: Partial, issuer?: string) { 55 | const token = t instanceof Token ? t : new Token({ ...t, iss: issuer }); 56 | log(token, "save: saving token "); 57 | 58 | // ???: Should it only save to first datastore? 59 | const saved = await dataStores[0]!.create(token); 60 | if (!saved) { 61 | throw new Error("Could not save token"); 62 | } 63 | 64 | return saved; 65 | } 66 | 67 | export { Authorization as Token } from "@oada/models/authorization"; 68 | -------------------------------------------------------------------------------- /.github/workflows/semgrep-analysis.yml: -------------------------------------------------------------------------------- 1 | # This workflow file requires a free account on Semgrep.dev to 2 | # manage rules, file ignores, notifications, and more. 3 | # 4 | # See https://semgrep.dev/docs 5 | 6 | name: Semgrep 7 | 8 | permissions: read-all 9 | 10 | on: 11 | # Scan changed files in PRs (diff-aware scanning): 12 | pull_request: {} 13 | # Scan on-demand through GitHub Actions interface: 14 | workflow_dispatch: {} 15 | # Scan mainline branches and report all findings: 16 | push: 17 | branches: [master, main] 18 | # Schedule the CI job (this method uses cron syntax): 19 | schedule: 20 | - cron: 24 3 * * 3 21 | 22 | jobs: 23 | semgrep: 24 | # User definable name of this GitHub Actions job. 25 | name: semgrep/ci 26 | # If you are self-hosting, change the following `runs-on` value: 27 | runs-on: ubuntu-latest 28 | 29 | permissions: 30 | security-events: write 31 | 32 | container: 33 | # A Docker image with Semgrep installed. Do not change this. 34 | image: semgrep/semgrep 35 | 36 | # Skip any PR created by dependabot to avoid permission issues: 37 | if: (github.actor != 'dependabot[bot]') 38 | 39 | steps: 40 | # Fetch project source with GitHub Actions Checkout. 41 | - uses: actions/checkout@v5 42 | # Run the "semgrep ci" command on the command line of the docker image. 43 | - run: semgrep ci --sarif --output=semgrep.sarif 44 | continue-on-error: true 45 | env: 46 | # Connect to Semgrep Cloud Platform through your SEMGREP_APP_TOKEN. 47 | # Generate a token from Semgrep Cloud Platform > Settings 48 | # and add it to your GitHub secrets. 49 | SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} 50 | SEMGREP_DEPLOYMENT_ID: ${{ secrets.SEMGREP_DEPLOYMENT_ID }} 51 | 52 | - name: Secure Code Warrior 53 | uses: SecureCodeWarrior/github-action-add-sarif-contextual-training@v1 54 | with: 55 | inputSarifFile: ./semgrep.sarif 56 | outputSarifFile: ./securecodewarrior.sarif 57 | githubToken: ${{ secrets.GITHUB_TOKEN }} 58 | if: always() 59 | 60 | - name: Upload SARIF file for GitHub Advanced Security Dashboard 61 | uses: github/codeql-action/upload-sarif@v4 62 | with: 63 | sarif_file: ./securecodewarrior.sarif 64 | if: always() 65 | -------------------------------------------------------------------------------- /oada/services/auth/domains/localhost/signed_software_statement.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | // eslint-disable-next-line no-secrets/no-secrets 19 | export default "eyJqa3UiOiJodHRwczovL2lkZW50aXR5Lm9hZGEtZGV2LmNvbS9jZXJ0cyIsImtpZCI6ImtqY1NjamMzMmR3SlhYTEpEczNyMTI0c2ExIiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJyZWRpcmVjdF91cmlzIjpbImh0dHBzOi8vbG9jYWxob3N0L29hZGFhdXRoL2lkLXJlZGlyZWN0Il0sInRva2VuX2VuZHBvaW50X2F1dGhfbWV0aG9kIjoidXJuOmlldGY6cGFyYW1zOm9hdXRoOmNsaWVudC1hc3NlcnRpb24tdHlwZTpqd3QtYmVhcmVyIiwiZ3JhbnRfdHlwZXMiOlsiYXV0aG9yaXphdGlvbl9jb2RlIl0sInJlc3BvbnNlX3R5cGVzIjpbInRva2VuIiwiY29kZSIsImlkX3Rva2VuIiwiaWRfdG9rZW4gdG9rZW4iLCJjb2RlIGlkX3Rva2VuIiwiY29kZSB0b2tlbiIsImNvZGUgaWRfdG9rZW4gdG9rZW4iXSwiY2xpZW50X25hbWUiOiJMb2NhbGhvc3QiLCJjbGllbnRfdXJpIjoiaHR0cHM6Ly9sb2NhbGhvc3QiLCJjb250YWN0cyI6WyJBYXJvbiBBdWx0IDxhdWx0YWNAcHVyZHVlLmVkdT4iXSwiandrcyI6eyJrZXlzIjpbeyJraWQiOiI5MEQwMEE5OTdCNzc0QUQ0QjNCNEVFQjBFODREQzZDRiIsImt0eSI6IlJTQSIsIm4iOiI2QTJ3ZVY5eERhSWFyYWhTdkNTcFFqdC00b0I1ZVFYSWN0bWtnejdBODNQSjRWQ0IxNkRmbk9HMFUwV2FsdkdwVjJ4cEt6RkRmYzVQVFQ5UGNJX3BWaDBMQ0tWN2FvZmhtRHpqbWZad2lHWnpobzI1WHZ0d3ZBRFV0OTFCZnB3NmhKODY3Z1htRmJPcGFYRW5ZYk8yTUJvdzBtMmFLa1B5RTJpRm45aFFRbDZxM1h0YkFhZWppWVlLeGIxbkxRaHBjYkxYWDZ3ajVuUjYyTTd3eTVjTkJQVHRVbXBKaEtNbXlwNDMtM0JJNFg0ejB3ZXpVWEc5dmxhSGk5UEhDdG1DV2g2eUVNQk1abFlMaDJhd2ZJUW94NkpRaFIzTkVKMXRUVzlnRTdpMER3NnhsTjR2ZG1qM0VpWDZuS1VhWG9mM252QlNZVi0tV01YbWpwSDdxb09Ca1EiLCJlIjoiQVFBQiJ9XX0sInNvZnR3YXJlX2lkIjoiYTdlMjJkMTAtYzEzMS00OWM4LTkzOGItZmFhODExZjJiMjZjIiwicmVnaXN0cmF0aW9uX3Byb3ZpZGVyIjoiaHR0cHM6Ly9pZGVudGl0eS5vYWRhLWRldi5jb20iLCJpYXQiOjE1MDU3OTA4NDZ9.CoNNTADZ4tGufGT7f_hNSinu4HeT1nvA3eybHyZHV6MWeXw6wGvxw9hWTmvaFdlnDnhcDJ-gPCLtzs1dRZR5Vf-UF3vqZJVMOqoWIhRJnGYWmVleODwFzj2NcRjh-XiDWydPdOSWLvV7b1A6TG94_OUnzmfMnMEZ3PAeBQp66Tg"; 20 | -------------------------------------------------------------------------------- /oada/tests/restartall.ps1: -------------------------------------------------------------------------------- 1 | # if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs; exit } 2 | 3 | $scriptpath = $MyInvocation.MyCommand.Path 4 | $dir = Split-Path $scriptpath 5 | 6 | cd $dir 7 | cd .. 8 | 9 | Write-Host 10 | Write-Host "================================" 11 | Write-Host "pwd ..." 12 | Write-Host "================================" 13 | 14 | Write-Host $pwd 15 | 16 | Write-Host 17 | Write-Host "================================" 18 | Write-Host "docker-compose down ..." 19 | Write-Host "================================" 20 | docker-compose down 21 | 22 | cd .\oada-srvc-tests\ 23 | 24 | Write-Host 25 | Write-Host "================================" 26 | Write-Host "Clear docker containers ..." 27 | Write-Host "================================" 28 | docker stop $(docker ps -aq) 29 | docker rm $(docker ps -aq) 30 | docker volume rm $(docker volume ls -q) 31 | 32 | cd .. 33 | 34 | Write-Host 35 | Write-Host "================================" 36 | Write-Host "Git: pull stuff ..." 37 | Write-Host "================================" 38 | git pull 39 | # git submodule update --remote --merge 40 | 41 | Write-Host 42 | Write-Host "================================" 43 | Write-Host "docker-compose build ..." 44 | Write-Host "================================" 45 | docker-compose build 46 | 47 | Write-Host 48 | Write-Host "================================" 49 | Write-Host "Yarn install stuff ..." 50 | Write-Host "================================" 51 | docker-compose run --rm admin do-yarn-install.sh 52 | docker-compose run --rm admin do-yarn-upgrade.sh 53 | 54 | Write-Host 55 | Write-Host "================================" 56 | Write-Host "docker-compose up -d ..." 57 | Write-Host "================================" 58 | $env:DEBUG = "*" 59 | docker-compose up --force-recreate -d 60 | 61 | Write-Host 62 | Write-Host "================================" 63 | Write-Host "docker-compose ps ..." 64 | Write-Host "================================" 65 | docker-compose ps 66 | 67 | Write-Host 68 | Write-Host "================================" 69 | Write-Host "Done! Press any key to exit..." 70 | Write-Host "================================" 71 | $x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") 72 | -------------------------------------------------------------------------------- /oada/libs/lib-arangodb/src/libs/exampledocs/changeEdges.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | export default [ 19 | // ------------------------------------------------------- 20 | // /bookmarks/rocks 21 | { 22 | _id: "changeEdges/default:changeEdges_rocks_123", 23 | path: "/rocks", 24 | _from: "changes/default:resources_bookmarks_123", 25 | _to: "changes/default:resources_rocks_123", 26 | }, 27 | 28 | // -------------------------------------------------------- 29 | // /bookmarks/rocks/rocks-index 30 | { 31 | _id: "changeEdges/default:changeEdges_rocks-index_123", 32 | path: "/rocks-index", 33 | _from: "changes/default:resources_rocks_123", 34 | _to: "changes/default:resources_rocks_123:rocks-index", 35 | }, 36 | 37 | // -------------------------------------------------------- 38 | // /bookmarks/rocks/rocks-index/90j2klfdjss 39 | { 40 | _id: "changeEdges/default:changeEdges_90j2klfdjss_123", 41 | path: "/90jsklfdjss", 42 | _from: "changes/default:resources_rocks_123:rocks-index", 43 | _to: "changes/default:resources_rock_123", 44 | }, 45 | 46 | // ------------------------------------------------------- 47 | // /bookmarks/trellisfw 48 | { 49 | _id: "changeEdges/default:changeEdges_trellisfw_123", 50 | path: "/trellisfw", 51 | _from: "changes/default:resources_bookmarks_999", 52 | _to: "changes/default:resources_trellisfw_999", 53 | }, 54 | // -------------------------------------------------------- 55 | // /bookmarks/trellisfw/clients 56 | { 57 | _id: "changeEdges/default:changeEdges_clients_123", 58 | path: "/clients", 59 | _from: "changes/default:resources_trellisfw_999", 60 | _to: "changes/default:resources_clients_999", 61 | }, 62 | ]; 63 | -------------------------------------------------------------------------------- /oada/libs/lib-arangodb/test/token.test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import test from "ava"; 19 | import { authorizations, init } from "../dist/index.js"; 20 | // TODO: Would be nice to just expose these examples on oadaLib itself --- feel 21 | // like we will want them for all of the microservice tests 22 | import exampleTokens from "../dist/libs/exampledocs/authorizations.js"; 23 | import exampleUsers from "../dist/libs/exampledocs/users.js"; 24 | import type { UserID } from "../src/libs/users.js"; 25 | 26 | test.before(init.run); 27 | 28 | test.after(init.cleanup); 29 | 30 | test("should find a token", async (t) => { 31 | const token = exampleTokens[0]; 32 | 33 | const tok = await authorizations.findByToken(token.token); 34 | t.is(tok?.token, token.token); 35 | t.is(tok?.createTime, token.createTime); 36 | t.is(tok?.expiresIn, token.expiresIn); 37 | t.assert(typeof tok?.user === "object"); 38 | t.is(tok?.user?._id, token.user._id as UserID); 39 | t.is(tok?.clientId, token.clientId); 40 | }); 41 | 42 | test("should save a token", async (t) => { 43 | const token = exampleTokens[0]; 44 | const user = exampleUsers[0]; 45 | 46 | await authorizations.save({ 47 | ...token, 48 | // @ts-expect-error secrey key 49 | _key: `${token._key}-no-duplicates`, 50 | token: "abc-no-duplicates", 51 | user: { 52 | _id: user._id, 53 | }, 54 | }); 55 | 56 | const tok = await authorizations.findByToken("abc-no-duplicates"); 57 | t.is(tok?.token, "abc-no-duplicates"); 58 | t.is(tok?.createTime, token.createTime); 59 | t.is(tok?.expiresIn, token.expiresIn); 60 | t.assert(typeof tok?.user === "object"); 61 | t.is(tok?.user._id, user._id as UserID); 62 | t.is(tok?.clientId, token.clientId); 63 | }); 64 | -------------------------------------------------------------------------------- /oada/libs/lib-arangodb/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@oada/lib-arangodb", 3 | "version": "4.0.0", 4 | "description": "All OADA Arango interface code in one place.", 5 | "main": "dist/index.js", 6 | "bin": { 7 | "import": "./dist/import.js" 8 | }, 9 | "type": "module", 10 | "engines": { 11 | "node": ">=20.0.0" 12 | }, 13 | "files": [ 14 | "src/**/*", 15 | "dist/**/*" 16 | ], 17 | "contributors": [ 18 | "Alex Layton (https://github.com/awlayton)", 19 | "Andrew Balmos (https://github.com/abalmos)" 20 | ], 21 | "repository": { 22 | "type": "git", 23 | "url": "git+https://github.com/OADA/@oada/lib-arangodb.git" 24 | }, 25 | "author": "Aaron Ault (https://github.com/aultac)", 26 | "license": "Apache-2.0", 27 | "bugs": { 28 | "url": "https://github.com/OADA/@oada/lib-arangodb/issues" 29 | }, 30 | "homepage": "https://github.com/OADA/@oada/lib-arangodb#readme", 31 | "keywords": [ 32 | "oada", 33 | "arangodb", 34 | "lib" 35 | ], 36 | "scripts": { 37 | "build": "yarn g:tsc", 38 | "clean": "yarn run build --clean", 39 | "init": "node dist/init.js", 40 | "test": "yarn run build test && ava" 41 | }, 42 | "ava": { 43 | "files": [ 44 | "**/*.test.ts" 45 | ], 46 | "typescript": { 47 | "extensions": [ 48 | "ts" 49 | ], 50 | "rewritePaths": { 51 | "src/": "dist/", 52 | "test/": ".test/" 53 | }, 54 | "compile": false 55 | } 56 | }, 57 | "dependencies": { 58 | "@oada/lib-config": "workspace:^", 59 | "@oada/models": "workspace:^", 60 | "@oada/oadaify": "^2.1.0", 61 | "@oada/types": "^4.0.0", 62 | "arangojs": "^10.1.2", 63 | "bcryptjs": "^3.0.2", 64 | "debug": "^4.4.3", 65 | "deep-equal": "^2.2.3", 66 | "flat": "^6.0.1", 67 | "json-ptr": "^3.1.1", 68 | "p-throttle": "^8.0.0", 69 | "tslib": "2.8.1" 70 | }, 71 | "devDependencies": { 72 | "@ava/typescript": "^6.0.0", 73 | "@types/bcryptjs": "^3.0.0", 74 | "@types/convict": "^6.1.6", 75 | "@types/debug": "^4.1.12", 76 | "@types/deep-equal": "^1.0.4", 77 | "@types/flat": "^5.0.5", 78 | "@types/json-pointer": "^1.0.34", 79 | "@types/node": "^24.6.0", 80 | "ava": "6.4.1", 81 | "type-fest": "^5.0.1" 82 | }, 83 | "volta": { 84 | "node": "22.5.1" 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /oada/libs/lib-kafka/src/Kafka.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2022 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import debug from "debug"; 19 | import { Kafka, type KafkaConfig, type logLevel } from "kafkajs"; 20 | import { config } from "./config.js"; 21 | 22 | /** 23 | * Make kafkajs logging nicer? 24 | */ 25 | type KafkajsDebug = Record< 26 | keyof Omit, 27 | debug.Debugger 28 | >; 29 | const kafkajsDebugs = new Map(); 30 | function getKafkajsDebug(namespace: string): KafkajsDebug { 31 | const d = kafkajsDebugs.get(namespace); 32 | if (d) { 33 | return d; 34 | } 35 | 36 | const newDebug = { 37 | ERROR: debug(`kafkajs:${namespace}:error`), 38 | WARN: debug(`kafkajs:${namespace}:warn`), 39 | INFO: debug(`kafkajs:${namespace}:info`), 40 | DEBUG: debug(`kafkajs:${namespace}:debug`), 41 | }; 42 | kafkajsDebugs.set(namespace, newDebug); 43 | return newDebug; 44 | } 45 | 46 | /** 47 | * Wraps the `Kafka` client class to add our own defaults etc. 48 | * @see {@link Kafka} 49 | */ 50 | export default class IKafka extends Kafka { 51 | constructor({ 52 | brokers = config.get("kafka.broker"), 53 | ...rest 54 | }: Partial = {}) { 55 | super({ 56 | ...rest, 57 | /** 58 | * Make kafkajs logging nicer? 59 | */ 60 | logCreator() { 61 | return ({ namespace, label, log }) => { 62 | const l = label as keyof KafkajsDebug; 63 | 64 | const logger = getKafkajsDebug(namespace)[l]; 65 | if (log instanceof Error) { 66 | logger({ err: log }, log.message); 67 | } else { 68 | const { message, ...extra } = log; 69 | logger(extra, message); 70 | } 71 | }; 72 | }, 73 | brokers, 74 | }); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /oada/tests/test-host-level/containersAlive.js: -------------------------------------------------------------------------------- 1 | /* 2 | Note: This test requires monitoring over Docker containers, so it is not 3 | isolated in the tests container; Please run it on the host machine or using 4 | the admin container with Docker instead. 5 | 6 | Testing script 0: 7 | - Check that all the components needed are running as Docker containers. 8 | 9 | */ 10 | 11 | describe("Required Docker containers", () => { 12 | // Config.set('isTest', true); 13 | 14 | const debug = require("debug"); 15 | const trace = debug("tests:trace"); 16 | const info = debug("tests:info"); 17 | const error = debug("tests:error"); 18 | 19 | const { expect } = require("chai"); 20 | const Promise = require("bluebird"); 21 | 22 | const { exec } = require("node-exec-promise"); 23 | 24 | const REQUIRED_CONTAINER_NAMES = [ 25 | "arangodb", 26 | "auth", 27 | "graph-lookup", 28 | "http-handler", 29 | "hitman", 30 | "proxy", 31 | "rev-graph-update", 32 | "startup", 33 | "token-lookup", 34 | "well-known", 35 | "write-handler", 36 | ]; 37 | 38 | const containersAreRunning = Array.apply( 39 | null, 40 | Array.from({ length: REQUIRED_CONTAINER_NAMES.length }), 41 | ).map(Boolean, false); 42 | 43 | before((done) => { 44 | Promise.each(REQUIRED_CONTAINER_NAMES, (containerName, index) => { 45 | info(` ${containerName}`); 46 | return exec( 47 | `docker inspect -f '{{.State.Running}} ' ${containerName}`, 48 | ).then((execResult) => { 49 | trace( 50 | ` execResult for ${containerName}: ${JSON.stringify(execResult)}`, 51 | ); 52 | const isRunning = execResult.stdout.includes("true"); 53 | trace(` isRunning: ${isRunning}`); 54 | containersAreRunning[index] = isRunning; 55 | }); 56 | }) 57 | .catch((error_) => error(error_)) 58 | .asCallback(() => { 59 | trace(` containersAreRunning: ${containersAreRunning}`); 60 | done(); 61 | }); 62 | }); 63 | 64 | // Tests. 65 | describe("containersAreRunning", () => { 66 | trace(` containersAreRunning: ${containersAreRunning}`); 67 | for (const [index, containerName] of REQUIRED_CONTAINER_NAMES.entries()) { 68 | describe(containerName, () => { 69 | it("should be running", () => { 70 | expect(containersAreRunning[index]).to.be.a("Boolean").equals.true; 71 | }); 72 | }); 73 | } 74 | }); 75 | }); 76 | -------------------------------------------------------------------------------- /oada/services/auth/src/keys.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2024 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * https://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import { 19 | createPrivateKey, 20 | createPublicKey, 21 | createSecretKey, 22 | } from "node:crypto"; 23 | import { 24 | createLocalJWKSet, 25 | exportJWK, 26 | generateKeyPair, 27 | generateSecret, 28 | } from "jose"; 29 | import { config } from "./config.js"; 30 | 31 | const tokenConfig = config.get("auth.token"); 32 | 33 | /** 34 | * @todo proper key/kid management/storage/rotation 35 | */ 36 | export const kid = "oauth2-1"; 37 | 38 | export async function getKeyPair(file: File | string | undefined, alg: string) { 39 | if (!file) { 40 | return generateKeyPair(alg); 41 | } 42 | 43 | // Assume file is a private key 44 | const privateKey = createPrivateKey( 45 | typeof file === "string" ? file : Buffer.from(await file.arrayBuffer()), 46 | ); 47 | // Derive a public key from the private key 48 | const publicKey = createPublicKey(privateKey); 49 | return { privateKey, publicKey }; 50 | } 51 | 52 | export async function getSymmetricKey( 53 | file: File | string | undefined, 54 | alg: string, 55 | ) { 56 | if (!file) { 57 | return generateSecret(alg); 58 | } 59 | 60 | const key = 61 | typeof file === "string" ? file : Buffer.from(await file.arrayBuffer()); 62 | return createSecretKey(key as NodeJS.ArrayBufferView); 63 | } 64 | 65 | /** 66 | * @internal 67 | * @todo Support key rotation and stuff 68 | */ 69 | export const { publicKey, privateKey } = await getKeyPair( 70 | await tokenConfig.key, 71 | tokenConfig.alg, 72 | ); 73 | export const jwksPublic = { 74 | keys: [ 75 | { 76 | kid, 77 | alg: tokenConfig.alg, 78 | use: "sig", 79 | ...(await exportJWK(publicKey)), 80 | }, 81 | ], 82 | }; 83 | 84 | /** @internal */ 85 | export const JWKS = createLocalJWKSet(jwksPublic); 86 | -------------------------------------------------------------------------------- /oada/services/auth/src/db/arango/users.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import { users } from "@oada/lib-arangodb"; 19 | import debug from "debug"; 20 | 21 | import type { IUsers, User } from "../models/user.js"; 22 | 23 | const trace = debug("arango:user:trace"); 24 | 25 | export const findById = (async (id: string) => { 26 | trace("findById: searching for user %s", id); 27 | return users.findById(id); 28 | }) satisfies IUsers["findById"]; 29 | 30 | export const findByUsername = (async (username: User["username"]) => { 31 | trace("findByUsername: searching for user %s", username); 32 | return users.findByUsername(username); 33 | }) satisfies IUsers["findByUsername"]; 34 | 35 | export const findByUsernamePassword = (async ( 36 | username: User["username"], 37 | password: string, 38 | ) => { 39 | trace("findByUsername: searching for user %s with password", username); 40 | return users.findByUsernamePassword(username, password); 41 | }) satisfies IUsers["findByUsernamePassword"]; 42 | 43 | export const findByOIDCToken = (async (token: { sub: string; iss: string }) => { 44 | trace( 45 | "findByOIDCToken: searching for oidc token sub=%s, iss=%s", 46 | token.sub, 47 | token.iss, 48 | ); 49 | return users.findByOIDCToken(token); 50 | }) satisfies IUsers["findByOIDCToken"]; 51 | 52 | export const findByOIDCUsername = (async ( 53 | username: User["username"], 54 | domain: string, 55 | ) => { 56 | trace( 57 | "findByOIDCUsername: searching for oidc username %s at %d", 58 | username, 59 | domain, 60 | ); 61 | return users.findByOIDCUsername(username, domain); 62 | }) satisfies IUsers["findByOIDCUsername"]; 63 | 64 | export const update = (async (user: User) => { 65 | await users.update(user); 66 | }) satisfies IUsers["update"]; 67 | 68 | export const create = (async (user: User) => 69 | users.create(user)) satisfies IUsers["create"]; 70 | -------------------------------------------------------------------------------- /charts/oada/templates/well-known.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | * Copyright 2022 Open Ag Data Alliance 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */}} 16 | apiVersion: v1 17 | kind: Service 18 | metadata: 19 | namespace: {{ .Release.Namespace }} 20 | name: well-known-{{ .Release.Name }} 21 | labels: 22 | app.kubernetes.io/component: well-known 23 | {{- include "oada.chart.labels" . | nindent 4 }} 24 | spec: 25 | ports: 26 | - name: http 27 | port: 80 28 | targetPort: http 29 | selector: 30 | app.kubernetes.io/component: well-known 31 | {{- if .Values.ingress.enabled }} 32 | --- 33 | apiVersion: networking.k8s.io/v1 34 | kind: Ingress 35 | metadata: 36 | namespace: {{ .Release.Namespace }} 37 | name: well-known-ingress-{{ .Release.Name }} 38 | labels: 39 | app.kubernetes.io/component: well-known 40 | {{ include "oada.chart.labels" . | nindent 4 }} 41 | annotations: 42 | #nginx.ingress.kubernetes.io/rewrite-target: / 43 | cert-manager.io/issuer: issuer-oada-{{ .Release.Name }} 44 | spec: 45 | {{ if .Values.ingress.className -}} 46 | ingressClassName: {{ .Values.ingress.className }} 47 | {{- end }} 48 | tls: 49 | - hosts: {{ default (list "localhost") .Values.oada.domains | toJson }} 50 | secretName: {{ include "oada.tls" . }} 51 | rules: 52 | {{ if empty .Values.oada.domains -}} 53 | - http: 54 | paths: 55 | - path: /.well-known/ 56 | pathType: Prefix 57 | backend: 58 | service: 59 | name: well-known-{{ .Release.Name }} 60 | port: 61 | name: http 62 | {{- end }} 63 | {{- range .Values.oada.domains -}} 64 | - host: {{ quote . }} 65 | http: 66 | paths: 67 | - path: /.well-known/ 68 | pathType: Prefix 69 | backend: 70 | service: 71 | name: well-known-{{ $.Release.Name }} 72 | port: 73 | name: http 74 | {{ end -}} 75 | {{- end }} 76 | -------------------------------------------------------------------------------- /oada/libs/lib-arangodb/src/libs/exampledocs/edges.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | export default [ 19 | // ------------------------------------------------------- 20 | // /bookmarks/rocks 21 | { 22 | _id: "edges/default:edges_bookmarks_rocks_123", 23 | _from: "graphNodes/resources:default:resources_bookmarks_123", 24 | _to: "graphNodes/resources:default:resources_rocks_123", 25 | name: "rocks", 26 | versioned: true, 27 | }, 28 | 29 | // -------------------------------------------------------- 30 | // /bookmarks/rocks/rocks-index 31 | { 32 | _id: "edges/default:edges_rocks_rocks-index_123", 33 | _from: "graphNodes/resources:default:resources_rocks_123", 34 | _to: "graphNodes/resources:default:resources_rocks_123:rocks-index", 35 | name: "rocks-index", // This was internal to resource 36 | versioned: true, 37 | }, 38 | 39 | // -------------------------------------------------------- 40 | // /bookmarks/rocks/rocks-index/90j2klfdjss 41 | { 42 | _id: "edges/default:edges_rocks-index_rock_123", 43 | _from: "graphNodes/resources:default:resources_rocks_123:rocks-index", 44 | _to: "graphNodes/resources:default:resources_rock_123", 45 | name: "90j2klfdjss", 46 | versioned: true, 47 | }, 48 | 49 | // ------------------------------------------------------- 50 | // /bookmarks/trellisfw 51 | { 52 | _id: "edges/default:edges_bookmarks_trellisfw_999", 53 | _from: "graphNodes/resources:default:resources_bookmarks_999", 54 | _to: "graphNodes/resources:default:resources_trellisfw_999", 55 | name: "trellisfw", 56 | versioned: true, 57 | }, 58 | // -------------------------------------------------------- 59 | // /bookmarks/trellisfw/clients 60 | { 61 | _id: "edges/default:edges_trellisfw_clients_999", 62 | _from: "graphNodes/resources:default:resources_trellisfw_999", 63 | _to: "graphNodes/resources:default:resources_clients_999", 64 | name: "clients", 65 | versioned: true, 66 | }, 67 | ]; 68 | -------------------------------------------------------------------------------- /oada/services/auth/src/db/jwt/tokens.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2024 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import { randomBytes } from "node:crypto"; 19 | 20 | import debug from "debug"; 21 | import { jwtVerify, SignJWT } from "jose"; 22 | 23 | import { config } from "../../config.js"; 24 | import type { TokenClaims } from "../../index.js"; 25 | import { JWKS, kid, privateKey } from "../../keys.js"; 26 | import type { ITokens, Token } from "../models/token.js"; 27 | 28 | const tokenConfig = config.get("auth.token"); 29 | 30 | const trace = debug("arango:token:trace"); 31 | 32 | export const verify = (async (token: string, issuer: string) => { 33 | trace("findByToken: searching for token %s", token); 34 | const { payload } = await jwtVerify(token, JWKS, { 35 | issuer, 36 | audience: issuer, 37 | }); 38 | if (!payload) { 39 | throw new TypeError("Invalid token, no JWT payload"); 40 | } 41 | 42 | const { _id, ...t } = payload; 43 | 44 | return t; 45 | }) satisfies ITokens["verify"]; 46 | 47 | export const create = (async ( 48 | { sub, iat, exp, nbf, ...claims }: Token, 49 | issuer?: string, 50 | ) => { 51 | try { 52 | const iss = issuer ?? claims.iss; 53 | if (!iss) { 54 | throw new TypeError("Issuer not provided"); 55 | } 56 | 57 | const jwt = new SignJWT(claims) 58 | .setProtectedHeader({ 59 | alg: tokenConfig.alg, 60 | kid, 61 | jku: config.get("auth.endpoints.certs"), 62 | }) 63 | .setJti(randomBytes(16).toString("hex")) 64 | .setIssuedAt(iat) 65 | .setIssuer(iss) 66 | // ???: Should the audience be something different? 67 | // .setAudience(issuer) 68 | .setNotBefore(nbf ?? new Date()); 69 | 70 | if (sub) { 71 | jwt.setSubject(sub); 72 | } 73 | 74 | if (exp) { 75 | jwt.setExpirationTime(exp); 76 | } 77 | 78 | return await jwt.sign(privateKey); 79 | } catch (error: unknown) { 80 | throw new Error("Failed to issue token", { cause: error }); 81 | } 82 | }) satisfies ITokens["create"]; 83 | -------------------------------------------------------------------------------- /oada/tests/test-host-level/alwaysRestart.js: -------------------------------------------------------------------------------- 1 | /* 2 | Note: This test requires monitoring over Docker containers, so it is not 3 | isolated in the tests container; Please run it on the host machine or using 4 | the admin container with Docker instead. 5 | 6 | Testing script 1: 7 | - Any component should always be restarted some time after it gets killed. 8 | 9 | For easy of coding, we use GET to determine whether the component is back or 10 | not. 11 | */ 12 | 13 | describe("Components should be restarted after being killed", () => { 14 | // Config.set('isTest', true); 15 | 16 | const debug = require("debug"); 17 | const trace = debug("tests:trace"); 18 | const info = debug("tests:info"); 19 | const error = debug("tests:error"); 20 | 21 | const { expect } = require("chai"); 22 | const Promise = require("bluebird"); 23 | 24 | const { exec } = require("node-exec-promise"); 25 | 26 | const REQUIRED_CONTAINER_NAMES = [ 27 | "arangodb", 28 | "auth", 29 | "graph-lookup", 30 | "http-handler", 31 | "hitman", 32 | "proxy", 33 | "rev-graph-update", 34 | "startup", 35 | "token-lookup", 36 | "well-known", 37 | "write-handler", 38 | ]; 39 | 40 | const containersAreRunning = Array.apply( 41 | null, 42 | Array.from({ length: REQUIRED_CONTAINER_NAMES.length }), 43 | ).map(Boolean, false); 44 | 45 | before((done) => { 46 | Promise.each(REQUIRED_CONTAINER_NAMES, (containerName, index) => { 47 | info(` ${containerName}`); 48 | return exec( 49 | `docker inspect -f '{{.State.Running}} ' ${containerName}`, 50 | ).then((execResult) => { 51 | trace( 52 | ` execResult for ${containerName}: ${JSON.stringify(execResult)}`, 53 | ); 54 | const isRunning = execResult.stdout.includes("true"); 55 | trace(` isRunning: ${isRunning}`); 56 | containersAreRunning[index] = isRunning; 57 | }); 58 | }) 59 | .then(() => 60 | // Kill the containers specified. 61 | Promise.each(), 62 | ) 63 | .catch((error_) => error(error_)) 64 | .asCallback(() => { 65 | trace(` containersAreRunning: ${containersAreRunning}`); 66 | done(); 67 | }); 68 | }); 69 | 70 | // Tests. 71 | describe("containersAreRunning", () => { 72 | trace(` containersAreRunning: ${containersAreRunning}`); 73 | for (const [index, containerName] of REQUIRED_CONTAINER_NAMES.entries()) { 74 | describe(containerName, () => { 75 | it("should be running", () => { 76 | expect(containersAreRunning[index]).to.be.a("Boolean").equals.true; 77 | }); 78 | }); 79 | } 80 | }); 81 | }); 82 | -------------------------------------------------------------------------------- /oada/libs/models/src/client.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2024 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* eslint-disable @typescript-eslint/naming-convention */ 19 | 20 | import { randomBytes } from "node:crypto"; 21 | import type Metadata from "@oada/types/oauth-dyn-reg/response.js"; 22 | import { makeClass } from "@qlever-llc/interface2class"; 23 | import type { OmitIndexSignature, Opaque } from "type-fest"; 24 | import { generate } from "xksuid"; 25 | import { destructure } from "./decorators.js"; 26 | 27 | export type ClientID = Opaque; 28 | 29 | export const DEFAULT_SCOPES = ""; 30 | 31 | /** 32 | * Representation of an API client within OADA 33 | */ 34 | export 35 | @destructure 36 | class Client extends makeClass>() { 37 | // @ts-expect-error HACK 38 | constructor(client?: Partial); 39 | 40 | constructor( 41 | // biome-ignore lint/style/useDefaultParameterLast: 42 | rest: Partial = {}, 43 | 44 | override readonly client_id: ClientID, 45 | override readonly client_id_issued_at?: number, 46 | override readonly scope = DEFAULT_SCOPES, 47 | override readonly grant_types: Metadata["grant_types"] = [ 48 | "authorization_code", 49 | ], 50 | override readonly response_types: Metadata["response_types"] = ["code"], 51 | override readonly application_type: Metadata["application_type"] = "web", 52 | readonly puc?: string, 53 | readonly licenses: ReadonlyArray<{ id: string; name: string }> = [], 54 | readonly trusted?: boolean, 55 | override readonly client_secret?: string, 56 | override readonly client_secret_expires_at?: number, 57 | readonly registration_provider?: string, 58 | ) { 59 | super({ client_id, ...rest }); 60 | 61 | if (!client_id) { 62 | this.client_id = `clients/${generate()}` as ClientID; 63 | this.client_id_issued_at = Date.now() / 1000; 64 | } 65 | 66 | // TODO: More client secret logic/configurability 67 | if (this.application_type === "native" && !client_secret) { 68 | this.client_secret = randomBytes(256).toString("hex"); 69 | this.client_secret_expires_at = 0; 70 | } 71 | } 72 | } 73 | 74 | export default Client; 75 | -------------------------------------------------------------------------------- /oada/libs/lib-arangodb/src/libs/deviceCodes.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2017-2021 Open Ag Data Alliance 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import { aql } from "arangojs"; 19 | 20 | import { config } from "../config.js"; 21 | import { db as database } from "../db.js"; 22 | import { sanitizeResult } from "../util.js"; 23 | 24 | export interface DeviceCode { 25 | deviceCode: string; 26 | userCode: string; 27 | } 28 | 29 | const deviceCodes = database.collection( 30 | config.get("arangodb.collections.deviceCodes.name"), 31 | ); 32 | 33 | export async function findByDeviceCode( 34 | deviceCode: string, 35 | ): Promise { 36 | const cursor = await database.query( 37 | aql` 38 | FOR c IN ${deviceCodes} 39 | FILTER c.deviceCode == ${deviceCode} 40 | RETURN c`, 41 | ); 42 | 43 | const c = await cursor.next(); 44 | return c ? sanitizeResult(c) : undefined; 45 | } 46 | 47 | export async function findByUserCode( 48 | userCode: string, 49 | ): Promise { 50 | const cursor = await database.query( 51 | aql` 52 | FOR c IN ${deviceCodes} 53 | FILTER c.userCode == ${userCode} 54 | RETURN c`, 55 | ); 56 | 57 | const c = await cursor.next(); 58 | return c ? sanitizeResult(c) : undefined; 59 | } 60 | 61 | export async function save( 62 | deviceCode: DeviceCode, 63 | ): Promise { 64 | const { new: saved } = await deviceCodes.save(deviceCode, { 65 | returnNew: true, 66 | }); 67 | return saved; 68 | } 69 | 70 | export async function redeem(deviceCode: string) { 71 | const cursor = await database.query<{ redeemed: boolean; code?: DeviceCode }>( 72 | aql` 73 | LET code = ( 74 | FOR c IN ${deviceCodes} 75 | FILTER c.deviceCode == ${deviceCode} 76 | RETURN c 77 | ) 78 | LET clear = ( 79 | FOR c IN code 80 | FILTER HAS(c, 'approved') 81 | REMOVE c IN ${deviceCodes} 82 | RETURN OLD 83 | ) 84 | RETURN { 85 | redeemed: LENGTH(clear) == 1, 86 | code: FIRST(code), 87 | } 88 | `, 89 | ); 90 | return (await cursor.next())!; 91 | } 92 | --------------------------------------------------------------------------------