fix: allow optional phase5 custom admin role
This commit is contained in:
@@ -16711,11 +16711,14 @@ BEGIN
|
||||
'platform:overseas-warehouse:customer-visit:edit')) <> 14 THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='五期海外派送权限初始化失败:平台管理员授权不完整';
|
||||
END IF;
|
||||
IF (SELECT COUNT(*) FROM iam_role_permission grant_row
|
||||
JOIN iam_role role ON role.id=grant_row.role_id AND role.tenant_id=grant_row.tenant_id
|
||||
JOIN iam_permission permission ON permission.id=grant_row.permission_id
|
||||
WHERE role.role_code='PLATFORM_CUSTOM_ADMIN'
|
||||
AND permission.permission_code IN (
|
||||
IF EXISTS (SELECT 1 FROM iam_role role
|
||||
WHERE role.tenant_id=0 AND role.app_code='PLATFORM'
|
||||
AND UPPER(role.role_code)='PLATFORM_CUSTOM_ADMIN'
|
||||
AND role.status='ACTIVE' AND role.deleted=0
|
||||
AND (SELECT COUNT(*) FROM iam_role_permission grant_row
|
||||
JOIN iam_permission permission ON permission.id=grant_row.permission_id
|
||||
WHERE grant_row.role_id=role.id AND grant_row.tenant_id=role.tenant_id
|
||||
AND permission.permission_code IN (
|
||||
'platform:overseas-warehouse:dispatch:list',
|
||||
'platform:overseas-warehouse:dispatch:edit',
|
||||
'platform:overseas-warehouse:dispatch:cancel',
|
||||
@@ -16729,7 +16732,7 @@ BEGIN
|
||||
'platform:overseas-warehouse:delivery:return',
|
||||
'platform:overseas-warehouse:delivery:status',
|
||||
'platform:overseas-warehouse:customer-visit:list',
|
||||
'platform:overseas-warehouse:customer-visit:edit')) <> 14 THEN
|
||||
'platform:overseas-warehouse:customer-visit:edit')) <> 14) THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='五期海外派送权限初始化失败:平台自定义管理员授权不完整';
|
||||
END IF;
|
||||
SELECT COALESCE(SUM(role_code='WAREHOUSE_OPERATOR'),0),
|
||||
|
||||
+1
-1
@@ -18,8 +18,8 @@
|
||||
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency>
|
||||
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency>
|
||||
<dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency>
|
||||
<dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>test</scope></dependency>
|
||||
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
|
||||
</dependencies>
|
||||
<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
|
||||
</project>
|
||||
|
||||
|
||||
@@ -223,11 +223,14 @@ BEGIN
|
||||
'platform:overseas-warehouse:customer-visit:edit')) <> 14 THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='五期海外派送权限初始化失败:平台管理员授权不完整';
|
||||
END IF;
|
||||
IF (SELECT COUNT(*) FROM iam_role_permission grant_row
|
||||
JOIN iam_role role ON role.id=grant_row.role_id AND role.tenant_id=grant_row.tenant_id
|
||||
JOIN iam_permission permission ON permission.id=grant_row.permission_id
|
||||
WHERE role.role_code='PLATFORM_CUSTOM_ADMIN'
|
||||
AND permission.permission_code IN (
|
||||
IF EXISTS (SELECT 1 FROM iam_role role
|
||||
WHERE role.tenant_id=0 AND role.app_code='PLATFORM'
|
||||
AND UPPER(role.role_code)='PLATFORM_CUSTOM_ADMIN'
|
||||
AND role.status='ACTIVE' AND role.deleted=0
|
||||
AND (SELECT COUNT(*) FROM iam_role_permission grant_row
|
||||
JOIN iam_permission permission ON permission.id=grant_row.permission_id
|
||||
WHERE grant_row.role_id=role.id AND grant_row.tenant_id=role.tenant_id
|
||||
AND permission.permission_code IN (
|
||||
'platform:overseas-warehouse:dispatch:list',
|
||||
'platform:overseas-warehouse:dispatch:edit',
|
||||
'platform:overseas-warehouse:dispatch:cancel',
|
||||
@@ -241,7 +244,7 @@ BEGIN
|
||||
'platform:overseas-warehouse:delivery:return',
|
||||
'platform:overseas-warehouse:delivery:status',
|
||||
'platform:overseas-warehouse:customer-visit:list',
|
||||
'platform:overseas-warehouse:customer-visit:edit')) <> 14 THEN
|
||||
'platform:overseas-warehouse:customer-visit:edit')) <> 14) THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='五期海外派送权限初始化失败:平台自定义管理员授权不完整';
|
||||
END IF;
|
||||
SELECT COALESCE(SUM(role_code='WAREHOUSE_OPERATOR'),0),
|
||||
|
||||
+5
-1
@@ -108,7 +108,11 @@ class Phase5DeliveryPermissionSqlContractTest {
|
||||
"INTO v_warehouse_operator_permission_count, v_warehouse_tally_permission_count",
|
||||
"IF v_warehouse_operator_permission_count <> 14",
|
||||
"OR v_warehouse_tally_permission_count <> 5 THEN",
|
||||
"IF EXISTS (SELECT 1 FROM iam_role role",
|
||||
"AND UPPER(role.role_code)='PLATFORM_CUSTOM_ADMIN'",
|
||||
"WHERE grant_row.role_id=role.id AND grant_row.tenant_id=role.tenant_id",
|
||||
"平台自定义管理员授权不完整");
|
||||
assertThat(sql).doesNotContain("WHERE role.role_code='PLATFORM_CUSTOM_ADMIN'");
|
||||
assertThat(sql).doesNotContain(
|
||||
"IF (SELECT COUNT(*) FROM tmp_phase5_delivery_role_permission",
|
||||
"OR (SELECT COUNT(*) FROM tmp_phase5_delivery_role_permission");
|
||||
@@ -137,7 +141,7 @@ class Phase5DeliveryPermissionSqlContractTest {
|
||||
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);
|
||||
int nextSection = unifiedSql.indexOf("-- IAM 客户提交即成功", bodyStart);
|
||||
|
||||
assertThat(phase4).isGreaterThanOrEqualTo(0);
|
||||
assertThat(phase5).isGreaterThan(phase4);
|
||||
|
||||
+220
@@ -0,0 +1,220 @@
|
||||
package com.baiyue.iam.repository;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Statement;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class Phase5DeliveryPermissionSqlExecutionTest {
|
||||
private static final Pattern PLATFORM_CODE =
|
||||
Pattern.compile("platform:overseas-warehouse:[a-z0-9:-]+");
|
||||
|
||||
@Test
|
||||
void noCustomAdministratorDoesNotCreateAnAssertionViolation() throws Exception {
|
||||
try (Connection connection = database()) {
|
||||
executeGrant(connection);
|
||||
|
||||
assertThat(customAdministratorViolations(connection)).isZero();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void onePartiallyGrantedCustomAdministratorIsCompletedIdempotently() throws Exception {
|
||||
try (Connection connection = database()) {
|
||||
insertRole(connection, 11L, "platform_custom_admin");
|
||||
grantFirstPermissions(connection, 11L, 3);
|
||||
assertThat(customAdministratorViolations(connection)).isEqualTo(1);
|
||||
|
||||
executeGrant(connection);
|
||||
assertThat(grantCount(connection, 11L)).isEqualTo(14);
|
||||
assertThat(customAdministratorViolations(connection)).isZero();
|
||||
|
||||
executeGrant(connection);
|
||||
assertThat(grantCount(connection, 11L)).isEqualTo(14);
|
||||
assertThat(totalGrantCount(connection)).isEqualTo(14);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void multipleCustomAdministratorsExposeTheSingleIncompleteRole() throws Exception {
|
||||
try (Connection connection = database()) {
|
||||
insertRole(connection, 21L, "PLATFORM_CUSTOM_ADMIN");
|
||||
insertRole(connection, 22L, "Platform_Custom_Admin");
|
||||
grantFirstPermissions(connection, 21L, 14);
|
||||
grantFirstPermissions(connection, 22L, 13);
|
||||
|
||||
assertThat(customAdministratorViolations(connection)).isEqualTo(1);
|
||||
|
||||
executeGrant(connection);
|
||||
assertThat(grantCount(connection, 21L)).isEqualTo(14);
|
||||
assertThat(grantCount(connection, 22L)).isEqualTo(14);
|
||||
assertThat(customAdministratorViolations(connection)).isZero();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void multipleCompleteCustomAdministratorsRemainCompleteAfterReplay() throws Exception {
|
||||
try (Connection connection = database()) {
|
||||
insertRole(connection, 31L, "PLATFORM_CUSTOM_ADMIN");
|
||||
insertRole(connection, 32L, "platform_custom_admin");
|
||||
grantFirstPermissions(connection, 31L, 14);
|
||||
grantFirstPermissions(connection, 32L, 14);
|
||||
|
||||
assertThat(customAdministratorViolations(connection)).isZero();
|
||||
executeGrant(connection);
|
||||
executeGrant(connection);
|
||||
|
||||
assertThat(grantCount(connection, 31L)).isEqualTo(14);
|
||||
assertThat(grantCount(connection, 32L)).isEqualTo(14);
|
||||
assertThat(totalGrantCount(connection)).isEqualTo(28);
|
||||
}
|
||||
}
|
||||
|
||||
private static Connection database() throws Exception {
|
||||
Connection connection = DriverManager.getConnection(
|
||||
"jdbc:h2:mem:phase5_" + UUID.randomUUID() + ";MODE=MySQL;DATABASE_TO_LOWER=TRUE");
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
statement.execute("""
|
||||
CREATE TABLE iam_role (
|
||||
id BIGINT PRIMARY KEY,
|
||||
tenant_id BIGINT NOT NULL,
|
||||
app_code VARCHAR(32) NOT NULL,
|
||||
role_code VARCHAR(64) NOT NULL,
|
||||
status VARCHAR(16) NOT NULL,
|
||||
deleted INT NOT NULL
|
||||
)
|
||||
""");
|
||||
statement.execute("""
|
||||
CREATE TABLE iam_permission (
|
||||
id BIGINT PRIMARY KEY,
|
||||
tenant_id BIGINT NOT NULL,
|
||||
app_code VARCHAR(32) NOT NULL,
|
||||
permission_code VARCHAR(160) NOT NULL,
|
||||
status VARCHAR(16) NOT NULL,
|
||||
deleted INT NOT NULL
|
||||
)
|
||||
""");
|
||||
statement.execute("""
|
||||
CREATE TABLE iam_role_permission (
|
||||
tenant_id BIGINT NOT NULL,
|
||||
role_id BIGINT NOT NULL,
|
||||
permission_id BIGINT NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL,
|
||||
PRIMARY KEY (tenant_id, role_id, permission_id)
|
||||
)
|
||||
""");
|
||||
}
|
||||
long id = 1;
|
||||
for (String code : platformPermissions()) {
|
||||
try (PreparedStatement insert = connection.prepareStatement(
|
||||
"INSERT INTO iam_permission VALUES (?,0,'PLATFORM',?,'ACTIVE',0)")) {
|
||||
insert.setLong(1, id++);
|
||||
insert.setString(2, code);
|
||||
insert.executeUpdate();
|
||||
}
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
|
||||
private static void insertRole(Connection connection, long id, String roleCode) throws Exception {
|
||||
try (PreparedStatement insert = connection.prepareStatement(
|
||||
"INSERT INTO iam_role VALUES (?,0,'PLATFORM',?,'ACTIVE',0)")) {
|
||||
insert.setLong(1, id);
|
||||
insert.setString(2, roleCode);
|
||||
insert.executeUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
private static void grantFirstPermissions(Connection connection, long roleId, int limit) throws Exception {
|
||||
try (PreparedStatement insert = connection.prepareStatement("""
|
||||
INSERT INTO iam_role_permission (tenant_id, role_id, permission_id, created_at)
|
||||
SELECT 0, ?, id, CURRENT_TIMESTAMP FROM iam_permission ORDER BY id LIMIT ?
|
||||
""")) {
|
||||
insert.setLong(1, roleId);
|
||||
insert.setInt(2, limit);
|
||||
insert.executeUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
private static void executeGrant(Connection connection) throws Exception {
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
statement.executeUpdate(administratorGrantSql());
|
||||
}
|
||||
}
|
||||
|
||||
private static int grantCount(Connection connection, long roleId) throws Exception {
|
||||
try (PreparedStatement query = connection.prepareStatement(
|
||||
"SELECT COUNT(*) FROM iam_role_permission WHERE tenant_id=0 AND role_id=?")) {
|
||||
query.setLong(1, roleId);
|
||||
try (ResultSet result = query.executeQuery()) {
|
||||
result.next();
|
||||
return result.getInt(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int totalGrantCount(Connection connection) throws Exception {
|
||||
try (Statement query = connection.createStatement();
|
||||
ResultSet result = query.executeQuery("SELECT COUNT(*) FROM iam_role_permission")) {
|
||||
result.next();
|
||||
return result.getInt(1);
|
||||
}
|
||||
}
|
||||
|
||||
private static int customAdministratorViolations(Connection connection) throws Exception {
|
||||
String placeholders = String.join(",", platformPermissions().stream().map(code -> "?").toList());
|
||||
String sql = """
|
||||
SELECT COUNT(*) FROM iam_role role
|
||||
WHERE role.tenant_id=0 AND role.app_code='PLATFORM'
|
||||
AND UPPER(role.role_code)='PLATFORM_CUSTOM_ADMIN'
|
||||
AND role.status='ACTIVE' AND role.deleted=0
|
||||
AND (SELECT COUNT(*) FROM iam_role_permission grant_row
|
||||
JOIN iam_permission permission ON permission.id=grant_row.permission_id
|
||||
WHERE grant_row.role_id=role.id AND grant_row.tenant_id=role.tenant_id
|
||||
AND permission.permission_code IN (%s)) <> 14
|
||||
""".formatted(placeholders);
|
||||
try (PreparedStatement query = connection.prepareStatement(sql)) {
|
||||
int index = 1;
|
||||
for (String code : platformPermissions()) query.setString(index++, code);
|
||||
try (ResultSet result = query.executeQuery()) {
|
||||
result.next();
|
||||
return result.getInt(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String administratorGrantSql() throws Exception {
|
||||
String sql = sql();
|
||||
int comment = sql.indexOf("-- 平台管理员默认拥有五期全部后台动作");
|
||||
int start = sql.indexOf("INSERT IGNORE INTO iam_role_permission", comment);
|
||||
int end = sql.indexOf(';', start);
|
||||
assertThat(comment).isGreaterThanOrEqualTo(0);
|
||||
assertThat(start).isGreaterThan(comment);
|
||||
assertThat(end).isGreaterThan(start);
|
||||
return sql.substring(start, end);
|
||||
}
|
||||
|
||||
private static Set<String> platformPermissions() throws Exception {
|
||||
LinkedHashSet<String> codes = new LinkedHashSet<>();
|
||||
String grant = administratorGrantSql();
|
||||
PLATFORM_CODE.matcher(grant).results().map(result -> result.group()).forEach(codes::add);
|
||||
assertThat(codes).hasSize(14);
|
||||
return codes;
|
||||
}
|
||||
|
||||
private static String sql() throws Exception {
|
||||
return new ClassPathResource("db/phase5-delivery-permissions.sql")
|
||||
.getContentAsString(StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user