Reputation: 7126
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
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
Reputation: 6207
For example, given a Repository
for SomeEntity
you could override findAll
method with a custom @Query
filtering by attribute owner
with 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
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
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