refac: debt on role backend
This commit is contained in:
1 parent
de142f6c5f
commit
a043f7f41a
130 files changed
+3591
-512
No files matched your search
+33
-3
@@ -11,8 +11,8 @@ for example `https://cms.example/v1/article/`.
|
||||
|
||||
## Authentication
|
||||
- Public routes need nothing: `GET /v1/article/`, `GET /v1/article/{id}`, `GET /v1/article/{id}/seo`
|
||||
and `GET /v1/site/{key}/sitemap`. They return online articles only; the list and the resolved SEO
|
||||
object also answer drafts to a verified session or API key.
|
||||
and `GET /v1/site/{key}/sitemap`. They return online articles, plus the drafts the caller's role may read
|
||||
(see [Content permissions](#content-permissions)); any other draft answers 404 `Article not found`.
|
||||
- Everything else needs a signed-in browser session (the `jwt` cookie) or an API key:
|
||||
`Authorization: Bearer rcms_...`. Create keys at `/integration/api-keys`. A key acts as its
|
||||
creator, with that user's role, and shows in full once.
|
||||
@@ -173,7 +173,7 @@ RenewCMS renders no page and injects no meta tag: it returns the data a frontend
|
||||
|
||||
| Route | Who | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `GET /v1/article/{id}/seo` | public for online articles; a verified session or API key also reads drafts | The resolved object `{ title, description, canonical_url, robots, og, twitter, image, authors, published_at, modified_at, fallbacks, json_ld }`. It never carries the body, the id or `seo_dismissed`, ignores `format`, and writes nothing. An offline article for any other caller, and a missing one, is 404 `Article not found`. |
|
||||
| `GET /v1/article/{id}/seo` | public for online articles; a verified session or API key also reads the drafts its role may read | The resolved object `{ title, description, canonical_url, robots, og, twitter, image, authors, published_at, modified_at, fallbacks, json_ld }`. It never carries the body, the id or `seo_dismissed`, ignores `format`, and writes nothing. An offline article for any other caller, and a missing one, is 404 `Article not found`. |
|
||||
| `POST /v1/article/{id}/seo/check` | verified session or API key (401 without credentials, 403 unverified) | Evaluates the article without saving. The body is `{}` or any of the twelve SEO fields of `PATCH` plus `body`; each replaces the saved value for this check only. `site_id`, `author_ids`, unknown fields and `null` (except on `cover_image_id` and `social_image_id`) are 400 with the body-mismatch message. The other validation is the one of `PATCH` (`invalid_slug`, `invalid_url` as 422, `image_not_found`, validator text). Answers `{ status, suggestions, slug }` where `suggestions` is `[{ code, field, params }]` and `slug` is `{ available, suggestion }`. A taken slug is a 200 with `available: false` and the first free `<slug>-N` in `suggestion`, never a 409. |
|
||||
| `GET /v1/site/{key}/sitemap` | public | A JSON array `[{ url, modified_at, noindex }]` of the online articles of the site with that key, by id ascending. `url` is `base_url/slug` (never the canonical override). `page` (default 1) and `size` (25, 50, 100 or 500, default 100); an invalid value is 400 with the body-mismatch message. The total is in the `X-Total-Count` header. An unknown key, an id included, is 404 `site_not_found`. |
|
||||
|
||||
@@ -353,6 +353,36 @@ disabled variant on `POST`), 413 "The source image is too large to generate this
|
||||
source image can't be read, so this variant can't be generated.", 422 "Variants aren't generated for
|
||||
this format." and 500 "Internal server error".
|
||||
|
||||
## Content permissions
|
||||
|
||||
Articles and the entries of custom content types are checked against the `content.*` permissions of the
|
||||
caller's role, which is read on every request (a key follows its creator's role).
|
||||
|
||||
| Route | Permission | Scope check after the lookup |
|
||||
| --- | --- | --- |
|
||||
| `GET /v1/article/`, `GET /v1/article/{id}`, `GET /v1/article/{id}/seo` | public, `content.read` widens what drafts show | online articles, plus drafts when `content.read` is `all`, or the caller's own drafts when it is `own` |
|
||||
| `POST /v1/article/{id}/seo/check` | `content.read` | the article must be visible, else 404 |
|
||||
| `POST /v1/article/` | `content.create` | none; `created_by` is the caller and the article is always a draft |
|
||||
| `PATCH /v1/article/{id}` | `content.update` | `own` needs `created_by` to be the caller |
|
||||
| `DELETE /v1/article/{id}` | `content.delete` | same |
|
||||
| `PATCH /v1/article/{id}/publish`, `/unpublish` | `content.publish` | same; `PATCH` never changes `is_online` |
|
||||
| `GET /v1/content-type/{key}/entry`, `GET .../entry/{id}` | `content.read` for `{key}` | `own` lists only the caller's entries (total, page, size and `q` follow) and answers 404 `entry_not_found` for another's entry |
|
||||
| `POST /v1/content-type/{key}/entry` | `content.create` for `{key}` | `created_by` is the caller |
|
||||
| `PUT`, `DELETE .../entry/{id}` | `content.update`, `content.delete` for `{key}` | `own` needs `created_by` to be the caller |
|
||||
|
||||
Each action reads its own permission: publish does not imply update, update does not imply read. `own`
|
||||
means `created_by` equals the caller; an unattributed item (`created_by` 0) is owned by nobody. A permission
|
||||
can also be set for one content type (`content.update:blog`, `content.update:article` for articles); that
|
||||
row replaces the wildcard for the type, whether it lowers or raises it, and a `none` row denies. Only the
|
||||
wildcard applies to a type with no row. An id that does not exist is 404 even for a caller at `own`.
|
||||
|
||||
A refusal is 403 `missing_permission` with `X-Missing-Permission` set to the base key (`content.update`,
|
||||
never `content.update:blog`). The permission is checked before the id and the body are read, then the scope
|
||||
after the lookup, and a refused call writes nothing and records no activity event. The verification and
|
||||
token checks still come first. Creating a content type whose key is `article`, `author`, `site`, `media`
|
||||
or `user` is 409 `content_type_key_taken`. Owner-only permissions only count on the locked Owner role: the
|
||||
same key placed by hand on another role is ignored and `GET /v1/auth/me` does not list it.
|
||||
|
||||
## Errors
|
||||
Every error is a plain-text body with one sentence; the status is in the HTTP status line. The
|
||||
statuses are 400, 401, 403, 404, 409, 429 and 500. Messages are listed on the Integration page.
|
||||
|
||||
Reference in new issue
Block a user