feat: 引入 Flyway 数据库版本管理,替换 ddl-auto: update

所有服务(tenant/im/file/update/license/push/demo)统一:
- 添加 flyway-core + flyway-mysql 依赖
- ddl-auto 从 update 改为 validate
- 添加 V1__init.sql 基线(CREATE TABLE IF NOT EXISTS,幂等)
- baseline-on-migrate=true 兼容已有部署,存量库不重跑 V1

后续 Entity 变更须同步写 V(n+1) 迁移 SQL,Flyway 在容器
启动时自动按版本顺序执行,update.sh 无需任何改动。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
这个提交包含在:
XuqmGroup 2026-06-12 23:28:12 +08:00
父节点 ede000eac1
当前提交 200f8ae54a
共有 21 个文件被更改,包括 667 次插入7 次删除

查看文件

@ -64,6 +64,14 @@
<artifactId>mysql-connector-j</artifactId> <artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>

查看文件

@ -20,7 +20,7 @@ spring:
max-lifetime: 900000 max-lifetime: 900000
jpa: jpa:
hibernate: hibernate:
ddl-auto: update ddl-auto: validate
show-sql: false show-sql: false
properties: properties:
hibernate: hibernate:
@ -29,6 +29,11 @@ spring:
time-zone: UTC time-zone: UTC
serialization: serialization:
write-dates-as-timestamps: false write-dates-as-timestamps: false
flyway:
enabled: true
baseline-on-migrate: true
baseline-version: 0
locations: classpath:db/migration
jwt: jwt:
secret: ${XUQM_JWT_SECRET:xuqm-tenant-service-secret-key-must-be-at-least-256-bits-long-for-hmac} secret: ${XUQM_JWT_SECRET:xuqm-tenant-service-secret-key-must-be-at-least-256-bits-long-for-hmac}

查看文件

