From 06678723da51dda23594f04ff6c2989f26763cda Mon Sep 17 00:00:00 2001 From: Andrew Bone Date: Thu, 11 Jun 2026 15:57:22 +0100 Subject: [PATCH 1/2] Add manual permission for hidden collection --- .../server/src/bootstrap.ts | 69 ++++++++++++++++++- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/plugins/plugin-api-permissions/server/src/bootstrap.ts b/plugins/plugin-api-permissions/server/src/bootstrap.ts index 4655cb2..8f0afd8 100644 --- a/plugins/plugin-api-permissions/server/src/bootstrap.ts +++ b/plugins/plugin-api-permissions/server/src/bootstrap.ts @@ -32,10 +32,31 @@ const RBAC_ACTIONS = [ }, ]; +// This list should be kept in sync with the permissions defined in content manager for the API Role content type +const FULL_ACTIONS = [ + { + pluginAction: "plugin::api-permissions.roles.read", + cmAction: "plugin::content-manager.explorer.read", + }, + { + pluginAction: "plugin::api-permissions.roles.create", + cmAction: "plugin::content-manager.explorer.create", + }, + { + pluginAction: "plugin::api-permissions.roles.update", + cmAction: "plugin::content-manager.explorer.update", + }, + { + pluginAction: "plugin::api-permissions.roles.delete", + cmAction: "plugin::content-manager.explorer.delete", + }, +]; + export default async ({ strapi }: { strapi: Core.Strapi }) => { - await strapi - .service("admin::permission") - .actionProvider.registerMany(RBAC_ACTIONS); + const provider = strapi.service("admin::permission").actionProvider; + + await provider.registerMany(RBAC_ACTIONS); + await manualPermissionOverride(strapi); const roleCount = await strapi.documents(ROLE_UID).count({}); @@ -57,3 +78,45 @@ export default async ({ strapi }: { strapi: Core.Strapi }) => { }); } }; + +/** + * Manually override permissions for API Roles to ensure they are always in sync with Content Manager permissions. + * @param strapi The Strapi instance + */ +const manualPermissionOverride = async (strapi: Core.Strapi) => { + const provider = strapi.service("admin::permission").actionProvider; + + for (const { pluginAction, cmAction } of FULL_ACTIONS) { + const admin = provider.get(cmAction); + const alias = provider.get(pluginAction); + + if (admin) { + if (!admin.subjects) admin.subjects = []; + + if (!admin.subjects.includes(ROLE_UID)) admin.subjects.push(ROLE_UID); + } + + if (alias) { + if (!alias.aliases) alias.aliases = []; + + const exists = alias.aliases.some( + ({ actionId, subjects }: { actionId: string; subjects?: string[] }) => { + return actionId === cmAction && subjects?.includes(ROLE_UID); + }, + ); + + if (!exists) { + alias.aliases.push({ actionId: cmAction, subjects: [ROLE_UID] }); + } + } + } + + try { + await strapi.service("admin::role")?.resetSuperAdminPermissions?.(); + } catch (err) { + strapi.log.error( + "Failed to sync Super Admin permissions for API Roles:", + err, + ); + } +}; From 6df50d5757b2e031abb4159af027d3afcc0e4260 Mon Sep 17 00:00:00 2001 From: Andrew Bone Date: Fri, 12 Jun 2026 09:20:31 +0100 Subject: [PATCH 2/2] simplify manual permission overrides --- .../server/src/bootstrap.ts | 50 +++++++------------ 1 file changed, 19 insertions(+), 31 deletions(-) diff --git a/plugins/plugin-api-permissions/server/src/bootstrap.ts b/plugins/plugin-api-permissions/server/src/bootstrap.ts index 8f0afd8..853cb29 100644 --- a/plugins/plugin-api-permissions/server/src/bootstrap.ts +++ b/plugins/plugin-api-permissions/server/src/bootstrap.ts @@ -32,26 +32,6 @@ const RBAC_ACTIONS = [ }, ]; -// This list should be kept in sync with the permissions defined in content manager for the API Role content type -const FULL_ACTIONS = [ - { - pluginAction: "plugin::api-permissions.roles.read", - cmAction: "plugin::content-manager.explorer.read", - }, - { - pluginAction: "plugin::api-permissions.roles.create", - cmAction: "plugin::content-manager.explorer.create", - }, - { - pluginAction: "plugin::api-permissions.roles.update", - cmAction: "plugin::content-manager.explorer.update", - }, - { - pluginAction: "plugin::api-permissions.roles.delete", - cmAction: "plugin::content-manager.explorer.delete", - }, -]; - export default async ({ strapi }: { strapi: Core.Strapi }) => { const provider = strapi.service("admin::permission").actionProvider; @@ -86,27 +66,35 @@ export default async ({ strapi }: { strapi: Core.Strapi }) => { const manualPermissionOverride = async (strapi: Core.Strapi) => { const provider = strapi.service("admin::permission").actionProvider; - for (const { pluginAction, cmAction } of FULL_ACTIONS) { - const admin = provider.get(cmAction); - const alias = provider.get(pluginAction); + for (const action of ["read", "create", "update", "delete"]) { + const adminString = `plugin::content-manager.explorer.${action}`; + const aliasString = `plugin::api-permissions.roles.${action}`; + + const adminAction = provider.get(adminString); + const aliasAction = provider.get(aliasString); - if (admin) { - if (!admin.subjects) admin.subjects = []; + if (adminAction) { + if (!adminAction.subjects) adminAction.subjects = []; - if (!admin.subjects.includes(ROLE_UID)) admin.subjects.push(ROLE_UID); + if (!adminAction.subjects.includes(ROLE_UID)) { + adminAction.subjects.push(ROLE_UID); + } } - if (alias) { - if (!alias.aliases) alias.aliases = []; + if (aliasAction) { + if (!aliasAction.aliases) aliasAction.aliases = []; - const exists = alias.aliases.some( + const exists = aliasAction.aliases.some( ({ actionId, subjects }: { actionId: string; subjects?: string[] }) => { - return actionId === cmAction && subjects?.includes(ROLE_UID); + return actionId === adminString && subjects?.includes(ROLE_UID); }, ); if (!exists) { - alias.aliases.push({ actionId: cmAction, subjects: [ROLE_UID] }); + aliasAction.aliases.push({ + actionId: adminString, + subjects: [ROLE_UID], + }); } } }