feat: add registration validator
This commit is contained in:
parent
c28f6e464f
commit
fd2f08e8bc
@ -1,4 +1,6 @@
|
||||
<%@ page contentType="text/html;charset=UTF-8" %>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Charm Registration</title>
|
||||
@ -20,6 +22,13 @@
|
||||
</table>
|
||||
<button type="submit">${requestScope.wordBundle.getWord("save")}</button>
|
||||
</form>
|
||||
|
||||
<div style="color: red">
|
||||
<c:forEach var="error" items="${errors}">
|
||||
<span>${wordBundle.getWord(error)}</span>
|
||||
<br>
|
||||
</c:forEach>
|
||||
</div>
|
||||
</div>
|
||||
<%@ include file="footer.jsp" %>
|
||||
</body>
|
||||
|
||||
@ -7,6 +7,10 @@ confirm-password=Confirm password
|
||||
delete=Delete
|
||||
email=Email
|
||||
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
|
||||
gender=Gender
|
||||
inactive=Inactive
|
||||
@ -16,6 +20,9 @@ other=Other
|
||||
page-bad-request=Bad request
|
||||
page-not-found=Page not found
|
||||
password=Password
|
||||
photo=Photo
|
||||
save=Save
|
||||
status=Status
|
||||
surname=Surname
|
||||
surname=Surname
|
||||
unexpected-error=Unexpected error
|
||||
update=Update
|
||||
@ -7,6 +7,10 @@ confirm-password=Confirm password
|
||||
delete=Delete
|
||||
email=Email
|
||||
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
|
||||
gender=Gender
|
||||
inactive=Inactive
|
||||
@ -16,6 +20,9 @@ other=Other
|
||||
page-bad-request=Bad request
|
||||
page-not-found=Page not found
|
||||
password=Password
|
||||
photo=Photo
|
||||
save=Save
|
||||
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
|
||||
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
|
||||
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
|
||||
gender=\u041F\u043E\u043B
|
||||
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-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
|
||||
photo=\u0424\u043E\u0442\u043E
|
||||
save=\u0421\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C
|
||||
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.mapper.RequestToRegistrationDtoMapper;
|
||||
import ru.charm.back.service.ProfileService;
|
||||
import ru.charm.back.validator.RegistrationValidator;
|
||||
import ru.charm.back.validator.ValidationResult;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@ -18,6 +20,7 @@ public class RegistrationController extends HttpServlet {
|
||||
private final ProfileService service = ProfileService.getInstance();
|
||||
|
||||
private final RequestToRegistrationDtoMapper requestToRegistrationDtoMapper = RequestToRegistrationDtoMapper.getInstance();
|
||||
private final RegistrationValidator validator = RegistrationValidator.getInstance();
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
@ -25,8 +28,16 @@ public class RegistrationController extends HttpServlet {
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
ValidationResult validationResult = validator.validate(dto);
|
||||
if (!validationResult.isValid()) {
|
||||
req.setAttribute("errors", validationResult.getErrors());
|
||||
doGet(req, resp);
|
||||
return;
|
||||
}
|
||||
|
||||
Long id = service.save(dto);
|
||||
log.info("Profile with the email address {} has been registered with id {}", dto.getEmail(), 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.HttpServletRequestWrapper;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import ru.charm.back.model.Gender;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -39,16 +41,13 @@ public class HiddenHttpMethodFilter implements Filter {
|
||||
|
||||
|
||||
public static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {
|
||||
@Setter
|
||||
@Getter
|
||||
public final String method;
|
||||
|
||||
public HttpMethodRequestWrapper(HttpServletRequest request, String method) {
|
||||
super(request);
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod() {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,21 +48,11 @@ public class ProfileService {
|
||||
public void update(ProfileUpdateDto dto) {
|
||||
dao.findById(dto.getId())
|
||||
.ifPresent(profile -> {
|
||||
checkEmail(profile.getEmail(), dto.getEmail());
|
||||
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) {
|
||||
return dao.delete(id);
|
||||
}
|
||||
|
||||
@ -2,8 +2,13 @@ package ru.charm.back.utils;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@UtilityClass
|
||||
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) {
|
||||
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