From 4794efa23cf254158dec273dfdcf04c5ee2bbaf3 Mon Sep 17 00:00:00 2001 From: Tyagi-Sunny Date: Tue, 21 Jan 2025 15:50:15 +0530 Subject: [PATCH] fix(sandbox): fix oauth exmple sandbox fix oauth exmple sandbox MIGRATION CHANGE: migration-20230323132703- fix oauth exmple sandbox migration-20240116123737- fix oauth exmple sandbox migration-20241105074844- fix oauth exmple sandbox migration-20210421113146- fix oauth exmple sandbox migration-20220607063927- fix oauth exmple sandbox migration-20221110095658- fix oauth exmple sandbox migration-20221123082900- fix oauth exmple sandbox migration-20230524115047- fix oauth exmple sandbox 0 --- package-lock.json | 311 +- packages/cli/README.md | 2 +- sandbox/auth-ms-basic-example/package.json | 2 +- sandbox/oauth-example/.dockerignore | 3 +- sandbox/oauth-example/.env.defaults | 66 + sandbox/oauth-example/.env.example | 87 + sandbox/oauth-example/.eslintignore | 3 +- sandbox/oauth-example/.eslintrc.js | 10 + sandbox/oauth-example/.mocharc.json | 3 +- sandbox/oauth-example/.nycrc | 5 + sandbox/oauth-example/.prettierignore | 3 + sandbox/oauth-example/.vscode/settings.json | 11 +- sandbox/oauth-example/.yo-rc.json | 4 +- sandbox/oauth-example/CHANGELOG.md | 492 --- sandbox/oauth-example/Dockerfile | 70 +- sandbox/oauth-example/README.md | 2 +- sandbox/oauth-example/database.json | 21 - ...1113036-init.js => 20210318100600-init.js} | 27 +- ...init.js => 20221110095658-updated-init.js} | 4 +- .../20230323132703-client-type-column.js | 59 + ...ed.js => 20230524115047-login-activity.js} | 34 +- .../20240116123737-sync-with-user-tenant.js | 59 + .../20241105074844-add-jwt-keys-schema.js | 59 + .../oauth-example/migrations/database.json | 38 +- ...-down.sql => 20210318100600-init-down.sql} | 0 ...init-up.sql => 20210318100600-init-up.sql} | 159 +- .../sqls/20210421113146-seed-down.sql | 8 - .../sqls/20210421113146-seed-up.sql | 51 - .../20220607063927-secret-key-column-up.sql | 2 +- ...l => 20221110095658-updated-init-down.sql} | 0 .../sqls/20221110095658-updated-init-up.sql | 11 + .../sqls/20221123082900-updated-init-up.sql | 11 - ...20230323132703-client-type-column-down.sql | 3 + .../20230323132703-client-type-column-up.sql | 4 + .../20230524115047-login-activity-down.sql | 6 + .../sqls/20230524115047-login-activity-up.sql | 16 + ...40116123737-sync-with-user-tenant-down.sql | 1 + ...0240116123737-sync-with-user-tenant-up.sql | 15 + ...0241105074844-add-jwt-keys-schema-down.sql | 1 + .../20241105074844-add-jwt-keys-schema-up.sql | 7 + sandbox/oauth-example/package.json | 69 +- sandbox/oauth-example/public/index.html | 16 +- .../acceptance/home-page.acceptance.ts | 8 +- .../acceptance/ping.controller.acceptance.ts | 8 +- .../src/__tests__/acceptance/test-helper.ts | 31 +- sandbox/oauth-example/src/application.ts | 145 +- .../src/controllers/home-page.controller.ts | 39 + .../oauth-example/src/controllers/index.ts | 5 +- .../src/controllers/ping.controller.ts | 23 +- .../{db.datasource.ts => auth.datasource.ts} | 34 +- .../oauth-example/src/datasources/index.ts | 6 +- .../src/datasources/redis.datasource.ts | 50 +- sandbox/oauth-example/src/index.ts | 15 +- sandbox/oauth-example/src/migrate.ts | 24 - sandbox/oauth-example/src/models/README.md | 3 + sandbox/oauth-example/src/models/index.ts | 0 sandbox/oauth-example/src/openapi-spec.ts | 27 +- sandbox/oauth-example/src/openapi.json | 3036 +++++++++++++++++ .../src/opentelemetry-registry.ts | 31 + .../src/providers/azure-ad-signup.provider.ts | 86 - .../facebook-oauth2-signup.provider.ts | 88 - .../google-oauth2-signup.provider.ts | 19 +- sandbox/oauth-example/src/providers/index.ts | 8 - .../src/providers/saml-signup.provider.ts | 89 - .../src/providers/saml-verify.provider.ts | 54 - .../oauth-example/src/repositories/README.md | 3 - .../oauth-example/src/repositories/index.ts | 7 - .../src/repositories/role.repository.ts | 20 - .../src/repositories/tenant.repository.ts | 43 - .../src/repositories/user.repository.ts | 245 -- sandbox/oauth-example/src/sequence.ts | 7 - sandbox/oauth-example/tsconfig.json | 11 +- services/payment-service/openapi.json | 2 +- services/payment-service/openapi.md | 4 +- services/reporting-service/openapi.json | 2 +- services/reporting-service/openapi.md | 4 +- services/user-tenant-service/openapi.json | 2 +- services/user-tenant-service/openapi.md | 4 +- 78 files changed, 4327 insertions(+), 1611 deletions(-) create mode 100644 sandbox/oauth-example/.env.defaults create mode 100644 sandbox/oauth-example/.env.example create mode 100644 sandbox/oauth-example/.nycrc delete mode 100644 sandbox/oauth-example/CHANGELOG.md delete mode 100644 sandbox/oauth-example/database.json rename sandbox/oauth-example/migrations/{20210421113036-init.js => 20210318100600-init.js} (77%) rename sandbox/oauth-example/migrations/{20221123082900-updated-init.js => 20221110095658-updated-init.js} (93%) create mode 100644 sandbox/oauth-example/migrations/20230323132703-client-type-column.js rename sandbox/oauth-example/migrations/{20210421113146-seed.js => 20230524115047-login-activity.js} (55%) create mode 100644 sandbox/oauth-example/migrations/20240116123737-sync-with-user-tenant.js create mode 100644 sandbox/oauth-example/migrations/20241105074844-add-jwt-keys-schema.js rename sandbox/oauth-example/migrations/sqls/{20210421113036-init-down.sql => 20210318100600-init-down.sql} (100%) rename sandbox/oauth-example/migrations/sqls/{20210421113036-init-up.sql => 20210318100600-init-up.sql} (59%) delete mode 100644 sandbox/oauth-example/migrations/sqls/20210421113146-seed-down.sql delete mode 100644 sandbox/oauth-example/migrations/sqls/20210421113146-seed-up.sql rename sandbox/oauth-example/migrations/sqls/{20221123082900-updated-init-down.sql => 20221110095658-updated-init-down.sql} (100%) create mode 100644 sandbox/oauth-example/migrations/sqls/20221110095658-updated-init-up.sql delete mode 100644 sandbox/oauth-example/migrations/sqls/20221123082900-updated-init-up.sql create mode 100644 sandbox/oauth-example/migrations/sqls/20230323132703-client-type-column-down.sql create mode 100644 sandbox/oauth-example/migrations/sqls/20230323132703-client-type-column-up.sql create mode 100644 sandbox/oauth-example/migrations/sqls/20230524115047-login-activity-down.sql create mode 100644 sandbox/oauth-example/migrations/sqls/20230524115047-login-activity-up.sql create mode 100644 sandbox/oauth-example/migrations/sqls/20240116123737-sync-with-user-tenant-down.sql create mode 100644 sandbox/oauth-example/migrations/sqls/20240116123737-sync-with-user-tenant-up.sql create mode 100644 sandbox/oauth-example/migrations/sqls/20241105074844-add-jwt-keys-schema-down.sql create mode 100644 sandbox/oauth-example/migrations/sqls/20241105074844-add-jwt-keys-schema-up.sql create mode 100644 sandbox/oauth-example/src/controllers/home-page.controller.ts rename sandbox/oauth-example/src/datasources/{db.datasource.ts => auth.datasource.ts} (54%) delete mode 100644 sandbox/oauth-example/src/migrate.ts create mode 100644 sandbox/oauth-example/src/models/README.md delete mode 100644 sandbox/oauth-example/src/models/index.ts create mode 100644 sandbox/oauth-example/src/openapi.json create mode 100644 sandbox/oauth-example/src/opentelemetry-registry.ts delete mode 100644 sandbox/oauth-example/src/providers/azure-ad-signup.provider.ts delete mode 100644 sandbox/oauth-example/src/providers/facebook-oauth2-signup.provider.ts delete mode 100644 sandbox/oauth-example/src/providers/saml-signup.provider.ts delete mode 100644 sandbox/oauth-example/src/providers/saml-verify.provider.ts delete mode 100644 sandbox/oauth-example/src/repositories/README.md delete mode 100644 sandbox/oauth-example/src/repositories/index.ts delete mode 100644 sandbox/oauth-example/src/repositories/role.repository.ts delete mode 100644 sandbox/oauth-example/src/repositories/tenant.repository.ts delete mode 100644 sandbox/oauth-example/src/repositories/user.repository.ts delete mode 100644 sandbox/oauth-example/src/sequence.ts diff --git a/package-lock.json b/package-lock.json index 2542e79325..523163262c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,6 +33,10 @@ "typedoc-plugin-markdown": "3.14.0" } }, + "node_modules/-auth": { + "resolved": "sandbox/oauth-example", + "link": true + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -11175,10 +11179,6 @@ "resolved": "sandbox/notification-socket-example", "link": true }, - "node_modules/@sourceloop/oauth-example-api": { - "resolved": "sandbox/oauth-example", - "link": true - }, "node_modules/@sourceloop/oidc-basic-example": { "resolved": "sandbox/oidc-basic-example", "link": true @@ -44405,37 +44405,275 @@ } }, "sandbox/oauth-example": { - "name": "@sourceloop/oauth-example-api", - "version": "0.5.13", + "name": "-auth", + "version": "0.0.1", "license": "MIT", "dependencies": { "@loopback/boot": "^7.0.9", + "@loopback/context": "^7.0.9", "@loopback/core": "^6.1.6", + "@loopback/openapi-v3": "^10.0.9", "@loopback/repository": "^7.0.9", "@loopback/rest": "^14.0.9", "@loopback/rest-explorer": "^7.0.9", "@loopback/service-proxy": "^7.0.9", + "@opentelemetry/exporter-jaeger": "^1.15.0", + "@opentelemetry/plugin-dns": "^0.15.0", + "@opentelemetry/plugin-http": "^0.18.2", + "@opentelemetry/plugin-https": "^0.18.2", + "@opentelemetry/plugin-pg": "^0.15.0", + "@opentelemetry/plugin-pg-pool": "^0.15.0", + "@opentelemetry/sdk-trace-base": "^1.15.0", + "@opentelemetry/sdk-trace-node": "^1.15.0", "@sourceloop/authentication-service": "^20.0.2", - "bcrypt": "^5.0.1", + "@sourceloop/core": "^15.0.2", "db-migrate": "^1.0.0-beta.21", "db-migrate-pg": "^1.3.0", "dotenv": "^16.4.5", "dotenv-extended": "^2.9.0", + "loopback-connector-kv-redis": "^4.0.0", "loopback-connector-postgresql": "^7.1.8", + "loopback4-authentication": "^12.1.1", + "loopback4-authorization": "^7.0.3", + "swagger-stats": "^0.99.5", + "symlink-resolver": "0.2.1", "tslib": "^2.6.2" }, "devDependencies": { + "@istanbuljs/nyc-config-typescript": "^1.0.2", "@loopback/build": "^11.0.8", "@loopback/eslint-config": "^15.0.4", "@loopback/testlab": "^7.0.8", - "@types/bcrypt": "^5.0.0", "@types/node": "^20.12.7", "eslint": "^8.57.0", + "nodemon": "^2.0.21", + "nyc": "^15.1.0", "source-map-support": "^0.5.21", "typescript": "^5.4.5" }, "engines": { - "node": "18 || 20" + "node": ">=18" + } + }, + "sandbox/oauth-example/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "sandbox/oauth-example/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "sandbox/oauth-example/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "sandbox/oauth-example/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "sandbox/oauth-example/node_modules/foreground-child": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "sandbox/oauth-example/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "sandbox/oauth-example/node_modules/istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "sandbox/oauth-example/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "sandbox/oauth-example/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "sandbox/oauth-example/node_modules/nyc": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", + "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", + "dev": true, + "dependencies": { + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "caching-transform": "^4.0.0", + "convert-source-map": "^1.7.0", + "decamelize": "^1.2.0", + "find-cache-dir": "^3.2.0", + "find-up": "^4.1.0", + "foreground-child": "^2.0.0", + "get-package-type": "^0.1.0", + "glob": "^7.1.6", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-hook": "^3.0.0", + "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-processinfo": "^2.0.2", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.2", + "make-dir": "^3.0.0", + "node-preload": "^0.2.1", + "p-map": "^3.0.0", + "process-on-spawn": "^1.0.0", + "resolve-from": "^5.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "spawn-wrap": "^2.0.0", + "test-exclude": "^6.0.0", + "yargs": "^15.0.2" + }, + "bin": { + "nyc": "bin/nyc.js" + }, + "engines": { + "node": ">=8.9" + } + }, + "sandbox/oauth-example/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "sandbox/oauth-example/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "sandbox/oauth-example/node_modules/p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "sandbox/oauth-example/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "sandbox/oauth-example/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" } }, "sandbox/oauth-example/node_modules/typescript": { @@ -44451,6 +44689,61 @@ "node": ">=14.17" } }, + "sandbox/oauth-example/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "sandbox/oauth-example/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "sandbox/oauth-example/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "sandbox/oauth-example/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, "sandbox/oidc-basic-example": { "name": "@sourceloop/oidc-basic-example", "version": "0.4.9", diff --git a/packages/cli/README.md b/packages/cli/README.md index 250126b983..93d860fc6e 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -18,7 +18,7 @@ $ npm install -g @sourceloop/cli $ sl COMMAND running command... $ sl (-v|--version|version) -@sourceloop/cli/9.2.3 linux-x64 node-v18.20.5 +@sourceloop/cli/9.2.3 linux-x64 node-v18.18.2 $ sl --help [COMMAND] USAGE $ sl COMMAND diff --git a/sandbox/auth-ms-basic-example/package.json b/sandbox/auth-ms-basic-example/package.json index 4b5fcade71..c35e587d00 100644 --- a/sandbox/auth-ms-basic-example/package.json +++ b/sandbox/auth-ms-basic-example/package.json @@ -92,4 +92,4 @@ "lodash": "^4.17.21" } } -} +} \ No newline at end of file diff --git a/sandbox/oauth-example/.dockerignore b/sandbox/oauth-example/.dockerignore index 7aecc7e3dd..86e2a5ca75 100644 --- a/sandbox/oauth-example/.dockerignore +++ b/sandbox/oauth-example/.dockerignore @@ -1,5 +1,6 @@ -node_modules +coverage npm-debug.log /dist # Cache used by TypeScript's incremental build *.tsbuildinfo +mochawesome-report \ No newline at end of file diff --git a/sandbox/oauth-example/.env.defaults b/sandbox/oauth-example/.env.defaults new file mode 100644 index 0000000000..9be445332f --- /dev/null +++ b/sandbox/oauth-example/.env.defaults @@ -0,0 +1,66 @@ +NODE_ENV=production +LOG_LEVEL=info +USER_TEMP_PASSWORD=temp123!@ +GOOGLE_AUTH_URL=q +GOOGLE_AUTH_CLIENT_ID=a +GOOGLE_AUTH_CLIENT_SECRET=q +GOOGLE_AUTH_TOKEN_URL=q +GOOGLE_AUTH_CALLBACK_URL=q +GOOGLE_TOKEN_INFO_URL=q +INSTAGRAM_AUTH_URL=q +INSTAGRAM_AUTH_CLIENT_ID=a +INSTAGRAM_AUTH_CLIENT_SECRET=q +INSTAGRAM_AUTH_TOKEN_URL=q +INSTAGRAM_AUTH_CALLBACK_URL=q +SAML_URL=q +SAML_CLIENT_ID=a +SAML_CLIENT_SECRET=q +SAML_TOKEN_URL=q +SAML_CALLBACK_URL=q +APPLE_AUTH_URL=q +APPLE_AUTH_CLIENT_ID=a +APPLE_AUTH_TEAM_ID=q +APPLE_AUTH_KEY_ID=q +APPLE_AUTH_CALLBACK_URL=q +FACEBOOK_AUTH_URL=q +FACEBOOK_AUTH_CLIENT_ID=a +FACEBOOK_AUTH_CLIENT_SECRET=q +FACEBOOK_AUTH_TOKEN_URL=q +FACEBOOK_AUTH_CALLBACK_URL=q +REDIS_PORT=a +REDIS_HOST=a +REDIS_URL= +REDIS_PASSWORD=a +REDIS_DATABASE=a +FORGOT_PASSWORD_LINK_EXPIRY=30 +REQUEST_SIGNUP_LINK_EXPIRY=30 + +# AZURE AD +#boolean values will be 0 or 1 + +AZURE_AUTH_ENABLED=0 +AZURE_IDENTITY_METADATA=https://login.microsoftonline.com/common/.well-known/openid-configuration +AZURE_AUTH_CLIENT_ID=a +AZURE_AUTH_REDIRECT_URL=url +AZURE_AUTH_CLIENT_SECRET=client_secret +AZURE_AUTH_ALLOW_HTTP_REDIRECT=1 +AZURE_AUTH_COOKIE_INSTEAD_SESSION=1 +AZURE_AUTH_PASS_REQ_CALLBACK=0 +AZURE_AUTH_VALIDATE_ISSUER=0 +AZURE_AUTH_B2C_TENANT=0 +AZURE_AUTH_CLOCK_SKEW=300 +AZURE_AUTH_LOG_LEVEL= +AZURE_AUTH_LOG_PII=1 +AZURE_AUTH_NONCE_TIME=3600 +AZURE_AUTH_NONCE_COUNT=10 +AZURE_AUTH_ISSUER= + +# key is 32 bit + +AZURE_AUTH_COOKIE_KEY= + +#iv is 12 bit + +AZURE_AUTH_COOKIE_IV= + +MAX_JWT_KEYS=2 diff --git a/sandbox/oauth-example/.env.example b/sandbox/oauth-example/.env.example new file mode 100644 index 0000000000..fc4607c679 --- /dev/null +++ b/sandbox/oauth-example/.env.example @@ -0,0 +1,87 @@ +NODE_ENV= +LOG_LEVEL= +DB_HOST= +DB_PORT= +DB_USER= +DB_PASSWORD= +DB_DATABASE= +DB_SCHEMA= +REDIS_HOST= +REDIS_PORT= +REDIS_URL= +REDIS_PASSWORD= +REDIS_DATABASE= +# PRIVATE_DECRYPTION_KEY= +JWT_SECRET= +JWT_ISSUER= +# USER_TEMP_PASSWORD= +GOOGLE_AUTH_URL= +GOOGLE_AUTH_CLIENT_ID= +GOOGLE_AUTH_CLIENT_SECRET= +GOOGLE_AUTH_TOKEN_URL= +GOOGLE_AUTH_CALLBACK_URL= +# GOOGLE_TOKEN_INFO_URL= +# SAML_URL= +# SAML_CLIENT_ID= +# SAML_CLIENT_SECRET= +# SAML_TOKEN_URL= +# SAML_CALLBACK_URL= +# INSTAGRAM_AUTH_URL= +# INSTAGRAM_AUTH_CLIENT_ID= +# INSTAGRAM_AUTH_CLIENT_SECRET= +# INSTAGRAM_AUTH_TOKEN_URL= +# INSTAGRAM_AUTH_CALLBACK_URL= +# APPLE_AUTH_URL= +# APPLE_AUTH_CLIENT_ID= +# APPLE_AUTH_TEAM_ID= +# APPLE_AUTH_KEY_ID= +# APPLE_AUTH_CALLBACK_URL= +# FACEBOOK_AUTH_URL= +# FACEBOOK_AUTH_CLIENT_ID= +# FACEBOOK_AUTH_CLIENT_SECRET= +# FACEBOOK_AUTH_TOKEN_URL= +# FACEBOOK_AUTH_CALLBACK_URL= +# FORGOT_PASSWORD_LINK_EXPIRY= +# KEYCLOAK_HOST= +# KEYCLOAK_REALM= +# KEYCLOAK_CLIENT_ID= +# KEYCLOAK_CLIENT_SECRET= +# KEYCLOAK_CALLBACK_URL= + +# # AZURE AD +# #boolean values will be 0 or 1 + +# AZURE_AUTH_ENABLED= +# AZURE_IDENTITY_METADATA= +# AZURE_AUTH_CLIENT_ID= +# AZURE_AUTH_REDIRECT_URL= +# AZURE_AUTH_CLIENT_SECRET= +# AZURE_AUTH_ALLOW_HTTP_REDIRECT= +# AZURE_AUTH_COOKIE_INSTEAD_SESSION= +# AZURE_AUTH_PASS_REQ_CALLBACK= +# AZURE_AUTH_VALIDATE_ISSUER= +# AZURE_AUTH_B2C_TENANT= +# AZURE_AUTH_CLOCK_SKEW= +# AZURE_AUTH_LOG_LEVEL= +# AZURE_AUTH_LOG_PII= +# AZURE_AUTH_NONCE_TIME= +# AZURE_AUTH_NONCE_COUNT= +# AZURE_AUTH_ISSUER= + +# # key is 32 bit + +# AZURE_AUTH_COOKIE_KEY= + +# #iv is 12 bit + +# AZURE_AUTH_COOKIE_IV= + + +# AUTH0_DOMAIN= +# AUTH0_CLIENT_ID= +# AUTH0_CLIENT_SECRET= +# AUTH0_CALLBACK_URL= + +# MAX_JWT_KEYS= +# JWT_PRIVATE_KEY_PASSPHRASE= +# API_BASE_URL= diff --git a/sandbox/oauth-example/.eslintignore b/sandbox/oauth-example/.eslintignore index 51b39e3ec0..e300953d30 100644 --- a/sandbox/oauth-example/.eslintignore +++ b/sandbox/oauth-example/.eslintignore @@ -2,4 +2,5 @@ node_modules/ dist/ coverage/ migrations/ -.eslintrc.js +migration.js +.eslintrc.js \ No newline at end of file diff --git a/sandbox/oauth-example/.eslintrc.js b/sandbox/oauth-example/.eslintrc.js index 978b9dcca2..aef13fa415 100644 --- a/sandbox/oauth-example/.eslintrc.js +++ b/sandbox/oauth-example/.eslintrc.js @@ -1,3 +1,13 @@ module.exports = { extends: '@loopback/eslint-config', + rules: { + 'no-extra-boolean-cast': 'off', + '@typescript-eslint/interface-name-prefix': 'off', + 'no-prototype-builtins': 'off', + 'no-await-in-loop': 'error', + }, + parserOptions: { + project: './tsconfig.json', + tsconfigRootDir: __dirname, + }, }; diff --git a/sandbox/oauth-example/.mocharc.json b/sandbox/oauth-example/.mocharc.json index 7b523c3163..a141fff9d2 100644 --- a/sandbox/oauth-example/.mocharc.json +++ b/sandbox/oauth-example/.mocharc.json @@ -1,5 +1,6 @@ { "exit": true, "recursive": true, - "require": "source-map-support/register" + "require": "source-map-support/register", + "reporter": "mochawesome" } diff --git a/sandbox/oauth-example/.nycrc b/sandbox/oauth-example/.nycrc new file mode 100644 index 0000000000..115a4e397c --- /dev/null +++ b/sandbox/oauth-example/.nycrc @@ -0,0 +1,5 @@ +{ + "extends": "@istanbuljs/nyc-config-typescript", + "all": true, + "reporter": ["html", "text-summary"] +} \ No newline at end of file diff --git a/sandbox/oauth-example/.prettierignore b/sandbox/oauth-example/.prettierignore index c6911da9e1..3f725726d0 100644 --- a/sandbox/oauth-example/.prettierignore +++ b/sandbox/oauth-example/.prettierignore @@ -1,2 +1,5 @@ dist *.json +coverage +mochawesome-report +node_modules/ \ No newline at end of file diff --git a/sandbox/oauth-example/.vscode/settings.json b/sandbox/oauth-example/.vscode/settings.json index 07313667ec..fa3c3aea67 100644 --- a/sandbox/oauth-example/.vscode/settings.json +++ b/sandbox/oauth-example/.vscode/settings.json @@ -5,8 +5,8 @@ "editor.trimAutoWhitespace": true, "editor.formatOnSave": true, "editor.codeActionsOnSave": { - "source.organizeImports": true, - "source.fixAll.eslint": true + "source.organizeImports": "explicit", + "source.fixAll.eslint": "explicit" }, "files.exclude": { @@ -15,7 +15,7 @@ "**/.hg": true, "**/.svn": true, "**/CVS": true, - "dist": true, + "dist": true }, "files.insertFinalNewline": true, "files.trimTrailingWhitespace": true, @@ -25,8 +25,5 @@ "typescript.preferences.quoteStyle": "single", "eslint.run": "onSave", "eslint.nodePath": "./node_modules", - "eslint.validate": [ - "javascript", - "typescript" - ] + "eslint.validate": ["javascript", "typescript"] } diff --git a/sandbox/oauth-example/.yo-rc.json b/sandbox/oauth-example/.yo-rc.json index a464128411..d4a996bdbb 100644 --- a/sandbox/oauth-example/.yo-rc.json +++ b/sandbox/oauth-example/.yo-rc.json @@ -1,6 +1,6 @@ { - "@loopback/cli": { + "@sourceloop/cli": { "packageManager": "npm", - "version": "4.1.0" + "version": "5.2.4" } } diff --git a/sandbox/oauth-example/CHANGELOG.md b/sandbox/oauth-example/CHANGELOG.md deleted file mode 100644 index 92dc1b2c86..0000000000 --- a/sandbox/oauth-example/CHANGELOG.md +++ /dev/null @@ -1,492 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -## 0.5.13 (2025-01-07) - -* chore(deps): version update (#2227) ([6d6b00e](https://github.com/sourcefuse/loopback4-microservice-catalog/commit/6d6b00e)), closes [#2227](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/2227) - - - - - -## 0.5.12 (2024-12-20) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.5.11 (2024-12-05) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.5.10 (2024-11-22) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.5.9 (2024-10-22) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.5.8 (2024-10-16) - -* chore(ci-cd): resolve sonar issues (#2179) ([12ec556](https://github.com/sourcefuse/loopback4-microservice-catalog/commit/12ec556)), closes [#2179](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/2179) [#2177](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/2177) [#2177](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/2177) -* chore(ci-cd): resolve sonar issues (#2180) ([19c969b](https://github.com/sourcefuse/loopback4-microservice-catalog/commit/19c969b)), closes [#2180](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/2180) [#2177](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/2177) - - - - - -## 0.5.7 (2024-09-30) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.5.6 (2024-09-30) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.5.5 (2024-09-26) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.5.4 (2024-08-05) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.5.3 (2024-06-11) - -* chore: publish release ([89d1599](https://github.com/sourcefuse/loopback4-microservice-catalog/commit/89d1599)) -* chore(deps): version update in sandbox (#2109) ([615d7f5](https://github.com/sourcefuse/loopback4-microservice-catalog/commit/615d7f5)), closes [#2109](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/2109) [#2104](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/2104) [#2104](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/2104) -* chore(deps): version bump commit (#2111) ([c87bc75](https://github.com/sourcefuse/loopback4-microservice-catalog/commit/c87bc75)), closes [#2111](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/2111) [#00](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/00) -* fix(all-services): revert to pr 2072 (#2106) ([502812f](https://github.com/sourcefuse/loopback4-microservice-catalog/commit/502812f)), closes [#2106](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/2106) [#0](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/0) [#0](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/0) - - - - - -## 0.5.2 (2024-06-10) - -* fix(all-services): revert to pr 2072 (#2106) ([502812f](https://github.com/sourcefuse/loopback4-microservice-catalog/commit/502812f)), closes [#2106](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/2106) [#0](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/0) [#0](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/0) - - - - - -## 0.5.1 (2024-06-04) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.5.0 (2024-05-20) - -* feat(all-services): Follow solid for repositories in all services (#2072) ([82c934b](https://github.com/sourcefuse/loopback4-microservice-catalog/commit/82c934b)), closes [#2072](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/2072) [#2037](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/2037) - - - - - -## 0.4.4 (2024-05-07) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.4.3 (2024-04-05) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.4.2 (2024-04-02) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.4.1 (2024-03-26) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.4.0 (2024-03-20) - -* feat(authentication-service): added SAML example (#1912) ([72002ac](https://github.com/sourcefuse/loopback4-microservice-catalog/commit/72002ac)), closes [#1912](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1912) [#1663](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1663) [#1663](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1663) - - -### BREAKING CHANGE - -* - - - - -## 0.3.12 (2024-03-12) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.3.11 (2024-03-06) - -* fix(all-services): fix sonar issues in all services (#2018) ([33dfa77](https://github.com/sourcefuse/loopback4-microservice-catalog/commit/33dfa77)), closes [#2018](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/2018) [#2013](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/2013) -* fix(all-services): fix the pending sonar issues in all services (#2025) ([b2f6dc3](https://github.com/sourcefuse/loopback4-microservice-catalog/commit/b2f6dc3)), closes [#2025](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/2025) [#2013](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/2013) -* chore(deps): update versions in sandbox and fix vulnerabilities (#1941) ([5e37add](https://github.com/sourcefuse/loopback4-microservice-catalog/commit/5e37add)), closes [#1941](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1941) [#1934](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1934) - - - - - -## 0.3.10 (2024-02-02) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.3.9 (2024-02-01) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.3.8 (2024-01-23) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.3.7 (2024-01-19) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.3.6 (2024-01-09) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.3.5 (2024-01-01) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.3.4 (2024-01-01) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.3.3 (2023-12-22) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.3.2 (2023-12-07) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.3.1 (2023-12-07) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.3.0 (2023-11-09) - -* feat(chore): migrate to use npm workspaces (#1684) ([72d8f6e](https://github.com/sourcefuse/loopback4-microservice-catalog/commit/72d8f6e)), closes [#1684](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1684) [#1673](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1673) [#1673](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1673) [#1673](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1673) [#1673](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1673) [#1673](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1673) [#1673](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1673) [#1673](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1673) [#1673](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1673) [#1673](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1673) - - -### BREAKING CHANGE - -* lerna bootstrap command will not be supported -* lerna bootstrap command will not be supported -* lerna bootstrap command will not be supported -* lerna bootstrap will not be supported -* lerna bootstrap will not be supported - - - - -## 0.2.25 (2023-10-19) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.2.24 (2023-10-05) - -* refactor(all-services): remove redundant `posttest` script (#1677) ([4b252cf](https://github.com/sourcefuse/loopback4-microservice-catalog/commit/4b252cf)), closes [#1677](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1677) [#1657](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1657) - - - - - -## 0.2.23 (2023-09-01) - -* refactor(all-services): fix sonar code smells (#1602) ([51f1cc3](https://github.com/sourcefuse/loopback4-microservice-catalog/commit/51f1cc3)), closes [#1602](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1602) - - - - - -## 0.2.22 (2023-08-10) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.2.21 (2023-08-09) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.2.20 (2023-07-28) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.2.19 (2023-07-18) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.2.18 (2023-07-11) - -* chore(deps): combine dependabot updates (#1474) ([c333a9c](https://github.com/sourcefuse/loopback4-microservice-catalog/commit/c333a9c)), closes [#1474](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1474) -* chore(deps): combine snyk updates (#1480) ([ef93ac6](https://github.com/sourcefuse/loopback4-microservice-catalog/commit/ef93ac6)), closes [#1480](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1480) -* chore(deps): package lock upgrade (#1519) ([5aaddbf](https://github.com/sourcefuse/loopback4-microservice-catalog/commit/5aaddbf)), closes [#1519](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1519) - - - - - -## 0.2.17 (2023-06-19) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.2.16 (2023-06-10) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.2.15 (2023-06-08) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.2.14 (2023-06-08) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.2.13 (2023-06-07) - -* refactor(all-services): remove empty and unnecessary folder (#1423) ([15c8235](https://github.com/sourcefuse/loopback4-microservice-catalog/commit/15c8235)), closes [#1423](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1423) - - - - - -## 0.2.12 (2023-05-11) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.2.11 (2023-05-03) - -* chore(all-services): update license and copyright headers (#1405) ([7493640](https://github.com/sourcefuse/loopback4-microservice-catalog/commit/7493640)), closes [#1405](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1405) - - - - - -## 0.2.10 (2023-04-27) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.2.9 (2023-04-10) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.2.8 (2023-03-15) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.2.7 (2023-03-06) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.2.6 (2023-02-01) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.2.5 (2023-01-31) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.2.4 (2023-01-20) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.2.3 (2023-01-17) - -* fix(authentication-service): fix sql syntax in migrations. (#1205) ([2a1298b](https://github.com/sourcefuse/loopback4-microservice-catalog/commit/2a1298b)), closes [#1205](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1205) [#1204](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1204) [#1204](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1204) - - - - - -## 0.2.2 (2023-01-12) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.2.1 (2022-12-07) - -**Note:** Version bump only for package @sourceloop/oauth-example-api - - - - - -## 0.2.0 (2022-11-25) - -* feat(authentication-service): feat(authentication-service): change parent class AuthClient (#1081) ([537cc75](https://github.com/sourcefuse/loopback4-microservice-catalog/commit/537cc75)), closes [#1081](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1081) - - - - - -## 0.1.0 (2022-10-17) - -* feat(sandbox): add oAuth-example with ui (#1008) ([2c990dc](https://github.com/sourcefuse/loopback4-microservice-catalog/commit/2c990dc)), closes [#1008](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/1008) [#993](https://github.com/sourcefuse/loopback4-microservice-catalog/issues/993) diff --git a/sandbox/oauth-example/Dockerfile b/sandbox/oauth-example/Dockerfile index 320047513d..17580fe640 100644 --- a/sandbox/oauth-example/Dockerfile +++ b/sandbox/oauth-example/Dockerfile @@ -1,5 +1,23 @@ # Check out https://hub.docker.com/_/node to select a new base image -FROM node:lts-slim +ARG nodeVer=18-alpine + +# select a base image to build from +FROM node:$nodeVer AS BASE + +# Take the build variables for image base +ARG SERVICE_NAME +ARG FROM_FOLDER +# This command is used to install some dependencies in the Docker image. +# Nessasary for running node-prune and npm install +RUN apk update && apk add --no-cache --virtual .gyp \ + python3 \ + make \ + g++ \ + bash \ + curl + +# This is used to download and install the `node-prune` tool in the Docker image. +RUN curl -sfL https://gobinaries.com/tj/node-prune | bash -s -- -b /usr/local/bin # Set to a non-root built-in user `node` USER node @@ -7,6 +25,7 @@ USER node # Create app directory (with user `node`) RUN mkdir -p /home/node/app +# Set the working directory to `/home/node/app` WORKDIR /home/node/app # Install app dependencies @@ -14,15 +33,56 @@ WORKDIR /home/node/app # where available (npm@5+) COPY --chown=node package*.json ./ -RUN npm ci +# The following two commands is used to copy the `packages`,`service` directory from the local file system to the Docker image. +# The `--chown=node` flag ensures that the ownership of the copied files/directories is set to the `node` user. +# This is important because the subsequent commands in the Dockerfile are executed with the `node` user, +# and it needs the appropriate permissions to access and modify the copied files/directories. +COPY --chown=node packages ./packages -# Bundle app source code -COPY --chown=node . . +COPY --chown=node $FROM_FOLDER/$SERVICE_NAME ./$FROM_FOLDER/$SERVICE_NAME +# Installing all dependencies +RUN npm install + +# Building the app +# set the Working Directory to the service +WORKDIR /home/node/app/$FROM_FOLDER/$SERVICE_NAME +# Run Build Command RUN npm run build +# Run node-prune +RUN npm prune --production +RUN /usr/local/bin/node-prune + +# Start fresh for a smaller image size +FROM node:$nodeVer + +# Take the build variables for image stage +ARG SERVICE_NAME +ARG FROM_FOLDER + +RUN mkdir -p /home/node/app + +USER node + +WORKDIR /home/node/app + + +# These `COPY` commands are used to copy files and directories from the `BASE` +# stage of the Docker image to the current stage. +COPY --from=BASE --chown=node /home/node/app/node_modules ./node_modules +COPY --from=BASE --chown=node /home/node/app/package.json ./ +COPY --from=BASE --chown=node /home/node/app/package-lock.json ./ +COPY --from=BASE --chown=node /home/node/app/packages ./packages +COPY --from=BASE --chown=node /home/node/app/$FROM_FOLDER/$SERVICE_NAME ./$FROM_FOLDER/$SERVICE_NAME + +# Set the working directory to `/home/node/app/services/auth-service` +WORKDIR /home/node/app/$FROM_FOLDER/$SERVICE_NAME + + # Bind to all network interfaces so that it can be mapped to the host OS ENV HOST=0.0.0.0 PORT=3000 EXPOSE ${PORT} -CMD [ "node", "." ] + +CMD [ "node", "." ] \ No newline at end of file diff --git a/sandbox/oauth-example/README.md b/sandbox/oauth-example/README.md index 8bb67b6509..80e4d61385 100644 --- a/sandbox/oauth-example/README.md +++ b/sandbox/oauth-example/README.md @@ -1,4 +1,4 @@ -# auth-service +# auth This application is generated using [LoopBack 4 CLI](https://loopback.io/doc/en/lb4/Command-line-interface.html) with the [initial project layout](https://loopback.io/doc/en/lb4/Loopback-application-layout.html). diff --git a/sandbox/oauth-example/database.json b/sandbox/oauth-example/database.json deleted file mode 100644 index cf1880315e..0000000000 --- a/sandbox/oauth-example/database.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "defaultEnv": "local", - "local": { - "driver": "pg", - "host": { - "ENV": "DB_HOST" - }, - "port": { - "ENV": "DB_PORT" - }, - "user": { - "ENV": "DB_USER" - }, - "password": { - "ENV": "DB_PASSWORD" - }, - "database": { - "ENV": "DB_DATABASE" - } - } - } \ No newline at end of file diff --git a/sandbox/oauth-example/migrations/20210421113036-init.js b/sandbox/oauth-example/migrations/20210318100600-init.js similarity index 77% rename from sandbox/oauth-example/migrations/20210421113036-init.js rename to sandbox/oauth-example/migrations/20210318100600-init.js index 4faf7411cb..f7aa1b04c5 100644 --- a/sandbox/oauth-example/migrations/20210421113036-init.js +++ b/sandbox/oauth-example/migrations/20210318100600-init.js @@ -5,16 +5,8 @@ var type; var seed; var fs = require('fs'); var path = require('path'); -var Promise; - -function handleFile(filePath, resolve, reject) { - fs.readFile(filePath, {encoding: 'utf-8'}, function (err, data) { - if (err) return reject(err); - console.log('received data: ' + data); - resolve(data); - }); -} +var Promise; /** * We receive the dbmigrate dependency from dbmigrate initially. @@ -28,23 +20,32 @@ exports.setup = function (options, seedLink) { }; exports.up = function (db) { - var filePath = path.join(__dirname, 'sqls', '20210421113036-init-up.sql'); + var filePath = path.join(__dirname, 'sqls', '20210318100600-init-up.sql'); return new Promise(function (resolve, reject) { - handleFile(filePath, resolve, reject); + receiveData(resolve, reject, filePath); }).then(function (data) { return db.runSql(data); }); }; exports.down = function (db) { - var filePath = path.join(__dirname, 'sqls', '20210421113036-init-down.sql'); + var filePath = path.join(__dirname, 'sqls', '20210318100600-init-down.sql'); return new Promise(function (resolve, reject) { - handleFile(filePath, resolve, reject); + receiveData(resolve, reject, filePath); }).then(function (data) { return db.runSql(data); }); }; +function receiveData(resolve, reject, filePath) { + fs.readFile(filePath, {encoding: 'utf-8'}, function (err, data) { + if (err) return reject(err); + console.log('received data: ' + data); + + resolve(data); + }); +} + exports._meta = { version: 1, }; diff --git a/sandbox/oauth-example/migrations/20221123082900-updated-init.js b/sandbox/oauth-example/migrations/20221110095658-updated-init.js similarity index 93% rename from sandbox/oauth-example/migrations/20221123082900-updated-init.js rename to sandbox/oauth-example/migrations/20221110095658-updated-init.js index 7509afe9ab..250582cb55 100644 --- a/sandbox/oauth-example/migrations/20221123082900-updated-init.js +++ b/sandbox/oauth-example/migrations/20221110095658-updated-init.js @@ -22,7 +22,7 @@ exports.up = function (db) { var filePath = path.join( __dirname, 'sqls', - '20221123082900-updated-init-up.sql', + '20221110095658-updated-init-up.sql', ); return new Promise(function (resolve, reject) { fs.readFile(filePath, {encoding: 'utf-8'}, function (err, data) { @@ -40,7 +40,7 @@ exports.down = function (db) { var filePath = path.join( __dirname, 'sqls', - '20221123082900-updated-init-down.sql', + '20221110095658-updated-init-down.sql', ); return new Promise(function (resolve, reject) { fs.readFile(filePath, {encoding: 'utf-8'}, function (err, data) { diff --git a/sandbox/oauth-example/migrations/20230323132703-client-type-column.js b/sandbox/oauth-example/migrations/20230323132703-client-type-column.js new file mode 100644 index 0000000000..2608f6e0f0 --- /dev/null +++ b/sandbox/oauth-example/migrations/20230323132703-client-type-column.js @@ -0,0 +1,59 @@ +'use strict'; + +var dbm; +var type; +var seed; +var fs = require('fs'); +var path = require('path'); +var Promise; + +/** + * We receive the dbmigrate dependency from dbmigrate initially. + * This enables us to not have to rely on NODE_PATH. + */ +exports.setup = function (options, seedLink) { + dbm = options.dbmigrate; + type = dbm.dataType; + seed = seedLink; + Promise = options.Promise; +}; + +exports.up = function (db) { + var filePath = path.join( + __dirname, + 'sqls', + '20230323132703-client-type-column-up.sql', + ); + return new Promise(function (resolve, reject) { + fs.readFile(filePath, {encoding: 'utf-8'}, function (err, data) { + if (err) return reject(err); + console.log('received data: ' + data); + + resolve(data); + }); + }).then(function (data) { + return db.runSql(data); + }); +}; + +exports.down = function (db) { + var filePath = path.join( + __dirname, + 'sqls', + '20230323132703-client-type-column-down.sql', + ); + return new Promise(function (resolve, reject) { + fs.readFile(filePath, {encoding: 'utf-8'}, function (err, data) { + if (err) return reject(err); + console.log('received data: ' + data); + + resolve(data); + }); + }).then(function (data) { + return db.runSql(data); + }); +}; + +exports._meta = { + version: 1, +}; diff --git a/sandbox/oauth-example/migrations/20210421113146-seed.js b/sandbox/oauth-example/migrations/20230524115047-login-activity.js similarity index 55% rename from sandbox/oauth-example/migrations/20210421113146-seed.js rename to sandbox/oauth-example/migrations/20230524115047-login-activity.js index 629a05737b..fc6fbcb7c3 100644 --- a/sandbox/oauth-example/migrations/20210421113146-seed.js +++ b/sandbox/oauth-example/migrations/20230524115047-login-activity.js @@ -7,14 +7,6 @@ var fs = require('fs'); var path = require('path'); var Promise; -function handleFile(filePath, resolve, reject) { - fs.readFile(filePath, {encoding: 'utf-8'}, function (err, data) { - if (err) return reject(err); - console.log('received data: ' + data); - - resolve(data); - }); -} /** * We receive the dbmigrate dependency from dbmigrate initially. * This enables us to not have to rely on NODE_PATH. @@ -27,18 +19,36 @@ exports.setup = function (options, seedLink) { }; exports.up = function (db) { - var filePath = path.join(__dirname, 'sqls', '20210421113146-seed-up.sql'); + var filePath = path.join( + __dirname, + 'sqls', + '20230524115047-login-activity-up.sql', + ); return new Promise(function (resolve, reject) { - handleFile(filePath, resolve, reject); + fs.readFile(filePath, {encoding: 'utf-8'}, function (err, data) { + if (err) return reject(err); + console.log('received data: ' + data); + + resolve(data); + }); }).then(function (data) { return db.runSql(data); }); }; exports.down = function (db) { - var filePath = path.join(__dirname, 'sqls', '20210421113146-seed-down.sql'); + var filePath = path.join( + __dirname, + 'sqls', + '20230524115047-login-activity-down.sql', + ); return new Promise(function (resolve, reject) { - handleFile(filePath, resolve, reject); + fs.readFile(filePath, {encoding: 'utf-8'}, function (err, data) { + if (err) return reject(err); + console.log('received data: ' + data); + + resolve(data); + }); }).then(function (data) { return db.runSql(data); }); diff --git a/sandbox/oauth-example/migrations/20240116123737-sync-with-user-tenant.js b/sandbox/oauth-example/migrations/20240116123737-sync-with-user-tenant.js new file mode 100644 index 0000000000..5481f600c7 --- /dev/null +++ b/sandbox/oauth-example/migrations/20240116123737-sync-with-user-tenant.js @@ -0,0 +1,59 @@ +'use strict'; + +var dbm; +var type; +var seed; +var fs = require('fs'); +var path = require('path'); +var Promise; + +/** + * We receive the dbmigrate dependency from dbmigrate initially. + * This enables us to not have to rely on NODE_PATH. + */ +exports.setup = function (options, seedLink) { + dbm = options.dbmigrate; + type = dbm.dataType; + seed = seedLink; + Promise = options.Promise; +}; + +exports.up = function (db) { + var filePath = path.join( + __dirname, + 'sqls', + '20240116123737-sync-with-user-tenant-up.sql', + ); + return new Promise(function (resolve, reject) { + fs.readFile(filePath, {encoding: 'utf-8'}, function (err, data) { + if (err) return reject(err); + console.log('received data: ' + data); + + resolve(data); + }); + }).then(function (data) { + return db.runSql(data); + }); +}; + +exports.down = function (db) { + var filePath = path.join( + __dirname, + 'sqls', + '20240116123737-sync-with-user-tenant-down.sql', + ); + return new Promise(function (resolve, reject) { + fs.readFile(filePath, {encoding: 'utf-8'}, function (err, data) { + if (err) return reject(err); + console.log('received data: ' + data); + + resolve(data); + }); + }).then(function (data) { + return db.runSql(data); + }); +}; + +exports._meta = { + version: 1, +}; diff --git a/sandbox/oauth-example/migrations/20241105074844-add-jwt-keys-schema.js b/sandbox/oauth-example/migrations/20241105074844-add-jwt-keys-schema.js new file mode 100644 index 0000000000..b1ebc0e60c --- /dev/null +++ b/sandbox/oauth-example/migrations/20241105074844-add-jwt-keys-schema.js @@ -0,0 +1,59 @@ +'use strict'; + +var dbm; +var type; +var seed; +var fs = require('fs'); +var path = require('path'); +var Promise; + +/** + * We receive the dbmigrate dependency from dbmigrate initially. + * This enables us to not have to rely on NODE_PATH. + */ +exports.setup = function (options, seedLink) { + dbm = options.dbmigrate; + type = dbm.dataType; + seed = seedLink; + Promise = options.Promise; +}; + +exports.up = function (db) { + var filePath = path.join( + __dirname, + 'sqls', + '20241105074844-add-jwt-keys-schema-up.sql', + ); + return new Promise(function (resolve, reject) { + fs.readFile(filePath, {encoding: 'utf-8'}, function (err, data) { + if (err) return reject(err); + console.log('received data: ' + data); + + resolve(data); + }); + }).then(function (data) { + return db.runSql(data); + }); +}; + +exports.down = function (db) { + var filePath = path.join( + __dirname, + 'sqls', + '20241105074844-add-jwt-keys-schema-down.sql', + ); + return new Promise(function (resolve, reject) { + fs.readFile(filePath, {encoding: 'utf-8'}, function (err, data) { + if (err) return reject(err); + console.log('received data: ' + data); + + resolve(data); + }); + }).then(function (data) { + return db.runSql(data); + }); +}; + +exports._meta = { + version: 1, +}; diff --git a/sandbox/oauth-example/migrations/database.json b/sandbox/oauth-example/migrations/database.json index 414a359e8c..b50814c9ad 100644 --- a/sandbox/oauth-example/migrations/database.json +++ b/sandbox/oauth-example/migrations/database.json @@ -1,22 +1,22 @@ { - "defaultEnv": "master", - "master": { - "driver": "pg", - "host": { - "ENV": "DB_HOST" - }, - "port": { - "ENV": "DB_PORT" - }, - "user": { - "ENV": "DB_USER" - }, - "password": { - "ENV": "DB_PASSWORD" - }, - "database": { - "ENV": "DB_DATABASE" - } + "defaultEnv": "master", + "master": { + "driver": "pg", + "host": { + "ENV": "DB_HOST" }, - "sql-file": true + "port": { + "ENV": "DB_PORT" + }, + "user": { + "ENV": "DB_USER" + }, + "password": { + "ENV": "DB_PASSWORD" + }, + "database": { + "ENV": "DB_DATABASE" + } + }, + "sql-file": true } \ No newline at end of file diff --git a/sandbox/oauth-example/migrations/sqls/20210421113036-init-down.sql b/sandbox/oauth-example/migrations/sqls/20210318100600-init-down.sql similarity index 100% rename from sandbox/oauth-example/migrations/sqls/20210421113036-init-down.sql rename to sandbox/oauth-example/migrations/sqls/20210318100600-init-down.sql diff --git a/sandbox/oauth-example/migrations/sqls/20210421113036-init-up.sql b/sandbox/oauth-example/migrations/sqls/20210318100600-init-up.sql similarity index 59% rename from sandbox/oauth-example/migrations/sqls/20210421113036-init-up.sql rename to sandbox/oauth-example/migrations/sqls/20210318100600-init-up.sql index f860c3fc70..5d87000632 100644 --- a/sandbox/oauth-example/migrations/sqls/20210421113036-init-up.sql +++ b/sandbox/oauth-example/migrations/sqls/20210318100600-init-up.sql @@ -1,18 +1,17 @@ -DROP SCHEMA IF EXISTS main CASCADE; -CREATE SCHEMA main; +CREATE SCHEMA IF NOT EXISTS main; SET search_path TO main,public; GRANT ALL ON SCHEMA main TO public; -CREATE TABLE main.auth_clients ( +CREATE TABLE IF NOT EXISTS main.auth_clients ( id integer NOT NULL GENERATED BY DEFAULT AS IDENTITY, client_id varchar(50) NOT NULL , - client_secret varchar(50) NOT NULL , + client_secret text NOT NULL , redirect_url varchar(200) , access_token_expiration integer DEFAULT 900 NOT NULL , refresh_token_expiration integer DEFAULT 86400 NOT NULL , auth_code_expiration integer DEFAULT 180 NOT NULL , - secret varchar(50) NOT NULL , + secret text NOT NULL , created_on timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL , modified_on timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL , deleted bool DEFAULT false NOT NULL , @@ -21,22 +20,7 @@ CREATE TABLE main.auth_clients ( CONSTRAINT pk_auth_clients_id PRIMARY KEY ( id ) ); -CREATE TABLE main.groups ( - id uuid DEFAULT md5(random()::text || clock_timestamp()::text)::uuid NOT NULL , - name varchar(200) NOT NULL , - description varchar(500) , - photo_url varchar(500) , - created_by uuid , - modified_by uuid , - created_on timestamptz DEFAULT CURRENT_TIMESTAMP , - modified_on timestamptz DEFAULT CURRENT_TIMESTAMP , - deleted bool DEFAULT false , - deleted_on timestamptz , - deleted_by uuid , - CONSTRAINT pk_groups_id PRIMARY KEY ( id ) - ); - -CREATE TABLE main.roles ( + CREATE TABLE IF NOT EXISTS main.roles ( id uuid DEFAULT md5(random()::text || clock_timestamp()::text)::uuid NOT NULL , name varchar(100) NOT NULL , created_on timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL , @@ -50,8 +34,8 @@ CREATE TABLE main.roles ( deleted_on timestamptz , CONSTRAINT pk_roles_id PRIMARY KEY ( id ) ); - -CREATE TABLE main.tenants ( + + CREATE TABLE IF NOT EXISTS main.tenants ( id uuid DEFAULT md5(random()::text || clock_timestamp()::text)::uuid NOT NULL , name varchar(100) NOT NULL , status integer DEFAULT 0 NOT NULL , @@ -72,7 +56,25 @@ CREATE TABLE main.tenants ( CONSTRAINT idx_tenants UNIQUE ( "key" ) ); -CREATE TABLE main.users ( + CREATE TABLE IF NOT EXISTS main.tenant_configs ( + id uuid DEFAULT md5(random()::text || clock_timestamp()::text)::uuid NOT NULL , + config_key varchar(100) NOT NULL , + config_value jsonb NOT NULL , + created_on timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL , + modified_on timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL , + created_by integer , + modified_by integer , + deleted bool DEFAULT false NOT NULL , + tenant_id uuid NOT NULL , + deleted_by uuid , + deleted_on timestamptz , + CONSTRAINT pk_tenant_configs_id PRIMARY KEY ( id ), + CONSTRAINT fk_tenant_configs_tenants FOREIGN KEY ( tenant_id ) REFERENCES main.tenants( id ) + + ); + + +CREATE TABLE IF NOT EXISTS main.users ( id uuid DEFAULT md5(random()::text || clock_timestamp()::text)::uuid NOT NULL , first_name varchar(50) NOT NULL , middle_name varchar(50) , @@ -86,40 +88,16 @@ CREATE TABLE main.users ( modified_by uuid , deleted bool DEFAULT false NOT NULL , last_login timestamptz , - photo_url varchar(250) , auth_client_ids integer[] , gender char(1) , dob date , - designation varchar(50) , default_tenant_id uuid , deleted_by uuid , deleted_on timestamptz , CONSTRAINT pk_users_id PRIMARY KEY ( id ) ); -CREATE TABLE main.todo ( - id uuid DEFAULT md5(random()::text || clock_timestamp()::text)::uuid NOT NULL , - title varchar(50) NOT NULL , - description varchar(150) NOT NULL , - items _text - ); - -CREATE TABLE main.tenant_configs ( - id uuid DEFAULT md5(random()::text || clock_timestamp()::text)::uuid NOT NULL , - config_key varchar(100) NOT NULL , - config_value jsonb NOT NULL , - created_on timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL , - modified_on timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL , - created_by integer , - modified_by integer , - deleted bool DEFAULT false NOT NULL , - tenant_id uuid NOT NULL , - deleted_by uuid , - deleted_on timestamptz , - CONSTRAINT pk_tenant_configs_id PRIMARY KEY ( id ) - ); - -CREATE TABLE main.user_credentials ( +CREATE TABLE IF NOT EXISTS main.user_credentials ( id uuid DEFAULT md5(random()::text || clock_timestamp()::text)::uuid NOT NULL , user_id uuid NOT NULL , auth_provider varchar(50) DEFAULT 'internal'::character varying NOT NULL , @@ -132,10 +110,12 @@ CREATE TABLE main.user_credentials ( deleted_on timestamptz , deleted_by uuid , CONSTRAINT pk_user_credentials_id PRIMARY KEY ( id ), - CONSTRAINT idx_user_credentials_user_id UNIQUE ( user_id ) + CONSTRAINT idx_user_credentials_user_id UNIQUE ( user_id ), + CONSTRAINT idx_user_credentials_uniq UNIQUE ( auth_provider, auth_id, auth_token, "password" ), + CONSTRAINT fk_user_credentials_users FOREIGN KEY ( user_id ) REFERENCES main.users( id ) ); - -CREATE TABLE main.user_tenants ( + + CREATE TABLE IF NOT EXISTS main.user_tenants ( id uuid DEFAULT md5(random()::text || clock_timestamp()::text)::uuid NOT NULL , user_id uuid NOT NULL , tenant_id uuid NOT NULL , @@ -147,38 +127,48 @@ CREATE TABLE main.user_tenants ( locale varchar(5) , deleted_by uuid , deleted_on timestamptz , - CONSTRAINT pk_user_tenants_id PRIMARY KEY ( id ) + CONSTRAINT pk_user_tenants_id PRIMARY KEY ( id ), + CONSTRAINT fk_user_tenants_users FOREIGN KEY ( user_id ) REFERENCES main.users( id ) , + CONSTRAINT fk_user_tenants_tenants FOREIGN KEY ( tenant_id ) REFERENCES main.tenants( id ) , + CONSTRAINT fk_user_tenants_roles FOREIGN KEY ( role_id ) REFERENCES main.roles( id ) ); -CREATE TABLE main.user_groups ( + CREATE TABLE IF NOT EXISTS main.user_permissions ( id uuid DEFAULT md5(random()::text || clock_timestamp()::text)::uuid NOT NULL , user_tenant_id uuid NOT NULL , - group_id uuid NOT NULL , - created_on timestamptz DEFAULT CURRENT_TIMESTAMP , - modified_on timestamptz DEFAULT CURRENT_TIMESTAMP , - deleted bool DEFAULT false , + permission text NOT NULL , + allowed bool NOT NULL , + created_on timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL , + modified_on timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL , created_by uuid , modified_by uuid , + deleted bool DEFAULT false NOT NULL , deleted_on timestamptz , deleted_by uuid , - CONSTRAINT pk_user_groups_id PRIMARY KEY ( id ) + CONSTRAINT pk_user_permissions_id PRIMARY KEY ( id ), + CONSTRAINT fk_user_permissions FOREIGN KEY ( user_tenant_id ) REFERENCES main.user_tenants( id ) + ); -CREATE TABLE main.user_permissions ( - id uuid DEFAULT md5(random()::text || clock_timestamp()::text)::uuid NOT NULL , - user_tenant_id uuid NOT NULL , - permission varchar(50) NOT NULL , - allowed bool NOT NULL , +CREATE TABLE IF NOT EXISTS main.user_resources ( + deleted bool DEFAULT false NOT NULL , + deleted_on timestamptz , + deleted_by uuid , created_on timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL , modified_on timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL , created_by uuid , modified_by uuid , - deleted bool DEFAULT false NOT NULL , - deleted_on timestamptz , - deleted_by uuid , - CONSTRAINT pk_user_permissions_id PRIMARY KEY ( id ) + id uuid DEFAULT md5(random()::text || clock_timestamp()::text)::uuid NOT NULL , + user_tenant_id uuid , + resource_name varchar(50) , + resource_value varchar(100) , + allowed bool DEFAULT true NOT NULL , + CONSTRAINT user_resources_pkey PRIMARY KEY ( id ), + CONSTRAINT fk_user_resources FOREIGN KEY ( user_tenant_id ) REFERENCES main.user_tenants( id ) + ); + CREATE OR REPLACE FUNCTION main.moddatetime() RETURNS trigger LANGUAGE plpgsql @@ -190,35 +180,18 @@ END; $function$ ; -CREATE TRIGGER mdt_auth_clients BEFORE UPDATE ON main.auth_clients FOR EACH ROW EXECUTE PROCEDURE main.moddatetime('modified_on'); - -CREATE TRIGGER mdt_roles BEFORE UPDATE ON main.roles FOR EACH ROW EXECUTE PROCEDURE main.moddatetime('modified_on'); - -CREATE TRIGGER mdt_tenant_configs BEFORE UPDATE ON main.tenant_configs FOR EACH ROW EXECUTE PROCEDURE main.moddatetime('modified_on'); - -CREATE TRIGGER mdt_tenants BEFORE UPDATE ON main.tenants FOR EACH ROW EXECUTE PROCEDURE main.moddatetime('modified_on'); - -CREATE TRIGGER mdt_user_credentials BEFORE UPDATE ON main.user_credentials FOR EACH ROW EXECUTE PROCEDURE main.moddatetime('modified_on'); - -CREATE TRIGGER mdt_user_permissions BEFORE UPDATE ON main.user_permissions FOR EACH ROW EXECUTE PROCEDURE main.moddatetime('modified_on'); - -CREATE TRIGGER mdt_user_tenants BEFORE UPDATE ON main.user_tenants FOR EACH ROW EXECUTE PROCEDURE main.moddatetime('modified_on'); - -CREATE TRIGGER mdt_users BEFORE UPDATE ON main.users FOR EACH ROW EXECUTE PROCEDURE main.moddatetime('modified_on'); - -ALTER TABLE main.tenant_configs ADD CONSTRAINT fk_tenant_configs_tenants FOREIGN KEY ( tenant_id ) REFERENCES main.tenants( id ); - -ALTER TABLE main.user_credentials ADD CONSTRAINT fk_user_credentials_users FOREIGN KEY ( user_id ) REFERENCES main.users( id ); +CREATE OR REPLACE TRIGGER mdt_auth_clients BEFORE UPDATE ON main.auth_clients FOR EACH ROW EXECUTE PROCEDURE main.moddatetime('modified_on'); -ALTER TABLE main.user_groups ADD CONSTRAINT fk_user_tenant FOREIGN KEY ( user_tenant_id ) REFERENCES main.user_tenants( id ); +CREATE OR REPLACE TRIGGER mdt_roles BEFORE UPDATE ON main.roles FOR EACH ROW EXECUTE PROCEDURE main.moddatetime('modified_on'); -ALTER TABLE main.user_groups ADD CONSTRAINT fk_groups FOREIGN KEY ( group_id ) REFERENCES main.groups( id ); +CREATE OR REPLACE TRIGGER mdt_tenant_configs BEFORE UPDATE ON main.tenant_configs FOR EACH ROW EXECUTE PROCEDURE main.moddatetime('modified_on'); -ALTER TABLE main.user_permissions ADD CONSTRAINT fk_user_permissions FOREIGN KEY ( user_tenant_id ) REFERENCES main.user_tenants( id ); +CREATE OR REPLACE TRIGGER mdt_tenants BEFORE UPDATE ON main.tenants FOR EACH ROW EXECUTE PROCEDURE main.moddatetime('modified_on'); -ALTER TABLE main.user_tenants ADD CONSTRAINT fk_user_tenants_users FOREIGN KEY ( user_id ) REFERENCES main.users( id ); +CREATE OR REPLACE TRIGGER mdt_user_credentials BEFORE UPDATE ON main.user_credentials FOR EACH ROW EXECUTE PROCEDURE main.moddatetime('modified_on'); -ALTER TABLE main.user_tenants ADD CONSTRAINT fk_user_tenants_tenants FOREIGN KEY ( tenant_id ) REFERENCES main.tenants( id ); +CREATE OR REPLACE TRIGGER mdt_user_permissions BEFORE UPDATE ON main.user_permissions FOR EACH ROW EXECUTE PROCEDURE main.moddatetime('modified_on'); -ALTER TABLE main.user_tenants ADD CONSTRAINT fk_user_tenants_roles FOREIGN KEY ( role_id ) REFERENCES main.roles( id ); +CREATE OR REPLACE TRIGGER mdt_user_tenants BEFORE UPDATE ON main.user_tenants FOR EACH ROW EXECUTE PROCEDURE main.moddatetime('modified_on'); +CREATE OR REPLACE TRIGGER mdt_users BEFORE UPDATE ON main.users FOR EACH ROW EXECUTE PROCEDURE main.moddatetime('modified_on'); \ No newline at end of file diff --git a/sandbox/oauth-example/migrations/sqls/20210421113146-seed-down.sql b/sandbox/oauth-example/migrations/sqls/20210421113146-seed-down.sql deleted file mode 100644 index 0e68c90bbe..0000000000 --- a/sandbox/oauth-example/migrations/sqls/20210421113146-seed-down.sql +++ /dev/null @@ -1,8 +0,0 @@ -SET search_path TO main,public; - -DELETE FROM user_credentials; -DELETE FROM user_tenants; -DELETE FROM users; -DELETE FROM tenants; -DELETE FROM roles; -DELETE FROM auth_clients; diff --git a/sandbox/oauth-example/migrations/sqls/20210421113146-seed-up.sql b/sandbox/oauth-example/migrations/sqls/20210421113146-seed-up.sql deleted file mode 100644 index b4113d3e8b..0000000000 --- a/sandbox/oauth-example/migrations/sqls/20210421113146-seed-up.sql +++ /dev/null @@ -1,51 +0,0 @@ -SET search_path -TO main,public; - -/* Inserting auth clients */ -insert into auth_clients - (client_id, client_secret, secret) -values - ('test_client_id', 'test_client_secret', 'secret'); - --- Inserting roles -insert into roles - (name, permissions, role_type) -values - ('Admin', '{CreateTodo,UpdateTodo,DeleteTodo}', 0); - -insert into roles - (name, permissions, role_type) -values - ('Others', '{}', 1); - --- Inserting tenants -insert into tenants - (name, status, key) -values - ('Master', 1, 'master'); - --- Inserting Admin User -insert into users - (first_name, last_name, username, email, default_tenant_id) -select 'Admin', 'User', 'admin@example.com', 'admin@example.com', id -from tenants -where key = 'master'; - -insert into user_tenants - (user_id, tenant_id, status, role_id) -select (select id - from users - where username = 'admin@example.com'), (select id - from tenants - where key = 'master'), 1, id -from roles -where role_type = 0; - -insert into user_credentials - (user_id, auth_provider, password) -select id, 'internal', '$2a$10$TOLMGK43MjbibS8Jap2RXeHl3.4sJcR3eFbms2dBll2LTMggSK9hG' -from users -where username = 'admin@example.com'; -update users set auth_client_ids = ARRAY[(select id from auth_clients where client_id = 'test_client_id')::integer]; - - diff --git a/sandbox/oauth-example/migrations/sqls/20220607063927-secret-key-column-up.sql b/sandbox/oauth-example/migrations/sqls/20220607063927-secret-key-column-up.sql index d66c203490..570a7ab069 100644 --- a/sandbox/oauth-example/migrations/sqls/20220607063927-secret-key-column-up.sql +++ b/sandbox/oauth-example/migrations/sqls/20220607063927-secret-key-column-up.sql @@ -1,2 +1,2 @@ ALTER TABLE main.user_credentials -ADD secret_key varchar(100); +ADD IF NOT EXISTS secret_key text; diff --git a/sandbox/oauth-example/migrations/sqls/20221123082900-updated-init-down.sql b/sandbox/oauth-example/migrations/sqls/20221110095658-updated-init-down.sql similarity index 100% rename from sandbox/oauth-example/migrations/sqls/20221123082900-updated-init-down.sql rename to sandbox/oauth-example/migrations/sqls/20221110095658-updated-init-down.sql diff --git a/sandbox/oauth-example/migrations/sqls/20221110095658-updated-init-up.sql b/sandbox/oauth-example/migrations/sqls/20221110095658-updated-init-up.sql new file mode 100644 index 0000000000..22c5208465 --- /dev/null +++ b/sandbox/oauth-example/migrations/sqls/20221110095658-updated-init-up.sql @@ -0,0 +1,11 @@ +ALTER TABLE main.auth_clients +ADD IF NOT EXISTS created_by varchar(100), +ADD IF NOT EXISTS modified_by varchar(100); + +ALTER TABLE main.user_credentials +ADD IF NOT EXISTS created_by varchar(100), +ADD IF NOT EXISTS modified_by varchar(100); + +ALTER TABLE main.user_tenants +ADD IF NOT EXISTS created_by varchar(100), +ADD IF NOT EXISTS modified_by varchar(100); \ No newline at end of file diff --git a/sandbox/oauth-example/migrations/sqls/20221123082900-updated-init-up.sql b/sandbox/oauth-example/migrations/sqls/20221123082900-updated-init-up.sql deleted file mode 100644 index 7a3da56364..0000000000 --- a/sandbox/oauth-example/migrations/sqls/20221123082900-updated-init-up.sql +++ /dev/null @@ -1,11 +0,0 @@ -ALTER TABLE main.auth_clients -ADD created_by varchar(100), -ADD modified_by varchar(100); - -ALTER TABLE main.user_credentials -ADD created_by varchar(100), -ADD modified_by varchar(100); - -ALTER TABLE main.user_tenants -ADD created_by varchar(100), -ADD modified_by varchar(100); \ No newline at end of file diff --git a/sandbox/oauth-example/migrations/sqls/20230323132703-client-type-column-down.sql b/sandbox/oauth-example/migrations/sqls/20230323132703-client-type-column-down.sql new file mode 100644 index 0000000000..752870fd2f --- /dev/null +++ b/sandbox/oauth-example/migrations/sqls/20230323132703-client-type-column-down.sql @@ -0,0 +1,3 @@ +/* Replace with your SQL commands */ + +ALTER TABLE main.auth_clients DROP COLUMN client_type; diff --git a/sandbox/oauth-example/migrations/sqls/20230323132703-client-type-column-up.sql b/sandbox/oauth-example/migrations/sqls/20230323132703-client-type-column-up.sql new file mode 100644 index 0000000000..c9c45ba9b1 --- /dev/null +++ b/sandbox/oauth-example/migrations/sqls/20230323132703-client-type-column-up.sql @@ -0,0 +1,4 @@ +/* Replace with your SQL commands */ + +ALTER TABLE main.auth_clients +ADD IF NOT EXISTS client_type varchar(100) DEFAULT 'public'; diff --git a/sandbox/oauth-example/migrations/sqls/20230524115047-login-activity-down.sql b/sandbox/oauth-example/migrations/sqls/20230524115047-login-activity-down.sql new file mode 100644 index 0000000000..fa7e8d10a1 --- /dev/null +++ b/sandbox/oauth-example/migrations/sqls/20230524115047-login-activity-down.sql @@ -0,0 +1,6 @@ +/* Replace with your SQL commands */ + +SET search_path TO main,public; +GRANT ALL ON SCHEMA main TO public; + +drop table main.login_activity; \ No newline at end of file diff --git a/sandbox/oauth-example/migrations/sqls/20230524115047-login-activity-up.sql b/sandbox/oauth-example/migrations/sqls/20230524115047-login-activity-up.sql new file mode 100644 index 0000000000..075c744eac --- /dev/null +++ b/sandbox/oauth-example/migrations/sqls/20230524115047-login-activity-up.sql @@ -0,0 +1,16 @@ +/* Replace with your SQL commands */ + +SET search_path TO main,public; +GRANT ALL ON SCHEMA main TO public; + +CREATE TABLE main.login_activity ( + id uuid DEFAULT md5(random()::text || clock_timestamp()::text)::uuid NOT NULL , + actor text NOT NULL, + tenant_id text, + login_time timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL, + token_payload text NOT NULL, + login_type text NOT NULL, + device_info text, + ip_address text, + CONSTRAINT pk_login_activity PRIMARY KEY ( id ) +); \ No newline at end of file diff --git a/sandbox/oauth-example/migrations/sqls/20240116123737-sync-with-user-tenant-down.sql b/sandbox/oauth-example/migrations/sqls/20240116123737-sync-with-user-tenant-down.sql new file mode 100644 index 0000000000..44f074ea89 --- /dev/null +++ b/sandbox/oauth-example/migrations/sqls/20240116123737-sync-with-user-tenant-down.sql @@ -0,0 +1 @@ +/* Replace with your SQL commands */ \ No newline at end of file diff --git a/sandbox/oauth-example/migrations/sqls/20240116123737-sync-with-user-tenant-up.sql b/sandbox/oauth-example/migrations/sqls/20240116123737-sync-with-user-tenant-up.sql new file mode 100644 index 0000000000..98849b18b4 --- /dev/null +++ b/sandbox/oauth-example/migrations/sqls/20240116123737-sync-with-user-tenant-up.sql @@ -0,0 +1,15 @@ +/* Replace with your SQL commands */ + +ALTER TABLE main.roles +ADD IF NOT EXISTS tenant_id uuid NOT NULL, +ADD IF NOT EXISTS allowed_clients text[], +ADD IF NOT EXISTS description varchar(500); + +ALTER TABLE main.tenants +ADD IF NOT EXISTS website varchar(100); + +ALTER TABLE main.users +ADD IF NOT EXISTS photo_url text, +ADD IF NOT EXISTS designation varchar(50); + + diff --git a/sandbox/oauth-example/migrations/sqls/20241105074844-add-jwt-keys-schema-down.sql b/sandbox/oauth-example/migrations/sqls/20241105074844-add-jwt-keys-schema-down.sql new file mode 100644 index 0000000000..fbcccb9d0c --- /dev/null +++ b/sandbox/oauth-example/migrations/sqls/20241105074844-add-jwt-keys-schema-down.sql @@ -0,0 +1 @@ +DROP TABLE main.jwt_keys; diff --git a/sandbox/oauth-example/migrations/sqls/20241105074844-add-jwt-keys-schema-up.sql b/sandbox/oauth-example/migrations/sqls/20241105074844-add-jwt-keys-schema-up.sql new file mode 100644 index 0000000000..f644e574f5 --- /dev/null +++ b/sandbox/oauth-example/migrations/sqls/20241105074844-add-jwt-keys-schema-up.sql @@ -0,0 +1,7 @@ +CREATE TABLE main.jwt_keys ( + id SERIAL PRIMARY KEY, + key_id VARCHAR(100) UNIQUE NOT NULL, + public_key TEXT NOT NULL, -- Public key in PEM format + private_key TEXT NOT NULL, -- Private key in PEM format + created_on TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); diff --git a/sandbox/oauth-example/package.json b/sandbox/oauth-example/package.json index df15b94e0e..babe5094d8 100644 --- a/sandbox/oauth-example/package.json +++ b/sandbox/oauth-example/package.json @@ -1,16 +1,16 @@ { - "name": "@sourceloop/oauth-example-api", - "version": "0.5.13", - "description": "oauth example.", + "name": "o-auth", + "version": "0.0.1", + "description": "auth", "keywords": [ - "loopback-application", + "loopback-microservice", "loopback" ], "private": true, "main": "dist/index.js", "types": "dist/index.d.ts", "engines": { - "node": "18 || 20" + "node": ">=18" }, "scripts": { "build": "lb-tsc", @@ -23,28 +23,34 @@ "eslint": "eslint --report-unused-disable-directives .", "eslint:fix": "npm run eslint -- --fix", "pretest": "npm run rebuild", - "test": "echo 'No Tests'", - "posttest": "npm run lint", - "test:dev": "lb-mocha --allow-console-logs dist/__tests__/**/*.js && npm run posttest", - "docker:build": "docker build -t auth-service .", - "docker:run": "docker run -p 3000:3000 -d auth-service", + "test": "lb-mocha --allow-console-logs \"dist/__tests__\"", + "test:dev": "lb-mocha --allow-console-logs dist/__tests__/**/*.js", + "docker:build": "DOCKER_BUILDKIT=1 sudo docker build --build-arg NR_ENABLED=$NR_ENABLED_VALUE --build-arg FROM_FOLDER=services --build-arg SERVICE_NAME=authentication-service -t $IMAGE_REPO_NAME/$npm_package_name:$npm_package_version ../../. -f ./Dockerfile", + "docker:run": "docker run -p 3000:3000 -d auth", + "symlink-resolver": "symlink-resolver", + "resolve-links": "npm run symlink-resolver build ./node_modules/@local", "premigrate": "npm run build", "migrate": "node ./dist/migrate", "preopenapi-spec": "npm run build", "openapi-spec": "node ./dist/openapi-spec", - "prestart": "npm run rebuild", - "start": "node -r source-map-support/register .", + "prestart": "npm run clean && npm run openapi-spec", + "start": "node -r ./dist/opentelemetry-registry.js -r source-map-support/register .", + "dev": "nodemon --watch src -e ts --exec \"npm run start\"", "clean": "lb-clean dist *.tsbuildinfo .eslintcache", "rebuild": "npm run clean && npm run build", - "db:migrate": "./node_modules/db-migrate/bin/db-migrate up --config './migrations/database.json'", - "db:migrate:down": "./node_modules/db-migrate/bin/db-migrate down --config './migrations/database.json'", - "db:migrate:reset": "./node_modules/db-migrate/bin/db-migrate reset --config './migrations/database.json'" + "docker:push": " docker push $IMAGE_REPO_NAME/$npm_package_name:$npm_package_version", + "docker:build:dev": "DOCKER_BUILDKIT=1 sudo docker build --build-arg NR_ENABLED=$NR_ENABLED_VALUE --build-arg FROM_FOLDER=services --build-arg SERVICE_NAME=authentication-service -t $IMAGE_REPO_NAME/$npm_package_name:$npm_package_version ../../. -f ./Dockerfile", + "docker:push:dev": " docker push $IMAGE_REPO_NAME/$npm_package_name:$npm_package_version", + "coverage": "nyc npm run test", + "db:migrate": "../../node_modules/db-migrate/bin/db-migrate up --config './migrations/database.json'", + "db:migrate:down": "../../node_modules/db-migrate/bin/db-migrate down --config './migrations/database.json'", + "db:migrate:reset": "../../node_modules/db-migrate/bin/db-migrate reset --config './migrations/database.json'" }, "repository": { "type": "git", "url": "" }, - "author": "Ankur ", + "author": "Tyagi-Sunny", "license": "MIT", "files": [ "README.md", @@ -59,23 +65,40 @@ "@loopback/rest": "^14.0.9", "@loopback/rest-explorer": "^7.0.9", "@loopback/service-proxy": "^7.0.9", - "@sourceloop/authentication-service": "^20.0.2", - "bcrypt": "^5.0.1", + "@loopback/openapi-v3": "^10.0.9", + "@loopback/context": "^7.0.9", + "@sourceloop/core": "^15.0.2", + "loopback4-authentication": "^12.1.1", + "loopback4-authorization": "^7.0.3", + "swagger-stats": "^0.99.5", + "@opentelemetry/exporter-jaeger": "^1.15.0", + "@opentelemetry/sdk-trace-node": "^1.15.0", + "@opentelemetry/plugin-dns": "^0.15.0", + "@opentelemetry/plugin-http": "^0.18.2", + "@opentelemetry/plugin-https": "^0.18.2", + "@opentelemetry/plugin-pg": "^0.15.0", + "@opentelemetry/plugin-pg-pool": "^0.15.0", + "@opentelemetry/sdk-trace-base": "^1.15.0", "db-migrate": "^1.0.0-beta.21", "db-migrate-pg": "^1.3.0", + "symlink-resolver": "0.2.1", "dotenv": "^16.4.5", "dotenv-extended": "^2.9.0", "loopback-connector-postgresql": "^7.1.8", - "tslib": "^2.6.2" + "loopback-connector-kv-redis": "^4.0.0", + "tslib": "^2.6.2", + "@sourceloop/authentication-service": "^20.0.2" }, "devDependencies": { "@loopback/build": "^11.0.8", - "@loopback/eslint-config": "^15.0.4", + "source-map-support": "^0.5.21", + "nodemon": "^2.0.21", + "nyc": "^15.1.0", + "@istanbuljs/nyc-config-typescript": "^1.0.2", "@loopback/testlab": "^7.0.8", - "@types/bcrypt": "^5.0.0", "@types/node": "^20.12.7", + "@loopback/eslint-config": "^15.0.4", "eslint": "^8.57.0", - "source-map-support": "^0.5.21", "typescript": "^5.4.5" } -} +} \ No newline at end of file diff --git a/sandbox/oauth-example/public/index.html b/sandbox/oauth-example/public/index.html index 3e9f36f599..6ddfab83e2 100644 --- a/sandbox/oauth-example/public/index.html +++ b/sandbox/oauth-example/public/index.html @@ -1,7 +1,7 @@ - oauth example + auth @@ -80,18 +80,22 @@
-

