From e8bca67186a975000b7cc6e08da374bbd3276fc4 Mon Sep 17 00:00:00 2001 From: Bassel Kanso Date: Wed, 24 Aug 2022 18:08:17 +0300 Subject: [PATCH 1/5] create route for api token layout --- .../controllers/__tests__/api-token.test.js | 53 +++++++++++++++++ .../admin/server/controllers/api-token.js | 7 +++ .../core/admin/server/routes/api-tokens.js | 8 +++ .../services/__tests__/api-token.test.js | 59 +++++++++++++++++++ .../core/admin/server/services/api-token.js | 47 ++++++++++++++- 5 files changed, 173 insertions(+), 1 deletion(-) diff --git a/packages/core/admin/server/controllers/__tests__/api-token.test.js b/packages/core/admin/server/controllers/__tests__/api-token.test.js index ec38fa432b..581cbc4a5c 100644 --- a/packages/core/admin/server/controllers/__tests__/api-token.test.js +++ b/packages/core/admin/server/controllers/__tests__/api-token.test.js @@ -292,4 +292,57 @@ describe('API Token Controller', () => { expect(send).toHaveBeenCalled(); }); }); + + describe('API tokens permissions layout', () => { + const layout = [ + { + label: 'address', + subjectId: 'api::address', + controllers: [ + { + label: 'address', + actions: ['api::address.address.find', 'api::address.address.findOne'], + }, + ], + }, + { + label: 'category', + subjectId: 'api::category', + controllers: [ + { + label: 'category', + actions: [ + 'api::category.category.find', + 'api::category.category.findOne', + 'api::category.category.create', + 'api::category.category.update', + 'api::category.category.delete', + 'api::category.category.createLocalization', + ], + }, + ], + }, + ]; + + test('return API tokens layout successfully', async () => { + const getApiTokenLayout = jest.fn().mockResolvedValue(layout); + const send = jest.fn(); + const ctx = createContext({}, { send }); + + global.strapi = { + admin: { + services: { + 'api-token': { + getApiTokenLayout, + }, + }, + }, + }; + + await apiTokenController.getLayout(ctx); + + expect(getApiTokenLayout).toHaveBeenCalled(); + expect(send).toHaveBeenCalledWith({ data: layout }); + }); + }); }); diff --git a/packages/core/admin/server/controllers/api-token.js b/packages/core/admin/server/controllers/api-token.js index 132663d6cf..932a853393 100644 --- a/packages/core/admin/server/controllers/api-token.js +++ b/packages/core/admin/server/controllers/api-token.js @@ -128,4 +128,11 @@ module.exports = { const apiToken = await apiTokenService.update(id, attributes); ctx.send({ data: apiToken }); }, + + async getLayout(ctx) { + const apiTokenService = getService('api-token'); + const layout = await apiTokenService.getApiTokenLayout(); + + ctx.send({ data: layout }); + }, }; diff --git a/packages/core/admin/server/routes/api-tokens.js b/packages/core/admin/server/routes/api-tokens.js index e994382db6..b9653e4bcd 100644 --- a/packages/core/admin/server/routes/api-tokens.js +++ b/packages/core/admin/server/routes/api-tokens.js @@ -67,4 +67,12 @@ module.exports = [ ], }, }, + { + method: 'GET', + path: '/api-token-layout', + handler: 'api-token.getLayout', + config: { + policies: ['admin::isAuthenticatedAdmin'], + }, + }, ]; diff --git a/packages/core/admin/server/services/__tests__/api-token.test.js b/packages/core/admin/server/services/__tests__/api-token.test.js index fe819e156c..3cc229bbce 100644 --- a/packages/core/admin/server/services/__tests__/api-token.test.js +++ b/packages/core/admin/server/services/__tests__/api-token.test.js @@ -591,4 +591,63 @@ describe('API Token', () => { expect(res).toEqual(null); }); }); + + describe('Api token permissions layout', () => { + const actionsMap = { + 'api::address': { + controllers: { + address: ['find', 'findOne'], + }, + }, + 'api::category': { + controllers: { + category: ['find', 'findOne', 'create', 'update', 'delete', 'createLocalization'], + }, + }, + }; + + test('It returns all the permissions', async () => { + const getActionsMap = jest.fn().mockResolvedValue(actionsMap); + + global.strapi = { + contentAPI: { + permissions: { + getActionsMap, + }, + }, + }; + + const res = await apiTokenService.getApiTokenLayout(); + + expect(res).toEqual([ + { + label: 'address', + subjectId: 'api::address', + controllers: [ + { + label: 'address', + actions: ['api::address.address.find', 'api::address.address.findOne'], + }, + ], + }, + { + label: 'category', + subjectId: 'api::category', + controllers: [ + { + label: 'category', + actions: [ + 'api::category.category.find', + 'api::category.category.findOne', + 'api::category.category.create', + 'api::category.category.update', + 'api::category.category.delete', + 'api::category.category.createLocalization', + ], + }, + ], + }, + ]); + }); + }); }); diff --git a/packages/core/admin/server/services/api-token.js b/packages/core/admin/server/services/api-token.js index 8455753ea2..c389696db0 100644 --- a/packages/core/admin/server/services/api-token.js +++ b/packages/core/admin/server/services/api-token.js @@ -1,7 +1,7 @@ 'use strict'; const crypto = require('crypto'); -const { omit, difference, isEmpty, map, isArray } = require('lodash/fp'); +const { omit, difference, isEmpty, map, isArray, flatten } = require('lodash/fp'); const { ValidationError, NotFoundError } = require('@strapi/utils').errors; const constants = require('./constants'); @@ -29,6 +29,21 @@ const constants = require('./constants'); * @property {ApiToken|number} token */ +/** + * @typedef ApiTokenPermissionSubject + * + * @property {string} label + * @property {string} subjectId + * @property {Controller[]} controllers + */ + +/** + * @typedef Controller + * + * @property {string} label + * @property {string[]} actions + */ + /** @constant {Array} */ const SELECT_FIELDS = ['id', 'name', 'description', 'lastUsedAt', 'type', 'createdAt', 'updatedAt']; @@ -395,6 +410,35 @@ const update = async (id, attributes) => { }; }; +/** + * Return a layout of the api actions + * + * @returns {Promise} + */ +const getApiTokenLayout = async () => { + const actions = await strapi.contentAPI.permissions.getActionsMap(); + const subjects = Object.keys(actions) + .map((subjectId) => { + return { + label: subjectId.split('::')[1], + subjectId, + controllers: flatten( + Object.keys(actions[subjectId].controllers).map((controller) => { + return { + label: controller, + actions: actions[subjectId].controllers[controller].map( + (action) => `${subjectId}.${controller}.${action}` + ), + }; + }) + ), + }; + }) + .filter((actions) => actions.subjectId.includes('api::')); + + return subjects; +}; + module.exports = { create, regenerate, @@ -407,4 +451,5 @@ module.exports = { update, getByName, getBy, + getApiTokenLayout, }; From 9d76db03806cf8332e11c28b4ffc0bee99e9593a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Aug 2022 09:08:55 +0000 Subject: [PATCH 2/5] Bump @storybook/addon-links from 6.5.9 to 6.5.10 Bumps [@storybook/addon-links](https://github.com/storybookjs/storybook/tree/HEAD/addons/links) from 6.5.9 to 6.5.10. - [Release notes](https://github.com/storybookjs/storybook/releases) - [Changelog](https://github.com/storybookjs/storybook/blob/v6.5.10/CHANGELOG.md) - [Commits](https://github.com/storybookjs/storybook/commits/v6.5.10/addons/links) --- updated-dependencies: - dependency-name: "@storybook/addon-links" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- packages/core/helper-plugin/package.json | 2 +- yarn.lock | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/core/helper-plugin/package.json b/packages/core/helper-plugin/package.json index 65c243f612..3d98e3dbf2 100644 --- a/packages/core/helper-plugin/package.json +++ b/packages/core/helper-plugin/package.json @@ -73,7 +73,7 @@ "@babel/runtime": "7.18.9", "@storybook/addon-actions": "6.5.10", "@storybook/addon-essentials": "6.5.9", - "@storybook/addon-links": "6.5.9", + "@storybook/addon-links": "6.5.10", "@storybook/builder-webpack5": "6.5.9", "@storybook/manager-webpack5": "6.4.10", "@storybook/react": "^6.5.10", diff --git a/yarn.lock b/yarn.lock index 963aca7df3..c67c24eef3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3888,16 +3888,16 @@ regenerator-runtime "^0.13.7" ts-dedent "^2.0.0" -"@storybook/addon-links@6.5.9": - version "6.5.9" - resolved "https://registry.yarnpkg.com/@storybook/addon-links/-/addon-links-6.5.9.tgz#91cbca0c044796badf2498723fdd10dacea5748b" - integrity sha512-4BYC7pkxL3NLRnEgTA9jpIkObQKril+XFj1WtmY/lngF90vvK0Kc/TtvTA2/5tSgrHfxEuPevIdxMIyLJ4ejWQ== +"@storybook/addon-links@6.5.10": + version "6.5.10" + resolved "https://registry.yarnpkg.com/@storybook/addon-links/-/addon-links-6.5.10.tgz#f66568fbc84b942032ac2de85f799d69fcf77922" + integrity sha512-r3WzYIPz7WjHiaPObC2Tg6bHuZRBb/Kt/X+Eitw+jTqBel7ksvkO36tn81q8Eyj61qIdNQmUWAaX/0aewT0kLA== dependencies: - "@storybook/addons" "6.5.9" - "@storybook/client-logger" "6.5.9" - "@storybook/core-events" "6.5.9" + "@storybook/addons" "6.5.10" + "@storybook/client-logger" "6.5.10" + "@storybook/core-events" "6.5.10" "@storybook/csf" "0.0.2--canary.4566f4d.1" - "@storybook/router" "6.5.9" + "@storybook/router" "6.5.10" "@types/qs" "^6.9.5" core-js "^3.8.2" global "^4.4.0" From a772f8a8ac700f4cc8c2387dd83d936db2d74a6a Mon Sep 17 00:00:00 2001 From: Bassel Kanso Date: Thu, 25 Aug 2022 16:57:45 +0300 Subject: [PATCH 3/5] add content type permissions to the permissions route --- .../controllers/__tests__/api-token.test.js | 53 ----------------- .../controllers/__tests__/permission.test.js | 34 +++++++++++ .../admin/server/controllers/permission.js | 6 ++ .../core/admin/server/routes/permissions.js | 8 +++ .../services/__tests__/api-token.test.js | 59 ------------------- .../core/admin/server/services/api-token.js | 47 +-------------- 6 files changed, 49 insertions(+), 158 deletions(-) diff --git a/packages/core/admin/server/controllers/__tests__/api-token.test.js b/packages/core/admin/server/controllers/__tests__/api-token.test.js index 581cbc4a5c..ec38fa432b 100644 --- a/packages/core/admin/server/controllers/__tests__/api-token.test.js +++ b/packages/core/admin/server/controllers/__tests__/api-token.test.js @@ -292,57 +292,4 @@ describe('API Token Controller', () => { expect(send).toHaveBeenCalled(); }); }); - - describe('API tokens permissions layout', () => { - const layout = [ - { - label: 'address', - subjectId: 'api::address', - controllers: [ - { - label: 'address', - actions: ['api::address.address.find', 'api::address.address.findOne'], - }, - ], - }, - { - label: 'category', - subjectId: 'api::category', - controllers: [ - { - label: 'category', - actions: [ - 'api::category.category.find', - 'api::category.category.findOne', - 'api::category.category.create', - 'api::category.category.update', - 'api::category.category.delete', - 'api::category.category.createLocalization', - ], - }, - ], - }, - ]; - - test('return API tokens layout successfully', async () => { - const getApiTokenLayout = jest.fn().mockResolvedValue(layout); - const send = jest.fn(); - const ctx = createContext({}, { send }); - - global.strapi = { - admin: { - services: { - 'api-token': { - getApiTokenLayout, - }, - }, - }, - }; - - await apiTokenController.getLayout(ctx); - - expect(getApiTokenLayout).toHaveBeenCalled(); - expect(send).toHaveBeenCalledWith({ data: layout }); - }); - }); }); diff --git a/packages/core/admin/server/controllers/__tests__/permission.test.js b/packages/core/admin/server/controllers/__tests__/permission.test.js index eb8900ff1c..72a5cb15f4 100644 --- a/packages/core/admin/server/controllers/__tests__/permission.test.js +++ b/packages/core/admin/server/controllers/__tests__/permission.test.js @@ -197,4 +197,38 @@ describe('Permission Controller', () => { expect(ctx.body.data).toHaveLength(localTestData.permissions.valid.length); }); }); + + describe('Content API permissions', () => { + const actionsMap = { + 'api::address': { + controllers: { + address: ['find', 'findOne'], + }, + }, + 'api::category': { + controllers: { + category: ['find', 'findOne', 'create', 'update', 'delete', 'createLocalization'], + }, + }, + }; + + test('return API tokens layout successfully', async () => { + const getActionsMap = jest.fn().mockResolvedValue(actionsMap); + const send = jest.fn(); + const ctx = createContext({}, { send }); + + global.strapi = { + contentAPI: { + permissions: { + getActionsMap, + }, + }, + }; + + await permissionController.getContentApiPermissions(ctx); + + expect(getActionsMap).toHaveBeenCalled(); + expect(send).toHaveBeenCalledWith({ data: actionsMap }); + }); + }); }); diff --git a/packages/core/admin/server/controllers/permission.js b/packages/core/admin/server/controllers/permission.js index 481f5adb41..5704f8fc86 100644 --- a/packages/core/admin/server/controllers/permission.js +++ b/packages/core/admin/server/controllers/permission.js @@ -44,4 +44,10 @@ module.exports = { }, }; }, + + async getContentApiPermissions(ctx) { + const actionsMap = await strapi.contentAPI.permissions.getActionsMap(); + + ctx.send({ data: actionsMap }); + }, }; diff --git a/packages/core/admin/server/routes/permissions.js b/packages/core/admin/server/routes/permissions.js index 5e279338e2..bb6ba7501c 100644 --- a/packages/core/admin/server/routes/permissions.js +++ b/packages/core/admin/server/routes/permissions.js @@ -17,4 +17,12 @@ module.exports = [ policies: ['admin::isAuthenticatedAdmin'], }, }, + { + method: 'GET', + path: '/content-api-permissions', + handler: 'permission.getContentApiPermissions', + config: { + policies: ['admin::isAuthenticatedAdmin'], + }, + }, ]; diff --git a/packages/core/admin/server/services/__tests__/api-token.test.js b/packages/core/admin/server/services/__tests__/api-token.test.js index 3cc229bbce..fe819e156c 100644 --- a/packages/core/admin/server/services/__tests__/api-token.test.js +++ b/packages/core/admin/server/services/__tests__/api-token.test.js @@ -591,63 +591,4 @@ describe('API Token', () => { expect(res).toEqual(null); }); }); - - describe('Api token permissions layout', () => { - const actionsMap = { - 'api::address': { - controllers: { - address: ['find', 'findOne'], - }, - }, - 'api::category': { - controllers: { - category: ['find', 'findOne', 'create', 'update', 'delete', 'createLocalization'], - }, - }, - }; - - test('It returns all the permissions', async () => { - const getActionsMap = jest.fn().mockResolvedValue(actionsMap); - - global.strapi = { - contentAPI: { - permissions: { - getActionsMap, - }, - }, - }; - - const res = await apiTokenService.getApiTokenLayout(); - - expect(res).toEqual([ - { - label: 'address', - subjectId: 'api::address', - controllers: [ - { - label: 'address', - actions: ['api::address.address.find', 'api::address.address.findOne'], - }, - ], - }, - { - label: 'category', - subjectId: 'api::category', - controllers: [ - { - label: 'category', - actions: [ - 'api::category.category.find', - 'api::category.category.findOne', - 'api::category.category.create', - 'api::category.category.update', - 'api::category.category.delete', - 'api::category.category.createLocalization', - ], - }, - ], - }, - ]); - }); - }); }); diff --git a/packages/core/admin/server/services/api-token.js b/packages/core/admin/server/services/api-token.js index c389696db0..8455753ea2 100644 --- a/packages/core/admin/server/services/api-token.js +++ b/packages/core/admin/server/services/api-token.js @@ -1,7 +1,7 @@ 'use strict'; const crypto = require('crypto'); -const { omit, difference, isEmpty, map, isArray, flatten } = require('lodash/fp'); +const { omit, difference, isEmpty, map, isArray } = require('lodash/fp'); const { ValidationError, NotFoundError } = require('@strapi/utils').errors; const constants = require('./constants'); @@ -29,21 +29,6 @@ const constants = require('./constants'); * @property {ApiToken|number} token */ -/** - * @typedef ApiTokenPermissionSubject - * - * @property {string} label - * @property {string} subjectId - * @property {Controller[]} controllers - */ - -/** - * @typedef Controller - * - * @property {string} label - * @property {string[]} actions - */ - /** @constant {Array} */ const SELECT_FIELDS = ['id', 'name', 'description', 'lastUsedAt', 'type', 'createdAt', 'updatedAt']; @@ -410,35 +395,6 @@ const update = async (id, attributes) => { }; }; -/** - * Return a layout of the api actions - * - * @returns {Promise} - */ -const getApiTokenLayout = async () => { - const actions = await strapi.contentAPI.permissions.getActionsMap(); - const subjects = Object.keys(actions) - .map((subjectId) => { - return { - label: subjectId.split('::')[1], - subjectId, - controllers: flatten( - Object.keys(actions[subjectId].controllers).map((controller) => { - return { - label: controller, - actions: actions[subjectId].controllers[controller].map( - (action) => `${subjectId}.${controller}.${action}` - ), - }; - }) - ), - }; - }) - .filter((actions) => actions.subjectId.includes('api::')); - - return subjects; -}; - module.exports = { create, regenerate, @@ -451,5 +407,4 @@ module.exports = { update, getByName, getBy, - getApiTokenLayout, }; From 3ce256e279b3fe31a316f3d7ffb69835a72ce034 Mon Sep 17 00:00:00 2001 From: Bassel Kanso Date: Fri, 26 Aug 2022 10:02:13 +0300 Subject: [PATCH 4/5] add content api permissions controller to it's separate file --- .../controllers/__tests__/content-api.test.js | 38 +++++++++++++++++++ .../admin/server/controllers/content-api.js | 9 +++++ .../core/admin/server/controllers/index.js | 1 + .../admin/server/controllers/permission.js | 6 --- .../core/admin/server/routes/content-api.js | 12 ++++++ packages/core/admin/server/routes/index.js | 2 + .../core/admin/server/routes/permissions.js | 8 ---- 7 files changed, 62 insertions(+), 14 deletions(-) create mode 100644 packages/core/admin/server/controllers/__tests__/content-api.test.js create mode 100644 packages/core/admin/server/controllers/content-api.js create mode 100644 packages/core/admin/server/routes/content-api.js diff --git a/packages/core/admin/server/controllers/__tests__/content-api.test.js b/packages/core/admin/server/controllers/__tests__/content-api.test.js new file mode 100644 index 0000000000..6fce23383b --- /dev/null +++ b/packages/core/admin/server/controllers/__tests__/content-api.test.js @@ -0,0 +1,38 @@ +'use strict'; + +const createContext = require('../../../../../../test/helpers/create-context'); +const contentApiController = require('../content-api'); + +describe('Content API permissions', () => { + const actionsMap = { + 'api::address': { + controllers: { + address: ['find', 'findOne'], + }, + }, + 'api::category': { + controllers: { + category: ['find', 'findOne', 'create', 'update', 'delete', 'createLocalization'], + }, + }, + }; + + test('return content api layout successfully', async () => { + const getActionsMap = jest.fn().mockResolvedValue(actionsMap); + const send = jest.fn(); + const ctx = createContext({}, { send }); + + global.strapi = { + contentAPI: { + permissions: { + getActionsMap, + }, + }, + }; + + await contentApiController.getPermissions(ctx); + + expect(getActionsMap).toHaveBeenCalled(); + expect(send).toHaveBeenCalledWith({ data: actionsMap }); + }); +}); diff --git a/packages/core/admin/server/controllers/content-api.js b/packages/core/admin/server/controllers/content-api.js new file mode 100644 index 0000000000..7a988a1713 --- /dev/null +++ b/packages/core/admin/server/controllers/content-api.js @@ -0,0 +1,9 @@ +'use strict'; + +module.exports = { + async getPermissions(ctx) { + const actionsMap = await strapi.contentAPI.permissions.getActionsMap(); + + ctx.send({ data: actionsMap }); + }, +}; diff --git a/packages/core/admin/server/controllers/index.js b/packages/core/admin/server/controllers/index.js index 696358b183..a42f15cf61 100644 --- a/packages/core/admin/server/controllers/index.js +++ b/packages/core/admin/server/controllers/index.js @@ -9,4 +9,5 @@ module.exports = { role: require('./role'), user: require('./user'), webhooks: require('./webhooks'), + 'content-api': require('./content-api'), }; diff --git a/packages/core/admin/server/controllers/permission.js b/packages/core/admin/server/controllers/permission.js index 5704f8fc86..481f5adb41 100644 --- a/packages/core/admin/server/controllers/permission.js +++ b/packages/core/admin/server/controllers/permission.js @@ -44,10 +44,4 @@ module.exports = { }, }; }, - - async getContentApiPermissions(ctx) { - const actionsMap = await strapi.contentAPI.permissions.getActionsMap(); - - ctx.send({ data: actionsMap }); - }, }; diff --git a/packages/core/admin/server/routes/content-api.js b/packages/core/admin/server/routes/content-api.js new file mode 100644 index 0000000000..cc563c1b94 --- /dev/null +++ b/packages/core/admin/server/routes/content-api.js @@ -0,0 +1,12 @@ +'use strict'; + +module.exports = [ + { + method: 'GET', + path: '/content-api/permissions', + handler: 'content-api.getPermissions', + config: { + policies: ['admin::isAuthenticatedAdmin'], + }, + }, +]; diff --git a/packages/core/admin/server/routes/index.js b/packages/core/admin/server/routes/index.js index ee0b6f8606..8181e79715 100644 --- a/packages/core/admin/server/routes/index.js +++ b/packages/core/admin/server/routes/index.js @@ -7,6 +7,7 @@ const users = require('./users'); const roles = require('./roles'); const webhooks = require('./webhooks'); const apiTokens = require('./api-tokens'); +const contentApi = require('./content-api'); module.exports = [ ...admin, @@ -16,4 +17,5 @@ module.exports = [ ...roles, ...webhooks, ...apiTokens, + ...contentApi, ]; diff --git a/packages/core/admin/server/routes/permissions.js b/packages/core/admin/server/routes/permissions.js index bb6ba7501c..5e279338e2 100644 --- a/packages/core/admin/server/routes/permissions.js +++ b/packages/core/admin/server/routes/permissions.js @@ -17,12 +17,4 @@ module.exports = [ policies: ['admin::isAuthenticatedAdmin'], }, }, - { - method: 'GET', - path: '/content-api-permissions', - handler: 'permission.getContentApiPermissions', - config: { - policies: ['admin::isAuthenticatedAdmin'], - }, - }, ]; From db4c3af1f90e5a872a27fd6a1830f88e9a80cc5b Mon Sep 17 00:00:00 2001 From: Bassel Kanso Date: Fri, 26 Aug 2022 10:42:01 +0300 Subject: [PATCH 5/5] remove test --- .../controllers/__tests__/permission.test.js | 34 ------------------- 1 file changed, 34 deletions(-) diff --git a/packages/core/admin/server/controllers/__tests__/permission.test.js b/packages/core/admin/server/controllers/__tests__/permission.test.js index 72a5cb15f4..eb8900ff1c 100644 --- a/packages/core/admin/server/controllers/__tests__/permission.test.js +++ b/packages/core/admin/server/controllers/__tests__/permission.test.js @@ -197,38 +197,4 @@ describe('Permission Controller', () => { expect(ctx.body.data).toHaveLength(localTestData.permissions.valid.length); }); }); - - describe('Content API permissions', () => { - const actionsMap = { - 'api::address': { - controllers: { - address: ['find', 'findOne'], - }, - }, - 'api::category': { - controllers: { - category: ['find', 'findOne', 'create', 'update', 'delete', 'createLocalization'], - }, - }, - }; - - test('return API tokens layout successfully', async () => { - const getActionsMap = jest.fn().mockResolvedValue(actionsMap); - const send = jest.fn(); - const ctx = createContext({}, { send }); - - global.strapi = { - contentAPI: { - permissions: { - getActionsMap, - }, - }, - }; - - await permissionController.getContentApiPermissions(ctx); - - expect(getActionsMap).toHaveBeenCalled(); - expect(send).toHaveBeenCalledWith({ data: actionsMap }); - }); - }); });