123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- 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"
- )
- type UserService struct {
- }
- // Add Update 保存或者修改
- func (c *UserService) Add(body *models.LdapUser) (*models.LdapUser, error) {
- server := models.LdapServer{
- Key: body.ServerKey,
- }
- o := orm.NewOrm()
- err := o.Read(&server, "Key")
- if err != nil {
- return nil, err
- }
- body.Uid = server.Uid
- exist := models.LdapUser{
- Account: body.Account,
- }
- isNew := false
- err = o.Read(&exist, "Account")
- if err != nil && errors.Is(err, orm.ErrNoRows) {
- _, err = o.Insert(body)
- isNew = true
- } else if err != nil {
- return nil, err
- } else {
- body.Id = exist.Id
- _, err = o.Update(body)
- }
- if err != nil {
- return nil, err
- }
- client, err := GetActiveClient(&server)
- if err != nil {
- return nil, err
- }
- err = client.Add(body)
- if err != nil {
- return nil, err
- }
- if body.Password != config.ReplacePassword {
- err := client.ModifyPasswordByAdmin(body.DN, body.Password)
- if err != nil {
- return nil, errors.New("新增成功,但密码修改失败!")
- }
- if isNew {
- SendUserAddEmail(body, body.Password)
- }
- }
- entry, err := client.SearchByAccount(body.Account)
- if err != nil {
- return nil, err
- }
- modifyLDAPUser(body, entry)
- _, _ = o.Update(body)
- return body, nil
- }
- // get /ldap/users
- func (c *UserService) GetDetail(id int) (*models.LdapUser, error) {
- o := orm.NewOrm()
- user := models.LdapUser{Id: id}
- err := o.Read(&user, "Id")
- if err != nil {
- return nil, err
- }
- user.Password = config.ReplacePassword
- return &user, nil
- }
- func (c *UserService) GetByAccount(account string) (*models.LdapUser, error) {
- o := orm.NewOrm()
- user := models.LdapUser{Account: account}
- err := o.Read(&user, "Account")
- if err != nil {
- return nil, err
- }
- 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 := models.InsertOrUpdate[models.LdapUser](o, user, "DN")
- if err != nil {
- logs.Error("save user fail: %v", err)
- }
- }
- for _, organize := range organizeList {
- _, err = models.InsertOrUpdate[models.LdapOrganize](o, 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 = models.InsertOrUpdate[models.LdapUser](o, 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
- }
|