-
Notifications
You must be signed in to change notification settings - Fork 677
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
Add infrastructure for generic query augmentation [DATACMNS-293] #766
Comments
Neale Upstone commented This is exactly the issue I just came looking for. Participating in the creation and/or execution of the queries for CrudRepository methods is one part of the equation, the other is being able to add argument resolvers (such as being able to extract values from the Spring Security principle, and expose them as a named parameters, such that we could use it in JQL queries) |
Zoltan Altfatter commented Would be great to have this functionality |
Ian Duffy commented Any ETA on this? |
Pedro Vilaça commented As this issue isn't in-progress yet, do you suggest anything as a workaround to add a filter to the queries for entities that has a specific annotation? we're working with spring security ACL and we're trying to find a way to do the filtering without need to write all the queries by hand |
Brian Susko commented I'd also be interested in any recommendations on this until such case this is implemented. It seems there should be a lower-level API we can tie into to add a dynamic criteria. In the end, it would be nice to get access to the entity type also, so we can check for things like "if typeof T, add this criterion with a base interface for all entities needed. Something like that. Just my $.02, thanks |
Raghavendra Chary B commented Currently we are using below as a workaround: Where we use CrudRepository so that Spring security ACL PostFilter can be applied:
|
Oliver Drotbohm commented We'll be looking into this for the Gosling release train again. The biggest reason we haven't really gotten much farther is that we'd like to get more feedback on what we currently have. So everyone interested: there's actually a way to help us out with that:
|
Jordi Llach Fernandez commented After reviewing the changes done in sprin-data-commons and spring-data-jpa here are my thoughts. As far as I've seen I think that is approach is right as long as we have access to the entity type in the Thus one could implement a custom augmentor that could modify the query by checking if an annotated field of the entity contains certain values. |
Oliver Drotbohm commented That's very useful, thanks. Indeed annotations will definitely play an important role in augmentation as they're a nice tool to declaratively define expected augmenting behavior. That said, as you can see from the fact that The entity type is handed into the Does that make sense? |
Jordi Llach Fernandez commented Actually I was planning to use Maybe |
Oliver Drotbohm commented Just to make sure, we're on the same page here: |
Jordi Llach Fernandez commented My last comment about "(unnecesary?) extra checks" just tries to point out that IF To make it clearer, the code I was expecting to find in
About "AnnotationBasedQueryAugmentor considers repository annotations on both the type level as well as on methods" : |
Oliver Drotbohm commented The invocation of individual methods of the Also, keep in mind that the |
ken p commented I haven't had the time to pull the aforementioned branch, so forgive me for asking prior to doing so, but will the |
Gazal Gaffoor commented Any update on this issue? The code for DATAJPA-307 is ready, right? Is this issue pending on DATAMONGO-1151? |
François Lecomte commented Hi there. couldn't wait any longer for this to be fixed... so here's my proposal : a Spring Security extension with beans defining ACL strategies ; easy to plug with Post/PreAuthorize annotations, and able to inject ACL restrictions inside JPA queries (thx to Spring data JPA). noSQL databases are not yet supported, but that shouldn't hurt much. I'm interested in your feedback : |
Terje Strand commented As an alternative to François suggestion, I have been able to work around this issue by creating a custom implemented base repository class (i.e. use " By doing this, there are only 4 methods in QueryDslJpaRepository that needs to be extended/implemented in the base class: 'findAll(Pageable pageable)', 'findOne(ID id)', 'save(S entity)' and 'delete(ID id)'. The rest of the public methods I throw a 'not implemented exception'. I use QueryDsl to append predicates to queries to restrict the data set according to my data model. Three notes:
|
Oliver Drotbohm commented The problem unfortunately by far isn't that simple. If it was, we definitely wouldn't have postponed the inclusion of what we already have for so long. Even François' solution has quite some significant security holes, which — especially when adding security features to an API — is kind of problematic. It might just work for him, but it's definitely not something we can actually ship with the framework. It's not even a bug in his implementation really but the way that JPA works: if you read an instance of an entity, it doesn't have to be explicitly saved again. The JPA provider might just flush back changes. This alone makes it pretty tricky as you need to use store specific mechanisms — i.e. That said, I think it's kind of dangerous to throw something together that covers the happy path for oneself, throw this out and create the impression it'd solve a much broader problem. Especially when it comes to security related topics |
François Lecomte commented yeah u r right, my implementation is not fully operational, I agree it can't be shipped that way, and actually it's not the purpose. |
Casey Link commented We worked around this in a way similar to We implemented our own base repository implementation from scratch (not relying on Then in this repository implementation we add a protected method like the following that is used by the
Then we inherited from the base repository and implemented a new repository (along with a repository factory bean) that knows how/when to selectively augment the query based on the currently authenticated user. This ensures all standard query methods can be wrapped by our access control system. There is no way for a developer to write a query that could accidentally bypass the access control (one of our main concerns). It also plays nicely with spring data rest. However there are two limitations:
|
Connor Sadler commented Is this still being worked on please? Thanks |
I just stumbled upon this ticket as it's exactly what I was hoping was supported already out of box. Our use case, is that in a multi-tenancy system, we want to leverage authorization rules attached to roles that modify database queries - for example using the database to filter out documents that one might not have access to based on certain metadata values on those documents (and these fields we'd filter on are configurable by tenant). |
Multi-tenancy and role-based query filtering is the exact use case I'm thinking about as well. Any updates for this? |
Sure. I will add a comment for the yearly "Is this still being worked on?" |
Leaving a comment here, so that I get notifications. I need this for a multi-tenancy use case in ReactiveMongoRepository. I like the spring boot magic of queries from interface method names, but shame that we cannot use it when doing multi-tenant. |
Im facing currently the same problem as the guys before me, would be great to have this feature! |
Same issue here, same use case. This is a blocker for using Spring ACL to its fullest capacity, as there is no effective way to query for domain objects that a user has access to without querying ACL itself for all ObjectIdentities, then making a second query for all objects in that list. |
It seems that this issue is quiet old and has not seen any movement in a while, is there anything that we can do to make it more of a priority? I am happy to contribute if that will help get things moving. Seems like there are a number of interconnected issues across different spring projects that are not seeing any movement. |
I reached out to the data-mongodb team about the above ticket, and they suggested that a common pre-execution hook with a defined api be added instead of making a method visible. Is this repository a proper place to add such an api? |
Just checking back in for visibility here. The issue has been open for 11(!) years with no comment from the spring team. I am about to replace Spring ACL for a more supported library due to the lack of movement here, and I wanted to quickly see if the spring team has any plans on addressing this? |
I have begun the long process to learn an entire framework to address this. I cannot promise I have the skill or knowledge necessary to cover every use case, however it is my hope that I can address this and unblock a dozen use cases. Any help will be greatly appreciated. |
Let me be the first to say, Happy 2025! This issue is still open. |
Happy new years everyone! With an issue being over 12 years open you would assume someone would reply, but alas, the most common use case for spring ACL is still not possible for....reasons. For an otherwise stellar library, this is an exceptionally large hole that no one has addressed. I gave a crack at it, but after over a week of trying to understand the 'proper' way to get this done, I had to produce something and just worked around it. We modeled the spring ACL entity graph as our own classes, then threw them into QueryDSL to generate dsl-based Q-classes. We swapped around our own entity model so that we could use a common entity type as the parent class (In our case, called AclAwareEntity). All permissions were placed on the superclass instead of the individual entities. We then wrote an abstract predicate that did a left join on the entity superclass (using QClass._super) to check if the permission mask was there. We used a recursive SQL function to walk up the parent chain to handle ACL inheritance. We used AspectJ to then intercept the call to generate the search predicate and appended our acl-aware predicate on top of it. We had to manage ACL's manually for this, so we also had to write code to replace So pretty much we had to discard all the niceties of spring ACL, break object encapsulation and then write a whole service layer to fix something that has been requested for 12 years. |
Wow! 😮 That seems like a lot of work. I'm sorry you had to go through all that. It sounds like you needed a much more generic solution for ACL than even I needed. Can you tell me more about your query modifying Aspect? I've been tasked with re-investigating a rewrite of our current approach and so far the JPA Query interception in an Aspect is the only way I see to go about it. However, it seems exceedingly complex compared to our already complex approach that works. |
Yeah for sure.
The aspect is a pointcut around any method whose signature returns a
querydsl predicate, which also is annotated with @AclAwarePredicate.
The pointcut uses the target method to look up the implementing class
(manager service). Inside the manager service is a reference to the entity
being used by that manager (we try and force a single domain per manager
for code simplicity).
We use reflection on that entity to grab its @entity and @table annotations
(using the spring auto naming strategy as a fallback), as well as the ID
property of the entity.
Then, you can go one of two ways. Either you grab the generic Q class
(which is what I did) for the entity superclass and augment the query with
the ACL sub query, or you grab the actual entity primary class and replace
the incoming querydsl predicate with an instance of JPAQuery.
This is to handle inheritance, since you will need to force an inner join
on the base table and the sub table to search on entity properties and the
ACL table.
Then, the aspect returns a querydsl predicate object transparently to the
calling method who is none the wiser that anything has changed.
You can only do this with the repository methods that take a specification
or querydsl predicate (so pretty much JPASpeicificationExecutor and
QuerydslPredicateExecutor).
The derived queries as part of the SimpleJpaRepository aren't handled with
my method.
…On Mon, Jan 6, 2025, 10:20 a.m. Daniel Shiplett ***@***.***> wrote:
So pretty much we had to discard all the niceties of spring ACL, break
object encapsulation and then write a whole service layer to fix something
that has been requested for 12 years.
Wow! 😮
That seems like a lot of work. I'm sorry you had to go through all that.
It sounds like you needed a much more generic solution for ACL than even I
needed.
Can you tell me more about your query modifying Aspect? I've been tasked
with re-investigating a rewrite of our current approach and so far the JPA
Query interception in an Aspect is the only way I see to go about it.
However, it seems exceedingly complex compared to our already complex
approach that works.
—
Reply to this email directly, view it on GitHub
<#766 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AB35IPGZPSCJUV3IOMPNJ4L2JKNKXAVCNFSM5ZM6G742U5DIOJSWCZC7NNSXTN2JONZXKZKDN5WW2ZLOOQ5TENJXGMZTEOJVGU2A>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
Oliver Drotbohm opened DATACMNS-293 and commented
When working with repositories there might be use cases that involve the queries to be executed for that repository to contain some kind of global criteria. A good example for such a scenario is ACL based security to domain objects, e.g. with a global criteria causing the repository to only return domain objects created by the current user or only objects the current user is allowed to read.
A related example is working with data that has a soft-delete flag and essentially has to consider objects with that flag set to true non-existant.
Implementing these kinds of scenarios require the queries to the underlying store to be augmented with additional criterias. So we need to come up with some an SPI to prepare the query about to be executed and potentially even alter a
delete(…)
call into an update (for the soft-delete case).From a more general point of view we need access to the method the query is executed for and it's associated metadata
Issue Links:
SEC-2409 Spring Security / Spring Data Acl Integration
("is depended on by")
DATAMONGO-1151 Introduce ability to append queries against a particular collection
("is depended on by")
DATAJPA-307 Add support for soft deletes
DATAJPA-1551 Create an API to customize query creation and query processing
116 votes, 92 watchers
The text was updated successfully, but these errors were encountered: