Полный продакшен-рефактор fix25: split peer/admin, удаление legacy, шифрование secret, auth_id, новые API/роуты и зачистка subscription

This commit is contained in:
2026-05-09 00:27:45 +05:00
parent e60594e09e
commit d73bab99ec
34 changed files with 930 additions and 1673 deletions
+106 -68
View File
@@ -1,70 +1,108 @@
CREATE TABLE IF NOT EXISTS account
(
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL UNIQUE DEFAULT '',
pass TEXT NOT NULL DEFAULT '',
con_pass TEXT NOT NULL DEFAULT '',
quota INTEGER NOT NULL DEFAULT 0,
download INTEGER NOT NULL DEFAULT 0,
upload INTEGER NOT NULL DEFAULT 0,
expire_time INTEGER NOT NULL DEFAULT 0,
kick_util_time INTEGER NOT NULL DEFAULT 0,
device_no INTEGER NOT NULL DEFAULT 3,
role TEXT NOT NULL DEFAULT 'user',
deleted INTEGER NOT NULL DEFAULT 0,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
-- Reference schema only. Runtime schema is managed by dao/sqlite.go migrations.
CREATE TABLE schema_migrations (
version TEXT PRIMARY KEY,
applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
ALTER TABLE account
ADD COLUMN login_at INTEGER NOT NULL DEFAULT 0;
ALTER TABLE account
ADD COLUMN con_at INTEGER NOT NULL DEFAULT 0;
ALTER TABLE account
ADD COLUMN remark INTEGER NOT NULL DEFAULT '';
CREATE INDEX IF NOT EXISTS account_deleted_index ON account (deleted);
CREATE INDEX IF NOT EXISTS account_username_index ON account (username);
CREATE INDEX IF NOT EXISTS account_con_pass_index ON account (con_pass);
CREATE INDEX IF NOT EXISTS account_pass_index ON account (pass);
CREATE TABLE IF NOT EXISTS config
(
id INTEGER PRIMARY KEY AUTOINCREMENT,
key TEXT NOT NULL UNIQUE DEFAULT '',
value TEXT NOT NULL DEFAULT '',
remark TEXT NOT NULL DEFAULT '',
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
CREATE TABLE config (
id INTEGER PRIMARY KEY AUTOINCREMENT,
key TEXT NOT NULL UNIQUE DEFAULT '',
value TEXT NOT NULL DEFAULT '',
remark TEXT NOT NULL DEFAULT '',
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS config_key_index ON config (key);
INSERT INTO config (key, value, remark)
SELECT 'H_UI_WEB_PORT', '8081', 'HY2XS admin Web Port'
WHERE NOT EXISTS (SELECT 1 FROM config WHERE key = 'H_UI_WEB_PORT');
INSERT INTO config (key, value, remark)
SELECT 'H_UI_WEB_CONTEXT', '/', 'HY2XS admin Web Context'
WHERE NOT EXISTS (SELECT 1 FROM config WHERE key = 'H_UI_WEB_CONTEXT');
INSERT INTO config (key, value, remark)
SELECT 'H_UI_CRT_PATH', '', 'HY2XS admin CRT File Path'
WHERE NOT EXISTS (SELECT 1 FROM config WHERE key = 'H_UI_CRT_PATH');
INSERT INTO config (key, value, remark)
SELECT 'H_UI_KEY_PATH', '', 'HY2XS admin KEY File Path'
WHERE NOT EXISTS (SELECT 1 FROM config WHERE key = 'H_UI_KEY_PATH');
INSERT INTO config (key, value, remark)
SELECT 'JWT_SECRET', hex(randomblob(10)), 'JWT Secret'
WHERE NOT EXISTS (SELECT 1 FROM config WHERE key = 'JWT_SECRET');
INSERT INTO config (key, value, remark)
SELECT 'HYSTERIA2_ENABLE', '0', 'Hysteria2 Switch'
WHERE NOT EXISTS (SELECT 1 FROM config WHERE key = 'HYSTERIA2_ENABLE');
INSERT INTO config (key, value, remark)
SELECT 'HYSTERIA2_CONFIG', '', 'Hysteria2 Config'
WHERE NOT EXISTS (SELECT 1 FROM config WHERE key = 'HYSTERIA2_CONFIG');
INSERT INTO config (key, value, remark)
SELECT 'HYSTERIA2_TRAFFIC_TIME', '1', 'Hysteria2 Traffic Time'
WHERE NOT EXISTS (SELECT 1 FROM config WHERE key = 'HYSTERIA2_TRAFFIC_TIME');
INSERT INTO config (key, value, remark)
SELECT 'HYSTERIA2_CONFIG_REMARK', '', 'Hysteria2 Config Remark'
WHERE NOT EXISTS (SELECT 1 FROM config WHERE key = 'HYSTERIA2_CONFIG_REMARK');
INSERT INTO config (key, value, remark)
SELECT 'RESET_TRAFFIC_CRON', '', 'Reset Traffic Cron'
WHERE NOT EXISTS (SELECT 1 FROM config WHERE key = 'RESET_TRAFFIC_CRON');
INSERT INTO config (key, value, remark)
SELECT 'CLASH_EXTENSION', '', 'Clash Subscription Extension'
WHERE NOT EXISTS (SELECT 1 FROM config WHERE key = 'CLASH_EXTENSION');
CREATE INDEX config_key_index ON config (key);
CREATE TABLE admin_user (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL UNIQUE DEFAULT '',
password_hash TEXT NOT NULL DEFAULT '',
status INTEGER NOT NULL DEFAULT 1,
force_password_change INTEGER NOT NULL DEFAULT 0,
last_login_at INTEGER NOT NULL DEFAULT 0,
password_changed_at INTEGER NOT NULL DEFAULT 0,
token_version INTEGER NOT NULL DEFAULT 1,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX admin_user_username_index ON admin_user (username);
CREATE TABLE peer (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE DEFAULT '',
remark TEXT NOT NULL DEFAULT '',
auth_id TEXT NOT NULL UNIQUE DEFAULT '',
secret_digest TEXT NOT NULL UNIQUE DEFAULT '',
secret_ciphertext TEXT NOT NULL DEFAULT '',
quota_bytes INTEGER NOT NULL DEFAULT 0,
download_bytes INTEGER NOT NULL DEFAULT 0,
upload_bytes INTEGER NOT NULL DEFAULT 0,
expires_at INTEGER NOT NULL DEFAULT 0,
max_devices INTEGER NOT NULL DEFAULT 3,
disabled INTEGER NOT NULL DEFAULT 0,
banned_until INTEGER NOT NULL DEFAULT 0,
last_connection_at INTEGER NOT NULL DEFAULT 0,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX peer_name_index ON peer (name);
CREATE INDEX peer_auth_id_index ON peer (auth_id);
CREATE INDEX peer_secret_digest_index ON peer (secret_digest);
CREATE TABLE traffic_sample (
id INTEGER PRIMARY KEY AUTOINCREMENT,
peer_id INTEGER NOT NULL,
auth_id TEXT NOT NULL,
rx_bytes INTEGER NOT NULL DEFAULT 0,
tx_bytes INTEGER NOT NULL DEFAULT 0,
sampled_at INTEGER NOT NULL,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_traffic_sample_time ON traffic_sample(sampled_at);
CREATE INDEX idx_traffic_sample_peer_time ON traffic_sample(peer_id, sampled_at);
CREATE TABLE traffic_aggregate_hourly (
peer_id INTEGER NOT NULL,
hour_start INTEGER NOT NULL,
rx_bytes INTEGER NOT NULL DEFAULT 0,
tx_bytes INTEGER NOT NULL DEFAULT 0,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(peer_id, hour_start)
);
CREATE INDEX idx_traffic_hourly_hour_start ON traffic_aggregate_hourly(hour_start);
CREATE TABLE traffic_aggregate_daily (
peer_id INTEGER NOT NULL,
day_start INTEGER NOT NULL,
rx_bytes INTEGER NOT NULL DEFAULT 0,
tx_bytes INTEGER NOT NULL DEFAULT 0,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(peer_id, day_start)
);
CREATE INDEX idx_traffic_daily_day_start ON traffic_aggregate_daily(day_start);
CREATE TABLE metric_sample (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sampled_at INTEGER NOT NULL,
cpu_percent REAL NOT NULL DEFAULT 0,
load1 REAL NOT NULL DEFAULT 0,
mem_used_bytes INTEGER NOT NULL DEFAULT 0,
mem_total_bytes INTEGER NOT NULL DEFAULT 0,
mem_percent REAL NOT NULL DEFAULT 0,
disk_path TEXT NOT NULL DEFAULT '/',
disk_used_bytes INTEGER NOT NULL DEFAULT 0,
disk_total_bytes INTEGER NOT NULL DEFAULT 0,
disk_percent REAL NOT NULL DEFAULT 0,
hysteria_running INTEGER NOT NULL DEFAULT 0,
online_peers INTEGER NOT NULL DEFAULT 0,
online_devices INTEGER NOT NULL DEFAULT 0,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_metric_sample_time ON metric_sample(sampled_at);