mirror of
https://github.com/casdoor/casdoor.git
synced 2025-09-06 18:10:29 +08:00
feat: compatible different uid of LDAP server (#1860)
* feat: compatible different uid of LDAP server * Update organization.go --------- Co-authored-by: hsluoyz <hsluoyz@qq.com>
This commit is contained in:
@@ -126,7 +126,7 @@ func (c *ApiController) Signup() {
|
|||||||
username = id
|
username = id
|
||||||
}
|
}
|
||||||
|
|
||||||
initScore, err := getInitScore(organization)
|
initScore, err := organization.GetInitScore()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(fmt.Errorf(c.T("account:Get init score failed, error: %w"), err).Error())
|
c.ResponseError(fmt.Errorf(c.T("account:Get init score failed, error: %w"), err).Error())
|
||||||
return
|
return
|
||||||
|
@@ -454,7 +454,7 @@ func (c *ApiController) Login() {
|
|||||||
|
|
||||||
properties := map[string]string{}
|
properties := map[string]string{}
|
||||||
properties["no"] = strconv.Itoa(object.GetUserCount(application.Organization, "", "") + 2)
|
properties["no"] = strconv.Itoa(object.GetUserCount(application.Organization, "", "") + 2)
|
||||||
initScore, err := getInitScore(organization)
|
initScore, err := organization.GetInitScore()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(fmt.Errorf(c.T("account:Get init score failed, error: %w"), err).Error())
|
c.ResponseError(fmt.Errorf(c.T("account:Get init score failed, error: %w"), err).Error())
|
||||||
return
|
return
|
||||||
|
@@ -23,7 +23,8 @@ import (
|
|||||||
|
|
||||||
type LdapResp struct {
|
type LdapResp struct {
|
||||||
// Groups []LdapRespGroup `json:"groups"`
|
// Groups []LdapRespGroup `json:"groups"`
|
||||||
Users []object.LdapRespUser `json:"users"`
|
Users []object.LdapUser `json:"users"`
|
||||||
|
ExistUuids []string `json:"existUuids"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//type LdapRespGroup struct {
|
//type LdapRespGroup struct {
|
||||||
@@ -32,8 +33,8 @@ type LdapResp struct {
|
|||||||
//}
|
//}
|
||||||
|
|
||||||
type LdapSyncResp struct {
|
type LdapSyncResp struct {
|
||||||
Exist []object.LdapRespUser `json:"exist"`
|
Exist []object.LdapUser `json:"exist"`
|
||||||
Failed []object.LdapRespUser `json:"failed"`
|
Failed []object.LdapUser `json:"failed"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLdapUsers
|
// GetLdapUsers
|
||||||
@@ -71,30 +72,17 @@ func (c *ApiController) GetLdapUsers() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var resp LdapResp
|
|
||||||
uuids := make([]string, len(users))
|
uuids := make([]string, len(users))
|
||||||
for _, user := range users {
|
for i, user := range users {
|
||||||
resp.Users = append(resp.Users, object.LdapRespUser{
|
uuids[i] = user.GetLdapUuid()
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
existUuids := object.GetExistUuids(ldapServer.Owner, uuids)
|
existUuids := object.GetExistUuids(ldapServer.Owner, uuids)
|
||||||
|
|
||||||
c.ResponseOk(resp, existUuids)
|
resp := LdapResp{
|
||||||
|
Users: object.AutoAdjustLdapUser(users),
|
||||||
|
ExistUuids: existUuids,
|
||||||
|
}
|
||||||
|
c.ResponseOk(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLdaps
|
// GetLdaps
|
||||||
@@ -209,7 +197,7 @@ func (c *ApiController) DeleteLdap() {
|
|||||||
func (c *ApiController) SyncLdapUsers() {
|
func (c *ApiController) SyncLdapUsers() {
|
||||||
owner := c.Input().Get("owner")
|
owner := c.Input().Get("owner")
|
||||||
ldapId := c.Input().Get("ldapId")
|
ldapId := c.Input().Get("ldapId")
|
||||||
var users []object.LdapRespUser
|
var users []object.LdapUser
|
||||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &users)
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &users)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
|
@@ -16,7 +16,6 @@ package controllers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/conf"
|
"github.com/casdoor/casdoor/conf"
|
||||||
"github.com/casdoor/casdoor/i18n"
|
"github.com/casdoor/casdoor/i18n"
|
||||||
@@ -115,14 +114,6 @@ func (c *ApiController) RequireAdmin() (string, bool) {
|
|||||||
return user.Owner, true
|
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) {
|
func (c *ApiController) GetProviderFromContext(category string) (*object.Provider, *object.User, bool) {
|
||||||
providerName := c.Input().Get("provider")
|
providerName := c.Input().Get("provider")
|
||||||
if providerName != "" {
|
if providerName != "" {
|
||||||
|
@@ -88,7 +88,7 @@ func (l *LdapAutoSynchronizer) syncRoutine(ldap *Ldap, stopChan chan struct{}) {
|
|||||||
continue
|
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 {
|
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(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())
|
logs.Warning(err.Error())
|
||||||
|
@@ -19,7 +19,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/beego/beego"
|
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
goldap "github.com/go-ldap/ldap/v3"
|
goldap "github.com/go-ldap/ldap/v3"
|
||||||
"github.com/thanhpk/randstr"
|
"github.com/thanhpk/randstr"
|
||||||
@@ -35,35 +34,26 @@ type LdapConn struct {
|
|||||||
// Cn string
|
// Cn string
|
||||||
//}
|
//}
|
||||||
|
|
||||||
type ldapUser struct {
|
type LdapUser struct {
|
||||||
UidNumber string
|
UidNumber string `json:"uidNumber"`
|
||||||
Uid string
|
Uid string `json:"uid"`
|
||||||
Cn string
|
Cn string `json:"cn"`
|
||||||
GidNumber string
|
GidNumber string `json:"gidNumber"`
|
||||||
// Gcn string
|
// Gcn string
|
||||||
Uuid string
|
Uuid string `json:"uuid"`
|
||||||
DisplayName string
|
DisplayName string `json:"displayName"`
|
||||||
Mail string
|
Mail string
|
||||||
Email string
|
Email string `json:"email"`
|
||||||
EmailAddress string
|
EmailAddress string
|
||||||
TelephoneNumber string
|
TelephoneNumber string
|
||||||
Mobile string
|
Mobile string
|
||||||
MobileTelephoneNumber string
|
MobileTelephoneNumber string
|
||||||
RegisteredAddress string
|
RegisteredAddress string
|
||||||
PostalAddress string
|
PostalAddress string
|
||||||
}
|
|
||||||
|
|
||||||
type LdapRespUser struct {
|
GroupId string `json:"groupId"`
|
||||||
UidNumber string `json:"uidNumber"`
|
Phone string `json:"phone"`
|
||||||
Uid string `json:"uid"`
|
Address string `json:"address"`
|
||||||
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) {
|
func (ldap *Ldap) GetLdapConn() (c *LdapConn, err error) {
|
||||||
@@ -136,7 +126,7 @@ func isMicrosoftAD(Conn *goldap.Conn) (bool, error) {
|
|||||||
return isMicrosoft, err
|
return isMicrosoft, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LdapConn) GetLdapUsers(ldapServer *Ldap) ([]ldapUser, error) {
|
func (l *LdapConn) GetLdapUsers(ldapServer *Ldap) ([]LdapUser, error) {
|
||||||
SearchAttributes := []string{
|
SearchAttributes := []string{
|
||||||
"uidNumber", "cn", "sn", "gidNumber", "entryUUID", "displayName", "mail", "email",
|
"uidNumber", "cn", "sn", "gidNumber", "entryUUID", "displayName", "mail", "email",
|
||||||
"emailAddress", "telephoneNumber", "mobile", "mobileTelephoneNumber", "registeredAddress", "postalAddress",
|
"emailAddress", "telephoneNumber", "mobile", "mobileTelephoneNumber", "registeredAddress", "postalAddress",
|
||||||
@@ -159,9 +149,9 @@ func (l *LdapConn) GetLdapUsers(ldapServer *Ldap) ([]ldapUser, error) {
|
|||||||
return nil, errors.New("no result")
|
return nil, errors.New("no result")
|
||||||
}
|
}
|
||||||
|
|
||||||
var ldapUsers []ldapUser
|
var ldapUsers []LdapUser
|
||||||
for _, entry := range searchResult.Entries {
|
for _, entry := range searchResult.Entries {
|
||||||
var user ldapUser
|
var user LdapUser
|
||||||
for _, attribute := range entry.Attributes {
|
for _, attribute := range entry.Attributes {
|
||||||
switch attribute.Name {
|
switch attribute.Name {
|
||||||
case "uidNumber":
|
case "uidNumber":
|
||||||
@@ -241,27 +231,26 @@ func (l *LdapConn) GetLdapUsers(ldapServer *Ldap) ([]ldapUser, error) {
|
|||||||
// return groupMap, nil
|
// return groupMap, nil
|
||||||
// }
|
// }
|
||||||
|
|
||||||
func LdapUsersToLdapRespUsers(users []ldapUser) []LdapRespUser {
|
func AutoAdjustLdapUser(users []LdapUser) []LdapUser {
|
||||||
res := make([]LdapRespUser, 0)
|
res := make([]LdapUser, len(users))
|
||||||
for _, user := range users {
|
for i, user := range users {
|
||||||
res = append(res, LdapRespUser{
|
res[i] = LdapUser{
|
||||||
UidNumber: user.UidNumber,
|
UidNumber: user.UidNumber,
|
||||||
Uid: user.Uid,
|
Uid: user.Uid,
|
||||||
Cn: user.Cn,
|
Cn: user.Cn,
|
||||||
GroupId: user.GidNumber,
|
GroupId: user.GidNumber,
|
||||||
Uuid: user.Uuid,
|
Uuid: user.GetLdapUuid(),
|
||||||
DisplayName: user.DisplayName,
|
DisplayName: user.DisplayName,
|
||||||
Email: util.ReturnAnyNotEmpty(user.Email, user.EmailAddress, user.Mail),
|
Email: util.ReturnAnyNotEmpty(user.Email, user.EmailAddress, user.Mail),
|
||||||
Phone: util.ReturnAnyNotEmpty(user.Mobile, user.MobileTelephoneNumber, user.TelephoneNumber),
|
Mobile: util.ReturnAnyNotEmpty(user.Mobile, user.MobileTelephoneNumber, user.TelephoneNumber),
|
||||||
Address: util.ReturnAnyNotEmpty(user.PostalAddress, user.RegisteredAddress),
|
RegisteredAddress: util.ReturnAnyNotEmpty(user.PostalAddress, user.RegisteredAddress),
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
return res
|
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
|
var uuids []string
|
||||||
|
|
||||||
for _, user := range syncUsers {
|
for _, user := range syncUsers {
|
||||||
uuids = append(uuids, user.Uuid)
|
uuids = append(uuids, user.Uuid)
|
||||||
}
|
}
|
||||||
@@ -286,12 +275,6 @@ func SyncLdapUsers(owner string, syncUsers []LdapRespUser, ldapId string) (exist
|
|||||||
tag := strings.Join(ou, ".")
|
tag := strings.Join(ou, ".")
|
||||||
|
|
||||||
for _, syncUser := range syncUsers {
|
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)
|
existUuids := GetExistUuids(owner, uuids)
|
||||||
found := false
|
found := false
|
||||||
if len(existUuids) > 0 {
|
if len(existUuids) > 0 {
|
||||||
@@ -304,6 +287,7 @@ func SyncLdapUsers(owner string, syncUsers []LdapRespUser, ldapId string) (exist
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
|
score, _ := organization.GetInitScore()
|
||||||
newUser := &User{
|
newUser := &User{
|
||||||
Owner: owner,
|
Owner: owner,
|
||||||
Name: syncUser.buildLdapUserName(),
|
Name: syncUser.buildLdapUserName(),
|
||||||
@@ -315,7 +299,7 @@ func SyncLdapUsers(owner string, syncUsers []LdapRespUser, ldapId string) (exist
|
|||||||
Address: []string{syncUser.Address},
|
Address: []string{syncUser.Address},
|
||||||
Affiliation: affiliation,
|
Affiliation: affiliation,
|
||||||
Tag: tag,
|
Tag: tag,
|
||||||
Score: beego.AppConfig.DefaultInt("initScore", 2000),
|
Score: score,
|
||||||
Ldap: syncUser.Uuid,
|
Ldap: syncUser.Uuid,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,7 +326,7 @@ func GetExistUuids(owner string, uuids []string) []string {
|
|||||||
return existUuids
|
return existUuids
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ldapUser *LdapRespUser) buildLdapUserName() string {
|
func (ldapUser *LdapUser) buildLdapUserName() string {
|
||||||
user := User{}
|
user := User{}
|
||||||
uidWithNumber := fmt.Sprintf("%s_%s", ldapUser.Uid, ldapUser.UidNumber)
|
uidWithNumber := fmt.Sprintf("%s_%s", ldapUser.Uid, ldapUser.UidNumber)
|
||||||
has, err := adapter.Engine.Where("name = ? or name = ?", ldapUser.Uid, uidWithNumber).Get(&user)
|
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 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 != "" {
|
if ldapUser.DisplayName != "" {
|
||||||
return ldapUser.DisplayName
|
return ldapUser.DisplayName
|
||||||
}
|
}
|
||||||
@@ -368,6 +356,17 @@ func (ldapUser *LdapRespUser) buildLdapDisplayName() string {
|
|||||||
return ldapUser.Cn
|
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 {
|
func (ldap *Ldap) buildFilterString(user *User) string {
|
||||||
if len(ldap.FilterFields) == 0 {
|
if len(ldap.FilterFields) == 0 {
|
||||||
return fmt.Sprintf("(&%s(uid=%s))", ldap.Filter, user.Name)
|
return fmt.Sprintf("(&%s(uid=%s))", ldap.Filter, user.Name)
|
||||||
|
@@ -16,7 +16,9 @@ package object
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/casdoor/casdoor/conf"
|
||||||
"github.com/casdoor/casdoor/cred"
|
"github.com/casdoor/casdoor/cred"
|
||||||
"github.com/casdoor/casdoor/i18n"
|
"github.com/casdoor/casdoor/i18n"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
@@ -423,3 +425,11 @@ func (org *Organization) HasRequiredMfa() bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (org *Organization) GetInitScore() (int, error) {
|
||||||
|
if org != nil {
|
||||||
|
return org.InitScore, nil
|
||||||
|
} else {
|
||||||
|
return strconv.Atoi(conf.GetConfigString("initScore"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -94,7 +94,7 @@ class LdapSyncPage extends React.Component {
|
|||||||
if (res.status === "ok") {
|
if (res.status === "ok") {
|
||||||
this.setState((prevState) => {
|
this.setState((prevState) => {
|
||||||
prevState.users = res.data.users;
|
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;
|
return prevState;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -210,7 +210,7 @@ class LdapSyncPage extends React.Component {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
getCheckboxProps: record => ({
|
getCheckboxProps: record => ({
|
||||||
disabled: this.state.existUuids.indexOf(record.uuid) !== -1 || record.uidNumber === "",
|
disabled: this.state.existUuids.indexOf(record.uuid) !== -1,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user