|
@@ -1,10 +1,13 @@
|
|
|
package ldap
|
|
|
|
|
|
import (
|
|
|
+ "errors"
|
|
|
+ "fmt"
|
|
|
+ "github.com/astaxie/beego/logs"
|
|
|
"github.com/astaxie/beego/orm"
|
|
|
+ "github.com/go-ldap/ldap/v3"
|
|
|
"nginx-ui/server/config"
|
|
|
"nginx-ui/server/models"
|
|
|
- "time"
|
|
|
)
|
|
|
|
|
|
type UserService struct {
|
|
@@ -12,7 +15,6 @@ type UserService struct {
|
|
|
|
|
|
// Add Update 保存或者修改
|
|
|
func (c *UserService) Add(body *models.LdapUser) (*models.LdapUser, error) {
|
|
|
-
|
|
|
server := models.LdapServer{
|
|
|
Key: body.ServerKey,
|
|
|
}
|
|
@@ -22,8 +24,7 @@ func (c *UserService) Add(body *models.LdapUser) (*models.LdapUser, error) {
|
|
|
return nil, err
|
|
|
}
|
|
|
body.Uid = server.Uid
|
|
|
-
|
|
|
- _, err = o.Insert(body)
|
|
|
+ _, err = o.InsertOrUpdate(body)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
@@ -36,7 +37,17 @@ func (c *UserService) Add(body *models.LdapUser) (*models.LdapUser, error) {
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
- body.LastSyncDate = time.Now()
|
|
|
+ if body.Password != config.ReplacePassword {
|
|
|
+ err := client.ModifyPasswordByAdmin(body.DN, body.Password)
|
|
|
+ if err != nil {
|
|
|
+ return nil, errors.New("新增成功,但密码修改失败!")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ entry, err := client.SearchByAccount(body.Account)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ modifyLDAPUser(body, entry)
|
|
|
_, _ = o.Update(body)
|
|
|
return body, nil
|
|
|
}
|
|
@@ -53,3 +64,195 @@ func (c *UserService) GetDetail(id int) (*models.LdapUser, error) {
|
|
|
user.Password = config.ReplacePassword
|
|
|
return &user, nil
|
|
|
}
|
|
|
+
|
|
|
+func (c *UserService) Search(server *models.LdapServer, filter string) ([]*models.LdapUser, []*models.LdapOrganize, error) {
|
|
|
+
|
|
|
+ client, err := GetActiveClient(server)
|
|
|
+ if err != nil {
|
|
|
+ return nil, nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ entries, err := client.Search(filter)
|
|
|
+ if err != nil {
|
|
|
+ return nil, nil, err
|
|
|
+ }
|
|
|
+ var users []*models.LdapUser
|
|
|
+ var organizeList []*models.LdapOrganize
|
|
|
+ for _, entry := range entries {
|
|
|
+ var isOrganize = false
|
|
|
+ objectClass := entry.GetAttributeValues("objectClass")
|
|
|
+ for _, oc := range objectClass {
|
|
|
+ if oc == server.OrganizeClass || oc == "organization" {
|
|
|
+ isOrganize = true
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if isOrganize {
|
|
|
+ organize := models.LdapOrganize{
|
|
|
+ Name: entry.GetAttributeValue("ou"),
|
|
|
+ DN: entry.DN,
|
|
|
+ ServerKey: server.Key,
|
|
|
+ ObjectClass: entry.GetAttributeValue("objectClass"),
|
|
|
+ }
|
|
|
+ organizeList = append(organizeList, &organize)
|
|
|
+ } else {
|
|
|
+ user := createUser(entry)
|
|
|
+ user.ServerKey = server.Key
|
|
|
+ users = append(users, &user)
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ return users, organizeList, nil
|
|
|
+}
|
|
|
+
|
|
|
+// SyncUser SyncUsers 同步用户信息
|
|
|
+// post /ldap/user/sync
|
|
|
+func (c *UserService) SyncUser(server *models.LdapServer, current *models.LdapUser) error {
|
|
|
+ o := orm.NewOrm()
|
|
|
+ if server == nil {
|
|
|
+ server := &models.LdapServer{Key: current.ServerKey}
|
|
|
+ err := o.Read(server, "Key")
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ filter := fmt.Sprintf("(&(objectClass=*)(uid=%s))", current.Account)
|
|
|
+
|
|
|
+ users, _, err := c.Search(server, filter)
|
|
|
+ if len(users) != 1 {
|
|
|
+ return errors.New("账号不存在或者账号重复!")
|
|
|
+ }
|
|
|
+ user := users[0]
|
|
|
+ user.Id = current.Id
|
|
|
+ user.ServerKey = current.ServerKey
|
|
|
+ user.Uid = current.Uid
|
|
|
+ user.Remark = current.Remark
|
|
|
+
|
|
|
+ _, err = o.Update(user)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+// SyncUsers 同步用户信息
|
|
|
+// post /ldap/user/sync
|
|
|
+func (c *UserService) SyncUsers(current *models.User, req *LDAPUserSyncReq) (int, error) {
|
|
|
+ server := &models.LdapServer{Key: req.ServerKey}
|
|
|
+ o := orm.NewOrm()
|
|
|
+ err := o.Read(server, "Key")
|
|
|
+ if err != nil {
|
|
|
+ return 0, err
|
|
|
+ }
|
|
|
+ users, organizeList, err := c.Search(server, req.Filter)
|
|
|
+ if err != nil {
|
|
|
+ return 0, err
|
|
|
+ }
|
|
|
+ for _, user := range users {
|
|
|
+ user.Uid = string(rune(current.Id))
|
|
|
+ _, err := o.InsertOrUpdate(user, "DN")
|
|
|
+ if err != nil {
|
|
|
+ logs.Error("save user fail: %v", err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for _, organize := range organizeList {
|
|
|
+ _, err = o.InsertOrUpdate(organize, "DN")
|
|
|
+ if err != nil {
|
|
|
+ logs.Error("save organize fail: %v", err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return len(users), nil
|
|
|
+}
|
|
|
+
|
|
|
+func (c *UserService) Authentication(server *models.LdapServer, account string, password string) (*models.User, error) {
|
|
|
+ o := orm.NewOrm()
|
|
|
+ ldapUser := &models.LdapUser{
|
|
|
+ Account: account,
|
|
|
+ }
|
|
|
+ err := o.Read(ldapUser, "Account")
|
|
|
+ if err != nil && !errors.Is(err, orm.ErrNoRows) {
|
|
|
+ return nil, err
|
|
|
+ } else if err != nil {
|
|
|
+ // The username and password we want to check
|
|
|
+ filter := fmt.Sprintf("(&(objectClass=*)(uid=%s))", ldap.EscapeFilter(account))
|
|
|
+ users, _, err := c.Search(server, filter)
|
|
|
+ if err != nil || len(users) != 1 {
|
|
|
+ logs.Error("search fail: %v", err)
|
|
|
+ return nil, errors.New("您输入的账号或者密码错误!")
|
|
|
+ }
|
|
|
+ ldapUser = users[0]
|
|
|
+ _, err = o.InsertOrUpdate(ldapUser, "DN")
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ }
|
|
|
+ userDN := ldapUser.DN
|
|
|
+ client, err := GetActiveClient(server)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ err = client.Authentication(userDN, password)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ user := &models.User{
|
|
|
+ Account: account,
|
|
|
+ }
|
|
|
+ err = o.Read(user, "Account")
|
|
|
+ if err != nil && !errors.Is(err, orm.ErrNoRows) {
|
|
|
+ return nil, err
|
|
|
+ } else if err != nil {
|
|
|
+ createLocalUser(user, ldapUser)
|
|
|
+ _, err = o.Insert(user)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ } else if user.Source == "LDAP" {
|
|
|
+ user.Nickname = ldapUser.UserName
|
|
|
+ _, _ = o.Update(user, "Nickname")
|
|
|
+ }
|
|
|
+ return user, nil
|
|
|
+}
|
|
|
+
|
|
|
+// UpdateUserPassword 更新用户密码
|
|
|
+// post /ldap/user/modifyPassword
|
|
|
+func (c *UserService) UpdateUserPassword(req *UpdatePasswordReq, byAdmin bool) error {
|
|
|
+ o := orm.NewOrm()
|
|
|
+ user := models.LdapUser{
|
|
|
+ Account: req.Account,
|
|
|
+ }
|
|
|
+ err := o.Read(&user, "Account")
|
|
|
+ if err != nil {
|
|
|
+ if errors.Is(err, orm.ErrNoRows) {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ logs.Error("read user fail: %v", err)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ server := models.LdapServer{
|
|
|
+ Key: user.ServerKey,
|
|
|
+ }
|
|
|
+ err = o.Read(&server, "Key")
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ client, err := GetActiveClient(&server)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ if byAdmin {
|
|
|
+ err = client.ModifyPasswordByAdmin(user.DN, req.Password)
|
|
|
+ } else {
|
|
|
+ err = client.ModifyPassword(user.DN, req.OldPassword, req.Password)
|
|
|
+ }
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ err = c.SyncUser(&server, &user)
|
|
|
+ if err != nil {
|
|
|
+ return errors.New("密码更新成功,但更新用户信息失败:" + err.Error())
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|