From 4f6c11d05d02936159b79473172fd1436038df37 Mon Sep 17 00:00:00 2001 From: Simon Scherzinger Date: Thu, 23 May 2024 14:47:15 +0200 Subject: [PATCH 1/2] feat: nativePermissions support in GroupResource and AccountResource BREAKING CHANGE: This commit adds support for nativePermissions property. The setter for previously used permissions property has been removed. before: ```js const account = await api.account(id); account.permissions = generateNewPermissionArray(); ``` after: ```js const account = await api.account(id); account.nativePermissions = generateNewPermissionArray(); ``` --- src/resources/accounts/AccountResource.ts | 77 ++++++++++++++++++----- src/resources/accounts/GroupResource.ts | 33 +++++++--- test/accounts/Account.test.js | 10 +-- test/accounts/GroupResource.test.js | 18 +++--- test/apps/Apps.test.js | 19 ------ test/mocks/account-list.json | 24 ++++++- test/mocks/account-single.json | 12 +++- test/mocks/group-list.json | 4 ++ test/mocks/group-single.json | 2 + 9 files changed, 138 insertions(+), 61 deletions(-) diff --git a/src/resources/accounts/AccountResource.ts b/src/resources/accounts/AccountResource.ts index 26e61c8e..e695217d 100644 --- a/src/resources/accounts/AccountResource.ts +++ b/src/resources/accounts/AccountResource.ts @@ -4,17 +4,18 @@ import Resource from '../Resource'; import TokenList from './TokenList'; import { environment } from '../../Core'; import TokenResource from './TokenResource'; +// eslint-disable-next-line import/no-cycle import { tokenResponse } from '../../Accounts'; import { post } from '../../helper'; const relationsSymbol: any = Symbol.for('relations'); const environmentSymbol: any = Symbol.for('environment'); -export type accountType = 'Person' | 'Client' | 'API Key'; +export type AccountType = 'Person' | 'Client' | 'API Key'; interface AccountResource { accountID: string; - type: accountType | null; + type: AccountType | null; created: Date; email: string; name: string; @@ -51,6 +52,7 @@ interface AccountResource { legacyLoginDisabled: boolean; openID: Array; permissions: Array; + nativePermissions: Array; groups: Array; lastLogin: Date; } @@ -96,7 +98,8 @@ interface AccountResource { * @prop {boolean} legacyLoginDisabled - Whether or not this account has legacy login disabled * @prop {Array<{sub: string, iss: string, pending: boolean, email: string, name: string}>} * openID - Array of connected openID accounts - * @prop {Array} permissions - Array of permissions + * @prop {Array} permissions - Array of all permissions + * @prop {Array} nativePermissions - Array of native permissions * @prop {Array} groups - Array of groups this account is member of * @prop {Date} lastLogin - The {@link Date} on which this account was last logged in */ @@ -313,8 +316,18 @@ class AccountResource extends Resource { permissions: { enumerable: true, get: () => >this.getProperty('permissions'), - set: (value) => { - this.setProperty('permissions', value); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + set: (_value: Array) => { + console.warn( + 'set on AccountResource#permissions is deprecated. Use AccountResource#nativePermissions instead.', + ); + }, + }, + nativePermissions: { + enumerable: true, + get: () => >this.getProperty('nativePermissions'), + set: (value: Array) => { + this.setProperty('nativePermissions', value); return value; }, }, @@ -341,10 +354,7 @@ class AccountResource extends Resource { throw new Error('permission must be defined'); } - const current = this.permissions; - current.push(value); - this.permissions = current; - return this; + return this.addPermissions([value]); } /** @@ -358,9 +368,40 @@ class AccountResource extends Resource { throw new Error('permission must be defined'); } - let current = this.permissions; + let current = this.nativePermissions; current = current.concat(value); - this.permissions = current; + this.nativePermissions = current; + return this; + } + + /** + * Remove a single permission from this account. + * + * @param {string} value the permission to remove + * @returns {AccountResource} returns this account resource + */ + removePermission(value: string): AccountResource { + if (!value) { + throw new Error('permission must be defined'); + } + + return this.removePermissions([value]); + } + + /** + * Remove multiple permissions from this account. + * + * @param {Array} value the permissions to remove + * @returns {AccountResource} returns this account resource + */ + removePermissions(value: Array) { + if (!value || !Array.isArray(value)) { + throw new Error('permission must be defined and an array'); + } + + let current = this.nativePermissions; + current = current.filter((permission) => value.indexOf(permission) !== -1); + this.nativePermissions = current; return this; } @@ -375,8 +416,9 @@ class AccountResource extends Resource { throw new Error('permission must be defined'); } + // eslint-disable-next-line @typescript-eslint/dot-notation const trie = ShiroTrie['new'](); - trie.add(this.getAllPermissions()); + trie.add(this.permissions); return trie.check(permission); } @@ -392,8 +434,9 @@ class AccountResource extends Resource { throw new Error('query musst be defined'); } + // eslint-disable-next-line @typescript-eslint/dot-notation const trie = ShiroTrie['new'](); - trie.add(this.getAllPermissions()); + trie.add(this.permissions); return trie.permissions(query); } @@ -402,12 +445,12 @@ class AccountResource extends Resource { * Returns an array of all permissions of this account. The array will contain the account * permissions and all group permissions. * + * @deprecated Since Account Server 1.2.0 this is the same as {@link AccountResource#permissions} + * * @returns {array} All permissions. */ getAllPermissions(): Array { - return (this.groups ? this.groups : [{ permissions: [] }]) - .map((g) => g.permissions) - .reduce((all, current) => all.concat(current), this.permissions); + return this.permissions; } /** @@ -439,7 +482,7 @@ class AccountResource extends Resource { } return this.follow('ec:account/tokens') .then((request) => post(this[environmentSymbol], request)) - .then(([tokenResponse]) => tokenResponse); + .then(([r]) => r); } /** diff --git a/src/resources/accounts/GroupResource.ts b/src/resources/accounts/GroupResource.ts index aec5cbd8..8d361471 100644 --- a/src/resources/accounts/GroupResource.ts +++ b/src/resources/accounts/GroupResource.ts @@ -1,7 +1,7 @@ +import * as validate from 'validator'; + import Resource from '../Resource'; import { environment } from '../../Core'; -import * as validate from 'validator'; -import { isRegExp } from 'util'; const resourceSymbol: any = Symbol.for('resource'); @@ -9,6 +9,8 @@ interface GroupResource { groupID: string; name: string; permissions: Array; + subgroups: Array; + nativePermissions: Array; accounts: Array; customAuthDomain: string | null; customAuthDomainPriority: string | null; @@ -26,7 +28,9 @@ interface GroupResource { * * @prop {string} groupID - The id of the group * @prop {string} name - The group name - * @prop {Array} permissions - Array of permissions + * @prop {Array} permissions - Array of all permissions + * @prop {Array} subgroups - Array of all subgroups + * @prop {Array} nativePermissions - Array of native permissions * @prop {string} customAuthDomain - Domain from wich users in this group receive auth mails * @prop {string} customAuthDomainPriority - Priority of the custom auth domain * @prop {Object} groupSettings - Group settings @@ -56,7 +60,20 @@ class GroupResource extends Resource { permissions: { enumerable: true, get: () => >this.getProperty('permissions'), - set: (value: Array) => this.setProperty('permissions', value), + // eslint-disable-next-line @typescript-eslint/no-unused-vars + set: (_value: Array) => { + console.warn('set on GroupResource#permissions is deprecated. Use GroupResource#nativePermissions instead.'); + }, + }, + nativePermissions: { + enumerable: true, + get: () => >this.getProperty('nativePermissions'), + set: (value: Array) => this.setProperty('nativePermissions', value), + }, + subgroups: { + enumerable: true, + get: () => >this.getProperty('subgroups'), + set: (value: Array) => this.setProperty('subgroups', value), }, accounts: { enumerable: true, @@ -112,9 +129,9 @@ class GroupResource extends Resource { throw new Error('permission must be defined and an array'); } - let current = this.permissions; + let current = this.nativePermissions; current = current.concat(value); - this.permissions = current; + this.nativePermissions = current; return this; } @@ -143,9 +160,9 @@ class GroupResource extends Resource { throw new Error('permission must be defined and an array'); } - let current = this.permissions; + let current = this.nativePermissions; current = current.filter((permission) => value.indexOf(permission) !== -1); - this.permissions = current; + this.nativePermissions = current; return this; } diff --git a/test/accounts/Account.test.js b/test/accounts/Account.test.js index bc127eaf..e0c5a990 100644 --- a/test/accounts/Account.test.js +++ b/test/accounts/Account.test.js @@ -534,18 +534,18 @@ describe('Account Resource', () => { resource.hasPassword.should.be.true; }); it('should add single permission', () => { - resource.permissions.should.have.property('length', 1); + resource.nativePermissions.should.have.property('length', 1); resource.addPermission('acc:something'); - resource.permissions.should.have.property('length', 2); + resource.nativePermissions.should.have.property('length', 2); }); it('should throw on invalid single permission', () => { const throws = () => resource.addPermission(); throws.should.throw(Error); }); it('should add multiple permission', () => { - resource.permissions.should.have.property('length', 1); + resource.nativePermissions.should.have.property('length', 1); resource.addPermissions(['acc:something', 'acc:anything']); - resource.permissions.should.have.property('length', 3); + resource.nativePermissions.should.have.property('length', 3); }); it('should throw on undefined permissions', () => { const throws = () => resource.addPermissions(); @@ -599,7 +599,7 @@ describe('Account Resource', () => { }); }); - const setter = ['name', 'language', 'state', 'openID', 'permissions']; + const setter = ['name', 'language', 'state', 'openID', 'nativePermissions']; setter.forEach((name) => { it(`should call resource.setProperty with ${name}`, () => { const spy = sinon.spy(resource, 'setProperty'); diff --git a/test/accounts/GroupResource.test.js b/test/accounts/GroupResource.test.js index 2215a9f3..e1fb8708 100644 --- a/test/accounts/GroupResource.test.js +++ b/test/accounts/GroupResource.test.js @@ -74,18 +74,18 @@ describe('Group Resource', () => { resource.should.be.instanceOf(GroupResource); }); it('should add single permission', () => { - resource.permissions.should.have.property('length', 2); + resource.nativePermissions.should.have.property('length', 2); resource.addPermission('acc:something'); - resource.permissions.should.have.property('length', 3); + resource.nativePermissions.should.have.property('length', 3); }); it('should throw on undefined permission', () => { const throws = () => resource.addPermission(); throws.should.throw(Error); }); it('should add multiple permission', () => { - resource.permissions.should.have.property('length', 2); + resource.nativePermissions.should.have.property('length', 2); resource.addPermissions(['acc:something', 'acc:anything']); - resource.permissions.should.have.property('length', 4); + resource.nativePermissions.should.have.property('length', 4); }); it('should throw on undefined permissions', () => { const throws = () => resource.addPermissions(); @@ -96,18 +96,18 @@ describe('Group Resource', () => { throws.should.throw(Error); }); it('should remove single permission', () => { - resource.permissions.should.have.property('length', 2); + resource.nativePermissions.should.have.property('length', 2); resource.removePermission('app-create'); - resource.permissions.should.have.property('length', 1); + resource.nativePermissions.should.have.property('length', 1); }); it('should throw on undefined permission', () => { const throws = () => resource.removePermission(); throws.should.throw(Error); }); it('should remove multiple permissions', () => { - resource.permissions.should.have.property('length', 2); + resource.nativePermissions.should.have.property('length', 2); resource.removePermission(['app-create', 'app:codesource,datasource,target,platform']); - resource.permissions.should.have.property('length', 0); + resource.nativePermissions.should.have.property('length', 0); }); it('should throw on undefined permissions', () => { const throws = () => resource.removePermission(); @@ -201,7 +201,7 @@ describe('Group Resource', () => { }); }); - const setter = ['name', 'permissions']; + const setter = ['name', 'nativePermissions']; setter.forEach((name) => { it(`should call resource.setProperty with ${name}`, () => { const spy = sinon.spy(resource, 'setProperty'); diff --git a/test/apps/Apps.test.js b/test/apps/Apps.test.js index 546cfc0e..d8fbf26d 100644 --- a/test/apps/Apps.test.js +++ b/test/apps/Apps.test.js @@ -142,25 +142,6 @@ describe('Apps class', () => { }); }); - it.skip('should load stats list', () => { - // TODO fix SDK-103 - const apps = new Apps('live'); - const stub = sinon.stub(helper, 'get'); - stub.returns(resolver('app-stats-list.json')); - const follow = sinon.stub(apps, 'follow'); - follow.returns(Promise.resolve(apps.newRequest())); - - return apps - .statsList() - .then((list) => { - list.should.be.instanceof(AppStatsList); - stub.restore(); - }) - .catch((err) => { - stub.restore(); - throw err; - }); - }); it('should load stats resource', () => { const apps = new Apps('live'); const stub = sinon.stub(helper, 'get'); diff --git a/test/mocks/account-list.json b/test/mocks/account-list.json index 144a2c1b..3eab9872 100644 --- a/test/mocks/account-list.json +++ b/test/mocks/account-list.json @@ -57,7 +57,17 @@ } ], "state": "active", - "permissions": ["acc:permissions:dm:5510a8f9-67ce-4d4d-b5a1-a9fe6b7d8d72"], + "permissions": [ + "acc:permissions:dm:5510a8f9-67ce-4d4d-b5a1-a9fe6b7d8d72", + "acc:list,view,group,group-create,permissions,set-permissions,invite", + "dm:35b4f503-f361-4198-a11a-b2f24113731f", + "dm-stats,app-stats", + "dm-template-create,dm-template", + "acc:invalid-permissions", + "acc:client,client-create", + "mail" + ], + "nativePermissions": ["acc:permissions:dm:5510a8f9-67ce-4d4d-b5a1-a9fe6b7d8d72"], "groups": [ { "groupID": "260cb6b2-4fef-40e1-866a-659f2feb2500", @@ -120,7 +130,17 @@ } ], "state": "active", - "permissions": ["acc:permissions:dm:5510a8f9-67ce-4d4d-b5a1-a9fe6b7d8d72"], + "nativePermissions": ["acc:permissions:dm:5510a8f9-67ce-4d4d-b5a1-a9fe6b7d8d72"], + "permissions": [ + "acc:permissions:dm:5510a8f9-67ce-4d4d-b5a1-a9fe6b7d8d72", + "acc:list,view,group,group-create,permissions,set-permissions,invite", + "dm:35b4f503-f361-4198-a11a-b2f24113731f", + "dm-stats,app-stats", + "dm-template-create,dm-template", + "acc:invalid-permissions", + "acc:client,client-create", + "mail" + ], "groups": [ { "groupID": "260cb6b2-4fef-40e1-866a-659f2feb2500", diff --git a/test/mocks/account-single.json b/test/mocks/account-single.json index 295df702..720d2650 100644 --- a/test/mocks/account-single.json +++ b/test/mocks/account-single.json @@ -23,7 +23,17 @@ } ], "state": "active", - "permissions": ["acc:permissions:dm:5510a8f9-67ce-4d4d-b5a1-a9fe6b7d8d72"], + "permissions": [ + "acc:permissions:dm:5510a8f9-67ce-4d4d-b5a1-a9fe6b7d8d72", + "acc:list,view,group,group-create,permissions,set-permissions,invite", + "dm:35b4f503-f361-4198-a11a-b2f24113731f", + "dm-stats,app-stats", + "dm-template-create,dm-template", + "acc:invalid-permissions", + "acc:client,client-create", + "mail" + ], + "nativePermissions": ["acc:permissions:dm:5510a8f9-67ce-4d4d-b5a1-a9fe6b7d8d72"], "groups": [ { "groupID": "260cb6b2-4fef-40e1-866a-659f2feb2500", diff --git a/test/mocks/group-list.json b/test/mocks/group-list.json index 159d7e47..65994e3a 100644 --- a/test/mocks/group-list.json +++ b/test/mocks/group-list.json @@ -29,6 +29,8 @@ "name": "AppManager-User", "groupID": "c7df5f26-3fa2-4bd5-8a9a-47087d69ab29", "permissions": ["app-create", "app:codesource,datasource,target,platform"], + "nativePermissions": ["app-create", "app:codesource,datasource,target,platform"], + "subgroups": [], "_embedded": { "ec:account": [ { @@ -69,6 +71,8 @@ "name": "DataManager-User", "groupID": "21e6b4df-0b38-44cd-bc54-b1f517a5480b", "permissions": ["app-create", "app:codesource,datasource,target,platform"], + "nativePermissions": ["app-create", "app:codesource,datasource,target,platform"], + "subgroups": [], "_embedded": { "ec:account": [ { diff --git a/test/mocks/group-single.json b/test/mocks/group-single.json index c8bdaa44..0dfe5987 100644 --- a/test/mocks/group-single.json +++ b/test/mocks/group-single.json @@ -2,6 +2,8 @@ "name": "AppManager-User", "groupID": "c7df5f26-3fa2-4bd5-8a9a-47087d69ab29", "permissions": ["app-create", "app:codesource,datasource,target,platform"], + "nativePermissions": ["app-create", "app:codesource,datasource,target,platform"], + "subgroups": [], "_embedded": { "ec:account": [ { From c75d7f08da85f2204af0a5a14b9765128eace526 Mon Sep 17 00:00:00 2001 From: Simon Scherzinger Date: Thu, 23 May 2024 15:17:36 +0200 Subject: [PATCH 2/2] release version 0.30.0 --- docs/index.html | 187 ++++++++++++++++++++++++++++++++++++++++++++-- package-lock.json | 4 +- package.json | 2 +- 3 files changed, 185 insertions(+), 8 deletions(-) diff --git a/docs/index.html b/docs/index.html index a11dfc14..070d0e88 100644 --- a/docs/index.html +++ b/docs/index.html @@ -2,7 +2,7 @@ - ec.sdk 0.29.2 | Documentation + ec.sdk 0.30.0 | Documentation @@ -15,7 +15,7 @@

