From 16718f027778cb9ed06874e21d29904e7f9ce15d Mon Sep 17 00:00:00 2001 From: devmrko Date: Tue, 23 Jun 2026 11:28:59 +0900 Subject: [PATCH] [Developer] #424 add user and permission management Refs #424 --- .../domain/permission/PermissionView.java | 12 ++ .../ProtectedObjectCreateCommand.java | 12 ++ .../vpdbackoffice/domain/user/AppUser.java | 1 + .../domain/user/UserCreateCommand.java | 11 ++ .../domain/user/UserRoleView.java | 9 ++ .../mapper/PermissionMapper.java | 5 + .../mapper/ProtectedObjectMapper.java | 14 ++ .../vpdbackoffice/mapper/UserMapper.java | 14 ++ .../service/PermissionService.java | 17 +++ .../service/ProtectedObjectService.java | 45 +++++- .../vpdbackoffice/service/UserService.java | 64 +++++++++ .../web/PermissionController.java | 8 ++ .../web/ProtectedObjectController.java | 48 +++++++ .../vpdbackoffice/web/UserController.java | 77 ++++++++++ .../resources/mapper/PermissionMapper.xml | 22 +++ .../mapper/ProtectedObjectMapper.xml | 30 ++++ src/main/resources/mapper/UserMapper.xml | 50 +++++++ src/main/resources/static/css/app.css | 8 ++ .../resources/templates/fragments/layout.html | 2 + src/main/resources/templates/objects.html | 78 +++++++++++ src/main/resources/templates/permissions.html | 38 +++++ src/main/resources/templates/users.html | 131 ++++++++++++++++++ .../service/PermissionServiceTest.java | 15 +- 23 files changed, 708 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/cloudhandson/vpdbackoffice/domain/permission/PermissionView.java create mode 100644 src/main/java/com/cloudhandson/vpdbackoffice/domain/protectedobject/ProtectedObjectCreateCommand.java create mode 100644 src/main/java/com/cloudhandson/vpdbackoffice/domain/user/UserCreateCommand.java create mode 100644 src/main/java/com/cloudhandson/vpdbackoffice/domain/user/UserRoleView.java create mode 100644 src/main/java/com/cloudhandson/vpdbackoffice/service/UserService.java create mode 100644 src/main/java/com/cloudhandson/vpdbackoffice/web/ProtectedObjectController.java create mode 100644 src/main/java/com/cloudhandson/vpdbackoffice/web/UserController.java create mode 100644 src/main/resources/templates/objects.html create mode 100644 src/main/resources/templates/users.html diff --git a/src/main/java/com/cloudhandson/vpdbackoffice/domain/permission/PermissionView.java b/src/main/java/com/cloudhandson/vpdbackoffice/domain/permission/PermissionView.java new file mode 100644 index 0000000..293a6ef --- /dev/null +++ b/src/main/java/com/cloudhandson/vpdbackoffice/domain/permission/PermissionView.java @@ -0,0 +1,12 @@ +package com.cloudhandson.vpdbackoffice.domain.permission; + +public record PermissionView( + long permissionId, + long roleId, + String roleName, + long objectId, + String objectName, + String action, + String rules +) { +} diff --git a/src/main/java/com/cloudhandson/vpdbackoffice/domain/protectedobject/ProtectedObjectCreateCommand.java b/src/main/java/com/cloudhandson/vpdbackoffice/domain/protectedobject/ProtectedObjectCreateCommand.java new file mode 100644 index 0000000..364d3d9 --- /dev/null +++ b/src/main/java/com/cloudhandson/vpdbackoffice/domain/protectedobject/ProtectedObjectCreateCommand.java @@ -0,0 +1,12 @@ +package com.cloudhandson.vpdbackoffice.domain.protectedobject; + +import jakarta.validation.constraints.NotBlank; + +public record ProtectedObjectCreateCommand( + @NotBlank String owner, + @NotBlank String objectName, + @NotBlank String ordsPath, + String columns, + String sensitiveColumns +) { +} diff --git a/src/main/java/com/cloudhandson/vpdbackoffice/domain/user/AppUser.java b/src/main/java/com/cloudhandson/vpdbackoffice/domain/user/AppUser.java index b22aee6..49f2a56 100644 --- a/src/main/java/com/cloudhandson/vpdbackoffice/domain/user/AppUser.java +++ b/src/main/java/com/cloudhandson/vpdbackoffice/domain/user/AppUser.java @@ -5,6 +5,7 @@ public record AppUser( String username, String empNo, String deptCode, + String canReadContents, String activeYn ) { diff --git a/src/main/java/com/cloudhandson/vpdbackoffice/domain/user/UserCreateCommand.java b/src/main/java/com/cloudhandson/vpdbackoffice/domain/user/UserCreateCommand.java new file mode 100644 index 0000000..c0a721c --- /dev/null +++ b/src/main/java/com/cloudhandson/vpdbackoffice/domain/user/UserCreateCommand.java @@ -0,0 +1,11 @@ +package com.cloudhandson.vpdbackoffice.domain.user; + +import jakarta.validation.constraints.NotBlank; + +public record UserCreateCommand( + @NotBlank String username, + @NotBlank String empNo, + @NotBlank String deptCode, + boolean canReadContents +) { +} diff --git a/src/main/java/com/cloudhandson/vpdbackoffice/domain/user/UserRoleView.java b/src/main/java/com/cloudhandson/vpdbackoffice/domain/user/UserRoleView.java new file mode 100644 index 0000000..f303e27 --- /dev/null +++ b/src/main/java/com/cloudhandson/vpdbackoffice/domain/user/UserRoleView.java @@ -0,0 +1,9 @@ +package com.cloudhandson.vpdbackoffice.domain.user; + +public record UserRoleView( + long userId, + String username, + long roleId, + String roleName +) { +} diff --git a/src/main/java/com/cloudhandson/vpdbackoffice/mapper/PermissionMapper.java b/src/main/java/com/cloudhandson/vpdbackoffice/mapper/PermissionMapper.java index 399928c..69e14e8 100644 --- a/src/main/java/com/cloudhandson/vpdbackoffice/mapper/PermissionMapper.java +++ b/src/main/java/com/cloudhandson/vpdbackoffice/mapper/PermissionMapper.java @@ -3,6 +3,7 @@ package com.cloudhandson.vpdbackoffice.mapper; import com.cloudhandson.vpdbackoffice.domain.permission.AppRole; import com.cloudhandson.vpdbackoffice.domain.permission.PermissionRule; import com.cloudhandson.vpdbackoffice.domain.permission.PermissionSet; +import com.cloudhandson.vpdbackoffice.domain.permission.PermissionView; import java.util.List; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -14,6 +15,8 @@ public interface PermissionMapper { AppRole findRole(@Param("roleId") long roleId); + List findPermissionViews(); + PermissionSet findPermissionSet(@Param("roleId") long roleId, @Param("objectId") long objectId); Long findPermissionId(@Param("roleId") long roleId, @Param("objectId") long objectId); @@ -33,6 +36,8 @@ public interface PermissionMapper { void insertVisibleColumn(@Param("permissionId") long permissionId, @Param("columnName") String columnName); + int deletePermission(@Param("permissionId") long permissionId); + long nextPermissionId(); long nextRuleId(); diff --git a/src/main/java/com/cloudhandson/vpdbackoffice/mapper/ProtectedObjectMapper.java b/src/main/java/com/cloudhandson/vpdbackoffice/mapper/ProtectedObjectMapper.java index 3945a54..7568ec9 100644 --- a/src/main/java/com/cloudhandson/vpdbackoffice/mapper/ProtectedObjectMapper.java +++ b/src/main/java/com/cloudhandson/vpdbackoffice/mapper/ProtectedObjectMapper.java @@ -1,6 +1,7 @@ package com.cloudhandson.vpdbackoffice.mapper; import com.cloudhandson.vpdbackoffice.domain.protectedobject.ProtectedColumn; +import com.cloudhandson.vpdbackoffice.domain.protectedobject.ProtectedObjectCreateCommand; import com.cloudhandson.vpdbackoffice.domain.protectedobject.ProtectedObject; import java.util.List; import org.apache.ibatis.annotations.Mapper; @@ -14,4 +15,17 @@ public interface ProtectedObjectMapper { ProtectedObject findById(@Param("objectId") long objectId); List findColumns(@Param("objectId") long objectId); + + long nextObjectId(); + + long nextColumnId(); + + void insertObject(@Param("objectId") long objectId, @Param("command") ProtectedObjectCreateCommand command); + + void insertColumn(@Param("columnId") long columnId, + @Param("objectId") long objectId, + @Param("columnName") String columnName, + @Param("sensitiveYn") String sensitiveYn); + + int disableObject(@Param("objectId") long objectId); } diff --git a/src/main/java/com/cloudhandson/vpdbackoffice/mapper/UserMapper.java b/src/main/java/com/cloudhandson/vpdbackoffice/mapper/UserMapper.java index a349cb0..b2afd28 100644 --- a/src/main/java/com/cloudhandson/vpdbackoffice/mapper/UserMapper.java +++ b/src/main/java/com/cloudhandson/vpdbackoffice/mapper/UserMapper.java @@ -1,6 +1,8 @@ package com.cloudhandson.vpdbackoffice.mapper; import com.cloudhandson.vpdbackoffice.domain.user.AppUser; +import com.cloudhandson.vpdbackoffice.domain.user.UserCreateCommand; +import com.cloudhandson.vpdbackoffice.domain.user.UserRoleView; import java.util.List; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -10,5 +12,17 @@ public interface UserMapper { List findAll(); + List findUserRoles(); + AppUser findById(@Param("userId") long userId); + + long nextUserId(); + + void insertUser(@Param("userId") long userId, @Param("command") UserCreateCommand command); + + int updateActive(@Param("userId") long userId, @Param("activeYn") String activeYn); + + void insertUserRole(@Param("userId") long userId, @Param("roleId") long roleId); + + int deleteUserRole(@Param("userId") long userId, @Param("roleId") long roleId); } diff --git a/src/main/java/com/cloudhandson/vpdbackoffice/service/PermissionService.java b/src/main/java/com/cloudhandson/vpdbackoffice/service/PermissionService.java index 86ef10c..f3abc82 100644 --- a/src/main/java/com/cloudhandson/vpdbackoffice/service/PermissionService.java +++ b/src/main/java/com/cloudhandson/vpdbackoffice/service/PermissionService.java @@ -5,6 +5,7 @@ import com.cloudhandson.vpdbackoffice.domain.permission.AppRole; import com.cloudhandson.vpdbackoffice.domain.permission.PermissionRule; import com.cloudhandson.vpdbackoffice.domain.permission.PermissionSet; import com.cloudhandson.vpdbackoffice.domain.permission.PermissionSetCommand; +import com.cloudhandson.vpdbackoffice.domain.permission.PermissionView; import com.cloudhandson.vpdbackoffice.domain.permission.RuleCommand; import com.cloudhandson.vpdbackoffice.domain.protectedobject.ProtectedColumn; import com.cloudhandson.vpdbackoffice.mapper.PermissionMapper; @@ -38,6 +39,10 @@ public class PermissionService { return permissionMapper.findRoles(); } + public List findPermissionViews() { + return permissionMapper.findPermissionViews(); + } + @Transactional public PermissionSet savePermissionSet(PermissionSetCommand command) { if (!"SELECT".equalsIgnoreCase(command.action())) { @@ -83,6 +88,18 @@ public class PermissionService { return new PermissionSet(permissionId, command.roleId(), command.objectId(), "SELECT", List.of(), List.of()); } + @Transactional + public void deletePermission(long permissionId) { + permissionMapper.deleteRules(permissionId); + permissionMapper.deleteVisibleColumns(permissionId); + int deleted = permissionMapper.deletePermission(permissionId); + if (deleted == 0) { + throw new AppException("삭제할 권한을 찾을 수 없습니다."); + } + auditService.record(new AuditEvent("PERMISSION_DELETED", null, null, "SUCCESS", null, null, + "permissionId=" + permissionId)); + } + private void validateRules(List rules) { if (rules == null || rules.isEmpty()) { throw new AppException("행 규칙은 하나 이상 필요합니다."); diff --git a/src/main/java/com/cloudhandson/vpdbackoffice/service/ProtectedObjectService.java b/src/main/java/com/cloudhandson/vpdbackoffice/service/ProtectedObjectService.java index aa0474a..7b257d4 100644 --- a/src/main/java/com/cloudhandson/vpdbackoffice/service/ProtectedObjectService.java +++ b/src/main/java/com/cloudhandson/vpdbackoffice/service/ProtectedObjectService.java @@ -1,18 +1,27 @@ package com.cloudhandson.vpdbackoffice.service; +import com.cloudhandson.vpdbackoffice.domain.audit.AuditEvent; import com.cloudhandson.vpdbackoffice.domain.protectedobject.ProtectedColumn; import com.cloudhandson.vpdbackoffice.domain.protectedobject.ProtectedObject; +import com.cloudhandson.vpdbackoffice.domain.protectedobject.ProtectedObjectCreateCommand; import com.cloudhandson.vpdbackoffice.mapper.ProtectedObjectMapper; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Locale; +import java.util.Set; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service public class ProtectedObjectService { private final ProtectedObjectMapper mapper; + private final AuditService auditService; - public ProtectedObjectService(ProtectedObjectMapper mapper) { + public ProtectedObjectService(ProtectedObjectMapper mapper, AuditService auditService) { this.mapper = mapper; + this.auditService = auditService; } public List findEnabled() { @@ -30,4 +39,38 @@ public class ProtectedObjectService { public List findColumns(long objectId) { return mapper.findColumns(objectId); } + + @Transactional + public void createObject(ProtectedObjectCreateCommand command) { + long objectId = mapper.nextObjectId(); + mapper.insertObject(objectId, command); + Set sensitive = splitCsv(command.sensitiveColumns()); + for (String column : splitCsv(command.columns())) { + mapper.insertColumn(mapper.nextColumnId(), objectId, column, sensitive.contains(column) ? "Y" : "N"); + } + auditService.record(new AuditEvent("PROTECTED_OBJECT_CREATED", null, objectId, "SUCCESS", null, null, + command.objectName())); + } + + @Transactional + public void disableObject(long objectId) { + int updated = mapper.disableObject(objectId); + if (updated == 0) { + throw new AppException("보호 객체를 찾을 수 없습니다."); + } + auditService.record(new AuditEvent("PROTECTED_OBJECT_DISABLED", null, objectId, "SUCCESS", null, null, null)); + } + + private Set splitCsv(String value) { + Set result = new HashSet<>(); + if (value == null || value.isBlank()) { + return result; + } + Arrays.stream(value.split(",")) + .map(String::trim) + .filter(token -> !token.isBlank()) + .map(token -> token.toUpperCase(Locale.ROOT)) + .forEach(result::add); + return result; + } } diff --git a/src/main/java/com/cloudhandson/vpdbackoffice/service/UserService.java b/src/main/java/com/cloudhandson/vpdbackoffice/service/UserService.java new file mode 100644 index 0000000..238235e --- /dev/null +++ b/src/main/java/com/cloudhandson/vpdbackoffice/service/UserService.java @@ -0,0 +1,64 @@ +package com.cloudhandson.vpdbackoffice.service; + +import com.cloudhandson.vpdbackoffice.domain.audit.AuditEvent; +import com.cloudhandson.vpdbackoffice.domain.user.AppUser; +import com.cloudhandson.vpdbackoffice.domain.user.UserCreateCommand; +import com.cloudhandson.vpdbackoffice.domain.user.UserRoleView; +import com.cloudhandson.vpdbackoffice.mapper.UserMapper; +import java.util.List; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class UserService { + + private final UserMapper userMapper; + private final AuditService auditService; + + public UserService(UserMapper userMapper, AuditService auditService) { + this.userMapper = userMapper; + this.auditService = auditService; + } + + public List findAll() { + return userMapper.findAll(); + } + + public List findUserRoles() { + return userMapper.findUserRoles(); + } + + @Transactional + public void createUser(UserCreateCommand command) { + long userId = userMapper.nextUserId(); + userMapper.insertUser(userId, command); + auditService.record(new AuditEvent("USER_CREATED", null, null, "SUCCESS", null, null, command.username())); + } + + @Transactional + public void setActive(long userId, boolean active) { + int updated = userMapper.updateActive(userId, active ? "Y" : "N"); + if (updated == 0) { + throw new AppException("사용자를 찾을 수 없습니다."); + } + auditService.record(new AuditEvent("USER_ACTIVE_CHANGED", null, null, "SUCCESS", null, null, + "userId=" + userId + ",active=" + active)); + } + + @Transactional + public void grantRole(long userId, long roleId) { + userMapper.insertUserRole(userId, roleId); + auditService.record(new AuditEvent("USER_ROLE_GRANTED", null, null, "SUCCESS", null, null, + "userId=" + userId + ",roleId=" + roleId)); + } + + @Transactional + public void revokeRole(long userId, long roleId) { + int deleted = userMapper.deleteUserRole(userId, roleId); + if (deleted == 0) { + throw new AppException("삭제할 사용자 역할 매핑을 찾을 수 없습니다."); + } + auditService.record(new AuditEvent("USER_ROLE_REVOKED", null, null, "SUCCESS", null, null, + "userId=" + userId + ",roleId=" + roleId)); + } +} diff --git a/src/main/java/com/cloudhandson/vpdbackoffice/web/PermissionController.java b/src/main/java/com/cloudhandson/vpdbackoffice/web/PermissionController.java index 8d33270..c3635f5 100644 --- a/src/main/java/com/cloudhandson/vpdbackoffice/web/PermissionController.java +++ b/src/main/java/com/cloudhandson/vpdbackoffice/web/PermissionController.java @@ -30,6 +30,7 @@ public class PermissionController { public String permissions(Model model) { model.addAttribute("roles", permissionService.findRoles()); model.addAttribute("objects", protectedObjectService.findEnabled()); + model.addAttribute("permissions", permissionService.findPermissionViews()); return "permissions"; } @@ -52,4 +53,11 @@ public class PermissionController { redirectAttributes.addFlashAttribute("message", "권한을 저장했습니다."); return "redirect:/permissions"; } + + @PostMapping("/permissions/delete") + public String delete(@RequestParam long permissionId, RedirectAttributes redirectAttributes) { + permissionService.deletePermission(permissionId); + redirectAttributes.addFlashAttribute("message", "권한을 삭제했습니다."); + return "redirect:/permissions"; + } } diff --git a/src/main/java/com/cloudhandson/vpdbackoffice/web/ProtectedObjectController.java b/src/main/java/com/cloudhandson/vpdbackoffice/web/ProtectedObjectController.java new file mode 100644 index 0000000..fb45332 --- /dev/null +++ b/src/main/java/com/cloudhandson/vpdbackoffice/web/ProtectedObjectController.java @@ -0,0 +1,48 @@ +package com.cloudhandson.vpdbackoffice.web; + +import com.cloudhandson.vpdbackoffice.domain.protectedobject.ProtectedObjectCreateCommand; +import com.cloudhandson.vpdbackoffice.service.ProtectedObjectService; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +@Controller +public class ProtectedObjectController { + + private final ProtectedObjectService protectedObjectService; + + public ProtectedObjectController(ProtectedObjectService protectedObjectService) { + this.protectedObjectService = protectedObjectService; + } + + @GetMapping("/objects") + public String objects(Model model) { + model.addAttribute("objects", protectedObjectService.findEnabled()); + return "objects"; + } + + @PostMapping("/objects") + public String create( + @RequestParam String owner, + @RequestParam String objectName, + @RequestParam String ordsPath, + @RequestParam(required = false) String columns, + @RequestParam(required = false) String sensitiveColumns, + RedirectAttributes redirectAttributes + ) { + protectedObjectService.createObject( + new ProtectedObjectCreateCommand(owner, objectName, ordsPath, columns, sensitiveColumns)); + redirectAttributes.addFlashAttribute("message", "보호 객체를 추가했습니다."); + return "redirect:/objects"; + } + + @PostMapping("/objects/disable") + public String disable(@RequestParam long objectId, RedirectAttributes redirectAttributes) { + protectedObjectService.disableObject(objectId); + redirectAttributes.addFlashAttribute("message", "보호 객체를 비활성화했습니다."); + return "redirect:/objects"; + } +} diff --git a/src/main/java/com/cloudhandson/vpdbackoffice/web/UserController.java b/src/main/java/com/cloudhandson/vpdbackoffice/web/UserController.java new file mode 100644 index 0000000..45cc52b --- /dev/null +++ b/src/main/java/com/cloudhandson/vpdbackoffice/web/UserController.java @@ -0,0 +1,77 @@ +package com.cloudhandson.vpdbackoffice.web; + +import com.cloudhandson.vpdbackoffice.domain.user.UserCreateCommand; +import com.cloudhandson.vpdbackoffice.service.PermissionService; +import com.cloudhandson.vpdbackoffice.service.UserService; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +@Controller +public class UserController { + + private final UserService userService; + private final PermissionService permissionService; + + public UserController(UserService userService, PermissionService permissionService) { + this.userService = userService; + this.permissionService = permissionService; + } + + @GetMapping("/users") + public String users(Model model) { + model.addAttribute("users", userService.findAll()); + model.addAttribute("roles", permissionService.findRoles()); + model.addAttribute("userRoles", userService.findUserRoles()); + return "users"; + } + + @PostMapping("/users") + public String create( + @RequestParam String username, + @RequestParam String empNo, + @RequestParam String deptCode, + @RequestParam(defaultValue = "false") boolean canReadContents, + RedirectAttributes redirectAttributes + ) { + userService.createUser(new UserCreateCommand(username, empNo, deptCode, canReadContents)); + redirectAttributes.addFlashAttribute("message", "사용자를 추가했습니다."); + return "redirect:/users"; + } + + @PostMapping("/users/active") + public String active( + @RequestParam long userId, + @RequestParam boolean active, + RedirectAttributes redirectAttributes + ) { + userService.setActive(userId, active); + redirectAttributes.addFlashAttribute("message", "사용자 상태를 변경했습니다."); + return "redirect:/users"; + } + + @PostMapping("/users/roles") + public String grantRole( + @RequestParam long userId, + @RequestParam long roleId, + RedirectAttributes redirectAttributes + ) { + userService.grantRole(userId, roleId); + redirectAttributes.addFlashAttribute("message", "역할을 부여했습니다."); + return "redirect:/users"; + } + + @PostMapping("/users/roles/delete") + public String revokeRole( + @RequestParam long userId, + @RequestParam long roleId, + RedirectAttributes redirectAttributes + ) { + userService.revokeRole(userId, roleId); + redirectAttributes.addFlashAttribute("message", "역할을 해제했습니다."); + return "redirect:/users"; + } +} diff --git a/src/main/resources/mapper/PermissionMapper.xml b/src/main/resources/mapper/PermissionMapper.xml index d2d8aeb..b5e503c 100644 --- a/src/main/resources/mapper/PermissionMapper.xml +++ b/src/main/resources/mapper/PermissionMapper.xml @@ -14,6 +14,23 @@ WHERE role_id = #{roleId} + + + + + + + + + INSERT INTO cb_protected_object (object_id, owner, object_name, ords_path, enabled_yn) + VALUES ( + #{objectId}, + UPPER(#{command.owner}), + UPPER(#{command.objectName}), + #{command.ordsPath}, + 'Y' + ) + + + + INSERT INTO cb_protected_column (column_id, object_id, column_name, sensitive_yn) + VALUES (#{columnId}, #{objectId}, UPPER(#{columnName}), #{sensitiveYn}) + + + + UPDATE cb_protected_object + SET enabled_yn = 'N' + WHERE object_id = #{objectId} + diff --git a/src/main/resources/mapper/UserMapper.xml b/src/main/resources/mapper/UserMapper.xml index 9434274..0b6c819 100644 --- a/src/main/resources/mapper/UserMapper.xml +++ b/src/main/resources/mapper/UserMapper.xml @@ -7,6 +7,7 @@ user_name AS username, employee_no AS emp_no, dept_code, + can_read_contents, active AS active_yn FROM cb_app_user ORDER BY username @@ -17,8 +18,57 @@ user_name AS username, employee_no AS emp_no, dept_code, + can_read_contents, active AS active_yn FROM cb_app_user WHERE user_id = #{userId} + + + + + + + INSERT INTO cb_app_user ( + user_id, user_name, employee_no, dept_code, can_read_contents, active + ) VALUES ( + #{userId}, + #{command.username}, + #{command.empNo}, + #{command.deptCode}, + + 'Y' + 'N' + , + 'Y' + ) + + + + UPDATE cb_app_user + SET active = #{activeYn} + WHERE user_id = #{userId} + + + + INSERT INTO cb_user_role (user_id, role_id) + VALUES (#{userId}, #{roleId}) + + + + DELETE FROM cb_user_role + WHERE user_id = #{userId} + AND role_id = #{roleId} + diff --git a/src/main/resources/static/css/app.css b/src/main/resources/static/css/app.css index 6e114d8..3da194b 100644 --- a/src/main/resources/static/css/app.css +++ b/src/main/resources/static/css/app.css @@ -86,6 +86,14 @@ body { display: inline; } +.switch-field { + align-items: center; + display: flex; + gap: .5rem; + min-height: 38px; + padding-left: 2.5rem; +} + .token-value { display: block; margin-top: .5rem; diff --git a/src/main/resources/templates/fragments/layout.html b/src/main/resources/templates/fragments/layout.html index df9ec49..3cbeb0b 100644 --- a/src/main/resources/templates/fragments/layout.html +++ b/src/main/resources/templates/fragments/layout.html @@ -15,7 +15,9 @@
VPD Backoffice diff --git a/src/main/resources/templates/objects.html b/src/main/resources/templates/objects.html new file mode 100644 index 0000000..eeebc80 --- /dev/null +++ b/src/main/resources/templates/objects.html @@ -0,0 +1,78 @@ + + + + + +
+
+

