mirror of
https://github.com/iflytek/skillhub.git
synced 2026-10-11 03:37:57 +00:00
test(auth): cover competing initial grants and smoke endpoints
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
This commit is contained in:
parent
5120f4f046
commit
e8de0059ef
3 changed files with 65 additions and 6 deletions
|
|
@ -9,7 +9,7 @@
|
|||
- [x] 在本地登录、direct 本地认证、注册和密码管理服务端入口执行对应开关;关闭密码登录时一并阻止会直接建会话的本地注册。
|
||||
- [x] 在 OAuth 普通准入允许后的首次 ACTIVE 账号创建事务中匹配并消费角色规则,首次主体包含新角色。
|
||||
- [x] 在统一身份核心的 `LEGACY`、`SHADOW`、`ACTIVE` 模式下核对公开 OAuth 接入点;保持旧身份绑定写入权威与同邮箱不自动合并的现有行为(`OAuthLoginFlowServiceTest`、`IdentityBindingServiceTest`)。
|
||||
- [x] 保持已有账号、准入拒绝、未验证邮箱、停用规则、并发首次登录和人工角色修改的既定行为(OAuth 和授权单测、PostgreSQL 并发首次登录与人工撤权测试)。
|
||||
- [x] 保持已有账号、准入拒绝、未验证邮箱、停用规则、并发首次登录和人工角色修改的既定行为(OAuth 和授权单测、PostgreSQL 同身份及同邮箱不同身份并发测试与人工撤权测试)。
|
||||
|
||||
## 3. API 与 Web
|
||||
|
||||
|
|
@ -22,4 +22,4 @@
|
|||
|
||||
- [x] 验证两个开关的四种组合、直接 API 绕过尝试、已有会话、DB 故障与多实例设置可见性(本地 Compose HTTP 实测;DB 故障与两个服务实例读取使用 `LocalAuthSettingsServiceTest`)。
|
||||
- [x] 验证首次登录授权、准入优先、已有账号不补授权、同邮箱独立账号、邮箱验证、规则停用、角色人工修改和并发首次登录(OAuth/授权单测与 PostgreSQL 真实事务测试;本地 Compose 未接入真实外部 IdP)。
|
||||
- [x] 验证一次性部署初始化、角色规则删除后重启、非超管越权、审计记录和浏览器页面流程(初始化单测、Compose 权限与审计实测、Playwright 浏览器操作)。
|
||||
- [x] 验证一次性部署初始化、角色规则删除后重启、非超管越权、审计记录和浏览器页面流程(初始化单测、Compose 权限与审计实测、Playwright 浏览器操作;常驻 smoke 覆盖公开能力与后台配置读取)。
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ check_health "Health endpoint" "$ACTUATOR_BASE_URL/actuator/health"
|
|||
check_protected_actuator "Prometheus metrics requires auth" "$ACTUATOR_BASE_URL/actuator/prometheus"
|
||||
check "Namespaces API requires auth" "$BASE_URL/api/v1/namespaces" "401"
|
||||
check "Auth required" "$BASE_URL/api/v1/auth/me" "401"
|
||||
check "Local auth capabilities" "$BASE_URL/api/v1/auth/local/capabilities" "200"
|
||||
|
||||
curl -s -c "$COOKIE_JAR" "$BASE_URL/api/v1/auth/me" >/dev/null
|
||||
CSRF_TOKEN="$(awk '$6 == "XSRF-TOKEN" { print $7 }' "$COOKIE_JAR" | tail -n 1)"
|
||||
|
|
@ -227,6 +228,26 @@ fi
|
|||
# Refresh CSRF after login
|
||||
ADMIN_CSRF="$(awk '$6 == "XSRF-TOKEN" { print $7 }' "$ADMIN_COOKIE_JAR" | tail -n 1)"
|
||||
|
||||
SYSTEM_CONFIG_STATUS="$(curl --max-time 10 -s -o /dev/null -w "%{http_code}" \
|
||||
-b "$ADMIN_COOKIE_JAR" "$BASE_URL/api/v1/admin/system-config/auth/local" || true)"
|
||||
if [[ "$SYSTEM_CONFIG_STATUS" == "200" ]]; then
|
||||
echo "PASS: Read system auth settings (HTTP $SYSTEM_CONFIG_STATUS)"
|
||||
PASS=$((PASS + 1))
|
||||
else
|
||||
echo "FAIL: Read system auth settings (got $SYSTEM_CONFIG_STATUS)"
|
||||
FAIL=$((FAIL + 1))
|
||||
fi
|
||||
|
||||
ROLE_GRANTS_STATUS="$(curl --max-time 10 -s -o /dev/null -w "%{http_code}" \
|
||||
-b "$ADMIN_COOKIE_JAR" "$BASE_URL/api/v1/admin/system-config/role-grants" || true)"
|
||||
if [[ "$ROLE_GRANTS_STATUS" == "200" ]]; then
|
||||
echo "PASS: Read initial role grant rules (HTTP $ROLE_GRANTS_STATUS)"
|
||||
PASS=$((PASS + 1))
|
||||
else
|
||||
echo "FAIL: Read initial role grant rules (got $ROLE_GRANTS_STATUS)"
|
||||
FAIL=$((FAIL + 1))
|
||||
fi
|
||||
|
||||
# Create label definition
|
||||
CREATE_LABEL_STATUS="$(curl --max-time 10 -s -o /dev/null -w "%{http_code}" \
|
||||
-X POST "$BASE_URL/api/v1/admin/labels" \
|
||||
|
|
|
|||
|
|
@ -123,10 +123,7 @@ class SystemAuthSettingsPostgresTest {
|
|||
TransactionTemplate transactions = new TransactionTemplate(transactionManager);
|
||||
Long ruleId = transactions.execute(status -> rules.save(new ExternalRoleGrantRule(
|
||||
"github", email, roles.findByCode("SUPER_ADMIN").orElseThrow(), "admin")).getId());
|
||||
IdentityBindingService bindingService = new IdentityBindingService(
|
||||
identities, users, userRoles, mock(GlobalNamespaceMembershipService.class),
|
||||
mock(ApplicationEventPublisher.class), transactionManager,
|
||||
new InitialExternalRoleGrantService(rules, userRoles, mock(AuditLogService.class)));
|
||||
IdentityBindingService bindingService = bindingService();
|
||||
OAuthClaims claims = new OAuthClaims("github", subject, email, true, "admin", Map.of());
|
||||
CountDownLatch ready = new CountDownLatch(2);
|
||||
CountDownLatch start = new CountDownLatch(1);
|
||||
|
|
@ -165,6 +162,47 @@ class SystemAuthSettingsPostgresTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional(propagation = Propagation.NOT_SUPPORTED)
|
||||
void concurrentDifferentSubjectsSharingEmailCannotBothConsumeRule() throws Exception {
|
||||
String suffix = UUID.randomUUID().toString();
|
||||
String email = suffix + "@example.com";
|
||||
TransactionTemplate transactions = new TransactionTemplate(transactionManager);
|
||||
Long ruleId = transactions.execute(status -> rules.save(new ExternalRoleGrantRule(
|
||||
"github", email, roles.findByCode("SUPER_ADMIN").orElseThrow(), "admin")).getId());
|
||||
IdentityBindingService bindingService = bindingService();
|
||||
OAuthClaims firstClaims = new OAuthClaims("github", "first-" + suffix, email, true, "first", Map.of());
|
||||
OAuthClaims secondClaims = new OAuthClaims("github", "second-" + suffix, email, true, "second", Map.of());
|
||||
CountDownLatch ready = new CountDownLatch(2);
|
||||
CountDownLatch start = new CountDownLatch(1);
|
||||
|
||||
try (var executor = Executors.newFixedThreadPool(2)) {
|
||||
var first = executor.submit(() -> firstLogin(bindingService, firstClaims, ready, start));
|
||||
var second = executor.submit(() -> firstLogin(bindingService, secondClaims, ready, start));
|
||||
assertThat(ready.await(10, TimeUnit.SECONDS)).isTrue();
|
||||
start.countDown();
|
||||
PlatformPrincipal firstPrincipal = first.get(20, TimeUnit.SECONDS);
|
||||
PlatformPrincipal secondPrincipal = second.get(20, TimeUnit.SECONDS);
|
||||
|
||||
assertThat(firstPrincipal.userId()).isNotEqualTo(secondPrincipal.userId());
|
||||
assertThat(firstPrincipal.platformRoles().contains("SUPER_ADMIN"))
|
||||
.isNotEqualTo(secondPrincipal.platformRoles().contains("SUPER_ADMIN"));
|
||||
ExternalRoleGrantRule consumed = rules.findById(ruleId).orElseThrow();
|
||||
assertThat(consumed.getStatus()).isEqualTo(ExternalRoleGrantRule.Status.CONSUMED);
|
||||
assertThat(consumed.getGrantedUserId()).isIn(firstPrincipal.userId(), secondPrincipal.userId());
|
||||
assertThat(consumed.getMatchedSubject()).isIn(firstClaims.subject(), secondClaims.subject());
|
||||
assertThat(userRoles.findByUserId(firstPrincipal.userId()).size()
|
||||
+ userRoles.findByUserId(secondPrincipal.userId()).size()).isEqualTo(1);
|
||||
}
|
||||
}
|
||||
|
||||
private IdentityBindingService bindingService() {
|
||||
return new IdentityBindingService(identities, users, userRoles,
|
||||
mock(GlobalNamespaceMembershipService.class), mock(ApplicationEventPublisher.class),
|
||||
transactionManager, new InitialExternalRoleGrantService(
|
||||
rules, userRoles, mock(AuditLogService.class)));
|
||||
}
|
||||
|
||||
private static PlatformPrincipal firstLogin(IdentityBindingService service, OAuthClaims claims,
|
||||
CountDownLatch ready, CountDownLatch start) throws Exception {
|
||||
ready.countDown();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue