fix(domain): reject anonymous restricted resolves cleanly

Signed-off-by: dongmucat <1127093059@qq.com>
This commit is contained in:
dongmucat 2026-06-15 17:25:35 +08:00
parent f5259daa94
commit 5a708a5bd6
2 changed files with 29 additions and 3 deletions

View file

@ -16,19 +16,20 @@ public class VisibilityChecker {
}
public boolean canAccess(Skill skill, String currentUserId, Map<Long, NamespaceRole> userNamespaceRoles, Set<String> platformRoles) {
Map<Long, NamespaceRole> roles = userNamespaceRoles != null ? userNamespaceRoles : Map.of();
if (isSuperAdmin(platformRoles)) {
return true;
}
if (skill.isHidden()) {
return isOwner(skill, currentUserId) || isAdminOrAbove(userNamespaceRoles.get(skill.getNamespaceId()));
return isOwner(skill, currentUserId) || isAdminOrAbove(roles.get(skill.getNamespaceId()));
}
if (skill.getLatestVersionId() == null) {
return isOwner(skill, currentUserId);
}
return switch (skill.getVisibility()) {
case PUBLIC -> true;
case NAMESPACE_ONLY -> userNamespaceRoles.containsKey(skill.getNamespaceId());
case PRIVATE -> isOwner(skill, currentUserId) || isAdminOrAbove(userNamespaceRoles.get(skill.getNamespaceId()));
case NAMESPACE_ONLY -> roles.containsKey(skill.getNamespaceId());
case PRIVATE -> isOwner(skill, currentUserId) || isAdminOrAbove(roles.get(skill.getNamespaceId()));
};
}

View file

@ -830,6 +830,31 @@ class SkillQueryServiceTest {
service.resolveVersion("global", "unpublished", null, null, null, null, Map.of()));
}
@Test
void testResolveVersion_ShouldRejectAnonymousPrivateAndNamespaceOnlyWhenRolesAreMissing() throws Exception {
Namespace namespace = new Namespace("global", "Global", "owner-1");
setId(namespace, 1L);
Skill privateSkill = new Skill(1L, "private", "owner-1", SkillVisibility.PRIVATE);
setId(privateSkill, 11L);
privateSkill.setStatus(SkillStatus.ACTIVE);
privateSkill.setLatestVersionId(101L);
Skill namespaceOnlySkill = new Skill(1L, "team-only", "owner-1", SkillVisibility.NAMESPACE_ONLY);
setId(namespaceOnlySkill, 12L);
namespaceOnlySkill.setStatus(SkillStatus.ACTIVE);
namespaceOnlySkill.setLatestVersionId(102L);
when(namespaceRepository.findBySlug("global")).thenReturn(Optional.of(namespace));
when(skillRepository.findByNamespaceIdAndSlug(1L, "private")).thenReturn(List.of(privateSkill));
when(skillRepository.findByNamespaceIdAndSlug(1L, "team-only")).thenReturn(List.of(namespaceOnlySkill));
assertThrows(DomainForbiddenException.class, () ->
service.resolveVersion("global", "private", null, null, null, null, null));
assertThrows(DomainForbiddenException.class, () ->
service.resolveVersion("global", "team-only", null, null, null, null, null));
}
@Test
void testGetSkillDetail_ShouldFlagLifecyclePermissionForOwner() throws Exception {
String namespaceSlug = "test-ns";