ec.sdk

-
0.29.2
+
0.30.0
ec.sdk #addPermissions +
  • + #removePermission +
  • + +
  • + #removePermissions +
  • +
  • @@ -16890,7 +16902,14 @@

    permissions (Array<string>) - : Array of permissions + : Array of all permissions + + +
    + +
    + nativePermissions (Array<string>) + : Array of native permissions
    @@ -17065,6 +17084,148 @@

    + + +

  • +
    + +
    +
    +
    + + removePermission(value) +
    +
    + +
    + +
    +
    +
    + + removePermissions(value) +
    +
    + @@ -17231,7 +17392,9 @@

    - +
    Deprecated: Since Account Server 1.2.0 this is the same as +AccountResource#permissions +
    @@ -18244,7 +18407,21 @@

    permissions (Array<string>) - : Array of permissions + : Array of all permissions + + +
    + +
    + subgroups (Array<string>) + : Array of all subgroups + + +
    + +
    + nativePermissions (Array<string>) + : Array of native permissions
    diff --git a/package-lock.json b/package-lock.json index 95a35c33..473bcfc2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ec.sdk", - "version": "0.29.2", + "version": "0.30.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ec.sdk", - "version": "0.29.2", + "version": "0.30.0", "license": "ISC", "dependencies": { "@types/halfred": "^2.0.1", diff --git a/package.json b/package.json index 7acfa5a9..8d6b287c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ec.sdk", - "version": "0.29.2", + "version": "0.30.0", "description": "SDK for ec.api", "repository": "entrecode/ec.sdk", "author": "Simon Scherzinger ",