feat: 账号认证、用户管理与 API Token 管理
build-and-deploy / build-and-deploy (push) Successful in 21s

- 后端: Auth(登录/登出/me + session 中间件)、Users、Tokens 路由与 Service,
  scrypt 哈希+timingSafeEqual 校验、requireAdmin 保护、admin 用户自动初始化
- 前端: login.html(登录页, 无账号密码提示)、admin.html(用户+Token 管理,
  令牌明文显隐/复制/吊销/重置密码)、标题栏用户信息+系统管理入口
- 持久化: jsonAdapter 支持 users/api-tokens,运行时数据忽略入库
- 文档: 需求.md/原型设计.md 同步
This commit is contained in:
jif2.zhang
2026-09-11 17:12:37 +08:00
parent 963046edd9
commit 1765caba50
16 changed files with 2132 additions and 141 deletions
+40 -6
View File
@@ -7,10 +7,19 @@
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<!-- 标题栏:仅展示应用名与当前项目 -->
<header class="titlebar">
<span class="app-title">📋 Registry 配置管理中心</span>
<span class="current-project" id="current-project-name">未选择项目</span>
<!-- 标题栏:仅展示应用名与当前项目 -->
<header class="titlebar">
<span class="app-title">📋 Registry 配置管理中心</span>
<span class="current-project" id="current-project-name">未选择项目</span>
<div class="titlebar-right">
<span class="titlebar-user">
👤 <span id="user-name"></span>
<span class="role-badge" id="user-role"></span>
</span>
<a class="titlebar-link" id="admin-entry" href="/admin.html" style="display:none">⚙ 系统管理</a>
<a class="titlebar-link" href="/projects.html">项目列表</a>
<a class="titlebar-link" id="logout-link" href="#">退出登录</a>
</div>
</header>
<!-- 工具栏:分组处理(项目 / 模式 / 配置 / 数据) -->
@@ -312,8 +321,33 @@
</div>
</div>
<script src="/js/api.js"></script>
<script src="/js/tree.js"></script>
<script src="/js/api.js"></script>
<script src="/js/tree.js"></script>
<script>
// 认证初始化:检查登录状态,填充标题栏用户信息
(async function initAuth() {
try {
var user = await API.getMe();
document.getElementById("user-name").textContent = user.displayName || user.username;
var roleEl = document.getElementById("user-role");
if (user.role === "admin") {
roleEl.textContent = "管理员";
roleEl.className = "role-badge admin";
document.getElementById("admin-entry").style.display = "";
}
} catch (e) {
window.location.href = "/login.html";
return;
}
})();
document.getElementById("logout-link").addEventListener("click", async function (e) {
e.preventDefault();
try { await API.logout(); } catch (e) {}
localStorage.removeItem("registry_token");
localStorage.removeItem("registry_user");
window.location.href = "/login.html";
});
</script>
<script src="/js/app.js"></script>
</body>
</html>