Add multi-admin account management
Schema:
- New AdminUser model with bcrypt-hashed password (cost 10)
- Roles: admin (full) / operator (read-only ops)
- Status: active / disabled
- MustChangePassword flag forces first-login password change
Backend:
- store: Add admins [] + CRUD methods (ListAdmins strips PasswordHash)
- service: SeedDefaultAdminIfEmpty (uses env credentials on first run),
CreateAdmin, ChangePassword, ResetPassword, SetAdminStatus, DeleteAdmin
- middleware: JWT now carries user_id (UUID)
- api: login() uses bcrypt + updates last_login_at/ip, blocks disabled
- api: me() returns role + must_change_password
- api: new endpoints:
POST /api/me/password (self password change)
GET /api/admins
POST /api/admins (create)
POST /api/admins/:id/password (reset by admin)
POST /api/admins/:id/status (enable/disable)
DELETE /api/admins/:id (with self/last-admin guard)
Frontend:
- Login: must_change_password=true triggers forced change-password dialog
- Layout: admin dropdown shows role tag + 修改密码 / 退出登录
- New /admins page (admin only) with table + create/reset/status/delete
- Router guard hides /admins from non-admin accounts
- API client: Auth.changePassword, Admins.{list,create,resetPassword,setStatus,delete}
Security:
- PasswordHash stored as bcrypt $2a$10$... in db.json
- ListAdmins always returns PasswordHash=''; never leaks via API
- Login returns 403 for disabled accounts
Verified: 21/21 API tests + browser E2E (first-login forced change,
restart persistence, admin list without hash, role-based menu)
This commit is contained in:
@@ -50,6 +50,7 @@
|
||||
| 客户端证书 | 一键签发,自动生成 `.ovpn`(内嵌 CA/Cert/Key/TLS-Auth),无需额外文件 |
|
||||
| 固定 IP | 通过 CCD (`client-config-dir`) 为指定用户分配固定 VPN IP |
|
||||
| **访问控制(白名单)** | 实例/用户两层 allow_networks,合并生效;服务端 iptables 强制隔离 |
|
||||
| **多账号管理** | db.json 中存 bcrypt 哈希,可创建多个 admin/operator 账号,首登强制改密 |
|
||||
| 启停控制 | Web 一键启动/停止实例,显示 PID 与状态 |
|
||||
| 流量审计 | 解析 `status-version 3` 输出,记录上下行字节/连接时长 |
|
||||
| 证书到期提醒 | 仪表盘统计 30 天内到期的证书,单独证书管理页查看完整清单 |
|
||||
@@ -283,17 +284,47 @@ sudo ./scripts/install.sh -u
|
||||
|
||||
⚠️ **生产环境第一步**。
|
||||
|
||||
当前版本通过 systemd 环境变量修改密码:
|
||||
### 首次登录强制改密
|
||||
|
||||
首次访问用默认账号 `admin/admin123` 登录后,系统**强制**弹出"修改初始密码"对话框,
|
||||
必须改成 ≥6 位的强密码才能继续使用,无法跳过。这一步密码修改后会写入 `data/db.json`,
|
||||
**之后不再需要重启服务**,密码以 bcrypt 哈希持久化。
|
||||
|
||||
### 通过 Web 修改自己的密码
|
||||
|
||||
右上角 admin 下拉 → "修改密码" → 填写当前密码 + 新密码 → 保存,立即生效。
|
||||
|
||||
### 创建/管理其他账号
|
||||
|
||||
Web → 左侧"管理员"菜单(admin role 才可见):
|
||||
|
||||
| 操作 | 说明 |
|
||||
| ---- | ---- |
|
||||
| 新建账号 | 设置用户名、密码、角色(admin / operator) |
|
||||
| 重置密码 | 不知道旧密码也能强制改密,新密码立即生效 |
|
||||
| 启用/禁用 | 禁用后该账号无法登录(已登录的 token 仍可短期使用) |
|
||||
| 删除 | 不能删除自己、不能删除最后一个 admin |
|
||||
|
||||
所有账号操作都进入审计日志。
|
||||
|
||||
### 通过 systemd 环境变量重置(忘记密码时)
|
||||
|
||||
如果你把所有 admin 都禁用/删除了,或者忘了所有密码,可以临时用环境变量密码
|
||||
覆盖(只用于"首次登录然后改密",不持久):
|
||||
|
||||
```bash
|
||||
systemctl edit --full openvpn-manager
|
||||
# 找到 OVPNMGR_ADMIN_PASS 一行,改成你的强密码
|
||||
# 也建议修改 OVPNMGR_JWT_SECRET 为随机串
|
||||
# 找到 OVPNMGR_ADMIN_PASS 一行,改成你临时用的密码
|
||||
systemctl daemon-reload
|
||||
systemctl restart openvpn-manager
|
||||
# 用新密码登录,系统会触发 SeedDefaultAdminIfEmpty
|
||||
# 注:此路径只在 db.json 中无任何 admin 时生效;否则会校验 db.json 中的账号
|
||||
```
|
||||
|
||||
或重新跑 `install.sh --pass 新密码`。
|
||||
更可靠的做法:**直接编辑 `data/db.json`**,把 `password_hash` 替换为 bcrypt 哈希
|
||||
(用 `htpasswd -bnBC 10 "" yourpass | tr -d ':\n'` 生成)后重启服务。
|
||||
|
||||
> 环境变量里的 `OVPNMGR_ADMIN_USER` / `OVPNMGR_ADMIN_PASS` 仅在数据库为空时作为初始 seed 使用。
|
||||
|
||||
## 创建第一个实例
|
||||
|
||||
|
||||
Reference in New Issue
Block a user