0

I have a repository looking like this (with other CRUD methods stripped)

import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.StringPath;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.querydsl.binding.QuerydslBinderCustomizer;
import org.springframework.data.querydsl.binding.QuerydslBindings;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.lang.NonNull;
import org.springframework.security.access.prepost.PreAuthorize;

import java.util.Optional;
import java.util.UUID;

@PreAuthorize("hasRole('" + Constants.ROLE_USER + "')")
public interface ProjectRepository extends CrudRepository<Project, UUID>, QuerydslPredicateExecutor<Project>, QuerydslBinderCustomizer<QProject> {
    @Override
    default void customize(@NonNull QuerydslBindings bindings, @NonNull QProject root) {
        bindings.bind(String.class).first(
                (StringPath path, String value) -> path.containsIgnoreCase(value));
        bindings.including(root.name);
        bindings.including(root.description);
    }

    @Override
    @Query("select p from Project p left join p.roles r left join r.account a where ?#{principal.username} = a.username")
    @NonNull
    Page<Project> findAll(@NonNull Predicate predicate, @NonNull Pageable pageable);
}

As you can see I have a @Query annotation that limits the response of findAll based on who the user is. This causes the Predicate to be ignored entirely. So if I search for anything, it still returns all objects the user has access to. If I remove the @Query annotation then the searching works correctly. But of course I want my security to be applied. Is this a bug in QueryDsl? Or simply a limitation? How could I make this work?

Sebastiaan van den Broek
  • 5,818
  • 7
  • 40
  • 73
  • 1
    I doubt if you can combine both `@Query` and `@Predicate` https://stackoverflow.com/questions/26379522/can-i-combine-a-query-definition-and-specifications-on-one-spring-data-jpa-repo. Can you not specify the `a.username` search in the `Predicate` itself? – Madhusudana Reddy Sunnapu Mar 16 '18 at 07:51
  • I would really prefer to keep my security in 1 place, but perhaps I won't be able to. I'm not sure how I can modify this predicate as it's coming directly from the request, with Querydsl web support. But I'll try to figure that out.. – Sebastiaan van den Broek Mar 16 '18 at 09:14
  • I have never used it. But may be your repository can can ectend QuerydslBinderCustomizer and in the customize method QuerydslBindings can update Predicate to contain username. http://www.baeldung.com/rest-api-search-querydsl-web-in-spring-data-jpa – Madhusudana Reddy Sunnapu Mar 16 '18 at 11:58
  • can't get the QuerydslBinderCustomizer approach to work. Did you ever figure out a good solution for this? I'm facing the same issue. I suspect the only answer is going to be adding a controller/service layer in, but I'm keen to avoid that. – Gavin Clarke Jul 11 '18 at 15:28
  • @GavinClarke I didn’t, we dropped the whole thing for now. – Sebastiaan van den Broek Jul 11 '18 at 15:30

0 Answers0