diff --git a/server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/review/ReviewPermissionChecker.java b/server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/review/ReviewPermissionChecker.java new file mode 100644 index 00000000..388ec22f --- /dev/null +++ b/server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/review/ReviewPermissionChecker.java @@ -0,0 +1,60 @@ +package com.iflytek.skillhub.domain.review; + +import com.iflytek.skillhub.domain.namespace.NamespaceRole; +import com.iflytek.skillhub.domain.namespace.NamespaceType; +import org.springframework.stereotype.Component; + +import java.util.Map; +import java.util.Set; + +@Component +public class ReviewPermissionChecker { + + /** + * Check if a user can review a ReviewTask. + * + * @param task the review task + * @param userId the reviewer's user ID + * @param namespaceType the type of the namespace + * @param userNamespaceRoles user's roles keyed by namespace ID + * @param platformRoles user's platform-level roles + * @return true if the user is allowed to review + */ + public boolean canReview(ReviewTask task, + Long userId, + NamespaceType namespaceType, + Map userNamespaceRoles, + Set platformRoles) { + // Cannot review own submission + if (task.getSubmittedBy().equals(userId)) { + return false; + } + + // Global namespace: only SKILL_ADMIN or SUPER_ADMIN + if (namespaceType == NamespaceType.GLOBAL) { + return platformRoles.contains("SKILL_ADMIN") + || platformRoles.contains("SUPER_ADMIN"); + } + + // Team namespace: namespace ADMIN or OWNER + NamespaceRole role = userNamespaceRoles.get( + task.getNamespaceId()); + return role == NamespaceRole.ADMIN + || role == NamespaceRole.OWNER; + } + + /** + * Check if a user can review a PromotionRequest. + * Only SKILL_ADMIN or SUPER_ADMIN, and not own. + */ + public boolean canReviewPromotion( + PromotionRequest request, + Long userId, + Set platformRoles) { + if (request.getSubmittedBy().equals(userId)) { + return false; + } + return platformRoles.contains("SKILL_ADMIN") + || platformRoles.contains("SUPER_ADMIN"); + } +} diff --git a/server/skillhub-domain/src/test/java/com/iflytek/skillhub/domain/review/ReviewPermissionCheckerTest.java b/server/skillhub-domain/src/test/java/com/iflytek/skillhub/domain/review/ReviewPermissionCheckerTest.java new file mode 100644 index 00000000..6ca7ec06 --- /dev/null +++ b/server/skillhub-domain/src/test/java/com/iflytek/skillhub/domain/review/ReviewPermissionCheckerTest.java @@ -0,0 +1,112 @@ +package com.iflytek.skillhub.domain.review; + +import com.iflytek.skillhub.domain.namespace.NamespaceRole; +import com.iflytek.skillhub.domain.namespace.NamespaceType; +import org.junit.jupiter.api.Test; + +import java.util.Map; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.*; + +class ReviewPermissionCheckerTest { + + private final ReviewPermissionChecker checker = new ReviewPermissionChecker(); + + // --- canReview tests --- + + @Test + void cannotReviewOwnSubmission() { + Long userId = 1L; + ReviewTask task = new ReviewTask(1L, 10L, userId); + assertFalse(checker.canReview(task, userId, + NamespaceType.TEAM, Map.of(), Set.of())); + } + + @Test + void teamAdminCanReviewTeamSkill() { + ReviewTask task = new ReviewTask(1L, 10L, 2L); + assertTrue(checker.canReview(task, 1L, + NamespaceType.TEAM, + Map.of(10L, NamespaceRole.ADMIN), Set.of())); + } + + @Test + void teamOwnerCanReviewTeamSkill() { + ReviewTask task = new ReviewTask(1L, 10L, 2L); + assertTrue(checker.canReview(task, 1L, + NamespaceType.TEAM, + Map.of(10L, NamespaceRole.OWNER), Set.of())); + } + + @Test + void teamMemberCannotReviewTeamSkill() { + ReviewTask task = new ReviewTask(1L, 10L, 2L); + assertFalse(checker.canReview(task, 1L, + NamespaceType.TEAM, + Map.of(10L, NamespaceRole.MEMBER), Set.of())); + } + + @Test + void skillAdminCanReviewGlobalSkill() { + ReviewTask task = new ReviewTask(1L, 1L, 2L); + assertTrue(checker.canReview(task, 1L, + NamespaceType.GLOBAL, + Map.of(), Set.of("SKILL_ADMIN"))); + } + + @Test + void superAdminCanReviewGlobalSkill() { + ReviewTask task = new ReviewTask(1L, 1L, 2L); + assertTrue(checker.canReview(task, 1L, + NamespaceType.GLOBAL, + Map.of(), Set.of("SUPER_ADMIN"))); + } + + @Test + void skillAdminCannotReviewTeamSkill() { + ReviewTask task = new ReviewTask(1L, 10L, 2L); + assertFalse(checker.canReview(task, 1L, + NamespaceType.TEAM, + Map.of(), Set.of("SKILL_ADMIN"))); + } + + @Test + void nonAdminCannotReviewGlobalSkill() { + ReviewTask task = new ReviewTask(1L, 1L, 2L); + assertFalse(checker.canReview(task, 1L, + NamespaceType.GLOBAL, + Map.of(), Set.of())); + } + + // --- canReviewPromotion tests --- + + @Test + void skillAdminCanReviewPromotion() { + PromotionRequest req = new PromotionRequest(1L, 1L, 1L, 2L); + assertTrue(checker.canReviewPromotion(req, 1L, + Set.of("SKILL_ADMIN"))); + } + + @Test + void superAdminCanReviewPromotion() { + PromotionRequest req = new PromotionRequest(1L, 1L, 1L, 2L); + assertTrue(checker.canReviewPromotion(req, 1L, + Set.of("SUPER_ADMIN"))); + } + + @Test + void regularUserCannotReviewPromotion() { + PromotionRequest req = new PromotionRequest(1L, 1L, 1L, 2L); + assertFalse(checker.canReviewPromotion(req, 1L, + Set.of())); + } + + @Test + void cannotReviewOwnPromotion() { + Long userId = 2L; + PromotionRequest req = new PromotionRequest(1L, 1L, 1L, userId); + assertFalse(checker.canReviewPromotion(req, userId, + Set.of("SKILL_ADMIN"))); + } +}