organization-members

Set an organization member's groups

Changed on

Replace a member's groups, and with them the capabilities they hold.

Replaces the former update-role action. The request names groups -- the one write where a group name is the natural input, since assigning a group is the act of choosing one -- and the response reports the resulting permissions, which is what every authorization check actually reads.

Guards:

  • The organization keeps at least one member who can manage members. Restated from "cannot demote the last active admin": the rule counts by capability (organizations.manage_members) rather than by the role column, so it holds for any future group that carries the capability and does not depend on a representation the API no longer exposes.
  • A restricted organization may not write at all. See deactivate above for why the check is here rather than in OrganizationService.

Idempotency: assigning the groups a member already holds is a no-op success, including for the sole administrator re-assigning organization_admin to themselves -- the guard fires on losing the capability, not on writing it again.

post/organization-members/{user_id}/groups/

Request

  • The document declares no server URL.
  • Auth: one of:
    • HTTP bearer
    • API key in cookie sessionid

Path parameters

user_idstring required

Headers

X-Organization-Idstring

Selects the active organization for this request. Optional for callers that belong to exactly one active organization — the single membership is resolved implicitly. Required when the caller has two or more active memberships; omitting it in that case returns 400. If the header names an organization the caller is not an active member of, the server returns 403.

Request body

groupsGroupsEnum[] required

Groups to assign to this membership, replacing the ones it holds. organization_admin carries every capability; organization_billing_owner carries vinta_billing.manage_billing; organization_member carries none and is what a member with no capabilities holds. Naming a capability group alongside organization_member stores the capability group alone.

Response

user_idinteger required
organization_idinteger required
permissionsstring[] required

Capabilities this membership confers in this organization, as app_label.codename strings (for example organizations.manage_members). Resolved from the membership's groups and direct grants -- the same source every server-side authorization check reads -- so a client can gate UI on the exact string the API will enforce. Only organization-scoped capabilities appear: a global Django permission or superuser status grants nothing here, because it grants nothing in this organization either. An inactive membership resolves an empty list. The set of possible values grows over time; treat an unrecognised entry as an unknown capability rather than an error.

is_activeboolean required

Whether this membership is active. Inactive memberships are treated as gated: the user still has a row but loses all tenant-scoped access until reactivated. Use this to disable a user without deleting their membership record (which would lose their groups and history). Default True keeps every existing read unchanged.

user_emailstring email required
user_first_namestring required
user_last_namestring required

Changes