Issue
I'm currently testing out my spring boot app's API using Swagger, and when I input mismatching passwords, or even a password with a size outside the bounds (min=5 and max=15) of the size, I am not getting a 404 error code when it is expected. Other errors for other entity variables are getting properly caught, but seemingly nothing for the password. What may I have incorrect for plainPassword and repeatPassword to match in my entity below? Because the @PasswordMatch annotation doesn't seem to be doing the job I expect it to of comparing plainPassword and repeatPassword.
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.persistence.UniqueConstraint;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import com.bcore.hw.validation.PasswordMatch;
import lombok.NoArgsConstructor;
import lombok.Data;
@Entity
@Table(name="users", uniqueConstraints={@UniqueConstraint(columnNames = {"email"})})
@PasswordMatch(message="{register.repeatPassword.mismatch}")
@NoArgsConstructor
@Data
public class SiteUser {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long userId;
@Column(name="email", unique=true)
@Email(message="{register.email.invalid}")
@NotBlank(message="{register.email.invalid}")
private String email;
@Transient // meaning it will not be saved in DB
@Size(min=5, max=15, message="{register.password.size}")
private String plainPassword; //unencrytped
@Transient
private String repeatPassword;
@Column(name="password", length=60)
private String password;
@Column(name="role", length=20)
private String role;
@Column(name="enabled")
private Boolean enabled = false;
public void setPlainPassword(String plainPassword) {
//System.out.println("PASSWORD BEFORE " + plainPassword);
this.password = new BCryptPasswordEncoder().encode(plainPassword);
//System.out.println("HERE IS PASSWORD" + this.password + "PASSWORD LENGTH = " + (this.password).length());
this.plainPassword = plainPassword;
}
}
Updated with Custom Validator:
So here now I have PasswordMatch.java and PasswordMatchValidator.java, but have a little confusion as to how to set up the @PrePersist and @PreUpdate annotations in the entity:
package com.bcore.hw.validation;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
@Target(TYPE)
@Retention(RUNTIME)
@Constraint(validatedBy=PasswordMatchValidator.class)
@Documented
public @interface PasswordMatch {
String message() default "{error.password.mismatch}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
package com.bcore.hw.validation;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import com.bcore.hw.model.SiteUser;
public class PasswordMatchValidator implements ConstraintValidator<PasswordMatch, SiteUser>{
@Override
public void initialize(PasswordMatch p) {
}
public boolean isValid(SiteUser user, ConstraintValidatorContext c) {
String plainPassword = user.getPlainPassword();
String repeatPassword = user.getRepeatPassword();
if(plainPassword == null || !plainPassword.equals(repeatPassword)) {
return false;
}
return true;
}
}
Currently in the entity, you can see @PasswordMatch before the class definition, but this isn't working. So, @PrePersist and @PreUpdate are used only for entity method definitions, but what method would I place under them? A call to the isValid() method from the PasswordMatch interface? Not exactly sure what to do in the entity at this point.
Solution
It's seems to be this bug in open status because of @Transient
field
Answered By - Dmitriy Mishenyov
Answer Checked By - Terry (JavaFixing Volunteer)