From f1501cccc4e3a620cf13ac88ce7588c8ef5e4cb7 Mon Sep 17 00:00:00 2001 From: kushalshit27 <43465488+kushalshit27@users.noreply.github.com> Date: Fri, 2 May 2025 17:57:32 +0530 Subject: [PATCH 1/5] feat: add token quota schema for client credentials in clients and organizations --- src/tools/auth0/handlers/clients.ts | 25 +++++++++++++++++++++++ src/tools/auth0/handlers/organizations.ts | 25 +++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/src/tools/auth0/handlers/clients.ts b/src/tools/auth0/handlers/clients.ts index 9f685127..ab17447f 100644 --- a/src/tools/auth0/handlers/clients.ts +++ b/src/tools/auth0/handlers/clients.ts @@ -53,6 +53,31 @@ export const schema = { }, }, }, + token_quota: { + type: 'object', + properties: { + client_credentials: { + type: 'object', + properties: { + enforce: { + type: 'boolean', + default: true, + }, + per_day: { + type: 'integer', + minimum: 1, + }, + per_hour: { + type: 'integer', + minimum: 1, + }, + }, + additionalProperties: false, + minProperties: 1, + }, + }, + required: ['client_credentials'], + }, }, required: ['name'], }, diff --git a/src/tools/auth0/handlers/organizations.ts b/src/tools/auth0/handlers/organizations.ts index cd241657..c0d47fd0 100644 --- a/src/tools/auth0/handlers/organizations.ts +++ b/src/tools/auth0/handlers/organizations.ts @@ -45,6 +45,31 @@ export const schema = { }, default: [], }, + token_quota: { + type: 'object', + properties: { + client_credentials: { + type: 'object', + properties: { + enforce: { + type: 'boolean', + default: true, + }, + per_day: { + type: 'integer', + minimum: 1, + }, + per_hour: { + type: 'integer', + minimum: 1, + }, + }, + additionalProperties: false, + minProperties: 1, + }, + }, + required: ['client_credentials'], + }, }, required: ['name'], }, From b125b812648a4e57ab523da64c68c7d15e338d55 Mon Sep 17 00:00:00 2001 From: kushalshit27 <43465488+kushalshit27@users.noreply.github.com> Date: Fri, 2 May 2025 18:15:30 +0530 Subject: [PATCH 2/5] feat: add token quota configuration schema for clients and organizations --- src/tools/auth0/handlers/tenant.ts | 37 ++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/tools/auth0/handlers/tenant.ts b/src/tools/auth0/handlers/tenant.ts index e8b61919..6a537b0e 100644 --- a/src/tools/auth0/handlers/tenant.ts +++ b/src/tools/auth0/handlers/tenant.ts @@ -11,8 +11,45 @@ import { convertJsonToString } from '../../utils'; import { Asset, Assets } from '../../../types'; import log from '../../../logger'; +const tokenQuotaConfigurationSchema = { + type: 'object', + properties: { + client_credentials: { + type: 'object', + properties: { + enforce: { + type: 'boolean', + default: true, + }, + per_day: { + type: 'integer', + minimum: 1, + }, + per_hour: { + type: 'integer', + minimum: 1, + }, + }, + additionalProperties: false, + minProperties: 1, + }, + }, + required: ['client_credentials'], +}; + export const schema = { type: 'object', + properties: { + default_token_quota: { + type: 'object', + properties: { + clients: tokenQuotaConfigurationSchema, + organizations: tokenQuotaConfigurationSchema, + }, + additionalProperties: false, + minProperties: 1, + }, + }, }; export type Tenant = TenantSettings; From 1afb0b3349b719cead69bcb0d9c400c5e75f8a90 Mon Sep 17 00:00:00 2001 From: kushalshit27 <43465488+kushalshit27@users.noreply.github.com> Date: Mon, 5 May 2025 16:14:51 +0530 Subject: [PATCH 3/5] feat: allow token quota to be null in clients and organizations schemas --- src/tools/auth0/handlers/clients.ts | 2 +- src/tools/auth0/handlers/organizations.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/auth0/handlers/clients.ts b/src/tools/auth0/handlers/clients.ts index ab17447f..57a5ed93 100644 --- a/src/tools/auth0/handlers/clients.ts +++ b/src/tools/auth0/handlers/clients.ts @@ -54,7 +54,7 @@ export const schema = { }, }, token_quota: { - type: 'object', + type: ['object', 'null'], properties: { client_credentials: { type: 'object', diff --git a/src/tools/auth0/handlers/organizations.ts b/src/tools/auth0/handlers/organizations.ts index c0d47fd0..508b42a1 100644 --- a/src/tools/auth0/handlers/organizations.ts +++ b/src/tools/auth0/handlers/organizations.ts @@ -46,7 +46,7 @@ export const schema = { default: [], }, token_quota: { - type: 'object', + type: ['object', 'null'], properties: { client_credentials: { type: 'object', From f4d0df3f3a45380a4b3fd3335b5fdd4243f066b9 Mon Sep 17 00:00:00 2001 From: kushalshit27 <43465488+kushalshit27@users.noreply.github.com> Date: Tue, 13 May 2025 10:20:44 +0530 Subject: [PATCH 4/5] test: add token_quota property validation for clients, organizations, and tenants --- test/tools/auth0/handlers/clients.tests.js | 40 ++++++++++++++ .../auth0/handlers/organizations.tests.js | 52 ++++++++++++++++++ test/tools/auth0/handlers/tenant.tests.ts | 54 +++++++++++++++++++ 3 files changed, 146 insertions(+) diff --git a/test/tools/auth0/handlers/clients.tests.js b/test/tools/auth0/handlers/clients.tests.js index 29b6da62..11817318 100644 --- a/test/tools/auth0/handlers/clients.tests.js +++ b/test/tools/auth0/handlers/clients.tests.js @@ -184,6 +184,46 @@ describe('#clients handler', () => { await stageFn.apply(handler, [{ clients: [clientWithRefreshTokenPolicies] }]); }); + it('should allow valid token_quota property in client', async () => { + const clientWithTokenQuota = { + name: 'clientWithTokenQuota', + token_quota: { + client_credentials: { + enforce: true, + per_day: 1000, + per_hour: 100, + }, + }, + }; + let wasCreateCalled = false; + const auth0 = { + clients: { + create: function (data) { + wasCreateCalled = true; + expect(data).to.be.an('object'); + expect(data.name).to.equal('clientWithTokenQuota'); + expect(data.token_quota).to.deep.equal({ + client_credentials: { + enforce: true, + per_day: 1000, + per_hour: 100, + }, + }); + return Promise.resolve({ data }); + }, + update: () => Promise.resolve({ data: [] }), + delete: () => Promise.resolve({ data: [] }), + getAll: (params) => mockPagedData(params, 'clients', []), + }, + pool, + }; + const handler = new clients.default({ client: pageClient(auth0), config }); + const stageFn = Object.getPrototypeOf(handler).processChanges; + await stageFn.apply(handler, [{ clients: [clientWithTokenQuota] }]); + // eslint-disable-next-line no-unused-expressions + expect(wasCreateCalled).to.be.true; + }); + it('should get clients', async () => { const auth0 = { clients: { diff --git a/test/tools/auth0/handlers/organizations.tests.js b/test/tools/auth0/handlers/organizations.tests.js index 8d3dd417..66270b05 100644 --- a/test/tools/auth0/handlers/organizations.tests.js +++ b/test/tools/auth0/handlers/organizations.tests.js @@ -218,6 +218,58 @@ describe('#organizations handler', () => { ]); }); + it('should allow valid token_quota property in organization', async () => { + const orgWithTokenQuota = { + name: 'orgWithTokenQuota', + token_quota: { + client_credentials: { + enforce: false, + per_day: 500, + per_hour: 50, + }, + }, + }; + let wasCreateCalled = false; + const auth0 = { + organizations: { + create: function (data) { + wasCreateCalled = true; + expect(data).to.be.an('object'); + expect(data.name).to.equal('orgWithTokenQuota'); + expect(data.token_quota).to.deep.equal({ + client_credentials: { + enforce: false, + per_day: 500, + per_hour: 50, + }, + }); + data.id = 'fake'; + return Promise.resolve({ data }); + }, + update: () => Promise.resolve({ data: [] }), + delete: () => Promise.resolve({ data: [] }), + getAll: (params) => Promise.resolve(mockPagedData(params, 'organizations', [sampleOrg])), + getEnabledConnections: () => Promise.resolve({ data: [] }), + getOrganizationClientGrants: () => ({ data: [] }), + }, + connections: { + getAll: (params) => mockPagedData(params, 'connections', []), + }, + clients: { + getAll: (params) => mockPagedData(params, 'clients', sampleClients), + }, + clientGrants: { + getAll: (params) => mockPagedData(params, 'client_grants', [sampleClientGrant]), + }, + pool, + }; + const handler = new organizations.default({ client: pageClient(auth0), config }); + const stageFn = Object.getPrototypeOf(handler).processChanges; + await stageFn.apply(handler, [{ organizations: [orgWithTokenQuota] }]); + // eslint-disable-next-line no-unused-expressions + expect(wasCreateCalled).to.be.true; + }); + it('should get organizations', async () => { const auth0 = { organizations: { diff --git a/test/tools/auth0/handlers/tenant.tests.ts b/test/tools/auth0/handlers/tenant.tests.ts index 4bedb3d3..8d027905 100644 --- a/test/tools/auth0/handlers/tenant.tests.ts +++ b/test/tools/auth0/handlers/tenant.tests.ts @@ -83,6 +83,60 @@ describe('#tenant handler', () => { await stageFn.apply(handler, [{ tenant: { sandbox_version: '4' } }]); }); + it('should allow valid default_token_quota property in tenant', async () => { + const tenantWithDefaultTokenQuota = { + default_token_quota: { + clients: { + client_credentials: { + enforce: true, + per_day: 2000, + per_hour: 200, + }, + }, + organizations: { + client_credentials: { + enforce: false, + per_day: 1000, + per_hour: 100, + }, + }, + }, + }; + let wasUpdateCalled = false; + const auth0 = { + tenants: { + getSettings: () => ({ data: {} }), + updateSettings: function (data) { + wasUpdateCalled = true; + expect(data).to.be.an('object'); + expect(data.default_token_quota).to.deep.equal({ + clients: { + client_credentials: { + enforce: true, + per_day: 2000, + per_hour: 200, + }, + }, + organizations: { + client_credentials: { + enforce: false, + per_day: 1000, + per_hour: 100, + }, + }, + }); + return Promise.resolve(data); + }, + }, + }; + // @ts-ignore + const handler = new tenantHandler({ client: auth0 }); + const stageFn = Object.getPrototypeOf(handler).processChanges; + await stageFn.apply(handler, [{ tenant: tenantWithDefaultTokenQuota }]); + // eslint-disable-next-line no-unused-expressions + expect(wasUpdateCalled).to.be.true; + }); + describe('filtering-out unallowed tenant flags', async () => { it('should filter-out unallowed tenant flags', async () => { const proposedFlags = { From fc49e714157ffaddeb4f9af3a227ebceb2d1c0f5 Mon Sep 17 00:00:00 2001 From: kushalshit27 <43465488+kushalshit27@users.noreply.github.com> Date: Tue, 3 Jun 2025 19:25:12 +0530 Subject: [PATCH 5/5] chore: update dependencies to latest versions --- package-lock.json | 43 ++++++++++++++++++++++--------------------- package.json | 6 +++--- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0c7246f8..ffff3382 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "MIT", "dependencies": { "ajv": "^6.12.6", - "auth0": "^4.23.1", + "auth0": "^4.24.0", "dot-prop": "^5.3.0", "fs-extra": "^10.1.0", "js-yaml": "^4.1.0", @@ -19,7 +19,7 @@ "nconf": "^0.13.0", "promise-pool-executor": "^1.1.1", "sanitize-filename": "^1.6.3", - "undici": "^7.8.0", + "undici": "^7.10.0", "winston": "^3.17.0", "yargs": "^15.4.1" }, @@ -28,7 +28,7 @@ }, "devDependencies": { "@types/fs-extra": "^9.0.13", - "@types/lodash": "^4.17.16", + "@types/lodash": "^4.17.17", "@types/mocha": "^10.0.10", "@types/nconf": "^0.10.7", "@typescript-eslint/parser": "^5.62.0", @@ -945,9 +945,9 @@ "dev": true }, "node_modules/@types/lodash": { - "version": "4.17.16", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.16.tgz", - "integrity": "sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==", + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.17.tgz", + "integrity": "sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ==", "dev": true, "license": "MIT" }, @@ -1340,9 +1340,10 @@ "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" }, "node_modules/auth0": { - "version": "4.23.1", - "resolved": "https://registry.npmjs.org/auth0/-/auth0-4.23.1.tgz", - "integrity": "sha512-Kx7T4eDZXzUZwS2MqX5N+vO72AbWIepT7cXyIbcFuiFn5VjQMhs70N+Yihc9YUv24JODyBOdzZkM8yW2x5stLw==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/auth0/-/auth0-4.24.0.tgz", + "integrity": "sha512-LkJgQnibsREKC3LsjIZ/HuetIuHNOHdT+rI9ukt7MZOLwyNq2XW6zSnByKdjmPt9sf+w8oH8MIySlQBiUCL3Sw==", + "license": "MIT", "dependencies": { "jose": "^4.13.2", "undici-types": "^6.15.0", @@ -6031,9 +6032,9 @@ } }, "node_modules/undici": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.8.0.tgz", - "integrity": "sha512-vFv1GA99b7eKO1HG/4RPu2Is3FBTWBrmzqzO0mz+rLxN3yXkE4mqRcb8g8fHxzX4blEysrNZLqg5RbJLqX5buA==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.10.0.tgz", + "integrity": "sha512-u5otvFBOBZvmdjWLVW+5DAc9Nkq8f24g0O9oY7qw2JVIF1VocIFoyz9JFkuVOS2j41AufeO0xnlweJ2RLT8nGw==", "license": "MIT", "engines": { "node": ">=20.18.1" @@ -7156,9 +7157,9 @@ "dev": true }, "@types/lodash": { - "version": "4.17.16", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.16.tgz", - "integrity": "sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==", + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.17.tgz", + "integrity": "sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ==", "dev": true }, "@types/mocha": { @@ -7422,9 +7423,9 @@ "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" }, "auth0": { - "version": "4.23.1", - "resolved": "https://registry.npmjs.org/auth0/-/auth0-4.23.1.tgz", - "integrity": "sha512-Kx7T4eDZXzUZwS2MqX5N+vO72AbWIepT7cXyIbcFuiFn5VjQMhs70N+Yihc9YUv24JODyBOdzZkM8yW2x5stLw==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/auth0/-/auth0-4.24.0.tgz", + "integrity": "sha512-LkJgQnibsREKC3LsjIZ/HuetIuHNOHdT+rI9ukt7MZOLwyNq2XW6zSnByKdjmPt9sf+w8oH8MIySlQBiUCL3Sw==", "requires": { "jose": "^4.13.2", "undici-types": "^6.15.0", @@ -10847,9 +10848,9 @@ } }, "undici": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.8.0.tgz", - "integrity": "sha512-vFv1GA99b7eKO1HG/4RPu2Is3FBTWBrmzqzO0mz+rLxN3yXkE4mqRcb8g8fHxzX4blEysrNZLqg5RbJLqX5buA==" + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.10.0.tgz", + "integrity": "sha512-u5otvFBOBZvmdjWLVW+5DAc9Nkq8f24g0O9oY7qw2JVIF1VocIFoyz9JFkuVOS2j41AufeO0xnlweJ2RLT8nGw==" }, "undici-types": { "version": "6.19.4", diff --git a/package.json b/package.json index 0c7df4de..12ebee0c 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "homepage": "https://github.com/auth0/auth0-deploy-cli#readme", "dependencies": { "ajv": "^6.12.6", - "auth0": "^4.23.1", + "auth0": "^4.24.0", "dot-prop": "^5.3.0", "fs-extra": "^10.1.0", "js-yaml": "^4.1.0", @@ -42,13 +42,13 @@ "nconf": "^0.13.0", "promise-pool-executor": "^1.1.1", "sanitize-filename": "^1.6.3", - "undici": "^7.8.0", + "undici": "^7.10.0", "winston": "^3.17.0", "yargs": "^15.4.1" }, "devDependencies": { "@types/fs-extra": "^9.0.13", - "@types/lodash": "^4.17.16", + "@types/lodash": "^4.17.17", "@types/mocha": "^10.0.10", "@types/nconf": "^0.10.7", "@typescript-eslint/parser": "^5.62.0",