294 lines
11 KiB
SQL
294 lines
11 KiB
SQL
CREATE TABLE settings (
|
|
key TEXT PRIMARY KEY,
|
|
value TEXT NOT NULL
|
|
);
|
|
|
|
CREATE TABLE servers (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL CHECK(char_length(btrim(name)) BETWEEN 1 AND 80),
|
|
region TEXT NOT NULL DEFAULT '',
|
|
group_name TEXT NOT NULL DEFAULT '默认',
|
|
tags TEXT NOT NULL DEFAULT '',
|
|
hidden BIGINT NOT NULL DEFAULT 0 CHECK(hidden IN (0, 1)),
|
|
sort_order BIGINT NOT NULL DEFAULT 0,
|
|
expires_at BIGINT,
|
|
traffic_limit BIGINT NOT NULL DEFAULT 0 CHECK(traffic_limit >= 0),
|
|
traffic_limit_type TEXT NOT NULL DEFAULT 'sum'
|
|
CHECK(traffic_limit_type IN ('sum', 'max', 'min', 'up', 'down')),
|
|
price DOUBLE PRECISION NOT NULL DEFAULT 0 CHECK(price BETWEEN 0 AND 1000000000),
|
|
billing_cycle BIGINT NOT NULL DEFAULT 30 CHECK(billing_cycle BETWEEN 0 AND 3650),
|
|
currency TEXT NOT NULL DEFAULT 'CNY' CHECK(currency ~ '^[A-Z]{3}$'),
|
|
auto_renewal BIGINT NOT NULL DEFAULT 0 CHECK(auto_renewal IN (0, 1)),
|
|
last_ip TEXT NOT NULL DEFAULT '',
|
|
ip_v4 TEXT NOT NULL DEFAULT '',
|
|
ip_v6 TEXT NOT NULL DEFAULT '',
|
|
network_interface TEXT NOT NULL DEFAULT '',
|
|
reset_day BIGINT NOT NULL DEFAULT 1 CHECK(reset_day BETWEEN 1 AND 31),
|
|
report_interval BIGINT NOT NULL DEFAULT 60 CHECK(report_interval BETWEEN 15 AND 3600),
|
|
collect_interval BIGINT NOT NULL DEFAULT 1 CHECK(collect_interval BETWEEN 1 AND 60),
|
|
rx_correction BIGINT NOT NULL DEFAULT 0,
|
|
tx_correction BIGINT NOT NULL DEFAULT 0,
|
|
agent_mirror TEXT NOT NULL DEFAULT '',
|
|
offline_notify_disabled BIGINT NOT NULL DEFAULT 0 CHECK(offline_notify_disabled IN (0, 1)),
|
|
auto_update BIGINT NOT NULL DEFAULT 1 CHECK(auto_update IN (0, 1)),
|
|
token_hash TEXT NOT NULL UNIQUE,
|
|
created_at BIGINT NOT NULL,
|
|
updated_at BIGINT NOT NULL,
|
|
CHECK(collect_interval <= report_interval),
|
|
CHECK((report_interval + collect_interval - 1) / collect_interval <= 720)
|
|
);
|
|
|
|
CREATE INDEX servers_sort ON servers(sort_order, created_at);
|
|
CREATE INDEX servers_public_sort ON servers(hidden, sort_order, created_at);
|
|
|
|
CREATE TABLE server_install_tokens (
|
|
token_hash TEXT PRIMARY KEY,
|
|
server_id TEXT NOT NULL REFERENCES servers(id) ON DELETE CASCADE,
|
|
created_at BIGINT NOT NULL
|
|
);
|
|
|
|
CREATE INDEX server_install_tokens_server ON server_install_tokens(server_id, created_at DESC);
|
|
|
|
CREATE TABLE metric_history (
|
|
server_id TEXT NOT NULL REFERENCES servers(id) ON DELETE CASCADE,
|
|
timestamp BIGINT NOT NULL,
|
|
cpu DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
load1 DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
load5 DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
load15 DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
mem_used BIGINT NOT NULL DEFAULT 0,
|
|
mem_total BIGINT NOT NULL DEFAULT 0,
|
|
swap_used BIGINT NOT NULL DEFAULT 0,
|
|
swap_total BIGINT NOT NULL DEFAULT 0,
|
|
disk_used BIGINT NOT NULL DEFAULT 0,
|
|
disk_total BIGINT NOT NULL DEFAULT 0,
|
|
net_in DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
net_out DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
net_rx_total BIGINT NOT NULL DEFAULT 0,
|
|
net_tx_total BIGINT NOT NULL DEFAULT 0,
|
|
uptime BIGINT NOT NULL DEFAULT 0,
|
|
processes BIGINT NOT NULL DEFAULT 0,
|
|
tcp_connections BIGINT NOT NULL DEFAULT 0,
|
|
udp_connections BIGINT NOT NULL DEFAULT 0,
|
|
gpu_usage DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
disk_read_bps DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
disk_write_bps DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
disk_read_iops DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
disk_write_iops DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
disk_await_ms DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
disk_utilization DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
sample_count BIGINT NOT NULL DEFAULT 1 CHECK(sample_count > 0),
|
|
first_timestamp BIGINT NOT NULL DEFAULT 0,
|
|
last_timestamp BIGINT NOT NULL DEFAULT 0,
|
|
cpu_min DOUBLE PRECISION,
|
|
cpu_max DOUBLE PRECISION,
|
|
mem_used_max BIGINT,
|
|
memory_avg DOUBLE PRECISION,
|
|
memory_min DOUBLE PRECISION,
|
|
disk_avg DOUBLE PRECISION,
|
|
disk_min DOUBLE PRECISION,
|
|
net_in_avg DOUBLE PRECISION,
|
|
net_in_min DOUBLE PRECISION,
|
|
net_out_avg DOUBLE PRECISION,
|
|
net_out_min DOUBLE PRECISION,
|
|
PRIMARY KEY(server_id, timestamp)
|
|
);
|
|
|
|
CREATE INDEX metric_history_time ON metric_history(timestamp);
|
|
|
|
CREATE TABLE server_latest_state (
|
|
server_id TEXT PRIMARY KEY REFERENCES servers(id) ON DELETE CASCADE,
|
|
latest_timestamp BIGINT NOT NULL,
|
|
latest_json TEXT NOT NULL DEFAULT '{}',
|
|
last_batch_id TEXT NOT NULL DEFAULT ''
|
|
);
|
|
|
|
CREATE TABLE admin_2fa (
|
|
username TEXT PRIMARY KEY,
|
|
totp_secret TEXT NOT NULL,
|
|
enabled BIGINT NOT NULL DEFAULT 1 CHECK(enabled IN (0, 1)),
|
|
created_at BIGINT NOT NULL
|
|
);
|
|
|
|
CREATE TABLE remote_tasks (
|
|
id TEXT PRIMARY KEY,
|
|
server_id TEXT NOT NULL REFERENCES servers(id) ON DELETE CASCADE,
|
|
command TEXT NOT NULL,
|
|
status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('pending', 'sent', 'success', 'failed')),
|
|
requested_by TEXT NOT NULL,
|
|
requested_at BIGINT NOT NULL,
|
|
started_at BIGINT,
|
|
completed_at BIGINT,
|
|
result TEXT NOT NULL DEFAULT '',
|
|
exit_code BIGINT
|
|
);
|
|
|
|
CREATE INDEX remote_tasks_server ON remote_tasks(server_id);
|
|
|
|
CREATE INDEX remote_tasks_status_completed
|
|
ON remote_tasks(status, completed_at);
|
|
|
|
CREATE INDEX remote_tasks_status_requested
|
|
ON remote_tasks(status, requested_at);
|
|
|
|
CREATE TABLE exchange_rates (
|
|
base_currency TEXT PRIMARY KEY,
|
|
rates_json TEXT NOT NULL,
|
|
source TEXT NOT NULL,
|
|
rate_date TEXT NOT NULL,
|
|
fetched_at BIGINT NOT NULL,
|
|
attempted_at BIGINT NOT NULL
|
|
);
|
|
|
|
CREATE TABLE sessions (
|
|
id TEXT PRIMARY KEY,
|
|
token_hash TEXT NOT NULL UNIQUE,
|
|
username TEXT NOT NULL,
|
|
ip_address TEXT NOT NULL DEFAULT '',
|
|
user_agent TEXT NOT NULL DEFAULT '',
|
|
created_at BIGINT NOT NULL,
|
|
last_seen_at BIGINT NOT NULL,
|
|
expires_at BIGINT NOT NULL,
|
|
CHECK(last_seen_at >= created_at),
|
|
CHECK(expires_at > created_at)
|
|
);
|
|
|
|
CREATE INDEX sessions_expires_at ON sessions(expires_at);
|
|
CREATE INDEX sessions_user_activity ON sessions(username, last_seen_at DESC);
|
|
|
|
CREATE TABLE dashboard_proofs (
|
|
token_hash TEXT PRIMARY KEY,
|
|
created_at BIGINT NOT NULL,
|
|
expires_at BIGINT NOT NULL CHECK(expires_at > created_at)
|
|
);
|
|
|
|
CREATE INDEX dashboard_proofs_expires_at ON dashboard_proofs(expires_at);
|
|
|
|
CREATE TABLE server_traffic_state (
|
|
server_id TEXT PRIMARY KEY REFERENCES servers(id) ON DELETE CASCADE,
|
|
cycle_key BIGINT NOT NULL DEFAULT 0,
|
|
reset_day BIGINT NOT NULL DEFAULT 1 CHECK(reset_day BETWEEN 1 AND 31),
|
|
timestamp BIGINT NOT NULL DEFAULT 0,
|
|
raw_rx BIGINT NOT NULL DEFAULT 0 CHECK(raw_rx >= 0),
|
|
raw_tx BIGINT NOT NULL DEFAULT 0 CHECK(raw_tx >= 0),
|
|
used_rx BIGINT NOT NULL DEFAULT 0 CHECK(used_rx >= 0),
|
|
used_tx BIGINT NOT NULL DEFAULT 0 CHECK(used_tx >= 0)
|
|
);
|
|
|
|
CREATE TABLE latency_tasks (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
task_type TEXT NOT NULL CHECK(task_type IN ('tcp', 'icmp')),
|
|
target TEXT NOT NULL,
|
|
port BIGINT CHECK(port IS NULL OR port BETWEEN 1 AND 65535),
|
|
interval_seconds BIGINT NOT NULL CHECK(interval_seconds BETWEEN 30 AND 3600),
|
|
default_enabled BIGINT NOT NULL DEFAULT 0 CHECK(default_enabled IN (0, 1)),
|
|
sort_order BIGINT NOT NULL DEFAULT 0,
|
|
created_at BIGINT NOT NULL,
|
|
updated_at BIGINT NOT NULL,
|
|
CHECK((task_type = 'tcp' AND port IS NOT NULL) OR (task_type = 'icmp' AND port IS NULL))
|
|
);
|
|
|
|
CREATE INDEX latency_tasks_sort ON latency_tasks(sort_order, created_at);
|
|
|
|
CREATE TABLE latency_task_servers (
|
|
task_id TEXT NOT NULL REFERENCES latency_tasks(id) ON DELETE CASCADE,
|
|
server_id TEXT NOT NULL REFERENCES servers(id) ON DELETE CASCADE,
|
|
assigned_at BIGINT NOT NULL,
|
|
PRIMARY KEY(task_id, server_id)
|
|
);
|
|
|
|
CREATE INDEX latency_task_servers_server ON latency_task_servers(server_id, task_id);
|
|
|
|
CREATE TABLE latency_results (
|
|
task_id TEXT NOT NULL REFERENCES latency_tasks(id) ON DELETE CASCADE,
|
|
server_id TEXT NOT NULL REFERENCES servers(id) ON DELETE CASCADE,
|
|
timestamp BIGINT NOT NULL,
|
|
latency_ms DOUBLE PRECISION NOT NULL CHECK(latency_ms >= -1),
|
|
packet_loss DOUBLE PRECISION NOT NULL CHECK(packet_loss BETWEEN 0 AND 100),
|
|
PRIMARY KEY(task_id, server_id, timestamp)
|
|
);
|
|
|
|
CREATE INDEX latency_results_server_time ON latency_results(server_id, timestamp DESC);
|
|
CREATE INDEX latency_results_time ON latency_results(timestamp);
|
|
|
|
CREATE TABLE alert_rules (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
metric TEXT NOT NULL CHECK(metric IN ('cpu', 'memory', 'disk', 'net_in', 'net_out')),
|
|
threshold DOUBLE PRECISION NOT NULL CHECK(threshold > 0),
|
|
duration_minutes BIGINT NOT NULL CHECK(duration_minutes BETWEEN 1 AND 1440),
|
|
aggregation TEXT NOT NULL CHECK(aggregation IN ('average', 'continuous')),
|
|
all_servers BIGINT NOT NULL DEFAULT 0 CHECK(all_servers IN (0, 1)),
|
|
enabled BIGINT NOT NULL DEFAULT 1 CHECK(enabled IN (0, 1)),
|
|
created_at BIGINT NOT NULL,
|
|
updated_at BIGINT NOT NULL
|
|
);
|
|
|
|
CREATE INDEX alert_rules_created_at ON alert_rules(created_at);
|
|
|
|
CREATE TABLE alert_rule_servers (
|
|
rule_id TEXT NOT NULL REFERENCES alert_rules(id) ON DELETE CASCADE,
|
|
server_id TEXT NOT NULL REFERENCES servers(id) ON DELETE CASCADE,
|
|
PRIMARY KEY(rule_id, server_id)
|
|
);
|
|
|
|
CREATE INDEX alert_rule_servers_server ON alert_rule_servers(server_id, rule_id);
|
|
|
|
CREATE TABLE alert_states (
|
|
state_key TEXT PRIMARY KEY,
|
|
server_id TEXT NOT NULL REFERENCES servers(id) ON DELETE CASCADE,
|
|
rule_id TEXT REFERENCES alert_rules(id) ON DELETE CASCADE,
|
|
active BIGINT NOT NULL DEFAULT 0 CHECK(active IN (0, 1)),
|
|
updated_at BIGINT NOT NULL,
|
|
details_json TEXT NOT NULL DEFAULT '{}'
|
|
);
|
|
|
|
CREATE INDEX alert_states_active_time ON alert_states(active, updated_at);
|
|
CREATE INDEX alert_states_server ON alert_states(server_id);
|
|
CREATE INDEX alert_states_rule ON alert_states(rule_id);
|
|
|
|
CREATE TABLE notification_outbox (
|
|
id TEXT PRIMARY KEY,
|
|
state_key TEXT NOT NULL REFERENCES alert_states(state_key) ON DELETE CASCADE,
|
|
sequence BIGINT NOT NULL CHECK(sequence > 0),
|
|
title TEXT NOT NULL,
|
|
server_name TEXT NOT NULL,
|
|
message TEXT NOT NULL,
|
|
created_at BIGINT NOT NULL,
|
|
attempts BIGINT NOT NULL DEFAULT 0 CHECK(attempts >= 0),
|
|
next_attempt_at BIGINT NOT NULL,
|
|
UNIQUE(state_key, sequence)
|
|
);
|
|
|
|
CREATE INDEX notification_outbox_due ON notification_outbox(next_attempt_at, created_at);
|
|
|
|
CREATE TABLE notification_telegram (
|
|
id BIGINT PRIMARY KEY CHECK(id = 1),
|
|
bot_token TEXT NOT NULL,
|
|
chat_id TEXT NOT NULL,
|
|
message_thread_id BIGINT,
|
|
template TEXT NOT NULL,
|
|
updated_at BIGINT NOT NULL
|
|
);
|
|
|
|
CREATE TABLE themes (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
description TEXT NOT NULL DEFAULT '',
|
|
url TEXT NOT NULL UNIQUE,
|
|
resolved_url TEXT NOT NULL,
|
|
version TEXT NOT NULL DEFAULT '',
|
|
created_at BIGINT NOT NULL
|
|
);
|
|
|
|
CREATE INDEX themes_created_at ON themes(created_at DESC);
|
|
|
|
CREATE TABLE theme_previews (
|
|
token_hash TEXT PRIMARY KEY,
|
|
theme_id TEXT NOT NULL REFERENCES themes(id) ON DELETE CASCADE,
|
|
expires_at BIGINT NOT NULL
|
|
);
|
|
|
|
CREATE INDEX theme_previews_expires_at ON theme_previews(expires_at);
|