Skip to content

Commit e4004c7

Browse files
Add custom password validator to match old and new passwords
1 parent 71eb582 commit e4004c7

File tree

4 files changed

+66
-9
lines changed

4 files changed

+66
-9
lines changed

src/main/java/com/accolite/pru/health/AuthApp/advice/AuthControllerAdvice.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import org.springframework.security.authentication.BadCredentialsException;
2222
import org.springframework.security.core.userdetails.UsernameNotFoundException;
2323
import org.springframework.validation.BindingResult;
24-
import org.springframework.validation.FieldError;
24+
import org.springframework.validation.ObjectError;
2525
import org.springframework.web.bind.MethodArgumentNotValidException;
2626
import org.springframework.web.bind.annotation.ExceptionHandler;
2727
import org.springframework.web.bind.annotation.ResponseBody;
@@ -46,31 +46,31 @@ public class AuthControllerAdvice {
4646
@ResponseBody
4747
public ApiResponse processValidationError(MethodArgumentNotValidException ex) {
4848
BindingResult result = ex.getBindingResult();
49-
List<FieldError> fieldErrors = result.getFieldErrors();
49+
List<ObjectError> allErrors = result.getAllErrors();
5050
ApiResponse response = new ApiResponse();
5151
response.setSuccess(false);
52-
response.setData(processFieldErrors(fieldErrors).stream().collect(Collectors.joining("\n")));
52+
response.setData(processAllErrors(allErrors).stream().collect(Collectors.joining("\n")));
5353
return response;
5454
}
5555

5656
/**
5757
* Utility Method to generate localized message for a list of field errors
58-
* @param fieldErrors the field errors
58+
* @param allErrors the field errors
5959
* @return the list
6060
*/
61-
private List<String> processFieldErrors(List<FieldError> fieldErrors) {
62-
return fieldErrors.stream().map(this::resolveLocalizedErrorMessage).collect(Collectors.toList());
61+
private List<String> processAllErrors(List<ObjectError> allErrors) {
62+
return allErrors.stream().map(this::resolveLocalizedErrorMessage).collect(Collectors.toList());
6363
}
6464

6565
/**
6666
* Resolve localized error message. Utiity method to generate a localized error
6767
* message
68-
* @param fieldError the field error
68+
* @param objectError the field error
6969
* @return the string
7070
*/
71-
private String resolveLocalizedErrorMessage(FieldError fieldError) {
71+
private String resolveLocalizedErrorMessage(ObjectError objectError) {
7272
Locale currentLocale = LocaleContextHolder.getLocale();
73-
String localizedErrorMessage = messageSource.getMessage(fieldError, currentLocale);
73+
String localizedErrorMessage = messageSource.getMessage(objectError, currentLocale);
7474
logger.info(localizedErrorMessage);
7575
return localizedErrorMessage;
7676
}

src/main/java/com/accolite/pru/health/AuthApp/model/payload/PasswordResetRequest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
package com.accolite.pru.health.AuthApp.model.payload;
22

3+
import com.accolite.pru.health.AuthApp.validation.annotation.PasswordsMatch;
4+
35
import javax.validation.constraints.NotBlank;
46

7+
@PasswordsMatch(allowNull = false)
58
public class PasswordResetRequest {
9+
610
@NotBlank(message = "Password cannot be blank")
711
private String password;
812

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.accolite.pru.health.AuthApp.validation.annotation;
2+
3+
import com.accolite.pru.health.AuthApp.validation.validator.PasswordsMatchValidator;
4+
5+
import javax.validation.Constraint;
6+
import javax.validation.Payload;
7+
import java.lang.annotation.Documented;
8+
import java.lang.annotation.ElementType;
9+
import java.lang.annotation.Retention;
10+
import java.lang.annotation.RetentionPolicy;
11+
import java.lang.annotation.Target;
12+
13+
14+
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
15+
@Retention(RetentionPolicy.RUNTIME)
16+
@Constraint(validatedBy = PasswordsMatchValidator.class)
17+
@Documented
18+
public @interface PasswordsMatch {
19+
String message() default "The new passwords must match";
20+
21+
Class<?>[] groups() default {};
22+
23+
boolean allowNull() default false;
24+
25+
Class<? extends Payload>[] payload() default {};
26+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.accolite.pru.health.AuthApp.validation.validator;
2+
3+
import com.accolite.pru.health.AuthApp.model.payload.PasswordResetRequest;
4+
import com.accolite.pru.health.AuthApp.validation.annotation.PasswordsMatch;
5+
6+
import javax.validation.ConstraintValidator;
7+
import javax.validation.ConstraintValidatorContext;
8+
9+
public class PasswordsMatchValidator implements ConstraintValidator<PasswordsMatch, PasswordResetRequest> {
10+
11+
private Boolean allowNull;
12+
13+
@Override
14+
public void initialize(PasswordsMatch constraintAnnotation) {
15+
allowNull = constraintAnnotation.allowNull();
16+
}
17+
18+
@Override
19+
public boolean isValid(PasswordResetRequest value, ConstraintValidatorContext context) {
20+
String password = value.getPassword();
21+
String confirmPassword = value.getConfirmPassword();
22+
if (allowNull) {
23+
return null == password && null == confirmPassword;
24+
}
25+
return password.equals(confirmPassword);
26+
}
27+
}

0 commit comments

Comments
 (0)