feat(M1): 认证与用户管理 — 双通道登录、cookie 会话、用户 CRUD 与真实系统账号对接
认证: - 图形验证码 GET /auth/captcha(内置 PNG 渲染,零第三方依赖) - 外部用户 OTP 双通道:DB 存储(otp_codes)使邮件与 CLI 共用同一验证码/冷却/失败限速 - 管理员 bcrypt 登录 + 连续失败限速锁定;admin/forgot + admin/reset 邮件重置(SMTP 或日志) - cookie 会话(HttpOnly/SameSite)、me/logout、admin/user 鉴权中间件 用户管理(admin): - CRUD + disable/enable/extend/delete,对接 system 层真实 useradd/usermod/userdel/passwd - system 层三执行模式:dry-run(默认,安全)/ direct(容器/测试用户)/ sudo(生产 sudoers 白名单) - Exists 系统账号一致性检查;deploy/sudoers.example 白名单模板 - 关键操作接入 append-only 审计 其他: - CLI user otp 改 DB store,与邮件通道真正对齐 - 容器镜像补 shadow(alpine 无 useradd);Makefile VERSION 0.2.0-m1 - 测试:auth/service 单测 + api httptest 集成 + 容器内真实系统账号端到端验证
This commit is contained in:
@@ -141,11 +141,43 @@ type MailLog struct {
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// OTPCode 外部用户 OTP 验证码(DB 存储,邮件与 CLI 双通道共享)。
|
||||
//
|
||||
// 每用户一行(username 唯一):邮件通道经 Send 生成,CLI 通道经 Current
|
||||
// 读取同一验证码,保证"同一验证码、同一有效期、同一冷却与失败限速"(PLAN §2.2)。
|
||||
// 验证码为 6 位数字,生命周期短(10 分钟)且一次性消费,存储明文以便 CLI
|
||||
// 复用返回;并发写由单实例部署的串行事务保证(多实例需改 DB 行锁/Redis,PLAN §6)。
|
||||
type OTPCode struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
Username string `gorm:"size:64;uniqueIndex;not null" json:"username"`
|
||||
Code string `gorm:"size:16;not null" json:"-"`
|
||||
ExpiresAt time.Time `gorm:"index;not null" json:"expires_at"`
|
||||
CooldownUntil time.Time `json:"cooldown_until"` // Send 冷却截止
|
||||
Failures int `json:"failures"`
|
||||
FailedAt *time.Time `json:"failed_at"` // 失败计数窗口起点(窗口内达阈值限速)
|
||||
ConsumedAt *time.Time `json:"consumed_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// PasswordResetToken 管理员密码重置令牌(邮件重置)。DB 只存哈希,
|
||||
// 明文令牌仅经邮件/日志发送给管理员,一次有效。
|
||||
type PasswordResetToken struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
AdminID uint `gorm:"index;not null" json:"admin_id"`
|
||||
TokenHash string `gorm:"size:64;not null" json:"-"`
|
||||
ExpiresAt time.Time `gorm:"index;not null" json:"expires_at"`
|
||||
UsedAt *time.Time `json:"used_at"`
|
||||
IP string `gorm:"size:64" json:"ip"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
// AllModels 供 AutoMigrate 使用的全部模型。
|
||||
func AllModels() []any {
|
||||
return []any{
|
||||
&AdminUser{}, &User{}, &SSHKey{}, &Approval{},
|
||||
&AuditLog{}, &Session{}, &Setting{}, &MailLog{},
|
||||
&OTPCode{}, &PasswordResetToken{},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user