Patrick Grimard
Patrick Grimard

Reputation: 7126

Spring Data REST filtering data based on the user

If I have a repository setup like the following, making use of Spring Data REST, I can access the data at /receipts and see all data. However, I want to only return data for the user. I have a custom finder "findByStorer" which would do this. How would I get Spring Data REST to use this and get the storer value from the user rather than specifying a query parameter?

@RepositoryRestResource(collectionResourceRel = "receipts", path = "receipts")
public interface ReceiptRepository extends PagingAndSortingRepository<Receipt, BigDecimal> {

    @Query
    public Page<Receipt> findByStorer(String storer, Pageable pageable);
}

I haven't implemented any security yet, so this question is more theory at the moment than practice.

Thanks.

Upvotes: 8

Views: 7996

Answers (4)

pdorgambide
pdorgambide

Reputation: 1867

This issue is a tipical cross-cutting concern so I tried apply AOP. Define Advice and update the args (String storer), as explain at: https://stackoverflow.com/a/46353783/1203628

@Aspect
@Transactional
@Component
public class FilterProjectsAspect {

@Pointcut("execution(*  com.xxx.ReceiptRepository.findByStorer(..))")
    public void projectFindAll() {
    }

    @Around("projectFindAll()")
    public Object  filterProjectsByUser(final ProceedingJoinPoint pjp) throws Throwable {

        Object[] args = pjp.getArgs();
        for (int i = 0; i < args.length; i++) {
            if (args[i] instanceof String) {
                String storer=(String) args[i];
                // Find storer by user 
                args[i]=storer;  //Update args
            }
        return pjp.proceed(args);
    }

}

Upvotes: 0

Daniel Cerecedo
Daniel Cerecedo

Reputation: 6207

For example, given a Repositoryfor SomeEntity you could override findAll method with a custom @Query filtering by attribute ownerwith value of`#{principal.username}

@RepositoryRestResource(path = "some-entities", collectionResourceRel = "some-entities", itemResourceRel = "some-entity")
interface SomeEntityRepository extends PagingAndSortingRepository<SomeEntity, String> {
  @Override
  @RestResource(exported = true)
  @Query("select someEntity from SomeEntity someEntity where someEntity.owner = ?#{principal.username}")
  Iterable<SomeResource> findAll();
}

Upvotes: 3

Ben M
Ben M

Reputation: 1892

Building on @rpr's answer:

You should be able to reference properties of the joined entity (Storer). In your example if you have Receipt -> Storer -> User you can query the Receipts where Storer.user has a value injected from the Security Context.

@PreAuthorize("isFullyAuthenticated && (#userName==principal.username)")
Page<Receipt> findByStorer_User(@Param("userName") String userName)

Upvotes: 3

rpr
rpr

Reputation: 141

If you use Spring Security you can use this approach:

@PreAuthorize("isFullyAuthenticated() && (#userName == principal.username)")
public List<User> findByUserName(@Param("userName")String userName);

Upvotes: 2

Related Questions