重組前檢查點:根目錄 main package

This commit is contained in:
2026-10-03 09:23:38 +08:00
commit f373cb8d37
45 changed files with 5332 additions and 0 deletions
+99
View File
@@ -0,0 +1,99 @@
{{/* 金鑰管理頁(僅 admin)。以 layout.html(側邊導覽欄版面)為根模板組合
渲染:本檔僅定義區塊,不應單獨解析執行。導覽覆寫為「帳號資訊+金鑰
管理(aria-current)+應用程式管理」,側欄頁尾沿用版面預設(使用者
資訊與登出表單)。 */}}
{{define "title"}}金鑰管理 - alterminal{{end}}
{{define "navitems"}}
<li>
<a href="/login"
class="flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium text-neutral-600 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-700/60">
<svg class="size-5 shrink-0" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z"/>
</svg>
帳號資訊
</a>
</li>
<li>
<a href="/admin/keys" aria-current="page"
class="flex items-center gap-3 rounded-lg bg-brand/10 px-3 py-2 text-sm font-medium text-brand dark:bg-brand/25 dark:text-blue-200">
<svg class="size-5 shrink-0" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 5.25a3 3 0 0 1 3 3m3 0a6 6 0 0 1-7.029 5.912c-.563-.097-1.159.026-1.563.43L10.5 17.25H8.25v2.25H6v2.25H2.25v-2.818c0-.597.237-1.17.659-1.591l6.499-6.499c.404-.404.527-1 .43-1.563A6 6 0 1 1 21.75 8.25Z"/>
</svg>
金鑰管理
</a>
</li>
<li>
<a href="/admin/applications"
class="flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium text-neutral-600 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-700/60">
<svg class="size-5 shrink-0" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M21 7.5l-9-5.25L3 7.5m18 0l-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9"/>
</svg>
應用程式管理
</a>
</li>
{{end}}
{{define "content"}}
<section class="rounded-xl bg-white p-8 shadow-lg dark:bg-neutral-800 dark:shadow-black/40">
<div class="mb-6 flex flex-wrap items-start justify-between gap-4">
<div>
<h1 class="mb-1 text-xl font-semibold">金鑰管理</h1>
<p class="text-sm text-neutral-500 dark:text-neutral-400">JWT 簽章金鑰(RSA-2048 · RS256)</p>
</div>
<form method="post" action="/admin/keys">
<input type="hidden" name="csrf_token" value="{{.CSRF}}">
<button type="submit"
class="rounded-lg bg-brand px-4 py-2.5 text-sm font-semibold text-white hover:bg-brand-strong">產生新金鑰</button>
</form>
</div>
{{if .Error}}<p class="mb-4 rounded-lg bg-red-500/10 px-3 py-2.5 text-sm text-red-600 dark:text-red-400" role="alert">{{.Error}}</p>{{end}}
{{if not .ActiveCount}}<p class="mb-4 rounded-lg bg-amber-500/10 px-3 py-2.5 text-sm text-amber-700 dark:text-amber-400" role="alert">目前沒有使用中的金鑰,將無法簽發 JWT,請立即產生新金鑰。</p>{{end}}
{{if .Keys}}
<p class="mb-3 text-sm text-neutral-500 dark:text-neutral-400">使用中 {{.ActiveCount}} 把 / 共 {{len .Keys}} 把</p>
<div class="overflow-x-auto">
<table class="w-full text-left text-sm">
<thead>
<tr class="border-b border-neutral-200 dark:border-neutral-700">
<th scope="col" class="px-3 py-2 text-xs font-medium tracking-wide text-neutral-500 uppercase dark:text-neutral-400">kid</th>
<th scope="col" class="px-3 py-2 text-xs font-medium tracking-wide text-neutral-500 uppercase dark:text-neutral-400">演算法</th>
<th scope="col" class="px-3 py-2 text-xs font-medium tracking-wide text-neutral-500 uppercase dark:text-neutral-400">建立時間</th>
<th scope="col" class="px-3 py-2 text-xs font-medium tracking-wide text-neutral-500 uppercase dark:text-neutral-400">狀態</th>
<th scope="col" class="px-3 py-2"><span class="sr-only">操作</span></th>
</tr>
</thead>
<tbody class="divide-y divide-neutral-100 dark:divide-neutral-700/60">
{{range .Keys}}
<tr>
<td class="px-3 py-3 font-mono text-xs break-all">{{.Kid}}</td>
<td class="px-3 py-3 whitespace-nowrap">{{.Algorithm}}</td>
<td class="px-3 py-3 whitespace-nowrap text-neutral-500 dark:text-neutral-400">{{.CreatedAt}}</td>
<td class="px-3 py-3 whitespace-nowrap">
{{if .Active}}
<span class="rounded-full bg-emerald-500/10 px-2.5 py-0.5 text-xs font-medium text-emerald-700 dark:text-emerald-400">使用中</span>
{{else}}
<span class="rounded-full bg-neutral-500/10 px-2.5 py-0.5 text-xs font-medium text-neutral-600 dark:text-neutral-400">已退休</span>
{{end}}
</td>
<td class="px-3 py-3 whitespace-nowrap">
{{if .Active}}{{if .LastActive}}
<span class="text-xs text-neutral-400 dark:text-neutral-500" title="最後一把使用中金鑰,無法退休">唯一使用中金鑰</span>
{{else}}
<form method="post" action="/admin/keys/{{.ID}}/retire">
<input type="hidden" name="csrf_token" value="{{$.CSRF}}">
<button type="submit"
class="rounded-lg border border-neutral-300 px-3 py-1.5 text-xs font-semibold hover:bg-neutral-100 dark:border-neutral-600 dark:hover:bg-neutral-700">退休</button>
</form>
{{end}}{{end}}
</td>
</tr>
{{end}}
</tbody>
</table>
</div>
<p class="mt-4 text-sm text-neutral-500 dark:text-neutral-400">輪替方式:先「產生新金鑰」並以新金鑰簽發,舊金鑰確認無人使用後再「退休」(退休後仍發佈於 JWKS 一段時間供驗證)。</p>
{{else}}
<p class="py-6 text-sm text-neutral-500 dark:text-neutral-400">尚無簽章金鑰,點上方「產生新金鑰」建立第一把。</p>
{{end}}
</section>
{{end}}