RFC 115: Write API#115
Conversation
8bc966a to
a134a61
Compare
|
hi @thibaudcolas, so I know ninja is more well known but I have been looking into django-bolt. IF it was actually used my something as large as Wagtail, it would hopefully thrive. What I will say: I did develop this https://github.com/sinnwerkstatt/wagtail-ninja and I have a bunch of thoughts; if you're interested maybe we'll videocall about it? |
|
@andreasnuesslein I’d love to chat! will DM you on Slack. I’d love to do a "Wagtail on django-bolt" prototype. I expect it’s not going to score well with our criteria (compatibility is paramount, speed not so much). But it’d be a good stress-test of how well our implementation is layered. |
|
|
||
| - Clients send `Authorization: Bearer <token>` on every v3 request. | ||
| - Token issuance TBC - [`wagtail-write-api`](https://github.com/tomdyson/wagtail-write-api) precedent for reference: | ||
| - Tokens are 40-character hex keys, Wagtail-specific `ApiToken` model, many-to-one user. Keys are generated with `secrets.token_hex(20)` on creation. |
There was a problem hiding this comment.
In DTAP, code moves trough each environment from D to P.
Data moves the other way: PRD data is often copied under DEV to replicate a bug, or under ACC to validate something. ACC environments are also used to build and validate external integrations against. Like Write API clients.
Storing tokens in the DB means that copying the PRD data under ACC will destroy existing ACC tokens. Breaking those ACC Write API clients.
I'd like a way to dump and restore tokens. Maybe that is just ./manage.py dumpdata ... and loaddata.
Maybe Wagtail can help with persisting tokens? For example loading them on startup from a setting?
I can see the advantage in Wagtail Admin managed tokens, but there might be projects where you'd want tokens to be developer managed, and not editable via a management interface at all.
There was a problem hiding this comment.
yep that makes sense to me! I expect our core token implementation has to be usable enough so people don’t have to create custom auth code per project, but flexible enough that other forms of API auth and token management are also supported? Hence why the plan is for an admin interface. Management via the environment makes sense too, though would need to check how we’d make that work in conjunction to user accounts - would those tokens also map to a specific user account or not.
There was a problem hiding this comment.
Projects I work on have the same user on ACC and PRD. And we can restore tokens by selecting the user by username. We broke client authentication more often then I'd like to admit ;)
In think db stored and admin interface managed tokens are the way to go. It seems the desired way to manage tokens in the majority of projects. And has more advantages, like token invalidation. Permission on the model is sufficient to disallow access it if needed.
Being able to set the tokens, even if only programmatically is important. Maybe that is a sufficient requirement for now?
laymonage
left a comment
There was a problem hiding this comment.
This is very well-written, thanks Thibaud!
I'm happy with the proposal. There are lots of unknowns that aren't easy to determine at this stage, but I think this is a solid foundation to build the work on.
|
|
||
| TBC: Schemas should be cacheable client-side via a process-lifetime ETag. | ||
|
|
||
| It’s important the schema contains information that goes beyond data validation (like `help_text` overrides, `HelpPanel` contents, etc), so external CMS clients can provide the same information to their users. |
There was a problem hiding this comment.
I see its usefulness, but given things like HelpPanel require template rendering (and result in HTML), I wonder if that is something we do want to include in the API 🤔
Something to think about when implementing later I guess?
| ### Do we really want auto-incrementing IDs in the API? | ||
|
|
||
| Maybe, maybe not? See [Add a UUIDField to the Page model #6162](https://github.com/wagtail/wagtail/issues/6162), and [Support customizing/encoding IDs in the API #6917](https://github.com/wagtail/wagtail/issues/6917). | ||
|
|
||
| The write API is viable regardless of the IDs being used but it’s a good time to revisit this if we wanted. |
There was a problem hiding this comment.
I personally don't see this as a problem, given that the existing read API already works this way, and write access will only be given to those with the same permissions in the admin (which also use the auto ID by default).
| 1. **Schema layer** — request shape, types, required vs. optional fields. Generated from per-content-type Pydantic schemas (Django Ninja). Failure → **422** (Ninja/Pydantic default). | ||
| 2. **Content format layer** — StreamField block types validated against registered block definitions; rich text content validated against the declared `RichTextField` features whitelist. Failure → **422**. | ||
| 3. **Model layer** — `full_clean()` and other model-level constraints. Failure → **422**. | ||
| 4. **Permission layer** — checked before model save. Failure → **403**. |
There was a problem hiding this comment.
I get that this makes sense if we put (and use) the permission checks in the operations layer, but FWIW permission checks for the CMS itself is usually done in the view at the beginning of the request handling, after the object was retrieved.
I think this was probably the main motivation behind skip_permission_checks in the actions module. (If the view has already checked for permissions, it can be skipped during the operation execution.)
Not sure how much it matters, but worth flagging if we want the behaviour to be as close as the CMS/admin UI as much as possible.
It probably is better to put the permission checks inside the operations layer and use it that way in the API. This ensures future operations have the permission checks built into them, and any code that uses them won't have to worry about it. Then eventually maybe we refactor the admin views to use the same pattern.
|
|
||
| #### Workflow as validation | ||
|
|
||
| Some operations are valid in field-shape but invalid in workflow state, like submitting an already-published page to workflow. |
There was a problem hiding this comment.
This might not be the best example, isn't "submitting an already-published page to workflow" a normal use case when you want to moderate further edits?
Maybe something like "submitting a page that has an in-progress workflow to a new workflow", or "approving/cancelling a page that has completed its (or is not currently in a) workflow)"
| - [`FieldPanel`](https://docs.wagtail.org/en/stable/reference/panels.html) configuration: `help_text`, `read_only`, `required_on_save`, `permission`, `disable_comments`. | ||
| - Capabilities of other panels, such as [`PageChooserPanel`](https://docs.wagtail.org/en/stable/reference/panels.html#wagtail.admin.panels.PageChooserPanel) page-type filtering. |
There was a problem hiding this comment.
I'm a bit wary about coupling api_fields with panels. It does make sense if we view the API as a headless version of the CMS, but I can imagine people wanting to keep them separate.
Also we'll probably need a mechanism to "retrieve the panel instance for a given field of a model". I don't think it exists yet atm, and not sure how much work it is to get right (and performant).
I'm not against the idea, just thought it's worth flagging.
Stormheg
left a comment
There was a problem hiding this comment.
Thanks, this is really comprehensive. The scope and implementation plan looks fine to me. There's nothing I can think of right now that is missing.
My only question – already tackled in this document – what happens to the v2 api?
It is not easy to deprecate and remove, since many implementers will have build their sites/apps with it may have customized it with new filters and endpoints and such. I know I have done this.
For this reason, even if the v3 api matches the v2 api mostly, I feel we should continue to support the v2 api, with a long deprecation cycle since it is such an extensively used component that's hard to swap out for something new (clients need to be updated).
View as HTML. Feedback welcome! (see below). Pending approval by the core team, we’re tentatively planning to work on this with an initial version of the API shipping in Wagtail 8.0 in August 2026.
Key design decisions
Feedback welcome
Very keen to hear general feedback, and potential use cases people are interested in: what kinds of clients you’d want to see and how you’d use them.