From 65dcbd2236e6063dc70b4f8d9915baa213602d03 Mon Sep 17 00:00:00 2001 From: Yaodong Yu <2814461814@qq.com> Date: Fri, 19 May 2023 02:34:25 +0800 Subject: [PATCH] feat: compatible different uid of LDAP server (#1860) * feat: compatible different uid of LDAP server * Update organization.go --------- Co-authored-by: hsluoyz --- controllers/account.go | 2 +- controllers/auth.go | 2 +- controllers/ldap.go | 36 +++++---------- controllers/util.go | 9 ---- object/ldap_autosync.go | 2 +- object/ldap_conn.go | 99 ++++++++++++++++++++--------------------- object/organization.go | 10 +++++ web/src/LdapSyncPage.js | 4 +- 8 files changed, 76 insertions(+), 88 deletions(-) diff --git a/controllers/account.go b/controllers/account.go index 4d66588b..03910431 100644 --- a/controllers/account.go +++ b/controllers/account.go @@ -126,7 +126,7 @@ func (c *ApiController) Signup() { username = id } - initScore, err := getInitScore(organization) + initScore, err := organization.GetInitScore() if err != nil { c.ResponseError(fmt.Errorf(c.T("account:Get init score failed, error: %w"), err).Error()) return diff --git a/controllers/auth.go b/controllers/auth.go index 5784c0d9..29de5ad2 100644 --- a/controllers/auth.go +++ b/controllers/auth.go @@ -454,7 +454,7 @@ func (c *ApiController) Login() { properties := map[string]string{} properties["no"] = strconv.Itoa(object.GetUserCount(application.Organization, "", "") + 2) - initScore, err := getInitScore(organization) + initScore, err := organization.GetInitScore() if err != nil { c.ResponseError(fmt.Errorf(c.T("account:Get init score failed, error: %w"), err).Error()) return diff --git a/controllers/ldap.go b/controllers/ldap.go index 52dc242e..6a45f96e 100644 --- a/controllers/ldap.go +++ b/controllers/ldap.go @@ -23,7 +23,8 @@ import ( type LdapResp struct { // Groups []LdapRespGroup `json:"groups"` - Users []object.LdapRespUser `json:"users"` + Users []object.LdapUser `json:"users"` + ExistUuids []string `json:"existUuids"` } //type LdapRespGroup struct { @@ -32,8 +33,8 @@ type LdapResp struct { //} type LdapSyncResp struct { - Exist []object.LdapRespUser `json:"exist"` - Failed []object.LdapRespUser `json:"failed"` + Exist []object.LdapUser `json:"exist"` + Failed []object.LdapUser `json:"failed"` } // GetLdapUsers @@ -71,30 +72,17 @@ func (c *ApiController) GetLdapUsers() { return } - var resp LdapResp uuids := make([]string, len(users)) - for _, user := range users { - resp.Users = append(resp.Users, object.LdapRespUser{ - UidNumber: user.UidNumber, - Uid: user.Uid, - Cn: user.Cn, - GroupId: user.GidNumber, - // GroupName: groupsMap[user.GidNumber].Cn, - 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), - }) - - if user.Uuid != "" { - uuids = append(uuids, user.Uuid) - } + for i, user := range users { + uuids[i] = user.GetLdapUuid() } - existUuids := object.GetExistUuids(ldapServer.Owner, uuids) - c.ResponseOk(resp, existUuids) + resp := LdapResp{ + Users: object.AutoAdjustLdapUser(users), + ExistUuids: existUuids, + } + c.ResponseOk(resp) } // GetLdaps @@ -209,7 +197,7 @@ func (c *ApiController) DeleteLdap() { func (c *ApiController) SyncLdapUsers() { owner := c.Input().Get("owner") ldapId := c.Input().Get("ldapId") - var users []object.LdapRespUser + var users []object.LdapUser err := json.Unmarshal(c.Ctx.Input.RequestBody, &users) if err != nil { c.ResponseError(err.Error()) diff --git a/controllers/util.go b/controllers/util.go index 498b6b92..2c41a960 100644 --- a/controllers/util.go +++ b/controllers/util.go @@ -16,7 +16,6 @@ package controllers import ( "fmt" - "strconv" "github.com/casdoor/casdoor/conf" "github.com/casdoor/casdoor/i18n" @@ -115,14 +114,6 @@ func (c *ApiController) RequireAdmin() (string, bool) { return user.Owner, true } -func getInitScore(organization *object.Organization) (int, error) { - if organization != nil { - return organization.InitScore, nil - } else { - return strconv.Atoi(conf.GetConfigString("initScore")) - } -} - func (c *ApiController) GetProviderFromContext(category string) (*object.Provider, *object.User, bool) { providerName := c.Input().Get("provider") if providerName != "" { diff --git a/object/ldap_autosync.go b/object/ldap_autosync.go index 04cc19f2..8eb22a8b 100644 --- a/object/ldap_autosync.go +++ b/object/ldap_autosync.go @@ -88,7 +88,7 @@ func (l *LdapAutoSynchronizer) syncRoutine(ldap *Ldap, stopChan chan struct{}) { continue } - existed, failed, err := SyncLdapUsers(ldap.Owner, LdapUsersToLdapRespUsers(users), ldap.Id) + existed, failed, err := SyncLdapUsers(ldap.Owner, AutoAdjustLdapUser(users), ldap.Id) if len(failed) != 0 { logs.Warning(fmt.Sprintf("ldap autosync,%d new users,but %d user failed during :", len(users)-len(existed)-len(failed), len(failed)), failed) logs.Warning(err.Error()) diff --git a/object/ldap_conn.go b/object/ldap_conn.go index 515860c2..fce352aa 100644 --- a/object/ldap_conn.go +++ b/object/ldap_conn.go @@ -19,7 +19,6 @@ import ( "fmt" "strings" - "github.com/beego/beego" "github.com/casdoor/casdoor/util" goldap "github.com/go-ldap/ldap/v3" "github.com/thanhpk/randstr" @@ -35,35 +34,26 @@ type LdapConn struct { // Cn string //} -type ldapUser struct { - UidNumber string - Uid string - Cn string - GidNumber string +type LdapUser struct { + UidNumber string `json:"uidNumber"` + Uid string `json:"uid"` + Cn string `json:"cn"` + GidNumber string `json:"gidNumber"` // Gcn string - Uuid string - DisplayName string + Uuid string `json:"uuid"` + DisplayName string `json:"displayName"` Mail string - Email string + Email string `json:"email"` 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"` + GroupId string `json:"groupId"` + Phone string `json:"phone"` + Address string `json:"address"` } func (ldap *Ldap) GetLdapConn() (c *LdapConn, err error) { @@ -136,7 +126,7 @@ func isMicrosoftAD(Conn *goldap.Conn) (bool, error) { return isMicrosoft, err } -func (l *LdapConn) GetLdapUsers(ldapServer *Ldap) ([]ldapUser, error) { +func (l *LdapConn) GetLdapUsers(ldapServer *Ldap) ([]LdapUser, error) { SearchAttributes := []string{ "uidNumber", "cn", "sn", "gidNumber", "entryUUID", "displayName", "mail", "email", "emailAddress", "telephoneNumber", "mobile", "mobileTelephoneNumber", "registeredAddress", "postalAddress", @@ -159,9 +149,9 @@ func (l *LdapConn) GetLdapUsers(ldapServer *Ldap) ([]ldapUser, error) { return nil, errors.New("no result") } - var ldapUsers []ldapUser + var ldapUsers []LdapUser for _, entry := range searchResult.Entries { - var user ldapUser + var user LdapUser for _, attribute := range entry.Attributes { switch attribute.Name { case "uidNumber": @@ -241,27 +231,26 @@ func (l *LdapConn) GetLdapUsers(ldapServer *Ldap) ([]ldapUser, error) { // 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), - }) +func AutoAdjustLdapUser(users []LdapUser) []LdapUser { + res := make([]LdapUser, len(users)) + for i, user := range users { + res[i] = LdapUser{ + UidNumber: user.UidNumber, + Uid: user.Uid, + Cn: user.Cn, + GroupId: user.GidNumber, + Uuid: user.GetLdapUuid(), + DisplayName: user.DisplayName, + Email: util.ReturnAnyNotEmpty(user.Email, user.EmailAddress, user.Mail), + Mobile: util.ReturnAnyNotEmpty(user.Mobile, user.MobileTelephoneNumber, user.TelephoneNumber), + RegisteredAddress: util.ReturnAnyNotEmpty(user.PostalAddress, user.RegisteredAddress), + } } return res } -func SyncLdapUsers(owner string, syncUsers []LdapRespUser, ldapId string) (existUsers []LdapRespUser, failedUsers []LdapRespUser, err error) { +func SyncLdapUsers(owner string, syncUsers []LdapUser, ldapId string) (existUsers []LdapUser, failedUsers []LdapUser, err error) { var uuids []string - for _, user := range syncUsers { uuids = append(uuids, user.Uuid) } @@ -286,12 +275,6 @@ func SyncLdapUsers(owner string, syncUsers []LdapRespUser, ldapId string) (exist tag := strings.Join(ou, ".") for _, syncUser := range syncUsers { - if syncUser.Uuid == "" { - failedUsers = append(failedUsers, syncUser) - err = errors.New("uuid of user being synced is empty") - continue - } - existUuids := GetExistUuids(owner, uuids) found := false if len(existUuids) > 0 { @@ -304,6 +287,7 @@ func SyncLdapUsers(owner string, syncUsers []LdapRespUser, ldapId string) (exist } if !found { + score, _ := organization.GetInitScore() newUser := &User{ Owner: owner, Name: syncUser.buildLdapUserName(), @@ -315,7 +299,7 @@ func SyncLdapUsers(owner string, syncUsers []LdapRespUser, ldapId string) (exist Address: []string{syncUser.Address}, Affiliation: affiliation, Tag: tag, - Score: beego.AppConfig.DefaultInt("initScore", 2000), + Score: score, Ldap: syncUser.Uuid, } @@ -342,7 +326,7 @@ func GetExistUuids(owner string, uuids []string) []string { return existUuids } -func (ldapUser *LdapRespUser) buildLdapUserName() string { +func (ldapUser *LdapUser) 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) @@ -357,10 +341,14 @@ func (ldapUser *LdapRespUser) buildLdapUserName() string { return fmt.Sprintf("%s_%s", uidWithNumber, randstr.Hex(6)) } - return ldapUser.Uid + if ldapUser.Uid != "" { + return ldapUser.Uid + } + + return ldapUser.Cn } -func (ldapUser *LdapRespUser) buildLdapDisplayName() string { +func (ldapUser *LdapUser) buildLdapDisplayName() string { if ldapUser.DisplayName != "" { return ldapUser.DisplayName } @@ -368,6 +356,17 @@ func (ldapUser *LdapRespUser) buildLdapDisplayName() string { return ldapUser.Cn } +func (ldapUser *LdapUser) GetLdapUuid() string { + if ldapUser.Uuid != "" { + return ldapUser.Uuid + } + if ldapUser.Uid != "" { + return ldapUser.Uid + } + + 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) diff --git a/object/organization.go b/object/organization.go index 12224e04..14561166 100644 --- a/object/organization.go +++ b/object/organization.go @@ -16,7 +16,9 @@ package object import ( "fmt" + "strconv" + "github.com/casdoor/casdoor/conf" "github.com/casdoor/casdoor/cred" "github.com/casdoor/casdoor/i18n" "github.com/casdoor/casdoor/util" @@ -423,3 +425,11 @@ func (org *Organization) HasRequiredMfa() bool { } return false } + +func (org *Organization) GetInitScore() (int, error) { + if org != nil { + return org.InitScore, nil + } else { + return strconv.Atoi(conf.GetConfigString("initScore")) + } +} diff --git a/web/src/LdapSyncPage.js b/web/src/LdapSyncPage.js index f2582a5d..8367ea04 100644 --- a/web/src/LdapSyncPage.js +++ b/web/src/LdapSyncPage.js @@ -94,7 +94,7 @@ class LdapSyncPage extends React.Component { if (res.status === "ok") { this.setState((prevState) => { prevState.users = res.data.users; - prevState.existUuids = res.data2?.length > 0 ? res.data2.filter(uuid => uuid !== "") : []; + prevState.existUuids = res.data.existUuids?.length > 0 ? res.data.existUuids.filter(uuid => uuid !== "") : []; return prevState; }); } else { @@ -210,7 +210,7 @@ class LdapSyncPage extends React.Component { }); }, getCheckboxProps: record => ({ - disabled: this.state.existUuids.indexOf(record.uuid) !== -1 || record.uidNumber === "", + disabled: this.state.existUuids.indexOf(record.uuid) !== -1, }), };