feat: validate production runtime config
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { redirect } from "next/navigation";
|
||||
import { getSession } from "@/lib/auth";
|
||||
import { db } from "@/lib/db";
|
||||
import { checkRuntimeConfig } from "@/lib/config";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
@@ -12,6 +13,7 @@ export default async function AdminPage({ searchParams }: { searchParams: Promis
|
||||
const errors = db.prepare("SELECT scope,message,created_at FROM error_events ORDER BY id DESC LIMIT 30").all() as any[];
|
||||
const audits = db.prepare("SELECT a.action,a.target_type,a.target_id,a.metadata_json,a.created_at,u.username FROM audit_events a LEFT JOIN users u ON u.id=a.actor_user_id ORDER BY a.id DESC LIMIT 50").all() as any[];
|
||||
const sources = db.prepare("SELECT s.id,s.name,s.base_url,s.sync_status,s.last_synced_at,s.is_enabled,count(sm.user_id) AS member_count FROM sources s LEFT JOIN source_members sm ON sm.source_id=s.id GROUP BY s.id ORDER BY s.id DESC").all() as any[];
|
||||
const config = checkRuntimeConfig();
|
||||
return <><h1>管理員</h1>{query.updated && <p>管理操作已完成。</p>}{query.error && <p className="error">管理操作未完成。</p>}
|
||||
<section className="card"><h2>待審核檢舉</h2>{reports.length ? <ul className="job-list">{reports.map((report) => <li key={report.id}><strong>貼文 #{report.post_id}</strong> · 檢舉者 @{report.username || "已刪除使用者"}<br />{report.reason}<br /><span className="meta">{report.content.slice(0, 180)} · {new Date(report.created_at + "Z").toLocaleString("zh-TW")}</span><div className="row"><form action="/api/admin/moderate" method="post"><input type="hidden" name="action" value="hide-post" /><input type="hidden" name="id" value={report.post_id} /><button className="danger">隱藏貼文並結案</button></form><form action="/api/admin/moderate" method="post"><input type="hidden" name="action" value="resolve-report" /><input type="hidden" name="id" value={report.id} /><button>保留貼文並結案</button></form></div></li>)}</ul> : <p className="muted">沒有待審核檢舉。</p>}</section>
|
||||
<section className="card"><h2>使用者</h2><ul className="job-list">{users.map((account) => <li key={account.id}><strong>@{account.username}</strong> · <span className="tag">{account.role}</span> · {account.disabled ? "已停權" : "正常"}<div className="row">{account.id !== user.id && <form action="/api/admin/moderate" method="post"><input type="hidden" name="action" value={account.disabled ? "enable-user" : "disable-user"} /><input type="hidden" name="id" value={account.id} /><button className={account.disabled ? "" : "danger"}>{account.disabled ? "解除停權" : "停權"}</button></form>}<form action="/api/admin/moderate" method="post"><input type="hidden" name="action" value="reset-password" /><input type="hidden" name="id" value={account.id} /><input name="password" type="password" minLength={10} required placeholder="管理員重設密碼" /><button>重設密碼</button></form></div></li>)}</ul></section>
|
||||
@@ -19,5 +21,6 @@ export default async function AdminPage({ searchParams }: { searchParams: Promis
|
||||
<section className="card"><h2>最近系統錯誤</h2>{errors.length ? <ul className="job-list">{errors.map((error, index) => <li key={index}><strong>{error.scope}</strong> · <span className="error">{error.message}</span><br /><span className="meta">{new Date(error.created_at + "Z").toLocaleString("zh-TW")}</span></li>)}</ul> : <p className="muted">尚無記錄。</p>}</section>
|
||||
<section className="card"><h2>稽核紀錄</h2>{audits.length ? <ul className="job-list">{audits.map((item, index) => <li key={index}><strong>{item.action}</strong> · @{item.username || "system"} · {item.target_type} #{item.target_id || "—"}<br /><span className="meta">{new Date(item.created_at + "Z").toLocaleString("zh-TW")}</span></li>)}</ul> : <p className="muted">尚無稽核紀錄。</p>}</section>
|
||||
<section className="card"><h2>所有來源</h2><ul className="job-list">{sources.map((source) => <li key={source.id}><strong>{source.name}</strong> · <span className="tag">{source.is_enabled ? source.sync_status : "disabled"}</span> · 成員 {source.member_count}<br /><span className="meta">#{source.id} · {source.base_url} · 上次同步:{source.last_synced_at || "尚未完成"}</span></li>)}</ul></section>
|
||||
<section className="card"><h2>正式環境設定</h2>{config.ok ? <p>設定檢查通過。</p> : <ul>{config.errors.map((error) => <li className="error" key={error}>{error}</li>)}</ul>}</section>
|
||||
</>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user