Files
openvpn-manager/docs
cnbugs 09f6918aeb 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)
2026-08-09 21:45:41 +08:00
..
2026-08-09 21:45:41 +08:00