mirror of
https://github.com/casdoor/casdoor.git
synced 2025-05-23 02:35:49 +08:00
feat: add LDAP custom filter support (#1719)
* refactor: improve ldap server code * feat: custom filter * fix: fix displayName mapping * feat: add custom filter search fields * chore: add license * chore: i18n * chore: i18n * chore: update init field
This commit is contained in:
parent
968d8646b2
commit
1b1de1dd01
@ -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
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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": "ユーザー名には電子メールアドレスを使用できません",
|
||||
|
@ -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": "사용자 이름은 이메일 주소가 될 수 없습니다",
|
||||
|
@ -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": "Имя пользователя не может быть адресом электронной почты",
|
||||
|
@ -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",
|
||||
|
@ -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": "用户名不可以是邮箱地址",
|
||||
|
@ -159,8 +159,8 @@
|
||||
"serverName": "",
|
||||
"host": "",
|
||||
"port": 389,
|
||||
"admin": "",
|
||||
"passwd": "",
|
||||
"username": "",
|
||||
"password": "",
|
||||
"baseDn": "",
|
||||
"autoSync": 0,
|
||||
"lastSync": ""
|
||||
|
@ -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)
|
||||
|
19
ldap/util.go
19
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 ""
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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: "",
|
||||
|
402
object/ldap.go
402
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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
403
object/ldap_conn.go
Normal file
403
object/ldap_conn.go
Normal file
@ -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 ""
|
||||
}
|
||||
}
|
@ -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 ""
|
||||
}
|
||||
|
@ -166,13 +166,37 @@ class LdapEditPage extends React.Component {
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}}>
|
||||
<Col style={{lineHeight: "32px", textAlign: "right", paddingRight: "25px"}} span={3}>
|
||||
{Setting.getLabel(i18next.t("ldap:Search Filter"), i18next.t("ldap:Search Filter - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={21}>
|
||||
<Input value={this.state.ldap.filter} onChange={e => {
|
||||
this.updateLdapField("filter", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}}>
|
||||
<Col style={{lineHeight: "32px", textAlign: "right", paddingRight: "25px"}} span={3}>
|
||||
{Setting.getLabel(i18next.t("ldap:Filter fields"), i18next.t("ldap:Filter fields - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={21}>
|
||||
<Select value={this.state.ldap.filterFields ?? []} style={{width: "100%"}} mode={"multiple"} options={[
|
||||
{value: "uid", label: "uid"},
|
||||
{value: "mail", label: "Email"},
|
||||
{value: "mobile", label: "mobile"},
|
||||
].map((item) => Setting.getOption(item.label, item.value))} onChange={value => {
|
||||
this.updateLdapField("filterFields", value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}}>
|
||||
<Col style={{lineHeight: "32px", textAlign: "right", paddingRight: "25px"}} span={3}>
|
||||
{Setting.getLabel(i18next.t("ldap:Admin"), i18next.t("ldap:Admin - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={21}>
|
||||
<Input value={this.state.ldap.admin} onChange={e => {
|
||||
this.updateLdapField("admin", e.target.value);
|
||||
<Input value={this.state.ldap.username} onChange={e => {
|
||||
this.updateLdapField("username", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
@ -182,9 +206,9 @@ class LdapEditPage extends React.Component {
|
||||
</Col>
|
||||
<Col span={21}>
|
||||
<Input.Password
|
||||
iconRender={visible => (visible ? <EyeTwoTone /> : <EyeInvisibleOutlined />)} value={this.state.ldap.passwd}
|
||||
iconRender={visible => (visible ? <EyeTwoTone /> : <EyeInvisibleOutlined />)} value={this.state.ldap.password}
|
||||
onChange={e => {
|
||||
this.updateLdapField("passwd", e.target.value);
|
||||
this.updateLdapField("password", e.target.value);
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
|
@ -1,192 +0,0 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Col, Row, Table} from "antd";
|
||||
import * as Setting from "./Setting";
|
||||
import * as LdapBackend from "./backend/LdapBackend";
|
||||
import i18next from "i18next";
|
||||
import PopconfirmModal from "./PopconfirmModal";
|
||||
|
||||
class LdapListPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
ldaps: null,
|
||||
};
|
||||
}
|
||||
|
||||
UNSAFE_componentWillMount() {
|
||||
this.getLdaps();
|
||||
}
|
||||
|
||||
getLdaps() {
|
||||
LdapBackend.getLdaps("")
|
||||
.then((res) => {
|
||||
let ldapsData = [];
|
||||
if (res.status === "ok") {
|
||||
ldapsData = res.data;
|
||||
} else {
|
||||
Setting.showMessage("error", res.msg);
|
||||
}
|
||||
this.setState((prevState) => {
|
||||
prevState.ldaps = ldapsData;
|
||||
return prevState;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
deleteLdap(index) {
|
||||
|
||||
}
|
||||
|
||||
renderTable(ldaps) {
|
||||
const columns = [
|
||||
{
|
||||
title: i18next.t("ldap:Server name"),
|
||||
dataIndex: "serverName",
|
||||
key: "serverName",
|
||||
width: "200px",
|
||||
sorter: (a, b) => a.serverName.localeCompare(b.serverName),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/ldaps/${record.id}`}>
|
||||
{text}
|
||||
</Link>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Organization"),
|
||||
dataIndex: "owner",
|
||||
key: "owner",
|
||||
width: "140px",
|
||||
sorter: (a, b) => a.owner.localeCompare(b.owner),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/organizations/${text}`}>
|
||||
{text}
|
||||
</Link>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("ldap:Server"),
|
||||
dataIndex: "host",
|
||||
key: "host",
|
||||
ellipsis: true,
|
||||
sorter: (a, b) => a.host.localeCompare(b.host),
|
||||
render: (text, record, index) => {
|
||||
return `${text}:${record.port}`;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("ldap:Base DN"),
|
||||
dataIndex: "baseDn",
|
||||
key: "baseDn",
|
||||
ellipsis: true,
|
||||
sorter: (a, b) => a.baseDn.localeCompare(b.baseDn),
|
||||
},
|
||||
{
|
||||
title: i18next.t("ldap:Admin"),
|
||||
dataIndex: "admin",
|
||||
key: "admin",
|
||||
ellipsis: true,
|
||||
sorter: (a, b) => a.admin.localeCompare(b.admin),
|
||||
},
|
||||
{
|
||||
title: i18next.t("ldap:Auto Sync"),
|
||||
dataIndex: "autoSync",
|
||||
key: "autoSync",
|
||||
width: "100px",
|
||||
sorter: (a, b) => a.autoSync.localeCompare(b.autoSync),
|
||||
render: (text, record, index) => {
|
||||
return text === 0 ? (<span style={{color: "#faad14"}}>Disable</span>) : (
|
||||
<span style={{color: "#52c41a"}}>{text + " mins"}</span>);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("ldap:Last Sync"),
|
||||
dataIndex: "lastSync",
|
||||
key: "lastSync",
|
||||
ellipsis: true,
|
||||
sorter: (a, b) => a.lastSync.localeCompare(b.lastSync),
|
||||
render: (text, record, index) => {
|
||||
return text;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Action"),
|
||||
dataIndex: "",
|
||||
key: "op",
|
||||
width: "240px",
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<div>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}}
|
||||
type="primary"
|
||||
onClick={() => Setting.goToLink(`/ldap/sync/${record.id}`)}>{i18next.t("general:Sync")}</Button>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}}
|
||||
onClick={() => Setting.goToLink(`/ldap/${record.id}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<PopconfirmModal
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.serverName} ?`}
|
||||
onConfirm={() => this.deleteLdap(index)}
|
||||
>
|
||||
</PopconfirmModal>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Table columns={columns} dataSource={ldaps} rowKey="id" size="middle" bordered
|
||||
pagination={{pageSize: 100}}
|
||||
title={() => (
|
||||
<div>
|
||||
<span>{i18next.t("general:LDAPs")}</span>
|
||||
<Button type="primary" size="small" style={{marginLeft: "10px"}}
|
||||
onClick={() => {
|
||||
this.addLdap();
|
||||
}}>{i18next.t("general:Add")}</Button>
|
||||
</div>
|
||||
)}
|
||||
loading={ldaps === null}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Row style={{width: "100%"}}>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
{
|
||||
this.renderTable(this.state.ldaps)
|
||||
}
|
||||
</Col>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default LdapListPage;
|
@ -117,6 +117,15 @@
|
||||
"Scope - Tooltip": "Nutzungsszenarien des Zertifikats",
|
||||
"Type - Tooltip": "Art des Zertifikats"
|
||||
},
|
||||
"chat": {
|
||||
"Edit Chat": "Edit Chat",
|
||||
"Message count": "Message count",
|
||||
"New Chat": "New Chat",
|
||||
"Sub users": "Sub users",
|
||||
"Sub users - Tooltip": "Sub users - Tooltip",
|
||||
"User1": "User1",
|
||||
"User2": "User2"
|
||||
},
|
||||
"code": {
|
||||
"Code you received": "Der Code, den Sie erhalten haben",
|
||||
"Email code": "E-Mail-Code",
|
||||
@ -151,6 +160,7 @@
|
||||
"Application": "Applikation",
|
||||
"Applications": "Anwendungen",
|
||||
"Applications that require authentication": "Anwendungen, die eine Authentifizierung erfordern",
|
||||
"Author - Tooltip": "Author - Tooltip",
|
||||
"Avatar": "Avatar",
|
||||
"Avatar - Tooltip": "Öffentliches Avatarbild für den Benutzer",
|
||||
"Back Home": "Zurück nach Hause",
|
||||
@ -159,6 +169,7 @@
|
||||
"Cert": "Zertifikat",
|
||||
"Cert - Tooltip": "Das Public-Key-Zertifikat, das vom Client-SDK, das mit dieser Anwendung korrespondiert, verifiziert werden muss",
|
||||
"Certs": "Zertifikate",
|
||||
"Chats": "Chats",
|
||||
"Click to Upload": "Klicken Sie zum Hochladen",
|
||||
"Client IP": "Client-IP",
|
||||
"Close": "Schließen",
|
||||
@ -203,6 +214,7 @@
|
||||
"Master password": "Hauptpasswort",
|
||||
"Master password - Tooltip": "Kann zum Einloggen aller Benutzer unter dieser Organisation verwendet werden, was es Administratoren bequem macht, sich als dieser Benutzer einzuloggen, um technische Probleme zu lösen",
|
||||
"Menu": "Menü",
|
||||
"Messages": "Messages",
|
||||
"Method": "Methode",
|
||||
"Model": "Modell",
|
||||
"Model - Tooltip": "Casbin-Zugriffskontrollmodell",
|
||||
@ -269,11 +281,14 @@
|
||||
"URL": "URL",
|
||||
"URL - Tooltip": "URL-Link",
|
||||
"Up": "Oben",
|
||||
"Updated time": "Updated time",
|
||||
"User": "Nutzer",
|
||||
"User - Tooltip": "Stellen Sie sicher, dass der Benutzername korrekt ist",
|
||||
"User containers": "Nutzerpools",
|
||||
"User type": "Benutzertyp",
|
||||
"User type - Tooltip": "Tags, denen der Benutzer angehört, standardmäßig auf \"normaler Benutzer\" festgelegt",
|
||||
"User1 - Tooltip": "User1 - Tooltip",
|
||||
"User2 - Tooltip": "User2 - Tooltip",
|
||||
"Users": "Benutzer",
|
||||
"Users under all organizations": "Benutzer unter allen Organisationen",
|
||||
"Webhooks": "Webhooks",
|
||||
@ -293,8 +308,12 @@
|
||||
"Edit LDAP": "LDAP bearbeiten",
|
||||
"Enable SSL": "Aktivieren Sie SSL",
|
||||
"Enable SSL - Tooltip": "Ob SSL aktiviert werden soll",
|
||||
"Filter fields": "Filter fields",
|
||||
"Filter fields - Tooltip": "Filter fields - Tooltip",
|
||||
"Group ID": "Gruppen-ID",
|
||||
"Last Sync": "Letzte Synchronisation",
|
||||
"Search Filter": "Search Filter",
|
||||
"Search Filter - Tooltip": "Search Filter - Tooltip",
|
||||
"Server": "Server",
|
||||
"Server host": "Server Host",
|
||||
"Server host - Tooltip": "LDAP-Server-Adresse",
|
||||
@ -331,6 +350,15 @@
|
||||
"sign up now": "Melde dich jetzt an",
|
||||
"username, Email or phone": "Benutzername, E-Mail oder Telefon"
|
||||
},
|
||||
"message": {
|
||||
"Author": "Author",
|
||||
"Chat": "Chat",
|
||||
"Chat - Tooltip": "Chat - Tooltip",
|
||||
"Edit Message": "Edit Message",
|
||||
"New Message": "New Message",
|
||||
"Text": "Text",
|
||||
"Text - Tooltip": "Text - Tooltip"
|
||||
},
|
||||
"model": {
|
||||
"Edit Model": "Modell bearbeiten",
|
||||
"Model text": "Modelltext",
|
||||
|
@ -117,6 +117,15 @@
|
||||
"Scope - Tooltip": "Usage scenarios of the certificate",
|
||||
"Type - Tooltip": "Type of certificate"
|
||||
},
|
||||
"chat": {
|
||||
"Edit Chat": "Edit Chat",
|
||||
"Message count": "Message count",
|
||||
"New Chat": "New Chat",
|
||||
"Sub users": "Sub users",
|
||||
"Sub users - Tooltip": "Sub users - Tooltip",
|
||||
"User1": "User1",
|
||||
"User2": "User2"
|
||||
},
|
||||
"code": {
|
||||
"Code you received": "Code you received",
|
||||
"Email code": "Email code",
|
||||
@ -151,6 +160,7 @@
|
||||
"Application": "Application",
|
||||
"Applications": "Applications",
|
||||
"Applications that require authentication": "Applications that require authentication",
|
||||
"Author - Tooltip": "Author - Tooltip",
|
||||
"Avatar": "Avatar",
|
||||
"Avatar - Tooltip": "Public avatar image for the user",
|
||||
"Back Home": "Back Home",
|
||||
@ -159,6 +169,7 @@
|
||||
"Cert": "Cert",
|
||||
"Cert - Tooltip": "The public key certificate that needs to be verified by the client SDK corresponding to this application",
|
||||
"Certs": "Certs",
|
||||
"Chats": "Chats",
|
||||
"Click to Upload": "Click to Upload",
|
||||
"Client IP": "Client IP",
|
||||
"Close": "Close",
|
||||
@ -203,6 +214,7 @@
|
||||
"Master password": "Master password",
|
||||
"Master password - Tooltip": "Can be used to log in to all users under this organization, making it convenient for administrators to log in as this user to solve technical issues",
|
||||
"Menu": "Menu",
|
||||
"Messages": "Messages",
|
||||
"Method": "Method",
|
||||
"Model": "Model",
|
||||
"Model - Tooltip": "Casbin access control model",
|
||||
@ -269,11 +281,14 @@
|
||||
"URL": "URL",
|
||||
"URL - Tooltip": "URL link",
|
||||
"Up": "Up",
|
||||
"Updated time": "Updated time",
|
||||
"User": "User",
|
||||
"User - Tooltip": "Make sure the username is correct",
|
||||
"User containers": "User pools",
|
||||
"User type": "User type",
|
||||
"User type - Tooltip": "Tags that the user belongs to, defaulting to \"normal-user\"",
|
||||
"User1 - Tooltip": "User1 - Tooltip",
|
||||
"User2 - Tooltip": "User2 - Tooltip",
|
||||
"Users": "Users",
|
||||
"Users under all organizations": "Users under all organizations",
|
||||
"Webhooks": "Webhooks",
|
||||
@ -293,8 +308,12 @@
|
||||
"Edit LDAP": "Edit LDAP",
|
||||
"Enable SSL": "Enable SSL",
|
||||
"Enable SSL - Tooltip": "Whether to enable SSL",
|
||||
"Filter fields": "Filter fields",
|
||||
"Filter fields - Tooltip": "Filter fields - Tooltip",
|
||||
"Group ID": "Group ID",
|
||||
"Last Sync": "Last Sync",
|
||||
"Search Filter": "Search Filter",
|
||||
"Search Filter - Tooltip": "Search Filter - Tooltip",
|
||||
"Server": "Server",
|
||||
"Server host": "Server host",
|
||||
"Server host - Tooltip": "LDAP server address",
|
||||
@ -331,6 +350,15 @@
|
||||
"sign up now": "sign up now",
|
||||
"username, Email or phone": "username, Email or phone"
|
||||
},
|
||||
"message": {
|
||||
"Author": "Author",
|
||||
"Chat": "Chat",
|
||||
"Chat - Tooltip": "Chat - Tooltip",
|
||||
"Edit Message": "Edit Message",
|
||||
"New Message": "New Message",
|
||||
"Text": "Text",
|
||||
"Text - Tooltip": "Text - Tooltip"
|
||||
},
|
||||
"model": {
|
||||
"Edit Model": "Edit Model",
|
||||
"Model text": "Model text",
|
||||
|
@ -117,6 +117,15 @@
|
||||
"Scope - Tooltip": "Escenarios de uso del certificado",
|
||||
"Type - Tooltip": "Tipo de certificado"
|
||||
},
|
||||
"chat": {
|
||||
"Edit Chat": "Edit Chat",
|
||||
"Message count": "Message count",
|
||||
"New Chat": "New Chat",
|
||||
"Sub users": "Sub users",
|
||||
"Sub users - Tooltip": "Sub users - Tooltip",
|
||||
"User1": "User1",
|
||||
"User2": "User2"
|
||||
},
|
||||
"code": {
|
||||
"Code you received": "Código que recibió",
|
||||
"Email code": "Código de correo electrónico",
|
||||
@ -151,6 +160,7 @@
|
||||
"Application": "Aplicación",
|
||||
"Applications": "Aplicaciones",
|
||||
"Applications that require authentication": "Aplicaciones que requieren autenticación",
|
||||
"Author - Tooltip": "Author - Tooltip",
|
||||
"Avatar": "Avatar",
|
||||
"Avatar - Tooltip": "Imagen de avatar pública para el usuario",
|
||||
"Back Home": "Regreso a casa",
|
||||
@ -159,6 +169,7 @@
|
||||
"Cert": "ificado",
|
||||
"Cert - Tooltip": "El certificado de clave pública que necesita ser verificado por el SDK del cliente correspondiente a esta aplicación",
|
||||
"Certs": "Certificaciones",
|
||||
"Chats": "Chats",
|
||||
"Click to Upload": "Haz clic para cargar",
|
||||
"Client IP": "Dirección IP del cliente",
|
||||
"Close": "Cerca",
|
||||
@ -203,6 +214,7 @@
|
||||
"Master password": "Contraseña maestra",
|
||||
"Master password - Tooltip": "Se puede usar para iniciar sesión en todos los usuarios de esta organización, lo que hace conveniente que los administradores inicien sesión como este usuario para resolver problemas técnicos",
|
||||
"Menu": "Menú",
|
||||
"Messages": "Messages",
|
||||
"Method": "Método",
|
||||
"Model": "Modelo",
|
||||
"Model - Tooltip": "Modelo de control de acceso Casbin",
|
||||
@ -269,11 +281,14 @@
|
||||
"URL": "Dirección URL",
|
||||
"URL - Tooltip": "Enlace de URL",
|
||||
"Up": "Arriba",
|
||||
"Updated time": "Updated time",
|
||||
"User": "Usuario",
|
||||
"User - Tooltip": "Asegúrate de que el nombre de usuario sea correcto",
|
||||
"User containers": "Piscinas de usuarios",
|
||||
"User type": "Tipo de usuario",
|
||||
"User type - Tooltip": "Etiquetas a las que el usuario pertenece, con una configuración predeterminada en \"usuario-normal\"",
|
||||
"User1 - Tooltip": "User1 - Tooltip",
|
||||
"User2 - Tooltip": "User2 - Tooltip",
|
||||
"Users": "Usuarios",
|
||||
"Users under all organizations": "Usuarios bajo todas las organizaciones",
|
||||
"Webhooks": "Webhooks",
|
||||
@ -293,8 +308,12 @@
|
||||
"Edit LDAP": "Editar LDAP",
|
||||
"Enable SSL": "Habilitar SSL",
|
||||
"Enable SSL - Tooltip": "Si se habilita SSL",
|
||||
"Filter fields": "Filter fields",
|
||||
"Filter fields - Tooltip": "Filter fields - Tooltip",
|
||||
"Group ID": "Identificador de grupo",
|
||||
"Last Sync": "Última sincronización",
|
||||
"Search Filter": "Search Filter",
|
||||
"Search Filter - Tooltip": "Search Filter - Tooltip",
|
||||
"Server": "Servidor",
|
||||
"Server host": "Anfitrión del servidor",
|
||||
"Server host - Tooltip": "Dirección del servidor LDAP",
|
||||
@ -331,6 +350,15 @@
|
||||
"sign up now": "Regístrate ahora",
|
||||
"username, Email or phone": "Nombre de usuario, correo electrónico o teléfono"
|
||||
},
|
||||
"message": {
|
||||
"Author": "Author",
|
||||
"Chat": "Chat",
|
||||
"Chat - Tooltip": "Chat - Tooltip",
|
||||
"Edit Message": "Edit Message",
|
||||
"New Message": "New Message",
|
||||
"Text": "Text",
|
||||
"Text - Tooltip": "Text - Tooltip"
|
||||
},
|
||||
"model": {
|
||||
"Edit Model": "Editar modelo",
|
||||
"Model text": "Texto modelo",
|
||||
|
@ -117,6 +117,15 @@
|
||||
"Scope - Tooltip": "Scénarios d'utilisation du certificat",
|
||||
"Type - Tooltip": "Type de certificat"
|
||||
},
|
||||
"chat": {
|
||||
"Edit Chat": "Edit Chat",
|
||||
"Message count": "Message count",
|
||||
"New Chat": "New Chat",
|
||||
"Sub users": "Sub users",
|
||||
"Sub users - Tooltip": "Sub users - Tooltip",
|
||||
"User1": "User1",
|
||||
"User2": "User2"
|
||||
},
|
||||
"code": {
|
||||
"Code you received": "Le code que vous avez reçu",
|
||||
"Email code": "Code email",
|
||||
@ -151,6 +160,7 @@
|
||||
"Application": "Application",
|
||||
"Applications": "Applications",
|
||||
"Applications that require authentication": "Applications qui nécessitent une authentification",
|
||||
"Author - Tooltip": "Author - Tooltip",
|
||||
"Avatar": "Avatar",
|
||||
"Avatar - Tooltip": "Image d'avatar public pour l'utilisateur",
|
||||
"Back Home": "Retour à la maison",
|
||||
@ -159,6 +169,7 @@
|
||||
"Cert": "ainement",
|
||||
"Cert - Tooltip": "Le certificat de clé publique qui doit être vérifié par le kit de développement client correspondant à cette application",
|
||||
"Certs": "Certains",
|
||||
"Chats": "Chats",
|
||||
"Click to Upload": "Cliquez pour télécharger",
|
||||
"Client IP": "Adresse IP du client",
|
||||
"Close": "Fermer",
|
||||
@ -203,6 +214,7 @@
|
||||
"Master password": "Mot de passe principal",
|
||||
"Master password - Tooltip": "Peut être utilisé pour se connecter à tous les utilisateurs sous cette organisation, ce qui facilite la connexion des administrateurs en tant que cet utilisateur pour résoudre les problèmes techniques",
|
||||
"Menu": "Menu",
|
||||
"Messages": "Messages",
|
||||
"Method": "Méthode",
|
||||
"Model": "Modèle",
|
||||
"Model - Tooltip": "Modèle de contrôle d'accès Casbin",
|
||||
@ -269,11 +281,14 @@
|
||||
"URL": "URL",
|
||||
"URL - Tooltip": "Lien d'URL",
|
||||
"Up": "Haut",
|
||||
"Updated time": "Updated time",
|
||||
"User": "Utilisateur",
|
||||
"User - Tooltip": "Assurez-vous que le nom d'utilisateur est correct",
|
||||
"User containers": "Piscines d'utilisateurs",
|
||||
"User type": "Type d'utilisateur",
|
||||
"User type - Tooltip": "Balises auxquelles l'utilisateur appartient, avec une valeur par défaut \"utilisateur-normal\"",
|
||||
"User1 - Tooltip": "User1 - Tooltip",
|
||||
"User2 - Tooltip": "User2 - Tooltip",
|
||||
"Users": "Utilisateurs",
|
||||
"Users under all organizations": "Utilisateurs sous toutes les organisations",
|
||||
"Webhooks": "Webhooks",
|
||||
@ -293,8 +308,12 @@
|
||||
"Edit LDAP": "Modifier LDAP",
|
||||
"Enable SSL": "Activer SSL",
|
||||
"Enable SSL - Tooltip": "Que ce soit pour activer SSL",
|
||||
"Filter fields": "Filter fields",
|
||||
"Filter fields - Tooltip": "Filter fields - Tooltip",
|
||||
"Group ID": "Identifiant de groupe",
|
||||
"Last Sync": "Dernière synchronisation",
|
||||
"Search Filter": "Search Filter",
|
||||
"Search Filter - Tooltip": "Search Filter - Tooltip",
|
||||
"Server": "Serveur",
|
||||
"Server host": "Hébergeur de serveur",
|
||||
"Server host - Tooltip": "Adresse du serveur LDAP",
|
||||
@ -331,6 +350,15 @@
|
||||
"sign up now": "Inscrivez-vous maintenant",
|
||||
"username, Email or phone": "Nom d'utilisateur, e-mail ou téléphone"
|
||||
},
|
||||
"message": {
|
||||
"Author": "Author",
|
||||
"Chat": "Chat",
|
||||
"Chat - Tooltip": "Chat - Tooltip",
|
||||
"Edit Message": "Edit Message",
|
||||
"New Message": "New Message",
|
||||
"Text": "Text",
|
||||
"Text - Tooltip": "Text - Tooltip"
|
||||
},
|
||||
"model": {
|
||||
"Edit Model": "Modifier le modèle",
|
||||
"Model text": "Texte modèle",
|
||||
|
@ -117,6 +117,15 @@
|
||||
"Scope - Tooltip": "Skema penggunaan sertifikat:",
|
||||
"Type - Tooltip": "Jenis sertifikat"
|
||||
},
|
||||
"chat": {
|
||||
"Edit Chat": "Edit Chat",
|
||||
"Message count": "Message count",
|
||||
"New Chat": "New Chat",
|
||||
"Sub users": "Sub users",
|
||||
"Sub users - Tooltip": "Sub users - Tooltip",
|
||||
"User1": "User1",
|
||||
"User2": "User2"
|
||||
},
|
||||
"code": {
|
||||
"Code you received": "Kode yang kamu terima",
|
||||
"Email code": "Kode email",
|
||||
@ -151,6 +160,7 @@
|
||||
"Application": "Aplikasi",
|
||||
"Applications": "Aplikasi",
|
||||
"Applications that require authentication": "Aplikasi yang memerlukan autentikasi",
|
||||
"Author - Tooltip": "Author - Tooltip",
|
||||
"Avatar": "Avatar",
|
||||
"Avatar - Tooltip": "Gambar avatar publik untuk pengguna",
|
||||
"Back Home": "Kembali ke Rumah",
|
||||
@ -159,6 +169,7 @@
|
||||
"Cert": "Sertifikat",
|
||||
"Cert - Tooltip": "Sertifikat kunci publik yang perlu diverifikasi oleh SDK klien yang sesuai dengan aplikasi ini",
|
||||
"Certs": "Sertifikat",
|
||||
"Chats": "Chats",
|
||||
"Click to Upload": "Klik untuk Mengunggah",
|
||||
"Client IP": "IP klien",
|
||||
"Close": "Tutup",
|
||||
@ -203,6 +214,7 @@
|
||||
"Master password": "Kata sandi utama",
|
||||
"Master password - Tooltip": "Dapat digunakan untuk masuk ke semua pengguna di bawah organisasi ini, sehingga memudahkan administrator untuk masuk sebagai pengguna ini untuk menyelesaikan masalah teknis",
|
||||
"Menu": "Daftar makanan",
|
||||
"Messages": "Messages",
|
||||
"Method": "Metode",
|
||||
"Model": "Model",
|
||||
"Model - Tooltip": "Model kontrol akses Casbin",
|
||||
@ -269,11 +281,14 @@
|
||||
"URL": "URL",
|
||||
"URL - Tooltip": "Tautan URL",
|
||||
"Up": "Ke atas",
|
||||
"Updated time": "Updated time",
|
||||
"User": "Pengguna",
|
||||
"User - Tooltip": "Pastikan username-nya benar",
|
||||
"User containers": "User pools",
|
||||
"User type": "Jenis pengguna",
|
||||
"User type - Tooltip": "Tag yang dimiliki oleh pengguna, defaultnya adalah \"normal-user\"",
|
||||
"User1 - Tooltip": "User1 - Tooltip",
|
||||
"User2 - Tooltip": "User2 - Tooltip",
|
||||
"Users": "Pengguna-pengguna",
|
||||
"Users under all organizations": "Pengguna di bawah semua organisasi",
|
||||
"Webhooks": "Webhooks",
|
||||
@ -293,8 +308,12 @@
|
||||
"Edit LDAP": "Mengedit LDAP",
|
||||
"Enable SSL": "Aktifkan SSL",
|
||||
"Enable SSL - Tooltip": "Apakah untuk mengaktifkan SSL?",
|
||||
"Filter fields": "Filter fields",
|
||||
"Filter fields - Tooltip": "Filter fields - Tooltip",
|
||||
"Group ID": "ID grup",
|
||||
"Last Sync": "Terakhir Sinkronisasi",
|
||||
"Search Filter": "Search Filter",
|
||||
"Search Filter - Tooltip": "Search Filter - Tooltip",
|
||||
"Server": "Server",
|
||||
"Server host": "Hewan Server",
|
||||
"Server host - Tooltip": "Alamat server LDAP",
|
||||
@ -331,6 +350,15 @@
|
||||
"sign up now": "Daftar sekarang",
|
||||
"username, Email or phone": "nama pengguna, Email atau nomor telepon"
|
||||
},
|
||||
"message": {
|
||||
"Author": "Author",
|
||||
"Chat": "Chat",
|
||||
"Chat - Tooltip": "Chat - Tooltip",
|
||||
"Edit Message": "Edit Message",
|
||||
"New Message": "New Message",
|
||||
"Text": "Text",
|
||||
"Text - Tooltip": "Text - Tooltip"
|
||||
},
|
||||
"model": {
|
||||
"Edit Model": "Mengedit Model",
|
||||
"Model text": "Teks Model",
|
||||
|
@ -117,6 +117,15 @@
|
||||
"Scope - Tooltip": "証明書の使用シナリオ",
|
||||
"Type - Tooltip": "証明書の種類"
|
||||
},
|
||||
"chat": {
|
||||
"Edit Chat": "Edit Chat",
|
||||
"Message count": "Message count",
|
||||
"New Chat": "New Chat",
|
||||
"Sub users": "Sub users",
|
||||
"Sub users - Tooltip": "Sub users - Tooltip",
|
||||
"User1": "User1",
|
||||
"User2": "User2"
|
||||
},
|
||||
"code": {
|
||||
"Code you received": "受け取ったコード",
|
||||
"Email code": "メールコード",
|
||||
@ -151,6 +160,7 @@
|
||||
"Application": "アプリケーション",
|
||||
"Applications": "アプリケーション",
|
||||
"Applications that require authentication": "認証が必要なアプリケーション",
|
||||
"Author - Tooltip": "Author - Tooltip",
|
||||
"Avatar": "アバター",
|
||||
"Avatar - Tooltip": "ユーザーのパブリックアバター画像",
|
||||
"Back Home": "帰宅",
|
||||
@ -159,6 +169,7 @@
|
||||
"Cert": "証明書",
|
||||
"Cert - Tooltip": "このアプリケーションに対応するクライアントSDKによって検証する必要がある公開鍵証明書",
|
||||
"Certs": "証明書",
|
||||
"Chats": "Chats",
|
||||
"Click to Upload": "アップロードするにはクリックしてください",
|
||||
"Client IP": "クライアントIP",
|
||||
"Close": "閉じる",
|
||||
@ -203,6 +214,7 @@
|
||||
"Master password": "マスターパスワード",
|
||||
"Master password - Tooltip": "この組織のすべてのユーザーにログインするために使用でき、管理者が技術的な問題を解決するためにこのユーザーとしてログインするのに便利です",
|
||||
"Menu": "メニュー",
|
||||
"Messages": "Messages",
|
||||
"Method": "方法",
|
||||
"Model": "モデル",
|
||||
"Model - Tooltip": "カスビンアクセスコントロールモデル",
|
||||
@ -269,11 +281,14 @@
|
||||
"URL": "URL",
|
||||
"URL - Tooltip": "URLリンク",
|
||||
"Up": "アップ",
|
||||
"Updated time": "Updated time",
|
||||
"User": "ユーザー",
|
||||
"User - Tooltip": "ユーザー名が正しいことを確認してください",
|
||||
"User containers": "ユーザープール",
|
||||
"User type": "ユーザータイプ",
|
||||
"User type - Tooltip": "ユーザーが属するタグは、デフォルトでは「通常ユーザー」となります",
|
||||
"User1 - Tooltip": "User1 - Tooltip",
|
||||
"User2 - Tooltip": "User2 - Tooltip",
|
||||
"Users": "ユーザー",
|
||||
"Users under all organizations": "すべての組織のユーザー",
|
||||
"Webhooks": "Webhooks",
|
||||
@ -293,8 +308,12 @@
|
||||
"Edit LDAP": "LDAPを編集",
|
||||
"Enable SSL": "SSL を有効にする",
|
||||
"Enable SSL - Tooltip": "SSLを有効にするかどうか",
|
||||
"Filter fields": "Filter fields",
|
||||
"Filter fields - Tooltip": "Filter fields - Tooltip",
|
||||
"Group ID": "グループID",
|
||||
"Last Sync": "最後の同期",
|
||||
"Search Filter": "Search Filter",
|
||||
"Search Filter - Tooltip": "Search Filter - Tooltip",
|
||||
"Server": "サーバー",
|
||||
"Server host": "サーバーホスト",
|
||||
"Server host - Tooltip": "LDAPサーバーのアドレス",
|
||||
@ -331,6 +350,15 @@
|
||||
"sign up now": "今すぐサインアップ",
|
||||
"username, Email or phone": "ユーザー名、メールアドレス、または電話番号"
|
||||
},
|
||||
"message": {
|
||||
"Author": "Author",
|
||||
"Chat": "Chat",
|
||||
"Chat - Tooltip": "Chat - Tooltip",
|
||||
"Edit Message": "Edit Message",
|
||||
"New Message": "New Message",
|
||||
"Text": "Text",
|
||||
"Text - Tooltip": "Text - Tooltip"
|
||||
},
|
||||
"model": {
|
||||
"Edit Model": "編集モデル",
|
||||
"Model text": "モデルテキスト",
|
||||
|
@ -117,6 +117,15 @@
|
||||
"Scope - Tooltip": "인증서의 사용 시나리오",
|
||||
"Type - Tooltip": "증명서 유형"
|
||||
},
|
||||
"chat": {
|
||||
"Edit Chat": "Edit Chat",
|
||||
"Message count": "Message count",
|
||||
"New Chat": "New Chat",
|
||||
"Sub users": "Sub users",
|
||||
"Sub users - Tooltip": "Sub users - Tooltip",
|
||||
"User1": "User1",
|
||||
"User2": "User2"
|
||||
},
|
||||
"code": {
|
||||
"Code you received": "받은 코드",
|
||||
"Email code": "이메일 코드",
|
||||
@ -151,6 +160,7 @@
|
||||
"Application": "응용 프로그램",
|
||||
"Applications": "응용 프로그램",
|
||||
"Applications that require authentication": "인증이 필요한 애플리케이션들",
|
||||
"Author - Tooltip": "Author - Tooltip",
|
||||
"Avatar": "아바타",
|
||||
"Avatar - Tooltip": "사용자를 위한 공개 아바타 이미지",
|
||||
"Back Home": "집으로 돌아오기",
|
||||
@ -159,6 +169,7 @@
|
||||
"Cert": "인증서",
|
||||
"Cert - Tooltip": "이 응용 프로그램에 해당하는 클라이언트 SDK에서 확인해야 하는 공개 키 인증서",
|
||||
"Certs": "증명서",
|
||||
"Chats": "Chats",
|
||||
"Click to Upload": "클릭하여 업로드하세요",
|
||||
"Client IP": "고객 IP",
|
||||
"Close": "닫다",
|
||||
@ -203,6 +214,7 @@
|
||||
"Master password": "마스터 비밀번호",
|
||||
"Master password - Tooltip": "이 조직의 모든 사용자에게 로그인하는 데 사용될 수 있으며, 이 사용자로 로그인하여 기술 문제를 해결하는 관리자에게 편리합니다",
|
||||
"Menu": "메뉴",
|
||||
"Messages": "Messages",
|
||||
"Method": "방법",
|
||||
"Model": "모델",
|
||||
"Model - Tooltip": "Casbin 접근 제어 모델",
|
||||
@ -269,11 +281,14 @@
|
||||
"URL": "URL",
|
||||
"URL - Tooltip": "URL 링크",
|
||||
"Up": "위로",
|
||||
"Updated time": "Updated time",
|
||||
"User": "사용자",
|
||||
"User - Tooltip": "사용자 이름이 정확한지 확인하세요",
|
||||
"User containers": "사용자 풀",
|
||||
"User type": "사용자 유형",
|
||||
"User type - Tooltip": "사용자가 속한 태그는 기본적으로 \"보통 사용자\"로 설정됩니다",
|
||||
"User1 - Tooltip": "User1 - Tooltip",
|
||||
"User2 - Tooltip": "User2 - Tooltip",
|
||||
"Users": "사용자들",
|
||||
"Users under all organizations": "모든 조직의 사용자",
|
||||
"Webhooks": "Webhooks",
|
||||
@ -293,8 +308,12 @@
|
||||
"Edit LDAP": "LDAP 수정",
|
||||
"Enable SSL": "SSL 활성화",
|
||||
"Enable SSL - Tooltip": "SSL을 활성화할지 여부를 결정하십시오",
|
||||
"Filter fields": "Filter fields",
|
||||
"Filter fields - Tooltip": "Filter fields - Tooltip",
|
||||
"Group ID": "그룹 ID",
|
||||
"Last Sync": "마지막 동기화",
|
||||
"Search Filter": "Search Filter",
|
||||
"Search Filter - Tooltip": "Search Filter - Tooltip",
|
||||
"Server": "서버",
|
||||
"Server host": "서버 호스트",
|
||||
"Server host - Tooltip": "LDAP 서버 주소",
|
||||
@ -331,6 +350,15 @@
|
||||
"sign up now": "지금 가입하세요",
|
||||
"username, Email or phone": "유저명, 이메일 또는 전화번호"
|
||||
},
|
||||
"message": {
|
||||
"Author": "Author",
|
||||
"Chat": "Chat",
|
||||
"Chat - Tooltip": "Chat - Tooltip",
|
||||
"Edit Message": "Edit Message",
|
||||
"New Message": "New Message",
|
||||
"Text": "Text",
|
||||
"Text - Tooltip": "Text - Tooltip"
|
||||
},
|
||||
"model": {
|
||||
"Edit Model": "편집 형태 모델",
|
||||
"Model text": "모델 텍스트",
|
||||
|
@ -117,6 +117,15 @@
|
||||
"Scope - Tooltip": "Сценарии использования сертификата",
|
||||
"Type - Tooltip": "Тип сертификата"
|
||||
},
|
||||
"chat": {
|
||||
"Edit Chat": "Edit Chat",
|
||||
"Message count": "Message count",
|
||||
"New Chat": "New Chat",
|
||||
"Sub users": "Sub users",
|
||||
"Sub users - Tooltip": "Sub users - Tooltip",
|
||||
"User1": "User1",
|
||||
"User2": "User2"
|
||||
},
|
||||
"code": {
|
||||
"Code you received": "Код, который вы получили",
|
||||
"Email code": "Электронный код письма",
|
||||
@ -151,6 +160,7 @@
|
||||
"Application": "Приложение",
|
||||
"Applications": "Приложения",
|
||||
"Applications that require authentication": "Приложения, которые требуют аутентификации",
|
||||
"Author - Tooltip": "Author - Tooltip",
|
||||
"Avatar": "Аватар",
|
||||
"Avatar - Tooltip": "Публичное изображение аватара пользователя",
|
||||
"Back Home": "Домой",
|
||||
@ -159,6 +169,7 @@
|
||||
"Cert": "Сертификат",
|
||||
"Cert - Tooltip": "Сертификат открытого ключа, который требуется проверить клиентским SDK, соответствующим этому приложению",
|
||||
"Certs": "сертификаты",
|
||||
"Chats": "Chats",
|
||||
"Click to Upload": "Нажмите, чтобы загрузить",
|
||||
"Client IP": "Клиентский IP",
|
||||
"Close": "Близко",
|
||||
@ -203,6 +214,7 @@
|
||||
"Master password": "Главный пароль",
|
||||
"Master password - Tooltip": "Можно использовать для входа в учетные записи всех пользователей этой организации, что удобно для администраторов, чтобы войти в качестве этого пользователя и решить технические проблемы",
|
||||
"Menu": "Меню",
|
||||
"Messages": "Messages",
|
||||
"Method": "Метод",
|
||||
"Model": "Модель",
|
||||
"Model - Tooltip": "Модель контроля доступа Casbin",
|
||||
@ -269,11 +281,14 @@
|
||||
"URL": "URL",
|
||||
"URL - Tooltip": "Ссылка URL",
|
||||
"Up": "Вверх",
|
||||
"Updated time": "Updated time",
|
||||
"User": "Пользователь",
|
||||
"User - Tooltip": "Убедитесь, что имя пользователя правильное",
|
||||
"User containers": "Пользовательские пулы",
|
||||
"User type": "Тип пользователя",
|
||||
"User type - Tooltip": "Теги, к которым принадлежит пользователь, по умолчанию \"обычный пользователь\"",
|
||||
"User1 - Tooltip": "User1 - Tooltip",
|
||||
"User2 - Tooltip": "User2 - Tooltip",
|
||||
"Users": "Пользователи",
|
||||
"Users under all organizations": "Пользователи всех организаций",
|
||||
"Webhooks": "Webhooks",
|
||||
@ -293,8 +308,12 @@
|
||||
"Edit LDAP": "Изменить LDAP",
|
||||
"Enable SSL": "Включить SSL",
|
||||
"Enable SSL - Tooltip": "Перевод: Следует ли включать SSL",
|
||||
"Filter fields": "Filter fields",
|
||||
"Filter fields - Tooltip": "Filter fields - Tooltip",
|
||||
"Group ID": "Идентификатор группы",
|
||||
"Last Sync": "Последняя синхронизация",
|
||||
"Search Filter": "Search Filter",
|
||||
"Search Filter - Tooltip": "Search Filter - Tooltip",
|
||||
"Server": "Сервер",
|
||||
"Server host": "Хост сервера",
|
||||
"Server host - Tooltip": "Адрес сервера LDAP",
|
||||
@ -331,6 +350,15 @@
|
||||
"sign up now": "Зарегистрируйтесь сейчас",
|
||||
"username, Email or phone": "имя пользователя, электронная почта или телефон"
|
||||
},
|
||||
"message": {
|
||||
"Author": "Author",
|
||||
"Chat": "Chat",
|
||||
"Chat - Tooltip": "Chat - Tooltip",
|
||||
"Edit Message": "Edit Message",
|
||||
"New Message": "New Message",
|
||||
"Text": "Text",
|
||||
"Text - Tooltip": "Text - Tooltip"
|
||||
},
|
||||
"model": {
|
||||
"Edit Model": "Редактировать модель",
|
||||
"Model text": "Модельный текст",
|
||||
|
@ -117,6 +117,15 @@
|
||||
"Scope - Tooltip": "Các kịch bản sử dụng của giấy chứng nhận",
|
||||
"Type - Tooltip": "Loại chứng chỉ"
|
||||
},
|
||||
"chat": {
|
||||
"Edit Chat": "Edit Chat",
|
||||
"Message count": "Message count",
|
||||
"New Chat": "New Chat",
|
||||
"Sub users": "Sub users",
|
||||
"Sub users - Tooltip": "Sub users - Tooltip",
|
||||
"User1": "User1",
|
||||
"User2": "User2"
|
||||
},
|
||||
"code": {
|
||||
"Code you received": "Mã bạn nhận được",
|
||||
"Email code": "Mã email",
|
||||
@ -151,6 +160,7 @@
|
||||
"Application": "Ứng dụng",
|
||||
"Applications": "Ứng dụng",
|
||||
"Applications that require authentication": "Các ứng dụng yêu cầu xác thực",
|
||||
"Author - Tooltip": "Author - Tooltip",
|
||||
"Avatar": "Ảnh đại diện",
|
||||
"Avatar - Tooltip": "Ảnh đại diện công khai cho người dùng",
|
||||
"Back Home": "Trở về nhà",
|
||||
@ -159,6 +169,7 @@
|
||||
"Cert": "Chứng chỉ",
|
||||
"Cert - Tooltip": "Chứng chỉ khóa công khai cần được xác minh bởi SDK khách hàng tương ứng với ứng dụng này",
|
||||
"Certs": "Chứng chỉ",
|
||||
"Chats": "Chats",
|
||||
"Click to Upload": "Nhấp để tải lên",
|
||||
"Client IP": "Địa chỉ IP của khách hàng",
|
||||
"Close": "Đóng lại",
|
||||
@ -203,6 +214,7 @@
|
||||
"Master password": "Mật khẩu chính",
|
||||
"Master password - Tooltip": "Có thể được sử dụng để đăng nhập vào tất cả các người dùng trong tổ chức này, giúp cho quản trị viên dễ dàng đăng nhập với tư cách người dùng này để giải quyết các vấn đề kỹ thuật",
|
||||
"Menu": "Thực đơn",
|
||||
"Messages": "Messages",
|
||||
"Method": "Phương pháp",
|
||||
"Model": "Mô hình",
|
||||
"Model - Tooltip": "Mô hình kiểm soát truy cập Casbin",
|
||||
@ -269,11 +281,14 @@
|
||||
"URL": "URL",
|
||||
"URL - Tooltip": "Đường dẫn URL",
|
||||
"Up": "Lên",
|
||||
"Updated time": "Updated time",
|
||||
"User": "Người dùng",
|
||||
"User - Tooltip": "Hãy đảm bảo tên đăng nhập chính xác",
|
||||
"User containers": "Nhóm người dùng",
|
||||
"User type": "Loại người dùng",
|
||||
"User type - Tooltip": "Các thẻ mà người dùng thuộc vào, mặc định là \"người dùng bình thường\"",
|
||||
"User1 - Tooltip": "User1 - Tooltip",
|
||||
"User2 - Tooltip": "User2 - Tooltip",
|
||||
"Users": "Người dùng",
|
||||
"Users under all organizations": "Người dùng trong tất cả các tổ chức",
|
||||
"Webhooks": "Webhooks",
|
||||
@ -293,8 +308,12 @@
|
||||
"Edit LDAP": "Chỉnh sửa LDAP",
|
||||
"Enable SSL": "Kích hoạt SSL",
|
||||
"Enable SSL - Tooltip": "Có nên kích hoạt SSL hay không?",
|
||||
"Filter fields": "Filter fields",
|
||||
"Filter fields - Tooltip": "Filter fields - Tooltip",
|
||||
"Group ID": "Nhóm ID",
|
||||
"Last Sync": "Đồng bộ lần cuối",
|
||||
"Search Filter": "Search Filter",
|
||||
"Search Filter - Tooltip": "Search Filter - Tooltip",
|
||||
"Server": "Máy chủ",
|
||||
"Server host": "Máy chủ chủ động",
|
||||
"Server host - Tooltip": "Địa chỉ máy chủ LDAP",
|
||||
@ -331,6 +350,15 @@
|
||||
"sign up now": "Đăng ký ngay bây giờ",
|
||||
"username, Email or phone": "Tên đăng nhập, Email hoặc điện thoại"
|
||||
},
|
||||
"message": {
|
||||
"Author": "Author",
|
||||
"Chat": "Chat",
|
||||
"Chat - Tooltip": "Chat - Tooltip",
|
||||
"Edit Message": "Edit Message",
|
||||
"New Message": "New Message",
|
||||
"Text": "Text",
|
||||
"Text - Tooltip": "Text - Tooltip"
|
||||
},
|
||||
"model": {
|
||||
"Edit Model": "Chỉnh sửa mô hình",
|
||||
"Model text": "Văn bản mẫu",
|
||||
|
@ -117,6 +117,15 @@
|
||||
"Scope - Tooltip": "公钥证书的使用场景",
|
||||
"Type - Tooltip": "公钥证书的类型"
|
||||
},
|
||||
"chat": {
|
||||
"Edit Chat": "Edit Chat",
|
||||
"Message count": "Message count",
|
||||
"New Chat": "New Chat",
|
||||
"Sub users": "Sub users",
|
||||
"Sub users - Tooltip": "Sub users - Tooltip",
|
||||
"User1": "User1",
|
||||
"User2": "User2"
|
||||
},
|
||||
"code": {
|
||||
"Code you received": "验证码",
|
||||
"Email code": "邮箱验证码",
|
||||
@ -151,6 +160,7 @@
|
||||
"Application": "应用",
|
||||
"Applications": "应用",
|
||||
"Applications that require authentication": "需要认证和鉴权的应用",
|
||||
"Author - Tooltip": "Author - Tooltip",
|
||||
"Avatar": "头像",
|
||||
"Avatar - Tooltip": "公开展示的用户头像",
|
||||
"Back Home": "返回到首页",
|
||||
@ -159,6 +169,7 @@
|
||||
"Cert": "证书",
|
||||
"Cert - Tooltip": "该应用所对应的客户端SDK需要验证的公钥证书",
|
||||
"Certs": "证书",
|
||||
"Chats": "Chats",
|
||||
"Click to Upload": "点击上传",
|
||||
"Client IP": "客户端IP",
|
||||
"Close": "关闭",
|
||||
@ -203,6 +214,7 @@
|
||||
"Master password": "万能密码",
|
||||
"Master password - Tooltip": "可用来登录该组织下的所有用户,方便管理员以该用户身份登录,以解决技术问题",
|
||||
"Menu": "目录",
|
||||
"Messages": "Messages",
|
||||
"Method": "方法",
|
||||
"Model": "模型",
|
||||
"Model - Tooltip": "Casbin的访问控制模型",
|
||||
@ -269,11 +281,14 @@
|
||||
"URL": "链接",
|
||||
"URL - Tooltip": "URL链接",
|
||||
"Up": "上移",
|
||||
"Updated time": "Updated time",
|
||||
"User": "用户",
|
||||
"User - Tooltip": "请确保用户名正确",
|
||||
"User containers": "用户池",
|
||||
"User type": "用户类型",
|
||||
"User type - Tooltip": "用户所属的标签,默认为\"normal-user\"",
|
||||
"User1 - Tooltip": "User1 - Tooltip",
|
||||
"User2 - Tooltip": "User2 - Tooltip",
|
||||
"Users": "用户",
|
||||
"Users under all organizations": "所有组织里的用户",
|
||||
"Webhooks": "Webhooks",
|
||||
@ -293,8 +308,12 @@
|
||||
"Edit LDAP": "编辑LDAP",
|
||||
"Enable SSL": "启用SSL",
|
||||
"Enable SSL - Tooltip": "是否启用SSL",
|
||||
"Filter fields": "过滤字段",
|
||||
"Filter fields - Tooltip": "使用ldap用户登录Casdoor时, 用于搜索ldap服务器中该用户的字段 - Tooltip",
|
||||
"Group ID": "组ID",
|
||||
"Last Sync": "最近同步",
|
||||
"Search Filter": "Search Filter",
|
||||
"Search Filter - Tooltip": "Search Filter - Tooltip",
|
||||
"Server": "服务器",
|
||||
"Server host": "域名",
|
||||
"Server host - Tooltip": "LDAP服务器地址",
|
||||
@ -331,6 +350,15 @@
|
||||
"sign up now": "立即注册",
|
||||
"username, Email or phone": "用户名、Email或手机号"
|
||||
},
|
||||
"message": {
|
||||
"Author": "Author",
|
||||
"Chat": "Chat",
|
||||
"Chat - Tooltip": "Chat - Tooltip",
|
||||
"Edit Message": "Edit Message",
|
||||
"New Message": "New Message",
|
||||
"Text": "Text",
|
||||
"Text - Tooltip": "Text - Tooltip"
|
||||
},
|
||||
"model": {
|
||||
"Edit Model": "编辑模型",
|
||||
"Model text": "模型文本",
|
||||
|
@ -45,8 +45,8 @@ class LdapTable extends React.Component {
|
||||
serverName: "Example LDAP Server",
|
||||
host: "example.com",
|
||||
port: 389,
|
||||
admin: "cn=admin,dc=example,dc=com",
|
||||
passwd: "123",
|
||||
username: "cn=admin,dc=example,dc=com",
|
||||
password: "123",
|
||||
baseDn: "ou=People,dc=example,dc=com",
|
||||
autosync: 0,
|
||||
lastSync: "",
|
||||
|
Loading…
x
Reference in New Issue
Block a user