-
-
Notifications
You must be signed in to change notification settings - Fork 276
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
Handling inverted and direct rules with same condition when interpreting SQL conditions #1010
Comments
I also always had hard time to translate such intersection to DB query and as a result this edge case has never been solved on casl side. The recommendation says to get rid of inverted rules as much as possible. If you do not use them then you don’t have to solve this edge case. |
But it works better than it sounds from my message above. Because the issue appears only if we use the same property in you can safely combine can and cannot rules for db queries if they do not use the same attributes. But if they use the same attributes the logic should be changed and more complex SQL query must be generated by interpreter |
There is a way to make it work in SQL via Obviously this can be optimized to normal For example this: cannot('manage', 'Post', { id: { $gte 5 } })
can('manage', 'Post', { id: 10 })
can('manage', 'Post', { id: 1 })
cannot('manage', 'Post', { id: 1, private: true }) is translated to: CASE
WHEN id = 1 AND private = true THEN FALSE
WHEN id = 1 THEN TRUE
WHEN id = 10 THEN TRUE
WHEN id >= 5 THEN FALSE
END But it can be rewritten to (id = 1 AND private = false) OR id = 10 OR id < 5 and the actual casl rules also can be rewritten to get this better result: can('manage', 'Post', { id: { $lt 5 } })
can('manage', 'Post', { id: 10 })
can('manage', 'Post', { id: 1, private: false }) That's why the general recommendation to use direct rules still remains valid and will produce more optimized SQL query eventually |
The same is possible in MongoDB, either with |
Thanks so much for the in-depth response @stalniy! We're going to stick with this and invest some more time here on possible solutions to consistency between runtime and mapping to MariaDB. Knowing this is an edge-case motivates spending a bit more time trying to figure something out that could work. Toward your recommendation to not rely on inverted rules: we can certainly model "negative permissions" and map that to what the direct rules should be when hydrating users' Ability instances. I want to spend a bit more time working on a successful runtime-to-database mapping that includes conflicting direct/inverted rules, but I do fear that what we'll end up with is much less comprehensible than simple direct rules. Thanks again for the advice. We'll add any further insight we glean to this issue. |
Hello!
First, thanks so much for this library! We've gotten a lot of use out of CASL so far. Up to this point, we've yet to convert resource collections of our REST API to be scoped based on the CASL ability instance for a given user (we're reliant on legacy code to do this). Making this leap is one of the last steps we need to take to deprecate our legacy permissions model implementation.
We use
knex
and scope queries on REST resource collections before applying user-provided filters onto the query. We would instead like to use the interpreter in@ucast/sql
to process the Ability instance AST; producing a raw where constraint we can apply to our query builder.For additive permissions, everything seems to work as expected. However, we need to be able to support negative (inverted) permissions as well. The ability instance handles this great when querying permissions on individual resources. However, something is lost in translation in our processing of the underlying AST when producing SQL and after tinkering for a while and doing some research, we're left thinking this HAS to be a common problem others have solved.
I've created a simple example that demonstrates what we're trying to achieve:
Output when ordering is
cannot
beforecan
Output when ordering is
can
beforecannot
A few important notes:
ability.can
check behaves as expected. I will lose access if thecannot
comes last and I retain access ifcan
is last.We've also come across https://gist.github.com/ygrishajev/9ef01444fdb5c386c43b6611400c0fc6 which uses
rulesToQuery
to return AST nodes and constructs a compound condition manually. However, it seems to hit this same issue when there are inverted and non-inverted rules applied to a resource where you get a lossy translation to the database; differing from results you see callingability.can
.The text was updated successfully, but these errors were encountered: