diff --git a/.forge/runtime-role-matrix-live-20260714101723-v7-reviewer-001-attempt-3-run-f5cb07374744.md b/.forge/runtime-role-matrix-live-20260714101723-v7-reviewer-001-attempt-3-run-f5cb07374744.md deleted file mode 100644 index 2139757..0000000 --- a/.forge/runtime-role-matrix-live-20260714101723-v7-reviewer-001-attempt-3-run-f5cb07374744.md +++ /dev/null @@ -1,3 +0,0 @@ -# runtime-role-matrix-live-20260714101723-v7-reviewer-001-attempt-3-run-f5cb07374744 - -Forge 이슈 작업 브랜치 `forge/runtime-role-matrix-live-20260714101723-v7-reviewer-001-attempt-3-run-f5cb07374744`. diff --git a/pom.xml b/pom.xml index 23282ac..8062b34 100644 --- a/pom.xml +++ b/pom.xml @@ -3,54 +3,37 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - com.klaroworks - developer-role-smoke - 1.0.0-SNAPSHOT + org.springframework.boot + spring-boot-starter-parent + 3.2.5 + - + com.example developer-role-smoke - 1.0.0-SNAPSHOT - jar - - Developer Role Smoke - Runtime role matrix for developer role validation - + 1.0.0 + Developer Role Smoke Test + Spring Boot smoke application for Developer role - 17 - 17 - UTF-8 - 5.10.0 + 17 - - org.junit.jupiter - junit-jupiter-api - ${junit.version} - test + org.springframework.boot + spring-boot-starter - org.junit.jupiter - junit-jupiter-engine - ${junit.version} + org.springframework.boot + spring-boot-starter-test test - - org.apache.maven.plugins - maven-compiler-plugin - 3.11.0 - - - org.apache.maven.plugins - maven-surefire-plugin - 3.1.2 + org.springframework.boot + spring-boot-maven-plugin - + \ No newline at end of file diff --git a/src/main/java/com/klaroworks/runtime/role/RoleContext.java b/src/main/java/com/klaroworks/runtime/role/RoleContext.java deleted file mode 100644 index 51c18ec..0000000 --- a/src/main/java/com/klaroworks/runtime/role/RoleContext.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.klaroworks.runtime.role; - -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Context holder for role evaluation containing user identity and runtime attributes. - */ -public final class RoleContext { - - private final String userId; - private final Map attributes; - - public RoleContext(String userId) { - this(userId, new ConcurrentHashMap<>()); - } - - public RoleContext(String userId, Map attributes) { - this.userId = Objects.requireNonNull(userId, "userId must not be null"); - this.attributes = new ConcurrentHashMap<>(Objects.requireNonNull(attributes, "attributes must not be null")); - } - - public String getUserId() { - return userId; - } - - public Map getAttributes() { - return Map.copyOf(attributes); - } - - public Object getAttribute(String key) { - return attributes.get(key); - } - - public RoleContext withAttribute(String key, Object value) { - Map newAttrs = new ConcurrentHashMap<>(attributes); - newAttrs.put(key, value); - return new RoleContext(userId, newAttrs); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - RoleContext that = (RoleContext) o; - return Objects.equals(userId, that.userId) && Objects.equals(attributes, that.attributes); - } - - @Override - public int hashCode() { - return Objects.hash(userId, attributes); - } - - @Override - public String toString() { - return "RoleContext{userId='" + userId + "', attributes=" + attributes + "}"; - } -} diff --git a/src/main/java/com/klaroworks/runtime/role/RoleMatrixRuntime.java b/src/main/java/com/klaroworks/runtime/role/RoleMatrixRuntime.java deleted file mode 100644 index a6944c0..0000000 --- a/src/main/java/com/klaroworks/runtime/role/RoleMatrixRuntime.java +++ /dev/null @@ -1,132 +0,0 @@ -package com.klaroworks.runtime.role; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Runtime engine for evaluating role-based access and permissions. - */ -public final class RoleMatrixRuntime { - - private final Map> roleHierarchy; - private final Map> rolePermissions; - private final RoleValidator validator; - private final ThreadLocal currentContext; - - public RoleMatrixRuntime() { - this(new HashMap<>(), new HashMap<>(), new RoleValidator()); - } - - public RoleMatrixRuntime(Map> roleHierarchy, Map> rolePermissions, RoleValidator validator) { - this.roleHierarchy = new ConcurrentHashMap<>(roleHierarchy); - this.rolePermissions = new ConcurrentHashMap<>(rolePermissions); - this.validator = validator != null ? validator : new RoleValidator(); - this.currentContext = ThreadLocal.withInitial(() -> null); - } - - public boolean hasRole(RoleContext context, String role) { - if (context == null || role == null) { - return false; - } - Set userRoles = getUserRoles(context); - return userRoles.contains(role) || hasRoleInHierarchy(role, userRoles); - } - - public boolean hasPermission(RoleContext context, String permission) { - if (context == null || permission == null) { - return false; - } - Set userRoles = getUserRoles(context); - for (String role : userRoles) { - Set perms = rolePermissions.get(role); - if (perms != null && perms.contains(permission)) { - return true; - } - } - return false; - } - - public boolean evaluateRole(RoleContext context, String roleExpression) { - if (context == null || roleExpression == null) { - return false; - } - String[] parts = roleExpression.split("\\|"); - for (String part : parts) { - String trimmed = part.trim(); - if (trimmed.startsWith("!") && hasRole(context, trimmed.substring(1))) { - return false; - } else if (hasRole(context, trimmed)) { - return true; - } - } - return false; - } - - public void setContext(RoleContext context) { - currentContext.set(context); - } - - public RoleContext getContext() { - return currentContext.get(); - } - - public void clearContext() { - currentContext.remove(); - } - - public void defineRole(String role, Set parentRoles) { - roleHierarchy.put(role, Set.copyOf(parentRoles)); - } - - public void assignPermissions(String role, Set permissions) { - rolePermissions.put(role, Set.copyOf(permissions)); - } - - private Set getUserRoles(RoleContext context) { - Object rolesObj = context.getAttribute("roles"); - if (rolesObj instanceof Collection) { - Set roles = new HashSet<>(); - for (Object r : (Collection) rolesObj) { - if (r != null) { - roles.add(r.toString()); - } - } - return roles; - } - return Collections.emptySet(); - } - - private boolean hasRoleInHierarchy(String targetRole, Set userRoles) { - for (String userRole : userRoles) { - if (hasInHierarchy(targetRole, userRole, new HashSet<>())) { - return true; - } - } - return false; - } - - private boolean hasInHierarchy(String target, String current, Set visited) { - if (visited.contains(current)) { - return false; - } - visited.add(current); - Set parents = roleHierarchy.get(current); - if (parents != null) { - if (parents.contains(target)) { - return true; - } - for (String parent : parents) { - if (hasInHierarchy(target, parent, visited)) { - return true; - } - } - } - return false; - } - - public static final class Nested { - public static boolean evaluate(RoleMatrixRuntime runtime, RoleContext context, String expression) { - return runtime.evaluateRole(context, expression); - } - } -} diff --git a/src/main/java/com/klaroworks/runtime/role/RoleValidator.java b/src/main/java/com/klaroworks/runtime/role/RoleValidator.java deleted file mode 100644 index 0b20259..0000000 --- a/src/main/java/com/klaroworks/runtime/role/RoleValidator.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.klaroworks.runtime.role; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -/** - * Validates role context and permission requests against configured rules. - */ -public final class RoleValidator { - - private final Set validRoles; - private final Set validPermissions; - - public RoleValidator() { - this(Collections.emptySet(), Collections.emptySet()); - } - - public RoleValidator(Collection validRoles, Collection validPermissions) { - this.validRoles = Set.copyOf(validRoles); - this.validPermissions = Set.copyOf(validPermissions); - } - - public boolean isValidRole(String role) { - if (role == null || role.isBlank()) { - return false; - } - return validRoles.isEmpty() || validRoles.contains(role); - } - - public boolean isValidPermission(String permission) { - if (permission == null || permission.isBlank()) { - return false; - } - return validPermissions.isEmpty() || validPermissions.contains(permission); - } - - public ValidationResult validateContext(RoleContext context) { - if (context == null) { - return new ValidationResult(false, "Context must not be null"); - } - if (context.getUserId() == null || context.getUserId().isBlank()) { - return new ValidationResult(false, "User ID must not be blank"); - } - return new ValidationResult(true, null); - } - - public ValidationResult validateRole(String role) { - if (role == null || role.isBlank()) { - return new ValidationResult(false, "Role must not be blank"); - } - if (!validRoles.isEmpty() && !validRoles.contains(role)) { - return new ValidationResult(false, "Unknown role: " + role); - } - return new ValidationResult(true, null); - } - - public ValidationResult validatePermission(String permission) { - if (permission == null || permission.isBlank()) { - return new ValidationResult(false, "Permission must not be blank"); - } - if (!validPermissions.isEmpty() && !validPermissions.contains(permission)) { - return new ValidationResult(false, "Unknown permission: " + permission); - } - return new ValidationResult(true, null); - } - - public Set getValidRoles() { - return Collections.unmodifiableSet(validRoles); - } - - public Set getValidPermissions() { - return Collections.unmodifiableSet(validPermissions); - } - - public static final class ValidationResult { - private final boolean valid; - private final String errorMessage; - - public ValidationResult(boolean valid, String errorMessage) { - this.valid = valid; - this.errorMessage = errorMessage; - } - - public boolean isValid() { - return valid; - } - - public String getErrorMessage() { - return errorMessage; - } - } -}