From c4e33cf22faf1f997913d1ec60f231911bb69ca5 Mon Sep 17 00:00:00 2001 From: geonhos Date: Thu, 9 May 2024 10:10:12 +0900 Subject: [PATCH] =?UTF-8?q?=EB=A9=94=EB=89=B4=20=EB=8F=99=EC=A0=81=20?= =?UTF-8?q?=EB=85=B8=EC=B6=9C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- poc/admin/build.gradle | 1 + poc/admin/database/docker-compose.yml | 2 +- .../poc/admin/app/login/LoginResult.java | 41 +++++++++++- .../poc/admin/app/login/LoginService.java | 26 +++++++- .../bpgroup/poc/admin/domain/admin/Menu.java | 35 +++++++--- .../poc/admin/domain/admin/MenuGroup.java | 25 +++++++ .../admin/domain/admin/MenuRepository.java | 6 ++ .../bpgroup/poc/admin/domain/admin/Role.java | 8 ++- .../poc/admin/domain/admin/RoleMenu.java | 10 +-- .../authentication/AuthenticationDetail.java | 66 +++++++++++++++++++ .../poc/admin/values/AdministratorMenu.java | 4 ++ .../poc/admin/web/login/LoginController.java | 4 +- .../src/main/resources/application-local.yml | 2 +- poc/admin/src/main/resources/application.yml | 2 +- poc/admin/src/main/resources/data.sql | 49 ++++++++++++-- .../main/resources/templates/layout/lnb.html | 28 ++++---- 16 files changed, 267 insertions(+), 42 deletions(-) create mode 100644 poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/MenuGroup.java create mode 100644 poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/MenuRepository.java create mode 100644 poc/admin/src/main/java/com/bpgroup/poc/admin/values/AdministratorMenu.java diff --git a/poc/admin/build.gradle b/poc/admin/build.gradle index ffa503d..90325d8 100644 --- a/poc/admin/build.gradle +++ b/poc/admin/build.gradle @@ -21,6 +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 diff --git a/poc/admin/database/docker-compose.yml b/poc/admin/database/docker-compose.yml index 3cf2142..f0a0c7f 100644 --- a/poc/admin/database/docker-compose.yml +++ b/poc/admin/database/docker-compose.yml @@ -12,7 +12,7 @@ services: environment: - TZ=Asia/Seoul - MARIADB_ROOT_PASSWORD=root - - MARIADB_DATABASE=login + - MARIADB_DATABASE=admin-system - MARIADB_USER=admin - MARIADB_PASSWORD=1234 diff --git a/poc/admin/src/main/java/com/bpgroup/poc/admin/app/login/LoginResult.java b/poc/admin/src/main/java/com/bpgroup/poc/admin/app/login/LoginResult.java index a4ed910..5195fbd 100644 --- a/poc/admin/src/main/java/com/bpgroup/poc/admin/app/login/LoginResult.java +++ b/poc/admin/src/main/java/com/bpgroup/poc/admin/app/login/LoginResult.java @@ -1,22 +1,59 @@ package com.bpgroup.poc.admin.app.login; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.ToString; +import java.util.HashSet; +import java.util.Set; + @Getter -@ToString public class LoginResult { private Long id; private String loginId; private String name; private String email; - public static LoginResult of(Long id, String loginId, String name, String email) { + private Set menus = new HashSet<>(); + + public static LoginResult of(Long id, String loginId, String name, String email, Set menus) { LoginResult loginResult = new LoginResult(); loginResult.id = id; loginResult.loginId = loginId; loginResult.name = name; loginResult.email = email; + loginResult.menus = menus; return loginResult; } + + @Getter + @ToString + @EqualsAndHashCode + public static class MenuInfo { + private String menuGroupUri; + private String menuGroupName; + private Integer menuGroupSortOrder; + private String menuUri; + private String menuName; + private Integer menuSortOrder; + + public static MenuInfo of( + String menuGroupUri, + String menuGroupName, + Integer menuGroupSortOrder, + String menuUri, + String menuName, + Integer menuSortOrder + ) { + MenuInfo menuInfo = new MenuInfo(); + menuInfo.menuGroupUri = menuGroupUri; + menuInfo.menuGroupName = menuGroupName; + menuInfo.menuGroupSortOrder = menuGroupSortOrder; + menuInfo.menuUri = menuUri; + menuInfo.menuName = menuName; + menuInfo.menuSortOrder = menuSortOrder; + return menuInfo; + } + } + } diff --git a/poc/admin/src/main/java/com/bpgroup/poc/admin/app/login/LoginService.java b/poc/admin/src/main/java/com/bpgroup/poc/admin/app/login/LoginService.java index ae69d8d..5f07459 100644 --- a/poc/admin/src/main/java/com/bpgroup/poc/admin/app/login/LoginService.java +++ b/poc/admin/src/main/java/com/bpgroup/poc/admin/app/login/LoginService.java @@ -7,11 +7,16 @@ import com.bpgroup.poc.admin.domain.admin.AdministratorRepository; import lombok.RequiredArgsConstructor; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import java.util.Comparator; +import java.util.LinkedHashSet; import java.util.Optional; +import java.util.stream.Collectors; @Service @RequiredArgsConstructor +@Transactional public class LoginService { private final AdministratorRepository loginRepository; @@ -32,8 +37,27 @@ public class LoginService { administrator.get().getId(), administrator.get().getLoginId(), administrator.get().getName(), - administrator.get().getLoginId() + administrator.get().getLoginId(), + getMenus(administrator.get()) ); } + private static LinkedHashSet getMenus(Administrator administrator) { + return administrator.getAdministratorRole().getRole().getRoleMenus().stream() + .map(roleMenu -> LoginResult.MenuInfo.of( + roleMenu.getMenu().getMenuGroup().getUri(), + roleMenu.getMenu().getMenuGroup().getName(), + roleMenu.getMenu().getMenuGroup().getSortOrder(), + roleMenu.getMenu().getUri(), + roleMenu.getMenu().getName(), + roleMenu.getMenu().getSortOrder() + )) + .sorted( + Comparator + .comparingInt(LoginResult.MenuInfo::getMenuGroupSortOrder) + .thenComparingInt(LoginResult.MenuInfo::getMenuSortOrder) + ) + .collect(Collectors.toCollection(LinkedHashSet::new)); + } + } 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 index 35b35af..054d477 100644 --- 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 @@ -1,14 +1,29 @@ package com.bpgroup.poc.admin.domain.admin; -import lombok.RequiredArgsConstructor; +import com.bpgroup.poc.admin.domain.BaseEntity; +import jakarta.persistence.*; +import lombok.Getter; -@RequiredArgsConstructor -public enum Menu { - ADMINISTRATOR_MANAGEMENT("/admin/management", "관리자 관리"), - ROLE_MANAGEMENT("/admin/role", "권한 관리"), - MENU_MANAGEMENT("/admin/menu", "메뉴 관리") - ; +@Getter +@Entity +@Table(name = "menu") +public class Menu extends BaseEntity { - private final String uri; - private final String name; -} \ No newline at end of file + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "uri", length = 100, nullable = false) + private String uri; + + @Column(name = "name", length = 100, nullable = false) + private String name; + + @Column(name = "sort_order", nullable = false) + private Integer sortOrder; + + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) + @JoinColumn(name = "menu_group_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) + private MenuGroup menuGroup; + +} diff --git a/poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/MenuGroup.java b/poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/MenuGroup.java new file mode 100644 index 0000000..cfba4f3 --- /dev/null +++ b/poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/MenuGroup.java @@ -0,0 +1,25 @@ +package com.bpgroup.poc.admin.domain.admin; + +import com.bpgroup.poc.admin.domain.BaseEntity; +import jakarta.persistence.*; +import lombok.Getter; + +@Getter +@Entity +@Table(name = "menu_group") +public class MenuGroup extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "uri", length = 100, nullable = false) + private String uri; + + @Column(name = "name", length = 100, nullable = false) + private String name; + + @Column(name = "sort_order", nullable = false) + private Integer sortOrder; + +} diff --git a/poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/MenuRepository.java b/poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/MenuRepository.java new file mode 100644 index 0000000..9ce7974 --- /dev/null +++ b/poc/admin/src/main/java/com/bpgroup/poc/admin/domain/admin/MenuRepository.java @@ -0,0 +1,6 @@ +package com.bpgroup.poc.admin.domain.admin; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MenuRepository extends JpaRepository { +} 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 index 02a6a23..3d9e3df 100644 --- 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 @@ -2,10 +2,12 @@ package com.bpgroup.poc.admin.domain.admin; import com.bpgroup.poc.admin.domain.BaseEntity; import jakarta.persistence.*; +import lombok.Getter; -import java.util.ArrayList; -import java.util.List; +import java.util.HashSet; +import java.util.Set; +@Getter @Entity @Table(name = "role") public class Role extends BaseEntity { @@ -21,6 +23,6 @@ public class Role extends BaseEntity { private String description; @OneToMany(mappedBy = "role", fetch = FetchType.LAZY) - private List roleMenus = new ArrayList<>(); + private Set roleMenus = new HashSet<>(); } 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 index df8a1d4..4ebf40b 100644 --- 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 @@ -2,9 +2,11 @@ package com.bpgroup.poc.admin.domain.admin; import com.bpgroup.poc.admin.domain.BaseEntity; import jakarta.persistence.*; +import lombok.Getter; -@Table -@Entity(name = "role_menu") +@Getter +@Entity +@Table(name = "role_menu") public class RoleMenu extends BaseEntity { @Id @@ -15,8 +17,8 @@ public class RoleMenu extends BaseEntity { @JoinColumn(name = "role_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) private Role role; - @Enumerated(EnumType.STRING) - @Column(name = "menu", length = 100, nullable = false) + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) + @JoinColumn(name = "menu_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) private Menu menu; } diff --git a/poc/admin/src/main/java/com/bpgroup/poc/admin/security/authentication/AuthenticationDetail.java b/poc/admin/src/main/java/com/bpgroup/poc/admin/security/authentication/AuthenticationDetail.java index ce78b35..d702f7e 100644 --- a/poc/admin/src/main/java/com/bpgroup/poc/admin/security/authentication/AuthenticationDetail.java +++ b/poc/admin/src/main/java/com/bpgroup/poc/admin/security/authentication/AuthenticationDetail.java @@ -1,7 +1,11 @@ package com.bpgroup.poc.admin.security.authentication; import com.bpgroup.poc.admin.app.login.LoginResult; +import lombok.EqualsAndHashCode; import lombok.Getter; +import lombok.ToString; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; @Getter public class AuthenticationDetail { @@ -11,12 +15,74 @@ public class AuthenticationDetail { private String name; private String email; + private MultiValueMap menus = new LinkedMultiValueMap<>(); + public static AuthenticationDetail from(LoginResult result) { AuthenticationDetail authenticationDetail = new AuthenticationDetail(); authenticationDetail.id = result.getId(); authenticationDetail.loginId = result.getLoginId(); authenticationDetail.name = result.getName(); authenticationDetail.email = result.getEmail(); + + result.getMenus().forEach(menu -> authenticationDetail.menus.add( + MenuOneDepth.of( + menu.getMenuGroupUri(), + menu.getMenuGroupName(), + menu.getMenuGroupSortOrder() + ), + MenuTwoDepth.of( + menu.getMenuUri(), + menu.getMenuName(), + menu.getMenuSortOrder() + ) + )); + return authenticationDetail; } + + /** + * EqualsAndHashCode annotattion이 없을 경우 MultiValueMap을 사용할 때 중복된 key를 찾지 못함 + */ + @Getter + @ToString + @EqualsAndHashCode + private static class MenuOneDepth { + private String uri; + private String name; + private Integer sortOrder; + + public static MenuOneDepth of( + String uri, + String name, + Integer sortOrder + ) { + MenuOneDepth menu = new MenuOneDepth(); + menu.uri = uri; + menu.name = name; + menu.sortOrder = sortOrder; + return menu; + } + + } + + @Getter + @ToString + private static class MenuTwoDepth { + private String uri; + private String name; + private Integer sortOrder; + + public static MenuTwoDepth of( + String uri, + String name, + Integer sortOrder + ) { + MenuTwoDepth menu = new MenuTwoDepth(); + menu.uri = uri; + menu.name = name; + menu.sortOrder = sortOrder; + return menu; + } + } + } diff --git a/poc/admin/src/main/java/com/bpgroup/poc/admin/values/AdministratorMenu.java b/poc/admin/src/main/java/com/bpgroup/poc/admin/values/AdministratorMenu.java new file mode 100644 index 0000000..f485fd3 --- /dev/null +++ b/poc/admin/src/main/java/com/bpgroup/poc/admin/values/AdministratorMenu.java @@ -0,0 +1,4 @@ +package com.bpgroup.poc.admin.values; + +public class AdministratorMenu { +} diff --git a/poc/admin/src/main/java/com/bpgroup/poc/admin/web/login/LoginController.java b/poc/admin/src/main/java/com/bpgroup/poc/admin/web/login/LoginController.java index 0db4d8a..79e5d0a 100644 --- a/poc/admin/src/main/java/com/bpgroup/poc/admin/web/login/LoginController.java +++ b/poc/admin/src/main/java/com/bpgroup/poc/admin/web/login/LoginController.java @@ -4,12 +4,14 @@ import com.bpgroup.poc.admin.security.authentication.AuthenticationFailReason; 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.RequestParam; @Controller +@RequestMapping("/login") public class LoginController { - @GetMapping("/login") + @GetMapping public String loginPage( @RequestParam(required = false) AuthenticationFailReason error, Model model diff --git a/poc/admin/src/main/resources/application-local.yml b/poc/admin/src/main/resources/application-local.yml index a33e61d..d51ea7f 100644 --- a/poc/admin/src/main/resources/application-local.yml +++ b/poc/admin/src/main/resources/application-local.yml @@ -4,7 +4,7 @@ spring: mode: always datasource: - url: jdbc:mariadb://localhost:3307/login + url: jdbc:mariadb://localhost:3307/admin-system username: admin password: 1234 driver-class-name: org.mariadb.jdbc.Driver diff --git a/poc/admin/src/main/resources/application.yml b/poc/admin/src/main/resources/application.yml index 175c5f5..b7e819b 100644 --- a/poc/admin/src/main/resources/application.yml +++ b/poc/admin/src/main/resources/application.yml @@ -1,6 +1,6 @@ spring: application: - name: login + name: admin profiles: default: local \ No newline at end of file diff --git a/poc/admin/src/main/resources/data.sql b/poc/admin/src/main/resources/data.sql index 259b787..b587923 100644 --- a/poc/admin/src/main/resources/data.sql +++ b/poc/admin/src/main/resources/data.sql @@ -1,5 +1,6 @@ INSERT INTO `administrator` (`login_id`, `password`, `email`, `name`, `create_date`, `update_date`) -VALUES ('admin', '$2a$10$g6UOrQ/OS8o5r5CJk7C5juVFaItQ62U3EIn8zLPzkFplM3wVLvKZ2', 'admin@admin.com', '홍길동', CURDATE(), CURDATE()); +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()), @@ -9,9 +10,47 @@ VALUES ('SUPER_ADMIN', '최고 관리자', 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()); +INSERT INTO `menu_group` (`uri`, `name`, `sort_order`, `create_date`, `update_date`) +VALUES ('/admin', '관리자 관리', 2, CURDATE(), CURDATE()), + ('/settings', '설정', 3, CURDATE(), CURDATE()), + ('/temp', '임시', 1, CURDATE(), CURDATE()); + +INSERT INTO `menu` (`uri`, `name`, `sort_order`, `menu_group_id`, `create_date`, `update_date`) +VALUES ('/admin/management', '관리자 관리', 1, 1, CURDATE(), CURDATE()), + ('/admin/role', '권한 관리', 2, 1, CURDATE(), CURDATE()), + ('/admin/temp01', '관리자 임시 1', 4, 1, CURDATE(), CURDATE()), + ('/admin/temp02', '관리자 임시 2', 3, 1, CURDATE(), CURDATE()) +; + +INSERT INTO `menu` (`uri`, `name`, `sort_order`, `menu_group_id`, `create_date`, `update_date`) +VALUES ('/temp/temp01', '임시 01', 4, 3, CURDATE(), CURDATE()), + ('/temp/temp02', '임시 02', 2, 3, CURDATE(), CURDATE()), + ('/temp/temp03', '임시 03', 1, 3, CURDATE(), CURDATE()), + ('/temp/temp04', '임시 04', 3, 3, CURDATE(), CURDATE()) +; + + +INSERT INTO `menu` (`uri`, `name`, `sort_order`, `menu_group_id`, `create_date`, `update_date`) +VALUES ('/settings/code', '코드 관리', 1, 2, CURDATE(), CURDATE()), + ('/settings/component', '컴포넌트', 1, 2, CURDATE(), CURDATE()), + ('/settings/temp01', '세팅 임시 1', 4, 2, CURDATE(), CURDATE()), + ('/settings/temp02', '세팅 임시 2', 3, 2, CURDATE(), CURDATE()) +; + +INSERT INTO `role_menu` (`role_id`, `menu_id`, `create_date`, `update_date`) +VALUES ('1', '1', CURDATE(), CURDATE()), + ('1', '2', CURDATE(), CURDATE()), + ('1', '3', CURDATE(), CURDATE()), + ('1', '4', CURDATE(), CURDATE()), + ('1', '5', CURDATE(), CURDATE()), + ('1', '6', CURDATE(), CURDATE()), + ('1', '7', CURDATE(), CURDATE()), + ('1', '8', CURDATE(), CURDATE()), + ('1', '9', CURDATE(), CURDATE()), + ('1', '10', CURDATE(), CURDATE()), + ('1', '11', CURDATE(), CURDATE()), + ('1', '12', CURDATE(), CURDATE()) +; + diff --git a/poc/admin/src/main/resources/templates/layout/lnb.html b/poc/admin/src/main/resources/templates/layout/lnb.html index bf7f63e..05df06e 100644 --- a/poc/admin/src/main/resources/templates/layout/lnb.html +++ b/poc/admin/src/main/resources/templates/layout/lnb.html @@ -6,18 +6,20 @@ - + \ No newline at end of file