auth-service

+

auth

Version 1.0.0

-

OpenAPI spec: /openapi.json

-

API Explorer: /explorer

+

+ OpenAPI spec: + /openapi.json +

+

API Explorer: /explorer

+

Monitoring: /monitor

diff --git a/sandbox/oauth-example/src/__tests__/acceptance/home-page.acceptance.ts b/sandbox/oauth-example/src/__tests__/acceptance/home-page.acceptance.ts index 1ffdf417f0..e56145a78c 100644 --- a/sandbox/oauth-example/src/__tests__/acceptance/home-page.acceptance.ts +++ b/sandbox/oauth-example/src/__tests__/acceptance/home-page.acceptance.ts @@ -1,13 +1,9 @@ -// Copyright (c) 2023 Sourcefuse Technologies -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT import {Client} from '@loopback/testlab'; -import {AuthServiceApplication} from '../..'; +import {AuthApplication} from '../..'; import {setupApplication} from './test-helper'; describe('HomePage', () => { - let app: AuthServiceApplication; + let app: AuthApplication; let client: Client; before('setupApplication', async () => { diff --git a/sandbox/oauth-example/src/__tests__/acceptance/ping.controller.acceptance.ts b/sandbox/oauth-example/src/__tests__/acceptance/ping.controller.acceptance.ts index 9f31316af9..5353fb9b88 100644 --- a/sandbox/oauth-example/src/__tests__/acceptance/ping.controller.acceptance.ts +++ b/sandbox/oauth-example/src/__tests__/acceptance/ping.controller.acceptance.ts @@ -1,13 +1,9 @@ -// Copyright (c) 2023 Sourcefuse Technologies -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT import {Client, expect} from '@loopback/testlab'; -import {AuthServiceApplication} from '../..'; +import {AuthApplication} from '../..'; import {setupApplication} from './test-helper'; describe('PingController', () => { - let app: AuthServiceApplication; + let app: AuthApplication; let client: Client; before('setupApplication', async () => { diff --git a/sandbox/oauth-example/src/__tests__/acceptance/test-helper.ts b/sandbox/oauth-example/src/__tests__/acceptance/test-helper.ts index be0b911a79..5583ab5b3a 100644 --- a/sandbox/oauth-example/src/__tests__/acceptance/test-helper.ts +++ b/sandbox/oauth-example/src/__tests__/acceptance/test-helper.ts @@ -1,13 +1,9 @@ -// Copyright (c) 2023 Sourcefuse Technologies -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT +import {AuthApplication} from '../..'; import { - Client, createRestAppClient, givenHttpServerConfig, + Client, } from '@loopback/testlab'; -import {AuthServiceApplication} from '../..'; export async function setupApplication(): Promise { const restConfig = givenHttpServerConfig({ @@ -17,11 +13,22 @@ export async function setupApplication(): Promise { // host: process.env.HOST, // port: +process.env.PORT, }); + setUpEnv(); - const app = new AuthServiceApplication({ + const app = new AuthApplication({ rest: restConfig, }); + app.bind('datasources.config.db').to({ + name: 'db', + connector: 'memory', + }); + + app.bind(`datasources.config.${process.env.REDIS_NAME}`).to({ + name: process.env.REDIS_NAME, + connector: 'kv-memory', + }); + await app.boot(); await app.start(); @@ -30,7 +37,15 @@ export async function setupApplication(): Promise { return {app, client}; } +function setUpEnv() { + process.env.NODE_ENV = 'test'; + process.env.ENABLE_TRACING = '0'; + process.env.ENABLE_OBF = '0'; + process.env.REDIS_NAME = 'redis'; + process.env.HOST = 'localhost'; +} + export interface AppWithClient { - app: AuthServiceApplication; + app: AuthApplication; client: Client; } diff --git a/sandbox/oauth-example/src/application.ts b/sandbox/oauth-example/src/application.ts index 7b716c523e..9dda77f8f4 100644 --- a/sandbox/oauth-example/src/application.ts +++ b/sandbox/oauth-example/src/application.ts @@ -1,82 +1,116 @@ -// Copyright (c) 2023 Sourcefuse Technologies -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT import {BootMixin} from '@loopback/boot'; import {ApplicationConfig} from '@loopback/core'; -import {RepositoryMixin} from '@loopback/repository'; -import {RestApplication} from '@loopback/rest'; import { RestExplorerBindings, RestExplorerComponent, } from '@loopback/rest-explorer'; -import {ServiceMixin} from '@loopback/service-proxy'; +import * as dotenv from 'dotenv'; +import * as dotenvExt from 'dotenv-extended'; +import {AuthenticationComponent, Strategies} from 'loopback4-authentication'; +import { + AuthorizationBindings, + AuthorizationComponent, +} from 'loopback4-authorization'; +import { + ServiceSequence, + SFCoreBindings, + BearerVerifierBindings, + BearerVerifierComponent, + BearerVerifierConfig, + BearerVerifierType, + SECURITY_SCHEME_SPEC, +} from '@sourceloop/core'; import { AuthenticationServiceComponent, + AuthServiceBindings, SignUpBindings, } from '@sourceloop/authentication-service'; -import {Strategies} from 'loopback4-authentication'; -import {SamlStrategyFactoryProvider} from 'loopback4-authentication/SAML'; -import {GoogleAuthStrategyFactoryProvider} from 'loopback4-authentication/passport-google-oauth2'; -import {LocalPasswordStrategyFactoryProvider} from 'loopback4-authentication/passport-local'; +import {RepositoryMixin} from '@loopback/repository'; +import {RestApplication} from '@loopback/rest'; +import {ServiceMixin} from '@loopback/service-proxy'; import path from 'path'; -import { - AzureAdSignupProvider, - FacebookOauth2SignupProvider, - GoogleOauth2SignupProvider, - SamlVerifyProvider, -} from './providers'; -import {SamlSignupProvider} from './providers/saml-signup.provider'; -import {MySequence} from './sequence'; +import * as openapi from './openapi.json'; +import {GoogleOauth2SignupProvider} from './providers'; +import {GoogleAuthStrategyFactoryProvider} from 'loopback4-authentication/passport-google-oauth2'; export {ApplicationConfig}; -export class AuthServiceApplication extends BootMixin( +export class AuthApplication extends BootMixin( ServiceMixin(RepositoryMixin(RestApplication)), ) { constructor(options: ApplicationConfig = {}) { + const port = 3000; + dotenv.config(); + dotenvExt.load({ + schema: '.env.example', + errorOnMissing: process.env.NODE_ENV !== 'test', + includeProcessEnv: true, + }); + options.rest = options.rest ?? {}; + options.rest.basePath = process.env.BASE_PATH ?? ''; + options.rest.port = +(process.env.PORT ?? port); + options.rest.host = process.env.HOST; + options.rest.openApiSpec = { + endpointMapping: { + [`${options.rest.basePath}/openapi.json`]: { + version: '3.0.0', + format: 'json', + }, + }, + }; + super(options); - // Set up the custom sequence - this.sequence(MySequence); + // To check if monitoring is enabled from env or not + const enableObf = !!+(process.env.ENABLE_OBF ?? 0); + // To check if authorization is enabled for swagger stats or not + const authentication = + process.env.SWAGGER_USER && process.env.SWAGGER_PASSWORD ? true : false; + const obj = { + enableObf, + obfPath: process.env.OBF_PATH ?? '/obf', + openapiSpec: openapi, + authentication: authentication, + swaggerUsername: process.env.SWAGGER_USER, + swaggerPassword: process.env.SWAGGER_PASSWORD, + }; + this.bind(SFCoreBindings.config).to(obj); - // Set up default home page - this.static('/', path.join(__dirname, '../public')); + // Set up the custom sequence + this.sequence(ServiceSequence); - // Customize @loopback/rest-explorer configuration here - this.configure(RestExplorerBindings.COMPONENT).to({ - path: '/explorer', + // Add authentication component + this.component(AuthenticationComponent); + this.bind(AuthServiceBindings.Config).to({ + useSymmetricEncryption: true, }); - this.component(RestExplorerComponent); - this.component(AuthenticationServiceComponent); - - this.bind(Strategies.Passport.LOCAL_STRATEGY_FACTORY.key).toProvider( - LocalPasswordStrategyFactoryProvider, - ); - this.bind(SignUpBindings.GOOGLE_SIGN_UP_PROVIDER).toProvider( GoogleOauth2SignupProvider, ); - this.bind( - Strategies.Passport.GOOGLE_OAUTH2_STRATEGY_FACTORY.key, - ).toProvider(GoogleAuthStrategyFactoryProvider); - this.bind(SignUpBindings.FACEBOOK_SIGN_UP_PROVIDER).toProvider( - FacebookOauth2SignupProvider, - ); - this.bind(SignUpBindings.AZURE_AD_SIGN_UP_PROVIDER).toProvider( - AzureAdSignupProvider, + this.bind(Strategies.Passport.GOOGLE_OAUTH2_STRATEGY_FACTORY).toProvider( + GoogleAuthStrategyFactoryProvider, ); + // Add bearer verifier component + this.bind(BearerVerifierBindings.Config).to({ + type: BearerVerifierType.service, + } as BearerVerifierConfig); + this.component(BearerVerifierComponent); + // Add authorization component + this.bind(AuthorizationBindings.CONFIG).to({ + allowAlwaysPaths: ['/explorer', '/openapi.json'], + }); + this.component(AuthorizationComponent); - this.bind(SignUpBindings.SAML_SIGN_UP_PROVIDER).toProvider( - SamlSignupProvider, - ); + // Set up default home page + this.static('/', path.join(__dirname, '../public')); - this.bind(Strategies.Passport.SAML_VERIFIER).toProvider(SamlVerifyProvider); + // Customize @loopback/rest-explorer configuration here + this.configure(RestExplorerBindings.COMPONENT).to({ + path: '/explorer', + }); - this.bind(Strategies.Passport.SAML_STRATEGY_FACTORY.key).toProvider( - SamlStrategyFactoryProvider, - ); + this.component(RestExplorerComponent); this.projectRoot = __dirname; // Customize @loopback/boot Booter Conventions here @@ -88,5 +122,18 @@ export class AuthServiceApplication extends BootMixin( nested: true, }, }; + + this.api({ + openapi: '3.0.0', + info: { + title: 'auth', + version: '1.0.0', + }, + paths: {}, + components: { + securitySchemes: SECURITY_SCHEME_SPEC, + }, + servers: [{url: '/'}], + }); } } diff --git a/sandbox/oauth-example/src/controllers/home-page.controller.ts b/sandbox/oauth-example/src/controllers/home-page.controller.ts new file mode 100644 index 0000000000..4e6f52513c --- /dev/null +++ b/sandbox/oauth-example/src/controllers/home-page.controller.ts @@ -0,0 +1,39 @@ +import {get} from '@loopback/openapi-v3'; +import * as fs from 'fs'; +import * as path from 'path'; +import {inject} from '@loopback/context'; +import {RestBindings, Response} from '@loopback/rest'; +import {authorize} from 'loopback4-authorization'; +import {STATUS_CODE} from '@sourceloop/core'; + +export class HomePageController { + private readonly html: string; + constructor( + @inject(RestBindings.Http.RESPONSE) + private readonly response: Response, + ) { + this.html = fs.readFileSync( + path.join(__dirname, '../../public/index.html'), + 'utf-8', + ); + // Replace base path placeholder from env + this.html = this.html.replace( + /\$\{basePath\}/g, + process.env.BASE_PATH ?? '', + ); + } + + @authorize({permissions: ['*']}) + @get('/', { + responses: { + [STATUS_CODE.OK]: { + description: 'Home Page', + content: {'text/html': {schema: {type: 'string'}}}, + }, + }, + }) + homePage() { + this.response.status(STATUS_CODE.OK).contentType('html').send(this.html); + return this.response; + } +} diff --git a/sandbox/oauth-example/src/controllers/index.ts b/sandbox/oauth-example/src/controllers/index.ts index 76abc8e2f1..d20736dff8 100644 --- a/sandbox/oauth-example/src/controllers/index.ts +++ b/sandbox/oauth-example/src/controllers/index.ts @@ -1,5 +1,2 @@ -// Copyright (c) 2023 Sourcefuse Technologies -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT export * from './ping.controller'; +export * from './home-page.controller'; diff --git a/sandbox/oauth-example/src/controllers/ping.controller.ts b/sandbox/oauth-example/src/controllers/ping.controller.ts index 65cf734a32..56b0d46398 100644 --- a/sandbox/oauth-example/src/controllers/ping.controller.ts +++ b/sandbox/oauth-example/src/controllers/ping.controller.ts @@ -1,20 +1,11 @@ -// Copyright (c) 2023 Sourcefuse Technologies -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT import {inject} from '@loopback/core'; -import { - get, - Request, - response, - ResponseObject, - RestBindings, -} from '@loopback/rest'; +import {Request, RestBindings, get, ResponseObject} from '@loopback/rest'; +import {authorize} from 'loopback4-authorization'; +import {STATUS_CODE} from '@sourceloop/core'; /** * OpenAPI response for ping() */ -const statusCode = 200; const PING_RESPONSE: ResponseObject = { description: 'Ping Response', content: { @@ -48,8 +39,12 @@ export class PingController { ) {} // Map to `GET /ping` - @get('/ping') - @response(statusCode, PING_RESPONSE) + @authorize({permissions: ['*']}) + @get('/ping', { + responses: { + [STATUS_CODE.OK]: PING_RESPONSE, + }, + }) ping(): object { // Reply with a greeting, the current time, the url, and request headers return { diff --git a/sandbox/oauth-example/src/datasources/db.datasource.ts b/sandbox/oauth-example/src/datasources/auth.datasource.ts similarity index 54% rename from sandbox/oauth-example/src/datasources/db.datasource.ts rename to sandbox/oauth-example/src/datasources/auth.datasource.ts index b92709075d..3df40c0002 100644 --- a/sandbox/oauth-example/src/datasources/db.datasource.ts +++ b/sandbox/oauth-example/src/datasources/auth.datasource.ts @@ -1,20 +1,20 @@ -// Copyright (c) 2023 Sourcefuse Technologies -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT import {inject, lifeCycleObserver, LifeCycleObserver} from '@loopback/core'; import {juggler} from '@loopback/repository'; import {AuthDbSourceName} from '@sourceloop/authentication-service'; +const DEFAULT_MAX_CONNECTIONS = 25; +const DEFAULT_DB_IDLE_TIMEOUT_MILLIS = 60000; +const DEFAULT_DB_CONNECTION_TIMEOUT_MILLIS = 2000; + const config = { - name: AuthDbSourceName, + name: 'auth', connector: 'postgresql', host: process.env.DB_HOST, port: process.env.DB_PORT, user: process.env.DB_USER, + schema: process.env.DB_SCHEMA, password: process.env.DB_PASSWORD, database: process.env.DB_DATABASE, - schema: process.env.DB_SCHEMA, }; // Observe application's life cycle to disconnect the datasource when @@ -22,17 +22,33 @@ const config = { // gracefully. The `stop()` method is inherited from `juggler.DataSource`. // Learn more at https://loopback.io/doc/en/lb4/Life-cycle.html @lifeCycleObserver('datasource') -export class DbDataSource +export class AuthDataSource extends juggler.DataSource implements LifeCycleObserver { - static readonly dataSourceName = AuthDbSourceName; + static dataSourceName = AuthDbSourceName; + static readonly defaultConfig = config; constructor( - @inject('datasources.config.db', {optional: true}) + @inject('datasources.config.auth', {optional: true}) dsConfig: object = config, ) { + if (!!+(process.env.ENABLE_DB_CONNECTION_POOLING ?? 0)) { + const dbPool = { + max: +(process.env.DB_MAX_CONNECTIONS ?? DEFAULT_MAX_CONNECTIONS), + idleTimeoutMillis: +( + process.env.DB_IDLE_TIMEOUT_MILLIS ?? DEFAULT_DB_IDLE_TIMEOUT_MILLIS + ), + connectionTimeoutMillis: +( + process.env.DB_CONNECTION_TIMEOUT_MILLIS ?? + DEFAULT_DB_CONNECTION_TIMEOUT_MILLIS + ), + }; + + dsConfig = {...dsConfig, ...dbPool}; + } + super(dsConfig); } } diff --git a/sandbox/oauth-example/src/datasources/index.ts b/sandbox/oauth-example/src/datasources/index.ts index 0a6f13b851..d3aaddf849 100644 --- a/sandbox/oauth-example/src/datasources/index.ts +++ b/sandbox/oauth-example/src/datasources/index.ts @@ -1,6 +1,2 @@ -// Copyright (c) 2023 Sourcefuse Technologies -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT -export * from './db.datasource'; +export * from './auth.datasource'; export * from './redis.datasource'; diff --git a/sandbox/oauth-example/src/datasources/redis.datasource.ts b/sandbox/oauth-example/src/datasources/redis.datasource.ts index 9c05cc16c1..de47ed34ff 100644 --- a/sandbox/oauth-example/src/datasources/redis.datasource.ts +++ b/sandbox/oauth-example/src/datasources/redis.datasource.ts @@ -1,19 +1,35 @@ -// Copyright (c) 2023 Sourcefuse Technologies -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT import {inject, lifeCycleObserver, LifeCycleObserver} from '@loopback/core'; -import {juggler} from '@loopback/repository'; +import {AnyObject, juggler} from '@loopback/repository'; +import {readFileSync} from 'fs'; import {AuthCacheSourceName} from '@sourceloop/authentication-service'; const config = { - name: AuthCacheSourceName, + name: process.env.REDIS_NAME, connector: 'kv-redis', - url: '', host: process.env.REDIS_HOST, port: process.env.REDIS_PORT, password: process.env.REDIS_PASSWORD, - database: process.env.REDIS_DATABASE, + db: process.env.REDIS_DATABASE, + url: process.env.REDIS_URL, + tls: + +process.env.REDIS_TLS_ENABLED! || + (process.env.REDIS_TLS_CERT + ? { + ca: readFileSync(process.env.REDIS_TLS_CERT), + } + : undefined), + sentinels: + +process.env.REDIS_HAS_SENTINELS! && process.env.REDIS_SENTINELS + ? JSON.parse(process.env.REDIS_SENTINELS) + : undefined, + sentinelPassword: + +process.env.REDIS_HAS_SENTINELS! && process.env.REDIS_SENTINEL_PASSWORD + ? process.env.REDIS_SENTINEL_PASSWORD + : undefined, + role: + +process.env.REDIS_HAS_SENTINELS! && process.env.REDIS_SENTINEL_ROLE + ? process.env.REDIS_SENTINEL_ROLE + : undefined, }; // Observe application's life cycle to disconnect the datasource when @@ -25,13 +41,25 @@ export class RedisDataSource extends juggler.DataSource implements LifeCycleObserver { - static readonly dataSourceName = AuthCacheSourceName; + static dataSourceName = AuthCacheSourceName; static readonly defaultConfig = config; constructor( - @inject('datasources.config.redis', {optional: true}) - dsConfig: object = config, + @inject(`datasources.config.${process.env.REDIS_NAME}`, {optional: true}) + dsConfig: AnyObject = config, ) { + if ( + +process.env.REDIS_HAS_SENTINELS! && + !!process.env.REDIS_SENTINEL_HOST && + !!process.env.REDIS_SENTINEL_PORT + ) { + dsConfig.sentinels = [ + { + host: process.env.REDIS_SENTINEL_HOST, + port: +process.env.REDIS_SENTINEL_PORT, + }, + ]; + } super(dsConfig); } } diff --git a/sandbox/oauth-example/src/index.ts b/sandbox/oauth-example/src/index.ts index dd03ead610..592aa9d4fa 100644 --- a/sandbox/oauth-example/src/index.ts +++ b/sandbox/oauth-example/src/index.ts @@ -1,16 +1,11 @@ -// Copyright (c) 2023 Sourcefuse Technologies -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT -import * as dotenv from 'dotenv'; -import {ApplicationConfig, AuthServiceApplication} from './application'; +import {ApplicationConfig, AuthApplication} from './application'; + export * from './application'; -dotenv.config(); -const port = 3000; +const PORT = 3000; export async function main(options: ApplicationConfig = {}) { - const app = new AuthServiceApplication(options); + const app = new AuthApplication(options); await app.boot(); await app.start(); @@ -25,7 +20,7 @@ if (require.main === module) { // Run the application const config = { rest: { - port: +(process.env.PORT ?? port), + port: +(process.env.PORT ?? PORT), host: process.env.HOST, // The `gracePeriodForClose` provides a graceful close for http/https // servers with keep-alive clients. The default value is `Infinity` diff --git a/sandbox/oauth-example/src/migrate.ts b/sandbox/oauth-example/src/migrate.ts deleted file mode 100644 index 384c4e0d35..0000000000 --- a/sandbox/oauth-example/src/migrate.ts +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2023 Sourcefuse Technologies -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT -import {AuthServiceApplication} from './application'; - -export async function migrate(args: string[]) { - const existingSchema = args.includes('--rebuild') ? 'drop' : 'alter'; - console.log('Migrating schemas (%s existing schema)', existingSchema); //NOSONAR - - const app = new AuthServiceApplication(); - await app.boot(); - await app.migrateSchema({existingSchema}); - - // Connectors usually keep a pool of opened connections, - // this keeps the process running even after all work is done. - // We need to exit explicitly. - process.exit(0); -} - -migrate(process.argv).catch(err => { - console.error('Cannot migrate database schema', err); //NOSONAR - process.exit(1); -}); diff --git a/sandbox/oauth-example/src/models/README.md b/sandbox/oauth-example/src/models/README.md new file mode 100644 index 0000000000..f5ea972116 --- /dev/null +++ b/sandbox/oauth-example/src/models/README.md @@ -0,0 +1,3 @@ +# Models + +This directory contains code for models provided by this app. diff --git a/sandbox/oauth-example/src/models/index.ts b/sandbox/oauth-example/src/models/index.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/sandbox/oauth-example/src/openapi-spec.ts b/sandbox/oauth-example/src/openapi-spec.ts index 8d0b7b4aae..f5e8141b35 100644 --- a/sandbox/oauth-example/src/openapi-spec.ts +++ b/sandbox/oauth-example/src/openapi-spec.ts @@ -1,29 +1,28 @@ -// Copyright (c) 2023 Sourcefuse Technologies -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT import {ApplicationConfig} from '@loopback/core'; -import {AuthServiceApplication} from './application'; +import {AuthApplication} from './application'; -const port = 3000; -const two = 2; +const ARGV_INDEX = 2; /** * Export the OpenAPI spec from the application */ async function exportOpenApiSpec(): Promise { const config: ApplicationConfig = { rest: { - port: +(process.env.PORT ?? port), + port: +(process.env.PORT ?? 3000), host: process.env.HOST ?? 'localhost', }, }; - const outFile = process.argv[two] ?? ''; - const app = new AuthServiceApplication(config); + const outFile = process.argv[ARGV_INDEX] ?? './src/openapi.json'; + const app = new AuthApplication(config); await app.boot(); await app.exportOpenApiSpec(outFile); } -exportOpenApiSpec().catch(err => { - console.error('Fail to export OpenAPI spec from the application.', err); //NOSONAR - process.exit(1); -}); +exportOpenApiSpec() + .then(() => { + process.exit(0); + }) + .catch(err => { + console.error('Fail to export OpenAPI spec from the application.', err); + process.exit(1); + }); diff --git a/sandbox/oauth-example/src/openapi.json b/sandbox/oauth-example/src/openapi.json new file mode 100644 index 0000000000..2b15663ddf --- /dev/null +++ b/sandbox/oauth-example/src/openapi.json @@ -0,0 +1,3036 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "auth", + "version": "1.0.0", + "description": "auth", + "contact": { + "name": "Tyagi-Sunny", + "email": "sunny.tyagi@sourcefuse.com" + } + }, + "paths": { + "/.well-known/openid-configuration": { + "get": { + "x-controller-name": "IdentityServerController", + "x-operation-name": "getConfig", + "tags": [ + "IdentityServerController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "description": "To get the openid configuration", + "responses": { + "200": { + "description": "OpenId Configuration", + "content": {} + }, + "400": { + "description": "The syntax of the request entity is incorrect." + }, + "401": { + "description": "Invalid Credentials." + }, + "404": { + "description": "The entity requested does not exist." + }, + "422": { + "description": "The syntax of the request entity is incorrect" + } + }, + "operationId": "IdentityServerController.getConfig" + } + }, + "/active-users/{range}": { + "get": { + "x-controller-name": "LoginActivityController", + "x-operation-name": "getActiveUsers", + "tags": [ + "LoginActivityController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "200": { + "description": "LoginActivity model instance", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| ViewLoginActivity |\n", + "parameters": [ + { + "name": "range", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "startDate", + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "endDate", + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "filter", + "in": "query", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + ], + "operationId": "LoginActivityController.getActiveUsers" + } + }, + "/auth/apple-oauth-redirect": { + "get": { + "x-controller-name": "AppleLoginController", + "x-operation-name": "appleCallback", + "tags": [ + "AppleLoginController" + ], + "responses": { + "200": { + "description": "Apple Redirect Token Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + } + }, + "description": "", + "parameters": [ + { + "name": "code", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "state", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "operationId": "AppleLoginController.appleCallback" + } + }, + "/auth/auth0": { + "post": { + "x-controller-name": "Auth0LoginController", + "x-operation-name": "postLoginViaAuth0", + "tags": [ + "Auth0LoginController" + ], + "responses": { + "200": { + "description": "POST Call for auth0 based login", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + } + }, + "description": "", + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/ClientAuthRequest" + } + } + } + }, + "operationId": "Auth0LoginController.postLoginViaAuth0" + }, + "get": { + "x-controller-name": "Auth0LoginController", + "x-operation-name": "loginViaAuth0", + "tags": [ + "Auth0LoginController" + ], + "responses": { + "200": { + "description": "POST Call for auth0 based login", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + } + }, + "description": "", + "deprecated": true, + "parameters": [ + { + "name": "client_id", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "client_secret", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "operationId": "Auth0LoginController.loginViaAuth0" + } + }, + "/auth/auth0-auth-redirect": { + "get": { + "x-controller-name": "Auth0LoginController", + "x-operation-name": "auth0Callback", + "tags": [ + "Auth0LoginController" + ], + "responses": { + "200": { + "description": "Redirect Token Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + } + }, + "description": "", + "parameters": [ + { + "name": "code", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "state", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "operationId": "Auth0LoginController.auth0Callback" + } + }, + "/auth/azure": { + "post": { + "x-controller-name": "AzureLoginController", + "x-operation-name": "postLoginViaAzure", + "tags": [ + "AzureLoginController" + ], + "description": "POST Call for azure based login", + "responses": { + "200": { + "description": "Azure Token Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + } + }, + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/ClientAuthRequest" + } + } + } + }, + "operationId": "AzureLoginController.postLoginViaAzure" + }, + "get": { + "x-controller-name": "AzureLoginController", + "x-operation-name": "getLoginViaAzure", + "tags": [ + "AzureLoginController" + ], + "description": "POST Call for azure based login", + "responses": { + "200": { + "description": "Azure Token Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + } + }, + "deprecated": true, + "parameters": [ + { + "name": "client_id", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "client_secret", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "operationId": "AzureLoginController.getLoginViaAzure" + } + }, + "/auth/azure-oauth-redirect": { + "get": { + "x-controller-name": "AzureLoginController", + "x-operation-name": "azureCallback", + "tags": [ + "AzureLoginController" + ], + "responses": { + "200": { + "description": "Azure Redirect Token Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + } + }, + "description": "", + "parameters": [ + { + "name": "code", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "state", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "session_state", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "operationId": "AzureLoginController.azureCallback" + } + }, + "/auth/change-password": { + "patch": { + "x-controller-name": "LoginController", + "x-operation-name": "resetPassword", + "tags": [ + "LoginController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "200": { + "description": "If User password successfully changed." + } + }, + "description": "", + "parameters": [ + { + "name": "Authorization", + "in": "header", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResetPasswordPartial" + } + } + } + }, + "operationId": "LoginController.resetPassword" + } + }, + "/auth/check-qr-code": { + "get": { + "x-controller-name": "OtpController", + "x-operation-name": "checkQr", + "tags": [ + "OtpController" + ], + "description": "Returns isGenerated:true if secret_key already exist", + "responses": { + "200": { + "description": "secret_key already exists", + "content": {} + }, + "400": { + "description": "The syntax of the request entity is incorrect." + }, + "401": { + "description": "Invalid Credentials." + }, + "404": { + "description": "The entity requested does not exist." + }, + "422": { + "description": "The syntax of the request entity is incorrect" + } + }, + "parameters": [ + { + "name": "code", + "in": "header", + "schema": { + "type": "string" + } + }, + { + "name": "clientId", + "in": "header", + "schema": { + "type": "string" + } + } + ], + "operationId": "OtpController.checkQr" + } + }, + "/auth/cognito": { + "post": { + "x-controller-name": "CognitoLoginController", + "x-operation-name": "postLoginViaCognito", + "tags": [ + "CognitoLoginController" + ], + "responses": { + "200": { + "description": "POST Call for Cognito based login", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + } + }, + "description": "", + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/ClientAuthRequest" + } + } + } + }, + "operationId": "CognitoLoginController.postLoginViaCognito" + }, + "get": { + "x-controller-name": "CognitoLoginController", + "x-operation-name": "loginViaCognito", + "tags": [ + "CognitoLoginController" + ], + "responses": { + "200": { + "description": "Cognito Token Response (Deprecated: Possible security issue if secret is passed via query params, please use the post endpoint)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + } + }, + "description": "", + "deprecated": true, + "parameters": [ + { + "name": "client_id", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "client_secret", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "operationId": "CognitoLoginController.loginViaCognito" + } + }, + "/auth/cognito-auth-redirect": { + "get": { + "x-controller-name": "CognitoLoginController", + "x-operation-name": "cognitoCallback", + "tags": [ + "CognitoLoginController" + ], + "responses": { + "200": { + "description": "Cognito Redirect Token Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + } + }, + "description": "", + "parameters": [ + { + "name": "code", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "state", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "operationId": "CognitoLoginController.cognitoCallback" + } + }, + "/auth/create-qr-code": { + "post": { + "x-controller-name": "OtpController", + "x-operation-name": "createQr", + "tags": [ + "OtpController" + ], + "description": "Generates a new qrCode for Authenticator App", + "responses": { + "200": { + "description": "qrCode that you can use to generate codes in Authenticator App", + "content": {} + }, + "400": { + "description": "The syntax of the request entity is incorrect." + }, + "401": { + "description": "Invalid Credentials." + }, + "404": { + "description": "The entity requested does not exist." + }, + "422": { + "description": "The syntax of the request entity is incorrect" + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthTokenRequest" + } + } + } + }, + "operationId": "OtpController.createQr" + } + }, + "/auth/facebook": { + "post": { + "x-controller-name": "FacebookLoginController", + "x-operation-name": "postLoginViaFacebook", + "tags": [ + "FacebookLoginController" + ], + "responses": { + "200": { + "description": "POST Call for Facebook based login", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + } + }, + "description": "", + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/ClientAuthRequest" + } + } + } + }, + "operationId": "FacebookLoginController.postLoginViaFacebook" + } + }, + "/auth/facebook-auth-redirect": { + "get": { + "x-controller-name": "FacebookLoginController", + "x-operation-name": "facebookCallback", + "tags": [ + "FacebookLoginController" + ], + "responses": { + "200": { + "description": "Facebook Redirect Token Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + } + }, + "description": "", + "parameters": [ + { + "name": "code", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "state", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "operationId": "FacebookLoginController.facebookCallback" + } + }, + "/auth/forget-password": { + "post": { + "x-controller-name": "ForgetPasswordController", + "x-operation-name": "forgetPassword", + "tags": [ + "ForgetPasswordController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "204": { + "description": "Success Response." + }, + "400": { + "description": "The syntax of the request entity is incorrect." + }, + "401": { + "description": "Invalid Credentials." + }, + "404": { + "description": "The entity requested does not exist." + }, + "422": { + "description": "The syntax of the request entity is incorrect" + } + }, + "description": "", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForgetPasswordDto" + } + } + } + }, + "operationId": "ForgetPasswordController.forgetPassword" + } + }, + "/auth/google": { + "post": { + "x-controller-name": "GoogleLoginController", + "x-operation-name": "postLoginViaGoogle", + "tags": [ + "GoogleLoginController" + ], + "responses": { + "200": { + "description": "POST Call for Google based login", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + } + }, + "description": "", + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/ClientAuthRequest" + } + } + } + }, + "operationId": "GoogleLoginController.postLoginViaGoogle" + }, + "get": { + "x-controller-name": "GoogleLoginController", + "x-operation-name": "loginViaGoogle", + "tags": [ + "GoogleLoginController" + ], + "responses": { + "200": { + "description": "Google Token Response,\n (Deprecated: Possible security issue if secret is passed via query params,\n please use the post endpoint)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + } + }, + "description": "", + "deprecated": true, + "parameters": [ + { + "name": "client_id", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "client_secret", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "operationId": "GoogleLoginController.loginViaGoogle" + } + }, + "/auth/google-auth-redirect": { + "get": { + "x-controller-name": "GoogleLoginController", + "x-operation-name": "googleCallback", + "tags": [ + "GoogleLoginController" + ], + "responses": { + "200": { + "description": "Google Redirect Token Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + } + }, + "description": "", + "parameters": [ + { + "name": "code", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "state", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "operationId": "GoogleLoginController.googleCallback" + } + }, + "/auth/instagram": { + "post": { + "x-controller-name": "InstagramLoginController", + "x-operation-name": "postLoginViaInstagram", + "tags": [ + "InstagramLoginController" + ], + "responses": { + "200": { + "description": "POST Call for Instagram based login", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + } + }, + "description": "", + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/ClientAuthRequest" + } + } + } + }, + "operationId": "InstagramLoginController.postLoginViaInstagram" + } + }, + "/auth/instagram-auth-redirect": { + "get": { + "x-controller-name": "InstagramLoginController", + "x-operation-name": "instagramCallback", + "tags": [ + "InstagramLoginController" + ], + "responses": { + "200": { + "description": "Instagram Redirect Token Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + } + }, + "description": "", + "parameters": [ + { + "name": "code", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "state", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "operationId": "InstagramLoginController.instagramCallback" + } + }, + "/auth/keycloak": { + "post": { + "x-controller-name": "KeycloakLoginController", + "x-operation-name": "postLoginViaKeycloak", + "tags": [ + "KeycloakLoginController" + ], + "description": "POST Call for keycloak based login", + "responses": { + "200": { + "description": "Keycloak Token Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + } + }, + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/ClientAuthRequest" + } + } + } + }, + "operationId": "KeycloakLoginController.postLoginViaKeycloak" + }, + "get": { + "x-controller-name": "KeycloakLoginController", + "x-operation-name": "loginViaKeycloak", + "tags": [ + "KeycloakLoginController" + ], + "responses": { + "200": { + "description": "Keycloak Token Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + } + }, + "description": "", + "deprecated": true, + "parameters": [ + { + "name": "client_id", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "client_secret", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "operationId": "KeycloakLoginController.loginViaKeycloak" + } + }, + "/auth/keycloak-auth-redirect": { + "get": { + "x-controller-name": "KeycloakLoginController", + "x-operation-name": "keycloakCallback", + "tags": [ + "KeycloakLoginController" + ], + "responses": { + "200": { + "description": "Keycloak Redirect Token Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + } + }, + "description": "", + "parameters": [ + { + "name": "code", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "state", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "operationId": "KeycloakLoginController.keycloakCallback" + } + }, + "/auth/login": { + "post": { + "x-controller-name": "LoginController", + "x-operation-name": "login", + "tags": [ + "LoginController" + ], + "description": "Gets you the code that will be used for getting token (webapps)", + "responses": { + "200": { + "description": "Auth Code that you can use to generate access and refresh tokens using the POST /auth/token API", + "content": {} + }, + "400": { + "description": "The syntax of the request entity is incorrect." + }, + "401": { + "description": "Invalid Credentials." + }, + "404": { + "description": "The entity requested does not exist." + }, + "422": { + "description": "The syntax of the request entity is incorrect" + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LoginRequest" + } + } + } + }, + "operationId": "LoginController.login" + } + }, + "/auth/login-token": { + "post": { + "x-controller-name": "LoginController", + "x-operation-name": "loginWithClientUser", + "tags": [ + "LoginController" + ], + "description": "Gets you refresh token and access token in one hit. (mobile app)", + "responses": { + "200": { + "description": "Token Response Model", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + }, + "400": { + "description": "The syntax of the request entity is incorrect." + }, + "401": { + "description": "Invalid Credentials." + }, + "404": { + "description": "The entity requested does not exist." + }, + "422": { + "description": "The syntax of the request entity is incorrect" + } + }, + "deprecated": true, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LoginRequest" + } + } + } + }, + "operationId": "LoginController.loginWithClientUser" + } + }, + "/auth/me": { + "get": { + "x-controller-name": "LoginController", + "x-operation-name": "me", + "tags": [ + "LoginController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "description": "To get the user details", + "responses": { + "200": { + "description": "User Object", + "content": {} + }, + "400": { + "description": "The syntax of the request entity is incorrect." + }, + "401": { + "description": "Invalid Credentials." + }, + "404": { + "description": "The entity requested does not exist." + }, + "422": { + "description": "The syntax of the request entity is incorrect" + } + }, + "operationId": "LoginController.me" + } + }, + "/auth/oauth-apple": { + "post": { + "x-controller-name": "AppleLoginController", + "x-operation-name": "postLoginViaApple", + "tags": [ + "AppleLoginController" + ], + "responses": { + "200": { + "description": "POST Call for Apple based login", + "content": {} + } + }, + "description": "", + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/ClientAuthRequest" + } + } + } + }, + "operationId": "AppleLoginController.postLoginViaApple" + } + }, + "/auth/reset-password": { + "patch": { + "x-controller-name": "ForgetPasswordController", + "x-operation-name": "resetPassword", + "tags": [ + "ForgetPasswordController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "204": { + "description": "If User password successfully changed." + } + }, + "description": "", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResetPasswordWithClient" + } + } + } + }, + "operationId": "ForgetPasswordController.resetPassword" + } + }, + "/auth/saml": { + "post": { + "x-controller-name": "SamlLoginController", + "x-operation-name": "postLoginViaSaml", + "tags": [ + "SamlLoginController" + ], + "description": "POST Call for saml based login", + "responses": { + "200": { + "description": "Saml Token Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + } + }, + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/ClientAuthRequest" + } + } + } + }, + "operationId": "SamlLoginController.postLoginViaSaml" + } + }, + "/auth/saml-redirect": { + "post": { + "x-controller-name": "SamlLoginController", + "x-operation-name": "oktaSamlCallback", + "tags": [ + "SamlLoginController" + ], + "responses": { + "200": { + "description": "okta auth callback", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + } + }, + "description": "", + "parameters": [ + { + "name": "client", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "type": "object" + } + } + }, + "x-parameter-index": 1 + }, + "operationId": "SamlLoginController.oktaSamlCallback" + } + }, + "/auth/send-otp": { + "post": { + "x-controller-name": "OtpController", + "x-operation-name": "sendOtp", + "tags": [ + "OtpController" + ], + "description": "Sends OTP", + "responses": { + "200": { + "description": "Sends otp to user", + "content": {} + }, + "400": { + "description": "The syntax of the request entity is incorrect." + }, + "401": { + "description": "Invalid Credentials." + }, + "404": { + "description": "The entity requested does not exist." + }, + "422": { + "description": "The syntax of the request entity is incorrect" + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OtpSendRequest" + } + } + } + }, + "operationId": "OtpController.sendOtp" + } + }, + "/auth/sign-up/create-token": { + "post": { + "x-controller-name": "SignupRequestController", + "x-operation-name": "requestSignup", + "tags": [ + "SignupRequestController" + ], + "responses": { + "204": { + "description": "Sucess Response." + }, + "400": { + "description": "The syntax of the request entity is incorrect." + }, + "401": { + "description": "Invalid Credentials." + }, + "404": { + "description": "The entity requested does not exist." + }, + "422": { + "description": "The syntax of the request entity is incorrect" + } + }, + "description": "", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SignupRequestDto" + } + } + } + }, + "operationId": "SignupRequestController.requestSignup" + } + }, + "/auth/sign-up/create-user": { + "post": { + "x-controller-name": "SignupRequestController", + "x-operation-name": "signupWithToken", + "tags": [ + "SignupRequestController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "200": { + "description": "Sucess Response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LocalUserProfileDto" + } + } + } + }, + "400": { + "description": "The syntax of the request entity is incorrect." + }, + "401": { + "description": "Invalid Credentials." + }, + "404": { + "description": "The entity requested does not exist." + }, + "422": { + "description": "The syntax of the request entity is incorrect" + } + }, + "description": "", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LocalUserProfileDto" + } + } + } + }, + "operationId": "SignupRequestController.signupWithToken" + } + }, + "/auth/sign-up/verify-token": { + "get": { + "x-controller-name": "SignupRequestController", + "x-operation-name": "verifyInviteToken", + "tags": [ + "SignupRequestController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "200": { + "description": "Sucess Response." + }, + "400": { + "description": "The syntax of the request entity is incorrect." + }, + "401": { + "description": "Invalid Credentials." + }, + "404": { + "description": "The entity requested does not exist." + }, + "422": { + "description": "The syntax of the request entity is incorrect" + } + }, + "description": "", + "operationId": "SignupRequestController.verifyInviteToken" + } + }, + "/auth/switch-token": { + "post": { + "x-controller-name": "LoginController", + "x-operation-name": "switchToken", + "tags": [ + "LoginController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "description": "To switch the access-token", + "responses": { + "200": { + "description": "Switch access token with the tenant id provided.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + }, + "400": { + "description": "The syntax of the request entity is incorrect." + }, + "401": { + "description": "Invalid Credentials." + }, + "404": { + "description": "The entity requested does not exist." + }, + "422": { + "description": "The syntax of the request entity is incorrect" + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthRefreshTokenRequest" + } + } + } + }, + "operationId": "LoginController.switchToken" + } + }, + "/auth/token": { + "post": { + "x-controller-name": "LoginController", + "x-operation-name": "getToken", + "tags": [ + "LoginController" + ], + "description": "Send the code received from the POST /auth/login api and get refresh token and access token (webapps)", + "responses": { + "200": { + "description": "Token Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + }, + "400": { + "description": "The syntax of the request entity is incorrect." + }, + "401": { + "description": "Invalid Credentials." + }, + "404": { + "description": "The entity requested does not exist." + }, + "422": { + "description": "The syntax of the request entity is incorrect" + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthTokenRequest" + } + } + } + }, + "operationId": "LoginController.getToken" + } + }, + "/auth/token-refresh": { + "post": { + "x-controller-name": "LoginController", + "x-operation-name": "exchangeToken", + "tags": [ + "LoginController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "description": "Gets you a new access and refresh token once your access token is expired", + "responses": { + "200": { + "description": "New Token Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + }, + "400": { + "description": "The syntax of the request entity is incorrect." + }, + "401": { + "description": "Invalid Credentials." + }, + "404": { + "description": "The entity requested does not exist." + }, + "422": { + "description": "The syntax of the request entity is incorrect" + } + }, + "parameters": [ + { + "name": "device_id", + "in": "header", + "schema": { + "type": "string" + } + }, + { + "name": "Authorization", + "in": "header", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthRefreshTokenRequest" + } + } + } + }, + "operationId": "LoginController.exchangeToken" + } + }, + "/auth/verify-otp": { + "post": { + "x-controller-name": "OtpController", + "x-operation-name": "verifyOtp", + "tags": [ + "OtpController" + ], + "description": "Gets you the code that will be used for getting token (webapps)", + "responses": { + "200": { + "description": "Auth Code that you can use to generate access and refresh tokens using the POST /auth/token API", + "content": {} + }, + "400": { + "description": "The syntax of the request entity is incorrect." + }, + "401": { + "description": "Invalid Credentials." + }, + "404": { + "description": "The entity requested does not exist." + }, + "422": { + "description": "The syntax of the request entity is incorrect" + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OtpLoginRequest" + } + } + } + }, + "operationId": "OtpController.verifyOtp" + } + }, + "/auth/verify-reset-password-link": { + "get": { + "x-controller-name": "ForgetPasswordController", + "x-operation-name": "verifyResetPasswordLink", + "tags": [ + "ForgetPasswordController" + ], + "responses": { + "200": { + "description": "Check if Token Is Valid and not Expired." + } + }, + "description": "", + "parameters": [ + { + "name": "token", + "in": "query", + "schema": { + "type": "string" + }, + "required": true + } + ], + "operationId": "ForgetPasswordController.verifyResetPasswordLink" + } + }, + "/cognito/logout": { + "post": { + "x-controller-name": "LogoutController", + "x-operation-name": "cognitoLogout", + "tags": [ + "LogoutController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "description": "This API will log out the user from application as well as cognito", + "responses": { + "200": { + "description": "Success Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "The syntax of the request entity is incorrect." + }, + "401": { + "description": "Invalid Credentials." + }, + "404": { + "description": "The entity requested does not exist." + }, + "422": { + "description": "The syntax of the request entity is incorrect" + } + }, + "parameters": [ + { + "name": "Authorization", + "in": "header", + "schema": { + "type": "string" + }, + "description": "This is the access token which is required to authenticate user." + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RefreshTokenRequestPartial" + } + } + }, + "x-parameter-index": 1 + }, + "operationId": "LogoutController.cognitoLogout" + } + }, + "/connect/endsession": { + "post": { + "x-controller-name": "IdentityServerController", + "x-operation-name": "logout", + "tags": [ + "IdentityServerController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "description": "To logout", + "responses": { + "200": { + "description": "Success Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "The syntax of the request entity is incorrect." + }, + "401": { + "description": "Invalid Credentials." + }, + "404": { + "description": "The entity requested does not exist." + }, + "422": { + "description": "The syntax of the request entity is incorrect" + } + }, + "parameters": [ + { + "name": "Authorization", + "in": "header", + "schema": { + "type": "string" + }, + "description": "This is the access token which is required to authenticate user." + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthRefreshTokenRequestPartial" + } + } + }, + "x-parameter-index": 1 + }, + "operationId": "IdentityServerController.logout" + } + }, + "/connect/generate-keys": { + "post": { + "x-controller-name": "IdentityServerController", + "x-operation-name": "generateKeys", + "tags": [ + "IdentityServerController" + ], + "description": "Generate the set of public and private keys", + "responses": { + "200": { + "description": "JWKS Keys" + }, + "400": { + "description": "The syntax of the request entity is incorrect." + }, + "401": { + "description": "Invalid Credentials." + }, + "404": { + "description": "The entity requested does not exist." + }, + "422": { + "description": "The syntax of the request entity is incorrect" + } + }, + "operationId": "IdentityServerController.generateKeys" + } + }, + "/connect/get-keys": { + "get": { + "x-controller-name": "IdentityServerController", + "x-operation-name": "getKeys", + "tags": [ + "IdentityServerController" + ], + "description": "Get the public keys", + "responses": { + "200": { + "description": "JWKS Keys" + }, + "400": { + "description": "The syntax of the request entity is incorrect." + }, + "401": { + "description": "Invalid Credentials." + }, + "404": { + "description": "The entity requested does not exist." + }, + "422": { + "description": "The syntax of the request entity is incorrect" + } + }, + "operationId": "IdentityServerController.getKeys" + } + }, + "/connect/rotate-keys": { + "post": { + "x-controller-name": "IdentityServerController", + "x-operation-name": "rotateKeys", + "tags": [ + "IdentityServerController" + ], + "description": "Generate the set of public and private keys", + "responses": { + "200": { + "description": "JWKS Keys" + }, + "400": { + "description": "The syntax of the request entity is incorrect." + }, + "401": { + "description": "Invalid Credentials." + }, + "404": { + "description": "The entity requested does not exist." + }, + "422": { + "description": "The syntax of the request entity is incorrect" + } + }, + "operationId": "IdentityServerController.rotateKeys" + } + }, + "/connect/token": { + "post": { + "x-controller-name": "IdentityServerController", + "x-operation-name": "getToken", + "tags": [ + "IdentityServerController" + ], + "description": "Send the code received from the POST /auth/login api and get refresh token and access token (webapps)", + "responses": { + "200": { + "description": "Token Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenResponse" + } + } + } + }, + "400": { + "description": "The syntax of the request entity is incorrect." + }, + "401": { + "description": "Invalid Credentials." + }, + "404": { + "description": "The entity requested does not exist." + }, + "422": { + "description": "The syntax of the request entity is incorrect" + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthTokenRequest" + } + } + } + }, + "operationId": "IdentityServerController.getToken" + } + }, + "/connect/userinfo": { + "get": { + "x-controller-name": "IdentityServerController", + "x-operation-name": "me", + "tags": [ + "IdentityServerController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "description": "To get the user details", + "responses": { + "200": { + "description": "User Object", + "content": {} + }, + "400": { + "description": "The syntax of the request entity is incorrect." + }, + "401": { + "description": "Invalid Credentials." + }, + "404": { + "description": "The entity requested does not exist." + }, + "422": { + "description": "The syntax of the request entity is incorrect" + } + }, + "operationId": "IdentityServerController.me" + } + }, + "/google/logout": { + "post": { + "x-controller-name": "LogoutController", + "x-operation-name": "googleLogout", + "tags": [ + "LogoutController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "description": "This API will log out the user from application as well as google", + "responses": { + "200": { + "description": "Success Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "The syntax of the request entity is incorrect." + }, + "401": { + "description": "Invalid Credentials." + }, + "404": { + "description": "The entity requested does not exist." + }, + "422": { + "description": "The syntax of the request entity is incorrect" + } + }, + "parameters": [ + { + "name": "Authorization", + "in": "header", + "schema": { + "type": "string" + }, + "description": "This is the access token which is required to authenticate user." + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RefreshTokenRequestPartial" + } + } + }, + "x-parameter-index": 1 + }, + "operationId": "LogoutController.googleLogout" + } + }, + "/keycloak/logout": { + "post": { + "x-controller-name": "LogoutController", + "x-operation-name": "keycloakLogout", + "tags": [ + "LogoutController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "description": "This API will log out the user from application as well as keycloak", + "responses": { + "200": { + "description": "Success Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "The syntax of the request entity is incorrect." + }, + "401": { + "description": "Invalid Credentials." + }, + "404": { + "description": "The entity requested does not exist." + }, + "422": { + "description": "The syntax of the request entity is incorrect" + } + }, + "parameters": [ + { + "name": "Authorization", + "in": "header", + "schema": { + "type": "string" + }, + "description": "This is the access token which is required to authenticate user." + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RefreshTokenRequestPartial" + } + } + }, + "x-parameter-index": 1 + }, + "operationId": "LogoutController.keycloakLogout" + } + }, + "/login-activity/count": { + "get": { + "x-controller-name": "LoginActivityController", + "x-operation-name": "count", + "tags": [ + "LoginActivityController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "200": { + "description": "LoginActivity model count", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/loopback.Count" + } + } + } + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| ViewLoginActivity |\n", + "parameters": [ + { + "name": "where", + "in": "query", + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "login_activity.WhereFilter", + "additionalProperties": true, + "x-typescript-type": "@loopback/repository#Where" + } + } + } + } + ], + "operationId": "LoginActivityController.count" + } + }, + "/login-activity/{id}": { + "get": { + "x-controller-name": "LoginActivityController", + "x-operation-name": "findById", + "tags": [ + "LoginActivityController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "200": { + "description": "LoginActivity model instance", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LoginActivityWithRelations" + } + } + } + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| ViewLoginActivity |\n", + "parameters": [ + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "filter", + "in": "query", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/login_activity.Filter" + } + } + } + } + ], + "operationId": "LoginActivityController.findById" + } + }, + "/login-activity": { + "get": { + "x-controller-name": "LoginActivityController", + "x-operation-name": "find", + "tags": [ + "LoginActivityController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "200": { + "description": "Array of LoginActivity model instances", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/LoginActivityWithRelations" + } + } + } + } + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| ViewLoginActivity |\n", + "parameters": [ + { + "name": "filter", + "in": "query", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/login_activity.Filter" + } + } + } + } + ], + "operationId": "LoginActivityController.find" + } + }, + "/logout": { + "post": { + "x-controller-name": "LogoutController", + "x-operation-name": "logout", + "tags": [ + "LogoutController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "description": "To logout", + "responses": { + "200": { + "description": "Success Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "The syntax of the request entity is incorrect." + }, + "401": { + "description": "Invalid Credentials." + }, + "404": { + "description": "The entity requested does not exist." + }, + "422": { + "description": "The syntax of the request entity is incorrect" + } + }, + "parameters": [ + { + "name": "Authorization", + "in": "header", + "schema": { + "type": "string" + }, + "description": "This is the access token which is required to authenticate user." + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RefreshTokenRequestPartial" + } + } + }, + "x-parameter-index": 1 + }, + "operationId": "LogoutController.logout" + } + }, + "/ping": { + "get": { + "x-controller-name": "PingController", + "x-operation-name": "ping", + "tags": [ + "PingController" + ], + "responses": { + "200": { + "description": "Ping Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PingResponse" + } + } + } + } + }, + "description": "", + "operationId": "PingController.ping" + } + }, + "/": { + "get": { + "x-controller-name": "HomePageController", + "x-operation-name": "homePage", + "tags": [ + "HomePageController" + ], + "responses": { + "200": { + "description": "Home Page", + "content": { + "text/html": { + "schema": { + "type": "string" + } + } + } + } + }, + "description": "", + "operationId": "HomePageController.homePage" + } + } + }, + "components": { + "securitySchemes": { + "HTTPBearer": { + "type": "http", + "scheme": "bearer", + "bearerFormat": "JWT" + } + }, + "schemas": { + "LoginRequest": { + "title": "LoginRequest", + "type": "object", + "description": "This is the signature for login request.", + "properties": { + "client_id": { + "type": "string", + "description": "This property is supposed to be a string and is a required field" + }, + "client_secret": { + "type": "string", + "description": "This property is supposed to be a string and is a required field" + }, + "username": { + "type": "string", + "description": "This property is supposed to be a string and is a required field" + }, + "password": { + "type": "string", + "description": "This property is supposed to be a string and is a required field" + } + }, + "required": [ + "client_id", + "username", + "password" + ], + "additionalProperties": false + }, + "TokenResponse": { + "title": "TokenResponse", + "type": "object", + "description": "This is signature for successful token response.", + "properties": { + "accessToken": { + "type": "string", + "description": "This property is supposed to be a string and is a required field" + }, + "refreshToken": { + "type": "string", + "description": "This property is supposed to be a string and is a required field" + }, + "expires": { + "type": "number" + }, + "pubnubToken": { + "type": "string" + } + }, + "required": [ + "accessToken", + "refreshToken", + "expires" + ], + "additionalProperties": false + }, + "AuthTokenRequest": { + "title": "AuthTokenRequest", + "type": "object", + "description": "This is the signature for requesting the accessToken and refreshToken.", + "properties": { + "code": { + "type": "string" + }, + "clientId": { + "type": "string" + } + }, + "required": [ + "code", + "clientId" + ], + "additionalProperties": false + }, + "AuthRefreshTokenRequest": { + "title": "AuthRefreshTokenRequest", + "type": "object", + "properties": { + "refreshToken": { + "type": "string" + }, + "tenantId": { + "type": "string" + } + }, + "required": [ + "refreshToken" + ], + "additionalProperties": false + }, + "ResetPasswordPartial": { + "title": "ResetPasswordPartial", + "type": "object", + "description": "This is a signature for reset password. (tsType: Partial, schemaOptions: { partial: true })", + "properties": { + "refreshToken": { + "type": "string" + }, + "username": { + "type": "string", + "description": "This property is supposed to be a string and is a required field" + }, + "password": { + "type": "string", + "description": "This property is supposed to be a string and is a required field" + }, + "oldPassword": { + "type": "string", + "description": "This property is supposed to be a string and is a required field" + } + }, + "additionalProperties": false + }, + "ResetPassword": { + "title": "ResetPassword", + "type": "object", + "description": "This is a signature for reset password.", + "properties": { + "refreshToken": { + "type": "string" + }, + "username": { + "type": "string", + "description": "This property is supposed to be a string and is a required field" + }, + "password": { + "type": "string", + "description": "This property is supposed to be a string and is a required field" + }, + "oldPassword": { + "type": "string", + "description": "This property is supposed to be a string and is a required field" + } + }, + "required": [ + "refreshToken", + "username", + "password" + ], + "additionalProperties": false + }, + "ClientAuthRequest": { + "title": "ClientAuthRequest", + "type": "object", + "description": "This is signature for client authentication request.", + "properties": { + "client_id": { + "type": "string", + "description": "This property is supposed to be a string and is a required field" + }, + "client_secret": { + "type": "string", + "description": "This property is supposed to be a string and is a required field" + } + }, + "required": [ + "client_id", + "client_secret" + ], + "additionalProperties": false + }, + "SuccessResponse": { + "title": "SuccessResponse", + "type": "object", + "properties": { + "success": { + "type": "boolean" + } + }, + "additionalProperties": true + }, + "RefreshTokenRequestPartial": { + "title": "RefreshTokenRequestPartial", + "type": "object", + "description": "(tsType: Partial, schemaOptions: { partial: true })", + "properties": { + "refreshToken": { + "type": "string" + } + }, + "additionalProperties": false, + "x-typescript-type": "Partial" + }, + "RefreshTokenRequest": { + "title": "RefreshTokenRequest", + "type": "object", + "properties": { + "refreshToken": { + "type": "string" + } + }, + "required": [ + "refreshToken" + ], + "additionalProperties": false + }, + "OtpSendRequest": { + "title": "OtpSendRequest", + "type": "object", + "description": "This is the signature for OTP login request.", + "properties": { + "client_id": { + "type": "string", + "description": "This property is supposed to be a string and is a required field" + }, + "client_secret": { + "type": "string", + "description": "This property is supposed to be a string and is a required field" + }, + "key": { + "type": "string", + "description": "This property is supposed to be a string and is a required field" + } + }, + "required": [ + "client_id", + "client_secret", + "key" + ], + "additionalProperties": false + }, + "OtpLoginRequest": { + "title": "OtpLoginRequest", + "type": "object", + "description": "This is the signature for OTP login request.", + "properties": { + "key": { + "type": "string", + "description": "This property is supposed to be a string and is a required field" + }, + "otp": { + "type": "string", + "description": "This property is supposed to be a string and is a required field" + }, + "clientId": { + "type": "string" + } + }, + "required": [ + "key", + "otp" + ], + "additionalProperties": false + }, + "AuthUser": { + "title": "AuthUser", + "type": "object", + "description": "This is the signature for authenticated user which holds permissions and role.", + "properties": { + "deleted": { + "type": "boolean" + }, + "deletedOn": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "deletedBy": { + "type": "string", + "nullable": true + }, + "createdOn": { + "type": "string", + "format": "date-time" + }, + "modifiedOn": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "string" + }, + "modifiedBy": { + "type": "string" + }, + "id": { + "type": "string" + }, + "firstName": { + "type": "string" + }, + "lastName": { + "type": "string" + }, + "middleName": { + "type": "string" + }, + "username": { + "type": "string" + }, + "email": { + "type": "string" + }, + "phone": { + "type": "string", + "pattern": "^\\+?[1-9]\\d{1,14}$" + }, + "authClientIds": { + "type": "string" + }, + "lastLogin": { + "type": "string", + "format": "date-time" + }, + "photoUrl": { + "type": "string" + }, + "designation": { + "type": "string" + }, + "dob": { + "type": "string", + "format": "date-time" + }, + "gender": { + "type": "string", + "description": "This field takes a single character as input in database.\n 'M' for male and 'F' for female.", + "enum": [ + "M", + "F", + "O" + ] + }, + "defaultTenantId": { + "type": "string" + }, + "permissions": { + "type": "array", + "items": { + "type": "string" + } + }, + "role": { + "type": "string" + }, + "externalAuthToken": { + "type": "string" + }, + "deviceInfo": { + "type": "object", + "description": "This property consists of two optional fields.\n 1. userAgent\n 2. deviceId " + }, + "age": { + "type": "number" + }, + "externalRefreshToken": { + "type": "string" + }, + "authClientId": { + "type": "number" + }, + "userPreferences": { + "type": "object" + }, + "tenantId": { + "type": "string" + }, + "userTenantId": { + "type": "string" + }, + "passwordExpiryTime": { + "type": "string", + "format": "date-time" + }, + "status": { + "type": "number", + "enum": [ + 1, + 2, + 3, + 0, + 4 + ] + } + }, + "required": [ + "firstName", + "username", + "role" + ], + "additionalProperties": false + }, + "Function": {}, + "ForgetPasswordDto": { + "title": "ForgetPasswordDto", + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "client_id": { + "type": "string" + }, + "client_secret": { + "type": "string" + } + }, + "required": [ + "username", + "client_id", + "client_secret" + ], + "additionalProperties": false + }, + "AuthClient": { + "title": "AuthClient", + "type": "object", + "properties": { + "deleted": { + "type": "boolean" + }, + "deletedOn": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "deletedBy": { + "type": "string", + "nullable": true + }, + "createdOn": { + "type": "string", + "format": "date-time" + }, + "modifiedOn": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "string" + }, + "modifiedBy": { + "type": "string" + }, + "id": { + "type": "number" + }, + "clientId": { + "type": "string" + }, + "clientSecret": { + "type": "string" + }, + "secret": { + "type": "string", + "description": "Value can be a string or a private key." + }, + "redirectUrl": { + "type": "string" + }, + "accessTokenExpiration": { + "type": "number" + }, + "refreshTokenExpiration": { + "type": "number" + }, + "authCodeExpiration": { + "type": "number" + } + }, + "required": [ + "clientId", + "clientSecret", + "secret", + "accessTokenExpiration", + "refreshTokenExpiration", + "authCodeExpiration" + ], + "additionalProperties": false + }, + "ResetPasswordWithClient": { + "title": "ResetPasswordWithClient", + "type": "object", + "properties": { + "token": { + "type": "string" + }, + "password": { + "type": "string" + }, + "client_id": { + "type": "string" + }, + "client_secret": { + "type": "string" + } + }, + "required": [ + "token", + "password", + "client_id", + "client_secret" + ], + "additionalProperties": false + }, + "SignupRequestDto": { + "title": "SignupRequestDto", + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "data": { + "type": "object" + } + }, + "required": [ + "email" + ], + "additionalProperties": false + }, + "LocalUserProfileDto": { + "title": "LocalUserProfileDto", + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "password": { + "type": "string" + } + }, + "required": [ + "email", + "password" + ], + "additionalProperties": true + }, + "SignupRequest": { + "title": "SignupRequest", + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "expiry": { + "type": "string" + } + }, + "required": [ + "email" + ], + "additionalProperties": false + }, + "LoginActivityWithRelations": { + "title": "LoginActivityWithRelations", + "type": "object", + "description": "This is to maintain the daily login activity. (tsType: LoginActivityWithRelations, schemaOptions: { includeRelations: true })", + "properties": { + "id": { + "type": "string" + }, + "actor": { + "type": "string" + }, + "tenantId": { + "type": "string" + }, + "loginTime": { + "type": "string", + "format": "date-time" + }, + "tokenPayload": { + "type": "string" + }, + "loginType": { + "type": "string" + }, + "deviceInfo": { + "type": "string" + }, + "ipAddress": { + "type": "string" + } + }, + "additionalProperties": false + }, + "Date": {}, + "ActiveUsersFilter": { + "title": "ActiveUsersFilter", + "type": "object", + "properties": { + "inclusion": { + "type": "boolean" + }, + "userIdentity": { + "type": "string" + }, + "userIdentifier": { + "type": "object" + } + }, + "required": [ + "inclusion", + "userIdentity", + "userIdentifier" + ], + "additionalProperties": false + }, + "AuthRefreshTokenRequestPartial": { + "title": "AuthRefreshTokenRequestPartial", + "type": "object", + "description": "(tsType: Partial, schemaOptions: { partial: true })", + "properties": { + "refreshToken": { + "type": "string" + }, + "tenantId": { + "type": "string" + } + }, + "additionalProperties": false, + "x-typescript-type": "Partial" + }, + "loopback.Count": { + "type": "object", + "title": "loopback.Count", + "x-typescript-type": "@loopback/repository#Count", + "properties": { + "count": { + "type": "number" + } + } + }, + "login_activity.Filter": { + "type": "object", + "title": "login_activity.Filter", + "properties": { + "offset": { + "type": "integer", + "minimum": 0 + }, + "limit": { + "type": "integer", + "minimum": 1, + "example": 100 + }, + "skip": { + "type": "integer", + "minimum": 0 + }, + "order": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "where": { + "title": "login_activity.WhereFilter", + "type": "object", + "additionalProperties": true + }, + "fields": { + "oneOf": [ + { + "type": "object", + "properties": { + "id": { + "type": "boolean" + }, + "actor": { + "type": "boolean" + }, + "tenantId": { + "type": "boolean" + }, + "loginTime": { + "type": "boolean" + }, + "tokenPayload": { + "type": "boolean" + }, + "loginType": { + "type": "boolean" + }, + "deviceInfo": { + "type": "boolean" + }, + "ipAddress": { + "type": "boolean" + } + }, + "additionalProperties": false + }, + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "id", + "actor", + "tenantId", + "loginTime", + "tokenPayload", + "loginType", + "deviceInfo", + "ipAddress" + ], + "example": "id" + }, + "uniqueItems": true + } + ], + "title": "login_activity.Fields" + } + }, + "additionalProperties": false, + "x-typescript-type": "@loopback/repository#Filter" + }, + "PingResponse": { + "type": "object", + "title": "PingResponse", + "properties": { + "greeting": { + "type": "string" + }, + "date": { + "type": "string" + }, + "url": { + "type": "string" + }, + "headers": { + "type": "object", + "properties": { + "Content-Type": { + "type": "string" + } + }, + "additionalProperties": true + } + } + } + } + }, + "servers": [ + { + "url": "/" + } + ] +} \ No newline at end of file diff --git a/sandbox/oauth-example/src/opentelemetry-registry.ts b/sandbox/oauth-example/src/opentelemetry-registry.ts new file mode 100644 index 0000000000..02aef44196 --- /dev/null +++ b/sandbox/oauth-example/src/opentelemetry-registry.ts @@ -0,0 +1,31 @@ +import {JaegerExporter} from '@opentelemetry/exporter-jaeger'; +import {NodeTracerProvider} from '@opentelemetry/sdk-trace-node'; +import { + BatchSpanProcessor, + ConsoleSpanExporter, +} from '@opentelemetry/sdk-trace-base'; +import * as dotenv from 'dotenv'; +import * as dotenvExt from 'dotenv-extended'; + +dotenv.config(); +dotenvExt.load({ + schema: '.env.example', + errorOnMissing: true, + includeProcessEnv: true, +}); + +if (!!+(process.env.ENABLE_TRACING ?? 0)) { + const provider = new NodeTracerProvider(); + const option = { + serviceName: process.env.SERVICE_NAME ?? '', + tags: [], + // You can use the default UDPSender + host: process.env.OPENTELEMETRY_HOST ?? '', + port: process.env.OPENTELEMETRY_PORT ? +process.env.OPENTELEMETRY_PORT : 0, + }; + // Configure span processor to send spans to the exporter + const exporter = new JaegerExporter(option); + provider.addSpanProcessor(new BatchSpanProcessor(exporter)); + provider.addSpanProcessor(new BatchSpanProcessor(new ConsoleSpanExporter())); + provider.register(); +} diff --git a/sandbox/oauth-example/src/providers/azure-ad-signup.provider.ts b/sandbox/oauth-example/src/providers/azure-ad-signup.provider.ts deleted file mode 100644 index bdc726083c..0000000000 --- a/sandbox/oauth-example/src/providers/azure-ad-signup.provider.ts +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) 2023 Sourcefuse Technologies -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT -import {Provider} from '@loopback/context'; -import {repository} from '@loopback/repository'; -import {HttpErrors} from '@loopback/rest'; -import { - AuthClientRepository, - AzureAdSignUpFn, - User, - UserRelations, -} from '@sourceloop/authentication-service'; -import { - RoleRepository, - TenantRepository, - UserRepository, -} from '../repositories'; - -export class AzureAdSignupProvider implements Provider { - constructor( - @repository(RoleRepository) - private readonly roleRepo: RoleRepository, - @repository(TenantRepository) - private readonly tenantRepo: TenantRepository, - @repository(AuthClientRepository) - private readonly authClientRepo: AuthClientRepository, - @repository(UserRepository) - private readonly userRepo: UserRepository, - ) {} - - value(): AzureAdSignUpFn { - return async profile => { - const [tenant, role, client] = await Promise.all([ - this.tenantRepo.findOne({ - where: { - key: 'master', - }, - }), - this.roleRepo.findOne({ - where: { - roleType: 0, - }, - }), - this.authClientRepo.findOne({ - where: { - clientId: 'test_client_id', - }, - }), - ]); - - // check if user exist - - const userExists = await this.userRepo.findOne({ - where: { - or: [{username: profile.upn}, {email: profile.upn}], - }, - }); - if (userExists) { - throw new HttpErrors.BadRequest('User already exists'); - } - - const user = await this.userRepo.createWithoutPassword({ - firstName: profile.name!.givenName, - lastName: profile.name!.familyName, - username: profile.upn, - email: profile.upn, - defaultTenantId: tenant?.id, - authClientIds: `{${client?.id}}`, - }); - - await this.userRepo.credentials(user.id).create({ - userId: user.id, - authProvider: 'azure', - authId: profile.oid, - }); - - await this.userRepo.userTenants(user.id).create({ - userId: user.id, - tenantId: tenant?.id, - roleId: role?.id, - }); - return user as User & UserRelations; - }; - } -} diff --git a/sandbox/oauth-example/src/providers/facebook-oauth2-signup.provider.ts b/sandbox/oauth-example/src/providers/facebook-oauth2-signup.provider.ts deleted file mode 100644 index 36b1b61e33..0000000000 --- a/sandbox/oauth-example/src/providers/facebook-oauth2-signup.provider.ts +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2023 Sourcefuse Technologies -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT -import {Provider} from '@loopback/context'; -import {repository} from '@loopback/repository'; -import {HttpErrors} from '@loopback/rest'; -import { - AuthClientRepository, - FacebookSignUpFn, - User, - UserRelations, -} from '@sourceloop/authentication-service'; -import { - RoleRepository, - TenantRepository, - UserRepository, -} from '../repositories'; - -export class FacebookOauth2SignupProvider - implements Provider -{ - constructor( - @repository(RoleRepository) - private readonly roleRepo: RoleRepository, - @repository(TenantRepository) - private readonly tenantRepo: TenantRepository, - @repository(AuthClientRepository) - private readonly authClientRepo: AuthClientRepository, - @repository(UserRepository) - private readonly userRepo: UserRepository, - ) {} - - value(): FacebookSignUpFn { - return async profile => { - const [tenant, role, client] = await Promise.all([ - this.tenantRepo.findOne({ - where: { - key: 'master', - }, - }), - this.roleRepo.findOne({ - where: { - roleType: 0, - }, - }), - this.authClientRepo.findOne({ - where: { - clientId: 'test_client_id', - }, - }), - ]); - - // check if user exist - - const userExists = await this.userRepo.findOne({ - where: { - or: [{username: profile._json.email}, {email: profile._json.email}], - }, - }); - if (userExists) { - throw new HttpErrors.BadRequest('User already exists'); - } - - const user = await this.userRepo.createWithoutPassword({ - firstName: profile.name!.givenName ?? profile.displayName, - lastName: profile.name!.familyName, - username: profile._json.email ?? profile.displayName, - email: profile._json.email, - defaultTenantId: tenant?.id, - authClientIds: `{${client?.id}}`, - }); - - await this.userRepo.credentials(user.id).create({ - userId: user.id, - authProvider: 'facebook', - authId: profile.id, - }); - - await this.userRepo.userTenants(user.id).create({ - userId: user.id, - tenantId: tenant?.id, - roleId: role?.id, - }); - return user as User & UserRelations; - }; - } -} diff --git a/sandbox/oauth-example/src/providers/google-oauth2-signup.provider.ts b/sandbox/oauth-example/src/providers/google-oauth2-signup.provider.ts index 4542318deb..90253d6ab7 100644 --- a/sandbox/oauth-example/src/providers/google-oauth2-signup.provider.ts +++ b/sandbox/oauth-example/src/providers/google-oauth2-signup.provider.ts @@ -1,4 +1,4 @@ -// Copyright (c) 2023 Sourcefuse Technologies +// Copyright (c) 2022 Sourcefuse Technologies // // This software is released under the MIT License. // https://opensource.org/licenses/MIT @@ -8,14 +8,17 @@ import {HttpErrors} from '@loopback/rest'; import { AuthClientRepository, GoogleSignUpFn, - User, - UserRelations, -} from '@sourceloop/authentication-service'; -import { RoleRepository, TenantRepository, + User, + UserRelations, UserRepository, -} from '../repositories'; +} from '@sourceloop/authentication-service'; +// import { +// RoleRepository, +// TenantRepository, +// UserRepository, +// } from '../repositories'; export class GoogleOauth2SignupProvider implements Provider { constructor( @@ -61,8 +64,8 @@ export class GoogleOauth2SignupProvider implements Provider { } const user = await this.userRepo.createWithoutPassword({ - firstName: profile.name!.givenName, - lastName: profile.name!.familyName, + firstName: profile.name.givenName, + lastName: profile.name.familyName, username: profile._json.email, email: profile._json.email, defaultTenantId: tenant?.id, diff --git a/sandbox/oauth-example/src/providers/index.ts b/sandbox/oauth-example/src/providers/index.ts index e450690a57..befaf40a1e 100644 --- a/sandbox/oauth-example/src/providers/index.ts +++ b/sandbox/oauth-example/src/providers/index.ts @@ -1,9 +1 @@ -// Copyright (c) 2023 Sourcefuse Technologies -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT -export * from './azure-ad-signup.provider'; -export * from './facebook-oauth2-signup.provider'; export * from './google-oauth2-signup.provider'; -export * from './saml-signup.provider'; -export * from './saml-verify.provider'; diff --git a/sandbox/oauth-example/src/providers/saml-signup.provider.ts b/sandbox/oauth-example/src/providers/saml-signup.provider.ts deleted file mode 100644 index 5d38998cd4..0000000000 --- a/sandbox/oauth-example/src/providers/saml-signup.provider.ts +++ /dev/null @@ -1,89 +0,0 @@ -import {inject, Provider} from '@loopback/context'; -import {repository} from '@loopback/repository'; -import {HttpErrors} from '@loopback/rest'; -import { - AuthClient, - AuthClientRepository, - SamlSignUpFn, - TenantRepository, - User, - UserCredentialsRepository, - UserRelations, - UserRepository, -} from '@sourceloop/authentication-service'; -import {AuthenticationBindings} from 'loopback4-authentication'; -import {RoleRepository} from '../repositories'; - -export class SamlSignupProvider implements Provider { - constructor( - @repository(UserRepository) - public userRepository: UserRepository, - @repository(TenantRepository) - public tenantRepository: TenantRepository, - @repository(UserCredentialsRepository) - public userCredsRepository: UserCredentialsRepository, - @repository(RoleRepository) - private readonly roleRepo: RoleRepository, - @repository(TenantRepository) - private readonly tenantRepo: TenantRepository, - @repository(UserRepository) - private readonly userRepo: UserRepository, - @repository(AuthClientRepository) - private readonly authClientRepo: AuthClientRepository, - @inject(AuthenticationBindings.CURRENT_CLIENT) - private readonly client: AuthClient | undefined, - ) {} - - value(): SamlSignUpFn { - return async profile => { - // Find 1st tenant associated with this client_id - const [tenant, role, client] = await Promise.all([ - this.tenantRepo.findOne({ - where: { - key: 'master', - }, - }), - this.roleRepo.findOne({ - where: { - roleType: 0, - }, - }), - this.authClientRepo.findOne({ - where: { - clientId: 'test_client_id', - }, - }), - ]); - - const userExists = await this.userRepo.findOne({ - where: { - or: [{username: profile.email}, {email: profile.email}], - }, - }); - if (userExists) { - throw new HttpErrors.BadRequest('User already exists'); - } - const user = await this.userRepo.createWithoutPassword({ - username: profile.email, - firstName: String(profile.first_name), - lastName: String(profile.last_name), - email: profile.email, - defaultTenantId: tenant?.id, - authClientIds: `{${client?.id}}`, - }); - - await this.userRepo.credentials(user.id).create({ - userId: user.id, - authProvider: 'saml', - authId: profile.ID, - }); - - await this.userRepo.userTenants(user.id).create({ - userId: user.id, - tenantId: tenant?.id, - roleId: role?.id, - }); - return user as User & UserRelations; // NOSONAR - }; - } -} diff --git a/sandbox/oauth-example/src/providers/saml-verify.provider.ts b/sandbox/oauth-example/src/providers/saml-verify.provider.ts deleted file mode 100644 index 89901a54e0..0000000000 --- a/sandbox/oauth-example/src/providers/saml-verify.provider.ts +++ /dev/null @@ -1,54 +0,0 @@ -import {inject, Provider} from '@loopback/context'; -import {repository} from '@loopback/repository'; -import {HttpErrors, Request} from '@loopback/rest'; -import * as samlStrategy from '@node-saml/passport-saml'; -import { - AuthUser, - SamlSignUpFn, - SignUpBindings, - UserCredentialsRepository, - UserRepository, -} from '@sourceloop/authentication-service'; -import {AuthErrorKeys, VerifyFunction} from 'loopback4-authentication'; - -export class SamlVerifyProvider implements Provider { - constructor( - @repository(UserRepository) - public userRepository: UserRepository, - @repository(UserCredentialsRepository) - public userCredsRepository: UserCredentialsRepository, - @inject(SignUpBindings.SAML_SIGN_UP_PROVIDER) - private readonly signupProvider: SamlSignUpFn, - ) {} - - value(): VerifyFunction.SamlFn { - return async ( - profile: samlStrategy.Profile, - cb: samlStrategy.VerifiedCallback, - req?: Request, - ) => { - const user = await this.signupProvider(profile); - if (user == null) { - throw new HttpErrors.Unauthorized(AuthErrorKeys.InvalidCredentials); - } - // Just to check if userCreds has entry for this user for this provider - const creds = await this.userCredsRepository.findOne({ - where: { - userId: user.id, - authProvider: 'saml', - }, - }); - if ( - !creds || - creds.authProvider !== 'saml' || - creds.authId !== profile.ID - ) { - throw new HttpErrors.Unauthorized(AuthErrorKeys.InvalidCredentials); - } - - const authUser: AuthUser = new AuthUser(user); - authUser.permissions = []; - return authUser; - }; - } -} diff --git a/sandbox/oauth-example/src/repositories/README.md b/sandbox/oauth-example/src/repositories/README.md deleted file mode 100644 index 08638a7878..0000000000 --- a/sandbox/oauth-example/src/repositories/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Repositories - -This directory contains code for repositories provided by this app. diff --git a/sandbox/oauth-example/src/repositories/index.ts b/sandbox/oauth-example/src/repositories/index.ts deleted file mode 100644 index 01467df1a8..0000000000 --- a/sandbox/oauth-example/src/repositories/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) 2023 Sourcefuse Technologies -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT -export * from './role.repository'; -export * from './tenant.repository'; -export * from './user.repository'; diff --git a/sandbox/oauth-example/src/repositories/role.repository.ts b/sandbox/oauth-example/src/repositories/role.repository.ts deleted file mode 100644 index 50563bea76..0000000000 --- a/sandbox/oauth-example/src/repositories/role.repository.ts +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2023 Sourcefuse Technologies -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT -import {inject} from '@loopback/core'; -import {juggler} from '@loopback/repository'; -import {DefaultSoftCrudRepository} from '@sourceloop/core'; -import {AuthDbSourceName, Role} from '@sourceloop/authentication-service'; - -export class RoleRepository extends DefaultSoftCrudRepository< - Role, - typeof Role.prototype.id -> { - constructor( - @inject(`datasources.${AuthDbSourceName}`) - dataSource: juggler.DataSource, - ) { - super(Role, dataSource); - } -} diff --git a/sandbox/oauth-example/src/repositories/tenant.repository.ts b/sandbox/oauth-example/src/repositories/tenant.repository.ts deleted file mode 100644 index 0e13056fb6..0000000000 --- a/sandbox/oauth-example/src/repositories/tenant.repository.ts +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2023 Sourcefuse Technologies -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT -import {Getter, inject} from '@loopback/core'; -import { - HasManyRepositoryFactory, - juggler, - repository, -} from '@loopback/repository'; -import {DefaultSoftCrudRepository} from '@sourceloop/core'; -import { - AuthDbSourceName, - Tenant, - TenantConfig, - TenantConfigRepository, -} from '@sourceloop/authentication-service'; - -export class TenantRepository extends DefaultSoftCrudRepository< - Tenant, - typeof Tenant.prototype.id -> { - public readonly tenantConfigs: HasManyRepositoryFactory< - TenantConfig, - typeof Tenant.prototype.id - >; - - constructor( - @inject(`datasources.${AuthDbSourceName}`) dataSource: juggler.DataSource, - @repository.getter('TenantConfigRepository') - protected tenantConfigRepositoryGetter: Getter, - ) { - super(Tenant, dataSource); - this.tenantConfigs = this.createHasManyRepositoryFactoryFor( - 'tenantConfigs', - tenantConfigRepositoryGetter, - ); - this.registerInclusionResolver( - 'tenantConfigs', - this.tenantConfigs.inclusionResolver, - ); - } -} diff --git a/sandbox/oauth-example/src/repositories/user.repository.ts b/sandbox/oauth-example/src/repositories/user.repository.ts deleted file mode 100644 index edb6c28e41..0000000000 --- a/sandbox/oauth-example/src/repositories/user.repository.ts +++ /dev/null @@ -1,245 +0,0 @@ -// Copyright (c) 2023 Sourcefuse Technologies -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT -import {Getter, inject} from '@loopback/core'; -import { - BelongsToAccessor, - DataObject, - HasManyRepositoryFactory, - HasOneRepositoryFactory, - Options, - juggler, - repository, -} from '@loopback/repository'; -import {HttpErrors} from '@loopback/rest'; -import { - AuthDbSourceName, - OtpRepository, - Tenant, - TenantRepository, - User, - UserCredentials, - UserCredentialsRepository, - UserRelations, - UserTenant, - UserTenantRepository, -} from '@sourceloop/authentication-service'; -import { - AuthProvider, - AuthenticateErrorKeys, - DefaultSoftCrudRepository, - ILogger, - LOGGER, - UserStatus, -} from '@sourceloop/core'; -import * as bcrypt from 'bcrypt'; -import {AuthErrorKeys} from 'loopback4-authentication'; - -const saltRounds = 10; - -export class UserRepository extends DefaultSoftCrudRepository< - User, - typeof User.prototype.id, - UserRelations -> { - public readonly credentials: HasOneRepositoryFactory< - UserCredentials, - typeof User.prototype.id - >; - public readonly tenant: BelongsToAccessor; - - public readonly userTenants: HasManyRepositoryFactory< - UserTenant, - typeof User.prototype.id - >; - - constructor( - @inject(`datasources.${AuthDbSourceName}`) - dataSource: juggler.DataSource, - @repository.getter(UserCredentialsRepository) - getUserCredsRepository: Getter, - @repository.getter(OtpRepository) - public getOtpRepository: Getter, - @repository.getter('TenantRepository') - protected tenantRepositoryGetter: Getter, - @repository.getter('UserTenantRepository') - protected userTenantRepositoryGetter: Getter, - @inject(LOGGER.LOGGER_INJECT) private readonly logger: ILogger, - ) { - super(User, dataSource); - this.userTenants = this.createHasManyRepositoryFactoryFor( - 'userTenants', - userTenantRepositoryGetter, - ); - this.registerInclusionResolver( - 'userTenants', - this.userTenants.inclusionResolver, - ); - this.tenant = this.createBelongsToAccessorFor( - 'defaultTenant', - tenantRepositoryGetter, - ); - this.registerInclusionResolver( - 'defaultTenant', - this.tenant.inclusionResolver, - ); - - this.credentials = this.createHasOneRepositoryFactoryFor( - 'credentials', - getUserCredsRepository, - ); - this.registerInclusionResolver( - 'credentials', - this.credentials.inclusionResolver, - ); - } - - async create(entity: DataObject, options?: Options): Promise { - const user = await super.create(entity, options); - try { - // Add temporary password for first time - const password = (await bcrypt.hash( - process.env.USER_TEMP_PASSWORD as string, - saltRounds, - )) as string; - const creds = new UserCredentials({ - authProvider: 'internal', - password, - }); - await this.credentials(user.id).create(creds); - } catch (err) { - throw new HttpErrors.UnprocessableEntity('Error while hashing password'); - } - return user; - } - - async createWithoutPassword( - entity: DataObject, - options?: Options, - ): Promise { - return super.create(entity, options); - } - - async verifyPassword(username: string, password: string): Promise { - const user = await super.findOne({ - where: {username: username.toLowerCase()}, - }); - const creds = user && (await this.credentials(user.id).get()); - if (!user || user.deleted) { - throw new HttpErrors.Unauthorized(AuthenticateErrorKeys.UserDoesNotExist); - } else if ( - !creds?.password || - creds.authProvider !== AuthProvider.INTERNAL || - !(await bcrypt.compare(password, creds.password)) - ) { - this.logger.error('User creds not found in DB or is invalid'); - throw new HttpErrors.Unauthorized(AuthErrorKeys.InvalidCredentials); - } else { - return user; - } - } - - async updatePassword( - username: string, - password: string, - newPassword: string, - ): Promise { - const user = await super.findOne({where: {username}}); - const creds = user && (await this.credentials(user.id).get()); - // eslint-disable-next-line - if (!user || user.deleted || !creds?.password) { - throw new HttpErrors.Unauthorized(AuthenticateErrorKeys.UserDoesNotExist); - } else if (creds.authProvider !== AuthProvider.INTERNAL) { - throw new HttpErrors.BadRequest( - AuthenticateErrorKeys.PasswordCannotBeChanged, - ); - } else if (!(await bcrypt.compare(password, creds.password))) { - throw new HttpErrors.Unauthorized(AuthErrorKeys.WrongPassword); - } else if (await bcrypt.compare(newPassword, creds.password)) { - throw new HttpErrors.Unauthorized( - 'Password cannot be same as previous password!', - ); - } else { - // Do nothing - } - await this.credentials(user.id).patch({ - password: await bcrypt.hash(newPassword, saltRounds), - }); - return user; - } - - async changePassword( - username: string, - newPassword: string, - oldPassword?: string, - ): Promise { - const user = await super.findOne({where: {username}}); - const creds = user && (await this.credentials(user.id).get()); - - if (oldPassword) { - // This method considers old password as OTP - const otp = await (await this.getOtpRepository()).get(username); - if (!otp || otp.otp !== oldPassword) { - throw new HttpErrors.Unauthorized(AuthErrorKeys.WrongPassword); - } - } - - if (creds?.authProvider !== AuthProvider.INTERNAL) { - throw new HttpErrors.Unauthorized( - AuthenticateErrorKeys.PasswordCannotBeChanged, - ); - } - // eslint-disable-next-line - if (!user || user.deleted || !creds?.password) { - throw new HttpErrors.Unauthorized(AuthenticateErrorKeys.UserDoesNotExist); - } else if (await bcrypt.compare(newPassword, creds.password)) { - throw new HttpErrors.Unauthorized( - 'Password cannot be same as previous password!', - ); - } else { - // DO nothing - } - await this.credentials(user.id).patch({ - password: await bcrypt.hash(newPassword, saltRounds), - }); - return user; - } - - async updateLastLogin(userId: string): Promise { - await super.updateById( - userId, - { - lastLogin: Date.now(), - }, - { - currentUser: {id: userId}, - }, - ); - } - - async firstTimeUser(userId: string): Promise { - const user = await super.findOne({ - where: { - id: userId, - }, - }); - - if (!user) { - throw new HttpErrors.NotFound(AuthenticateErrorKeys.UserDoesNotExist); - } - - const userTenant = await ( - await this.userTenantRepositoryGetter() - ).findOne({ - where: { - userId, - tenantId: user.defaultTenantId, - status: { - inq: [UserStatus.REGISTERED, UserStatus.PASSWORD_CHANGE_NEEDED], - }, - }, - }); - return !!userTenant; - } -} diff --git a/sandbox/oauth-example/src/sequence.ts b/sandbox/oauth-example/src/sequence.ts deleted file mode 100644 index b97f09e3c0..0000000000 --- a/sandbox/oauth-example/src/sequence.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) 2023 Sourcefuse Technologies -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT -import {MiddlewareSequence} from '@loopback/rest'; - -export class MySequence extends MiddlewareSequence {} diff --git a/sandbox/oauth-example/tsconfig.json b/sandbox/oauth-example/tsconfig.json index c7b8e49eac..4d768146e7 100644 --- a/sandbox/oauth-example/tsconfig.json +++ b/sandbox/oauth-example/tsconfig.json @@ -1,9 +1,14 @@ { "$schema": "http://json.schemastore.org/tsconfig", "extends": "@loopback/build/config/tsconfig.common.json", + "experimentalDecorators": true, "compilerOptions": { "outDir": "dist", - "rootDir": "src" + "rootDir": "src", + "composite": true }, - "include": ["src"] -} + "include": [ + "src" + ], + "references": [] +} \ No newline at end of file diff --git a/services/payment-service/openapi.json b/services/payment-service/openapi.json index 778b1dc570..283e7d5473 100644 --- a/services/payment-service/openapi.json +++ b/services/payment-service/openapi.json @@ -2,7 +2,7 @@ "openapi": "3.0.0", "info": { "title": "@sourceloop/payment-service", - "version": "14.2.0", + "version": "15.0.2", "description": "payment microservice", "contact": { "name": "Sourcefuse" diff --git a/services/payment-service/openapi.md b/services/payment-service/openapi.md index 292f1d864f..272ee2b198 100644 --- a/services/payment-service/openapi.md +++ b/services/payment-service/openapi.md @@ -1,5 +1,5 @@ --- -title: "@sourceloop/payment-service v14.2.0" +title: "@sourceloop/payment-service v15.0.2" language_tabs: - javascript: JavaScript - javascript--nodejs: Node.JS @@ -16,7 +16,7 @@ headingLevel: 2 -

