-
Notifications
You must be signed in to change notification settings - Fork 2.8k
rfc: check condition in update permissions #3750
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
rfc: check condition in update permissions #3750
Conversation
paf31
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd be fine with this approach, but conceptually, I think the check constraint should live at the table/role level and be the same across updates and inserts. That way, the constraint acts like an invariant that must always be true for rows created in the table touched by users in that role. Disabling inserts for a role should IMO be a separate concern.
Notes:
- The idea of check constraints as invariants doesn't quite work when we allow
existsin conditions, because we can break the invariant by updating the joined table. Not sure if we want to consider that here. - It's also possible for one user to make it impossible for another user in a different role to update a row, in a new way which was not possible before. If a role R has update access to columns C1, C2, C3, say, and a check constraint on updates which involves data in column C4, an admin could modify C4 to make it impossible for a user in role R to ever satisfy the constraint. Again, not sure if we want to think about that case, but maybe the error messages won't be very informative if we don't.
lexi-lambda
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with @paf31’s comments. It seems a little bit odd to me to have to specify the same rules so many times:
-
The user has to set the permissions on what can be inserted.
-
Then they probably have to restrict updates to rows that satisfy those same conditions.
-
Finally, they have to also specify that the result of the update can’t break the invariants they already specified twice.
It’s possible that sometimes people want these things to be different, but it seems likely that, in the vast majority of cases, they want them all to be the same. Do you think we can come up with a design that matches that logical model a little bit better? I like Phil’s idea about making these a property of the table rather than something that belongs to a particular operation.
|
@paf31 The
You can have different conditions to check on
The check constraint will only be checked during the operation.
I'm sorry I don't quite follow this. The admin role could also modify some column involved in the
The console already helps with this situation, it lets you copy a condition from other permissions. So you would only write these rules once if they are all the same (but yes you would still have to say 'same as ..' multiple times which I don't think can be avoided).
I agree, our permissions API on the server is a bit low level (the console improves the DX by providing options like copying conditions etc), we can definitely add higher level abstractions at the server itself, maybe like Phil suggested, we can allow users to define conditions on a table and allow referring to these conditions by names when specifying permissions. However I feel that we can open a new RFC for this as
|
|
I just wanted to add my 2 cents around how I think about check contraints and permissions. This might not be completely related but seems relevant.
We often think of using permissions as a way to enforce general data consistency but that should be an anti-pattern as I can always then cause data inconsistencies by making a request as an admin. |
|
Sorry if this is a dumb question, but is there a reason why we're not reusing Postgres' row level security directly then? I know this would require mapping our roles to Postgres roles, or something like that, but it seems simpler than implementing a mirror of its permission system. Is it missing something we want? |
Couple of reasons:
|
|
Any thoughts on what the UI should look like for permissions? Right now it refers to "checks" even though those are currently really filters, but now we will have checks too :) |
|
If an insert becomes an update via |
I believe the update check should kick in as technically the insert is now reduced to an update
Seems like the row permissions section will need to be further split into 2 sections now, a "before check" and an "after check". I currently can't seem figure out what the messaging should be for the 2 sections to get away with minimal changes. Will give it some more thought and get back. Ideas are welcome of course :) |
@paf31 This is discussed in the 'Implementation' section of the RFC.
|
In that case, I will just carry on without implementing the console changes for now. It should be fine to merge this without UI support, since there are no breaking metadata changes. Perhaps if anyone needs this feature immediately, we can guide them on using the console to set these permissions? @0x777 @rikinsk In the meantime, I will work on updates to the |
@paf31 I really want to test it with your help. I can provide extensive feedback about the feature. As you may already know, I have suggested and gave a real-world example for it on #3536 also in this comment The lack of this feature is a blocker at the moment, unfortunately. I really appreciate all of your kind efforts. |
|
@yasinarik If you're able to build my branch then you should be able to use the API or the console to set update permissions on your table. There is a small example in the test suite in my branch: |
@paf31 Really sorry for bothering you too much Dear Freeman; however, I think I need a guide on this. I have never used Hasura without the web console (always used it with the UI). May I request a bit more help? I've checked the example btw. How long will it take do you guess the |
|
@yasinarik One option is to export metadata from the settings page in the console, edit the JSON to add the The simpler way might be to use the Please let me know if you need more help. |
|
@paf31 Dear Phil, I couldn't manage to build your branch that includes the required changes. Actually I couldn't find the right resources to do that. Also, I can say that I don't know how to build your branch and deploy that version on, let's say, Heroku. I understood how to export metadata and make changes then import it. It's OK. Is This Feasible?Apart from that, per my understanding, there seems to be no way to combine I don't know if it makes sense to you guys; however, my idea is to combine the separately written before and after conditions. The current improvement is great, I have to say that I can't express how I am glad about it. I just want to tell you that there are a lot of real-world scenarios that it is not appropriate to define all the before conditions in a single I imagine defining the Let me illustrate: Extended Example: |
|
Review app https://hge-ci-pull-3750.herokuapp.com is deleted |
|
Deploy preview for hasura-docs ready! Built with commit 52e2ea8 |
I definitely agree with this.
I'm not sure what the exact interface should be, but I think the biggest limitation currently in the check expression is that you cannot use the values of columns from before the update (old value of a column). Adding the ability to use 'old' values of a column in check expression is not easy to implement, we'll need to 1. come up with a meaningful syntax and 2. map to appropriate postgres sql statements (this is particularly hard because of upserts) About your use case here, wouldn't the recommendation in #3536 (comment) work? |
|
One idea could be to use a list of But, that would be outside the scope of this discussion. |
Can be previewed here. Issue: #384