diff --git a/controllers/ldap.go b/controllers/ldap.go
index 21ee6f38..c7318d13 100644
--- a/controllers/ldap.go
+++ b/controllers/ldap.go
@@ -65,7 +65,7 @@ func (c *ApiController) GetLdapUsers() {
// })
//}
- users, err := conn.GetLdapUsers(ldapServer.BaseDn)
+ users, err := conn.GetLdapUsers(ldapServer)
if err != nil {
c.ResponseError(err.Error())
return
@@ -80,10 +80,11 @@ func (c *ApiController) GetLdapUsers() {
Cn: user.Cn,
GroupId: user.GidNumber,
// GroupName: groupsMap[user.GidNumber].Cn,
- Uuid: user.Uuid,
- Email: util.GetMaxLenStr(user.Mail, user.Email, user.EmailAddress),
- Phone: util.GetMaxLenStr(user.TelephoneNumber, user.Mobile, user.MobileTelephoneNumber),
- Address: util.GetMaxLenStr(user.RegisteredAddress, user.PostalAddress),
+ Uuid: user.Uuid,
+ DisplayName: user.DisplayName,
+ Email: util.GetMaxLenStr(user.Mail, user.Email, user.EmailAddress),
+ Phone: util.GetMaxLenStr(user.TelephoneNumber, user.Mobile, user.MobileTelephoneNumber),
+ Address: util.GetMaxLenStr(user.RegisteredAddress, user.PostalAddress),
})
uuids = append(uuids, user.Uuid)
}
@@ -131,7 +132,7 @@ func (c *ApiController) AddLdap() {
return
}
- if util.IsStringsEmpty(ldap.Owner, ldap.ServerName, ldap.Host, ldap.Admin, ldap.Passwd, ldap.BaseDn) {
+ if util.IsStringsEmpty(ldap.Owner, ldap.ServerName, ldap.Host, ldap.Username, ldap.Password, ldap.BaseDn) {
c.ResponseError(c.T("general:Missing parameter"))
return
}
@@ -160,7 +161,7 @@ func (c *ApiController) AddLdap() {
func (c *ApiController) UpdateLdap() {
var ldap object.Ldap
err := json.Unmarshal(c.Ctx.Input.RequestBody, &ldap)
- if err != nil || util.IsStringsEmpty(ldap.Owner, ldap.ServerName, ldap.Host, ldap.Admin, ldap.Passwd, ldap.BaseDn) {
+ if err != nil || util.IsStringsEmpty(ldap.Owner, ldap.ServerName, ldap.Host, ldap.Username, ldap.Password, ldap.BaseDn) {
c.ResponseError(c.T("general:Missing parameter"))
return
}
diff --git a/i18n/locales/de/data.json b/i18n/locales/de/data.json
index 404916e5..bdd7316f 100644
--- a/i18n/locales/de/data.json
+++ b/i18n/locales/de/data.json
@@ -32,8 +32,8 @@
"Email is invalid": "E-Mail ist ungültig",
"Empty username.": "Leerer Benutzername.",
"FirstName cannot be blank": "Vorname darf nicht leer sein",
+ "LDAP user name or password incorrect": "Ldap Benutzername oder Passwort falsch",
"LastName cannot be blank": "Nachname darf nicht leer sein",
- "Ldap user name or password incorrect": "Ldap Benutzername oder Passwort falsch",
"Multiple accounts with same uid, please check your ldap server": "Mehrere Konten mit derselben uid, bitte überprüfen Sie Ihren LDAP-Server",
"Organization does not exist": "Organisation existiert nicht",
"Password must have at least 6 characters": "Das Passwort muss mindestens 6 Zeichen enthalten",
@@ -42,6 +42,7 @@
"Phone number is invalid": "Die Telefonnummer ist ungültig",
"Session outdated, please login again": "Sitzung abgelaufen, bitte erneut anmelden",
"The user is forbidden to sign in, please contact the administrator": "Dem Benutzer ist der Zugang verboten, bitte kontaktieren Sie den Administrator",
+ "The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "Der Benutzername darf nur alphanumerische Zeichen, Unterstriche oder Bindestriche enthalten, keine aufeinanderfolgenden Bindestriche oder Unterstriche haben und darf nicht mit einem Bindestrich oder Unterstrich beginnen oder enden.",
"Username already exists": "Benutzername existiert bereits",
"Username cannot be an email address": "Benutzername kann keine E-Mail-Adresse sein",
diff --git a/i18n/locales/en/data.json b/i18n/locales/en/data.json
index d53a9167..e63c6c5e 100644
--- a/i18n/locales/en/data.json
+++ b/i18n/locales/en/data.json
@@ -32,8 +32,8 @@
"Email is invalid": "Email is invalid",
"Empty username.": "Empty username.",
"FirstName cannot be blank": "FirstName cannot be blank",
+ "LDAP user name or password incorrect": "LDAP user name or password incorrect",
"LastName cannot be blank": "LastName cannot be blank",
- "Ldap user name or password incorrect": "Ldap user name or password incorrect",
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
"Organization does not exist": "Organization does not exist",
"Password must have at least 6 characters": "Password must have at least 6 characters",
@@ -42,6 +42,7 @@
"Phone number is invalid": "Phone number is invalid",
"Session outdated, please login again": "Session outdated, please login again",
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
+ "The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
"Username already exists": "Username already exists",
"Username cannot be an email address": "Username cannot be an email address",
diff --git a/i18n/locales/es/data.json b/i18n/locales/es/data.json
index b024aac4..d067cb8f 100644
--- a/i18n/locales/es/data.json
+++ b/i18n/locales/es/data.json
@@ -32,8 +32,8 @@
"Email is invalid": "El correo electrónico no es válido",
"Empty username.": "Nombre de usuario vacío.",
"FirstName cannot be blank": "El nombre no puede estar en blanco",
+ "LDAP user name or password incorrect": "Nombre de usuario o contraseña de Ldap incorrectos",
"LastName cannot be blank": "El apellido no puede estar en blanco",
- "Ldap user name or password incorrect": "Nombre de usuario o contraseña de Ldap incorrectos",
"Multiple accounts with same uid, please check your ldap server": "Cuentas múltiples con el mismo uid, por favor revise su servidor ldap",
"Organization does not exist": "La organización no existe",
"Password must have at least 6 characters": "La contraseña debe tener al menos 6 caracteres",
@@ -42,6 +42,7 @@
"Phone number is invalid": "El número de teléfono no es válido",
"Session outdated, please login again": "Sesión expirada, por favor vuelva a iniciar sesión",
"The user is forbidden to sign in, please contact the administrator": "El usuario no está autorizado a iniciar sesión, por favor contacte al administrador",
+ "The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "El nombre de usuario solo puede contener caracteres alfanuméricos, guiones bajos o guiones, no puede tener guiones o subrayados consecutivos, y no puede comenzar ni terminar con un guión o subrayado.",
"Username already exists": "El nombre de usuario ya existe",
"Username cannot be an email address": "Nombre de usuario no puede ser una dirección de correo electrónico",
diff --git a/i18n/locales/fr/data.json b/i18n/locales/fr/data.json
index 4440485b..d95af79e 100644
--- a/i18n/locales/fr/data.json
+++ b/i18n/locales/fr/data.json
@@ -32,8 +32,8 @@
"Email is invalid": "L'adresse e-mail est invalide",
"Empty username.": "Nom d'utilisateur vide.",
"FirstName cannot be blank": "Le prénom ne peut pas être laissé vide",
+ "LDAP user name or password incorrect": "Nom d'utilisateur ou mot de passe LDAP incorrect",
"LastName cannot be blank": "Le nom de famille ne peut pas être vide",
- "Ldap user name or password incorrect": "Nom d'utilisateur ou mot de passe LDAP incorrect",
"Multiple accounts with same uid, please check your ldap server": "Plusieurs comptes avec le même identifiant d'utilisateur, veuillez vérifier votre serveur LDAP",
"Organization does not exist": "L'organisation n'existe pas",
"Password must have at least 6 characters": "Le mot de passe doit comporter au moins 6 caractères",
@@ -42,6 +42,7 @@
"Phone number is invalid": "Le numéro de téléphone est invalide",
"Session outdated, please login again": "Session expirée, veuillez vous connecter à nouveau",
"The user is forbidden to sign in, please contact the administrator": "L'utilisateur est interdit de se connecter, veuillez contacter l'administrateur",
+ "The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "Le nom d'utilisateur ne peut contenir que des caractères alphanumériques, des traits soulignés ou des tirets, ne peut pas avoir de tirets ou de traits soulignés consécutifs et ne peut pas commencer ou se terminer par un tiret ou un trait souligné.",
"Username already exists": "Nom d'utilisateur existe déjà",
"Username cannot be an email address": "Nom d'utilisateur ne peut pas être une adresse e-mail",
diff --git a/i18n/locales/id/data.json b/i18n/locales/id/data.json
index a20b2908..f27cbf5a 100644
--- a/i18n/locales/id/data.json
+++ b/i18n/locales/id/data.json
@@ -32,8 +32,8 @@
"Email is invalid": "Email tidak valid",
"Empty username.": "Nama pengguna kosong.",
"FirstName cannot be blank": "Nama depan tidak boleh kosong",
+ "LDAP user name or password incorrect": "Nama pengguna atau kata sandi Ldap salah",
"LastName cannot be blank": "Nama belakang tidak boleh kosong",
- "Ldap user name or password incorrect": "Nama pengguna atau kata sandi Ldap salah",
"Multiple accounts with same uid, please check your ldap server": "Beberapa akun dengan uid yang sama, harap periksa server ldap Anda",
"Organization does not exist": "Organisasi tidak ada",
"Password must have at least 6 characters": "Kata sandi harus memiliki minimal 6 karakter",
@@ -42,6 +42,7 @@
"Phone number is invalid": "Nomor telepon tidak valid",
"Session outdated, please login again": "Sesi kedaluwarsa, silakan masuk lagi",
"The user is forbidden to sign in, please contact the administrator": "Pengguna dilarang masuk, silakan hubungi administrator",
+ "The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "Nama pengguna hanya bisa menggunakan karakter alfanumerik, garis bawah atau tanda hubung, tidak boleh memiliki dua tanda hubung atau garis bawah berurutan, dan tidak boleh diawali atau diakhiri dengan tanda hubung atau garis bawah.",
"Username already exists": "Nama pengguna sudah ada",
"Username cannot be an email address": "Username tidak bisa menjadi alamat email",
diff --git a/i18n/locales/ja/data.json b/i18n/locales/ja/data.json
index 43ba243d..74ae61bc 100644
--- a/i18n/locales/ja/data.json
+++ b/i18n/locales/ja/data.json
@@ -32,8 +32,8 @@
"Email is invalid": "電子メールは無効です",
"Empty username.": "空のユーザー名。",
"FirstName cannot be blank": "ファーストネームは空白にできません",
+ "LDAP user name or password incorrect": "Ldapのユーザー名またはパスワードが間違っています",
"LastName cannot be blank": "姓は空白にできません",
- "Ldap user name or password incorrect": "Ldapのユーザー名またはパスワードが間違っています",
"Multiple accounts with same uid, please check your ldap server": "同じuidを持つ複数のアカウントがあります。あなたのLDAPサーバーを確認してください",
"Organization does not exist": "組織は存在しません",
"Password must have at least 6 characters": "パスワードは少なくとも6つの文字が必要です",
@@ -42,6 +42,7 @@
"Phone number is invalid": "電話番号が無効です",
"Session outdated, please login again": "セッションが期限切れになりました。再度ログインしてください",
"The user is forbidden to sign in, please contact the administrator": "ユーザーはサインインできません。管理者に連絡してください",
+ "The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "ユーザー名には英数字、アンダースコア、ハイフンしか含めることができません。連続したハイフンまたはアンダースコアは不可であり、ハイフンまたはアンダースコアで始まるまたは終わることもできません。",
"Username already exists": "ユーザー名はすでに存在しています",
"Username cannot be an email address": "ユーザー名には電子メールアドレスを使用できません",
diff --git a/i18n/locales/ko/data.json b/i18n/locales/ko/data.json
index 79b10b95..f473a116 100644
--- a/i18n/locales/ko/data.json
+++ b/i18n/locales/ko/data.json
@@ -32,8 +32,8 @@
"Email is invalid": "이메일이 유효하지 않습니다",
"Empty username.": "빈 사용자 이름.",
"FirstName cannot be blank": "이름은 공백일 수 없습니다",
+ "LDAP user name or password incorrect": "LDAP 사용자 이름 또는 암호가 잘못되었습니다",
"LastName cannot be blank": "성은 비어 있을 수 없습니다",
- "Ldap user name or password incorrect": "LDAP 사용자 이름 또는 암호가 잘못되었습니다",
"Multiple accounts with same uid, please check your ldap server": "동일한 UID를 가진 여러 계정이 있습니다. LDAP 서버를 확인해주세요",
"Organization does not exist": "조직은 존재하지 않습니다",
"Password must have at least 6 characters": "암호는 적어도 6자 이상이어야 합니다",
@@ -42,6 +42,7 @@
"Phone number is invalid": "전화번호가 유효하지 않습니다",
"Session outdated, please login again": "세션이 만료되었습니다. 다시 로그인해주세요",
"The user is forbidden to sign in, please contact the administrator": "사용자는 로그인이 금지되어 있습니다. 관리자에게 문의하십시오",
+ "The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "사용자 이름은 알파벳, 숫자, 밑줄 또는 하이픈만 포함할 수 있으며, 연속된 하이픈 또는 밑줄을 가질 수 없으며, 하이픈 또는 밑줄로 시작하거나 끝날 수 없습니다.",
"Username already exists": "사용자 이름이 이미 존재합니다",
"Username cannot be an email address": "사용자 이름은 이메일 주소가 될 수 없습니다",
diff --git a/i18n/locales/ru/data.json b/i18n/locales/ru/data.json
index 72f9afae..d0cfa8ef 100644
--- a/i18n/locales/ru/data.json
+++ b/i18n/locales/ru/data.json
@@ -32,8 +32,8 @@
"Email is invalid": "Адрес электронной почты недействительный",
"Empty username.": "Пустое имя пользователя.",
"FirstName cannot be blank": "Имя не может быть пустым",
+ "LDAP user name or password incorrect": "Неправильное имя пользователя или пароль Ldap",
"LastName cannot be blank": "Фамилия не может быть пустой",
- "Ldap user name or password incorrect": "Неправильное имя пользователя или пароль Ldap",
"Multiple accounts with same uid, please check your ldap server": "Множественные учетные записи с тем же UID. Пожалуйста, проверьте свой сервер LDAP",
"Organization does not exist": "Организация не существует",
"Password must have at least 6 characters": "Пароль должен содержать не менее 6 символов",
@@ -42,6 +42,7 @@
"Phone number is invalid": "Номер телефона является недействительным",
"Session outdated, please login again": "Сессия устарела, пожалуйста, войдите снова",
"The user is forbidden to sign in, please contact the administrator": "Пользователю запрещен вход, пожалуйста, обратитесь к администратору",
+ "The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "Имя пользователя может состоять только из буквенно-цифровых символов, нижних подчеркиваний или дефисов, не может содержать последовательные дефисы или подчеркивания, а также не может начинаться или заканчиваться на дефис или подчеркивание.",
"Username already exists": "Имя пользователя уже существует",
"Username cannot be an email address": "Имя пользователя не может быть адресом электронной почты",
diff --git a/i18n/locales/vn/data.json b/i18n/locales/vn/data.json
index 0e980dc2..f83ccffd 100644
--- a/i18n/locales/vn/data.json
+++ b/i18n/locales/vn/data.json
@@ -32,8 +32,8 @@
"Email is invalid": "Địa chỉ email không hợp lệ",
"Empty username.": "Tên đăng nhập trống.",
"FirstName cannot be blank": "Tên không được để trống",
+ "LDAP user name or password incorrect": "Tên người dùng hoặc mật khẩu Ldap không chính xác",
"LastName cannot be blank": "Họ không thể để trống",
- "Ldap user name or password incorrect": "Tên người dùng hoặc mật khẩu Ldap không chính xác",
"Multiple accounts with same uid, please check your ldap server": "Nhiều tài khoản với cùng một uid, vui lòng kiểm tra máy chủ ldap của bạn",
"Organization does not exist": "Tổ chức không tồn tại",
"Password must have at least 6 characters": "Mật khẩu phải ít nhất 6 ký tự",
@@ -42,6 +42,7 @@
"Phone number is invalid": "Số điện thoại không hợp lệ",
"Session outdated, please login again": "Phiên làm việc hết hạn, vui lòng đăng nhập lại",
"The user is forbidden to sign in, please contact the administrator": "Người dùng bị cấm đăng nhập, vui lòng liên hệ với quản trị viên",
+ "The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "Tên người dùng chỉ có thể chứa các ký tự chữ và số, gạch dưới hoặc gạch ngang, không được có hai ký tự gạch dưới hoặc gạch ngang liền kề và không được bắt đầu hoặc kết thúc bằng dấu gạch dưới hoặc gạch ngang.",
"Username already exists": "Tên đăng nhập đã tồn tại",
"Username cannot be an email address": "Tên người dùng không thể là địa chỉ email",
diff --git a/i18n/locales/zh/data.json b/i18n/locales/zh/data.json
index 356d4152..7f5332bc 100644
--- a/i18n/locales/zh/data.json
+++ b/i18n/locales/zh/data.json
@@ -32,8 +32,8 @@
"Email is invalid": "无效邮箱",
"Empty username.": "用户名不可为空",
"FirstName cannot be blank": "名不可以为空",
+ "LDAP user name or password incorrect": "LDAP密码错误",
"LastName cannot be blank": "姓不可以为空",
- "Ldap user name or password incorrect": "LDAP密码错误",
"Multiple accounts with same uid, please check your ldap server": "多个帐户具有相同的uid,请检查您的 LDAP 服务器",
"Organization does not exist": "组织不存在",
"Password must have at least 6 characters": "新密码至少为6位",
@@ -42,6 +42,7 @@
"Phone number is invalid": "无效手机号",
"Session outdated, please login again": "会话已过期,请重新登录",
"The user is forbidden to sign in, please contact the administrator": "该用户被禁止登录,请联系管理员",
+ "The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "用户名只能包含字母数字字符、下划线或连字符,不能有连续的连字符或下划线,也不能以连字符或下划线开头或结尾",
"Username already exists": "用户名已存在",
"Username cannot be an email address": "用户名不可以是邮箱地址",
diff --git a/init_data.json.template b/init_data.json.template
index 5aa15f8d..46710975 100644
--- a/init_data.json.template
+++ b/init_data.json.template
@@ -159,8 +159,8 @@
"serverName": "",
"host": "",
"port": 389,
- "admin": "",
- "passwd": "",
+ "username": "",
+ "password": "",
"baseDn": "",
"autoSync": 0,
"lastSync": ""
diff --git a/ldap/server.go b/ldap/server.go
index fc488ae5..f67853a3 100644
--- a/ldap/server.go
+++ b/ldap/server.go
@@ -110,12 +110,11 @@ func handleSearch(w ldap.ResponseWriter, m *ldap.Message) {
for _, user := range users {
dn := fmt.Sprintf("cn=%s,%s", user.Name, string(r.BaseObject()))
e := ldap.NewSearchResultEntry(dn)
- e.AddAttribute("cn", message.AttributeValue(user.Name))
- e.AddAttribute("uid", message.AttributeValue(user.Name))
- e.AddAttribute("email", message.AttributeValue(user.Email))
- e.AddAttribute("mobile", message.AttributeValue(user.Phone))
- e.AddAttribute("userPassword", message.AttributeValue(getUserPasswordWithType(user)))
- // e.AddAttribute("postalAddress", message.AttributeValue(user.Address[0]))
+
+ for _, attr := range r.Attributes() {
+ e.AddAttribute(message.AttributeDescription(attr), getAttribute(string(attr), user))
+ }
+
w.Write(e)
}
w.Write(res)
diff --git a/ldap/util.go b/ldap/util.go
index 1674f425..499e3757 100644
--- a/ldap/util.go
+++ b/ldap/util.go
@@ -21,6 +21,7 @@ import (
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
+ "github.com/lor00x/goldap/message"
ldap "github.com/forestmgy/ldapserver"
)
@@ -68,6 +69,7 @@ func getUsername(filter string) string {
func GetFilteredUsers(m *ldap.Message) (filteredUsers []*object.User, code int) {
r := m.GetSearchRequest()
+
name, org, code := getNameAndOrgFromFilter(string(r.BaseObject()), r.FilterString())
if code != ldap.LDAPResultSuccess {
return nil, code
@@ -114,3 +116,20 @@ func getUserPasswordWithType(user *object.User) string {
}
return fmt.Sprintf("{%s}%s", prefix, user.Password)
}
+
+func getAttribute(attributeName string, user *object.User) message.AttributeValue {
+ switch attributeName {
+ case "cn":
+ return message.AttributeValue(user.Name)
+ case "uid":
+ return message.AttributeValue(user.Name)
+ case "email":
+ return message.AttributeValue(user.Email)
+ case "mobile":
+ return message.AttributeValue(user.Phone)
+ case "userPassword":
+ return message.AttributeValue(getUserPasswordWithType(user))
+ default:
+ return ""
+ }
+}
diff --git a/object/check.go b/object/check.go
index 879d256f..a4359d3c 100644
--- a/object/check.go
+++ b/object/check.go
@@ -188,29 +188,33 @@ func CheckPassword(user *User, password string, lang string) string {
}
}
-func checkLdapUserPassword(user *User, password string, lang string) (*User, string) {
+func checkLdapUserPassword(user *User, password string, lang string) string {
ldaps := GetLdaps(user.Owner)
ldapLoginSuccess := false
+ hit := false
+
for _, ldapServer := range ldaps {
conn, err := ldapServer.GetLdapConn()
if err != nil {
continue
}
- SearchFilter := fmt.Sprintf("(&(objectClass=posixAccount)(uid=%s))", user.Name)
- searchReq := goldap.NewSearchRequest(ldapServer.BaseDn,
- goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false,
- SearchFilter, []string{}, nil)
+
+ searchReq := goldap.NewSearchRequest(ldapServer.BaseDn, goldap.ScopeWholeSubtree, goldap.NeverDerefAliases,
+ 0, 0, false, ldapServer.buildFilterString(user), []string{}, nil)
+
searchResult, err := conn.Conn.Search(searchReq)
if err != nil {
- return nil, err.Error()
+ return err.Error()
}
if len(searchResult.Entries) == 0 {
continue
- } else if len(searchResult.Entries) > 1 {
- return nil, i18n.Translate(lang, "check:Multiple accounts with same uid, please check your ldap server")
+ }
+ if len(searchResult.Entries) > 1 {
+ return i18n.Translate(lang, "check:Multiple accounts with same uid, please check your ldap server")
}
+ hit = true
dn := searchResult.Entries[0].DN
if err := conn.Conn.Bind(dn, password); err == nil {
ldapLoginSuccess = true
@@ -219,9 +223,12 @@ func checkLdapUserPassword(user *User, password string, lang string) (*User, str
}
if !ldapLoginSuccess {
- return nil, i18n.Translate(lang, "check:Ldap user name or password incorrect")
+ if !hit {
+ return "user not exist"
+ }
+ return i18n.Translate(lang, "check:LDAP user name or password incorrect")
}
- return user, ""
+ return ""
}
func CheckUserPassword(organization string, username string, password string, lang string) (*User, string) {
@@ -236,10 +243,14 @@ func CheckUserPassword(organization string, username string, password string, la
if user.Ldap != "" {
// ONLY for ldap users
- return checkLdapUserPassword(user, password, lang)
+ if msg := checkLdapUserPassword(user, password, lang); msg != "" {
+ if msg == "user not exist" {
+ return nil, fmt.Sprintf(i18n.Translate(lang, "check:The user: %s doesn't exist in LDAP server"), username)
+ }
+ return nil, msg
+ }
} else {
- msg := CheckPassword(user, password, lang)
- if msg != "" {
+ if msg := CheckPassword(user, password, lang); msg != "" {
return nil, msg
}
}
diff --git a/object/init.go b/object/init.go
index 29473825..73619b2c 100644
--- a/object/init.go
+++ b/object/init.go
@@ -219,8 +219,8 @@ func initBuiltInLdap() {
ServerName: "BuildIn LDAP Server",
Host: "example.com",
Port: 389,
- Admin: "cn=buildin,dc=example,dc=com",
- Passwd: "123",
+ Username: "cn=buildin,dc=example,dc=com",
+ Password: "123",
BaseDn: "ou=BuildIn,dc=example,dc=com",
AutoSync: 0,
LastSync: "",
diff --git a/object/ldap.go b/object/ldap.go
index f7f441c5..49c4b0b8 100644
--- a/object/ldap.go
+++ b/object/ldap.go
@@ -15,14 +15,7 @@
package object
import (
- "errors"
- "fmt"
- "strings"
-
- "github.com/beego/beego"
"github.com/casdoor/casdoor/util"
- goldap "github.com/go-ldap/ldap/v3"
- "github.com/thanhpk/randstr"
)
type Ldap struct {
@@ -30,263 +23,20 @@ type Ldap struct {
Owner string `xorm:"varchar(100)" json:"owner"`
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
- ServerName string `xorm:"varchar(100)" json:"serverName"`
- Host string `xorm:"varchar(100)" json:"host"`
- Port int `json:"port"`
- EnableSsl bool `xorm:"bool" json:"enableSsl"`
- Admin string `xorm:"varchar(100)" json:"admin"`
- Passwd string `xorm:"varchar(100)" json:"passwd"`
- BaseDn string `xorm:"varchar(100)" json:"baseDn"`
+ ServerName string `xorm:"varchar(100)" json:"serverName"`
+ Host string `xorm:"varchar(100)" json:"host"`
+ Port int `xorm:"int" json:"port"`
+ EnableSsl bool `xorm:"bool" json:"enableSsl"`
+ Username string `xorm:"varchar(100)" json:"username"`
+ Password string `xorm:"varchar(100)" json:"password"`
+ BaseDn string `xorm:"varchar(100)" json:"baseDn"`
+ Filter string `xorm:"varchar(200)" json:"filter"`
+ FilterFields []string `xorm:"varchar(100)" json:"filterFields"`
AutoSync int `json:"autoSync"`
LastSync string `xorm:"varchar(100)" json:"lastSync"`
}
-type ldapConn struct {
- Conn *goldap.Conn
- IsAD bool
-}
-
-//type ldapGroup struct {
-// GidNumber string
-// Cn string
-//}
-
-type ldapUser struct {
- UidNumber string
- Uid string
- Cn string
- GidNumber string
- // Gcn string
- Uuid string
- Mail string
- Email string
- EmailAddress string
- TelephoneNumber string
- Mobile string
- MobileTelephoneNumber string
- RegisteredAddress string
- PostalAddress string
-}
-
-type LdapRespUser struct {
- UidNumber string `json:"uidNumber"`
- Uid string `json:"uid"`
- Cn string `json:"cn"`
- GroupId string `json:"groupId"`
- // GroupName string `json:"groupName"`
- Uuid string `json:"uuid"`
- Email string `json:"email"`
- Phone string `json:"phone"`
- Address string `json:"address"`
-}
-
-type ldapServerType struct {
- Vendorname string
- Vendorversion string
- IsGlobalCatalogReady string
- ForestFunctionality string
-}
-
-func LdapUsersToLdapRespUsers(users []ldapUser) []LdapRespUser {
- returnAnyNotEmpty := func(strs ...string) string {
- for _, str := range strs {
- if str != "" {
- return str
- }
- }
- return ""
- }
-
- res := make([]LdapRespUser, 0)
- for _, user := range users {
- res = append(res, LdapRespUser{
- UidNumber: user.UidNumber,
- Uid: user.Uid,
- Cn: user.Cn,
- GroupId: user.GidNumber,
- Uuid: user.Uuid,
- Email: returnAnyNotEmpty(user.Email, user.EmailAddress, user.Mail),
- Phone: returnAnyNotEmpty(user.Mobile, user.MobileTelephoneNumber, user.TelephoneNumber),
- Address: returnAnyNotEmpty(user.PostalAddress, user.RegisteredAddress),
- })
- }
- return res
-}
-
-func isMicrosoftAD(Conn *goldap.Conn) (bool, error) {
- SearchFilter := "(objectClass=*)"
- SearchAttributes := []string{"vendorname", "vendorversion", "isGlobalCatalogReady", "forestFunctionality"}
-
- searchReq := goldap.NewSearchRequest("",
- goldap.ScopeBaseObject, goldap.NeverDerefAliases, 0, 0, false,
- SearchFilter, SearchAttributes, nil)
- searchResult, err := Conn.Search(searchReq)
- if err != nil {
- return false, err
- }
- if len(searchResult.Entries) == 0 {
- return false, nil
- }
- isMicrosoft := false
- var ldapServerType ldapServerType
- for _, entry := range searchResult.Entries {
- for _, attribute := range entry.Attributes {
- switch attribute.Name {
- case "vendorname":
- ldapServerType.Vendorname = attribute.Values[0]
- case "vendorversion":
- ldapServerType.Vendorversion = attribute.Values[0]
- case "isGlobalCatalogReady":
- ldapServerType.IsGlobalCatalogReady = attribute.Values[0]
- case "forestFunctionality":
- ldapServerType.ForestFunctionality = attribute.Values[0]
- }
- }
- }
- if ldapServerType.Vendorname == "" &&
- ldapServerType.Vendorversion == "" &&
- ldapServerType.IsGlobalCatalogReady == "TRUE" &&
- ldapServerType.ForestFunctionality != "" {
- isMicrosoft = true
- }
- return isMicrosoft, err
-}
-
-func (ldap *Ldap) GetLdapConn() (c *ldapConn, err error) {
- var conn *goldap.Conn
- if ldap.EnableSsl {
- conn, err = goldap.DialTLS("tcp", fmt.Sprintf("%s:%d", ldap.Host, ldap.Port), nil)
- } else {
- conn, err = goldap.Dial("tcp", fmt.Sprintf("%s:%d", ldap.Host, ldap.Port))
- }
-
- if err != nil {
- return nil, err
- }
-
- err = conn.Bind(ldap.Admin, ldap.Passwd)
- if err != nil {
- return nil, err
- }
-
- isAD, err := isMicrosoftAD(conn)
- if err != nil {
- return nil, err
- }
- return &ldapConn{Conn: conn, IsAD: isAD}, nil
-}
-
-//FIXME: The Base DN does not necessarily contain the Group
-//func (l *ldapConn) GetLdapGroups(baseDn string) (map[string]ldapGroup, error) {
-// SearchFilter := "(objectClass=posixGroup)"
-// SearchAttributes := []string{"cn", "gidNumber"}
-// groupMap := make(map[string]ldapGroup)
-//
-// searchReq := goldap.NewSearchRequest(baseDn,
-// goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false,
-// SearchFilter, SearchAttributes, nil)
-// searchResult, err := l.Conn.Search(searchReq)
-// if err != nil {
-// return nil, err
-// }
-//
-// if len(searchResult.Entries) == 0 {
-// return nil, errors.New("no result")
-// }
-//
-// for _, entry := range searchResult.Entries {
-// var ldapGroupItem ldapGroup
-// for _, attribute := range entry.Attributes {
-// switch attribute.Name {
-// case "gidNumber":
-// ldapGroupItem.GidNumber = attribute.Values[0]
-// break
-// case "cn":
-// ldapGroupItem.Cn = attribute.Values[0]
-// break
-// }
-// }
-// groupMap[ldapGroupItem.GidNumber] = ldapGroupItem
-// }
-//
-// return groupMap, nil
-//}
-
-func (l *ldapConn) GetLdapUsers(baseDn string) ([]ldapUser, error) {
- SearchFilter := "(objectClass=posixAccount)"
- SearchAttributes := []string{
- "uidNumber", "uid", "cn", "gidNumber", "entryUUID", "mail", "email",
- "emailAddress", "telephoneNumber", "mobile", "mobileTelephoneNumber", "registeredAddress", "postalAddress",
- }
- SearchFilterMsAD := "(objectClass=user)"
- SearchAttributesMsAD := []string{
- "uidNumber", "sAMAccountName", "cn", "gidNumber", "entryUUID", "mail", "email",
- "emailAddress", "telephoneNumber", "mobile", "mobileTelephoneNumber", "registeredAddress", "postalAddress",
- }
- var searchReq *goldap.SearchRequest
- if l.IsAD {
- searchReq = goldap.NewSearchRequest(baseDn,
- goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false,
- SearchFilterMsAD, SearchAttributesMsAD, nil)
- } else {
- searchReq = goldap.NewSearchRequest(baseDn,
- goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false,
- SearchFilter, SearchAttributes, nil)
- }
- searchResult, err := l.Conn.SearchWithPaging(searchReq, 100)
- if err != nil {
- return nil, err
- }
-
- if len(searchResult.Entries) == 0 {
- return nil, errors.New("no result")
- }
-
- var ldapUsers []ldapUser
-
- for _, entry := range searchResult.Entries {
- var ldapUserItem ldapUser
- for _, attribute := range entry.Attributes {
- switch attribute.Name {
- case "uidNumber":
- ldapUserItem.UidNumber = attribute.Values[0]
- case "uid":
- ldapUserItem.Uid = attribute.Values[0]
- case "sAMAccountName":
- ldapUserItem.Uid = attribute.Values[0]
- case "cn":
- ldapUserItem.Cn = attribute.Values[0]
- case "gidNumber":
- ldapUserItem.GidNumber = attribute.Values[0]
- case "entryUUID":
- ldapUserItem.Uuid = attribute.Values[0]
- case "objectGUID":
- ldapUserItem.Uuid = attribute.Values[0]
- case "mail":
- ldapUserItem.Mail = attribute.Values[0]
- case "email":
- ldapUserItem.Email = attribute.Values[0]
- case "emailAddress":
- ldapUserItem.EmailAddress = attribute.Values[0]
- case "telephoneNumber":
- ldapUserItem.TelephoneNumber = attribute.Values[0]
- case "mobile":
- ldapUserItem.Mobile = attribute.Values[0]
- case "mobileTelephoneNumber":
- ldapUserItem.MobileTelephoneNumber = attribute.Values[0]
- case "registeredAddress":
- ldapUserItem.RegisteredAddress = attribute.Values[0]
- case "postalAddress":
- ldapUserItem.PostalAddress = attribute.Values[0]
- }
- }
- ldapUsers = append(ldapUsers, ldapUserItem)
- }
-
- return ldapUsers, nil
-}
-
func AddLdap(ldap *Ldap) bool {
if len(ldap.Id) == 0 {
ldap.Id = util.GenerateId()
@@ -307,12 +57,12 @@ func AddLdap(ldap *Ldap) bool {
func CheckLdapExist(ldap *Ldap) bool {
var result []*Ldap
err := adapter.Engine.Find(&result, &Ldap{
- Owner: ldap.Owner,
- Host: ldap.Host,
- Port: ldap.Port,
- Admin: ldap.Admin,
- Passwd: ldap.Passwd,
- BaseDn: ldap.BaseDn,
+ Owner: ldap.Owner,
+ Host: ldap.Host,
+ Port: ldap.Port,
+ Username: ldap.Username,
+ Password: ldap.Password,
+ BaseDn: ldap.BaseDn,
})
if err != nil {
panic(err)
@@ -359,7 +109,7 @@ func UpdateLdap(ldap *Ldap) bool {
}
affected, err := adapter.Engine.ID(ldap.Id).Cols("owner", "server_name", "host",
- "port", "enable_ssl", "admin", "passwd", "base_dn", "auto_sync").Update(ldap)
+ "port", "enable_ssl", "username", "password", "base_dn", "filter", "filter_fields", "auto_sync").Update(ldap)
if err != nil {
panic(err)
}
@@ -375,123 +125,3 @@ func DeleteLdap(ldap *Ldap) bool {
return affected != 0
}
-
-func SyncLdapUsers(owner string, users []LdapRespUser, ldapId string) (*[]LdapRespUser, *[]LdapRespUser) {
- var existUsers []LdapRespUser
- var failedUsers []LdapRespUser
- var uuids []string
-
- for _, user := range users {
- uuids = append(uuids, user.Uuid)
- }
-
- existUuids := CheckLdapUuidExist(owner, uuids)
-
- organization := getOrganization("admin", owner)
- ldap := GetLdap(ldapId)
-
- var dc []string
- for _, basedn := range strings.Split(ldap.BaseDn, ",") {
- if strings.Contains(basedn, "dc=") {
- dc = append(dc, basedn[3:])
- }
- }
- affiliation := strings.Join(dc, ".")
-
- var ou []string
- for _, admin := range strings.Split(ldap.Admin, ",") {
- if strings.Contains(admin, "ou=") {
- ou = append(ou, admin[3:])
- }
- }
- tag := strings.Join(ou, ".")
-
- for _, user := range users {
- found := false
- if len(existUuids) > 0 {
- for _, existUuid := range existUuids {
- if user.Uuid == existUuid {
- existUsers = append(existUsers, user)
- found = true
- }
- }
- }
-
- if !found && !AddUser(&User{
- Owner: owner,
- Name: buildLdapUserName(user.Uid, user.UidNumber),
- CreatedTime: util.GetCurrentTime(),
- DisplayName: user.Cn,
- Avatar: organization.DefaultAvatar,
- Email: user.Email,
- Phone: user.Phone,
- Address: []string{user.Address},
- Affiliation: affiliation,
- Tag: tag,
- Score: beego.AppConfig.DefaultInt("initScore", 2000),
- Ldap: user.Uuid,
- }) {
- failedUsers = append(failedUsers, user)
- continue
- }
- }
-
- return &existUsers, &failedUsers
-}
-
-func UpdateLdapSyncTime(ldapId string) {
- _, err := adapter.Engine.ID(ldapId).Update(&Ldap{LastSync: util.GetCurrentTime()})
- if err != nil {
- panic(err)
- }
-}
-
-func CheckLdapUuidExist(owner string, uuids []string) []string {
- var results []User
- var existUuids []string
- existUuidSet := make(map[string]struct{})
-
- //whereStr := ""
- //for i, uuid := range uuids {
- // if i == 0 {
- // whereStr = fmt.Sprintf("'%s'", uuid)
- // } else {
- // whereStr = fmt.Sprintf(",'%s'", uuid)
- // }
- //}
-
- err := adapter.Engine.Where(fmt.Sprintf("ldap IN (%s) AND owner = ?", "'"+strings.Join(uuids, "','")+"'"), owner).Find(&results)
- if err != nil {
- panic(err)
- }
-
- if len(results) > 0 {
- for _, result := range results {
- existUuidSet[result.Ldap] = struct{}{}
- }
- }
-
- for uuid := range existUuidSet {
- existUuids = append(existUuids, uuid)
- }
- return existUuids
-}
-
-func buildLdapUserName(uid, uidNum string) string {
- var result User
- uidWithNumber := fmt.Sprintf("%s_%s", uid, uidNum)
-
- has, err := adapter.Engine.Where("name = ? or name = ?", uid, uidWithNumber).Get(&result)
- if err != nil {
- panic(err)
- }
-
- if has {
- if result.Name == uid {
- return uidWithNumber
- }
- return fmt.Sprintf("%s_%s", uidWithNumber, randstr.Hex(6))
- }
-
- return uid
-}
diff --git a/object/ldap_autosync.go b/object/ldap_autosync.go
index 88cb7ab8..1a31ea01 100644
--- a/object/ldap_autosync.go
+++ b/object/ldap_autosync.go
@@ -82,7 +82,7 @@ func (l *LdapAutoSynchronizer) syncRoutine(ldap *Ldap, stopChan chan struct{}) {
continue
}
- users, err := conn.GetLdapUsers(ldap.BaseDn)
+ users, err := conn.GetLdapUsers(ldap)
if err != nil {
logs.Warning(fmt.Sprintf("autoSync failed for %s, error %s", ldap.Id, err))
continue
@@ -112,3 +112,10 @@ func (l *LdapAutoSynchronizer) LdapAutoSynchronizerStartUpAll() {
}
}
}
+
+func UpdateLdapSyncTime(ldapId string) {
+ _, err := adapter.Engine.ID(ldapId).Update(&Ldap{LastSync: util.GetCurrentTime()})
+ if err != nil {
+ panic(err)
+ }
+}
diff --git a/object/ldap_conn.go b/object/ldap_conn.go
new file mode 100644
index 00000000..e221e859
--- /dev/null
+++ b/object/ldap_conn.go
@@ -0,0 +1,403 @@
+// Copyright 2023 The Casdoor Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package object
+
+import (
+ "errors"
+ "fmt"
+ "strings"
+
+ "github.com/beego/beego"
+ "github.com/casdoor/casdoor/util"
+ goldap "github.com/go-ldap/ldap/v3"
+ "github.com/thanhpk/randstr"
+)
+
+type LdapConn struct {
+ Conn *goldap.Conn
+ IsAD bool
+}
+
+//type ldapGroup struct {
+// GidNumber string
+// Cn string
+//}
+
+type ldapUser struct {
+ UidNumber string
+ Uid string
+ Cn string
+ GidNumber string
+ // Gcn string
+ Uuid string
+ DisplayName string
+ Mail string
+ Email string
+ EmailAddress string
+ TelephoneNumber string
+ Mobile string
+ MobileTelephoneNumber string
+ RegisteredAddress string
+ PostalAddress string
+}
+
+type LdapRespUser struct {
+ UidNumber string `json:"uidNumber"`
+ Uid string `json:"uid"`
+ Cn string `json:"cn"`
+ GroupId string `json:"groupId"`
+ // GroupName string `json:"groupName"`
+ Uuid string `json:"uuid"`
+ DisplayName string `json:"displayName"`
+ Email string `json:"email"`
+ Phone string `json:"phone"`
+ Address string `json:"address"`
+}
+
+func (ldap *Ldap) GetLdapConn() (c *LdapConn, err error) {
+ var conn *goldap.Conn
+ if ldap.EnableSsl {
+ conn, err = goldap.DialTLS("tcp", fmt.Sprintf("%s:%d", ldap.Host, ldap.Port), nil)
+ } else {
+ conn, err = goldap.Dial("tcp", fmt.Sprintf("%s:%d", ldap.Host, ldap.Port))
+ }
+
+ if err != nil {
+ return nil, err
+ }
+
+ err = conn.Bind(ldap.Username, ldap.Password)
+ if err != nil {
+ return nil, err
+ }
+
+ isAD, err := isMicrosoftAD(conn)
+ if err != nil {
+ return nil, err
+ }
+ return &LdapConn{Conn: conn, IsAD: isAD}, nil
+}
+
+func isMicrosoftAD(Conn *goldap.Conn) (bool, error) {
+ SearchFilter := "(objectClass=*)"
+ SearchAttributes := []string{"vendorname", "vendorversion", "isGlobalCatalogReady", "forestFunctionality"}
+
+ searchReq := goldap.NewSearchRequest("",
+ goldap.ScopeBaseObject, goldap.NeverDerefAliases, 0, 0, false,
+ SearchFilter, SearchAttributes, nil)
+ searchResult, err := Conn.Search(searchReq)
+ if err != nil {
+ return false, err
+ }
+ if len(searchResult.Entries) == 0 {
+ return false, nil
+ }
+ isMicrosoft := false
+
+ type ldapServerType struct {
+ Vendorname string
+ Vendorversion string
+ IsGlobalCatalogReady string
+ ForestFunctionality string
+ }
+ var ldapServerTypes ldapServerType
+ for _, entry := range searchResult.Entries {
+ for _, attribute := range entry.Attributes {
+ switch attribute.Name {
+ case "vendorname":
+ ldapServerTypes.Vendorname = attribute.Values[0]
+ case "vendorversion":
+ ldapServerTypes.Vendorversion = attribute.Values[0]
+ case "isGlobalCatalogReady":
+ ldapServerTypes.IsGlobalCatalogReady = attribute.Values[0]
+ case "forestFunctionality":
+ ldapServerTypes.ForestFunctionality = attribute.Values[0]
+ }
+ }
+ }
+ if ldapServerTypes.Vendorname == "" &&
+ ldapServerTypes.Vendorversion == "" &&
+ ldapServerTypes.IsGlobalCatalogReady == "TRUE" &&
+ ldapServerTypes.ForestFunctionality != "" {
+ isMicrosoft = true
+ }
+ return isMicrosoft, err
+}
+
+func (l *LdapConn) GetLdapUsers(ldapServer *Ldap) ([]ldapUser, error) {
+ SearchAttributes := []string{
+ "uidNumber", "cn", "sn", "gidNumber", "entryUUID", "displayName", "mail", "email",
+ "emailAddress", "telephoneNumber", "mobile", "mobileTelephoneNumber", "registeredAddress", "postalAddress",
+ }
+ if l.IsAD {
+ SearchAttributes = append(SearchAttributes, "sAMAccountName")
+ } else {
+ SearchAttributes = append(SearchAttributes, "uid")
+ }
+
+ searchReq := goldap.NewSearchRequest(ldapServer.BaseDn, goldap.ScopeWholeSubtree, goldap.NeverDerefAliases,
+ 0, 0, false,
+ ldapServer.Filter, SearchAttributes, nil)
+ searchResult, err := l.Conn.SearchWithPaging(searchReq, 100)
+ if err != nil {
+ return nil, err
+ }
+
+ if len(searchResult.Entries) == 0 {
+ return nil, errors.New("no result")
+ }
+
+ var ldapUsers []ldapUser
+ for _, entry := range searchResult.Entries {
+ var user ldapUser
+ for _, attribute := range entry.Attributes {
+ switch attribute.Name {
+ case "uidNumber":
+ user.UidNumber = attribute.Values[0]
+ case "uid":
+ user.Uid = attribute.Values[0]
+ case "sAMAccountName":
+ user.Uid = attribute.Values[0]
+ case "cn":
+ user.Cn = attribute.Values[0]
+ case "gidNumber":
+ user.GidNumber = attribute.Values[0]
+ case "entryUUID":
+ user.Uuid = attribute.Values[0]
+ case "objectGUID":
+ user.Uuid = attribute.Values[0]
+ case "displayName":
+ user.DisplayName = attribute.Values[0]
+ case "mail":
+ user.Mail = attribute.Values[0]
+ case "email":
+ user.Email = attribute.Values[0]
+ case "emailAddress":
+ user.EmailAddress = attribute.Values[0]
+ case "telephoneNumber":
+ user.TelephoneNumber = attribute.Values[0]
+ case "mobile":
+ user.Mobile = attribute.Values[0]
+ case "mobileTelephoneNumber":
+ user.MobileTelephoneNumber = attribute.Values[0]
+ case "registeredAddress":
+ user.RegisteredAddress = attribute.Values[0]
+ case "postalAddress":
+ user.PostalAddress = attribute.Values[0]
+ }
+ }
+ ldapUsers = append(ldapUsers, user)
+ }
+
+ return ldapUsers, nil
+}
+
+// FIXME: The Base DN does not necessarily contain the Group
+//
+// func (l *ldapConn) GetLdapGroups(baseDn string) (map[string]ldapGroup, error) {
+// SearchFilter := "(objectClass=posixGroup)"
+// SearchAttributes := []string{"cn", "gidNumber"}
+// groupMap := make(map[string]ldapGroup)
+//
+// searchReq := goldap.NewSearchRequest(baseDn,
+// goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false,
+// SearchFilter, SearchAttributes, nil)
+// searchResult, err := l.Conn.Search(searchReq)
+// if err != nil {
+// return nil, err
+// }
+//
+// if len(searchResult.Entries) == 0 {
+// return nil, errors.New("no result")
+// }
+//
+// for _, entry := range searchResult.Entries {
+// var ldapGroupItem ldapGroup
+// for _, attribute := range entry.Attributes {
+// switch attribute.Name {
+// case "gidNumber":
+// ldapGroupItem.GidNumber = attribute.Values[0]
+// break
+// case "cn":
+// ldapGroupItem.Cn = attribute.Values[0]
+// break
+// }
+// }
+// groupMap[ldapGroupItem.GidNumber] = ldapGroupItem
+// }
+//
+// return groupMap, nil
+// }
+
+func LdapUsersToLdapRespUsers(users []ldapUser) []LdapRespUser {
+ res := make([]LdapRespUser, 0)
+ for _, user := range users {
+ res = append(res, LdapRespUser{
+ UidNumber: user.UidNumber,
+ Uid: user.Uid,
+ Cn: user.Cn,
+ GroupId: user.GidNumber,
+ Uuid: user.Uuid,
+ DisplayName: user.DisplayName,
+ Email: util.ReturnAnyNotEmpty(user.Email, user.EmailAddress, user.Mail),
+ Phone: util.ReturnAnyNotEmpty(user.Mobile, user.MobileTelephoneNumber, user.TelephoneNumber),
+ Address: util.ReturnAnyNotEmpty(user.PostalAddress, user.RegisteredAddress),
+ })
+ }
+ return res
+}
+
+func SyncLdapUsers(owner string, respUsers []LdapRespUser, ldapId string) (*[]LdapRespUser, *[]LdapRespUser) {
+ var existUsers []LdapRespUser
+ var failedUsers []LdapRespUser
+ var uuids []string
+
+ for _, user := range respUsers {
+ uuids = append(uuids, user.Uuid)
+ }
+
+ existUuids := CheckLdapUuidExist(owner, uuids)
+
+ organization := getOrganization("admin", owner)
+ ldap := GetLdap(ldapId)
+
+ var dc []string
+ for _, basedn := range strings.Split(ldap.BaseDn, ",") {
+ if strings.Contains(basedn, "dc=") {
+ dc = append(dc, basedn[3:])
+ }
+ }
+ affiliation := strings.Join(dc, ".")
+
+ var ou []string
+ for _, admin := range strings.Split(ldap.Username, ",") {
+ if strings.Contains(admin, "ou=") {
+ ou = append(ou, admin[3:])
+ }
+ }
+ tag := strings.Join(ou, ".")
+
+ for _, respUser := range respUsers {
+ found := false
+ if len(existUuids) > 0 {
+ for _, existUuid := range existUuids {
+ if respUser.Uuid == existUuid {
+ existUsers = append(existUsers, respUser)
+ found = true
+ }
+ }
+ }
+
+ if !found {
+ newUser := &User{
+ Owner: owner,
+ Name: respUser.buildLdapUserName(),
+ CreatedTime: util.GetCurrentTime(),
+ DisplayName: respUser.buildLdapDisplayName(),
+ Avatar: organization.DefaultAvatar,
+ Email: respUser.Email,
+ Phone: respUser.Phone,
+ Address: []string{respUser.Address},
+ Affiliation: affiliation,
+ Tag: tag,
+ Score: beego.AppConfig.DefaultInt("initScore", 2000),
+ Ldap: respUser.Uuid,
+ }
+
+ affected := AddUser(newUser)
+ if !affected {
+ failedUsers = append(failedUsers, respUser)
+ continue
+ }
+ }
+ }
+
+ return &existUsers, &failedUsers
+}
+
+func CheckLdapUuidExist(owner string, uuids []string) []string {
+ var results []User
+ var existUuids []string
+ existUuidSet := make(map[string]struct{})
+
+ err := adapter.Engine.Where(fmt.Sprintf("ldap IN (%s) AND owner = ?", "'"+strings.Join(uuids, "','")+"'"), owner).Find(&results)
+ if err != nil {
+ panic(err)
+ }
+
+ if len(results) > 0 {
+ for _, result := range results {
+ existUuidSet[result.Ldap] = struct{}{}
+ }
+ }
+
+ for uuid := range existUuidSet {
+ existUuids = append(existUuids, uuid)
+ }
+ return existUuids
+}
+
+func (ldapUser *LdapRespUser) buildLdapUserName() string {
+ user := User{}
+ uidWithNumber := fmt.Sprintf("%s_%s", ldapUser.Uid, ldapUser.UidNumber)
+ has, err := adapter.Engine.Where("name = ? or name = ?", ldapUser.Uid, uidWithNumber).Get(&user)
+ if err != nil {
+ panic(err)
+ }
+
+ if has {
+ if user.Name == ldapUser.Uid {
+ return uidWithNumber
+ }
+ return fmt.Sprintf("%s_%s", uidWithNumber, randstr.Hex(6))
+ }
+
+ return ldapUser.Uid
+}
+
+func (ldapUser *LdapRespUser) buildLdapDisplayName() string {
+ if ldapUser.DisplayName != "" {
+ return ldapUser.DisplayName
+ }
+
+ return ldapUser.Cn
+}
+
+func (ldap *Ldap) buildFilterString(user *User) string {
+ if len(ldap.FilterFields) == 0 {
+ return fmt.Sprintf("(&%s(uid=%s))", ldap.Filter, user.Name)
+ }
+
+ filter := fmt.Sprintf("(&%s(|", ldap.Filter)
+ for _, field := range ldap.FilterFields {
+ filter = fmt.Sprintf("%s(%s=%s)", filter, field, user.getFieldFromLdapAttribute(field))
+ }
+ filter = fmt.Sprintf("%s))", filter)
+
+ return filter
+}
+
+func (user *User) getFieldFromLdapAttribute(attribute string) string {
+ switch attribute {
+ case "uid":
+ return user.Name
+ case "mail":
+ return user.Email
+ case "mobile":
+ return user.Phone
+ default:
+ return ""
+ }
+}
diff --git a/util/slice.go b/util/slice.go
index 6fb95f8f..8767f8cb 100644
--- a/util/slice.go
+++ b/util/slice.go
@@ -30,3 +30,12 @@ func ContainsString(values []string, val string) bool {
sort.Strings(values)
return sort.SearchStrings(values, val) != len(values)
}
+
+func ReturnAnyNotEmpty(strs ...string) string {
+ for _, str := range strs {
+ if str != "" {
+ return str
+ }
+ }
+ return ""
+}
diff --git a/web/src/LdapEditPage.js b/web/src/LdapEditPage.js
index 259bad36..19086d5d 100644
--- a/web/src/LdapEditPage.js
+++ b/web/src/LdapEditPage.js
@@ -166,13 +166,37 @@ class LdapEditPage extends React.Component {
}} />
+