feat: add registration validator
This commit is contained in:
parent
c28f6e464f
commit
fd2f08e8bc
@ -1,4 +1,6 @@
|
|||||||
<%@ page contentType="text/html;charset=UTF-8" %>
|
<%@ page contentType="text/html;charset=UTF-8" %>
|
||||||
|
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||||
|
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<title>Charm Registration</title>
|
<title>Charm Registration</title>
|
||||||
@ -20,6 +22,13 @@
|
|||||||
</table>
|
</table>
|
||||||
<button type="submit">${requestScope.wordBundle.getWord("save")}</button>
|
<button type="submit">${requestScope.wordBundle.getWord("save")}</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<div style="color: red">
|
||||||
|
<c:forEach var="error" items="${errors}">
|
||||||
|
<span>${wordBundle.getWord(error)}</span>
|
||||||
|
<br>
|
||||||
|
</c:forEach>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<%@ include file="footer.jsp" %>
|
<%@ include file="footer.jsp" %>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@ -7,6 +7,10 @@ confirm-password=Confirm password
|
|||||||
delete=Delete
|
delete=Delete
|
||||||
email=Email
|
email=Email
|
||||||
email-warning=Changing your mail may have negative effects
|
email-warning=Changing your mail may have negative effects
|
||||||
|
error.age.invalid=Age must be between 18 and 100 years old
|
||||||
|
error.email.exist=This email already exists
|
||||||
|
error.email.invalid=Invalid email
|
||||||
|
error.password.invalid=Invalid password
|
||||||
female=Female
|
female=Female
|
||||||
gender=Gender
|
gender=Gender
|
||||||
inactive=Inactive
|
inactive=Inactive
|
||||||
@ -16,6 +20,9 @@ other=Other
|
|||||||
page-bad-request=Bad request
|
page-bad-request=Bad request
|
||||||
page-not-found=Page not found
|
page-not-found=Page not found
|
||||||
password=Password
|
password=Password
|
||||||
|
photo=Photo
|
||||||
save=Save
|
save=Save
|
||||||
status=Status
|
status=Status
|
||||||
surname=Surname
|
surname=Surname
|
||||||
|
unexpected-error=Unexpected error
|
||||||
|
update=Update
|
||||||
@ -7,6 +7,10 @@ confirm-password=Confirm password
|
|||||||
delete=Delete
|
delete=Delete
|
||||||
email=Email
|
email=Email
|
||||||
email-warning=Changing your mail may have negative effects
|
email-warning=Changing your mail may have negative effects
|
||||||
|
error.age.invalid=Age must be between 18 and 100 years old
|
||||||
|
error.email.exist=This email already exists
|
||||||
|
error.email.invalid=Invalid email
|
||||||
|
error.password.invalid=Invalid password
|
||||||
female=Female
|
female=Female
|
||||||
gender=Gender
|
gender=Gender
|
||||||
inactive=Inactive
|
inactive=Inactive
|
||||||
@ -16,6 +20,9 @@ other=Other
|
|||||||
page-bad-request=Bad request
|
page-bad-request=Bad request
|
||||||
page-not-found=Page not found
|
page-not-found=Page not found
|
||||||
password=Password
|
password=Password
|
||||||
|
photo=Photo
|
||||||
save=Save
|
save=Save
|
||||||
status=Status
|
status=Status
|
||||||
surname=Surname
|
surname=Surname
|
||||||
|
unexpected-error=Unexpected error
|
||||||
|
update=Update
|
||||||
@ -7,6 +7,10 @@ confirm-password=\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0
|
|||||||
delete=\u0423\u0434\u0430\u043B\u0438\u0442\u044C
|
delete=\u0423\u0434\u0430\u043B\u0438\u0442\u044C
|
||||||
email=\u041F\u043E\u0447\u0442\u0430
|
email=\u041F\u043E\u0447\u0442\u0430
|
||||||
email-warning=\u0421\u043C\u0435\u043D\u0430 \u043F\u043E\u0447\u0442\u044B \u043C\u043E\u0436\u0435\u0442 \u043F\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043A \u043D\u0435\u0436\u0435\u043B\u0430\u0442\u0435\u043B\u044C\u043D\u044B\u043C \u043F\u043E\u0441\u043B\u0435\u0434\u0441\u0442\u0432\u0438\u044F\u043C
|
email-warning=\u0421\u043C\u0435\u043D\u0430 \u043F\u043E\u0447\u0442\u044B \u043C\u043E\u0436\u0435\u0442 \u043F\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043A \u043D\u0435\u0436\u0435\u043B\u0430\u0442\u0435\u043B\u044C\u043D\u044B\u043C \u043F\u043E\u0441\u043B\u0435\u0434\u0441\u0442\u0432\u0438\u044F\u043C
|
||||||
|
error.age.invalid=\u0412\u043E\u0437\u0440\u0430\u0441\u0442 \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043E\u0442 18 \u0434\u043E 100 \u043B\u0435\u0442
|
||||||
|
error.email.exist=\u0422\u0430\u043A\u0430\u044F \u043F\u043E\u0447\u0442\u0430 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442
|
||||||
|
error.email.invalid=\u041D\u0435\u0432\u0435\u0440\u043D\u0430\u044F \u043F\u043E\u0447\u0442\u0430
|
||||||
|
error.password.invalid=\u041D\u0435\u043F\u043E\u0434\u0445\u043E\u0434\u044F\u0449\u0438\u0439 \u043F\u0430\u0440\u043E\u043B\u044C
|
||||||
female=\u0416\u0435\u043D\u0449\u0438\u043D\u0430
|
female=\u0416\u0435\u043D\u0449\u0438\u043D\u0430
|
||||||
gender=\u041F\u043E\u043B
|
gender=\u041F\u043E\u043B
|
||||||
inactive=\u041D\u0435\u0430\u043A\u0442\u0438\u0432\u043D\u044B\u0439
|
inactive=\u041D\u0435\u0430\u043A\u0442\u0438\u0432\u043D\u044B\u0439
|
||||||
@ -16,6 +20,9 @@ other=\u0414\u0440\u0443\u0433\u043E\u0435
|
|||||||
page-bad-request=\u041D\u0435\u043A\u043E\u0440\u0440\u0435\u043A\u0442\u043D\u044B\u0439 \u0437\u0430\u043F\u0440\u043E\u0441
|
page-bad-request=\u041D\u0435\u043A\u043E\u0440\u0440\u0435\u043A\u0442\u043D\u044B\u0439 \u0437\u0430\u043F\u0440\u043E\u0441
|
||||||
page-not-found=\u0421\u0442\u0440\u0430\u043D\u0438\u0446\u0430 \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u0430
|
page-not-found=\u0421\u0442\u0440\u0430\u043D\u0438\u0446\u0430 \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u0430
|
||||||
password=\u041F\u0430\u0440\u043E\u043B\u044C
|
password=\u041F\u0430\u0440\u043E\u043B\u044C
|
||||||
|
photo=\u0424\u043E\u0442\u043E
|
||||||
save=\u0421\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C
|
save=\u0421\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C
|
||||||
status=\u0421\u0442\u0430\u0442\u0443\u0441
|
status=\u0421\u0442\u0430\u0442\u0443\u0441
|
||||||
surname=\u0424\u0430\u043C\u0438\u043B\u0438\u044F
|
surname=\u0424\u0430\u043C\u0438\u043B\u0438\u044F
|
||||||
|
unexpected-error=\u041D\u0435\u043F\u0440\u0435\u0434\u0432\u0438\u0434\u0435\u043D\u043D\u0430\u044F \u043E\u0448\u0438\u0431\u043A\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430
|
||||||
|
update=\u041E\u0431\u043D\u043E\u0432\u0438\u0442\u044C
|
||||||
@ -1,33 +0,0 @@
|
|||||||
package ru.charm.back.controller;
|
|
||||||
|
|
||||||
import jakarta.servlet.ServletConfig;
|
|
||||||
import jakarta.servlet.ServletException;
|
|
||||||
import jakarta.servlet.annotation.WebServlet;
|
|
||||||
import jakarta.servlet.http.HttpServlet;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
@WebServlet("/like")
|
|
||||||
public class LikeController extends HttpServlet {
|
|
||||||
@Override
|
|
||||||
public void init(ServletConfig config) throws ServletException {
|
|
||||||
System.out.println("LikeController init" + config.getServletName() );
|
|
||||||
super.init(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
|
||||||
resp.setContentType("text/plain");
|
|
||||||
System.out.println("User-Agent: " + req.getHeader("User-Agent"));
|
|
||||||
resp.getWriter().write("Like count: 101");
|
|
||||||
resp.setHeader("X-Custom-Header", "Zalupa");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void destroy() {
|
|
||||||
System.out.println("LikeController destroy");
|
|
||||||
super.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -9,6 +9,8 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import ru.charm.back.dto.RegistrationDto;
|
import ru.charm.back.dto.RegistrationDto;
|
||||||
import ru.charm.back.mapper.RequestToRegistrationDtoMapper;
|
import ru.charm.back.mapper.RequestToRegistrationDtoMapper;
|
||||||
import ru.charm.back.service.ProfileService;
|
import ru.charm.back.service.ProfileService;
|
||||||
|
import ru.charm.back.validator.RegistrationValidator;
|
||||||
|
import ru.charm.back.validator.ValidationResult;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@ -18,6 +20,7 @@ public class RegistrationController extends HttpServlet {
|
|||||||
private final ProfileService service = ProfileService.getInstance();
|
private final ProfileService service = ProfileService.getInstance();
|
||||||
|
|
||||||
private final RequestToRegistrationDtoMapper requestToRegistrationDtoMapper = RequestToRegistrationDtoMapper.getInstance();
|
private final RequestToRegistrationDtoMapper requestToRegistrationDtoMapper = RequestToRegistrationDtoMapper.getInstance();
|
||||||
|
private final RegistrationValidator validator = RegistrationValidator.getInstance();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||||
@ -25,8 +28,16 @@ public class RegistrationController extends HttpServlet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
|
||||||
RegistrationDto dto = requestToRegistrationDtoMapper.map(req);
|
RegistrationDto dto = requestToRegistrationDtoMapper.map(req);
|
||||||
|
|
||||||
|
ValidationResult validationResult = validator.validate(dto);
|
||||||
|
if (!validationResult.isValid()) {
|
||||||
|
req.setAttribute("errors", validationResult.getErrors());
|
||||||
|
doGet(req, resp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Long id = service.save(dto);
|
Long id = service.save(dto);
|
||||||
log.info("Profile with the email address {} has been registered with id {}", dto.getEmail(), id);
|
log.info("Profile with the email address {} has been registered with id {}", dto.getEmail(), id);
|
||||||
resp.sendRedirect(String.format("/profile?id=%s", id));
|
resp.sendRedirect(String.format("/profile?id=%s", id));
|
||||||
|
|||||||
@ -5,6 +5,8 @@ import jakarta.servlet.annotation.WebFilter;
|
|||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletRequestWrapper;
|
import jakarta.servlet.http.HttpServletRequestWrapper;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
import ru.charm.back.model.Gender;
|
import ru.charm.back.model.Gender;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -39,16 +41,13 @@ public class HiddenHttpMethodFilter implements Filter {
|
|||||||
|
|
||||||
|
|
||||||
public static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {
|
public static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
public final String method;
|
public final String method;
|
||||||
|
|
||||||
public HttpMethodRequestWrapper(HttpServletRequest request, String method) {
|
public HttpMethodRequestWrapper(HttpServletRequest request, String method) {
|
||||||
super(request);
|
super(request);
|
||||||
this.method = method;
|
this.method = method;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getMethod() {
|
|
||||||
return method;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,21 +48,11 @@ public class ProfileService {
|
|||||||
public void update(ProfileUpdateDto dto) {
|
public void update(ProfileUpdateDto dto) {
|
||||||
dao.findById(dto.getId())
|
dao.findById(dto.getId())
|
||||||
.ifPresent(profile -> {
|
.ifPresent(profile -> {
|
||||||
checkEmail(profile.getEmail(), dto.getEmail());
|
|
||||||
dao.update(profileUpdateDtoToProfileMapper.map(dto, profile));
|
dao.update(profileUpdateDtoToProfileMapper.map(dto, profile));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkEmail(String oldEmail, String newEmail) {
|
|
||||||
if (newEmail == null) return;
|
|
||||||
Set<String> emails = dao.getAllEmails();
|
|
||||||
if (!Objects.equals(oldEmail, newEmail) &&
|
|
||||||
emails.contains(newEmail)) {
|
|
||||||
throw new DuplicateEmailException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean delete(Long id) {
|
public boolean delete(Long id) {
|
||||||
return dao.delete(id);
|
return dao.delete(id);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,8 +2,13 @@ package ru.charm.back.utils;
|
|||||||
|
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
|
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@UtilityClass
|
@UtilityClass
|
||||||
public class StringUtils {
|
public class StringUtils {
|
||||||
|
public static final Pattern VALID_EMAIL_ADDRESS_REGEX =
|
||||||
|
Pattern.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$", Pattern.CASE_INSENSITIVE);
|
||||||
|
|
||||||
public static boolean isBlank(String str) {
|
public static boolean isBlank(String str) {
|
||||||
return str == null || str.isBlank();
|
return str == null || str.isBlank();
|
||||||
}
|
}
|
||||||
|
|||||||
35
src/ru/charm/back/validator/RegistrationValidator.java
Normal file
35
src/ru/charm/back/validator/RegistrationValidator.java
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package ru.charm.back.validator;
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import ru.charm.back.dao.ProfileDao;
|
||||||
|
import ru.charm.back.dto.RegistrationDto;
|
||||||
|
import ru.charm.back.mapper.ProfileUpdateDtoToProfileMapper;
|
||||||
|
|
||||||
|
import static ru.charm.back.utils.StringUtils.VALID_EMAIL_ADDRESS_REGEX;
|
||||||
|
import static ru.charm.back.utils.StringUtils.isBlank;
|
||||||
|
|
||||||
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
|
public class RegistrationValidator implements Validator<RegistrationDto> {
|
||||||
|
private static final RegistrationValidator INSTANCE = new RegistrationValidator();
|
||||||
|
public static RegistrationValidator getInstance() { return INSTANCE; }
|
||||||
|
|
||||||
|
private final ProfileDao dao = ProfileDao.getInstance();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValidationResult validate(RegistrationDto dto) {
|
||||||
|
ValidationResult validationResult = new ValidationResult();
|
||||||
|
|
||||||
|
if (isBlank(dto.getEmail()) || !VALID_EMAIL_ADDRESS_REGEX.matcher(dto.getEmail()).matches()) {
|
||||||
|
validationResult.addError("error.email.invalid");
|
||||||
|
} else if (dao.getAllEmails().contains(dto.getEmail())) {
|
||||||
|
validationResult.addError("error.email.exists");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isBlank(dto.getPassword())) {
|
||||||
|
validationResult.addError("error.password.invalid");
|
||||||
|
}
|
||||||
|
|
||||||
|
return validationResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
20
src/ru/charm/back/validator/ValidationResult.java
Normal file
20
src/ru/charm/back/validator/ValidationResult.java
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package ru.charm.back.validator;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ValidationResult {
|
||||||
|
private final List<String> errors = new ArrayList<>();
|
||||||
|
|
||||||
|
public boolean isValid() {
|
||||||
|
return errors.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addError(String code) {
|
||||||
|
errors.add(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getErrors() {
|
||||||
|
return new ArrayList<>(errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
5
src/ru/charm/back/validator/Validator.java
Normal file
5
src/ru/charm/back/validator/Validator.java
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package ru.charm.back.validator;
|
||||||
|
|
||||||
|
public interface Validator<T> {
|
||||||
|
ValidationResult validate(T object);
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user