[Developer] #424 hide orphan protected objects in permission picker
This commit is contained in:
@@ -29,6 +29,10 @@ public interface PermissionMapper {
|
|||||||
|
|
||||||
Long findPermissionId(@Param("roleId") long roleId, @Param("objectId") long objectId);
|
Long findPermissionId(@Param("roleId") long roleId, @Param("objectId") long objectId);
|
||||||
|
|
||||||
|
Long findObjectIdByPermissionId(@Param("permissionId") long permissionId);
|
||||||
|
|
||||||
|
int countPermissionsByObjectId(@Param("objectId") long objectId);
|
||||||
|
|
||||||
void insertPermission(@Param("permissionId") long permissionId,
|
void insertPermission(@Param("permissionId") long permissionId,
|
||||||
@Param("roleId") long roleId,
|
@Param("roleId") long roleId,
|
||||||
@Param("objectId") long objectId,
|
@Param("objectId") long objectId,
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ public interface ProtectedObjectMapper {
|
|||||||
|
|
||||||
List<ProtectedObject> findEnabled();
|
List<ProtectedObject> findEnabled();
|
||||||
|
|
||||||
|
List<ProtectedObject> findEnabledWithPermissions();
|
||||||
|
|
||||||
ProtectedObject findById(@Param("objectId") long objectId);
|
ProtectedObject findById(@Param("objectId") long objectId);
|
||||||
|
|
||||||
ProtectedObject findByOwnerAndName(@Param("owner") String owner, @Param("objectName") String objectName);
|
ProtectedObject findByOwnerAndName(@Param("owner") String owner, @Param("objectName") String objectName);
|
||||||
|
|||||||
@@ -110,12 +110,16 @@ public class PermissionService {
|
|||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void deletePermission(long permissionId) {
|
public void deletePermission(long permissionId) {
|
||||||
|
Long objectId = permissionMapper.findObjectIdByPermissionId(permissionId);
|
||||||
permissionMapper.deleteRules(permissionId);
|
permissionMapper.deleteRules(permissionId);
|
||||||
permissionMapper.deleteVisibleColumns(permissionId);
|
permissionMapper.deleteVisibleColumns(permissionId);
|
||||||
int deleted = permissionMapper.deletePermission(permissionId);
|
int deleted = permissionMapper.deletePermission(permissionId);
|
||||||
if (deleted == 0) {
|
if (deleted == 0) {
|
||||||
throw new AppException("삭제할 권한을 찾을 수 없습니다.");
|
throw new AppException("삭제할 권한을 찾을 수 없습니다.");
|
||||||
}
|
}
|
||||||
|
if (objectId != null && permissionMapper.countPermissionsByObjectId(objectId) == 0) {
|
||||||
|
protectedObjectService.disableObject(objectId);
|
||||||
|
}
|
||||||
auditService.record(new AuditEvent("PERMISSION_DELETED", null, null, "SUCCESS", null, null,
|
auditService.record(new AuditEvent("PERMISSION_DELETED", null, null, "SUCCESS", null, null,
|
||||||
"permissionId=" + permissionId));
|
"permissionId=" + permissionId));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,10 @@ public class ProtectedObjectService {
|
|||||||
return mapper.findEnabled();
|
return mapper.findEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<ProtectedObject> findEnabledWithPermissions() {
|
||||||
|
return mapper.findEnabledWithPermissions();
|
||||||
|
}
|
||||||
|
|
||||||
public List<DatabaseObjectOption> findDatabaseObjects() {
|
public List<DatabaseObjectOption> findDatabaseObjects() {
|
||||||
CacheEntry<List<DatabaseObjectOption>> cached = databaseObjectsCache;
|
CacheEntry<List<DatabaseObjectOption>> cached = databaseObjectsCache;
|
||||||
if (cached != null && !cached.expired()) {
|
if (cached != null && !cached.expired()) {
|
||||||
@@ -83,6 +87,7 @@ public class ProtectedObjectService {
|
|||||||
for (String column : splitCsv(normalized.columns())) {
|
for (String column : splitCsv(normalized.columns())) {
|
||||||
mapper.insertColumn(mapper.nextColumnId(), objectId, column, sensitive.contains(column) ? "Y" : "N");
|
mapper.insertColumn(mapper.nextColumnId(), objectId, column, sensitive.contains(column) ? "Y" : "N");
|
||||||
}
|
}
|
||||||
|
databaseObjectsCache = null;
|
||||||
protectedColumnsCache.remove(objectId);
|
protectedColumnsCache.remove(objectId);
|
||||||
auditService.record(new AuditEvent("PROTECTED_OBJECT_CREATED", null, objectId, "SUCCESS", null, null,
|
auditService.record(new AuditEvent("PROTECTED_OBJECT_CREATED", null, objectId, "SUCCESS", null, null,
|
||||||
normalized.objectName()));
|
normalized.objectName()));
|
||||||
@@ -96,6 +101,8 @@ public class ProtectedObjectService {
|
|||||||
if (existing != null) {
|
if (existing != null) {
|
||||||
if (!existing.enabled()) {
|
if (!existing.enabled()) {
|
||||||
mapper.enableObject(existing.objectId());
|
mapper.enableObject(existing.objectId());
|
||||||
|
databaseObjectsCache = null;
|
||||||
|
protectedColumnsCache.remove(existing.objectId());
|
||||||
auditService.record(new AuditEvent("PROTECTED_OBJECT_RE_ENABLED", null, existing.objectId(), "SUCCESS", null,
|
auditService.record(new AuditEvent("PROTECTED_OBJECT_RE_ENABLED", null, existing.objectId(), "SUCCESS", null,
|
||||||
null, existing.displayName()));
|
null, existing.displayName()));
|
||||||
return mapper.findById(existing.objectId());
|
return mapper.findById(existing.objectId());
|
||||||
@@ -119,6 +126,7 @@ public class ProtectedObjectService {
|
|||||||
for (String column : columns) {
|
for (String column : columns) {
|
||||||
mapper.insertColumn(mapper.nextColumnId(), objectId, column, "N");
|
mapper.insertColumn(mapper.nextColumnId(), objectId, column, "N");
|
||||||
}
|
}
|
||||||
|
databaseObjectsCache = null;
|
||||||
protectedColumnsCache.remove(objectId);
|
protectedColumnsCache.remove(objectId);
|
||||||
auditService.record(new AuditEvent("PROTECTED_OBJECT_AUTO_CREATED", null, objectId, "SUCCESS", null, null,
|
auditService.record(new AuditEvent("PROTECTED_OBJECT_AUTO_CREATED", null, objectId, "SUCCESS", null, null,
|
||||||
command.objectName()));
|
command.objectName()));
|
||||||
@@ -162,6 +170,8 @@ public class ProtectedObjectService {
|
|||||||
if (updated == 0) {
|
if (updated == 0) {
|
||||||
throw new AppException("보호 객체를 찾을 수 없습니다.");
|
throw new AppException("보호 객체를 찾을 수 없습니다.");
|
||||||
}
|
}
|
||||||
|
databaseObjectsCache = null;
|
||||||
|
protectedColumnsCache.remove(objectId);
|
||||||
auditService.record(new AuditEvent("PROTECTED_OBJECT_DISABLED", null, objectId, "SUCCESS", null, null, null));
|
auditService.record(new AuditEvent("PROTECTED_OBJECT_DISABLED", null, objectId, "SUCCESS", null, null, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public class PermissionController {
|
|||||||
@GetMapping("/permissions")
|
@GetMapping("/permissions")
|
||||||
public String permissions(Model model) {
|
public String permissions(Model model) {
|
||||||
long started = System.nanoTime();
|
long started = System.nanoTime();
|
||||||
var objects = protectedObjectService.findEnabled();
|
var objects = protectedObjectService.findEnabledWithPermissions();
|
||||||
long objectsAt = System.nanoTime();
|
long objectsAt = System.nanoTime();
|
||||||
var roles = permissionService.findRoles();
|
var roles = permissionService.findRoles();
|
||||||
long rolesAt = System.nanoTime();
|
long rolesAt = System.nanoTime();
|
||||||
|
|||||||
@@ -84,6 +84,20 @@
|
|||||||
AND o.object_id = #{objectId}
|
AND o.object_id = #{objectId}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="findObjectIdByPermissionId" resultType="long">
|
||||||
|
SELECT o.object_id
|
||||||
|
FROM cb_permission p
|
||||||
|
JOIN cb_protected_object o ON o.object_name = p.target_name
|
||||||
|
WHERE p.perm_id = #{permissionId}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="countPermissionsByObjectId" resultType="int">
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM cb_permission p
|
||||||
|
JOIN cb_protected_object o ON o.object_name = p.target_name
|
||||||
|
WHERE o.object_id = #{objectId}
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="findPermissionSet" resultType="com.cloudhandson.vpdbackoffice.domain.permission.PermissionSet">
|
<select id="findPermissionSet" resultType="com.cloudhandson.vpdbackoffice.domain.permission.PermissionSet">
|
||||||
SELECT p.perm_id AS permission_id,
|
SELECT p.perm_id AS permission_id,
|
||||||
p.role_id,
|
p.role_id,
|
||||||
|
|||||||
@@ -9,6 +9,14 @@
|
|||||||
ORDER BY owner, object_name
|
ORDER BY owner, object_name
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="findEnabledWithPermissions" resultType="com.cloudhandson.vpdbackoffice.domain.protectedobject.ProtectedObject">
|
||||||
|
SELECT DISTINCT po.object_id, po.owner, po.object_name, po.ords_path, po.enabled_yn
|
||||||
|
FROM cb_protected_object po
|
||||||
|
JOIN cb_permission p ON p.target_name = po.object_name
|
||||||
|
WHERE po.enabled_yn = 'Y'
|
||||||
|
ORDER BY po.owner, po.object_name
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="findById" resultType="com.cloudhandson.vpdbackoffice.domain.protectedobject.ProtectedObject">
|
<select id="findById" resultType="com.cloudhandson.vpdbackoffice.domain.protectedobject.ProtectedObject">
|
||||||
SELECT object_id, owner, object_name, ords_path, enabled_yn
|
SELECT object_id, owner, object_name, ords_path, enabled_yn
|
||||||
FROM cb_protected_object
|
FROM cb_protected_object
|
||||||
@@ -31,6 +39,7 @@
|
|||||||
AND NOT EXISTS (
|
AND NOT EXISTS (
|
||||||
SELECT 1
|
SELECT 1
|
||||||
FROM cb_protected_object po
|
FROM cb_protected_object po
|
||||||
|
JOIN cb_permission p ON p.target_name = po.object_name
|
||||||
WHERE po.owner = all_objects.owner
|
WHERE po.owner = all_objects.owner
|
||||||
AND po.object_name = all_objects.object_name
|
AND po.object_name = all_objects.object_name
|
||||||
AND po.enabled_yn = 'Y'
|
AND po.enabled_yn = 'Y'
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.cloudhandson.vpdbackoffice.service;
|
package com.cloudhandson.vpdbackoffice.service;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
|
|
||||||
import com.cloudhandson.vpdbackoffice.domain.audit.AuditEvent;
|
import com.cloudhandson.vpdbackoffice.domain.audit.AuditEvent;
|
||||||
@@ -74,6 +75,24 @@ class PermissionServiceTest {
|
|||||||
.hasMessageContaining("허용되지 않은");
|
.hasMessageContaining("허용되지 않은");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void disablesProtectedObjectWhenLastPermissionIsDeleted() {
|
||||||
|
var mapper = new FakePermissionMapper();
|
||||||
|
boolean[] disabled = {false};
|
||||||
|
AuditService auditService = new AuditService(new NoopAuditMapper());
|
||||||
|
ProtectedObjectService objectService = new ProtectedObjectService(null, auditService) {
|
||||||
|
@Override
|
||||||
|
public void disableObject(long objectId) {
|
||||||
|
disabled[0] = objectId == 1L;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
PermissionService service = new PermissionService(mapper, objectService, auditService);
|
||||||
|
|
||||||
|
service.deletePermission(1000L);
|
||||||
|
|
||||||
|
assertThat(disabled[0]).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
private static class NoopAuditMapper implements AuditMapper {
|
private static class NoopAuditMapper implements AuditMapper {
|
||||||
@Override
|
@Override
|
||||||
public void insert(AuditEvent event) {
|
public void insert(AuditEvent event) {
|
||||||
@@ -120,6 +139,16 @@ class PermissionServiceTest {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long findObjectIdByPermissionId(long permissionId) {
|
||||||
|
return permissionId == 1000L ? 1L : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int countPermissionsByObjectId(long objectId) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void insertPermission(long permissionId, long roleId, long objectId, String action) {
|
public void insertPermission(long permissionId, long roleId, long objectId, String action) {
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user