테이블/뷰 관리

+

권한에 사용할 보호 객체와 ORDS 경로를 등록합니다.

+
+ +
+ +
+

테이블/뷰 추가

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

등록된 테이블/뷰

+
+ + + + + + + + + + + + + + + + + + + + + + +
IDOwnerObjectORDS Path
1ADMINCB_V_SEARCH_DOCUMENTSpath +
+ + + +
+
등록된 테이블/뷰가 없습니다.
+
+
+
+ + diff --git a/src/main/resources/templates/permissions.html b/src/main/resources/templates/permissions.html index aeb0af1..04bcab7 100644 --- a/src/main/resources/templates/permissions.html +++ b/src/main/resources/templates/permissions.html @@ -12,6 +12,7 @@
+

권한 추가

+ +
+

권한 목록

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
ID역할테이블/뷰Action행 규칙
100HR_DEPT_ROLECB_V_SEARCH_DOCUMENTSSELECTALL +
+ + + +
+
등록된 권한이 없습니다.
+
+
diff --git a/src/main/resources/templates/users.html b/src/main/resources/templates/users.html new file mode 100644 index 0000000..8c4b513 --- /dev/null +++ b/src/main/resources/templates/users.html @@ -0,0 +1,131 @@ + + + + + +
+
+

사용자 관리

