merge: maestro/tsk_tFMU7-hKzfOf [tsk_tFMU7-hKzfOf] codes 激活码模块
解决与 1A 骨架的冲突:module 统一为 github.com/wangjia/pangolin/server (codes 分支原用 pangolin/server,7 个源文件 import 已改写); go.mod require 并集(redis 取 9.20.1);Makefile 以骨架为基底并入 build-codegen/test-unit/test-integration target。 go build/vet 通过,codes 单测通过。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
-- Migration 001: baseline schema for the codes module and its dependencies.
|
||||
-- MySQL 8.x · InnoDB · utf8mb4 · UTC
|
||||
-- Apply with: mysql -u root -p pangolin < migrations/001_init.sql
|
||||
|
||||
SET time_zone = '+00:00';
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
-- Core account tables (needed by foreign keys from subscriptions)
|
||||
-- -------------------------------------------------------------------------
|
||||
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
uuid CHAR(36) NOT NULL UNIQUE, -- public-facing identifier
|
||||
email VARCHAR(255) NOT NULL UNIQUE,
|
||||
pw_hash VARCHAR(255) NOT NULL, -- argon2id
|
||||
dp_uuid CHAR(36) NOT NULL, -- data-plane UUID (sing-box)
|
||||
status ENUM('active','banned') NOT NULL DEFAULT 'active',
|
||||
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
-- Plan catalogue (digital values per design/CLAUDE.md §7)
|
||||
-- -------------------------------------------------------------------------
|
||||
|
||||
CREATE TABLE IF NOT EXISTS plans (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
code ENUM('free','pro','team') NOT NULL UNIQUE,
|
||||
max_devices INT NOT NULL, -- free 1 / pro 5 / team 10
|
||||
daily_minutes INT NULL, -- free 10; NULL = unlimited
|
||||
ad_gate BOOLEAN NOT NULL DEFAULT FALSE -- free users must watch an ad daily
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
INSERT IGNORE INTO plans (code, max_devices, daily_minutes, ad_gate) VALUES
|
||||
('free', 1, 10, TRUE),
|
||||
('pro', 5, NULL, FALSE),
|
||||
('team', 10, NULL, FALSE);
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
-- Subscriptions
|
||||
-- -------------------------------------------------------------------------
|
||||
|
||||
CREATE TABLE IF NOT EXISTS subscriptions (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id BIGINT UNSIGNED NOT NULL,
|
||||
plan_id BIGINT UNSIGNED NOT NULL,
|
||||
expires_at DATETIME(6) NOT NULL,
|
||||
source ENUM('trial','code') NOT NULL,
|
||||
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||
FOREIGN KEY (user_id) REFERENCES users(id),
|
||||
FOREIGN KEY (plan_id) REFERENCES plans(id),
|
||||
INDEX idx_user_exp (user_id, expires_at)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
-- Activation-code tables
|
||||
-- -------------------------------------------------------------------------
|
||||
|
||||
CREATE TABLE IF NOT EXISTS code_batches (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
channel ENUM('store','tg','line','manual') NOT NULL,
|
||||
created_by VARCHAR(64) NOT NULL,
|
||||
note VARCHAR(255) NULL,
|
||||
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS codes (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
-- SHA-256(canonical_plaintext) stored as 64-char hex.
|
||||
-- Plaintext NEVER stored in any column.
|
||||
code_hash CHAR(64) NOT NULL UNIQUE,
|
||||
plan_id BIGINT UNSIGNED NOT NULL,
|
||||
duration_days INT NOT NULL,
|
||||
batch_id BIGINT UNSIGNED NOT NULL,
|
||||
status ENUM('unused','redeemed','void') NOT NULL DEFAULT 'unused',
|
||||
redeemed_by BIGINT UNSIGNED NULL, -- FK to users.id (not enforced to avoid
|
||||
redeemed_at DATETIME(6) NULL, -- locking the users table on redeem)
|
||||
FOREIGN KEY (plan_id) REFERENCES plans(id),
|
||||
FOREIGN KEY (batch_id) REFERENCES code_batches(id),
|
||||
INDEX idx_status (status)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
-- Audit log (all sensitive operations must be recorded)
|
||||
-- -------------------------------------------------------------------------
|
||||
|
||||
CREATE TABLE IF NOT EXISTS audit_log (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
actor VARCHAR(64) NOT NULL, -- e.g. "user:123" or "admin:7"
|
||||
action VARCHAR(64) NOT NULL, -- e.g. "redeem", "ban", "node_drain"
|
||||
target VARCHAR(128) NOT NULL, -- abbreviated; never contains plaintext codes
|
||||
meta JSON NULL, -- structured context (no PII beyond IDs)
|
||||
at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||
INDEX idx_at (at)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
Reference in New Issue
Block a user