diff --git a/versioned_docs/version-3.0/concepts/access-governance/access-control.mdx b/versioned_docs/version-3.0/concepts/access-governance/access-control.mdx index 699015a1..66342e8e 100644 --- a/versioned_docs/version-3.0/concepts/access-governance/access-control.mdx +++ b/versioned_docs/version-3.0/concepts/access-governance/access-control.mdx @@ -82,6 +82,8 @@ Permissions are declared in code per resource area and assigned to standard role ## Related +- Concept: [Role](../access-governance/role.mdx) +- Flow: [Create a role](../../flows/access-governance/create-a-role.mdx) - Reference: [Role](../../references/access-governance/role.mdx) - Reference: [Permission](../../references/access-governance/permission.mdx) - Reference: [Permission association](../../references/access-governance/permission-association.mdx) diff --git a/versioned_docs/version-3.0/concepts/access-governance/role.mdx b/versioned_docs/version-3.0/concepts/access-governance/role.mdx new file mode 100644 index 00000000..e58b76b8 --- /dev/null +++ b/versioned_docs/version-3.0/concepts/access-governance/role.mdx @@ -0,0 +1,82 @@ +--- +sidebar_position: 5 +--- + +# Role + +A **role** is a named set of permissions. You grant a role to a user inside one boundary, such as a facility or an organization. The role decides what that user can do inside that boundary. + +## What it represents + +Care has no separate list of powers for each person. Every ability comes from a role that somebody grants at a place. A role holds three things: + +- **A name** — what the deployment calls this set of permissions, for example "Doctor" or "Pharmacist". +- **A description** — free text that tells an administrator what the role is for. +- **Contexts** — the kinds of boundary where the role applies. +- **Permissions** — the actions that the role allows. A role needs a minimum of one permission. + +A role is not a job title. "Doctor", "Nurse" and "Pharmacist" are only permission sets with convenient names. Two roles with similar names have no relation to each other. Care also allows the same name in two different contexts: "Admin" exists as a facility role and as a separate responsibility role. + +:::note +A role is different from a **responsibility** (a role organization). A role is a set of permissions. A responsibility is a group of users. See [Organization](../access-governance/organization.mdx). +::: + +## Contexts + +The contexts of a role say where an administrator can grant it. A role with the Facility context only appears when somebody assigns a user inside a facility. + +| Context | Where the role applies | +| --- | --- | +| Facility | Inside a facility, and inside the departments of that facility | +| Government Organization | Inside a government organization, such as a state or a district | +| Responsibility | Inside a responsibility, which is a group of users | + +## System roles and custom roles + +Care marks the roles that it supplies with the **System** badge. A deployment can add custom roles beside them. + +| Type | Who creates it | What you can change | +| --- | --- | --- | +| System role | Care supplies it with the product | Nothing. You cannot edit or delete a system role. | +| Custom role | A super administrator creates it | The name, the description, the contexts, and the permissions. | + +To start a custom role from a system role, clone the system role. Care copies the permissions into a new role and adds "(Copy)" to the name. + +These are the system roles: + +| Role | Purpose | Contexts | +| --- | --- | --- | +| Doctor | Doctor at some facility | Facility, Government Organization | +| Nurse | Nurse at some facility | Facility, Government Organization | +| Staff | Staff at some facility | Facility, Government Organization | +| Volunteer | Volunteer at some facility | Facility, Government Organization | +| Pharmacist | Pharmacist at some facility | Facility | +| Administrator | Administrator at a given boundary | Facility, Government Organization | +| Facility Admin | Administrator of a facility. Care gives this role to the person who creates the facility. | Facility | +| Admin | Administrator of a facility or a government organization | Facility, Government Organization | +| Admin | Administrator of a responsibility | Responsibility | +| Manager | Manager of a responsibility | Responsibility | +| Member | Member of a responsibility | Responsibility | + +## How a role reaches a user + +A role gives no access on its own. An administrator grants the role to a user inside one organization or one facility. The user then holds the permissions of that role in that boundary and in everything below it. + +```text +User → Role → Boundary (facility, organization, or responsibility) +``` + +The same user can hold different roles in different boundaries. The access of a user on a record is the sum of every role that reaches that record. If you move a user to a new facility, the old access does not follow, because somebody granted it at the old boundary. + +## Permissions + +Every permission in a role is one action, such as "Can Create Patient". Care declares the permissions in the product, and an administrator selects them when the administrator builds a role. Care matches the permission to the kind of resource that the user acts on. For this reason, a permission for a patient does not also allow an action on a facility. + +## Related + +- Flow: [Create a role](../../flows/access-governance/create-a-role.mdx) +- Flow: [Edit or clone a role](../../flows/access-governance/edit-a-role.mdx) +- Concept: [Roles & permissions](../access-governance/access-control.mdx) +- Concept: [Organization](../access-governance/organization.mdx) +- Concept: [User](../access-governance/user.mdx) +- Reference: [Role](../../references/access-governance/role.mdx) diff --git a/versioned_docs/version-3.0/flows/access-governance/_category_.json b/versioned_docs/version-3.0/flows/access-governance/_category_.json new file mode 100644 index 00000000..84656e51 --- /dev/null +++ b/versioned_docs/version-3.0/flows/access-governance/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Access & Governance", + "position": 2, + "key": "access-governance-flows" +} diff --git a/versioned_docs/version-3.0/flows/access-governance/create-a-role.mdx b/versioned_docs/version-3.0/flows/access-governance/create-a-role.mdx new file mode 100644 index 00000000..1c39eb99 --- /dev/null +++ b/versioned_docs/version-3.0/flows/access-governance/create-a-role.mdx @@ -0,0 +1,88 @@ +--- +sidebar_position: 1 +--- + +# How to create a role + +## Overview + +This flow describes how to create a custom [role](../../concepts/access-governance/role.mdx) in Care. A role is a named set of permissions that an administrator grants to a user inside a facility or an organization. + +## Pre-requisites + +- You sign in to Care with a super administrator account. +- You know the actions that the new role must allow. +- You know the boundaries where somebody grants the role: a facility, a government organization, or a responsibility. + +## Permissions + +Care controls the roles page by account type, not by a named permission. + +| Permission | Access | +| --- | --- | +| Super administrator account | Create, edit, and delete custom roles. | +| Any signed-in account | View the list of roles. | + +## Steps + +### 1. Open the roles page + +Select **Admin** in the sidebar. Select **RBAC**, then select **Roles**. Care shows the page **Roles** with the text "Manage Roles and Permissions". + +### 2. Start a new role + +Select **Add Role**. Care opens the panel **Add Role** with the text "Create a new custom role with specific permissions". + +### 3. Name the role + +| Components | What it captures | +| --- | --- | +| Name | The name of the role. The name is mandatory, and it must be different from the name of every other role. | +| Description | Free text that tells an administrator what the role is for. | + +### 4. Select the contexts + +Select a minimum of one context under **Contexts**. Care pre-selects **Facility** and **Government Organization**. + +| Context | Where somebody grants the role | +| --- | --- | +| Facility | Inside a facility | +| Government Organization | Inside a government organization | +| Responsibility | Inside a group of users | + +If you select no context, Care shows the message "Select at least one context". + +### 5. Select the permissions + +Care shows the permissions with a checkbox for each one. Select a minimum of one permission. + +- To find a permission, enter a part of its name in **Search permissions**. +- To select every permission in the list, select **Select All**. +- To remove your selection, select **Clear**. + +Care counts your selection above the list, for example "12 Selected". + +:::note +If you select no permission, Care shows the message "At least one permission is required". +::: + +### 6. Save the role + +Select **Create Role**. Care shows the message "Role created successfully" and closes the panel. + +## Expected Outcome + +- The new role is in the list on the **Roles** page. +- The card of the role shows its contexts and the number of its permissions. +- An administrator can now grant the role to a user inside a boundary that you selected. + +## Related + +Concepts: + +- [Role](../../concepts/access-governance/role.mdx) +- [Roles & permissions](../../concepts/access-governance/access-control.mdx) + +Flows: + +- [Edit or clone a role](./edit-a-role.mdx) diff --git a/versioned_docs/version-3.0/flows/access-governance/edit-a-role.mdx b/versioned_docs/version-3.0/flows/access-governance/edit-a-role.mdx new file mode 100644 index 00000000..3e2ac2ae --- /dev/null +++ b/versioned_docs/version-3.0/flows/access-governance/edit-a-role.mdx @@ -0,0 +1,78 @@ +--- +sidebar_position: 2 +--- + +# How to edit or clone a role + +## Overview + +This flow describes how to change a custom [role](../../concepts/access-governance/role.mdx), and how to clone a role into a new one. Care supplies the system roles, and you cannot change them. Clone a system role to start a custom role from it. + +## Pre-requisites + +- You sign in to Care with a super administrator account. +- The role is in the list on the **Roles** page. +- If you want to change the role directly, the role is a custom role. Care shows a **System** badge and a lock icon on each system role. + +## Permissions + +Care controls the roles page by account type, not by a named permission. + +| Permission | Access | +| --- | --- | +| Super administrator account | Create, edit, and delete custom roles. | +| Any signed-in account | View the list of roles. | + +## Steps + +### 1. Open the roles page + +Select **Admin** in the sidebar. Select **RBAC**, then select **Roles**. + +### 2. Find the role + +Enter a part of the name of the role in **Search Roles**. To show only the roles of one boundary, select **Facility**, **Government Organization**, or **Responsibility** above the list. To remove the filter, select **All**. + +If no role matches, Care shows "No roles found" with the text "Adjust role filters". + +### 3. Open the actions of the role + +Select the actions icon on the card of the role. Care shows **Edit** and **Clone**. Care shows **Edit** only for a custom role. + +### 4. Edit the role + +Select **Edit**. Care opens the panel **Edit Role** with the text "Update role name, contexts, and permissions". + +| Components | What it captures | +| --- | --- | +| Name | The name of the role. The name must stay different from the name of every other role. | +| Description | Free text that tells an administrator what the role is for. | +| Contexts | The boundaries where somebody grants the role. Select a minimum of one context. | +| Permissions | The actions that the role allows. Select a minimum of one permission. | + +Select **Update Role**. Care shows the message "Role updated successfully". + +:::note +Care keeps **Update Role** inactive until you change a value in the panel. +::: + +### 5. Clone the role + +Select **Clone**. Care opens the panel with the values of the source role and adds "(Copy)" to the name. Change the name, the contexts, and the permissions. Select **Create Role**. Care shows the message "Role created successfully". + +## Expected Outcome + +- The list on the **Roles** page shows your changes, or shows the new role from the clone. +- Each user who holds the role gets the new set of permissions. +- The system roles stay unchanged. + +## Related + +Concepts: + +- [Role](../../concepts/access-governance/role.mdx) +- [Roles & permissions](../../concepts/access-governance/access-control.mdx) + +Flows: + +- [Create a role](./create-a-role.mdx) diff --git a/versioned_docs/version-3.0/references/access-governance/role.mdx b/versioned_docs/version-3.0/references/access-governance/role.mdx index c1c6f5f9..746bbada 100644 --- a/versioned_docs/version-3.0/references/access-governance/role.mdx +++ b/versioned_docs/version-3.0/references/access-governance/role.mdx @@ -26,7 +26,7 @@ Both extend `BaseModel` (see [Base model](../foundation/base-model.mdx)), so the ## `RoleModel` fields -User-created roles can be deleted by anyone holding the right permission. System roles (`is_system=True`) are exempt: the API blocks creating, updating, or deleting them. +Only a superuser can create, update, or delete a role through the API. System roles (`is_system=True`) are exempt even then: the API blocks creating, updating, or deleting them. ### Identity & description @@ -197,15 +197,38 @@ Both queries join through `RolePermission` and exclude `temp_deleted=True` grant `invalidate_role_permissions_cache`, a `@receiver([post_save, post_delete], sender=RolePermission)` handler, clears both cache keys for the affected `role_id` on every create, update, or delete of a `RolePermission`. ORM writes invalidate the cache automatically; raw SQL writes skip the signal and leave stale caches behind. +## Viewset + +`RoleViewSet` (`care/security/api/viewsets/roles.py`) extends `EMRModelViewSet` with `database_model = RoleModel`, `pydantic_model = RoleCreateSpec`, and `pydantic_read_model = RoleReadSpec`. + +| Aspect | Behaviour | +| --- | --- | +| Authorization | `permissions_controller` returns `True` for `list` and `retrieve`; every write action requires `request.user.is_superuser`. No permission slug gates this viewset | +| Filters | `RoleFilter` — `name` (`icontains`) and `context`, which matches with `contexts__overlap=[value]` | +| Create | `perform_create` runs in a transaction, then materializes `instance.permissions` into `RolePermission` rows | +| Update | `perform_update` deletes the existing `RolePermission` rows and recreates them from the payload, so `permissions` is a full replacement, never a patch | +| Delete | `validate_destroy` raises `"Cannot delete system roles"` when `is_system=True`; `perform_destroy` also deletes the role's `RolePermission` rows | + +`_add_permissions` resolves the payload against `PermissionModel.slug`. `RoleCreateSpec.permissions` is typed against permission **names**, so a payload only takes effect where the permission `name` and `slug` agree. + +## Permission and role sync + +The `sync_permissions_roles` management command (`care/security/management/commands/sync_permissions_roles.py`) writes the code-declared permissions and system roles to the database. It runs under a Redis lock, marks existing rows `temp_deleted=True`, upserts every registered permission and role, deletes the rows that no handler still declares, then rebuilds the `RolePermission` rows for system roles from each permission's `roles` list. Run it after every deployment and plugin change. + ## API integration notes +- Only a superuser can create, update, or delete a role. Any authenticated caller can list and retrieve roles. - Both create and update go through `RoleCreateSpec`. `permissions` is required (≥ 1) and de-duplicated; you never set `is_system`, and `True` is rejected. +- Update replaces the role's permission set. Send the full list on every update. - Reads use `RoleReadSpec` (full, with nested `PermissionSpec[]`) or `RoleReadMinimalSpec` (no permissions), depending on the endpoint. - To change a role's membership, write `RolePermission` rows rather than editing `RoleModel` directly. Use the ORM so the cache-invalidation signal fires; raw SQL leaves the Redis cache stale. - Other access-control models (organization memberships, patient/encounter associations) reference roles to resolve a user's effective permissions in a given context. ## Related +- Concept: [Role](../../concepts/access-governance/role.mdx) +- Flow: [Create a role](../../flows/access-governance/create-a-role.mdx) +- Flow: [Edit or clone a role](../../flows/access-governance/edit-a-role.mdx) - Reference: [Permission](../access-governance/permission.mdx) - Reference: [Permission association](../access-governance/permission-association.mdx) - Reference: [User](../access-governance/user.mdx) diff --git a/versioned_docs/version-3.1/concepts/access-governance/access-control.mdx b/versioned_docs/version-3.1/concepts/access-governance/access-control.mdx index 699015a1..66342e8e 100644 --- a/versioned_docs/version-3.1/concepts/access-governance/access-control.mdx +++ b/versioned_docs/version-3.1/concepts/access-governance/access-control.mdx @@ -82,6 +82,8 @@ Permissions are declared in code per resource area and assigned to standard role ## Related +- Concept: [Role](../access-governance/role.mdx) +- Flow: [Create a role](../../flows/access-governance/create-a-role.mdx) - Reference: [Role](../../references/access-governance/role.mdx) - Reference: [Permission](../../references/access-governance/permission.mdx) - Reference: [Permission association](../../references/access-governance/permission-association.mdx) diff --git a/versioned_docs/version-3.1/concepts/access-governance/role.mdx b/versioned_docs/version-3.1/concepts/access-governance/role.mdx new file mode 100644 index 00000000..e58b76b8 --- /dev/null +++ b/versioned_docs/version-3.1/concepts/access-governance/role.mdx @@ -0,0 +1,82 @@ +--- +sidebar_position: 5 +--- + +# Role + +A **role** is a named set of permissions. You grant a role to a user inside one boundary, such as a facility or an organization. The role decides what that user can do inside that boundary. + +## What it represents + +Care has no separate list of powers for each person. Every ability comes from a role that somebody grants at a place. A role holds three things: + +- **A name** — what the deployment calls this set of permissions, for example "Doctor" or "Pharmacist". +- **A description** — free text that tells an administrator what the role is for. +- **Contexts** — the kinds of boundary where the role applies. +- **Permissions** — the actions that the role allows. A role needs a minimum of one permission. + +A role is not a job title. "Doctor", "Nurse" and "Pharmacist" are only permission sets with convenient names. Two roles with similar names have no relation to each other. Care also allows the same name in two different contexts: "Admin" exists as a facility role and as a separate responsibility role. + +:::note +A role is different from a **responsibility** (a role organization). A role is a set of permissions. A responsibility is a group of users. See [Organization](../access-governance/organization.mdx). +::: + +## Contexts + +The contexts of a role say where an administrator can grant it. A role with the Facility context only appears when somebody assigns a user inside a facility. + +| Context | Where the role applies | +| --- | --- | +| Facility | Inside a facility, and inside the departments of that facility | +| Government Organization | Inside a government organization, such as a state or a district | +| Responsibility | Inside a responsibility, which is a group of users | + +## System roles and custom roles + +Care marks the roles that it supplies with the **System** badge. A deployment can add custom roles beside them. + +| Type | Who creates it | What you can change | +| --- | --- | --- | +| System role | Care supplies it with the product | Nothing. You cannot edit or delete a system role. | +| Custom role | A super administrator creates it | The name, the description, the contexts, and the permissions. | + +To start a custom role from a system role, clone the system role. Care copies the permissions into a new role and adds "(Copy)" to the name. + +These are the system roles: + +| Role | Purpose | Contexts | +| --- | --- | --- | +| Doctor | Doctor at some facility | Facility, Government Organization | +| Nurse | Nurse at some facility | Facility, Government Organization | +| Staff | Staff at some facility | Facility, Government Organization | +| Volunteer | Volunteer at some facility | Facility, Government Organization | +| Pharmacist | Pharmacist at some facility | Facility | +| Administrator | Administrator at a given boundary | Facility, Government Organization | +| Facility Admin | Administrator of a facility. Care gives this role to the person who creates the facility. | Facility | +| Admin | Administrator of a facility or a government organization | Facility, Government Organization | +| Admin | Administrator of a responsibility | Responsibility | +| Manager | Manager of a responsibility | Responsibility | +| Member | Member of a responsibility | Responsibility | + +## How a role reaches a user + +A role gives no access on its own. An administrator grants the role to a user inside one organization or one facility. The user then holds the permissions of that role in that boundary and in everything below it. + +```text +User → Role → Boundary (facility, organization, or responsibility) +``` + +The same user can hold different roles in different boundaries. The access of a user on a record is the sum of every role that reaches that record. If you move a user to a new facility, the old access does not follow, because somebody granted it at the old boundary. + +## Permissions + +Every permission in a role is one action, such as "Can Create Patient". Care declares the permissions in the product, and an administrator selects them when the administrator builds a role. Care matches the permission to the kind of resource that the user acts on. For this reason, a permission for a patient does not also allow an action on a facility. + +## Related + +- Flow: [Create a role](../../flows/access-governance/create-a-role.mdx) +- Flow: [Edit or clone a role](../../flows/access-governance/edit-a-role.mdx) +- Concept: [Roles & permissions](../access-governance/access-control.mdx) +- Concept: [Organization](../access-governance/organization.mdx) +- Concept: [User](../access-governance/user.mdx) +- Reference: [Role](../../references/access-governance/role.mdx) diff --git a/versioned_docs/version-3.1/flows/access-governance/_category_.json b/versioned_docs/version-3.1/flows/access-governance/_category_.json new file mode 100644 index 00000000..84656e51 --- /dev/null +++ b/versioned_docs/version-3.1/flows/access-governance/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Access & Governance", + "position": 2, + "key": "access-governance-flows" +} diff --git a/versioned_docs/version-3.1/flows/access-governance/create-a-role.mdx b/versioned_docs/version-3.1/flows/access-governance/create-a-role.mdx new file mode 100644 index 00000000..1c39eb99 --- /dev/null +++ b/versioned_docs/version-3.1/flows/access-governance/create-a-role.mdx @@ -0,0 +1,88 @@ +--- +sidebar_position: 1 +--- + +# How to create a role + +## Overview + +This flow describes how to create a custom [role](../../concepts/access-governance/role.mdx) in Care. A role is a named set of permissions that an administrator grants to a user inside a facility or an organization. + +## Pre-requisites + +- You sign in to Care with a super administrator account. +- You know the actions that the new role must allow. +- You know the boundaries where somebody grants the role: a facility, a government organization, or a responsibility. + +## Permissions + +Care controls the roles page by account type, not by a named permission. + +| Permission | Access | +| --- | --- | +| Super administrator account | Create, edit, and delete custom roles. | +| Any signed-in account | View the list of roles. | + +## Steps + +### 1. Open the roles page + +Select **Admin** in the sidebar. Select **RBAC**, then select **Roles**. Care shows the page **Roles** with the text "Manage Roles and Permissions". + +### 2. Start a new role + +Select **Add Role**. Care opens the panel **Add Role** with the text "Create a new custom role with specific permissions". + +### 3. Name the role + +| Components | What it captures | +| --- | --- | +| Name | The name of the role. The name is mandatory, and it must be different from the name of every other role. | +| Description | Free text that tells an administrator what the role is for. | + +### 4. Select the contexts + +Select a minimum of one context under **Contexts**. Care pre-selects **Facility** and **Government Organization**. + +| Context | Where somebody grants the role | +| --- | --- | +| Facility | Inside a facility | +| Government Organization | Inside a government organization | +| Responsibility | Inside a group of users | + +If you select no context, Care shows the message "Select at least one context". + +### 5. Select the permissions + +Care shows the permissions with a checkbox for each one. Select a minimum of one permission. + +- To find a permission, enter a part of its name in **Search permissions**. +- To select every permission in the list, select **Select All**. +- To remove your selection, select **Clear**. + +Care counts your selection above the list, for example "12 Selected". + +:::note +If you select no permission, Care shows the message "At least one permission is required". +::: + +### 6. Save the role + +Select **Create Role**. Care shows the message "Role created successfully" and closes the panel. + +## Expected Outcome + +- The new role is in the list on the **Roles** page. +- The card of the role shows its contexts and the number of its permissions. +- An administrator can now grant the role to a user inside a boundary that you selected. + +## Related + +Concepts: + +- [Role](../../concepts/access-governance/role.mdx) +- [Roles & permissions](../../concepts/access-governance/access-control.mdx) + +Flows: + +- [Edit or clone a role](./edit-a-role.mdx) diff --git a/versioned_docs/version-3.1/flows/access-governance/edit-a-role.mdx b/versioned_docs/version-3.1/flows/access-governance/edit-a-role.mdx new file mode 100644 index 00000000..3e2ac2ae --- /dev/null +++ b/versioned_docs/version-3.1/flows/access-governance/edit-a-role.mdx @@ -0,0 +1,78 @@ +--- +sidebar_position: 2 +--- + +# How to edit or clone a role + +## Overview + +This flow describes how to change a custom [role](../../concepts/access-governance/role.mdx), and how to clone a role into a new one. Care supplies the system roles, and you cannot change them. Clone a system role to start a custom role from it. + +## Pre-requisites + +- You sign in to Care with a super administrator account. +- The role is in the list on the **Roles** page. +- If you want to change the role directly, the role is a custom role. Care shows a **System** badge and a lock icon on each system role. + +## Permissions + +Care controls the roles page by account type, not by a named permission. + +| Permission | Access | +| --- | --- | +| Super administrator account | Create, edit, and delete custom roles. | +| Any signed-in account | View the list of roles. | + +## Steps + +### 1. Open the roles page + +Select **Admin** in the sidebar. Select **RBAC**, then select **Roles**. + +### 2. Find the role + +Enter a part of the name of the role in **Search Roles**. To show only the roles of one boundary, select **Facility**, **Government Organization**, or **Responsibility** above the list. To remove the filter, select **All**. + +If no role matches, Care shows "No roles found" with the text "Adjust role filters". + +### 3. Open the actions of the role + +Select the actions icon on the card of the role. Care shows **Edit** and **Clone**. Care shows **Edit** only for a custom role. + +### 4. Edit the role + +Select **Edit**. Care opens the panel **Edit Role** with the text "Update role name, contexts, and permissions". + +| Components | What it captures | +| --- | --- | +| Name | The name of the role. The name must stay different from the name of every other role. | +| Description | Free text that tells an administrator what the role is for. | +| Contexts | The boundaries where somebody grants the role. Select a minimum of one context. | +| Permissions | The actions that the role allows. Select a minimum of one permission. | + +Select **Update Role**. Care shows the message "Role updated successfully". + +:::note +Care keeps **Update Role** inactive until you change a value in the panel. +::: + +### 5. Clone the role + +Select **Clone**. Care opens the panel with the values of the source role and adds "(Copy)" to the name. Change the name, the contexts, and the permissions. Select **Create Role**. Care shows the message "Role created successfully". + +## Expected Outcome + +- The list on the **Roles** page shows your changes, or shows the new role from the clone. +- Each user who holds the role gets the new set of permissions. +- The system roles stay unchanged. + +## Related + +Concepts: + +- [Role](../../concepts/access-governance/role.mdx) +- [Roles & permissions](../../concepts/access-governance/access-control.mdx) + +Flows: + +- [Create a role](./create-a-role.mdx) diff --git a/versioned_docs/version-3.1/references/access-governance/role.mdx b/versioned_docs/version-3.1/references/access-governance/role.mdx index c1c6f5f9..746bbada 100644 --- a/versioned_docs/version-3.1/references/access-governance/role.mdx +++ b/versioned_docs/version-3.1/references/access-governance/role.mdx @@ -26,7 +26,7 @@ Both extend `BaseModel` (see [Base model](../foundation/base-model.mdx)), so the ## `RoleModel` fields -User-created roles can be deleted by anyone holding the right permission. System roles (`is_system=True`) are exempt: the API blocks creating, updating, or deleting them. +Only a superuser can create, update, or delete a role through the API. System roles (`is_system=True`) are exempt even then: the API blocks creating, updating, or deleting them. ### Identity & description @@ -197,15 +197,38 @@ Both queries join through `RolePermission` and exclude `temp_deleted=True` grant `invalidate_role_permissions_cache`, a `@receiver([post_save, post_delete], sender=RolePermission)` handler, clears both cache keys for the affected `role_id` on every create, update, or delete of a `RolePermission`. ORM writes invalidate the cache automatically; raw SQL writes skip the signal and leave stale caches behind. +## Viewset + +`RoleViewSet` (`care/security/api/viewsets/roles.py`) extends `EMRModelViewSet` with `database_model = RoleModel`, `pydantic_model = RoleCreateSpec`, and `pydantic_read_model = RoleReadSpec`. + +| Aspect | Behaviour | +| --- | --- | +| Authorization | `permissions_controller` returns `True` for `list` and `retrieve`; every write action requires `request.user.is_superuser`. No permission slug gates this viewset | +| Filters | `RoleFilter` — `name` (`icontains`) and `context`, which matches with `contexts__overlap=[value]` | +| Create | `perform_create` runs in a transaction, then materializes `instance.permissions` into `RolePermission` rows | +| Update | `perform_update` deletes the existing `RolePermission` rows and recreates them from the payload, so `permissions` is a full replacement, never a patch | +| Delete | `validate_destroy` raises `"Cannot delete system roles"` when `is_system=True`; `perform_destroy` also deletes the role's `RolePermission` rows | + +`_add_permissions` resolves the payload against `PermissionModel.slug`. `RoleCreateSpec.permissions` is typed against permission **names**, so a payload only takes effect where the permission `name` and `slug` agree. + +## Permission and role sync + +The `sync_permissions_roles` management command (`care/security/management/commands/sync_permissions_roles.py`) writes the code-declared permissions and system roles to the database. It runs under a Redis lock, marks existing rows `temp_deleted=True`, upserts every registered permission and role, deletes the rows that no handler still declares, then rebuilds the `RolePermission` rows for system roles from each permission's `roles` list. Run it after every deployment and plugin change. + ## API integration notes +- Only a superuser can create, update, or delete a role. Any authenticated caller can list and retrieve roles. - Both create and update go through `RoleCreateSpec`. `permissions` is required (≥ 1) and de-duplicated; you never set `is_system`, and `True` is rejected. +- Update replaces the role's permission set. Send the full list on every update. - Reads use `RoleReadSpec` (full, with nested `PermissionSpec[]`) or `RoleReadMinimalSpec` (no permissions), depending on the endpoint. - To change a role's membership, write `RolePermission` rows rather than editing `RoleModel` directly. Use the ORM so the cache-invalidation signal fires; raw SQL leaves the Redis cache stale. - Other access-control models (organization memberships, patient/encounter associations) reference roles to resolve a user's effective permissions in a given context. ## Related +- Concept: [Role](../../concepts/access-governance/role.mdx) +- Flow: [Create a role](../../flows/access-governance/create-a-role.mdx) +- Flow: [Edit or clone a role](../../flows/access-governance/edit-a-role.mdx) - Reference: [Permission](../access-governance/permission.mdx) - Reference: [Permission association](../access-governance/permission-association.mdx) - Reference: [User](../access-governance/user.mdx) diff --git a/versioned_sidebars/version-3.0-sidebars.json b/versioned_sidebars/version-3.0-sidebars.json index d253abeb..741c2803 100644 --- a/versioned_sidebars/version-3.0-sidebars.json +++ b/versioned_sidebars/version-3.0-sidebars.json @@ -22,6 +22,12 @@ "label": "Clinical", "key": "clinical-flows", "items": ["flows/clinical/create-patient", "flows/clinical/manage-encounter-care-team"] + }, + { + "type": "category", + "label": "Access & Governance", + "key": "access-governance-flows", + "items": ["flows/access-governance/create-a-role", "flows/access-governance/edit-a-role"] } ] }, diff --git a/versioned_sidebars/version-3.1-sidebars.json b/versioned_sidebars/version-3.1-sidebars.json index ffc66fb9..9b891617 100644 --- a/versioned_sidebars/version-3.1-sidebars.json +++ b/versioned_sidebars/version-3.1-sidebars.json @@ -40,6 +40,12 @@ }, "flows/clinical/manage-encounter-care-team" ] + }, + { + "type": "category", + "label": "Access & Governance", + "key": "access-governance-flows", + "items": ["flows/access-governance/create-a-role", "flows/access-governance/edit-a-role"] } ] },