У меня есть подтверждение, что электронная почта уникальна.Это работа при регистрации.Но когда я пытаюсь изменить адрес электронной почты в профиле пользователя, у меня появляется ошибка.
Я проверяю электронную почту, чтобы запустить userRepository.findByEmail.Если пользователь был найден, то электронная почта не уникальна.Но когда пользователь меняет свой адрес электронной почты в профиле, findByEmail возвращает этого пользователя.Проверка не пройдена.
Мне нужно проверить, что пользователь, возвращенный функцией findByUser, не является тем же пользователем, который меняет электронную почту.Для этого мне нужно передать пользователя, который меняет электронную почту в валидаторе.
Это мой код.
сущность:
@Data
@Table(name = "users")
@NoArgsConstructor
@CheckPasswordConfirm(message = "Password not equal!")
@Entity
public class User implements UserDetails{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@NotBlank(message = "Username is empty!")
@UniqueUsername(message = "Username isn't unique")
private String username;
@NotBlank(message = "Password is empty!")
private String password;
@Transient
@NotBlank(message = "Password confirm is empty!")
private String passwordconfirm;
private boolean active;
@Email(message = "E-mail!")
@NotBlank(message = "E-mail is empty!")
@UniqueEmail(message = "Email isn't unique!")
private String email;
private String activationCode;
@ElementCollection(targetClass = Role.class, fetch = FetchType.EAGER)
@CollectionTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"))
@Enumerated(EnumType.STRING)
private Set<Role> roles;
public boolean isAdmin()
{
return roles.contains(Role.ADMIN);
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return getRoles();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
Аннотация UniqueEmail:
@Constraint(validatedBy = UniqueEmailValidator.class)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface UniqueEmail {
public String message();
public Class<?>[] groups() default {};
public Class<? extends Payload>[] payload() default{};
}
Валидатор:
package ru.watchlist.domain.validation.validators;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.springframework.beans.factory.annotation.Autowired;
import ru.watchlist.domain.validation.annotations.UniqueEmail;
import ru.watchlist.service.UserService;
public class UniqueEmailValidator implements ConstraintValidator<UniqueEmail, String> {
@Autowired
private UserService userService;
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
return value != null && !userService.isEmailAlredyUse(value);
}
}
userService.isEmailAlredyUse:
public boolean isEmailAlredyUse(String value) {
User user = userRepository.findByEmail(value);
if(user != null) {
return true;
}
return false;
}
Здесь мне нужно проверить:
User userFromDB = userRepository.findByEmail(value);
if(userFromDB != null && user != userFromDB) {
return true;
}
Как мне решить эту проблему?
PS Если я сделаю валидатор для класса с кросс-полями, я не смогу показать ошибки с их полями в Thymeleaf.Поэтому мне нужен валидатор для полей.
PSS Мой контроллер:
@Controller
@RequestMapping("/profile")
public class ProfileController {
@Autowired
UserService userService;
@GetMapping
public String profile(@AuthenticationPrincipal User user, Model model) {
model.addAttribute(user);
return "profile";
}
@PostMapping("/update")
public String saveChanges(@Valid User user, Errors errors) {
if(errors.hasErrors()) {
return "profile";
}
userService.addUser(user);
return "redirect:/profile";
}
}
UserRepository:
public interface UserRepository extends JpaRepository<User, Long>{
User findByUsername(String username);
User findByActivationCode(String code);
User findByEmail(String email);
}