Replies: 2 comments
-
casl was not designed to support state machine flows. But I see 2 options which you can use:
allow('publish', post, { status: 'draft' }) // draft -> published
allow('discard', post, { status: 'draft' }) // draft -> discarded
allow('discard', post, { status: 'published' }) // published -> discarded Using fields level permission to represent the initial state is a bit weird and I think is the wrong way. The best one, obviously is to built a specialized library for this: state('status', (transition) => {
transition("draft", { to: ["published", "discarded"] });
transition("published", { to: ["discarded"] });
// etc
}) This is business logic related stuff which very likely does not depend on user permissions and that's why should be implemented separately IMO |
Beta Was this translation helpful? Give feedback.
-
@stalniy Agree on all points and thanks for the pointers to other options. The reason this business logic is getting mixed in with user permissions was abstracted out of my initial writeup. In our case, different user roles in our system have different permissions around specific transitions. To extend the Post example, a user with the "manager" role can "publish" a draft on behalf of someone else, but someone with an "editor" role cannot. From a DX perspective, we've embraced the Many thanks! Love the library 👍 |
Beta Was this translation helpful? Give feedback.
-
We have several domain models that support a
status
field, and business rules which control what transitions are allowed in each state, all of which can be modeled with a basic state machine. My current understanding of the CASL api says that specifying permissions for State Machine transitions is not possible using the core API. I'm posting this to see how others have approached the state machine problem, see if this has been considered (or built, we're still on v3 😬), or if not, propose an api that would fit nicely with the project.State Machine Problem: Controlling Status Transitions
What I see missing in CASL is the ability to specify a target state for permissioning, ie: I can define permissions for changing a specific field, but I cannot define permissions for setting a specific field to a specific value. While we have many more statuses and conditions on each transition, the scenario can be simplified to the "post" model used elsewhere in the docs. For the sake of explanation, I propose adding a "status" field to the Post model, with the hope of defining the following simple state machine:
I'm currently playing around with modeling this via a custom action, "transition," and (ab)using the fields prop to serve as a proxy for the target state. It looks like this:
which will work fine, but feels like a misuse of the api. This feels like a common problem, that I would ...
Proposed API:
I propose extending how "field" permissions are checked/calculated, and allow for objects to be passed in the fields place to define specific transitions. Continuing the scenario above, this would look like:
The biggest drawback to this approach (aside from any technical considerations) is the readability/DX, since the last arg (conditions) is the current value, while the second to last (fields) is the target, which essentially reverses the natural transition order. In writing the example, I got tripped up a few times and added the transition comments on each line of the definition.
Would love to hear people's thoughts on this topic
Beta Was this translation helpful? Give feedback.
All reactions