Files
danyang-match/tests/invariants/PermissionMatrixTest.java
T

335 lines
15 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.danyang.match.platform.invariants;
import com.danyang.match.platform.shared.constant.Constants;
import org.junit.jupiter.api.*;
import java.util.*;
import static org.junit.jupiter.api.Assertions.*;
/**
* 必须永久存在的权限测试矩阵
* 每次CI都运行 — 保护9角色×8模块权限边界
*/
class PermissionMatrixTest {
// 角色权限矩阵定义
// Row = Role, Column = Permission Module
private static final Map<String, Map<String, Boolean>> PERMISSION_MATRIX = new LinkedHashMap<>();
static {
// super_admin: 全部权限
Map<String, Boolean> superAdmin = new HashMap<>();
superAdmin.put("user.view", true);
superAdmin.put("user.sensitive.view", true);
superAdmin.put("user.status.change", true);
superAdmin.put("review.view", true);
superAdmin.put("review.process", true);
superAdmin.put("matchmaker.view", true);
superAdmin.put("matchmaker.assign", true);
superAdmin.put("matchmaker.service", true);
superAdmin.put("activity.view", true);
superAdmin.put("activity.create", true);
superAdmin.put("activity.review_registration", true);
superAdmin.put("risk.report.view", true);
superAdmin.put("risk.report.process", true);
superAdmin.put("risk.user.ban", true);
superAdmin.put("organization.manage", true);
superAdmin.put("permission.manage", true);
superAdmin.put("analytics.view", true);
superAdmin.put("data.export", true);
PERMISSION_MATRIX.put("super_admin", superAdmin);
// platform_admin: 大部分权限,无permission.manage
Map<String, Boolean> platformAdmin = new HashMap<>();
platformAdmin.put("user.view", true);
platformAdmin.put("user.sensitive.view", true);
platformAdmin.put("user.status.change", true);
platformAdmin.put("review.view", true);
platformAdmin.put("review.process", true);
platformAdmin.put("matchmaker.view", true);
platformAdmin.put("matchmaker.assign", true);
platformAdmin.put("matchmaker.service", true);
platformAdmin.put("activity.view", true);
platformAdmin.put("activity.create", true);
platformAdmin.put("activity.review_registration", true);
platformAdmin.put("risk.report.view", true);
platformAdmin.put("risk.report.process", true);
platformAdmin.put("risk.user.ban", true);
platformAdmin.put("organization.manage", true);
platformAdmin.put("permission.manage", false); // 不能管理权限
platformAdmin.put("analytics.view", true);
platformAdmin.put("data.export", true);
PERMISSION_MATRIX.put("platform_admin", platformAdmin);
// organization_admin: 本机构范围内
Map<String, Boolean> orgAdmin = new HashMap<>();
orgAdmin.put("user.view", true); // 本机构用户
orgAdmin.put("user.sensitive.view", false);
orgAdmin.put("user.status.change", false);
orgAdmin.put("review.view", true);
orgAdmin.put("review.process", true);
orgAdmin.put("matchmaker.view", true);
orgAdmin.put("matchmaker.assign", false);
orgAdmin.put("matchmaker.service", true);
orgAdmin.put("activity.view", true);
orgAdmin.put("activity.create", true);
orgAdmin.put("activity.review_registration", true);
orgAdmin.put("risk.report.view", false);
orgAdmin.put("risk.report.process", false);
orgAdmin.put("risk.user.ban", false);
orgAdmin.put("organization.manage", true);
orgAdmin.put("permission.manage", false);
orgAdmin.put("analytics.view", true);
orgAdmin.put("data.export", false);
PERMISSION_MATRIX.put("organization_admin", orgAdmin);
// reviewer: 仅审核
Map<String, Boolean> reviewer = new HashMap<>();
reviewer.put("user.view", false);
reviewer.put("user.sensitive.view", false);
reviewer.put("user.status.change", false);
reviewer.put("review.view", true);
reviewer.put("review.process", true);
reviewer.put("matchmaker.view", false);
reviewer.put("matchmaker.assign", false);
reviewer.put("matchmaker.service", false);
reviewer.put("activity.view", false);
reviewer.put("activity.create", false);
reviewer.put("activity.review_registration", false);
reviewer.put("risk.report.view", false);
reviewer.put("risk.report.process", false);
reviewer.put("risk.user.ban", false);
reviewer.put("organization.manage", false);
reviewer.put("permission.manage", false);
reviewer.put("analytics.view", false);
reviewer.put("data.export", false);
PERMISSION_MATRIX.put("reviewer", reviewer);
// matchmaker: 红娘服务
Map<String, Boolean> matchmaker = new HashMap<>();
matchmaker.put("user.view", true); // 服务必要
matchmaker.put("user.sensitive.view", false);
matchmaker.put("user.status.change", false);
matchmaker.put("review.view", false);
matchmaker.put("review.process", false);
matchmaker.put("matchmaker.view", true);
matchmaker.put("matchmaker.assign", false);
matchmaker.put("matchmaker.service", true);
matchmaker.put("activity.view", false);
matchmaker.put("activity.create", false);
matchmaker.put("activity.review_registration", false);
matchmaker.put("risk.report.view", false);
matchmaker.put("risk.report.process", false);
matchmaker.put("risk.user.ban", false);
matchmaker.put("organization.manage", false);
matchmaker.put("permission.manage", false);
matchmaker.put("analytics.view", false);
matchmaker.put("data.export", false);
PERMISSION_MATRIX.put("matchmaker", matchmaker);
// activity_manager: 活动管理
Map<String, Boolean> activityManager = new HashMap<>();
activityManager.put("user.view", true); // 活动必要
activityManager.put("user.sensitive.view", false);
activityManager.put("user.status.change", false);
activityManager.put("review.view", false);
activityManager.put("review.process", false);
activityManager.put("matchmaker.view", false);
activityManager.put("matchmaker.assign", false);
activityManager.put("matchmaker.service", false);
activityManager.put("activity.view", true);
activityManager.put("activity.create", true);
activityManager.put("activity.review_registration", true);
activityManager.put("risk.report.view", false);
activityManager.put("risk.report.process", false);
activityManager.put("risk.user.ban", false);
activityManager.put("organization.manage", false);
activityManager.put("permission.manage", false);
activityManager.put("analytics.view", false);
activityManager.put("data.export", false);
PERMISSION_MATRIX.put("activity_manager", activityManager);
// risk_operator: 风控
Map<String, Boolean> riskOperator = new HashMap<>();
riskOperator.put("user.view", true); // 案件必要
riskOperator.put("user.sensitive.view", true); // 特殊
riskOperator.put("user.status.change", false);
riskOperator.put("review.view", false);
riskOperator.put("review.process", false);
riskOperator.put("matchmaker.view", false);
riskOperator.put("matchmaker.assign", false);
riskOperator.put("matchmaker.service", false);
riskOperator.put("activity.view", false);
riskOperator.put("activity.create", false);
riskOperator.put("activity.review_registration", false);
riskOperator.put("risk.report.view", true);
riskOperator.put("risk.report.process", true);
riskOperator.put("risk.user.ban", true);
riskOperator.put("organization.manage", false);
riskOperator.put("permission.manage", false);
riskOperator.put("analytics.view", false);
riskOperator.put("data.export", false);
PERMISSION_MATRIX.put("risk_operator", riskOperator);
// volunteer: 最小权限
Map<String, Boolean> volunteer = new HashMap<>();
volunteer.put("user.view", false);
volunteer.put("user.sensitive.view", false);
volunteer.put("user.status.change", false);
volunteer.put("review.view", false);
volunteer.put("review.process", false);
volunteer.put("matchmaker.view", false);
volunteer.put("matchmaker.assign", false);
volunteer.put("matchmaker.service", false);
volunteer.put("activity.view", true); // 签到必要
volunteer.put("activity.create", false);
volunteer.put("activity.review_registration", false);
volunteer.put("risk.report.view", false);
volunteer.put("risk.report.process", false);
volunteer.put("risk.user.ban", false);
volunteer.put("organization.manage", false);
volunteer.put("permission.manage", false);
volunteer.put("analytics.view", false);
volunteer.put("data.export", false);
PERMISSION_MATRIX.put("volunteer", volunteer);
// data_viewer: 仅查看统计
Map<String, Boolean> dataViewer = new HashMap<>();
dataViewer.put("user.view", false);
dataViewer.put("user.sensitive.view", false);
dataViewer.put("user.status.change", false);
dataViewer.put("review.view", false);
dataViewer.put("review.process", false);
dataViewer.put("matchmaker.view", false);
dataViewer.put("matchmaker.assign", false);
dataViewer.put("matchmaker.service", false);
dataViewer.put("activity.view", false);
dataViewer.put("activity.create", false);
dataViewer.put("activity.review_registration", false);
dataViewer.put("risk.report.view", false);
dataViewer.put("risk.report.process", false);
dataViewer.put("risk.user.ban", false);
dataViewer.put("organization.manage", false);
dataViewer.put("permission.manage", false);
dataViewer.put("analytics.view", true);
dataViewer.put("data.export", false);
PERMISSION_MATRIX.put("data_viewer", dataViewer);
}
// ==================== 权限矩阵测试 ====================
@Test
void testSuperAdminHasMostPermissions() {
long count = PERMISSION_MATRIX.get("super_admin").values().stream()
.filter(Boolean::booleanValue).count();
assertTrue(count >= 15, "super_admin应有至少15项权限,实际" + count);
}
@Test
void testVolunteerHasMinimalPermissions() {
long count = PERMISSION_MATRIX.get("volunteer").values().stream()
.filter(Boolean::booleanValue).count();
assertEquals(1, count, "志愿者应仅有1项权限(activity.view)");
}
@Test
void testDataViewerCannotAccessUserData() {
assertFalse(PERMISSION_MATRIX.get("data_viewer").get("user.view"),
"data_viewer不应有user.view权限");
assertFalse(PERMISSION_MATRIX.get("data_viewer").get("user.sensitive.view"),
"data_viewer不应有user.sensitive.view权限");
}
@Test
void testReviewerCanOnlyReview() {
long reviewCount = 0;
for (Map.Entry<String, Boolean> e : PERMISSION_MATRIX.get("reviewer").entrySet()) {
if (e.getValue()) reviewCount++;
}
assertEquals(2, reviewCount, "审核员应有且仅有review.view + review.process两项权限");
}
@Test
void testRiskOperatorCannotManageOrganization() {
assertFalse(PERMISSION_MATRIX.get("risk_operator").get("organization.manage"),
"风控员不应有组织管理权限");
}
@Test
void testMatchmakerCannotBanUsers() {
assertFalse(PERMISSION_MATRIX.get("matchmaker").get("risk.user.ban"),
"红娘不应有封禁用户权限");
}
@Test
void testActivityManagerCannotProcessReports() {
assertFalse(PERMISSION_MATRIX.get("activity_manager").get("risk.report.process"),
"活动管理员不应有举报处理权限");
}
@Test
void testNoRoleHasAllPermissions() {
// 除super_admin外,没有任何角色拥有全部权限
for (Map.Entry<String, Map<String, Boolean>> entry : PERMISSION_MATRIX.entrySet()) {
if ("super_admin".equals(entry.getKey())) continue;
long denied = entry.getValue().values().stream()
.filter(v -> !v).count();
assertTrue(denied >= 5,
entry.getKey() + " 应有至少5个被拒绝的权限");
}
}
@Test
void testSuperAdminCanDoEverything() {
Map<String, Boolean> perms = PERMISSION_MATRIX.get("super_admin");
long granted = perms.values().stream().filter(Boolean::booleanValue).count();
assertEquals(perms.size(), granted, "super_admin应有全部权限");
}
@Test
void testOrganizationAdminCannotManagePermissions() {
assertFalse(PERMISSION_MATRIX.get("organization_admin").get("permission.manage"),
"机构管理员不应有权限管理权限");
}
@Test
void testAllRolesHaveUniquePermissionSets() {
// 每个角色的权限集合应该不同(不能完全相同)
Set<String> roleNames = PERMISSION_MATRIX.keySet();
for (int i = 0; i < roleNames.size(); i++) {
for (int j = i + 1; j < roleNames.size(); j++) {
String r1 = new ArrayList<>(roleNames).get(i);
String r2 = new ArrayList<>(roleNames).get(j);
// 两个不同角色的权限不完全相同
boolean different = false;
for (String perm : PERMISSION_MATRIX.get(r1).keySet()) {
if (!PERMISSION_MATRIX.get(r1).get(perm).equals(
PERMISSION_MATRIX.get(r2).get(perm))) {
different = true;
break;
}
}
assertTrue(different, r1 + " 和 " + r2 + " 的权限集应不同");
}
}
}
// ==================== 与数据库权限码对照 ====================
@Test
void testAllDefinedPermissionsExistInCodebase() {
// 验证权限矩阵中定义的权限码都在 permissions 表中有所对应
String[] expectedCodes = {
"user.view", "user.sensitive.view", "user.status.change",
"review.view", "review.process",
"matchmaker.view", "matchmaker.assign", "matchmaker.service",
"activity.view", "activity.create", "activity.review_registration",
"risk.report.view", "risk.report.process", "risk.user.ban",
"organization.manage", "permission.manage",
"analytics.view", "data.export"
};
assertEquals(18, expectedCodes.length, "权限码数量应与定义一致");
}
}