@ -0,0 +1,11 @@
CREATE TABLE IF NOT EXISTS demo_user (
id VARCHAR(36) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
user_id VARCHAR(128) NOT NULL,
password_hash VARCHAR(128) NOT NULL,
nickname VARCHAR(64),
avatar VARCHAR(512),
gender VARCHAR(16),
created_at DATETIME(6) NOT NULL,
UNIQUE KEY uq_demo_user_appkey_userid (app_key, user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

查看文件

@ -59,6 +59,14 @@
<artifactId>mysql-connector-j</artifactId> <artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>

查看文件

@ -20,7 +20,7 @@ spring:
max-lifetime: 900000 max-lifetime: 900000
jpa: jpa:
hibernate: hibernate:
ddl-auto: update ddl-auto: validate
show-sql: false show-sql: false
properties: properties:
hibernate: hibernate:
@ -34,6 +34,11 @@ spring:
time-zone: UTC time-zone: UTC
serialization: serialization:
write-dates-as-timestamps: false write-dates-as-timestamps: false
flyway:
enabled: true
baseline-on-migrate: true
baseline-version: 0
locations: classpath:db/migration
jwt: jwt:
secret: ${XUQM_JWT_SECRET:xuqm-tenant-service-secret-key-must-be-at-least-256-bits-long-for-hmac} secret: ${XUQM_JWT_SECRET:xuqm-tenant-service-secret-key-must-be-at-least-256-bits-long-for-hmac}

查看文件

@ -0,0 +1,14 @@
CREATE TABLE IF NOT EXISTS file_record (
id VARCHAR(36) NOT NULL PRIMARY KEY,
hash VARCHAR(64) NOT NULL,
original_name VARCHAR(255),
mime_type VARCHAR(128),
size BIGINT NOT NULL,
ext VARCHAR(16),
storage_path VARCHAR(512) NOT NULL,
thumbnail_path VARCHAR(512),
thumbnail_size BIGINT NOT NULL,
created_at DATETIME(6) NOT NULL,
last_accessed_at DATETIME(6) NOT NULL,
UNIQUE KEY uk_file_record_hash (hash)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

查看文件

@ -71,6 +71,14 @@
<artifactId>mysql-connector-j</artifactId> <artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>

查看文件

@ -17,7 +17,7 @@ spring:
max-lifetime: 900000 max-lifetime: 900000
jpa: jpa:
hibernate: hibernate:
ddl-auto: update ddl-auto: validate
show-sql: false show-sql: false
properties: properties:
hibernate: hibernate:
@ -38,6 +38,11 @@ spring:
time-zone: UTC time-zone: UTC
serialization: serialization:
write-dates-as-timestamps: false write-dates-as-timestamps: false
flyway:
enabled: true
baseline-on-migrate: true
baseline-version: 0
locations: classpath:db/migration
jwt: jwt:
secret: ${XUQM_JWT_SECRET:xuqm-tenant-service-secret-key-must-be-at-least-256-bits-long-for-hmac} secret: ${XUQM_JWT_SECRET:xuqm-tenant-service-secret-key-must-be-at-least-256-bits-long-for-hmac}

查看文件

@ -0,0 +1,195 @@
CREATE TABLE IF NOT EXISTS im_account (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
user_id VARCHAR(128) NOT NULL,
nickname VARCHAR(64),
gender VARCHAR(16),
avatar VARCHAR(512),
admin BIT(1) NOT NULL,
status VARCHAR(16) NOT NULL,
created_at DATETIME(6) NOT NULL,
UNIQUE KEY uk_im_account_app_user (app_key, user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS im_blacklist (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
user_id VARCHAR(128) NOT NULL,
blocked_user_id VARCHAR(128) NOT NULL,
created_at DATETIME(6) NOT NULL,
UNIQUE KEY uk_im_blacklist (app_key, user_id, blocked_user_id),
INDEX idx_blacklist_app_user (app_key, user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS im_conversation_state (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
user_id VARCHAR(128) NOT NULL,
target_id VARCHAR(128) NOT NULL,
chat_type VARCHAR(16) NOT NULL,
pinned BIT(1) NOT NULL,
muted BIT(1) NOT NULL,
hidden BIT(1) NOT NULL,
draft TEXT,
conversation_group VARCHAR(64),
last_read_at DATETIME(6),
created_at DATETIME(6) NOT NULL,
updated_at DATETIME(6) NOT NULL,
UNIQUE KEY uk_im_conv_state (app_key, user_id, target_id, chat_type),
INDEX idx_conv_state_app_user (app_key, user_id),
INDEX idx_conv_state_app_target (app_key, target_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS im_friends (
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
user_id VARCHAR(128) NOT NULL,
friend_id VARCHAR(128) NOT NULL,
friend_group VARCHAR(64),
created_at DATETIME(6) NOT NULL,
UNIQUE KEY uk_im_friends (app_key, user_id, friend_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS im_friend_request (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
from_user_id VARCHAR(128) NOT NULL,
to_user_id VARCHAR(128) NOT NULL,
remark VARCHAR(256),
status VARCHAR(16) NOT NULL,
created_at DATETIME(6) NOT NULL,
reviewed_at DATETIME(6),
UNIQUE KEY uk_im_friend_request (app_key, from_user_id, to_user_id),
INDEX idx_friend_request_app_to (app_key, to_user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS im_global_mute (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
enabled BIT(1) NOT NULL,
created_at DATETIME(6) NOT NULL,
updated_at DATETIME(6) NOT NULL,
UNIQUE KEY uk_im_global_mute_app (app_key)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS im_group (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
name VARCHAR(128) NOT NULL,
group_type VARCHAR(16),
creator_id VARCHAR(128) NOT NULL,
member_ids TEXT NOT NULL,
admin_ids TEXT NOT NULL,
announcement TEXT,
member_info TEXT,
ext_attributes TEXT,
created_at DATETIME(6) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS im_group_join_request (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
group_id VARCHAR(64) NOT NULL,
requester_id VARCHAR(128) NOT NULL,
remark VARCHAR(256),
status VARCHAR(16) NOT NULL,
created_at DATETIME(6) NOT NULL,
reviewed_at DATETIME(6),
INDEX idx_group_join_request_app_group (app_key, group_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS im_group_mute (
id VARCHAR(255) NOT NULL PRIMARY KEY,
group_id VARCHAR(64) NOT NULL,
user_id VARCHAR(128) NOT NULL,
muted_until DATETIME(6),
created_at DATETIME(6) NOT NULL,
updated_at DATETIME(6) NOT NULL,
UNIQUE KEY uk_im_group_mute (group_id, user_id),
INDEX idx_group_mute_group_user (group_id, user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS im_message (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
from_user_id VARCHAR(128) NOT NULL,
to_id VARCHAR(128) NOT NULL,
chat_type VARCHAR(16) NOT NULL,
msg_type VARCHAR(16) NOT NULL,
content TEXT NOT NULL,
status VARCHAR(16) NOT NULL,
mentioned_user_ids VARCHAR(128),
edited_at DATETIME(6),
created_at DATETIME(6) NOT NULL,
INDEX idx_app_from (app_key, from_user_id),
INDEX idx_app_to (app_key, to_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS im_offline_message (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
user_id VARCHAR(64) NOT NULL,
message_id VARCHAR(64) NOT NULL,
delivered BIT(1) NOT NULL,
created_at DATETIME(6) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS im_operation_log (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
operator_id VARCHAR(128) NOT NULL,
action VARCHAR(64) NOT NULL,
resource_type VARCHAR(64) NOT NULL,
resource_id VARCHAR(128),
detail TEXT,
created_at DATETIME(6) NOT NULL,
INDEX idx_op_log_app_time (app_key, created_at),
INDEX idx_op_log_app_operator (app_key, operator_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS im_keyword_filter (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
pattern VARCHAR(512) NOT NULL,
replacement VARCHAR(128),
action VARCHAR(16) NOT NULL,
enabled BIT(1) NOT NULL,
created_at DATETIME(6) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS im_webhook_alert (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
webhook_id VARCHAR(64) NOT NULL,
webhook_url VARCHAR(512) NOT NULL,
alert_type VARCHAR(32) NOT NULL,
description VARCHAR(512),
acknowledged BIT(1) NOT NULL,
created_at DATETIME(6) NOT NULL,
acknowledged_at DATETIME(6)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS im_webhook_config (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
url VARCHAR(512) NOT NULL,
secret VARCHAR(256),
enabled BIT(1) NOT NULL,
created_at DATETIME(6) NOT NULL,
consecutive_failures INT NOT NULL,
last_failure_at DATETIME(6)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS im_webhook_delivery (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
callback_id VARCHAR(64) NOT NULL,
callback_event VARCHAR(64) NOT NULL,
url VARCHAR(512) NOT NULL,
http_status INT NOT NULL,
response_body VARCHAR(4000),
error_message VARCHAR(4000),
attempt INT NOT NULL,
success BIT(1) NOT NULL,
created_at DATETIME(6) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

查看文件

@ -59,6 +59,14 @@
<artifactId>mysql-connector-j</artifactId> <artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>

查看文件

@ -17,7 +17,7 @@ spring:
max-lifetime: 900000 max-lifetime: 900000
jpa: jpa:
hibernate: hibernate:
ddl-auto: update ddl-auto: validate
show-sql: false show-sql: false
properties: properties:
hibernate: hibernate:
@ -26,6 +26,11 @@ spring:
time-zone: UTC time-zone: UTC
serialization: serialization:
write-dates-as-timestamps: false write-dates-as-timestamps: false
flyway:
enabled: true
baseline-on-migrate: true
baseline-version: 0
locations: classpath:db/migration
jwt: jwt:
secret: ${XUQM_JWT_SECRET:xuqm-tenant-service-secret-key-must-be-at-least-256-bits-long-for-hmac} secret: ${XUQM_JWT_SECRET:xuqm-tenant-service-secret-key-must-be-at-least-256-bits-long-for-hmac}

查看文件

@ -0,0 +1,49 @@
CREATE TABLE IF NOT EXISTS app_licenses (
app_key VARCHAR(64) NOT NULL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
android_package_name VARCHAR(128),
ios_bundle_id VARCHAR(128),
harmony_bundle_name VARCHAR(128),
max_devices INT NOT NULL DEFAULT 1,
registered_devices INT NOT NULL DEFAULT 0,
expires_at DATETIME(6),
is_active BIT(1) NOT NULL DEFAULT 1,
remark VARCHAR(500),
created_at DATETIME(6) NOT NULL,
updated_at DATETIME(6) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS devices (
id VARCHAR(36) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
device_id VARCHAR(255) NOT NULL,
device_name VARCHAR(255),
device_model VARCHAR(255),
device_vendor VARCHAR(255),
os_version VARCHAR(255),
user_id VARCHAR(255),
user_name VARCHAR(255),
user_email VARCHAR(255),
user_phone VARCHAR(64),
user_info_json TEXT,
token_hash VARCHAR(512) NOT NULL,
registered_at DATETIME(6) NOT NULL,
last_verified_at DATETIME(6),
is_active BIT(1) NOT NULL DEFAULT 1,
created_at DATETIME(6) NOT NULL,
updated_at DATETIME(6) NOT NULL,
UNIQUE KEY uk_app_key_device_id (app_key, device_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS license_operation_log (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
operator VARCHAR(128) NOT NULL,
action VARCHAR(64) NOT NULL,
resource_type VARCHAR(64) NOT NULL,
resource_id VARCHAR(128),
summary VARCHAR(255),
detail_json TEXT,
created_at DATETIME(6) NOT NULL,
INDEX idx_license_op_log_app_time (app_key, created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

查看文件

@ -59,6 +59,14 @@
<artifactId>mysql-connector-j</artifactId> <artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>

查看文件

@ -17,8 +17,13 @@ spring:
max-lifetime: 900000 max-lifetime: 900000
jpa: jpa:
hibernate: hibernate:
ddl-auto: update ddl-auto: validate
show-sql: false show-sql: false
flyway:
enabled: true
baseline-on-migrate: true
baseline-version: 0
locations: classpath:db/migration
jwt: jwt:
secret: ${XUQM_JWT_SECRET:xuqm-tenant-service-secret-key-must-be-at-least-256-bits-long-for-hmac} secret: ${XUQM_JWT_SECRET:xuqm-tenant-service-secret-key-must-be-at-least-256-bits-long-for-hmac}

查看文件

@ -0,0 +1,63 @@
CREATE TABLE IF NOT EXISTS push_user (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
user_id VARCHAR(128) NOT NULL,
nickname VARCHAR(64),
gender VARCHAR(16),
avatar VARCHAR(512),
status VARCHAR(16) NOT NULL,
created_at DATETIME(6) NOT NULL,
UNIQUE KEY uk_push_user (app_key, user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS push_device_token (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
user_id VARCHAR(128) NOT NULL,
vendor VARCHAR(16) NOT NULL,
token VARCHAR(512) NOT NULL,
platform VARCHAR(32),
device_id VARCHAR(128),
brand VARCHAR(64),
model VARCHAR(128),
os_version VARCHAR(64),
app_version VARCHAR(64),
receive_push BIT(1) NOT NULL DEFAULT 1,
last_login_at DATETIME(6),
created_at DATETIME(6) NOT NULL,
updated_at DATETIME(6) NOT NULL,
UNIQUE KEY uk_push_device_token (app_key, user_id, device_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS push_device_login_log (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
user_id VARCHAR(128) NOT NULL,
vendor VARCHAR(16) NOT NULL,
token_hash VARCHAR(128) NOT NULL,
token_preview VARCHAR(128) NOT NULL,
platform VARCHAR(32),
device_id VARCHAR(128) NOT NULL,
brand VARCHAR(64),
model VARCHAR(128),
os_version VARCHAR(64),
app_version VARCHAR(64),
receive_push BIT(1) NOT NULL,
event_type VARCHAR(32) NOT NULL,
created_at DATETIME(6) NOT NULL,
INDEX idx_push_device_log_user_time (app_key, user_id, created_at),
INDEX idx_push_device_log_token (token_hash)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS push_operation_log (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
operator VARCHAR(128) NOT NULL,
action VARCHAR(64) NOT NULL,
resource_type VARCHAR(64) NOT NULL,
resource_id VARCHAR(128),
summary VARCHAR(255),
detail TEXT,
created_at DATETIME(6) NOT NULL,
INDEX idx_push_op_log_app_time (app_key, created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

查看文件

@ -76,6 +76,14 @@
<artifactId>mysql-connector-j</artifactId> <artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>

查看文件

@ -17,7 +17,7 @@ spring:
max-lifetime: 900000 max-lifetime: 900000
jpa: jpa:
hibernate: hibernate:
ddl-auto: update ddl-auto: validate
show-sql: false show-sql: false
properties: properties:
hibernate: hibernate:
@ -52,6 +52,11 @@ spring:
time-zone: UTC time-zone: UTC
serialization: serialization:
write-dates-as-timestamps: false write-dates-as-timestamps: false
flyway:
enabled: true
baseline-on-migrate: true
baseline-version: 0
locations: classpath:db/migration
jwt: jwt:
secret: ${XUQM_JWT_SECRET:xuqm-tenant-service-secret-key-must-be-at-least-256-bits-long-for-hmac} secret: ${XUQM_JWT_SECRET:xuqm-tenant-service-secret-key-must-be-at-least-256-bits-long-for-hmac}

查看文件

@ -0,0 +1,131 @@
CREATE TABLE IF NOT EXISTS t_tenant (
id VARCHAR(255) NOT NULL PRIMARY KEY,
username VARCHAR(64) NOT NULL,
password VARCHAR(128) NOT NULL,
email VARCHAR(128) NOT NULL,
nickname VARCHAR(64) NOT NULL,
phone VARCHAR(32),
type VARCHAR(16) NOT NULL,
status VARCHAR(20) NOT NULL,
parent_id VARCHAR(64),
created_at DATETIME(6) NOT NULL,
UNIQUE KEY uk_t_tenant_username (username),
UNIQUE KEY uk_t_tenant_email (email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS t_app (
id VARCHAR(255) NOT NULL PRIMARY KEY,
tenant_id VARCHAR(64) NOT NULL,
package_name VARCHAR(128) NOT NULL,
ios_bundle_id VARCHAR(128),
harmony_bundle_name VARCHAR(128),
name VARCHAR(128) NOT NULL,
description VARCHAR(512),
icon_url VARCHAR(512),
app_key VARCHAR(64) NOT NULL,
app_secret VARCHAR(128) NOT NULL,
created_at DATETIME(6) NOT NULL,
license_file_content VARCHAR(4096),
is_default BIT(1) DEFAULT 0,
deletable BIT(1) DEFAULT 1,
UNIQUE KEY uk_t_app_app_key (app_key)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS t_api_key (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
api_key VARCHAR(64) NOT NULL,
name VARCHAR(128),
enabled BIT(1) NOT NULL,
created_at DATETIME(6) NOT NULL,
UNIQUE KEY uk_t_api_key (api_key)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS t_feature_service (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
platform VARCHAR(16) NOT NULL,
service_type VARCHAR(16) NOT NULL,
enabled BIT(1) NOT NULL,
config TEXT,
secret_key VARCHAR(128) NOT NULL,
created_at DATETIME(6) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS t_operation_log (
id VARCHAR(255) NOT NULL PRIMARY KEY,
tenant_id VARCHAR(64) NOT NULL,
module_type VARCHAR(32) NOT NULL,
resource_type VARCHAR(64) NOT NULL,
resource_id VARCHAR(128),
action VARCHAR(64) NOT NULL,
operator VARCHAR(128),
detail_json TEXT,
summary VARCHAR(255),
ip_address VARCHAR(64),
created_at DATETIME(6) NOT NULL,
INDEX idx_t_op_log_tenant_time (tenant_id, created_at),
INDEX idx_t_op_log_tenant_module (tenant_id, module_type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS t_email_verification (
id VARCHAR(255) NOT NULL PRIMARY KEY,
email VARCHAR(128) NOT NULL,
code VARCHAR(16) NOT NULL,
purpose VARCHAR(32) NOT NULL,
used BIT(1) NOT NULL,
expires_at DATETIME(6) NOT NULL,
created_at DATETIME(6) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS t_migrate_key (
id VARCHAR(255) NOT NULL PRIMARY KEY,
tenant_id VARCHAR(64) NOT NULL,
key_hash VARCHAR(128) NOT NULL,
created_at DATETIME(6) NOT NULL,
expires_at DATETIME(6) NOT NULL,
used_at DATETIME(6)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS t_ops_admin (
id VARCHAR(255) NOT NULL PRIMARY KEY,
username VARCHAR(64) NOT NULL,
password VARCHAR(128) NOT NULL,
created_at DATETIME(6) NOT NULL,
email VARCHAR(128),
last_login_at DATETIME(6),
UNIQUE KEY uk_t_ops_admin_username (username),
UNIQUE KEY uk_t_ops_admin_email (email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS t_risk_config (
id VARCHAR(255) NOT NULL PRIMARY KEY,
ip_rate_limit INT NOT NULL,
login_fail_threshold INT NOT NULL,
login_lock_minutes INT NOT NULL,
abnormal_detection BIT(1) NOT NULL,
updated_at DATETIME(6) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS t_sensitive_word (
id VARCHAR(255) NOT NULL PRIMARY KEY,
word VARCHAR(256) NOT NULL,
level VARCHAR(16) NOT NULL,
category VARCHAR(64) NOT NULL,
enabled BIT(1) NOT NULL,
created_at DATETIME(6) NOT NULL,
updated_at DATETIME(6) NOT NULL,
UNIQUE KEY uk_t_sensitive_word (word)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS t_service_activation_request (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
platform VARCHAR(16) NOT NULL,
service_type VARCHAR(16) NOT NULL,
status VARCHAR(16) NOT NULL,
apply_reason VARCHAR(512),
review_note VARCHAR(512),
created_at DATETIME(6) NOT NULL,
reviewed_at DATETIME(6)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

查看文件

@ -68,6 +68,14 @@
<artifactId>mysql-connector-j</artifactId> <artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>

查看文件

@ -17,12 +17,17 @@ spring:
max-lifetime: 900000 max-lifetime: 900000
jpa: jpa:
hibernate: hibernate:
ddl-auto: update ddl-auto: validate
show-sql: false show-sql: false
servlet: servlet:
multipart: multipart:
max-file-size: 200MB max-file-size: 200MB
max-request-size: 200MB max-request-size: 200MB
flyway:
enabled: true
baseline-on-migrate: true
baseline-version: 0
locations: classpath:db/migration
jwt: jwt:
secret: ${XUQM_JWT_SECRET:xuqm-tenant-service-secret-key-must-be-at-least-256-bits-long-for-hmac} secret: ${XUQM_JWT_SECRET:xuqm-tenant-service-secret-key-must-be-at-least-256-bits-long-for-hmac}

查看文件

@ -0,0 +1,106 @@
CREATE TABLE IF NOT EXISTS update_app_version (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
platform VARCHAR(16) NOT NULL,
version_name VARCHAR(32) NOT NULL,
version_code INT NOT NULL,
download_url VARCHAR(512),
change_log TEXT,
force_update BIT(1) NOT NULL,
publish_status VARCHAR(16) NOT NULL,
store_submit_mode VARCHAR(16),
store_submit_scheduled_at DATETIME(6),
app_store_url VARCHAR(256),
market_url VARCHAR(256),
gray_enabled BIT(1) NOT NULL DEFAULT 0,
gray_percent INT NOT NULL DEFAULT 0,
scheduled_publish_at DATETIME(6),
store_submit_targets TEXT,
store_review_status TEXT,
auto_publish_after_review BIT(1) NOT NULL DEFAULT 0,
webhook_url VARCHAR(512),
gray_mode VARCHAR(24) NOT NULL DEFAULT 'PERCENT',
gray_member_ids TEXT,
gray_group_names TEXT,
extra_member_ids TEXT,
pending_store_publish_type VARCHAR(16),
pending_store_publish_scheduled_at DATETIME(6),
pending_store_publish_updated_at DATETIME(6),
package_name VARCHAR(256),
apk_hash VARCHAR(64),
created_at DATETIME(6) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS update_publish_config (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
config_json TEXT,
updated_at DATETIME(6) NOT NULL,
UNIQUE KEY uk_update_publish_config_app (app_key)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS update_store_config (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
store_type VARCHAR(16) NOT NULL,
config_json TEXT,
enabled BIT(1) NOT NULL DEFAULT 1,
updated_at DATETIME(6) NOT NULL,
UNIQUE KEY uk_update_store_config (app_key, store_type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS update_gray_member (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
user_id VARCHAR(128) NOT NULL,
name VARCHAR(128),
source VARCHAR(16) NOT NULL DEFAULT 'SYNC',
active BIT(1) NOT NULL DEFAULT 1,
extra_json VARCHAR(512),
updated_at DATETIME(6) NOT NULL,
UNIQUE KEY uk_update_gray_member (app_key, user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS update_gray_tag (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
tag_name VARCHAR(64) NOT NULL,
user_id VARCHAR(128) NOT NULL,
created_at DATETIME(6) NOT NULL,
UNIQUE KEY uk_update_gray_tag (app_key, tag_name, user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS update_rn_bundle (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
module_id VARCHAR(64) NOT NULL,
platform VARCHAR(16) NOT NULL,
version VARCHAR(32) NOT NULL,
bundle_url VARCHAR(512) NOT NULL,
md5 VARCHAR(64) NOT NULL,
min_common_version VARCHAR(32),
package_name VARCHAR(256),
note VARCHAR(512),
publish_status VARCHAR(16) NOT NULL,
publish_mode VARCHAR(16),
scheduled_publish_at DATETIME(6),
gray_enabled BIT(1) NOT NULL DEFAULT 0,
gray_percent INT NOT NULL DEFAULT 0,
gray_mode VARCHAR(24) NOT NULL DEFAULT 'PERCENT',
gray_member_ids TEXT,
gray_group_names TEXT,
extra_member_ids TEXT,
created_at DATETIME(6) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS update_operation_log (
id VARCHAR(255) NOT NULL PRIMARY KEY,
app_key VARCHAR(64) NOT NULL,
resource_type VARCHAR(32) NOT NULL,
resource_id VARCHAR(64) NOT NULL,
action VARCHAR(32) NOT NULL,
operator VARCHAR(128),
reason VARCHAR(1024),
detail_json TEXT,
created_at DATETIME(6) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;