+

Bearer Token과 권한 매핑에 사용할 내부 사용자를 관리합니다.

+
+ +
+ +
+

사용자 추가

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

사용자 목록

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
ID사용자명사번부서민감 컬럼상태
1agent_hrE10234HRNY +
+ + + + +
+
등록된 사용자가 없습니다.
+
+
+ +
+

역할 부여

+
+ + + + +
+
+ +
+

사용자 역할 목록

+
+ + + + + + + + + + + + + + + + + + +
사용자역할
agent_hrHR_DEPT_ROLE +
+ + + + +
+
부여된 역할이 없습니다.
+
+
+
+ + diff --git a/src/test/java/com/cloudhandson/vpdbackoffice/service/PermissionServiceTest.java b/src/test/java/com/cloudhandson/vpdbackoffice/service/PermissionServiceTest.java index b75bc19..b70ad22 100644 --- a/src/test/java/com/cloudhandson/vpdbackoffice/service/PermissionServiceTest.java +++ b/src/test/java/com/cloudhandson/vpdbackoffice/service/PermissionServiceTest.java @@ -7,6 +7,7 @@ import com.cloudhandson.vpdbackoffice.domain.permission.AppRole; import com.cloudhandson.vpdbackoffice.domain.permission.PermissionRule; import com.cloudhandson.vpdbackoffice.domain.permission.PermissionSet; import com.cloudhandson.vpdbackoffice.domain.permission.PermissionSetCommand; +import com.cloudhandson.vpdbackoffice.domain.permission.PermissionView; import com.cloudhandson.vpdbackoffice.domain.permission.RuleCommand; import com.cloudhandson.vpdbackoffice.domain.protectedobject.ProtectedColumn; import com.cloudhandson.vpdbackoffice.domain.protectedobject.ProtectedObject; @@ -25,7 +26,8 @@ class PermissionServiceTest { @BeforeEach void setUp() { permissionMapper = new FakePermissionMapper(); - protectedObjectService = new ProtectedObjectService(null) { + AuditService auditService = new AuditService(new NoopAuditMapper()); + protectedObjectService = new ProtectedObjectService(null, auditService) { @Override public ProtectedObject assertEnabled(long objectId) { return new ProtectedObject(1L, "ADMIN", "CB_V_SEARCH_DOCUMENTS", "cb-agent-security/vpd/documents", "Y"); @@ -36,7 +38,6 @@ class PermissionServiceTest { return List.of(); } }; - AuditService auditService = new AuditService(new NoopAuditMapper()); permissionService = new PermissionService(permissionMapper, protectedObjectService, auditService); } @@ -87,6 +88,11 @@ class PermissionServiceTest { return roleId == 10L ? new AppRole(10L, "HR_DEPT_ROLE", null) : null; } + @Override + public List findPermissionViews() { + return List.of(); + } + @Override public PermissionSet findPermissionSet(long roleId, long objectId) { return null; @@ -121,6 +127,11 @@ class PermissionServiceTest { public void insertVisibleColumn(long permissionId, String columnName) { } + @Override + public int deletePermission(long permissionId) { + return 1; + } + @Override public long nextPermissionId() { return 1000L;