diff --git a/lib/jackson-annotations-2.21.jar b/lib/jackson-annotations-2.21.jar new file mode 100644 index 0000000..8bcca18 Binary files /dev/null and b/lib/jackson-annotations-2.21.jar differ diff --git a/lib/jackson-core-2.21.0.jar b/lib/jackson-core-2.21.0.jar new file mode 100644 index 0000000..ae05d27 Binary files /dev/null and b/lib/jackson-core-2.21.0.jar differ diff --git a/lib/jackson-databind-2.21.0.jar b/lib/jackson-databind-2.21.0.jar new file mode 100644 index 0000000..358b3a4 Binary files /dev/null and b/lib/jackson-databind-2.21.0.jar differ diff --git a/lib/jackson-datatype-jsr310-2.21.0.jar b/lib/jackson-datatype-jsr310-2.21.0.jar new file mode 100644 index 0000000..ab686d0 Binary files /dev/null and b/lib/jackson-datatype-jsr310-2.21.0.jar differ diff --git a/src/ru/charm/back/controller/filter/AuthFilter.java b/src/ru/charm/back/controller/filter/AuthFilter.java index ece1e18..0a3ddce 100644 --- a/src/ru/charm/back/controller/filter/AuthFilter.java +++ b/src/ru/charm/back/controller/filter/AuthFilter.java @@ -14,6 +14,9 @@ import java.io.IOException; import java.util.Arrays; import java.util.Set; +import static ru.charm.back.utils.UrlUtils.LOGIN_REST_URL; +import static ru.charm.back.utils.UrlUtils.REST_URL; + @WebFilter("/*") @Slf4j public class AuthFilter implements Filter { @@ -24,12 +27,15 @@ public class AuthFilter implements Filter { HttpServletRequest req = (HttpServletRequest) servletRequest; HttpServletResponse res = (HttpServletResponse) servletResponse; - if (PRIVATE_PATHS.contains(req.getRequestURI())) { + if (!LOGIN_REST_URL.equals(req.getRequestURI()) && PRIVATE_PATHS.contains(req.getRequestURI())) { ProfileGetDto userDetails = (ProfileGetDto) req.getSession().getAttribute("userDetails"); log.info("User {} is trying to access {}", userDetails, req.getRequestURI()); if (userDetails == null) { res.sendError(HttpServletResponse.SC_UNAUTHORIZED); - } else if (userDetails.getRole() == Role.ADMIN || userDetails.getId().toString().equals( req.getParameter("id"))) { + } else if (!req.getRequestURI().startsWith(REST_URL) && + userDetails.getRole() == Role.ADMIN || + userDetails.getId().toString().equals( req.getParameter("id")) + ) { filterChain.doFilter(req, res); } else { res.sendError(HttpServletResponse.SC_FORBIDDEN); diff --git a/src/ru/charm/back/controller/filter/ErrorFilter.java b/src/ru/charm/back/controller/filter/ErrorFilter.java index 98af12a..78d50b5 100644 --- a/src/ru/charm/back/controller/filter/ErrorFilter.java +++ b/src/ru/charm/back/controller/filter/ErrorFilter.java @@ -9,6 +9,8 @@ import lombok.extern.slf4j.Slf4j; import java.io.IOException; import static jakarta.servlet.RequestDispatcher.ERROR_EXCEPTION; +import static jakarta.servlet.RequestDispatcher.ERROR_REQUEST_URI; +import static ru.charm.back.utils.UrlUtils.REST_URL; @WebFilter(value = "/*", dispatcherTypes = DispatcherType.ERROR) @Slf4j @@ -26,6 +28,14 @@ public class ErrorFilter implements Filter { log.warn("Exception code {}", res.getStatus()); } - filterChain.doFilter(servletRequest, servletResponse); + String requestUri = (String) req.getAttribute(ERROR_REQUEST_URI); + + if (requestUri.startsWith(REST_URL)) { + res.setContentType("application/json"); + res.setCharacterEncoding("UTF-8"); + } else { + filterChain.doFilter(servletRequest, servletResponse); + } + } } diff --git a/src/ru/charm/back/controller/rest/LoginController.java b/src/ru/charm/back/controller/rest/LoginController.java new file mode 100644 index 0000000..74af948 --- /dev/null +++ b/src/ru/charm/back/controller/rest/LoginController.java @@ -0,0 +1,46 @@ +package ru.charm.back.controller.rest; + +import com.fasterxml.jackson.databind.DatabindException; +import com.fasterxml.jackson.databind.ObjectMapper; +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 lombok.extern.slf4j.Slf4j; +import ru.charm.back.dto.LoginDto; +import ru.charm.back.dto.ProfileGetDto; +import ru.charm.back.mapper.RequestToLoginDtoMapper; +import ru.charm.back.service.ProfileService; + +import java.io.BufferedReader; +import java.io.IOException; +import java.util.Optional; + +import static ru.charm.back.utils.UrlUtils.LOGIN_REST_URL; + +@WebServlet(LOGIN_REST_URL) +@Slf4j +public class LoginController extends HttpServlet { + private final ProfileService service = ProfileService.getInstance(); + private final ObjectMapper objectMapper = new ObjectMapper(); + + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { + try (BufferedReader reader = req.getReader()) { + LoginDto dto = objectMapper.readValue(reader, LoginDto.class); + Optional userDetailOpt = service.login(dto); + + if (userDetailOpt.isPresent()) { + req.getSession().setAttribute("userDetails", userDetailOpt.get()); + return; + } else { + resp.sendError(HttpServletResponse.SC_NOT_FOUND); + return; + } + } catch (DatabindException e) { + resp.sendError(HttpServletResponse.SC_BAD_REQUEST); + } + } +} diff --git a/src/ru/charm/back/controller/rest/ProfileController.java b/src/ru/charm/back/controller/rest/ProfileController.java new file mode 100644 index 0000000..71fde65 --- /dev/null +++ b/src/ru/charm/back/controller/rest/ProfileController.java @@ -0,0 +1,52 @@ +package ru.charm.back.controller.rest; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.json.JsonMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import jakarta.servlet.annotation.MultipartConfig; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import ru.charm.back.dto.ProfileGetDto; +import ru.charm.back.service.ProfileService; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Optional; + +import static jakarta.servlet.http.HttpServletResponse.SC_NOT_FOUND; +import static ru.charm.back.utils.UrlUtils.REST_URL; + +@WebServlet(REST_URL + "/profile") +@MultipartConfig +public class ProfileController extends HttpServlet { + private final ProfileService service = ProfileService.getInstance(); + + private final ObjectMapper objectMapper = JsonMapper.builder() + .configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true) + .addModule(new JavaTimeModule()) + .build(); + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + try (PrintWriter writer = resp.getWriter()) { + resp.setContentType("application/json"); + resp.setCharacterEncoding("UTF-8"); + + String sId = req.getParameter("id"); + if (sId != null) { + Optional optProfileDto = service.findById(Long.parseLong(sId)); + if (optProfileDto.isPresent()) { + ProfileGetDto profileGetDto = optProfileDto.get(); + objectMapper.writeValue(writer, profileGetDto); + } else { + resp.sendError(SC_NOT_FOUND); + } + } else { + objectMapper.writeValue(writer, service.findAll()); + } + } + } +} \ No newline at end of file diff --git a/src/ru/charm/back/utils/UrlUtils.java b/src/ru/charm/back/utils/UrlUtils.java new file mode 100644 index 0000000..dd5615a --- /dev/null +++ b/src/ru/charm/back/utils/UrlUtils.java @@ -0,0 +1,33 @@ +package ru.charm.back.utils; + +import lombok.experimental.UtilityClass; + +import java.util.Set; + +@UtilityClass +public class UrlUtils { + + public static final String PROFILE_URL = "/profile"; + public static final String CREDENTIALS_URL = "/credentials"; + public static final String LOGIN_URL = "/login"; + public static final String LOGOUT_URL = "/logout"; + public static final String REGISTRATION_URL = "/registration"; + public static final String LANG_URL = "/lang"; + public static final String CONTENT_URL = "/content"; + public static final String BASE_CONTENT_PATH = "/Users/andrey.s.eliseev/Downloads"; + + public static final Set PRIVATE_PATHS = Set.of(PROFILE_URL, CREDENTIALS_URL); + + public static final Set ENTRY_PATHS = Set.of(LOGIN_URL, REGISTRATION_URL); + + public static String getJspPath(String url) { + return "/WEB-INF/jsp" + url + ".jsp"; + } + + public static final String REST_URL = "/api/v1"; + public static final String LOGIN_REST_URL = REST_URL + LOGIN_URL; + + public static String getProfilePhotoPath(Long id, String fileName) { + return "/profiles/" + id + "/" + fileName; + } +}