65 lines
5.4 KiB
Markdown
65 lines
5.4 KiB
Markdown
This release replaces the fixed owner, admin and writer roles with roles and permissions you can build and assign from the web app.
|
|
|
|
## New
|
|
|
|
**Roles**
|
|
- A new Roles screen under Settings lists every role with its member count. You can create a role, edit its permissions in a grid, preview the result, reassign its members, delete it, and reset a built-in role to its defaults.
|
|
- Each permission is set to None, Own or All. Content permissions (read, create, update, delete, publish) can also be set per content type, and the per-type setting replaces the general one for that type.
|
|
- Three built-in roles ship with the app: Owner (locked), Admin and Writer. Only the Owner edits the Admin and Writer roles.
|
|
- Nobody can grant a permission they do not hold, edit their own role, or touch a role that holds more than they do.
|
|
|
|
**Users and ownership**
|
|
- Invitations carry a role (Writer by default), and pending invites show it.
|
|
- A Change role dialog on the Users screen moves a person to another role.
|
|
- The Owner can transfer ownership to a verified user by typing their email to confirm. The former Owner becomes an Admin, and the change takes effect at once.
|
|
- Users show who last assigned their role. Your Profile has a role card with a summary of what you can do.
|
|
|
|
**Content permissions**
|
|
- Articles and entries of custom content types follow the content permissions of your role. With Own, you only change what you created, and other people's items are shown as view only.
|
|
- Publish is its own permission: a role can write drafts without being able to put them online.
|
|
- The articles list and the editor hide or disable what your role cannot do, and say why.
|
|
- Settings pages are read only, with a banner, for roles that can view but not edit. Owner only actions are marked as such.
|
|
|
|
**Integration page**
|
|
- The Integration page has a search bar and a complete list of API routes, including the ones for API keys.
|
|
|
|
## Improvements and fixes
|
|
|
|
- API keys follow the current role of their creator, and the API keys screen says so.
|
|
- The Activity log records role changes, role edits, ownership transfers and the role of each invite, and has a Roles category with a diff of the grants in the detail panel.
|
|
- The "Jump to" links on the Integration page now scroll only the page's own scroll container.
|
|
- `/settings/permissions` is retired and redirects to `/settings/roles`.
|
|
|
|
## API
|
|
|
|
- `GET /v1/role`, `GET /v1/role/{id}`, `POST /v1/role`, `PUT /v1/role/{id}`, `DELETE /v1/role/{id}`, `POST /v1/role/{id}/reassign` and `POST /v1/role/{id}/reset` manage roles. Writes need a real session. Refusals are plain text codes such as `role_locked`, `own_role`, `escalation`, `role_name_taken`, `role_has_members` and `role_conflict` (stale `version`).
|
|
- `PUT /v1/user/{id}/role` changes a user's role with `{"role_id": N}`. It answers `403` `role_locked` for the Owner role and `403` `own_role` for your own account.
|
|
- `POST /v1/site/transfer-ownership` takes `{"user_id", "confirm_email"}`. It answers `400` `confirmation_mismatch` or `invalid_transfer`.
|
|
- `POST /v1/user/invite` accepts an optional `role_id`; the renew response and invite items carry the role.
|
|
- Changed: a refused call answers `403` `missing_permission` with an `X-Missing-Permission` header naming the permission, instead of "Only owners and admins can do this." or "Only the owner can do this.".
|
|
- Changed: user and invite items carry `role` as `{ id, name, built_in, locked }`, and the plain `role` string is gone. Accepted users also carry `role_assigned_by`.
|
|
- Changed: `GET /v1/auth/me` carries an `access` object with the role, the effective permissions and `role_assigned_by`.
|
|
- Changed: article and entry responses carry `created_by` for signed-in callers and API keys. Drafts are listed and read according to `content.read`.
|
|
- Changed: creating a content type whose key is `article`, `author`, `site`, `media` or `user` answers `409` `content_type_key_taken`.
|
|
- Changed: deleting a content type removes its per-type grants from every role.
|
|
- `GET /v1/activity` accepts the `roles` category and the new `user.change_role`, `user.transfer_ownership` and `role.*` events.
|
|
|
|
## Under the hood
|
|
|
|
- Roles, grants and a migration marker are stored in new tables, and the permission checks live behind a domain role package used by the HTTP middleware.
|
|
- New feature specs and tests cover the backend and the web app, in `features/roles_permissions_*.feature`, `features/roles_spa_*.feature`, `features/integration_search.feature` and `features/integration_api_key_routes.feature`.
|
|
- The design specs for roles are in `docs/design/screens/roles.md`.
|
|
|
|
## Upgrading
|
|
|
|
- Replace the binary, or pull the new image. Back up the database first as usual.
|
|
- The schema migrates by itself at startup. The three built-in roles are seeded, existing users and open invites are moved to the role matching their former owner, admin or writer value, and existing articles and entries get a creator when one can be found. The old `users.role` column stays in the database, unused.
|
|
- No new environment variable.
|
|
- Behaviour change for existing installs: Writers can no longer publish unless you grant it, and every restricted action now answers `missing_permission`.
|
|
- Clients that read the `role` string of users or invites must read `role.name` instead.
|
|
|
|
## Known limitations
|
|
|
|
- An unattributed article or entry (`created_by` 0) is owned by nobody, so a role at Own cannot change it.
|
|
- A user whose role no longer exists is denied everywhere and gets a `500` on `GET /v1/auth/me` until an Owner assigns a role.
|