Merge pull request #66 from perfect-panel/dev

Dev
This commit is contained in:
Ember Moth
2026-07-05 20:44:55 +08:00
committed by GitHub
81 changed files with 805 additions and 77 deletions
+3
View File
@@ -1 +1,4 @@
/target /target
AGENTS.md
LOGGING_DESIGN.md
MIGRATION_STRATEGY.md
@@ -0,0 +1,36 @@
-- 000001_init_schema.down.sql
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS `user_subscribe_log`;
DROP TABLE IF EXISTS `user_subscribe`;
DROP TABLE IF EXISTS `user_login_log`;
DROP TABLE IF EXISTS `user_gift_amount_log`;
DROP TABLE IF EXISTS `user_device`;
DROP TABLE IF EXISTS `user_commission_log`;
DROP TABLE IF EXISTS `user_balance_log`;
DROP TABLE IF EXISTS `user_auth_methods`;
DROP TABLE IF EXISTS `user`;
DROP TABLE IF EXISTS `traffic_log`;
DROP TABLE IF EXISTS `ticket_follow`;
DROP TABLE IF EXISTS `ticket`;
DROP TABLE IF EXISTS `system`;
DROP TABLE IF EXISTS `subscribe_type`;
DROP TABLE IF EXISTS `subscribe_group`;
DROP TABLE IF EXISTS `subscribe`;
DROP TABLE IF EXISTS `sms`;
DROP TABLE IF EXISTS `server_rule_group`;
DROP TABLE IF EXISTS `server_group`;
DROP TABLE IF EXISTS `server`;
DROP TABLE IF EXISTS `payment`;
DROP TABLE IF EXISTS `order`;
DROP TABLE IF EXISTS `message_log`;
DROP TABLE IF EXISTS `document`;
DROP TABLE IF EXISTS `coupon`;
DROP TABLE IF EXISTS `auth_method`;
DROP TABLE IF EXISTS `application_version`;
DROP TABLE IF EXISTS `application_config`;
DROP TABLE IF EXISTS `application`;
DROP TABLE IF EXISTS `announcement`;
DROP TABLE IF EXISTS `ads`;
SET FOREIGN_KEY_CHECKS = 1;
@@ -0,0 +1,21 @@
-- 000002_init_data.down.sql
SET
FOREIGN_KEY_CHECKS = 0;
DELETE
FROM `auth_method`
WHERE `id` IN (1, 2, 3, 4, 5, 6, 7, 8);
DELETE
FROM `payment`
WHERE `id` = -1;
DELETE
FROM `subscribe_type`
WHERE `id` IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);
DELETE
FROM `system`
WHERE `id` IN
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41);
SET
FOREIGN_KEY_CHECKS = 1;
@@ -0,0 +1,72 @@
-- migrations/02003_update_payment.down.sql
-- Purpose: Revert updates to payment and order tables
-- Author: PPanel Team, 2025-04-21
SET FOREIGN_KEY_CHECKS = 0;
-- Drop payment_id column from order table (if exists)
SET @column_exists = (SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'order'
AND COLUMN_NAME = 'payment_id');
SET @sql = IF(@column_exists > 0,
'ALTER TABLE `order` DROP COLUMN `payment_id`',
'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- Drop platform column from payment table (if exists)
SET @column_exists = (SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'payment'
AND COLUMN_NAME = 'platform');
SET @sql = IF(@column_exists > 0,
'ALTER TABLE `payment` DROP COLUMN `platform`',
'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- Drop description column from payment table (if exists)
SET @column_exists = (SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'payment'
AND COLUMN_NAME = 'description');
SET @sql = IF(@column_exists > 0,
'ALTER TABLE `payment` DROP COLUMN `description`',
'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- Drop token column from payment table (if exists)
SET @column_exists = (SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'payment'
AND COLUMN_NAME = 'token');
SET @sql = IF(@column_exists > 0,
'ALTER TABLE `payment` DROP COLUMN `token`',
'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- Optionally restore mark column (if needed, adjust definition as per original schema)
SET @column_exists = (SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'payment'
AND COLUMN_NAME = 'mark');
SET @sql = IF(@column_exists = 0,
'ALTER TABLE `payment` ADD COLUMN `mark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT \'Payment Mark\' AFTER `name`',
'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET FOREIGN_KEY_CHECKS = 1;
@@ -0,0 +1,4 @@
-- migrations/02003_rebuild_rule.up.sql
-- Purpose: Back rebuilding server rule table
-- Author: PPanel Team, 2025-04-21
DROP TABLE IF EXISTS server_rule_group;
@@ -0,0 +1,52 @@
-- migrations/02004_create_user_device_online_record.down.sql
-- Purpose: Drop user device online record table
-- Author: PPanel Team, 2025-04-22
DROP TABLE IF EXISTS `user_device_online_record`;
-- User subscribe table migration for removing finished_at column
SET @column_exists = (SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'user_subscribe'
AND COLUMN_NAME = 'finished_at');
SET @sql = IF(@column_exists > 0,
'ALTER TABLE `user_subscribe` DROP COLUMN `finished_at`',
'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- Application config table migration for removing invitation_link column
SET @column_exists = (SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'application_config'
AND COLUMN_NAME = 'invitation_link');
SET @sql = IF(@column_exists > 0,
'ALTER TABLE `application_config` DROP COLUMN `invitation_link`',
'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- Application config table migration for removing kr_website_id column
SET @column_exists = (SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'application_config'
AND COLUMN_NAME = 'kr_website_id');
SET @sql = IF(@column_exists > 0,
'ALTER TABLE `application_config` DROP COLUMN `kr_website_id`',
'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
@@ -0,0 +1,5 @@
-- migrations/02008_create_user_reset_subscribe_log.down.sql
-- Purpose: Drop user_reset_subscribe_log table
-- Author: PPanel Team, 2025-04-22
DROP TABLE IF EXISTS `user_reset_subscribe_log`;
@@ -0,0 +1,3 @@
ALTER TABLE `server_rule_group`
DROP COLUMN `default`,
DROP COLUMN `type`;
+1
View File
@@ -0,0 +1 @@
DROP TABLE IF EXISTS `email_task`;
@@ -0,0 +1 @@
DROP TABLE IF EXISTS `subscribe_application`;
+106
View File
@@ -0,0 +1,106 @@
CREATE TABLE IF NOT EXISTS `user_balance_log`
(
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL COMMENT 'User ID',
`amount` bigint NOT NULL COMMENT 'Amount',
`type` tinyint(1) NOT NULL COMMENT 'Type: 1: Recharge 2: Withdraw 3: Payment 4: Refund 5: Reward',
`order_id` bigint DEFAULT NULL COMMENT 'Order ID',
`balance` bigint NOT NULL COMMENT 'Balance',
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci;
CREATE TABLE IF NOT EXISTS `user_commission_log`
(
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL COMMENT 'User ID',
`order_no` varchar(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'Order No.',
`amount` bigint NOT NULL COMMENT 'Amount',
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci;
CREATE TABLE IF NOT EXISTS `user_gift_amount_log`
(
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL COMMENT 'User ID',
`user_subscribe_id` bigint DEFAULT NULL COMMENT 'Deduction User Subscribe ID',
`order_no` varchar(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'Order No.',
`type` tinyint(1) NOT NULL COMMENT 'Type: 1: Increase 2: Reduce',
`amount` bigint NOT NULL COMMENT 'Amount',
`balance` bigint NOT NULL COMMENT 'Balance',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT 'Remark',
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci;
CREATE TABLE IF NOT EXISTS `user_login_log`
(
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL COMMENT 'User ID',
`login_ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'Login IP',
`user_agent` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'UserAgent',
`success` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Login Success',
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci;
CREATE TABLE IF NOT EXISTS `user_reset_subscribe_log`
(
`id` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`user_id` BIGINT NOT NULL COMMENT 'User ID',
`type` TINYINT(1) NOT NULL COMMENT 'Type: 1: Auto 2: Advance 3: Paid',
`order_no` VARCHAR(255) DEFAULT NULL COMMENT 'Order No.',
`user_subscribe_id` BIGINT NOT NULL COMMENT 'User Subscribe ID',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Creation Time',
INDEX `idx_user_id` (`user_id`),
INDEX `idx_user_subscribe_id` (`user_subscribe_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci;
CREATE TABLE IF NOT EXISTS `user_subscribe_log`
(
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL COMMENT 'User ID',
`user_subscribe_id` bigint NOT NULL COMMENT 'User Subscribe ID',
`token` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'Token',
`ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'IP',
`user_agent` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'UserAgent',
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_user_subscribe_id` (`user_subscribe_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci;
CREATE TABLE IF NOT EXISTS `message_log`
(
`id` bigint NOT NULL AUTO_INCREMENT,
`type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'email' COMMENT 'Message Type',
`platform` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'smtp' COMMENT 'Platform',
`to` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'To',
`subject` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Subject',
`content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 'Content',
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Status',
`created_at` datetime(3) DEFAULT NULL COMMENT 'Create Time',
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci;
DROP TABLE IF EXISTS `system_logs`;
+2
View File
@@ -0,0 +1,2 @@
DROP TABLE IF EXISTS `nodes`;
DROP TABLE IF EXISTS `servers`;
@@ -0,0 +1,5 @@
ALTER TABLE `subscribe`
DROP COLUMN `nodes`,
DROP COLUMN `node_tags`,
ADD COLUMN `server` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'Server',
ADD COLUMN `server_group` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'Server Group';
@@ -0,0 +1,3 @@
ALTER TABLE `user`
DROP COLUMN `referral_percentage`,
DROP COLUMN `only_first_purchase`;
@@ -0,0 +1,2 @@
ALTER TABLE `nodes`
DROP COLUMN `sort`;
@@ -0,0 +1 @@
DROP INDEX idx_traffic_log_time_user_sub ON traffic_log;
@@ -0,0 +1,2 @@
DROP TABLE IF EXISTS `subscribe_type`;
DROP TABLE IF EXISTS `sms`;
View File
@@ -0,0 +1,3 @@
ALTER TABLE `user`
DROP COLUMN `algo`,
DROP COLUMN `salt`;
@@ -0,0 +1,7 @@
INSERT INTO `system` (`category`, `key`, `value`, `type`, `desc`, `created_at`, `updated_at`)
SELECT 'site', 'CustomData', '{
"kr_website_id": ""
}', 'string', 'Custom Data', '2025-04-22 14:25:16.637', '2025-10-14 15:47:19.187'
WHERE NOT EXISTS (
SELECT 1 FROM `system` WHERE `category` = 'site' AND `key` = 'CustomData'
);
@@ -0,0 +1 @@
ALTER TABLE traffic_log DROP INDEX idx_timestamp;
@@ -0,0 +1,2 @@
ALTER TABLE `user_subscribe`
DROP COLUMN `note`;
@@ -0,0 +1,2 @@
ALTER TABLE `user`
DROP COLUMN IF EXISTS `rules`;
@@ -0,0 +1,5 @@
DROP TABLE IF EXISTS `withdrawals`;
DELETE FROM `system`
WHERE `category` = 'invite'
AND `key` = 'WithdrawalMethod';
+27
View File
@@ -0,0 +1,27 @@
CREATE TABLE IF NOT EXISTS `server`
(
`id` bigint NOT NULL AUTO_INCREMENT,
`name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Node Name',
`tags` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Tags',
`country` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Country',
`city` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'City',
`latitude` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'latitude',
`longitude` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'longitude',
`server_addr` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Server Address',
`relay_mode` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'none' COMMENT 'Relay Mode',
`relay_node` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 'Relay Node',
`speed_limit` bigint NOT NULL DEFAULT '0' COMMENT 'Speed Limit',
`traffic_ratio` decimal(4, 2) NOT NULL DEFAULT '0.00' COMMENT 'Traffic Ratio',
`group_id` bigint DEFAULT NULL COMMENT 'Group ID',
`protocol` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Protocol',
`config` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 'Config',
`enable` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Enabled',
`sort` bigint NOT NULL DEFAULT '0' COMMENT 'Sort',
`last_reported_at` datetime(3) DEFAULT NULL COMMENT 'Last Reported Time',
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
PRIMARY KEY (`id`),
KEY `idx_group_id` (`group_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci;
@@ -0,0 +1,2 @@
ALTER TABLE `subscribe`
DROP COLUMN `show_original_price`;
@@ -0,0 +1,5 @@
-- This migration script reverts the inventory values in the 'subscribe' table
UPDATE `subscribe`
SET `inventory` = 0
WHERE `inventory` = -1;
@@ -0,0 +1 @@
DROP INDEX idx_type_date ON system_logs;
@@ -0,0 +1,131 @@
SET @index_exists = (SELECT COUNT(1)
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'nodes'
AND INDEX_NAME = 'idx_nodes_port');
SET @sql = IF(@index_exists > 0,
'ALTER TABLE `nodes` DROP INDEX `idx_nodes_port`',
'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @index_exists = (SELECT COUNT(1)
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'nodes'
AND INDEX_NAME = 'idx_nodes_tags');
SET @sql = IF(@index_exists > 0,
'ALTER TABLE `nodes` DROP INDEX `idx_nodes_tags`',
'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @index_exists = (SELECT COUNT(1)
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'nodes'
AND INDEX_NAME = 'idx_nodes_address');
SET @sql = IF(@index_exists > 0,
'ALTER TABLE `nodes` DROP INDEX `idx_nodes_address`',
'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @index_exists = (SELECT COUNT(1)
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'nodes'
AND INDEX_NAME = 'idx_nodes_name');
SET @sql = IF(@index_exists > 0,
'ALTER TABLE `nodes` DROP INDEX `idx_nodes_name`',
'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @index_exists = (SELECT COUNT(1)
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'servers'
AND INDEX_NAME = 'idx_servers_address');
SET @sql = IF(@index_exists > 0,
'ALTER TABLE `servers` DROP INDEX `idx_servers_address`',
'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @index_exists = (SELECT COUNT(1)
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'servers'
AND INDEX_NAME = 'idx_servers_name');
SET @sql = IF(@index_exists > 0,
'ALTER TABLE `servers` DROP INDEX `idx_servers_name`',
'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @index_exists = (SELECT COUNT(1)
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'payment'
AND INDEX_NAME = 'idx_payment_name');
SET @sql = IF(@index_exists > 0,
'ALTER TABLE `payment` DROP INDEX `idx_payment_name`',
'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @index_exists = (SELECT COUNT(1)
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'coupon'
AND INDEX_NAME = 'idx_coupon_name');
SET @sql = IF(@index_exists > 0,
'ALTER TABLE `coupon` DROP INDEX `idx_coupon_name`',
'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @index_exists = (SELECT COUNT(1)
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'user'
AND INDEX_NAME = 'idx_user_refer_code');
SET @sql = IF(@index_exists > 0,
'ALTER TABLE `user` DROP INDEX `idx_user_refer_code`',
'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @index_exists = (SELECT COUNT(1)
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'order'
AND INDEX_NAME = 'idx_order_coupon');
SET @sql = IF(@index_exists > 0,
'ALTER TABLE `order` DROP INDEX `idx_order_coupon`',
'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @index_exists = (SELECT COUNT(1)
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'order'
AND INDEX_NAME = 'idx_order_trade_no');
SET @sql = IF(@index_exists > 0,
'ALTER TABLE `order` DROP INDEX `idx_order_trade_no`',
'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
@@ -0,0 +1 @@
DROP TABLE IF EXISTS `server_config_overrides`;
@@ -0,0 +1,17 @@
SET @column_exists = (
SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'payment'
AND COLUMN_NAME = 'sort'
);
SET @sql = IF(
@column_exists > 0,
'ALTER TABLE `payment` DROP COLUMN `sort`',
'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
@@ -0,0 +1 @@
DELETE FROM `system` WHERE `category` = 'subscribe' AND `key` = 'ShowTutorial';
@@ -0,0 +1 @@
SELECT 1;
@@ -0,0 +1,32 @@
-- 000001_init_schema.down.sql
DROP TABLE IF EXISTS "user_subscribe_log";
DROP TABLE IF EXISTS "user_subscribe";
DROP TABLE IF EXISTS "user_login_log";
DROP TABLE IF EXISTS "user_gift_amount_log";
DROP TABLE IF EXISTS "user_device";
DROP TABLE IF EXISTS "user_commission_log";
DROP TABLE IF EXISTS "user_balance_log";
DROP TABLE IF EXISTS "user_auth_methods";
DROP TABLE IF EXISTS "user";
DROP TABLE IF EXISTS "traffic_log";
DROP TABLE IF EXISTS "ticket_follow";
DROP TABLE IF EXISTS "ticket";
DROP TABLE IF EXISTS "system";
DROP TABLE IF EXISTS "subscribe_type";
DROP TABLE IF EXISTS "subscribe_group";
DROP TABLE IF EXISTS "subscribe";
DROP TABLE IF EXISTS "sms";
DROP TABLE IF EXISTS "server_rule_group";
DROP TABLE IF EXISTS "server_group";
DROP TABLE IF EXISTS "server";
DROP TABLE IF EXISTS "payment";
DROP TABLE IF EXISTS "order";
DROP TABLE IF EXISTS "message_log";
DROP TABLE IF EXISTS "document";
DROP TABLE IF EXISTS "coupon";
DROP TABLE IF EXISTS "auth_method";
DROP TABLE IF EXISTS "application_version";
DROP TABLE IF EXISTS "application_config";
DROP TABLE IF EXISTS "application";
DROP TABLE IF EXISTS "announcement";
DROP TABLE IF EXISTS "ads";
@@ -0,0 +1,15 @@
-- 000002_init_data.down.sql
DELETE
FROM "auth_method"
WHERE "id" IN (1, 2, 3, 4, 5, 6, 7, 8);
DELETE
FROM "payment"
WHERE "id" = -1;
DELETE
FROM "subscribe_type"
WHERE "id" IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);
DELETE
FROM "system"
WHERE "id" IN
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41);
@@ -0,0 +1,5 @@
ALTER TABLE "order" DROP COLUMN IF EXISTS "payment_id";
ALTER TABLE "payment" DROP COLUMN IF EXISTS "platform";
ALTER TABLE "payment" DROP COLUMN IF EXISTS "description";
ALTER TABLE "payment" DROP COLUMN IF EXISTS "token";
ALTER TABLE "payment" ADD COLUMN IF NOT EXISTS "mark" VARCHAR(255) DEFAULT NULL;
@@ -0,0 +1,4 @@
-- migrations/02003_rebuild_rule.up.sql
-- Purpose: Back rebuilding server rule table
-- Author: PPanel Team, 2025-04-21
DROP TABLE IF EXISTS server_rule_group;
@@ -0,0 +1,4 @@
DROP TABLE IF EXISTS "user_device_online_record";
ALTER TABLE "user_subscribe" DROP COLUMN IF EXISTS "finished_at";
ALTER TABLE "application_config" DROP COLUMN IF EXISTS "invitation_link";
ALTER TABLE "application_config" DROP COLUMN IF EXISTS "kr_website_id";
@@ -0,0 +1,5 @@
-- migrations/02008_create_user_reset_subscribe_log.down.sql
-- Purpose: Drop user_reset_subscribe_log table
-- Author: PPanel Team, 2025-04-22
DROP TABLE IF EXISTS "user_reset_subscribe_log";
@@ -0,0 +1,3 @@
ALTER TABLE "server_rule_group"
DROP COLUMN "default",
DROP COLUMN "type";
+1
View File
@@ -0,0 +1 @@
DROP TABLE IF EXISTS "email_task";
@@ -0,0 +1 @@
DROP TABLE IF EXISTS "subscribe_application";
@@ -0,0 +1,85 @@
CREATE TABLE IF NOT EXISTS "user_balance_log"
(
"id" BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL,
"user_id" bigint NOT NULL,
"amount" bigint NOT NULL,
"type" SMALLINT NOT NULL,
"order_id" bigint DEFAULT NULL,
"balance" bigint NOT NULL,
"created_at" TIMESTAMP(3) DEFAULT NULL,
PRIMARY KEY ("id")
);
CREATE INDEX IF NOT EXISTS "user_balance_log_idx_user_id" ON "user_balance_log" ("user_id");
CREATE TABLE IF NOT EXISTS "user_commission_log"
(
"id" BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL,
"user_id" bigint NOT NULL,
"order_no" varchar(191) DEFAULT NULL,
"amount" bigint NOT NULL,
"created_at" TIMESTAMP(3) DEFAULT NULL,
PRIMARY KEY ("id")
);
CREATE INDEX IF NOT EXISTS "user_commission_log_idx_user_id" ON "user_commission_log" ("user_id");
CREATE TABLE IF NOT EXISTS "user_gift_amount_log"
(
"id" BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL,
"user_id" bigint NOT NULL,
"user_subscribe_id" bigint DEFAULT NULL,
"order_no" varchar(191) DEFAULT NULL,
"type" SMALLINT NOT NULL,
"amount" bigint NOT NULL,
"balance" bigint NOT NULL,
"remark" varchar(255) DEFAULT '',
"created_at" TIMESTAMP(3) DEFAULT NULL,
PRIMARY KEY ("id")
);
CREATE INDEX IF NOT EXISTS "user_gift_amount_log_idx_user_id" ON "user_gift_amount_log" ("user_id");
CREATE TABLE IF NOT EXISTS "user_login_log"
(
"id" BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL,
"user_id" bigint NOT NULL,
"login_ip" varchar(255) NOT NULL,
"user_agent" text NOT NULL,
"success" BOOLEAN NOT NULL DEFAULT false,
"created_at" TIMESTAMP(3) DEFAULT NULL,
PRIMARY KEY ("id")
);
CREATE INDEX IF NOT EXISTS "user_login_log_idx_user_id" ON "user_login_log" ("user_id");
CREATE TABLE IF NOT EXISTS "user_reset_subscribe_log"
(
"id" BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY,
"user_id" BIGINT NOT NULL,
"type" SMALLINT NOT NULL,
"order_no" VARCHAR(255) DEFAULT NULL,
"user_subscribe_id" BIGINT NOT NULL,
"created_at" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS "user_reset_subscribe_log_idx_user_id" ON "user_reset_subscribe_log" ("user_id");
CREATE INDEX IF NOT EXISTS "user_reset_subscribe_log_idx_user_subscribe_id" ON "user_reset_subscribe_log" ("user_subscribe_id");
CREATE TABLE IF NOT EXISTS "user_subscribe_log"
(
"id" BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL,
"user_id" bigint NOT NULL,
"user_subscribe_id" bigint NOT NULL,
"token" varchar(255) NOT NULL,
"ip" varchar(255) NOT NULL,
"user_agent" text NOT NULL,
"created_at" TIMESTAMP(3) DEFAULT NULL,
PRIMARY KEY ("id")
);
CREATE INDEX IF NOT EXISTS "user_subscribe_log_idx_user_id" ON "user_subscribe_log" ("user_id");
CREATE INDEX IF NOT EXISTS "user_subscribe_log_idx_user_subscribe_id" ON "user_subscribe_log" ("user_subscribe_id");
CREATE TABLE IF NOT EXISTS "message_log"
(
"id" BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL,
"type" varchar(50) NOT NULL DEFAULT 'email',
"platform" varchar(50) NOT NULL DEFAULT 'smtp',
"to" text NOT NULL,
"subject" varchar(255) NOT NULL DEFAULT '',
"content" text,
"status" SMALLINT NOT NULL DEFAULT '0',
"created_at" TIMESTAMP(3) DEFAULT NULL,
"updated_at" TIMESTAMP(3) DEFAULT NULL,
PRIMARY KEY ("id")
);
DROP TABLE IF EXISTS "system_logs";
+2
View File
@@ -0,0 +1,2 @@
DROP TABLE IF EXISTS "nodes";
DROP TABLE IF EXISTS "servers";
@@ -0,0 +1,5 @@
ALTER TABLE "subscribe"
DROP COLUMN "nodes",
DROP COLUMN "node_tags",
ADD COLUMN "server" VARCHAR(255) NOT NULL DEFAULT '' ,
ADD COLUMN "server_group" VARCHAR(255) NOT NULL DEFAULT '';
@@ -0,0 +1,3 @@
ALTER TABLE "user"
DROP COLUMN "referral_percentage",
DROP COLUMN "only_first_purchase";
@@ -0,0 +1,2 @@
ALTER TABLE "nodes"
DROP COLUMN "sort";
@@ -0,0 +1 @@
DROP INDEX IF EXISTS "idx_traffic_log_time_user_sub";
@@ -0,0 +1,2 @@
DROP TABLE IF EXISTS "subscribe_type";
DROP TABLE IF EXISTS "sms";
@@ -0,0 +1,2 @@
ALTER TABLE "user" DROP COLUMN IF EXISTS "algo";
ALTER TABLE "user" DROP COLUMN IF EXISTS "salt";
@@ -0,0 +1,7 @@
INSERT INTO "system" ("category", "key", "value", "type", "desc", "created_at", "updated_at")
SELECT 'site', 'CustomData', '{
"kr_website_id": ""
}', 'string', 'Custom Data', '2025-04-22 14:25:16.637', '2025-10-14 15:47:19.187'
WHERE NOT EXISTS (
SELECT 1 FROM "system" WHERE "category" = 'site' AND "key" = 'CustomData'
);
@@ -0,0 +1 @@
DROP INDEX IF EXISTS "idx_timestamp";
@@ -0,0 +1,2 @@
ALTER TABLE "user_subscribe"
DROP COLUMN "note";
@@ -0,0 +1,2 @@
ALTER TABLE "user"
DROP COLUMN IF EXISTS "rules";
@@ -0,0 +1,4 @@
DROP TABLE IF EXISTS "withdrawals";
DELETE FROM "system"
WHERE "category" = 'invite'
AND "key" = 'WithdrawalMethod';
+25
View File
@@ -0,0 +1,25 @@
CREATE TABLE IF NOT EXISTS "server"
(
"id" BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL,
"name" varchar(100) NOT NULL DEFAULT '',
"tags" varchar(128) NOT NULL DEFAULT '',
"country" varchar(128) NOT NULL DEFAULT '',
"city" varchar(128) NOT NULL DEFAULT '',
"latitude" varchar(128) NOT NULL DEFAULT '',
"longitude" varchar(128) NOT NULL DEFAULT '',
"server_addr" varchar(100) NOT NULL DEFAULT '',
"relay_mode" varchar(20) NOT NULL DEFAULT 'none',
"relay_node" text,
"speed_limit" bigint NOT NULL DEFAULT '0',
"traffic_ratio" decimal(4, 2) NOT NULL DEFAULT '0.00',
"group_id" bigint DEFAULT NULL,
"protocol" varchar(20) NOT NULL DEFAULT '',
"config" text,
"enable" SMALLINT NOT NULL DEFAULT '1',
"sort" bigint NOT NULL DEFAULT '0',
"last_reported_at" TIMESTAMP(3) DEFAULT NULL,
"created_at" TIMESTAMP(3) DEFAULT NULL,
"updated_at" TIMESTAMP(3) DEFAULT NULL,
PRIMARY KEY ("id")
);
CREATE INDEX IF NOT EXISTS "server_idx_group_id" ON "server" ("group_id");
@@ -0,0 +1,2 @@
ALTER TABLE "subscribe"
DROP COLUMN "show_original_price";
@@ -0,0 +1,4 @@
-- This migration script reverts the inventory values in the 'subscribe' table
UPDATE "subscribe"
SET "inventory" = 0
WHERE "inventory" = -1;
@@ -0,0 +1 @@
DROP INDEX IF EXISTS "idx_type_date";
@@ -0,0 +1,29 @@
DROP INDEX IF EXISTS "idx_system_logs_content_trgm";
DROP INDEX IF EXISTS "idx_ticket_description_trgm";
DROP INDEX IF EXISTS "idx_ticket_title_trgm";
DROP INDEX IF EXISTS "idx_subscribe_description_trgm";
DROP INDEX IF EXISTS "idx_subscribe_name_trgm";
DROP INDEX IF EXISTS "idx_document_content_trgm";
DROP INDEX IF EXISTS "idx_document_title_trgm";
DROP INDEX IF EXISTS "idx_announcement_content_trgm";
DROP INDEX IF EXISTS "idx_announcement_title_trgm";
DROP INDEX IF EXISTS "idx_ads_content_trgm";
DROP INDEX IF EXISTS "idx_ads_title_trgm";
DROP INDEX IF EXISTS "idx_nodes_port";
DROP INDEX IF EXISTS "idx_nodes_tags_pattern";
DROP INDEX IF EXISTS "idx_nodes_address_pattern";
DROP INDEX IF EXISTS "idx_nodes_name_pattern";
DROP INDEX IF EXISTS "idx_servers_address_pattern";
DROP INDEX IF EXISTS "idx_servers_name_pattern";
DROP INDEX IF EXISTS "idx_payment_name_pattern";
DROP INDEX IF EXISTS "idx_coupon_code_pattern";
DROP INDEX IF EXISTS "idx_coupon_name_pattern";
DROP INDEX IF EXISTS "idx_user_auth_identifier_pattern";
DROP INDEX IF EXISTS "idx_user_refer_code_pattern";
DROP INDEX IF EXISTS "idx_order_coupon_pattern";
DROP INDEX IF EXISTS "idx_order_trade_no_pattern";
DROP INDEX IF EXISTS "idx_order_order_no_pattern";
@@ -0,0 +1 @@
DROP TABLE IF EXISTS "server_config_overrides";
@@ -0,0 +1,2 @@
ALTER TABLE "payment"
DROP COLUMN IF EXISTS "sort";
@@ -0,0 +1 @@
DELETE FROM "system" WHERE "category" = 'subscribe' AND "key" = 'ShowTutorial';
@@ -0,0 +1,3 @@
ALTER TABLE "servers"
ALTER COLUMN "last_reported_at" TYPE timestamp(3)
USING "last_reported_at" AT TIME ZONE 'UTC';
+1
View File
@@ -3,6 +3,7 @@ use std::sync::Arc;
use axum::routing::get; use axum::routing::get;
use tracing_subscriber::layer::SubscriberExt as _; use tracing_subscriber::layer::SubscriberExt as _;
use tracing_subscriber::util::SubscriberInitExt as _; use tracing_subscriber::util::SubscriberInitExt as _;
use tracing_subscriber::Layer as _;
use tracing_subscriber::EnvFilter; use tracing_subscriber::EnvFilter;
pub mod adapter; pub mod adapter;
+23 -77
View File
@@ -1,20 +1,14 @@
//! OpenTelemetry provider initialisation — ported from `pkg/trace/agent.go`. //! OpenTelemetry provider initialisation — ported from `pkg/trace/agent.go`.
//! //!
//! This module only initialises the OTel `TracerProvider` and registers it as //! Currently only the stdout exporter is wired up. OTLP gRPC / HTTP support
//! the global OTel provider. It does NOT touch the `tracing` subscriber — the //! can be added once the opentelemetry-otlp 0.27 builder API is confirmed.
//! bridge layer (`tracing-opentelemetry`) is added in `main.rs` when building
//! the subscriber stack.
//! //!
//! Supported batchers (mirrors Go `kindJaeger` / `kindOtlpGrpc` / etc.): //! To enable: set `Trace.Batcher = "stdout"` in config (any non-empty batcher
//! - `"jaeger"` → OTLP gRPC (Jaeger v2 speaks native OTLP) //! with a non-empty endpoint also works; set `Trace.Disabled = true` to opt out).
//! - `"otlpgrpc"` → OTLP gRPC
//! - `"otlphttp"` → OTLP HTTP
//! - `"stdout"` → pretty-print to stdout
//! - disabled / empty endpoint → no-op
use opentelemetry::global; use opentelemetry::global;
use opentelemetry::trace::TracerProvider as _; use opentelemetry::KeyValue;
use opentelemetry_sdk::trace::{RandomIdGenerator, Sampler, TracerProvider}; use opentelemetry_sdk::trace::TracerProvider;
use opentelemetry_sdk::Resource; use opentelemetry_sdk::Resource;
use crate::config::TraceConfig; use crate::config::TraceConfig;
@@ -35,84 +29,36 @@ impl Drop for OtelGuard {
/// Build and install the OTel `TracerProvider`. /// Build and install the OTel `TracerProvider`.
/// ///
/// Returns `None` when tracing is disabled or no endpoint is configured. /// Returns `None` when tracing is disabled (config `Trace.Disabled = true`)
/// The caller must keep the returned `OtelGuard` alive for the process lifetime. /// or no batcher is configured.
pub fn init_otel(cfg: &TraceConfig) -> Option<OtelGuard> { pub fn init_otel(cfg: &TraceConfig) -> Option<OtelGuard> {
if cfg.disabled { if cfg.disabled {
return None; return None;
} }
if cfg.endpoint.is_empty() && cfg.batcher.as_str() != "stdout" { // Require explicit opt-in: batcher must be set.
if cfg.batcher.is_empty() || cfg.batcher == "none" {
return None; return None;
} }
let resource = Resource::builder() let resource = Resource::new(vec![KeyValue::new(
.with_service_name(cfg.name.clone()) opentelemetry_semantic_conventions::resource::SERVICE_NAME,
cfg.name.clone(),
)]);
// ── Exporter selection ────────────────────────────────────────────────
// Only stdout is wired for now; extend with OTLP branches as needed.
let exporter = opentelemetry_stdout::SpanExporter::default();
let provider = TracerProvider::builder()
.with_resource(resource)
.with_simple_exporter(exporter)
.build(); .build();
let sampler = if (cfg.sampler - 1.0_f64).abs() < f64::EPSILON {
Sampler::AlwaysOn
} else {
Sampler::TraceIdRatioBased(cfg.sampler)
};
let provider = match build_provider(cfg, resource, sampler) {
Ok(p) => p,
Err(e) => {
tracing::error!("[otel] failed to initialise TracerProvider: {e}");
return None;
}
};
global::set_tracer_provider(provider.clone()); global::set_tracer_provider(provider.clone());
tracing::info!( tracing::info!(
batcher = %cfg.batcher, batcher = %cfg.batcher,
endpoint = %cfg.endpoint, name = %cfg.name,
"OpenTelemetry tracing initialised", "OpenTelemetry tracing initialised",
); );
Some(OtelGuard { provider }) Some(OtelGuard { provider })
} }
// ─── private helpers ─────────────────────────────────────────────────────────
fn build_provider(
cfg: &TraceConfig,
resource: Resource,
sampler: Sampler,
) -> anyhow::Result<TracerProvider> {
use opentelemetry_sdk::trace::BatchExporter;
let exporter: BatchExporter = match cfg.batcher.as_str() {
"jaeger" | "otlpgrpc" => {
use opentelemetry_otlp::SpanExporter;
let exp = SpanExporter::builder()
.with_tonic()
.with_endpoint(&cfg.endpoint)
.build()
.map_err(|e| anyhow::anyhow!("otlpgrpc: {e}"))?;
BatchExporter::new(exp, opentelemetry_sdk::runtime::Tokio)
}
"otlphttp" => {
use opentelemetry_otlp::SpanExporter;
let mut b = SpanExporter::builder().with_http().with_endpoint(&cfg.endpoint);
if !cfg.otlp_headers.is_empty() {
b = b.with_headers(cfg.otlp_headers.clone());
}
let exp = b.build().map_err(|e| anyhow::anyhow!("otlphttp: {e}"))?;
BatchExporter::new(exp, opentelemetry_sdk::runtime::Tokio)
}
// stdout / default
_ => {
let exp = opentelemetry_stdout::SpanExporter::default();
BatchExporter::new(exp, opentelemetry_sdk::runtime::Tokio)
}
};
let provider = TracerProvider::builder()
.with_resource(resource)
.with_sampler(sampler)
.with_id_generator(RandomIdGenerator::default())
.with_span_processor(exporter)
.build();
Ok(provider)
}