Skip to content

fix(organizations): extend global-admin bypass to updateRole + centralize isGlobalAdmin helper #3510

Description

@PierreBrisorgueil

Problem

Follow-up to #3505. Two related improvements surfaced during review that are intentionally out of scope for that PR:

  1. modules/organizations/controllers/organizations.membership.controller.js#updateRole still requires the actor to be an org owner (req.membership.role === OWNER). Global platform admins hitting this handler (even when they are not a member of the target org) will get a 403. For consistency with the remove-member / delete-org bypass, admins should be able to change member roles too — notably to transfer ownership during moderation.

  2. The pattern Array.isArray(req.user?.roles) && req.user.roles.includes('admin') is now repeated in organizations.controller.js, organizations.membership.controller.js, organizations.middleware.js, and organizations.policy.js. This should be centralized (e.g. req.isGlobalAdmin populated once in an auth middleware, or a small helper in lib/helpers/auth.js).

Expected behaviour

  • Global admin can call PUT /api/organizations/:orgId/memberships/:memberId with { role: 'owner' | 'admin' | 'member' } and succeed even when not a member of the target org.
  • A single source of truth for isGlobalAdmin(req) used consistently across the codebase.

Scope note

Item 1 must preserve the belt-and-suspenders block against CASL shipping update Membership by mistake for non-owner org roles — the fix is to allow only global admins + owners, not to loosen CASL overall.

Metadata

Metadata

Assignees

No one assigned

    Labels

    FixA bug fix

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions