diff --git a/resources/WEB-INF/jsp/registration.jsp b/resources/WEB-INF/jsp/registration.jsp
index 3d7546e..e78000b 100644
--- a/resources/WEB-INF/jsp/registration.jsp
+++ b/resources/WEB-INF/jsp/registration.jsp
@@ -1,4 +1,6 @@
<%@ page contentType="text/html;charset=UTF-8" %>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+
Charm Registration
@@ -20,6 +22,13 @@
+
+
+
+ ${wordBundle.getWord(error)}
+
+
+
<%@ include file="footer.jsp" %>
diff --git a/resources/words.properties b/resources/words.properties
index ac8383d..f487cad 100644
--- a/resources/words.properties
+++ b/resources/words.properties
@@ -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
\ No newline at end of file
+surname=Surname
+unexpected-error=Unexpected error
+update=Update
\ No newline at end of file
diff --git a/resources/words_en.properties b/resources/words_en.properties
index ac8383d..f487cad 100644
--- a/resources/words_en.properties
+++ b/resources/words_en.properties
@@ -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
\ No newline at end of file
+surname=Surname
+unexpected-error=Unexpected error
+update=Update
\ No newline at end of file
diff --git a/resources/words_ru.properties b/resources/words_ru.properties
index 1cf55c7..879135e 100644
--- a/resources/words_ru.properties
+++ b/resources/words_ru.properties
@@ -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
\ No newline at end of file
+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
\ No newline at end of file
diff --git a/src/ru/charm/back/controller/LikeController.java b/src/ru/charm/back/controller/LikeController.java
deleted file mode 100644
index 715cb42..0000000
--- a/src/ru/charm/back/controller/LikeController.java
+++ /dev/null
@@ -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();
- }
-}
diff --git a/src/ru/charm/back/controller/RegistrationController.java b/src/ru/charm/back/controller/RegistrationController.java
index 2f413a6..b60e0ce 100644
--- a/src/ru/charm/back/controller/RegistrationController.java
+++ b/src/ru/charm/back/controller/RegistrationController.java
@@ -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));
diff --git a/src/ru/charm/back/controller/filter/HiddenHttpMethodFilter.java b/src/ru/charm/back/controller/filter/HiddenHttpMethodFilter.java
index d45302f..54537d1 100644
--- a/src/ru/charm/back/controller/filter/HiddenHttpMethodFilter.java
+++ b/src/ru/charm/back/controller/filter/HiddenHttpMethodFilter.java
@@ -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;
- }
}
}
diff --git a/src/ru/charm/back/service/ProfileService.java b/src/ru/charm/back/service/ProfileService.java
index 3d95643..05fb635 100644
--- a/src/ru/charm/back/service/ProfileService.java
+++ b/src/ru/charm/back/service/ProfileService.java
@@ -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 emails = dao.getAllEmails();
- if (!Objects.equals(oldEmail, newEmail) &&
- emails.contains(newEmail)) {
- throw new DuplicateEmailException();
- }
- }
-
public boolean delete(Long id) {
return dao.delete(id);
}
diff --git a/src/ru/charm/back/utils/StringUtils.java b/src/ru/charm/back/utils/StringUtils.java
index 6b9da5e..a6652d5 100644
--- a/src/ru/charm/back/utils/StringUtils.java
+++ b/src/ru/charm/back/utils/StringUtils.java
@@ -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();
}
diff --git a/src/ru/charm/back/validator/RegistrationValidator.java b/src/ru/charm/back/validator/RegistrationValidator.java
new file mode 100644
index 0000000..e1621e3
--- /dev/null
+++ b/src/ru/charm/back/validator/RegistrationValidator.java
@@ -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 {
+ 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;
+ }
+}
diff --git a/src/ru/charm/back/validator/ValidationResult.java b/src/ru/charm/back/validator/ValidationResult.java
new file mode 100644
index 0000000..6d3ef45
--- /dev/null
+++ b/src/ru/charm/back/validator/ValidationResult.java
@@ -0,0 +1,20 @@
+package ru.charm.back.validator;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ValidationResult {
+ private final List errors = new ArrayList<>();
+
+ public boolean isValid() {
+ return errors.isEmpty();
+ }
+
+ public void addError(String code) {
+ errors.add(code);
+ }
+
+ public List getErrors() {
+ return new ArrayList<>(errors);
+ }
+}
diff --git a/src/ru/charm/back/validator/Validator.java b/src/ru/charm/back/validator/Validator.java
new file mode 100644
index 0000000..dcc785a
--- /dev/null
+++ b/src/ru/charm/back/validator/Validator.java
@@ -0,0 +1,5 @@
+package ru.charm.back.validator;
+
+public interface Validator {
+ ValidationResult validate(T object);
+}