@sourceloop/payment-service v14.2.0

+

@sourceloop/payment-service v15.0.2

> Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu. diff --git a/services/reporting-service/openapi.json b/services/reporting-service/openapi.json index b89fcc3a4c..d61d1e8bb1 100644 --- a/services/reporting-service/openapi.json +++ b/services/reporting-service/openapi.json @@ -2,7 +2,7 @@ "openapi": "3.0.0", "info": { "title": "@sourceloop/reporting-service", - "version": "3.1.0", + "version": "4.0.2", "description": "reporting-service.", "contact": { "name": "Sourav Bhargava", diff --git a/services/reporting-service/openapi.md b/services/reporting-service/openapi.md index 590413270a..0b1074df83 100644 --- a/services/reporting-service/openapi.md +++ b/services/reporting-service/openapi.md @@ -1,5 +1,5 @@ --- -title: "@sourceloop/reporting-service v3.1.0" +title: "@sourceloop/reporting-service v4.0.2" language_tabs: - javascript: JavaScript - javascript--nodejs: Node.JS @@ -16,7 +16,7 @@ headingLevel: 2 -

@sourceloop/reporting-service v3.1.0

+

@sourceloop/reporting-service v4.0.2

> Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu. diff --git a/services/user-tenant-service/openapi.json b/services/user-tenant-service/openapi.json index 54af6ca2af..8c71e9f2a5 100644 --- a/services/user-tenant-service/openapi.json +++ b/services/user-tenant-service/openapi.json @@ -2,7 +2,7 @@ "openapi": "3.0.0", "info": { "title": "@sourceloop/user-tenant-service", - "version": "2.3.0", + "version": "3.0.2", "description": "Sourceloop User Tenant Service", "contact": { "name": "SourceFuse" diff --git a/services/user-tenant-service/openapi.md b/services/user-tenant-service/openapi.md index 12abbf13c2..1d34d3b0cc 100644 --- a/services/user-tenant-service/openapi.md +++ b/services/user-tenant-service/openapi.md @@ -1,5 +1,5 @@ --- -title: "@sourceloop/user-tenant-service v2.3.0" +title: "@sourceloop/user-tenant-service v3.0.2" language_tabs: - javascript: JavaScript - javascript--nodejs: Node.JS @@ -16,7 +16,7 @@ headingLevel: 2 -

@sourceloop/user-tenant-service v2.3.0

+

@sourceloop/user-tenant-service v3.0.2

> Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.