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
|
'platform:overseas-warehouse:customer-visit:edit')) <> 14 THEN
|
||||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='五期海外派送权限初始化失败:平台管理员授权不完整';
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='五期海外派送权限初始化失败:平台管理员授权不完整';
|
||||||
END IF;
|
END IF;
|
||||||
IF (SELECT COUNT(*) FROM iam_role_permission grant_row
|
IF EXISTS (SELECT 1 FROM iam_role role
|
||||||
JOIN iam_role role ON role.id=grant_row.role_id AND role.tenant_id=grant_row.tenant_id
|
WHERE role.tenant_id=0 AND role.app_code='PLATFORM'
|
||||||
JOIN iam_permission permission ON permission.id=grant_row.permission_id
|
AND UPPER(role.role_code)='PLATFORM_CUSTOM_ADMIN'
|
||||||
WHERE role.role_code='PLATFORM_CUSTOM_ADMIN'
|
AND role.status='ACTIVE' AND role.deleted=0
|
||||||
AND permission.permission_code IN (
|
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:list',
|
||||||
'platform:overseas-warehouse:dispatch:edit',
|
'platform:overseas-warehouse:dispatch:edit',
|
||||||
'platform:overseas-warehouse:dispatch:cancel',
|
'platform:overseas-warehouse:dispatch:cancel',
|
||||||
@@ -16729,7 +16732,7 @@ BEGIN
|
|||||||
'platform:overseas-warehouse:delivery:return',
|
'platform:overseas-warehouse:delivery:return',
|
||||||
'platform:overseas-warehouse:delivery:status',
|
'platform:overseas-warehouse:delivery:status',
|
||||||
'platform:overseas-warehouse:customer-visit:list',
|
'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='五期海外派送权限初始化失败:平台自定义管理员授权不完整';
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='五期海外派送权限初始化失败:平台自定义管理员授权不完整';
|
||||||
END IF;
|
END IF;
|
||||||
SELECT COALESCE(SUM(role_code='WAREHOUSE_OPERATOR'),0),
|
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.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency>
|
||||||
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</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.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>
|
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
|
<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
|
||||||
</project>
|
</project>
|
||||||
|
|
||||||
|
|||||||
@@ -223,11 +223,14 @@ BEGIN
|
|||||||
'platform:overseas-warehouse:customer-visit:edit')) <> 14 THEN
|
'platform:overseas-warehouse:customer-visit:edit')) <> 14 THEN
|
||||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='五期海外派送权限初始化失败:平台管理员授权不完整';
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='五期海外派送权限初始化失败:平台管理员授权不完整';
|
||||||
END IF;
|
END IF;
|
||||||
IF (SELECT COUNT(*) FROM iam_role_permission grant_row
|
IF EXISTS (SELECT 1 FROM iam_role role
|
||||||
JOIN iam_role role ON role.id=grant_row.role_id AND role.tenant_id=grant_row.tenant_id
|
WHERE role.tenant_id=0 AND role.app_code='PLATFORM'
|
||||||
JOIN iam_permission permission ON permission.id=grant_row.permission_id
|
AND UPPER(role.role_code)='PLATFORM_CUSTOM_ADMIN'
|
||||||
WHERE role.role_code='PLATFORM_CUSTOM_ADMIN'
|
AND role.status='ACTIVE' AND role.deleted=0
|
||||||
AND permission.permission_code IN (
|
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:list',
|
||||||
'platform:overseas-warehouse:dispatch:edit',
|
'platform:overseas-warehouse:dispatch:edit',
|
||||||
'platform:overseas-warehouse:dispatch:cancel',
|
'platform:overseas-warehouse:dispatch:cancel',
|
||||||
@@ -241,7 +244,7 @@ BEGIN
|
|||||||
'platform:overseas-warehouse:delivery:return',
|
'platform:overseas-warehouse:delivery:return',
|
||||||
'platform:overseas-warehouse:delivery:status',
|
'platform:overseas-warehouse:delivery:status',
|
||||||
'platform:overseas-warehouse:customer-visit:list',
|
'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='五期海外派送权限初始化失败:平台自定义管理员授权不完整';
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='五期海外派送权限初始化失败:平台自定义管理员授权不完整';
|
||||||
END IF;
|
END IF;
|
||||||
SELECT COALESCE(SUM(role_code='WAREHOUSE_OPERATOR'),0),
|
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",
|
"INTO v_warehouse_operator_permission_count, v_warehouse_tally_permission_count",
|
||||||
"IF v_warehouse_operator_permission_count <> 14",
|
"IF v_warehouse_operator_permission_count <> 14",
|
||||||
"OR v_warehouse_tally_permission_count <> 5 THEN",
|
"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(
|
assertThat(sql).doesNotContain(
|
||||||
"IF (SELECT COUNT(*) FROM tmp_phase5_delivery_role_permission",
|
"IF (SELECT COUNT(*) FROM tmp_phase5_delivery_role_permission",
|
||||||
"OR (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 phase4 = unifiedSql.indexOf("-- 四期海外权限统一目录");
|
||||||
int phase5 = unifiedSql.indexOf("-- 五期海外排车、出库与派送权限(来源:iam/db/phase5-delivery-permissions.sql)");
|
int phase5 = unifiedSql.indexOf("-- 五期海外排车、出库与派送权限(来源:iam/db/phase5-delivery-permissions.sql)");
|
||||||
int bodyStart = unifiedSql.indexOf("USE baiyue_iam;", phase5);
|
int bodyStart = unifiedSql.indexOf("USE baiyue_iam;", phase5);
|
||||||
int nextSection = unifiedSql.indexOf("-- 海外智能排车草稿锁", bodyStart);
|
int nextSection = unifiedSql.indexOf("-- IAM 客户提交即成功", bodyStart);
|
||||||
|
|
||||||
assertThat(phase4).isGreaterThanOrEqualTo(0);
|
assertThat(phase4).isGreaterThanOrEqualTo(0);
|
||||||
assertThat(phase5).isGreaterThan(phase4);
|
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