From 55ff41e29b373f3a63228e67d5739879a913e22e Mon Sep 17 00:00:00 2001 From: wangsijie Date: Tue, 9 Jul 2024 16:20:55 +0800 Subject: [PATCH] feat(core): add quota guard for subject tokens (#6205) --- packages/core/package.json | 2 +- packages/core/src/libraries/quota.ts | 1 + packages/core/src/routes/security/index.ts | 10 +- pnpm-lock.yaml | 183 ++++++++++++++------- 4 files changed, 133 insertions(+), 63 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index dcbb5c5b3..ad3556771 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -93,7 +93,7 @@ "zod": "^3.22.4" }, "devDependencies": { - "@logto/cloud": "0.2.5-a7eedce", + "@logto/cloud": "0.2.5-3046fa6", "@silverhand/eslint-config": "6.0.1", "@silverhand/ts-config": "6.0.0", "@types/debug": "^4.1.7", diff --git a/packages/core/src/libraries/quota.ts b/packages/core/src/libraries/quota.ts index 6ac9e26c8..a1030cf85 100644 --- a/packages/core/src/libraries/quota.ts +++ b/packages/core/src/libraries/quota.ts @@ -73,6 +73,7 @@ export const createQuotaLibrary = ( omniSignInEnabled: notNumber, // No limit for now builtInEmailConnectorEnabled: notNumber, // No limit for now customJwtEnabled: notNumber, // No limit for now + subjectTokenEnabled: notNumber, // No limit for now }; const getTenantUsage = async (key: keyof FeatureQuota, queryKey?: string): Promise => { diff --git a/packages/core/src/routes/security/index.ts b/packages/core/src/routes/security/index.ts index 13fc457d5..45440dc87 100644 --- a/packages/core/src/routes/security/index.ts +++ b/packages/core/src/routes/security/index.ts @@ -6,11 +6,18 @@ import { object, string } from 'zod'; import { subjectTokenExpiresIn, subjectTokenPrefix } from '#src/constants/index.js'; import { EnvSet } from '#src/env-set/index.js'; import koaGuard from '#src/middleware/koa-guard.js'; +import koaQuotaGuard from '#src/middleware/koa-quota-guard.js'; import { type RouterInitArgs, type ManagementApiRouter } from '../types.js'; export default function securityRoutes(...args: RouterInitArgs) { - const [router, { queries }] = args; + const [ + router, + { + queries, + libraries: { quota }, + }, + ] = args; const { subjectTokens: { insertSubjectToken }, } = queries; @@ -21,6 +28,7 @@ export default function securityRoutes(...args: R router.post( '/security/subject-tokens', + koaQuotaGuard({ key: 'subjectTokenEnabled', quota }), koaGuard({ body: object({ userId: string(), diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3dcabfaed..095450077 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3357,8 +3357,8 @@ importers: version: 3.22.4 devDependencies: '@logto/cloud': - specifier: 0.2.5-a7eedce - version: 0.2.5-a7eedce(zod@3.22.4) + specifier: 0.2.5-3046fa6 + version: 0.2.5-3046fa6(zod@3.22.4) '@silverhand/eslint-config': specifier: 6.0.1 version: 6.0.1(eslint@8.57.0)(prettier@3.0.0)(typescript@5.3.3) @@ -3421,7 +3421,7 @@ importers: version: 8.57.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.10.4) + version: 29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@types/node@20.10.4)(typescript@5.3.3)) jest-matcher-specific-error: specifier: ^1.0.0 version: 1.0.0 @@ -3676,7 +3676,7 @@ importers: version: 3.0.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.12.7) + version: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.12.7)(typescript@5.3.3)) jest-environment-jsdom: specifier: ^29.7.0 version: 29.7.0 @@ -3685,7 +3685,7 @@ importers: version: 2.0.0 jest-transformer-svg: specifier: ^2.0.0 - version: 2.0.0(jest@29.7.0(@types/node@20.12.7))(react@18.2.0) + version: 2.0.0(jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.12.7)(typescript@5.3.3)))(react@18.2.0) js-base64: specifier: ^3.7.5 version: 3.7.5 @@ -3824,7 +3824,7 @@ importers: version: 10.0.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.10.4) + version: 29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@types/node@20.10.4)(typescript@5.3.3)) jest-matcher-specific-error: specifier: ^1.0.0 version: 1.0.0 @@ -5240,6 +5240,10 @@ packages: '@logto/client@2.7.2': resolution: {integrity: sha512-jsmuDl9QpXfR3uLEMPE67tvYoL5XcjJi+4yGqucYPjd4GH6SUHp3N9skk8C/OyygnKDPLY+ttwD0LaIbpGvn+Q==} + '@logto/cloud@0.2.5-3046fa6': + resolution: {integrity: sha512-Q/UrDDUOIq3fIogArVLdWkaKVcalLrDyLF2UDEjr1WZ5+9GqyV3MVmG3KljxnRujamKK0bnQF+QAFAJTQJJUMg==} + engines: {node: ^20.9.0} + '@logto/cloud@0.2.5-a7eedce': resolution: {integrity: sha512-FFjkGjqUgn9PCZnSuCODm2FcjqBm4JfPxfHCiXlOkUjeUhTJLrj7C0gjKzSQ/B6IaWri4EXN/meuqi5z/AMIPg==} engines: {node: ^20.9.0} @@ -14637,6 +14641,41 @@ snapshots: - supports-color - ts-node + '@jest/core@29.7.0(ts-node@10.9.2(@types/node@20.10.4)(typescript@5.3.3))': + dependencies: + '@jest/console': 29.7.0 + '@jest/reporters': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.12.7 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.8.0 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 29.7.0 + jest-config: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@types/node@20.10.4)(typescript@5.3.3)) + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-resolve-dependencies: 29.7.0 + jest-runner: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + jest-watcher: 29.7.0 + micromatch: 4.0.5 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + - ts-node + '@jest/create-cache-key-function@27.5.1': dependencies: '@jest/types': 27.5.1 @@ -14896,6 +14935,13 @@ snapshots: camelcase-keys: 7.0.2 jose: 5.2.4 + '@logto/cloud@0.2.5-3046fa6(zod@3.22.4)': + dependencies: + '@silverhand/essentials': 2.9.1 + '@withtyped/server': 0.13.6(zod@3.22.4) + transitivePeerDependencies: + - zod + '@logto/cloud@0.2.5-a7eedce(zod@3.22.4)': dependencies: '@silverhand/essentials': 2.9.1 @@ -15958,10 +16004,10 @@ snapshots: eslint-config-prettier: 9.1.0(eslint@8.57.0) eslint-config-xo: 0.44.0(eslint@8.57.0) eslint-config-xo-typescript: 4.0.0(@typescript-eslint/eslint-plugin@7.7.0(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0)(typescript@5.3.3))(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0)(typescript@5.3.3) - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0))(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0) eslint-plugin-consistent-default-export-name: 0.0.15 eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) eslint-plugin-n: 17.2.1(eslint@8.57.0) eslint-plugin-no-use-extend-native: 0.5.0 eslint-plugin-prettier: 5.1.3(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.0.0) @@ -17990,13 +18036,13 @@ snapshots: dependencies: lodash.get: 4.4.2 - create-jest@29.7.0(@types/node@20.10.4): + create-jest@29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@types/node@20.10.4)(typescript@5.3.3)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.10.4) + jest-config: 29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@types/node@20.10.4)(typescript@5.3.3)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -18802,13 +18848,13 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0))(eslint@8.57.0): + eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0): dependencies: debug: 4.3.4 enhanced-resolve: 5.16.0 eslint: 8.57.0 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.7.3 is-core-module: 2.13.1 @@ -18819,14 +18865,14 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.8.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): + eslint-module-utils@2.8.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0): dependencies: debug: 3.2.7(supports-color@5.5.0) optionalDependencies: '@typescript-eslint/parser': 7.7.0(eslint@8.57.0)(typescript@5.3.3) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0))(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0) transitivePeerDependencies: - supports-color @@ -18848,7 +18894,7 @@ snapshots: eslint: 8.57.0 ignore: 5.3.1 - eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): + eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): dependencies: array-includes: 3.1.8 array.prototype.findlastindex: 1.2.5 @@ -18858,7 +18904,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.3.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) hasown: 2.0.2 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -20333,35 +20379,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@20.10.4): + jest-cli@29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@types/node@20.10.4)(typescript@5.3.3)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.12.7)(typescript@5.3.3)) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.10.4)(typescript@5.3.3)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.10.4) + create-jest: 29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@types/node@20.10.4)(typescript@5.3.3)) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.10.4) - jest-util: 29.7.0 - jest-validate: 29.7.0 - yargs: 17.7.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - - jest-cli@29.7.0(@types/node@20.12.7): - dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.12.7)(typescript@5.3.3)) - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.12.7)(typescript@5.3.3)) - exit: 0.1.2 - import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.12.7)(typescript@5.3.3)) + jest-config: 29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@types/node@20.10.4)(typescript@5.3.3)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -20390,7 +20417,7 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@20.10.4): + jest-config@29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@types/node@20.10.4)(typescript@5.3.3)): dependencies: '@babel/core': 7.24.4 '@jest/test-sequencer': 29.7.0 @@ -20416,6 +20443,7 @@ snapshots: strip-json-comments: 3.1.1 optionalDependencies: '@types/node': 20.10.4 + ts-node: 10.9.2(@types/node@20.10.4)(typescript@5.3.3) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -20451,6 +20479,37 @@ snapshots: - babel-plugin-macros - supports-color + jest-config@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@types/node@20.10.4)(typescript@5.3.3)): + dependencies: + '@babel/core': 7.24.4 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.24.4) + chalk: 4.1.2 + ci-info: 3.8.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0 + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.5 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 20.12.7 + ts-node: 10.9.2(@types/node@20.10.4)(typescript@5.3.3) + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + jest-dev-server@10.0.0: dependencies: chalk: 4.1.2 @@ -20707,11 +20766,6 @@ snapshots: jest: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.12.7)(typescript@5.3.3)) react: 18.2.0 - jest-transformer-svg@2.0.0(jest@29.7.0(@types/node@20.12.7))(react@18.2.0): - dependencies: - jest: 29.7.0(@types/node@20.12.7) - react: 18.2.0 - jest-util@29.5.0: dependencies: '@jest/types': 29.6.3 @@ -20764,24 +20818,12 @@ snapshots: merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@20.10.4): + jest@29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@types/node@20.10.4)(typescript@5.3.3)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.12.7)(typescript@5.3.3)) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.10.4)(typescript@5.3.3)) '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@20.10.4) - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - - jest@29.7.0(@types/node@20.12.7): - dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.12.7)(typescript@5.3.3)) - '@jest/types': 29.6.3 - import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@20.12.7) + jest-cli: 29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@types/node@20.10.4)(typescript@5.3.3)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -24292,6 +24334,25 @@ snapshots: optionalDependencies: '@swc/core': 1.3.52(@swc/helpers@0.5.1) + ts-node@10.9.2(@types/node@20.10.4)(typescript@5.3.3): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.9 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 20.10.4 + acorn: 8.10.0 + acorn-walk: 8.2.0 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.3.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + optional: true + tsconfig-paths@3.15.0: dependencies: '@types/json5': 0.0.29