feat: 修复仪表盘数据管线 — 补充应用发布种子数据 + 修复limit参数解析 + LDAP认证集成 + User类型完善

后端改进:
- 修复 dashboard/recent-alerts 的 limit 参数解析 (原代码错误地将数字解析为日期)
- 为 dashboard/recent-releases 添加 limit 参数解析支持
- 新增 generateAppReleases 种子数据生成函数 (10条应用发布记录)
- 修复 AlertEvent 的 rule_name/rule_id/severity 数据一致性
- 添加 go-ldap/ldap/v3 依赖并集成 LDAP 认证处理器
- 添加 seed.go 自动种子数据初始化 (admin用户+LDAP配置)
- User model 添加 AuthSource/LDAPConfig 字段

前端改进:
- 修复 User 类型定义以匹配后端 API (real_name/is_admin/auth_source等)
- 修复 Header.tsx 的 real_name 属性引用导致 TypeScript 编译错误
- 统一 API 服务层、暗色主题样式、组件联调优化

验证:
- go build ./... 编译通过
- npm run build 构建通过
- 仪表盘发布历史、告警消息等区域数据正常展示
- 健康检查 /health 正常
This commit is contained in:
attacker committed 2026-06-14 02:11:10 +08:00
1 parent 97c4207ff8
commit ff0b268984
39 files changed
+4283 -1878

No files matched your search

+79 -18
View File
@@ -46,26 +46,87 @@ func (h *UserHandler) Login(c *gin.Context) {
}
var user models.User
if err := h.db.Where("username = ?", req.Username).First(&user).Error; err != nil {
c.JSON(http.StatusUnauthorized, models.Response{
Code: 401,
Message: "用户名或密码错误",
})
return
}
err := h.db.Where("username = ?", req.Username).First(&user).Error
if user.Status != 1 {
c.JSON(http.StatusUnauthorized, models.Response{
Code: 401,
Message: "账号已被禁用",
})
return
}
if err == nil {
// 本地用户存在
if user.Status != 1 {
c.JSON(http.StatusUnauthorized, models.Response{
Code: 401,
Message: "账号已被禁用",
})
return
}
if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password)); err != nil {
c.JSON(http.StatusUnauthorized, models.Response{
Code: 401,
Message: "用户名或密码错误",
// 先尝试本地密码验证
passOk := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password)) == nil
if !passOk {
// 本地密码失败 — LDAP 用户尝试 LDAP 认证
if user.AuthSource == "ldap" || user.Password == "-" {
ldapInfo, ldapErr := tryLDAPAuth(h.db, req.Username, req.Password)
if ldapErr != nil {
c.JSON(http.StatusUnauthorized, models.Response{
Code: 401,
Message: "用户名或密码错误",
})
return
}
// LDAP OK — 更新本地信息
if ldapInfo != nil {
updates := map[string]interface{}{}
if ldapInfo.DisplayName != "" && ldapInfo.DisplayName != user.RealName {
updates["real_name"] = ldapInfo.DisplayName
}
if ldapInfo.Email != "" && ldapInfo.Email != user.Email {
updates["email"] = ldapInfo.Email
}
if len(updates) > 0 {
h.db.Model(&user).Updates(updates)
}
}
} else {
c.JSON(http.StatusUnauthorized, models.Response{
Code: 401,
Message: "用户名或密码错误",
})
return
}
}
} else if err == gorm.ErrRecordNotFound {
// 本地用户不存在 — 尝试 LDAP 认证
ldapInfo, ldapErr := tryLDAPAuth(h.db, req.Username, req.Password)
if ldapErr != nil {
c.JSON(http.StatusUnauthorized, models.Response{
Code: 401,
Message: "用户名或密码错误",
})
return
}
// LDAP 认证成功,自动创建本地用户
newUser := models.User{
Username: ldapInfo.Username,
Password: "-",
RealName: ldapInfo.DisplayName,
Email: ldapInfo.Email,
Status: 1,
AuthSource: "ldap",
}
if newUser.RealName == "" {
newUser.RealName = newUser.Username
}
if err := h.db.Create(&newUser).Error; err != nil {
c.JSON(http.StatusInternalServerError, models.Response{
Code: 500,
Message: "创建LDAP用户失败: " + err.Error(),
})
return
}
user = newUser
} else {
c.JSON(http.StatusInternalServerError, models.Response{
Code: 500,
Message: "数据库错误",
})
return
}