diff --git a/stockMate/src/main/java/com/stockm8/config/WebConfig.java b/stockMate/src/main/java/com/stockm8/config/WebConfig.java index b8b86f1..efb8192 100644 --- a/stockMate/src/main/java/com/stockm8/config/WebConfig.java +++ b/stockMate/src/main/java/com/stockm8/config/WebConfig.java @@ -18,8 +18,6 @@ import org.springframework.context.support.ResourceBundleMessageSource; import org.springframework.format.FormatterRegistry; import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.jdbc.datasource.DataSourceTransactionManager; -import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.validation.MessageCodesResolver; import org.springframework.validation.Validator; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; @@ -44,6 +42,7 @@ import com.stockm8.interceptor.AdminInterceptor; import com.stockm8.interceptor.AuthorizationInterceptor; import com.stockm8.interceptor.FlashMessageInterceptor; +import com.stockm8.interceptor.ManagerInterceptor; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; @@ -65,6 +64,9 @@ public class WebConfig implements WebMvcConfigurer { @Autowired private AdminInterceptor adminInterceptor; + @Autowired + private ManagerInterceptor managerInterceptor; + /** * 인터셉터 설정 * 특정 URL 패턴에 대해 AuthorizationInterceptor를 적용하며, 일부 URL은 제외합니다. @@ -83,10 +85,14 @@ public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(adminInterceptor) .addPathPatterns("/admin/**") // /admin/** 경로에만 적용 .excludePathPatterns(excludedPaths.toArray(new String[0])); + + registry.addInterceptor(managerInterceptor) + .addPathPatterns("/manager/**") // /admin/** 경로에만 적용 + .excludePathPatterns(excludedPaths.toArray(new String[0])); // Intercepter 적용 registry.addInterceptor(authorizationInterceptor) - .addPathPatterns("/dashboard", "/business", "/category/**", "/product/**", "/warehouse/**", "/stock/**", "/order/**") // 인터셉터를 적용할 경로 + .addPathPatterns("/dashboard", "/business", "/category/**", "/product/**", "/warehouse/**", "/stock/**", "/order/**") // 인터셉터를 적용할 경로 .excludePathPatterns( // 제외할 경로들 "/", // 홈 경로 제외 "/favicon.ico", // 브라우저 기본 요청 제외 diff --git a/stockMate/src/main/java/com/stockm8/controller/BusinessController.java b/stockMate/src/main/java/com/stockm8/controller/BusinessController.java index 0883da0..54bd38b 100644 --- a/stockMate/src/main/java/com/stockm8/controller/BusinessController.java +++ b/stockMate/src/main/java/com/stockm8/controller/BusinessController.java @@ -36,7 +36,6 @@ public String registBusinessGET() throws Exception { return "business/register"; // 회사 등록 폼 페이지로 이동 } - // 비즈니스 등록 처리 @PostMapping("/register") public String registerBusinessPOST(BusinessVO business, HttpServletRequest request, Model model) throws Exception { diff --git a/stockMate/src/main/java/com/stockm8/controller/HomeController.java b/stockMate/src/main/java/com/stockm8/controller/HomeController.java index bea48e0..90f1ccf 100644 --- a/stockMate/src/main/java/com/stockm8/controller/HomeController.java +++ b/stockMate/src/main/java/com/stockm8/controller/HomeController.java @@ -12,9 +12,9 @@ import javax.mail.internet.MimeMessage; import javax.servlet.http.HttpSession; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @@ -22,6 +22,10 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.mvc.support.RedirectAttributes; +import com.stockm8.domain.enums.UserRole; +import com.stockm8.domain.vo.UserVO; +import com.stockm8.service.UserService; + /** * Handles requests for the application home page. */ @@ -30,6 +34,9 @@ public class HomeController { private static final Logger logger = LoggerFactory.getLogger(HomeController.class); + @Autowired + private UserService userService; + /** * Simply selects the home view to render by returning its name. */ @@ -45,20 +52,31 @@ public String home(Locale locale, Model model) { model.addAttribute("serverTime", formattedDate ); return "main"; } + //http://localhost:8088/dashboard @RequestMapping(value = "/dashboard", method = RequestMethod.GET) - public String dash(Locale locale, Model model) { + public String dash(HttpSession session, Locale locale, Model model) throws Exception { logger.info("😁Welcome dashboad😁! The client locale is {}.", locale); + // 세션에서 userId 가져오기 + Long userId = (session != null) ? (Long) session.getAttribute("userId") : null; + + // userId로 사용자 정보 조회 + UserVO user = userService.getUserById(userId); + logger.info("세션으로 들고온 유저정보: " + user); + UserRole userRole = user.getUserRole(); + Date date = new Date(); DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale); String formattedDate = dateFormat.format(date); model.addAttribute("serverTime", formattedDate ); - + model.addAttribute("userRole", userRole); + return "dashboard"; } + // http://localhost:8088/qrScanner @RequestMapping(value = "/qrScanner", method = RequestMethod.GET) public String qrScanner(Locale locale, Model model) { diff --git a/stockMate/src/main/java/com/stockm8/controller/ManagerController.java b/stockMate/src/main/java/com/stockm8/controller/ManagerController.java index 2a1358d..a7c22a9 100644 --- a/stockMate/src/main/java/com/stockm8/controller/ManagerController.java +++ b/stockMate/src/main/java/com/stockm8/controller/ManagerController.java @@ -1,5 +1,68 @@ package com.stockm8.controller; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.SessionAttribute; + +import com.stockm8.domain.dto.PendingUserDTO; +import com.stockm8.domain.enums.UserRole; +import com.stockm8.domain.vo.UserVO; +import com.stockm8.service.UserService; + +@Controller +@RequestMapping(value = "/manager/*") public class ManagerController { + + private static final Logger logger = LoggerFactory.getLogger(AdminController.class); + + @Autowired + private UserService userService; + + /** + * 매니저 메인 페이지 표시(GET) + * + * @throws Exception + * + */ + // http://localhost:8088/admin/main + @GetMapping("/main") + public String managerMainGET(@SessionAttribute("userId") Long userId, Model model) throws Exception { + logger.info("managerMainGET() 호출 - 페이지 접근 (userId: {})", userId); + + // userId로 사용자 정보 가져오기 + UserVO user = userService.getUserById(userId); + + if (user != null) { + // 관리자 여부 확인 (MANAGER인 경우) + boolean isManager = user.getUserRole() == UserRole.MANAGER; + model.addAttribute("isManager", isManager); // JSP에 전달할 데이터 + } + return "manager/main"; // 메인 페이지 반환 + } + + // http://localhost:8088/manager/approve + @GetMapping("/approve") + public String managerApproveGET(@SessionAttribute("userId") Long userId, Model model) throws Exception { + logger.info("managerApproveGET() 호출 - 페이지 접근 (userId: {})", userId); + + // userId로 사용자 정보 가져오기 + UserVO user = userService.getUserById(userId); + int businessId = user.getBusinessId(); + + // 조건에 맞는 사용자와 사업자 정보 가져오기 + List pendingUsers = userService.getStaffByBusinessId(businessId); + + // JSP로 전달 + model.addAttribute("pendingUsers", pendingUsers); + + return "admin/approve"; // JSP 페이지 반환 + } } diff --git a/stockMate/src/main/java/com/stockm8/controller/UserController.java b/stockMate/src/main/java/com/stockm8/controller/UserController.java index df31de6..6fa29ca 100644 --- a/stockMate/src/main/java/com/stockm8/controller/UserController.java +++ b/stockMate/src/main/java/com/stockm8/controller/UserController.java @@ -86,7 +86,7 @@ public String userSignUpPOST(/* @ModelAttribute */ UserVO user) throws Exception return "redirect:/user/signin"; } - // http://localhost:8088/user/login (GET) + // http://localhost:8088/user/signin (GET) // 로그인 - 정보입력 / GET @RequestMapping(value = "/signin", method = RequestMethod.GET) public String userSgininGET(HttpServletRequest request, Model model) { @@ -100,7 +100,6 @@ public String userSgininGET(HttpServletRequest request, Model model) { model.addAttribute("errorMessage", errorMessage); } } - return "/user/signin"; } @@ -121,6 +120,7 @@ public String userLoginPOST(UserVO user, RedirectAttributes rttr, HttpSession se // 세션에 사용자 ID 저장 session.setAttribute("userId", resultVO.getUserId()); + logger.debug("세션 저장 완료 - Session ID: {}, User ID: {}", session.getId(), session.getAttribute("userId")); // 원래 요청 URL로 리다이렉트 String redirectUrl = (String) session.getAttribute("redirectAfterLogin"); @@ -131,7 +131,6 @@ public String userLoginPOST(UserVO user, RedirectAttributes rttr, HttpSession se } return "redirect:/dashboard"; } - // 로그인 실패 처리 logger.warn("로그인 실패, 사용자 정보를 찾을 수 없습니다."); rttr.addFlashAttribute("errorMessage", "로그인에 실패했습니다. 아이디와 비밀번호를 확인해주세요."); @@ -341,14 +340,14 @@ public void changePasswordPOST( // 비밀번호 찾기 - GET - @RequestMapping(value = "/findPassword", method = RequestMethod.GET) + @RequestMapping(value = "/findpassword", method = RequestMethod.GET) public String findPasswordGet() { - return "/user/findPassword"; // 비밀번호 찾기 페이지로 이동 + return "/user/findpassword"; // 비밀번호 찾기 페이지로 이동 } // 비밀번호 찾기 - POST - @RequestMapping(value = "/findPassword", method = RequestMethod.POST) - public String findPasswordPost(@RequestParam("email") String email, + @RequestMapping(value = "/findpassword", method = RequestMethod.POST) + public String findpasswordPost(@RequestParam("email") String email, @RequestParam("name") String name, Model model) { try { @@ -364,13 +363,13 @@ public String findPasswordPost(@RequestParam("email") String email, // 비밀번호가 일치하지 않으면 오류 메시지 추가 logger.info("비밀번호 찾기 실패: 이메일 또는 이름이 일치하지 않음"); // 실패 로그 model.addAttribute("errorMessage", "이메일 또는 이름이 일치하지 않습니다."); - return "/user/findPassword"; // 비밀번호 찾기 페이지로 다시 이동 + return "/user/findpassword"; // 비밀번호 찾기 페이지로 다시 이동 } } catch (Exception e) { e.printStackTrace(); logger.error("비밀번호 찾기 처리 중 오류 발생", e); // 예외 로그 추가 model.addAttribute("errorMessage", "비밀번호 찾기 처리 중 오류가 발생했습니다."); - return "/user/findPassword"; // 오류 발생 시 비밀번호 찾기 페이지로 돌아감 + return "/user/findpassword"; // 오류 발생 시 비밀번호 찾기 페이지로 돌아감 } } diff --git a/stockMate/src/main/java/com/stockm8/interceptor/AdminInterceptor.java b/stockMate/src/main/java/com/stockm8/interceptor/AdminInterceptor.java index 836e04a..875a1ca 100644 --- a/stockMate/src/main/java/com/stockm8/interceptor/AdminInterceptor.java +++ b/stockMate/src/main/java/com/stockm8/interceptor/AdminInterceptor.java @@ -1,7 +1,5 @@ package com.stockm8.interceptor; -import java.io.IOException; - import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; diff --git a/stockMate/src/main/java/com/stockm8/interceptor/AuthorizationInterceptor.java b/stockMate/src/main/java/com/stockm8/interceptor/AuthorizationInterceptor.java index 9739ae3..f9ce408 100644 --- a/stockMate/src/main/java/com/stockm8/interceptor/AuthorizationInterceptor.java +++ b/stockMate/src/main/java/com/stockm8/interceptor/AuthorizationInterceptor.java @@ -132,7 +132,7 @@ private boolean sendErrorMessage(HttpServletRequest request, HttpServletResponse private boolean isValidUser(HttpServletRequest request, HttpServletResponse response, UserVO user) throws Exception { // 허용된 역할 정의 - List allowedRoles = Arrays.asList(UserRole.MANAGER, UserRole.ADMIN /*Role.STAFF*/); + List allowedRoles = Arrays.asList(UserRole.MANAGER, UserRole.ADMIN /*UserRole.STAFF*/); // 1. PENDING 상태 처리 if (user.getUserStatus() == UserStatus.PENDING) { @@ -148,18 +148,18 @@ private boolean isValidUser(HttpServletRequest request, HttpServletResponse resp if (user.getBusinessId() != null) { logger.info("PENDING 상태의 사용자({})가 businessId({})를 가지고 있습니다. 메인 페이지로 이동합니다.", user.getUserId(), user.getBusinessId()); - sendErrorMessage(request, response, "승인 절차가 완료될 때까지 기다려주세요.", "/user/main"); + sendErrorMessage(request, response, "승인 절차가 완료될 때까지 기다려주세요.", "/main"); return false; } } // 2. APPROVED 상태 처리 if (user.getUserStatus() == UserStatus.APPROVED) { - if (!allowedRoles.contains(user.getUserRole())) { - logger.warn("권한 없는 사용자({})가 접근을 시도했습니다. 대시보드로 이동합니다. (역할: {})", user.getUserId(), user.getUserRole()); - return sendErrorMessage(request, response, "접근 권한이 없습니다.", "/dashboard"); - } - +// if (!allowedRoles.contains(user.getUserRole())) { +// logger.warn("권한 없는 사용자({})가 접근을 시도했습니다. 대시보드로 이동합니다. (역할: {})", user.getUserId(), user.getUserRole()); +// return sendErrorMessage(request, response, "접근 권한이 없습니다.", "/dashboard"); +// } +// logger.info("APPROVED 상태의 사용자({})가 대시보드로 접근합니다.", user.getUserId()); return true; } diff --git a/stockMate/src/main/java/com/stockm8/interceptor/ManagerInterceptor.java b/stockMate/src/main/java/com/stockm8/interceptor/ManagerInterceptor.java new file mode 100644 index 0000000..d9a4f87 --- /dev/null +++ b/stockMate/src/main/java/com/stockm8/interceptor/ManagerInterceptor.java @@ -0,0 +1,113 @@ +package com.stockm8.interceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.FlashMap; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.support.RequestContextUtils; + +import com.stockm8.domain.enums.UserRole; +import com.stockm8.domain.vo.UserVO; +import com.stockm8.service.UserService; + +@Component +public class ManagerInterceptor implements HandlerInterceptor { + + private static final Logger logger = LoggerFactory.getLogger(ManagerInterceptor.class); + + @Autowired + private UserService userService; // 유저 정보를 가져오기 위한 서비스 클래스 + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + HttpSession session = request.getSession(false); + Long userId = (session != null) ? (Long) session.getAttribute("userId") : null; + + // 1. 세션에서 사용자 ID 확인 + if (userId == null) { + logger.warn("세션에 유저 ID가 없습니다. 로그인 페이지로 이동합니다."); + saveRequestedUrlToSession(request); + return sendErrorMessage(request, response, "세션이 만료되었습니다. 다시 로그인해주세요.", "/user/signin"); + } + + // 2. DB에서 사용자 정보 조회 + UserVO user = userService.getUserById(userId); + if (user == null) { + logger.warn("해당 유저({}) 정보를 찾을 수 없습니다. 회원가입 페이지로 이동합니다.", userId); + return sendErrorMessage(request, response, "유저 정보를 찾을 수 없습니다. 회원가입을 진행해주세요.", "/user/signup"); + } + + // 3. 삭제된 계정 확인 + if (Boolean.TRUE.equals(user.getIsDeleted())) { + logger.warn("삭제된 유저({})입니다. 로그인 페이지로 이동합니다.", userId); + return sendErrorMessage(request, response, "삭제된 계정입니다. 관리자에게 문의해주세요.", "/user/signin"); + } + + // 4. 관리자 권한 확인 + if (user.getUserRole() != UserRole.MANAGER) { + logger.warn("권한 없는 접근 시도 (유저 ID: {}, 역할: {}).", userId, user.getUserRole()); + return sendErrorMessage(request, response, "매니저 전용 페이지입니다. 접근 권한이 없습니다.", "/user/signin"); + } + + // 검증 성공: 사용자 정보 저장 + logger.info("매니저 확인 완료 (유저 ID: {}, 이름: {}).", userId, user.getUserName()); + request.setAttribute("currentUser", user); + return true; + } + + /** + * 에러 메시지와 함께 리다이렉트 처리 + */ + private boolean sendErrorMessage(HttpServletRequest request, HttpServletResponse response, String message, String redirectUrl) + throws Exception { + + // FlashMap 객체 생성 및 에러 메시지 저장 + FlashMap flashMap = new FlashMap(); + flashMap.put("errorMessage", message); + + // FlashMap 저장소에 FlashMap 추가 + RequestContextUtils.getFlashMapManager(request).saveOutputFlashMap(flashMap, request, response); + + // 로그 출력 + logger.info("FlashMap에 저장된 에러 메시지: {}", message); + logger.info("리다이렉트 대상 URL: {}", redirectUrl); + + // 리다이렉트 수행 + response.sendRedirect(redirectUrl); + return false; // handlerInterceptor 처리 중단 + } + + /** + * 요청한 URL을 세션에 저장 (로그인 후 리다이렉트를 위해) + */ + private void saveRequestedUrlToSession(HttpServletRequest request) { + String requestedUrl = request.getRequestURI(); + String queryString = request.getQueryString(); + if (queryString != null) { + requestedUrl += "?" + queryString; + } + request.getSession().setAttribute("requestedUrl", requestedUrl); + } + + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, + ModelAndView modelAndView) throws Exception { + // TODO Auto-generated method stub + + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) + throws Exception { + // TODO Auto-generated method stub + + } + +} diff --git a/stockMate/src/main/resources/mappers/userMapper.xml b/stockMate/src/main/resources/mappers/userMapper.xml index 83193b9..20d5451 100644 --- a/stockMate/src/main/resources/mappers/userMapper.xml +++ b/stockMate/src/main/resources/mappers/userMapper.xml @@ -92,7 +92,7 @@ ORDER BY u.created_at DESC - SELECT u.user_id AS approvedUserId, u.email, u.user_name, diff --git a/stockMate/src/main/webapp/WEB-INF/views/dashboard.jsp b/stockMate/src/main/webapp/WEB-INF/views/dashboard.jsp index a404f17..40a9308 100644 --- a/stockMate/src/main/webapp/WEB-INF/views/dashboard.jsp +++ b/stockMate/src/main/webapp/WEB-INF/views/dashboard.jsp @@ -9,7 +9,6 @@ 대시보드 - -
-

Warehouse Management Solutions

-

스마트한 재고 관리와 최적화된 물류 시스템을 제공합니다.

-
- + + + + +
+

Warehouse Management Solutions

+

스마트한 재고 관리와 최적화된 물류 시스템을 제공합니다.

+
+ + @@ -270,4 +279,4 @@ body { } - + \ No newline at end of file diff --git a/stockMate/src/main/webapp/WEB-INF/views/manager/main.jsp b/stockMate/src/main/webapp/WEB-INF/views/manager/main.jsp new file mode 100644 index 0000000..88ccedc --- /dev/null +++ b/stockMate/src/main/webapp/WEB-INF/views/manager/main.jsp @@ -0,0 +1,67 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8"%> + + + + +매니저 페이지 + + + + + +

매니저 메인

+ + +
+
+ +
+
+ +
+
+ +
+
+ + +
+

회사 정보 - 사업자 번호, 연락처 등등 푸터 내용

+
+ + + diff --git a/stockMate/src/main/webapp/WEB-INF/views/user/signin.jsp b/stockMate/src/main/webapp/WEB-INF/views/user/signin.jsp index 1075eb2..0a3e6d7 100644 --- a/stockMate/src/main/webapp/WEB-INF/views/user/signin.jsp +++ b/stockMate/src/main/webapp/WEB-INF/views/user/signin.jsp @@ -1,108 +1,165 @@ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> + - - -로그인 - + + +