Skip to content

Commit 5d87a0c

Browse files
authored
Merge pull request #304 from iflytek/feat/oss-02-super-admin-visibility
feat(access): add SUPER_ADMIN platform role support
2 parents 1246cca + edcc248 commit 5d87a0c

11 files changed

Lines changed: 219 additions & 46 deletions

File tree

docs/oss-02-core-semantic-rules.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -589,13 +589,13 @@ private boolean canDownload(SkillVersion version, Skill skill, String currentUse
589589

590590
| 问题 | 严重程度 | 状态 |
591591
|------|---------|------|
592-
| 新增 UPLOADED 状态 || 待实现 |
593-
| PRIVATE skill 发布逻辑改动 || 待实现 |
594-
| 提交审核接口 || 待实现 |
595-
| 撤回审核后进入 UPLOADED || 待实现 |
596-
| 同名冲突检查补全 || 待实现 |
597-
| 管理员可见 UPLOADED skill || 待实现 |
598-
| package_name 唯一性检查 || 可选 |
592+
| 新增 UPLOADED 状态 || 已完成 |
593+
| PRIVATE skill 发布逻辑改动 || 已完成 |
594+
| 提交审核接口 || 已完成 |
595+
| 撤回审核后进入 UPLOADED || 已完成 |
596+
| 同名冲突检查补全 || 已完成 |
597+
| 管理员可见 UPLOADED skill || 已完成 |
598+
| package_name 唯一性检查 || 可选(SaaS Adapter 职责) |
599599

600600
---
601601

server/skillhub-app/src/main/java/com/iflytek/skillhub/filter/AuthContextFilter.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ protected void doFilterInternal(
7373
return;
7474
}
7575
request.setAttribute("userId", principal.userId());
76+
request.setAttribute("platformRoles", principal.platformRoles() != null ? principal.platformRoles() : java.util.Set.of());
7677
Map<Long, NamespaceRole> userNsRoles = namespaceMemberRepository.findByUserId(principal.userId()).stream()
7778
.collect(Collectors.toMap(
7879
NamespaceMember::getNamespaceId,

server/skillhub-app/src/main/resources/messages.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ error.skill.lifecycle.noPermission=Only the skill owner or namespace admin can m
104104
error.skill.version.exists=Version already exists: {0}
105105
error.skill.version.notFound=Version not found: {0}
106106
error.skill.version.notPublished=Version is not published: {0}
107-
error.skill.version.delete.unsupported=Only DRAFT or REJECTED versions can be deleted: {0}
107+
error.skill.version.delete.unsupported=Only DRAFT, UPLOADED, REJECTED, or SCAN_FAILED versions can be deleted: {0}
108108
error.skill.version.delete.lastVersion=Cannot delete the last remaining version: {0}
109109
error.skill.report.reason.required=Please provide a report reason
110110
error.skill.report.unavailable=This skill cannot be reported right now: {0}

server/skillhub-app/src/main/resources/messages_zh.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ error.skill.lifecycle.noPermission=只有技能所有者或命名空间管理员
104104
error.skill.version.exists=版本已存在:{0}
105105
error.skill.version.notFound=未找到版本:{0}
106106
error.skill.version.notPublished=版本未发布:{0}
107-
error.skill.version.delete.unsupported=只有 DRAFT 或 REJECTED 版本可以删除:{0}
107+
error.skill.version.delete.unsupported=只有 DRAFT、UPLOADED、REJECTEDSCAN_FAILED 版本可以删除:{0}
108108
error.skill.version.delete.lastVersion=无法删除最后一个版本:{0}
109109
error.skill.report.reason.required=请填写举报原因
110110
error.skill.report.unavailable=当前无法举报该技能:{0}

server/skillhub-app/src/test/java/com/iflytek/skillhub/controller/SkillControllerTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.util.TimeZone;
2323

2424
import static org.mockito.ArgumentMatchers.eq;
25+
import static org.mockito.ArgumentMatchers.anySet;
2526
import static org.mockito.Mockito.when;
2627
import static org.mockito.ArgumentMatchers.any;
2728
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;

server/skillhub-app/src/test/java/com/iflytek/skillhub/controller/portal/SkillPublishControllerTest.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
import static org.mockito.ArgumentMatchers.eq;
55
import static org.mockito.BDDMockito.given;
66
import static org.mockito.Mockito.verify;
7+
8+
import com.iflytek.skillhub.domain.skill.validation.PackageEntry;
9+
import org.mockito.ArgumentMatchers;
710
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication;
811
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
912
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart;
@@ -69,7 +72,7 @@ void publish_recordsMetricsAfterSuccess() throws Exception {
6972

7073
given(skillPublishService.publishFromEntries(
7174
eq("global"),
72-
anyList(),
75+
ArgumentMatchers.<List<PackageEntry>>any(),
7376
eq("usr_1"),
7477
eq(SkillVisibility.PUBLIC),
7578
eq(Set.of("SUPER_ADMIN")),
@@ -120,7 +123,7 @@ void publish_passesWarningConfirmationFlag() throws Exception {
120123

121124
given(skillPublishService.publishFromEntries(
122125
eq("global"),
123-
anyList(),
126+
ArgumentMatchers.<List<PackageEntry>>any(),
124127
eq("usr_1"),
125128
eq(SkillVisibility.PUBLIC),
126129
eq(Set.of("SUPER_ADMIN")),

server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/skill/VisibilityChecker.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.iflytek.skillhub.domain.namespace.NamespaceRole;
44

55
import java.util.Map;
6+
import java.util.Set;
67

78
/**
89
* Evaluates whether a caller may read a skill based on publication state, visibility, ownership,
@@ -11,6 +12,13 @@
1112
public class VisibilityChecker {
1213

1314
public boolean canAccess(Skill skill, String currentUserId, Map<Long, NamespaceRole> userNamespaceRoles) {
15+
return canAccess(skill, currentUserId, userNamespaceRoles, Set.of());
16+
}
17+
18+
public boolean canAccess(Skill skill, String currentUserId, Map<Long, NamespaceRole> userNamespaceRoles, Set<String> platformRoles) {
19+
if (isSuperAdmin(platformRoles)) {
20+
return true;
21+
}
1422
if (skill.isHidden()) {
1523
return isOwner(skill, currentUserId) || isAdminOrAbove(userNamespaceRoles.get(skill.getNamespaceId()));
1624
}
@@ -31,4 +39,8 @@ private boolean isOwner(Skill skill, String currentUserId) {
3139
private boolean isAdminOrAbove(NamespaceRole role) {
3240
return role == NamespaceRole.ADMIN || role == NamespaceRole.OWNER;
3341
}
42+
43+
private boolean isSuperAdmin(Set<String> platformRoles) {
44+
return platformRoles != null && platformRoles.contains("SUPER_ADMIN");
45+
}
3446
}

server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/skill/service/SkillQueryService.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.util.Map;
3131
import java.util.Objects;
3232
import java.util.Optional;
33+
import java.util.Set;
3334
import java.util.stream.Collectors;
3435

3536
/**
@@ -149,11 +150,14 @@ public SkillDetailDTO getSkillDetail(
149150
String skillSlug,
150151
String currentUserId,
151152
Map<Long, NamespaceRole> userNsRoles) {
152-
153153
Namespace namespace = findNamespace(namespaceSlug);
154154
Skill skill = resolveVisibleSkill(namespace.getId(), skillSlug, currentUserId);
155155

156-
// Visibility check
156+
if (namespace.getStatus() == com.iflytek.skillhub.domain.namespace.NamespaceStatus.ARCHIVED
157+
&& !isNamespaceMember(namespace.getId(), currentUserId, userNsRoles)) {
158+
throw new DomainForbiddenException("error.namespace.archived", namespaceSlug);
159+
}
160+
157161
if (!visibilityChecker.canAccess(skill, currentUserId, userNsRoles)) {
158162
throw new DomainForbiddenException("error.skill.access.denied", skillSlug);
159163
}
@@ -198,6 +202,15 @@ public SkillDetailDTO getSkillDetail(
198202
);
199203
}
200204

205+
public SkillDetailDTO getSkillDetail(
206+
String namespaceSlug,
207+
String skillSlug,
208+
String currentUserId,
209+
Map<Long, NamespaceRole> userNsRoles,
210+
Set<String> platformRoles) {
211+
return getSkillDetail(namespaceSlug, skillSlug, currentUserId, userNsRoles);
212+
}
213+
201214
/**
202215
* Lists skills within a namespace after filtering out records the caller is
203216
* not allowed to discover.

server/skillhub-domain/src/test/java/com/iflytek/skillhub/domain/skill/VisibilityCheckerTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import org.junit.jupiter.api.Test;
66

77
import java.util.Map;
8+
import java.util.Set;
89

910
import static org.junit.jupiter.api.Assertions.*;
1011

@@ -158,4 +159,34 @@ void testHiddenSkillAccessibleByNamespaceAdmin() {
158159
boolean canAccess = checker.canAccess(hiddenPublicSkill, ADMIN_USER_ID, roles);
159160
assertTrue(canAccess);
160161
}
162+
163+
@Test
164+
void testSuperAdminCanAccessPrivateSkill() {
165+
boolean canAccess = checker.canAccess(privateSkill, OTHER_USER_ID, Map.of(), Set.of("SUPER_ADMIN"));
166+
assertTrue(canAccess);
167+
}
168+
169+
@Test
170+
void testSuperAdminCanAccessHiddenSkill() {
171+
boolean canAccess = checker.canAccess(hiddenPublicSkill, OTHER_USER_ID, Map.of(), Set.of("SUPER_ADMIN"));
172+
assertTrue(canAccess);
173+
}
174+
175+
@Test
176+
void testSuperAdminCanAccessUnpublishedSkill() {
177+
boolean canAccess = checker.canAccess(unpublishedPublicSkill, OTHER_USER_ID, Map.of(), Set.of("SUPER_ADMIN"));
178+
assertTrue(canAccess);
179+
}
180+
181+
@Test
182+
void testNonSuperAdminPlatformRolesDoNotGrantAccess() {
183+
boolean canAccess = checker.canAccess(privateSkill, OTHER_USER_ID, Map.of(), Set.of("REVIEWER"));
184+
assertFalse(canAccess);
185+
}
186+
187+
@Test
188+
void testEmptyPlatformRolesDoNotGrantAccess() {
189+
boolean canAccess = checker.canAccess(privateSkill, OTHER_USER_ID, Map.of(), Set.of());
190+
assertFalse(canAccess);
191+
}
161192
}

0 commit comments

Comments
 (0)