feat(admin): auto-migrate admin DB tables on health check (audit_log, user, role, permission)
This commit is contained in:
parent
33a4a5c6c9
commit
3eeb054452
@ -1,7 +1,138 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { query } from "@/lib/db";
|
||||
|
||||
export const runtime = "nodejs";
|
||||
|
||||
export async function GET() {
|
||||
return NextResponse.json({ status: "ok" }, { status: 200 });
|
||||
let migrationDone = false;
|
||||
|
||||
async function ensureTables() {
|
||||
if (migrationDone) return;
|
||||
migrationDone = true;
|
||||
|
||||
console.log("[Health] Checking database tables...");
|
||||
|
||||
// 1. admin_audit_log
|
||||
await query(`
|
||||
CREATE TABLE IF NOT EXISTS admin_audit_log (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
user_id INTEGER NOT NULL,
|
||||
username VARCHAR(255) NOT NULL,
|
||||
action VARCHAR(50) NOT NULL,
|
||||
resource VARCHAR(255) NOT NULL,
|
||||
resource_id VARCHAR(255),
|
||||
request_params JSONB,
|
||||
ip_address VARCHAR(255),
|
||||
user_agent TEXT,
|
||||
result VARCHAR(20) NOT NULL DEFAULT 'success',
|
||||
error_message TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
)
|
||||
`);
|
||||
|
||||
// 2. admin_user
|
||||
await query(`
|
||||
CREATE TABLE IF NOT EXISTS admin_user (
|
||||
id SERIAL PRIMARY KEY,
|
||||
username VARCHAR(255) UNIQUE NOT NULL,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
is_active BOOLEAN NOT NULL DEFAULT true,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
)
|
||||
`);
|
||||
|
||||
// 3. admin_role
|
||||
await query(`
|
||||
CREATE TABLE IF NOT EXISTS admin_role (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255) UNIQUE NOT NULL,
|
||||
description TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
)
|
||||
`);
|
||||
|
||||
// 4. admin_permission
|
||||
await query(`
|
||||
CREATE TABLE IF NOT EXISTS admin_permission (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
code VARCHAR(255) UNIQUE NOT NULL,
|
||||
description TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
)
|
||||
`);
|
||||
|
||||
// 5. admin_user_role
|
||||
await query(`
|
||||
CREATE TABLE IF NOT EXISTS admin_user_role (
|
||||
user_id INTEGER NOT NULL REFERENCES admin_user(id) ON DELETE CASCADE,
|
||||
role_id INTEGER NOT NULL REFERENCES admin_role(id) ON DELETE CASCADE,
|
||||
PRIMARY KEY (user_id, role_id)
|
||||
)
|
||||
`);
|
||||
|
||||
// 6. admin_role_permission
|
||||
await query(`
|
||||
CREATE TABLE IF NOT EXISTS admin_role_permission (
|
||||
role_id INTEGER NOT NULL REFERENCES admin_role(id) ON DELETE CASCADE,
|
||||
permission_id INTEGER NOT NULL REFERENCES admin_permission(id) ON DELETE CASCADE,
|
||||
PRIMARY KEY (role_id, permission_id)
|
||||
)
|
||||
`);
|
||||
|
||||
// 索引
|
||||
await query(`CREATE INDEX IF NOT EXISTS idx_admin_user_username ON admin_user(username)`);
|
||||
await query(`CREATE INDEX IF NOT EXISTS idx_admin_audit_log_user_id ON admin_audit_log(user_id)`);
|
||||
await query(`CREATE INDEX IF NOT EXISTS idx_admin_audit_log_created_at ON admin_audit_log(created_at DESC)`);
|
||||
await query(`CREATE INDEX IF NOT EXISTS idx_admin_audit_log_action ON admin_audit_log(action)`);
|
||||
await query(`CREATE INDEX IF NOT EXISTS idx_admin_audit_log_resource ON admin_audit_log(resource)`);
|
||||
|
||||
// Seed data
|
||||
await query(`
|
||||
INSERT INTO admin_permission (name, code, description) VALUES
|
||||
('用户管理', 'user:read', '查看用户列表'),
|
||||
('用户创建', 'user:create', '创建管理员用户'),
|
||||
('用户更新', 'user:update', '更新管理员用户'),
|
||||
('用户删除', 'user:delete', '删除管理员用户'),
|
||||
('角色管理', 'role:read', '查看角色'),
|
||||
('角色创建', 'role:create', '创建角色'),
|
||||
('角色更新', 'role:update', '更新角色'),
|
||||
('角色删除', 'role:delete', '删除角色'),
|
||||
('权限管理', 'permission:read', '查看权限'),
|
||||
('权限创建', 'permission:create', '创建权限'),
|
||||
('权限更新', 'permission:update', '更新权限'),
|
||||
('权限删除', 'permission:delete', '删除权限'),
|
||||
('日志查看', 'log:read', '查看审计日志'),
|
||||
('会话管理', 'session:manage', '管理在线用户会话'),
|
||||
('平台数据', 'platform:read', '查看平台数据'),
|
||||
('平台管理', 'platform:manage', '管理平台数据')
|
||||
ON CONFLICT (code) DO NOTHING
|
||||
`);
|
||||
|
||||
await query(`
|
||||
INSERT INTO admin_role (name, description) VALUES
|
||||
('超级管理员', '拥有所有权限')
|
||||
ON CONFLICT (name) DO NOTHING
|
||||
`);
|
||||
|
||||
await query(`
|
||||
INSERT INTO admin_role_permission (role_id, permission_id)
|
||||
SELECT r.id, p.id
|
||||
FROM admin_role r
|
||||
CROSS JOIN admin_permission p
|
||||
WHERE r.name = '超级管理员'
|
||||
ON CONFLICT DO NOTHING
|
||||
`);
|
||||
|
||||
console.log("[Health] Database tables ready");
|
||||
}
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
await ensureTables();
|
||||
return NextResponse.json({ status: "ok" }, { status: 200 });
|
||||
} catch (e) {
|
||||
console.error("[Health] DB check failed:", e);
|
||||
return NextResponse.json({ status: "error", reason: String(e) }, { status: 503 });
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user