我有两个类。
主类是 GraphQL 查询解析器:
@Component
@AllArgsConstructor
class UserProfileQuery implements GraphQLQueryResolver {
private final UserProfileRepository userProfileRepository;
private final AddressRepository addressRepository;
private final UserRepository userRepository;
private final UserProfileAccessValidator validator;
@PreAuthorize("hasAuthority('ACCOUNT_OWNER')")
public Optional<List<UserProfile>> getUserProfiles(Long accountId) {
User user = userRepository.findById(LoggedUserHolder.getUserId()).orElseThrow(() -> new NotFoundException(User.class));
validator.validateAccountOwnerAccess(user, accountId);
return userProfileRepository.findMatchingAccountId(accountId);
}
@PreAuthorize("hasAuthority('ACCOUNT_OWNER')")
public Optional<UserProfile> getUserProfile(Long userProfileId) {
User user = userRepository.findById(LoggedUserHolder.getUserId()).orElseThrow(() -> new NotFoundException(User.class));
User checkedUser = userRepository.findByUserProfileId(userProfileId).orElseThrow(() -> new NotFoundException(User.class));
validator.validateAccountOwnerAccess(user, checkedUser);
return userProfileRepository.findById(userProfileId);
}
@PreAuthorize("hasAnyAuthority('ACCOUNT_OWNER','USER')")
public Set<Address> getAddresses(Long userProfileId) {
User user = userRepository.findById(LoggedUserHolder.getUserId()).orElseThrow(() -> new NotFoundException(User.class));
User checkedUser = userRepository.findByUserProfileId(userProfileId).orElseThrow(() -> new NotFoundException(User.class));
validator.validateAccountOwnerAndUserAccess(user, checkedUser);
return Optional.of(addressRepository.findByUserProfileId(userProfileId)).orElseThrow(() -> new NotFoundException(UserProfile.class));
}
}
第二个类是 validator :
@Component
@AllArgsConstructor
public class UserProfileAccessValidator {
private final UserRepository userRepository;
public void validateAccessForUserCreation(CreateUserProfileCommand command) {
User user = userRepository.findById(LoggedUserHolder.getUserId()).orElseThrow(() -> new NotFoundException(User.class));
User checkedUser = userRepository.findById(command.getUserId()).orElseThrow(() -> new NotFoundException(User.class));
validateAccountOwnerAndUserAccess(user, checkedUser);
}
public void validateAccountOwnerAndUserAccess(User user, User checkedUser) {
if (AccessValidationHelper.isAccountOwnerAndHasSameAccount(user, checkedUser)
|| AccessValidationHelper.isUserAndHasSameUserProfileId(user, checkedUser)) {
throw new IllegalOperationException();
}
}
public void validateAccountOwnerAccess(User user, User checkedUser) {
if (AccessValidationHelper.isAccountOwnerAndHasSameAccount(user, checkedUser)) {
throw new IllegalOperationException();
}
}
public void validateAccountOwnerAccess(User user, Long accountId) {
if (!user.getAccount().getId().equals(accountId)) {
throw new IllegalOperationException();
}
}
}
正如您所看到的,用户获取中有很多代码重复。
User user = userRepository.findById(LoggedUserHolder.getUserId()).orElseThrow(() -> new NotFoundException(User.class));
User checkedUser = userRepository.findById(command.getUserId()).orElseThrow(() -> new NotFoundException(User.class));
如何重构这两个类以避免代码重复?或者至少避免重复:
User user = userRepository.findById(LoggedUserHolder.getUserId()).orElseThrow(() -> new NotFoundException(User.class));
因为它正在从 Spring 上下文持有者中获取用户。我在这个问题上坐了一个小时,但没有好的解决方案来实现......
最佳答案
如果登录用户是主体,您可以使用 @PreAuthorize 表达式。如果这对您有用,那么您可以使用元注释。通过元注释,您可以减少代码量。这是一个关于如何使用它们的很好的教程:https://www.baeldung.com/spring-security-method-security
关于java - 如何从方法中提取依赖于类上下文的变量以避免重复代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58594304/