|
| 1 | +"use client"; |
| 2 | + |
| 3 | +/** |
| 4 | + * /admin/database — 数据库管理后台(iframe 嵌入 pgAdmin)。 |
| 5 | + * |
| 6 | + * 权限:<AdminGuard required="admin"> 兜底,非 admin 直接 403; |
| 7 | + * 真正的操作权限由 pgAdmin 自身登录(环境变量里的 PGADMIN_EMAIL / PGADMIN_PASSWORD) |
| 8 | + * 把守,前端这层只是"路由可见"。 |
| 9 | + * |
| 10 | + * 流量: |
| 11 | + * 浏览器 → involutionhell.com/admin/database |
| 12 | + * └─ iframe src="https://api.involutionhell.com/admin/pgadmin/" |
| 13 | + * └─ Caddy /admin/pgadmin/* → 127.0.0.1:8082(pgAdmin 容器) |
| 14 | + * |
| 15 | + * pgAdmin 容器环境里设了 SCRIPT_NAME=/admin/pgadmin, |
| 16 | + * Caddy 响应里剥掉 X-Frame-Options 并换成 CSP frame-ancestors 放行本站主域。 |
| 17 | + * |
| 18 | + * 为什么不把 pgAdmin 和主站 UI 做统一风格: |
| 19 | + * 用户明确说"管理员不配享受好 UI"——优先把基础能力接通,视觉一致性排最后。 |
| 20 | + */ |
| 21 | + |
| 22 | +import { AdminGuard } from "../events/AdminGuard"; |
| 23 | + |
| 24 | +// pgAdmin 所在路径。默认打 production Caddy,dev 如果要本地联调可以用 |
| 25 | +// NEXT_PUBLIC_PGADMIN_URL 覆盖(比如指到 http://localhost:8082/admin/pgadmin/)。 |
| 26 | +const PGADMIN_URL = |
| 27 | + process.env.NEXT_PUBLIC_PGADMIN_URL ?? |
| 28 | + "https://api.involutionhell.com/admin/pgadmin/"; |
| 29 | + |
| 30 | +export default function AdminDatabasePage() { |
| 31 | + return ( |
| 32 | + <AdminGuard> |
| 33 | + <AdminDatabaseInner /> |
| 34 | + </AdminGuard> |
| 35 | + ); |
| 36 | +} |
| 37 | + |
| 38 | +function AdminDatabaseInner() { |
| 39 | + return ( |
| 40 | + <main className="pt-24 pb-0 bg-[var(--background)] min-h-screen flex flex-col"> |
| 41 | + <div className="max-w-6xl w-full mx-auto px-6 lg:px-8 pb-4"> |
| 42 | + <header className="border-t-4 border-[var(--foreground)] pt-6 mb-4"> |
| 43 | + <div className="font-mono text-[10px] uppercase tracking-[0.3em] text-neutral-500"> |
| 44 | + Admin · Database |
| 45 | + </div> |
| 46 | + <h1 className="font-serif text-2xl md:text-3xl font-black uppercase mt-2 tracking-tight"> |
| 47 | + 数据库管理 |
| 48 | + </h1> |
| 49 | + <p className="mt-2 text-xs text-neutral-600 dark:text-neutral-400 leading-relaxed"> |
| 50 | + 下方嵌入的是 pgAdmin。首次进入要用{" "} |
| 51 | + <code className="font-mono text-[11px] bg-neutral-200 dark:bg-neutral-800 px-1"> |
| 52 | + PGADMIN_EMAIL |
| 53 | + </code>{" "} |
| 54 | + /{" "} |
| 55 | + <code className="font-mono text-[11px] bg-neutral-200 dark:bg-neutral-800 px-1"> |
| 56 | + PGADMIN_PASSWORD |
| 57 | + </code>{" "} |
| 58 | + 登录(在{" "} |
| 59 | + <code className="font-mono text-[11px] bg-neutral-200 dark:bg-neutral-800 px-1"> |
| 60 | + .env |
| 61 | + </code>{" "} |
| 62 | + 里)。 左树自动预注册了 “InvolutionHell (local)” |
| 63 | + 连接,双击即连。 备份/恢复在数据库右键菜单里;定时备份落在{" "} |
| 64 | + <code className="font-mono text-[11px] bg-neutral-200 dark:bg-neutral-800 px-1"> |
| 65 | + Storage → backups/ |
| 66 | + </code> |
| 67 | + 。 |
| 68 | + </p> |
| 69 | + </header> |
| 70 | + </div> |
| 71 | + |
| 72 | + {/* iframe 占满剩余视口,便于操作。高度用 calc 减去 header 高度约 220px。 */} |
| 73 | + <div className="flex-1 border-t border-[var(--foreground)]"> |
| 74 | + <iframe |
| 75 | + src={PGADMIN_URL} |
| 76 | + title="pgAdmin" |
| 77 | + className="w-full h-[calc(100vh-220px)] min-h-[600px] border-0" |
| 78 | + // 不加 sandbox:pgAdmin 依赖自己的 cookie + localStorage 保持登录态, |
| 79 | + // 用 sandbox 会屏蔽掉,功能直接残废。允许同源脚本和 form 提交。 |
| 80 | + referrerPolicy="no-referrer-when-downgrade" |
| 81 | + /> |
| 82 | + </div> |
| 83 | + </main> |
| 84 | + ); |
| 85 | +} |
0 commit comments