У меня есть два класса.
Основным классом является распознаватель запросов 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));
}
}
Второй класс является валидатором:
@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();
}
}
}
As Youможно увидеть, что при выборке пользователя происходит много дублирования кода.
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. Я сижу над этой проблемой уже час, и у меня нет хорошего решения для реализации ...