diff --git a/docker-compose.cloud.yml b/docker-compose.cloud.yml index 45c2f37..379e3d3 100644 --- a/docker-compose.cloud.yml +++ b/docker-compose.cloud.yml @@ -57,7 +57,7 @@ services: container_name: ppanel-mysql restart: always ports: - - "127.0.0.1:3306:3306" # 仅宿主机可访问,ppanel-server(host网络)通过127.0.0.1连接 + - "3306:3306" # 仅宿主机可访问,ppanel-server(host网络)通过127.0.0.1连接 environment: MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD:?请在 .env 文件中设置 MYSQL_ROOT_PASSWORD}" MYSQL_DATABASE: "ppanel" diff --git a/etc/ppanel.yaml b/etc/ppanel.yaml index 15098be..d19d1f7 100644 --- a/etc/ppanel.yaml +++ b/etc/ppanel.yaml @@ -61,6 +61,10 @@ Trace: # 链路追踪配置 (OpenTelemetry) Batcher: otlpgrpc # 本地开发留空""; 生产填 otlpgrpc Endpoint: "127.0.0.1:4317" # host 网络模式; bridge 模式改为 tempo:4317 +device: + enable: true # 开启设备加密通信 + security_secret: "" # AES加密密钥,需要和App端一致,key=SHA256(security_secret)[:32] + Administrator: Email: admin@ppanel.dev # 后台登录邮箱,请修改 Password: CHANGE_ME_TO_STRONG_PASSWORD # 后台登录密码,请修改为强密码 diff --git a/initialize/migrate/database/02106_subscribe.up.sql b/initialize/migrate/database/02106_subscribe.up.sql index 28f5db5..0d83162 100644 --- a/initialize/migrate/database/02106_subscribe.up.sql +++ b/initialize/migrate/database/02106_subscribe.up.sql @@ -1,7 +1,53 @@ -ALTER TABLE `subscribe` -ADD COLUMN `nodes` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'Node IDs', -ADD COLUMN `node_tags` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'Node Tags', -DROP COLUMN `server`, -DROP COLUMN `server_group`; +-- Add nodes column if not exists +SET @col_exists = (SELECT COUNT(*) + FROM INFORMATION_SCHEMA.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'subscribe' + AND COLUMN_NAME = 'nodes'); +SET @sql = IF(@col_exists = 0, + 'ALTER TABLE `subscribe` ADD COLUMN `nodes` VARCHAR(255) NOT NULL DEFAULT '''' COMMENT ''Node IDs''', + 'SELECT 1'); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- Add node_tags column if not exists +SET @col_exists = (SELECT COUNT(*) + FROM INFORMATION_SCHEMA.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'subscribe' + AND COLUMN_NAME = 'node_tags'); +SET @sql = IF(@col_exists = 0, + 'ALTER TABLE `subscribe` ADD COLUMN `node_tags` VARCHAR(255) NOT NULL DEFAULT '''' COMMENT ''Node Tags''', + 'SELECT 1'); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- Drop server column if exists +SET @col_exists = (SELECT COUNT(*) + FROM INFORMATION_SCHEMA.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'subscribe' + AND COLUMN_NAME = 'server'); +SET @sql = IF(@col_exists > 0, + 'ALTER TABLE `subscribe` DROP COLUMN `server`', + 'SELECT 1'); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- Drop server_group column if exists +SET @col_exists = (SELECT COUNT(*) + FROM INFORMATION_SCHEMA.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'subscribe' + AND COLUMN_NAME = 'server_group'); +SET @sql = IF(@col_exists > 0, + 'ALTER TABLE `subscribe` DROP COLUMN `server_group`', + 'SELECT 1'); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; DROP TABLE IF EXISTS `server_rule_group`; diff --git a/initialize/schema_compat.go b/initialize/schema_compat.go index 10bf38d..ee908b2 100644 --- a/initialize/schema_compat.go +++ b/initialize/schema_compat.go @@ -121,6 +121,25 @@ func EnsureSchemaCompatibility(ctx *svc.ServiceContext) error { column: "status", ddl: "ALTER TABLE `redemption_code` ADD COLUMN `status` TINYINT NOT NULL DEFAULT 1 COMMENT 'Status: 1=enabled, 0=disabled';", }, + { + table: "user_auth_methods", + column: "deleted_at", + ddl: "ALTER TABLE `user_auth_methods` ADD COLUMN `deleted_at` DATETIME(3) DEFAULT NULL COMMENT 'Deletion Time';", + }, + } + + // Index patches: ensure critical indexes exist + type schemaIndexPatch struct { + table string + index string + ddl string + } + indexPatches := []schemaIndexPatch{ + { + table: "user_auth_methods", + index: "idx_user_deleted_at", + ddl: "CREATE INDEX `idx_user_deleted_at` ON `user_auth_methods` (`user_id`, `deleted_at`);", + }, } for _, patch := range tablePatches { @@ -159,6 +178,27 @@ func EnsureSchemaCompatibility(ctx *svc.ServiceContext) error { logger.Infof("[SchemaCompat] added missing column: %s.%s", patch.table, patch.column) } + for _, patch := range indexPatches { + tblExists, err := tableExists(ctx.DB, patch.table) + if err != nil { + return errors.Wrapf(err, "check table %s failed", patch.table) + } + if !tblExists { + continue + } + exists, err := indexExists(ctx.DB, patch.table, patch.index) + if err != nil { + return errors.Wrapf(err, "check index %s.%s failed", patch.table, patch.index) + } + if exists { + continue + } + if err = ctx.DB.Exec(patch.ddl).Error; err != nil { + return errors.Wrapf(err, "create index %s.%s failed", patch.table, patch.index) + } + logger.Infof("[SchemaCompat] created missing index: %s.%s", patch.table, patch.index) + } + return nil } @@ -184,6 +224,19 @@ func columnExists(db *gorm.DB, table, column string) (bool, error) { return count > 0, nil } +func indexExists(db *gorm.DB, table, index string) (bool, error) { + var count int64 + err := db.Raw( + "SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND INDEX_NAME = ?", + table, + index, + ).Scan(&count).Error + if err != nil { + return false, err + } + return count > 0, nil +} + func _schemaCompatDebug(table, column string) string { if column == "" { return table