package services import ( "time" "lokistack/models" "lokistack/pkg/crypto" "lokistack/repository" ) // LDAPImportUser 批量导入请求中的用户条目(数据来自预览接口) type LDAPImportUser struct { DN string `json:"dn"` Username string `json:"username" binding:"required"` Nickname string `json:"nickname"` Email string `json:"email"` } // LDAPImportResult 导入结果(与前端展示契约对齐) type LDAPImportResult struct { SuccessCount int `json:"successCount"` SkippedCount int `json:"skippedCount"` UpdatedCount int `json:"updatedCount"` FailedCount int `json:"failedCount"` FailedUsers []map[string]interface{} `json:"failedUsers"` } // BatchImportLDAPUsers 批量导入 LDAP 用户: // 已存在且 LDAP 用户 → 跳过;本地同名 → 更新昵称并转 LDAP;否则新建(user 角色,密码占位)。 func BatchImportLDAPUsers(users []LDAPImportUser) *LDAPImportResult { result := &LDAPImportResult{FailedUsers: []map[string]interface{}{}} db := repository.GetDB() for _, in := range users { if in.Username == "" { continue } // 查找本地同名用户(读锁短持有;NextID/CreateUser 不可在持锁时调用) db.RLock() idx := -1 for i := range db.Users { if db.Users[i].Username == in.Username { idx = i break } } db.RUnlock() if idx >= 0 { db.Lock() if db.Users[idx].AuthSource == "ldap" { db.Unlock() result.SkippedCount++ continue } db.Users[idx].AuthSource = "ldap" // 本地同名 → 转 LDAP 并同步昵称 if in.Nickname != "" { db.Users[idx].Nickname = in.Nickname } db.Users[idx].UpdatedAt = time.Now() db.RequestSave() db.Unlock() result.UpdatedCount++ continue } hash, err := crypto.HashPassword("ldap-user-" + in.Username + "-no-local-login") if err != nil { result.FailedCount++ result.FailedUsers = append(result.FailedUsers, map[string]interface{}{ "username": in.Username, "error": err.Error(), }) continue } u := &models.User{ Username: in.Username, Password: hash, Nickname: in.Nickname, Role: "user", AuthSource: "ldap", } if err := db.CreateUser(u); err != nil { result.FailedCount++ result.FailedUsers = append(result.FailedUsers, map[string]interface{}{ "username": in.Username, "error": err.Error(), }) continue } result.SuccessCount++ } return result } // SearchLDAPUsersForImport 预览入口(服务层薄封装,便于 controller 调用) func SearchLDAPUsersForImport(cfg *LDAPConfig, ouDN string) ([]map[string]interface{}, error) { users, err := searchLDAPUsers(cfg, ouDN, 500) if err != nil { return nil, err } out := make([]map[string]interface{}, 0, len(users)) for _, u := range users { out = append(out, map[string]interface{}{ "dn": u.DN, "username": u.Username, "displayName": u.DisplayName, "email": u.Email, }) } return out, nil }