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 { NextResponse } from "next/server";
|
||||||
|
import { query } from "@/lib/db";
|
||||||
|
|
||||||
export const runtime = "nodejs";
|
export const runtime = "nodejs";
|
||||||
|
|
||||||
export async function GET() {
|
let migrationDone = false;
|
||||||
return NextResponse.json({ status: "ok" }, { status: 200 });
|
|
||||||
|
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