Phase 8: 完成多租户SaaS架构、订阅计费系统、企业级功能
- 任务1: 多租户SaaS架构 (tenant_manager.py) - 任务2: 订阅与计费系统 (subscription_manager.py) - 任务3: 企业级功能 (enterprise_manager.py) - 更新 schema.sql 添加所有相关表 - 更新 main.py 添加所有API端点 - 更新 README.md 进度表
This commit is contained in:
@@ -1060,125 +1060,349 @@ CREATE INDEX IF NOT EXISTS idx_usage_tenant ON tenant_usage(tenant_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_date ON tenant_usage(date);
|
||||
|
||||
-- ============================================
|
||||
-- Phase 8: Multi-Tenant SaaS Architecture
|
||||
-- Phase 8 Task 2: 订阅与计费系统
|
||||
-- ============================================
|
||||
|
||||
-- 租户主表
|
||||
CREATE TABLE IF NOT EXISTS tenants (
|
||||
-- 订阅计划表
|
||||
CREATE TABLE IF NOT EXISTS subscription_plans (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
slug TEXT UNIQUE NOT NULL, -- URL 友好的唯一标识
|
||||
description TEXT DEFAULT '',
|
||||
status TEXT DEFAULT 'active', -- active, suspended, trial, expired, pending
|
||||
plan TEXT DEFAULT 'free', -- free, starter, professional, enterprise
|
||||
max_projects INTEGER DEFAULT 5,
|
||||
max_members INTEGER DEFAULT 10,
|
||||
max_storage_gb REAL DEFAULT 1.0,
|
||||
max_api_calls_per_day INTEGER DEFAULT 1000,
|
||||
billing_email TEXT DEFAULT '',
|
||||
subscription_start TEXT,
|
||||
subscription_end TEXT,
|
||||
tier TEXT UNIQUE NOT NULL, -- free/pro/enterprise
|
||||
description TEXT,
|
||||
price_monthly REAL DEFAULT 0,
|
||||
price_yearly REAL DEFAULT 0,
|
||||
currency TEXT DEFAULT 'CNY',
|
||||
features TEXT DEFAULT '[]', -- JSON array
|
||||
limits TEXT DEFAULT '{}', -- JSON object
|
||||
is_active INTEGER DEFAULT 1,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
created_by TEXT DEFAULT '', -- 创建者用户ID
|
||||
db_schema TEXT DEFAULT '', -- 数据库 schema 名称
|
||||
table_prefix TEXT DEFAULT '' -- 表前缀
|
||||
metadata TEXT DEFAULT '{}'
|
||||
);
|
||||
|
||||
-- 租户域名绑定表
|
||||
CREATE TABLE IF NOT EXISTS tenant_domains (
|
||||
-- 订阅表
|
||||
CREATE TABLE IF NOT EXISTS subscriptions (
|
||||
id TEXT PRIMARY KEY,
|
||||
tenant_id TEXT NOT NULL,
|
||||
domain TEXT NOT NULL, -- 自定义域名
|
||||
status TEXT DEFAULT 'pending', -- pending, verified, active, failed, expired
|
||||
verification_record TEXT DEFAULT '', -- DNS TXT 记录值
|
||||
verification_expires_at TEXT,
|
||||
ssl_enabled INTEGER DEFAULT 0,
|
||||
ssl_cert_path TEXT,
|
||||
ssl_key_path TEXT,
|
||||
ssl_expires_at TEXT,
|
||||
plan_id TEXT NOT NULL,
|
||||
status TEXT DEFAULT 'pending', -- active/cancelled/expired/past_due/trial/pending
|
||||
current_period_start TIMESTAMP,
|
||||
current_period_end TIMESTAMP,
|
||||
cancel_at_period_end INTEGER DEFAULT 0,
|
||||
canceled_at TIMESTAMP,
|
||||
trial_start TIMESTAMP,
|
||||
trial_end TIMESTAMP,
|
||||
payment_provider TEXT, -- stripe/alipay/wechat/bank_transfer
|
||||
provider_subscription_id TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
verified_at TEXT,
|
||||
UNIQUE(tenant_id, domain),
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
metadata TEXT DEFAULT '{}',
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (plan_id) REFERENCES subscription_plans(id)
|
||||
);
|
||||
|
||||
-- 用量记录表
|
||||
CREATE TABLE IF NOT EXISTS usage_records (
|
||||
id TEXT PRIMARY KEY,
|
||||
tenant_id TEXT NOT NULL,
|
||||
resource_type TEXT NOT NULL, -- transcription/storage/api_call/export
|
||||
quantity REAL DEFAULT 0,
|
||||
unit TEXT NOT NULL, -- minutes/mb/count/page
|
||||
recorded_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
cost REAL DEFAULT 0,
|
||||
description TEXT,
|
||||
metadata TEXT DEFAULT '{}',
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- 租户品牌配置表(白标)
|
||||
CREATE TABLE IF NOT EXISTS tenant_branding (
|
||||
-- 支付记录表
|
||||
CREATE TABLE IF NOT EXISTS payments (
|
||||
id TEXT PRIMARY KEY,
|
||||
tenant_id TEXT UNIQUE NOT NULL,
|
||||
logo_url TEXT,
|
||||
logo_dark_url TEXT, -- 深色模式 Logo
|
||||
favicon_url TEXT,
|
||||
primary_color TEXT DEFAULT '#3B82F6',
|
||||
secondary_color TEXT DEFAULT '#10B981',
|
||||
accent_color TEXT DEFAULT '#F59E0B',
|
||||
background_color TEXT DEFAULT '#FFFFFF',
|
||||
text_color TEXT DEFAULT '#1F2937',
|
||||
dark_primary_color TEXT DEFAULT '#60A5FA',
|
||||
dark_background_color TEXT DEFAULT '#111827',
|
||||
dark_text_color TEXT DEFAULT '#F9FAFB',
|
||||
font_family TEXT DEFAULT 'Inter, system-ui, sans-serif',
|
||||
heading_font_family TEXT,
|
||||
custom_css TEXT DEFAULT '',
|
||||
custom_js TEXT DEFAULT '',
|
||||
app_name TEXT DEFAULT 'InsightFlow',
|
||||
login_page_title TEXT DEFAULT '登录到 InsightFlow',
|
||||
login_page_description TEXT DEFAULT '',
|
||||
footer_text TEXT DEFAULT '© 2024 InsightFlow',
|
||||
tenant_id TEXT NOT NULL,
|
||||
subscription_id TEXT,
|
||||
invoice_id TEXT,
|
||||
amount REAL NOT NULL,
|
||||
currency TEXT DEFAULT 'CNY',
|
||||
provider TEXT NOT NULL, -- stripe/alipay/wechat/bank_transfer
|
||||
provider_payment_id TEXT,
|
||||
status TEXT DEFAULT 'pending', -- pending/processing/completed/failed/refunded/partial_refunded
|
||||
payment_method TEXT,
|
||||
payment_details TEXT DEFAULT '{}', -- JSON
|
||||
paid_at TIMESTAMP,
|
||||
failed_at TIMESTAMP,
|
||||
failure_reason TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (subscription_id) REFERENCES subscriptions(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (invoice_id) REFERENCES invoices(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
-- 发票表
|
||||
CREATE TABLE IF NOT EXISTS invoices (
|
||||
id TEXT PRIMARY KEY,
|
||||
tenant_id TEXT NOT NULL,
|
||||
subscription_id TEXT,
|
||||
invoice_number TEXT UNIQUE NOT NULL,
|
||||
status TEXT DEFAULT 'draft', -- draft/issued/paid/overdue/void/credit_note
|
||||
amount_due REAL DEFAULT 0,
|
||||
amount_paid REAL DEFAULT 0,
|
||||
currency TEXT DEFAULT 'CNY',
|
||||
period_start TIMESTAMP,
|
||||
period_end TIMESTAMP,
|
||||
description TEXT,
|
||||
line_items TEXT DEFAULT '[]', -- JSON array
|
||||
due_date TIMESTAMP,
|
||||
paid_at TIMESTAMP,
|
||||
voided_at TIMESTAMP,
|
||||
void_reason TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (subscription_id) REFERENCES subscriptions(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
-- 退款表
|
||||
CREATE TABLE IF NOT EXISTS refunds (
|
||||
id TEXT PRIMARY KEY,
|
||||
tenant_id TEXT NOT NULL,
|
||||
payment_id TEXT NOT NULL,
|
||||
invoice_id TEXT,
|
||||
amount REAL NOT NULL,
|
||||
currency TEXT DEFAULT 'CNY',
|
||||
reason TEXT,
|
||||
status TEXT DEFAULT 'pending', -- pending/approved/rejected/completed/failed
|
||||
requested_by TEXT NOT NULL,
|
||||
requested_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
approved_by TEXT,
|
||||
approved_at TIMESTAMP,
|
||||
completed_at TIMESTAMP,
|
||||
provider_refund_id TEXT,
|
||||
metadata TEXT DEFAULT '{}',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (payment_id) REFERENCES payments(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (invoice_id) REFERENCES invoices(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
-- 账单历史表
|
||||
CREATE TABLE IF NOT EXISTS billing_history (
|
||||
id TEXT PRIMARY KEY,
|
||||
tenant_id TEXT NOT NULL,
|
||||
type TEXT NOT NULL, -- subscription/usage/payment/refund
|
||||
amount REAL NOT NULL,
|
||||
currency TEXT DEFAULT 'CNY',
|
||||
description TEXT,
|
||||
reference_id TEXT, -- 关联的订阅/支付/退款ID
|
||||
balance_after REAL DEFAULT 0,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
metadata TEXT DEFAULT '{}',
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- 订阅相关索引
|
||||
CREATE INDEX IF NOT EXISTS idx_subscriptions_tenant ON subscriptions(tenant_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_subscriptions_status ON subscriptions(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_subscriptions_plan ON subscriptions(plan_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_records_tenant ON usage_records(tenant_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_records_type ON usage_records(resource_type);
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_records_recorded ON usage_records(recorded_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_payments_tenant ON payments(tenant_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_payments_status ON payments(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_payments_provider ON payments(provider);
|
||||
CREATE INDEX IF NOT EXISTS idx_invoices_tenant ON invoices(tenant_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_invoices_status ON invoices(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_invoices_number ON invoices(invoice_number);
|
||||
CREATE INDEX IF NOT EXISTS idx_refunds_tenant ON refunds(tenant_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_refunds_status ON refunds(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_refunds_payment ON refunds(payment_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_billing_history_tenant ON billing_history(tenant_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_billing_history_created ON billing_history(created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_billing_history_type ON billing_history(type);
|
||||
|
||||
-- ============================================
|
||||
-- Phase 8 Task 3: 企业级功能
|
||||
-- ============================================
|
||||
|
||||
-- SSO 配置表
|
||||
CREATE TABLE IF NOT EXISTS sso_configs (
|
||||
id TEXT PRIMARY KEY,
|
||||
tenant_id TEXT NOT NULL,
|
||||
provider TEXT NOT NULL, -- wechat_work/dingtalk/feishu/okta/azure_ad/google/custom_saml
|
||||
status TEXT DEFAULT 'disabled', -- disabled/pending/active/error
|
||||
entity_id TEXT,
|
||||
sso_url TEXT,
|
||||
slo_url TEXT,
|
||||
certificate TEXT, -- X.509 证书
|
||||
metadata_url TEXT,
|
||||
metadata_xml TEXT,
|
||||
client_id TEXT,
|
||||
client_secret TEXT,
|
||||
authorization_url TEXT,
|
||||
token_url TEXT,
|
||||
userinfo_url TEXT,
|
||||
scopes TEXT DEFAULT '["openid", "email", "profile"]',
|
||||
attribute_mapping TEXT DEFAULT '{}', -- JSON: 属性映射
|
||||
auto_provision INTEGER DEFAULT 1, -- 自动创建用户
|
||||
default_role TEXT DEFAULT 'member',
|
||||
domain_restriction TEXT DEFAULT '[]', -- JSON: 允许的邮箱域名
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
last_tested_at TIMESTAMP,
|
||||
last_error TEXT,
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- SAML 认证请求表
|
||||
CREATE TABLE IF NOT EXISTS saml_auth_requests (
|
||||
id TEXT PRIMARY KEY,
|
||||
tenant_id TEXT NOT NULL,
|
||||
sso_config_id TEXT NOT NULL,
|
||||
request_id TEXT NOT NULL UNIQUE,
|
||||
relay_state TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
expires_at TIMESTAMP NOT NULL,
|
||||
used INTEGER DEFAULT 0,
|
||||
used_at TIMESTAMP,
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (sso_config_id) REFERENCES sso_configs(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- SAML 认证响应表
|
||||
CREATE TABLE IF NOT EXISTS saml_auth_responses (
|
||||
id TEXT PRIMARY KEY,
|
||||
request_id TEXT NOT NULL,
|
||||
tenant_id TEXT NOT NULL,
|
||||
user_id TEXT,
|
||||
email TEXT,
|
||||
name TEXT,
|
||||
attributes TEXT DEFAULT '{}', -- JSON: SAML 属性
|
||||
session_index TEXT,
|
||||
processed INTEGER DEFAULT 0,
|
||||
processed_at TIMESTAMP,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (request_id) REFERENCES saml_auth_requests(request_id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- SCIM 配置表
|
||||
CREATE TABLE IF NOT EXISTS scim_configs (
|
||||
id TEXT PRIMARY KEY,
|
||||
tenant_id TEXT NOT NULL,
|
||||
provider TEXT NOT NULL,
|
||||
status TEXT DEFAULT 'disabled',
|
||||
scim_base_url TEXT,
|
||||
scim_token TEXT,
|
||||
sync_interval_minutes INTEGER DEFAULT 60,
|
||||
last_sync_at TIMESTAMP,
|
||||
last_sync_status TEXT,
|
||||
last_sync_error TEXT,
|
||||
last_sync_users_count INTEGER DEFAULT 0,
|
||||
attribute_mapping TEXT DEFAULT '{}',
|
||||
sync_rules TEXT DEFAULT '{}',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- 租户成员表
|
||||
CREATE TABLE IF NOT EXISTS tenant_members (
|
||||
-- SCIM 用户表
|
||||
CREATE TABLE IF NOT EXISTS scim_users (
|
||||
id TEXT PRIMARY KEY,
|
||||
tenant_id TEXT NOT NULL,
|
||||
user_id TEXT NOT NULL,
|
||||
external_id TEXT NOT NULL,
|
||||
user_name TEXT NOT NULL,
|
||||
email TEXT NOT NULL,
|
||||
name TEXT DEFAULT '',
|
||||
role TEXT DEFAULT 'viewer', -- owner, admin, editor, viewer, guest
|
||||
status TEXT DEFAULT 'invited', -- active, invited, suspended, removed
|
||||
invited_by TEXT,
|
||||
invited_at TEXT,
|
||||
invitation_token TEXT,
|
||||
invitation_expires_at TEXT,
|
||||
joined_at TEXT,
|
||||
last_active_at TEXT,
|
||||
custom_permissions TEXT DEFAULT '[]', -- JSON 数组
|
||||
display_name TEXT,
|
||||
given_name TEXT,
|
||||
family_name TEXT,
|
||||
active INTEGER DEFAULT 1,
|
||||
groups TEXT DEFAULT '[]',
|
||||
raw_data TEXT DEFAULT '{}',
|
||||
synced_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE(tenant_id, user_id),
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
UNIQUE(tenant_id, external_id)
|
||||
);
|
||||
|
||||
-- 审计日志导出表
|
||||
CREATE TABLE IF NOT EXISTS audit_log_exports (
|
||||
id TEXT PRIMARY KEY,
|
||||
tenant_id TEXT NOT NULL,
|
||||
export_format TEXT NOT NULL, -- json/csv/pdf/xlsx
|
||||
start_date TIMESTAMP NOT NULL,
|
||||
end_date TIMESTAMP NOT NULL,
|
||||
filters TEXT DEFAULT '{}',
|
||||
compliance_standard TEXT, -- soc2/iso27001/gdpr/hipaa/pci_dss
|
||||
status TEXT DEFAULT 'pending', -- pending/processing/completed/failed
|
||||
file_path TEXT,
|
||||
file_size INTEGER,
|
||||
record_count INTEGER,
|
||||
checksum TEXT,
|
||||
downloaded_by TEXT,
|
||||
downloaded_at TIMESTAMP,
|
||||
expires_at TIMESTAMP,
|
||||
created_by TEXT NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
completed_at TIMESTAMP,
|
||||
error_message TEXT,
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- 租户角色表
|
||||
CREATE TABLE IF NOT EXISTS tenant_roles (
|
||||
-- 数据保留策略表
|
||||
CREATE TABLE IF NOT EXISTS data_retention_policies (
|
||||
id TEXT PRIMARY KEY,
|
||||
tenant_id TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT DEFAULT '',
|
||||
permissions TEXT DEFAULT '[]', -- JSON 数组
|
||||
is_system INTEGER DEFAULT 0, -- 1=系统预设, 0=自定义
|
||||
description TEXT,
|
||||
resource_type TEXT NOT NULL, -- project/transcript/entity/audit_log/user_data
|
||||
retention_days INTEGER NOT NULL,
|
||||
action TEXT NOT NULL, -- archive/delete/anonymize
|
||||
conditions TEXT DEFAULT '{}',
|
||||
auto_execute INTEGER DEFAULT 0,
|
||||
execute_at TEXT, -- cron 表达式
|
||||
notify_before_days INTEGER DEFAULT 7,
|
||||
archive_location TEXT,
|
||||
archive_encryption INTEGER DEFAULT 1,
|
||||
is_active INTEGER DEFAULT 1,
|
||||
last_executed_at TIMESTAMP,
|
||||
last_execution_result TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- 租户相关索引
|
||||
CREATE INDEX IF NOT EXISTS idx_tenants_slug ON tenants(slug);
|
||||
CREATE INDEX IF NOT EXISTS idx_tenants_status ON tenants(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_domains_tenant ON tenant_domains(tenant_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_domains_domain ON tenant_domains(domain);
|
||||
CREATE INDEX IF NOT EXISTS idx_domains_status ON tenant_domains(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_members_tenant ON tenant_members(tenant_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_members_user ON tenant_members(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_members_role ON tenant_members(role);
|
||||
CREATE INDEX IF NOT EXISTS idx_members_status ON tenant_members(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_members_token ON tenant_members(invitation_token);
|
||||
CREATE INDEX IF NOT EXISTS idx_roles_tenant ON tenant_roles(tenant_id);
|
||||
-- 数据保留任务表
|
||||
CREATE TABLE IF NOT EXISTS data_retention_jobs (
|
||||
id TEXT PRIMARY KEY,
|
||||
policy_id TEXT NOT NULL,
|
||||
tenant_id TEXT NOT NULL,
|
||||
status TEXT DEFAULT 'pending', -- pending/running/completed/failed
|
||||
started_at TIMESTAMP,
|
||||
completed_at TIMESTAMP,
|
||||
affected_records INTEGER DEFAULT 0,
|
||||
archived_records INTEGER DEFAULT 0,
|
||||
deleted_records INTEGER DEFAULT 0,
|
||||
error_count INTEGER DEFAULT 0,
|
||||
details TEXT DEFAULT '{}',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (policy_id) REFERENCES data_retention_policies(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- 更新项目表,添加租户关联(可选,支持租户隔离)
|
||||
ALTER TABLE projects ADD COLUMN tenant_id TEXT;
|
||||
CREATE INDEX IF NOT EXISTS idx_projects_tenant ON projects(tenant_id);
|
||||
-- 企业级功能相关索引
|
||||
CREATE INDEX IF NOT EXISTS idx_sso_tenant ON sso_configs(tenant_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_sso_provider ON sso_configs(provider);
|
||||
CREATE INDEX IF NOT EXISTS idx_saml_requests_config ON saml_auth_requests(sso_config_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_saml_requests_expires ON saml_auth_requests(expires_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_saml_responses_request ON saml_auth_responses(request_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_scim_config_tenant ON scim_configs(tenant_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_scim_users_tenant ON scim_users(tenant_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_scim_users_external ON scim_users(external_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_audit_export_tenant ON audit_log_exports(tenant_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_audit_export_status ON audit_log_exports(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_retention_tenant ON data_retention_policies(tenant_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_retention_type ON data_retention_policies(resource_type);
|
||||
CREATE INDEX IF NOT EXISTS idx_retention_jobs_policy ON data_retention_jobs(policy_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_retention_jobs_status ON data_retention_jobs(status);
|
||||
|
||||
Reference in New Issue
Block a user