Chen Li (Migrated from SEC-3212) said:

I was trying to authorize apis work with Spring Data JPA. When I try to authorize permission for getting page of entities, it throws the exception: java.lang.IllegalArgumentException: Filter target must be a collection or array type, but was Page 0 of 3 containing domain.Consumption instances

The code is:

@PreAuthorize(
        "hasRole('ROLE_USER')")
@PostFilter(
        "hasPermission(filterObject, 'read') or " +
        "hasPermission(filterObject, admin)")
Page<Consumption> getAllConsumptions(Pageable pageable);

Will Spring Security filter those are not a collection nor array like 'org.springframework.data.domain.Page' above?

Comment From: spring-projects-issues

Rob Winch said:

Thanks for the report! It is unlikely Spring Security will ever support @PostFilter on Page objects. This is because the result won't be valid anymore (i.e. you request 10 results, Spring Security will remove 2 of them and you will only have 8). Instead, you should use the Spring Data integration to update your query. See http://docs.spring.io/spring-security/site/docs/4.0.x/reference/htmlsingle/#data

Comment From: spring-projects-issues

Chen Li said:

@Rob You are right. Thank you :)

Comment From: rwong2000

@rwinch I am having trouble replacing the @PostFilter with @Query and hasPermission. Is there an example for this type of query ? Something along the lines of @Query("select e from MyEntity e where 1= ?#{hasPermission(e.id,'com.foo.MyEntity', 'read') } ") Page<MyEntity> findEntities(Pageable pageable);

Comment From: jorgeliano-lcg

@rwong2000 Did you ever get an example for this? I'm trying to do the same thing

Comment From: ghost

@jorgeliano-lcg & @rwong2000 did you guys find any solution to ?

@Query("select e from MyEntity e where 1= ?#{hasPermission(e.id,'com.foo.MyEntity', 'read') } ") Page<MyEntity> findEntities(Pageable pageable);

Comment From: sac-cas

Maybe not the right place, but how you manage such a query on a no sql db like mongo? Actually we got: @Query("{organization: ?#{ hasRole('ROLE_MANAGER') ? {$exists:true} : principal.organizationId}}") Page<Briefing> findAll(Pageable pageable); So if the user has the role manager he will get all entities otherwise only the one of his organization. I prefer using hasPermission instead of hasRole. Any idea?

Comment From: shamal

Refering to:

Rob Winch said:

Thanks for the report! It is unlikely Spring Security will ever support @PostFilter on Page objects. This is because the result won't be valid anymore (i.e. you request 10 results, Spring Security will remove 2 of them and you will only have 8). Instead, you should use the Spring Data integration to update your query. See http://docs.spring.io/spring-security/site/docs/4.0.x/reference/htmlsingle/#data

With the following code:

public interface BookRepository extends JpaRepository<Book, Long> {
    @PreAuthorize("hasAuthority('AUTHOR')")
    @Query("select b from Book b where b.author.id = ?#{ principal?.id }")
    Page<Facility> findAllOwned(Pageable p);
}

I'm getting the below error:

org.springframework.expression.spel.SpelEvaluationException: 
EL1008E: 
Property or field 'id' cannot be found on object of type 'java.lang.String' - maybe not public?

The full issue is in Stackoverflow https://stackoverflow.com/questions/48478982/spelevaluationexception-when-using-spring-security-expressions-with-query

Comment From: j3ernhard

I'm also working with Spring Data and Spring Security ACL and I have the same problem as @rwong2000 , @jorgeliano-lcg and @saubhagyab . Is there any working solution for that, I did not find anything on stackoverflow or elsewhere. I have debugged it and it searches with e.id on Page or Pageable instead of MyEntity.

Comment From: sebboursier

Same as @rwong2000, trying to access to a SPQL parameter in a SpEL expression that is itself in the SPQL.

@Query("select o from #{#entityName} o where 1 = ?#{@someBean.some(o, authentication)} ") Page<T> findAll(Pageable pageable);

But can't figure how to access 'o' in SpEL.

Comment From: selvaebi

Has anybody have any solution for this ? else any workaround for applying security over Page returning repository methods ? i can do a default implementation and apply security over it , but still checking is there any solution for this.

Comment From: RhysWilliams-CSI

Same as @rwong2000, trying to access to a SPQL parameter in a SpEL expression that is itself in the SPQL.

@Query("select o from #{#entityName} o where 1 = ?#{@someBean.some(o, authentication)} ") Page<T> findAll(Pageable pageable);

But can't figure how to access 'o' in SpEL.

Did you ever figure this bit out? Running into same issue.

Comment From: mikezerosix

Using @Query to solve problem in @PostFilter is not a solution, it is barely a temp workaround. That in unmaintainable spaghetti. Hardcododing S(P)QL code into your application is NOT a good solution.

Reopen this !

Comment From: epernice

For some use cases the @Query workaround seems like it would not work. For example, JpaSpecificationExecutor has this:

Page<T> findAll(Specification<T> spec, Pageable pageable);

Our codebase is using this heavily. I'm not sure how you would write a custom @Query that filters based on the provided spec and I suspect it is not feasible.