feat: complete phase 5 overseas fulfillment contracts
This commit is contained in:
@@ -20,6 +20,11 @@ class IamOpenApiContractTest {
|
||||
|
||||
assertThat(document).contains("/api/platform/v1/iam/authorization/permissions:")
|
||||
.contains("/api/merchant/v1/iam/authorization/permissions:")
|
||||
.contains("platform:overseas-warehouse:dispatch:transfer-delivery")
|
||||
.contains("platform:overseas-warehouse:outbound:cancel")
|
||||
.contains("merchant:warehouse:delivery:list")
|
||||
.contains("merchant:warehouse:delivery:create")
|
||||
.contains("列表权限包含详情只读")
|
||||
.contains("PermissionCodesApiResponse:")
|
||||
.contains("TenantPageApiResponse:")
|
||||
.contains("TenantApiResponse:")
|
||||
|
||||
+4
@@ -96,6 +96,10 @@ class OverseasPhase4PermissionSqlContractTest {
|
||||
void servicePermissionConstantsExactlyMatchTheIamCatalog() throws Exception {
|
||||
Set<String> moduleCatalog = codes(new ClassPathResource("db/lastleg-permissions.sql")
|
||||
.getContentAsString(StandardCharsets.UTF_8));
|
||||
codes(new ClassPathResource("db/phase5-delivery-permissions.sql")
|
||||
.getContentAsString(StandardCharsets.UTF_8)).stream()
|
||||
.filter(code -> code.startsWith("platform:"))
|
||||
.forEach(moduleCatalog::add);
|
||||
Set<String> serviceCatalog = new LinkedHashSet<>();
|
||||
serviceCatalog.addAll(codes(repositoryFile(
|
||||
"lastleg-service/src/main/java/com/baiyue/lastleg/security/OverseasPermissions.java")));
|
||||
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
package com.baiyue.iam.repository;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class Phase5DeliveryPermissionSqlContractTest {
|
||||
private static final Pattern CODE = Pattern.compile("(?:platform:overseas-warehouse|merchant:warehouse):[a-z0-9:-]+");
|
||||
private static final Set<String> REQUIRED = Set.of(
|
||||
"platform:overseas-warehouse:dispatch:edit",
|
||||
"platform:overseas-warehouse:dispatch:cancel",
|
||||
"platform:overseas-warehouse:dispatch:transfer-delivery",
|
||||
"platform:overseas-warehouse:outbound:list",
|
||||
"platform:overseas-warehouse:outbound:create",
|
||||
"platform:overseas-warehouse:outbound:cancel",
|
||||
"platform:overseas-warehouse:delivery:list",
|
||||
"merchant:warehouse:delivery:list",
|
||||
"merchant:warehouse:delivery:create");
|
||||
|
||||
@Test
|
||||
void definesOnlyTheFrozenPhase5DeliveryCatalogWithoutAliases() throws Exception {
|
||||
String sql = sql();
|
||||
|
||||
assertThat(codes(sql)).containsExactlyInAnyOrderElementsOf(REQUIRED);
|
||||
assertThat(codes(sql)).noneMatch(code -> code.endsWith(":view"));
|
||||
assertThat(sql).contains(
|
||||
"guard_phase5_delivery_permission_ids",
|
||||
"权限ID或编码冲突",
|
||||
"permission_type=VALUES(permission_type)",
|
||||
"列表权限同时覆盖列表和详情只读");
|
||||
}
|
||||
|
||||
@Test
|
||||
void grantsAdministratorsAndWarehouseRolesByTheFrozenMinimumMatrix() throws Exception {
|
||||
String sql = sql();
|
||||
|
||||
assertThat(sql).contains(
|
||||
"UPPER(role.role_code) IN ('PLATFORM_ADMIN','PLATFORM_CUSTOM_ADMIN')",
|
||||
"tmp_phase5_delivery_role_permission",
|
||||
"('WAREHOUSE_OPERATOR','platform:overseas-warehouse:dispatch:edit')",
|
||||
"('WAREHOUSE_OPERATOR','platform:overseas-warehouse:outbound:create')",
|
||||
"('WAREHOUSE_TALLY','platform:overseas-warehouse:outbound:list')",
|
||||
"('WAREHOUSE_TALLY','platform:overseas-warehouse:delivery:list')",
|
||||
"role.role_code IN ('OVERSEAS_WAREHOUSE_PDA_OPERATOR','CN_FIRSTLEG_PDA_OPERATOR')",
|
||||
"PDA岗位错误获得后台权限");
|
||||
assertThat(sql).doesNotContain(
|
||||
"('WAREHOUSE_TALLY','platform:overseas-warehouse:dispatch:edit')",
|
||||
"('WAREHOUSE_TALLY','platform:overseas-warehouse:outbound:create')",
|
||||
"('OVERSEAS_WAREHOUSE_PDA_OPERATOR','platform:overseas-warehouse:",
|
||||
"('CN_FIRSTLEG_PDA_OPERATOR','platform:overseas-warehouse:");
|
||||
}
|
||||
|
||||
@Test
|
||||
void grantsOnlyTheDefaultCustomerAdministratorAutomatically() throws Exception {
|
||||
String sql = sql();
|
||||
int marker = sql.indexOf("-- 客户默认管理员获得派送列表/详情只读及独立创建");
|
||||
int assertion = sql.indexOf("DROP PROCEDURE IF EXISTS assert_phase5_delivery_permissions", marker);
|
||||
assertThat(marker).isGreaterThanOrEqualTo(0);
|
||||
assertThat(assertion).isGreaterThan(marker);
|
||||
|
||||
String grant = sql.substring(marker, assertion);
|
||||
assertThat(grant).contains(
|
||||
"role.role_code='MERCHANT_OWNER'",
|
||||
"merchant:warehouse:delivery:list",
|
||||
"merchant:warehouse:delivery:create");
|
||||
assertThat(grant).doesNotContain("MERCHANT_OPERATOR", "ORDER_VIEWER", "role.role_code IN");
|
||||
}
|
||||
|
||||
@Test
|
||||
void domesticUnifiedEntryInlinesTheCompleteModuleSqlAfterPhase4Permissions() throws Exception {
|
||||
String moduleSql = sql().trim();
|
||||
String unifiedSql = repositoryFile("deploy/sql/头程数据库统一增量-MySQL8.sql");
|
||||
int phase4 = unifiedSql.indexOf("-- 四期海外权限统一目录");
|
||||
int phase5 = unifiedSql.indexOf("-- 五期海外排车、出库与派送权限(来源:iam/db/phase5-delivery-permissions.sql)");
|
||||
int bodyStart = unifiedSql.indexOf("USE baiyue_iam;", phase5);
|
||||
int nextSection = unifiedSql.indexOf("-- 海外智能排车草稿锁", bodyStart);
|
||||
|
||||
assertThat(phase4).isGreaterThanOrEqualTo(0);
|
||||
assertThat(phase5).isGreaterThan(phase4);
|
||||
assertThat(bodyStart).isGreaterThan(phase5);
|
||||
assertThat(nextSection).isGreaterThan(bodyStart);
|
||||
assertThat(unifiedSql.substring(bodyStart, nextSection).trim()).isEqualTo(moduleSql);
|
||||
assertThat(codes(unifiedSql.substring(phase5, nextSection)))
|
||||
.containsExactlyInAnyOrderElementsOf(REQUIRED);
|
||||
}
|
||||
|
||||
@Test
|
||||
void deploymentGuideUsesOnlyTheDomesticUnifiedEntry() throws Exception {
|
||||
String readme = repositoryFile("deploy/sql/README.md");
|
||||
|
||||
assertThat(readme).contains(
|
||||
"五期海外排车、出库与派送权限",
|
||||
"测试和部署只执行固定入口,不再单独执行模块脚本",
|
||||
"merchant:warehouse:delivery:list",
|
||||
"merchant:warehouse:delivery:create",
|
||||
"PDA 岗位不得获得上述后台权限");
|
||||
}
|
||||
|
||||
private static String sql() throws Exception {
|
||||
return new ClassPathResource("db/phase5-delivery-permissions.sql")
|
||||
.getContentAsString(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private static Set<String> codes(String source) {
|
||||
Set<String> values = new LinkedHashSet<>();
|
||||
CODE.matcher(source).results().map(result -> result.group()).forEach(values::add);
|
||||
return values;
|
||||
}
|
||||
|
||||
private static String repositoryFile(String relativePath) throws Exception {
|
||||
Path path = Path.of(relativePath);
|
||||
if (!Files.exists(path)) path = Path.of("..").resolve(relativePath);
|
||||
return Files.readString(path, StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
@@ -74,6 +74,22 @@ class AuthorizationSnapshotServiceTest {
|
||||
verify(mapper).findPermissions(42L, 0L, 9L, "PLATFORM");
|
||||
}
|
||||
|
||||
@Test
|
||||
void exposesPhase5DeliveryPermissionsFromCurrentRoleAssignments() {
|
||||
when(mapper.countActiveIdentity(42L, 7L, 9L)).thenReturn(1);
|
||||
when(mapper.findRoles(42L, 7L, 9L, "MERCHANT")).thenReturn(List.of("MERCHANT_OWNER"));
|
||||
when(mapper.findPermissions(42L, 7L, 9L, "MERCHANT")).thenReturn(List.of(
|
||||
"merchant:warehouse:delivery:list",
|
||||
"merchant:warehouse:delivery:create"));
|
||||
|
||||
var result = service.currentPermissions(new AuthenticatedUser(42L, 7L, 7L, 9L,
|
||||
"owner", "MERCHANT", "MERCHANT", java.util.Set.of()), "MERCHANT");
|
||||
|
||||
assertThat(result).containsExactlyInAnyOrder(
|
||||
"merchant:warehouse:delivery:create",
|
||||
"merchant:warehouse:delivery:list");
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsIncompleteCurrentIdentityAsBusinessError() {
|
||||
assertThatThrownBy(() -> service
|
||||
|
||||
Reference in New Issue
Block a user