doc/development/permissions/internal_permission_groups.md
Internal permission groups are YAML-based configuration files that define logical groupings of permissions which are activated or deactivated together based on internal resource state. They allow you to centrally manage sets of permissions that should be collectively prevented (or enabled) when a specific condition is met, such as a group being archived.
Internal permission groups are defined as YAML files under
config/authz/permission_groups/internal/. Each file contains a description and
a list of permission names. At runtime, the
Authz::PermissionGroups::Internal class loads these files and provides a lookup
API to retrieve a group by its identifier.
The identifier for an internal permission group is derived from its file path
relative to the config/authz/permission_groups/internal/ directory:
For example, config/authz/permission_groups/internal/group/archived.yml
produces the identifier group:archived.
Each YAML file must contain:
description: A human-readable explanation of when these permissions apply.permissions: A list of permission (ability) names as strings.Example (config/authz/permission_groups/internal/group/archived.yml):
description: Permissions that are disabled when a group is archived
permissions:
- activate_group_member
- admin_build
- create_projects
- push_code
# ... additional permissions
To use an internal permission group in a DeclarativePolicy policy, call
Authz::PermissionGroups::Internal.get with the group identifier and splat
the returned permissions into a prevent rule:
# app/policies/group_policy.rb
condition(:archived, scope: :subject) { @subject.self_or_ancestors_archived? }
rule { archived }.policy do
prevent(*Authz::PermissionGroups::Internal.get('group:archived').permissions)
end
This prevents all listed permissions when the archived condition is true,
replacing the need to maintain a long inline list of prevent calls.
Create the YAML file. Add a new .yml file under
config/authz/permission_groups/internal/. Use directories to namespace by
resource type:
config/authz/permission_groups/internal/<resource>/<subresource>/<name>.yml
For example, to define permissions to prevent when a project is locked:
# config/authz/permission_groups/internal/project/locked.yml
description: Permissions that are disabled when a project is locked
permissions:
- push_code
- create_merge_request_from
- admin_merge_request
Reference it in a policy. Use the identifier derived from the file path
(project:locked in this example):
# app/policies/project_policy.rb
condition(:locked, scope: :subject) { @subject.locked? }
rule { locked }.policy do
prevent(*Authz::PermissionGroups::Internal.get('project:locked').permissions)
end
Use internal permission groups when:
prevent calls throughout policy files.Do not use internal permission groups for: