diff --git a/poc/admin/build.gradle b/poc/admin/build.gradle index fd1e58f..ffa503d 100644 --- a/poc/admin/build.gradle +++ b/poc/admin/build.gradle @@ -21,7 +21,7 @@ dependencies { // thymeleaf implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' - implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6' + implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:3.3.0' // jpa implementation 'org.springframework.boot:spring-boot-starter-data-jpa' diff --git a/poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/Administrator.java b/poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/Administrator.java index bf0f65e..d82129c 100644 --- a/poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/Administrator.java +++ b/poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/Administrator.java @@ -13,16 +13,19 @@ public class Administrator extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(name = "login_id") + @Column(name = "login_id", length = 100, nullable = false) private String loginId; - @Column(name = "password") + @Column(name = "password", length = 255, nullable = false) private String password; - @Column(name = "email") + @Column(name = "email", length = 100, nullable = false) private String email; - @Column(name = "name") + @Column(name = "name", length = 100, nullable = false) private String name; + @OneToOne(mappedBy = "administrator", fetch = FetchType.LAZY) + private AdministratorRole administratorRole; + } diff --git a/poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/AdministratorRole.java b/poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/AdministratorRole.java new file mode 100644 index 0000000..bb26a09 --- /dev/null +++ b/poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/AdministratorRole.java @@ -0,0 +1,24 @@ +package com.bpgroup.poc.admin.domain.admin; + +import com.bpgroup.poc.admin.domain.BaseEntity; +import jakarta.persistence.*; +import lombok.Getter; + +@Getter +@Entity +@Table(name = "administrator_role") +public class AdministratorRole extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) + @JoinColumn(name = "administrator_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) + private Administrator administrator; + + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) + @JoinColumn(name = "role_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) + private Role role; + +} diff --git a/poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/Menu.java b/poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/Menu.java new file mode 100644 index 0000000..35b35af --- /dev/null +++ b/poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/Menu.java @@ -0,0 +1,14 @@ +package com.bpgroup.poc.admin.domain.admin; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public enum Menu { + ADMINISTRATOR_MANAGEMENT("/admin/management", "관리자 관리"), + ROLE_MANAGEMENT("/admin/role", "권한 관리"), + MENU_MANAGEMENT("/admin/menu", "메뉴 관리") + ; + + private final String uri; + private final String name; +} \ No newline at end of file diff --git a/poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/Role.java b/poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/Role.java new file mode 100644 index 0000000..02a6a23 --- /dev/null +++ b/poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/Role.java @@ -0,0 +1,26 @@ +package com.bpgroup.poc.admin.domain.admin; + +import com.bpgroup.poc.admin.domain.BaseEntity; +import jakarta.persistence.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Table(name = "role") +public class Role extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "name", length = 100, nullable = false) + private String name; + + @Column(name = "description") + private String description; + + @OneToMany(mappedBy = "role", fetch = FetchType.LAZY) + private List roleMenus = new ArrayList<>(); + +} diff --git a/poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/RoleMenu.java b/poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/RoleMenu.java new file mode 100644 index 0000000..df8a1d4 --- /dev/null +++ b/poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/RoleMenu.java @@ -0,0 +1,22 @@ +package com.bpgroup.poc.admin.domain.admin; + +import com.bpgroup.poc.admin.domain.BaseEntity; +import jakarta.persistence.*; + +@Table +@Entity(name = "role_menu") +public class RoleMenu extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) + @JoinColumn(name = "role_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) + private Role role; + + @Enumerated(EnumType.STRING) + @Column(name = "menu", length = 100, nullable = false) + private Menu menu; + +} diff --git a/poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/RoleRepository.java b/poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/RoleRepository.java new file mode 100644 index 0000000..449da60 --- /dev/null +++ b/poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/RoleRepository.java @@ -0,0 +1,6 @@ +package com.bpgroup.poc.admin.domain.admin; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface RoleRepository extends JpaRepository { +} diff --git a/poc/admin/src/main/java/com/bpgroup/poc/admin/security/SecurityConfig.java b/poc/admin/src/main/java/com/bpgroup/poc/admin/security/SecurityConfig.java index 24c7d3e..9261d37 100644 --- a/poc/admin/src/main/java/com/bpgroup/poc/admin/security/SecurityConfig.java +++ b/poc/admin/src/main/java/com/bpgroup/poc/admin/security/SecurityConfig.java @@ -2,6 +2,7 @@ package com.bpgroup.poc.admin.security; import com.bpgroup.poc.admin.common.FormatHelper; import com.bpgroup.poc.admin.security.authentication.AuthenticationFailException; +import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -15,6 +16,7 @@ import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import java.util.Objects; @Configuration +@RequiredArgsConstructor public class SecurityConfig { private static final String LOGIN_PATH = "/login"; @@ -27,19 +29,20 @@ public class SecurityConfig { CsrfTokenRequestAttributeHandler csrfTokenRequestAttributeHandler = new CsrfTokenRequestAttributeHandler(); csrfTokenRequestAttributeHandler.setCsrfRequestAttributeName("_csrf"); - http.csrf(t -> { - t.csrfTokenRequestHandler(csrfTokenRequestAttributeHandler) + http.csrf(c -> { + c.csrfTokenRequestHandler(csrfTokenRequestAttributeHandler) .ignoringRequestMatchers("/common/modal/**") .ignoringRequestMatchers(LOGIN_PATH, LOGOUT_PATH, ERROR_PATH) // CSRF 무시 URL 설정 .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()); // CSRF 토큰을 쿠키에 저장 및 사용 가능 }).addFilterAfter(new CsrfCookieFilter(), BasicAuthenticationFilter.class); // 로그인이 완료된 후 CSRF Filter 를 실행 // 인증 설정 - http.authorizeHttpRequests(c -> c - .requestMatchers("/css/**", "/images/**", "/js/**").permitAll() - .requestMatchers("/common/modal/**").permitAll() - .requestMatchers(LOGIN_PATH, LOGOUT_PATH, ERROR_PATH).permitAll() - .anyRequest().authenticated()); + http.authorizeHttpRequests(c -> { + c.requestMatchers("/css/**", "/images/**", "/js/**").permitAll() + .requestMatchers("/common/modal/**").permitAll() + .requestMatchers(LOGIN_PATH, LOGOUT_PATH, ERROR_PATH).permitAll() + .anyRequest().authenticated(); + }); http.formLogin(c -> c .loginPage(LOGIN_PATH) diff --git a/poc/admin/src/main/java/com/bpgroup/poc/admin/web/advice/PathInfoControllerAdvice.java b/poc/admin/src/main/java/com/bpgroup/poc/admin/web/advice/PathInfoControllerAdvice.java new file mode 100644 index 0000000..044d070 --- /dev/null +++ b/poc/admin/src/main/java/com/bpgroup/poc/admin/web/advice/PathInfoControllerAdvice.java @@ -0,0 +1,35 @@ +package com.bpgroup.poc.admin.web.advice; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ModelAttribute; + +@ControllerAdvice +@RequiredArgsConstructor +public class PathInfoControllerAdvice { + + @ModelAttribute("pathInfo") + public PathInfo pathInfo(HttpServletRequest request) { + return new PathInfo(request); + } + + @Getter + public static class PathInfo { + + private final String currentPath; + + public PathInfo(HttpServletRequest request) { + this.currentPath = request.getServletPath(); + } + + public boolean isActive(String path) { + return currentPath.startsWith(path); + } + + public String activeClass(String path) { + return isActive(path) ? "active" : ""; + } + } +} diff --git a/poc/admin/src/main/java/com/bpgroup/poc/admin/web/main/admin/management/AdministratorManagementController.java b/poc/admin/src/main/java/com/bpgroup/poc/admin/web/main/admin/management/AdministratorManagementController.java new file mode 100644 index 0000000..ebddf87 --- /dev/null +++ b/poc/admin/src/main/java/com/bpgroup/poc/admin/web/main/admin/management/AdministratorManagementController.java @@ -0,0 +1,16 @@ +package com.bpgroup.poc.admin.web.main.admin.management; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +@RequestMapping("/admin/management") +public class AdministratorManagementController { + + @GetMapping + public String administratorManagementPage() { + return "main/admin/management/list"; + } + +} diff --git a/poc/admin/src/main/java/com/bpgroup/poc/admin/web/main/admin/role/RoleController.java b/poc/admin/src/main/java/com/bpgroup/poc/admin/web/main/admin/role/RoleController.java new file mode 100644 index 0000000..4ab3b8e --- /dev/null +++ b/poc/admin/src/main/java/com/bpgroup/poc/admin/web/main/admin/role/RoleController.java @@ -0,0 +1,15 @@ +package com.bpgroup.poc.admin.web.main.admin.role; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +@RequestMapping("/admin/role") +public class RoleController { + + @GetMapping + public String rolePage() { + return "main/admin/role/list"; + } +} diff --git a/poc/admin/src/main/resources/data.sql b/poc/admin/src/main/resources/data.sql index 1544061..259b787 100644 --- a/poc/admin/src/main/resources/data.sql +++ b/poc/admin/src/main/resources/data.sql @@ -1,2 +1,17 @@ INSERT INTO `administrator` (`login_id`, `password`, `email`, `name`, `create_date`, `update_date`) -VALUES ('admin', '$2a$10$g6UOrQ/OS8o5r5CJk7C5juVFaItQ62U3EIn8zLPzkFplM3wVLvKZ2', 'admin@admin.com', '홍길동', CURDATE(), CURDATE()); \ No newline at end of file +VALUES ('admin', '$2a$10$g6UOrQ/OS8o5r5CJk7C5juVFaItQ62U3EIn8zLPzkFplM3wVLvKZ2', 'admin@admin.com', '홍길동', CURDATE(), CURDATE()); + +INSERT INTO `role` (`name`, `description`, `create_date`, `update_date`) +VALUES ('SUPER_ADMIN', '최고 관리자', CURDATE(), CURDATE()), + ('ADMIN', '관리자', CURDATE(), CURDATE()), + ('CLIENT', '고객', CURDATE(), CURDATE()); + +INSERT INTO `administrator_role` (`administrator_id`, `role_id`, `create_date`, `update_date`) +VALUES ('1', '1', CURDATE(), CURDATE()); + +INSERT INTO `role_menu` (`role_id`, `menu`, `create_date`, `update_date`) +VALUES ('1', 'ADMINISTRATOR_MANAGEMENT', CURDATE(), CURDATE()), + ('1', 'ROLE_MANAGEMENT', CURDATE(), CURDATE()), + ('1', 'MENU_MANAGEMENT', CURDATE(), CURDATE()); + + diff --git a/poc/admin/src/main/resources/templates/layout/common.html b/poc/admin/src/main/resources/templates/layout/common.html new file mode 100644 index 0000000..64dd0c5 --- /dev/null +++ b/poc/admin/src/main/resources/templates/layout/common.html @@ -0,0 +1,36 @@ + + + + + + + 관리자 시스템 + + + + + + + + + + + + + + +
+ +
+
+ +
+ +
+
+ + + + + diff --git a/poc/admin/src/main/resources/templates/main/gnb.html b/poc/admin/src/main/resources/templates/layout/gnb.html similarity index 100% rename from poc/admin/src/main/resources/templates/main/gnb.html rename to poc/admin/src/main/resources/templates/layout/gnb.html diff --git a/poc/admin/src/main/resources/templates/layout/lnb.html b/poc/admin/src/main/resources/templates/layout/lnb.html new file mode 100644 index 0000000..bf7f63e --- /dev/null +++ b/poc/admin/src/main/resources/templates/layout/lnb.html @@ -0,0 +1,23 @@ + + + + + + + diff --git a/poc/admin/src/main/resources/templates/main/admin/management/list.html b/poc/admin/src/main/resources/templates/main/admin/management/list.html new file mode 100644 index 0000000..bb3d4ab --- /dev/null +++ b/poc/admin/src/main/resources/templates/main/admin/management/list.html @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/poc/admin/src/main/resources/templates/main/admin/management/root.html b/poc/admin/src/main/resources/templates/main/admin/management/root.html new file mode 100644 index 0000000..761f575 --- /dev/null +++ b/poc/admin/src/main/resources/templates/main/admin/management/root.html @@ -0,0 +1,15 @@ + + + + + + + + + + + + + diff --git a/poc/admin/src/main/resources/templates/main/admin/role/list.html b/poc/admin/src/main/resources/templates/main/admin/role/list.html new file mode 100644 index 0000000..d4ebe8f --- /dev/null +++ b/poc/admin/src/main/resources/templates/main/admin/role/list.html @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/poc/admin/src/main/resources/templates/main/admin/role/root.html b/poc/admin/src/main/resources/templates/main/admin/role/root.html new file mode 100644 index 0000000..761f575 --- /dev/null +++ b/poc/admin/src/main/resources/templates/main/admin/role/root.html @@ -0,0 +1,15 @@ + + + + + + + + + + + + + diff --git a/poc/admin/src/main/resources/templates/main/lnb.html b/poc/admin/src/main/resources/templates/main/lnb.html deleted file mode 100644 index 9e3015f..0000000 --- a/poc/admin/src/main/resources/templates/main/lnb.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - diff --git a/poc/admin/src/main/resources/templates/main/main.html b/poc/admin/src/main/resources/templates/main/main.html index 2be9a79..0e4b13b 100644 --- a/poc/admin/src/main/resources/templates/main/main.html +++ b/poc/admin/src/main/resources/templates/main/main.html @@ -1,37 +1,17 @@ - - - - - 관리자 시스템 - - - - - - - - - - - - - + xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" + layout:decorate="~{layout/common.html}"> -
- -
-
- -
- -
-
- - + + + + + +