package ldap_lib import ( "errors" "fmt" "strings" "github.com/go-ldap/ldap/v3" "gorm.io/gorm" ) type Ldap struct { baseDN string rootDN string conn *ldap.Conn peopleGroupDN string jwtSecret string MysqlConn *gorm.DB } func NewLdap(conn *ldap.Conn, baseDN, rootDN, peopleGroupDN, jwtSecret string, mysqlConn *gorm.DB) *Ldap { return &Ldap{ baseDN: baseDN, rootDN: rootDN, conn: conn, peopleGroupDN: peopleGroupDN, jwtSecret: jwtSecret, MysqlConn: mysqlConn, } } // 更新资源(分组/用户) func (l *Ldap) Update(DN string, attr map[string][]string) error { if DN == l.rootDN { return errors.New("根用户不能更新") } modify := ldap.NewModifyRequest(DN, nil) for key, v := range attr { modify.Replace(key, v) } return l.conn.Modify(modify) } // 创建资源(分组/用户) func (l *Ldap) Create(DN string, attr map[string][]string) error { add := ldap.NewAddRequest(DN, nil) for key, v := range attr { add.Attribute(key, v) } return l.conn.Add(add) } // 删除资源(分组/用户) func (l *Ldap) Delete(DN string) error { if DN == l.rootDN { return errors.New("根用户不能删除") } del := ldap.NewDelRequest(DN, nil) return l.conn.Del(del) } // 查询资源(分组/用户) func (l *Ldap) Search(DN string, scope int, filter string, attr []string, controls []ldap.Control) (resp *ldap.SearchResult, err error) { if DN == l.rootDN { return nil, errors.New("没有权限查询根用户") } if filter == "" { rootCn := strings.Split(l.rootDN, ",") if len(rootCn) == 0 { return nil, errors.New("root用户DN未设置") } filter = "(&(objectClass=*)(!(" + rootCn[0] + ")))" } searchRequest := ldap.NewSearchRequest( DN, scope, ldap.NeverDerefAliases, 0, 0, false, filter, attr, controls, ) // 执行搜索请求 return l.conn.Search(searchRequest) } // 分页查询资源(分组/用户) func (l *Ldap) SearchWithPaging(DN string, scope int, filter string, attr []string, pageSize uint32, pagingCookie string) (resp *ldap.SearchResult, err error) { if DN == l.rootDN { return nil, errors.New("没有权限查询根用户") } if filter == "" { rootCn := strings.Split(l.rootDN, ",") if len(rootCn) == 0 { return nil, errors.New("root用户DN未设置") } filter = "(&(objectClass=*)(!(" + rootCn[0] + ")))" } searchRequest := ldap.NewSearchRequest( DN, scope, ldap.NeverDerefAliases, 0, 0, false, filter, attr, nil, ) pagingCtl := ldap.NewControlPaging(pageSize) pagingCtl.SetCookie([]byte(pagingCookie)) searchRequest.Controls = []ldap.Control{ pagingCtl, } // 执行搜索请求 return l.conn.Search(searchRequest) } // ********************************************************************************************* // 查询组织列表 type OrganizationInfo struct { Name string `json:"name"` DN string `json:"dn"` Owner string `json:"owner"` Members []string `json:"members"` } func (l *Ldap) GetOrganizationList(scope int, organizationDNs []string, fields []string, control []ldap.Control) ([]OrganizationInfo, error) { filterBuilder := strings.Builder{} for _, dn := range organizationDNs { //提取 ou filterBuilder.WriteString(fmt.Sprintf("(%s)", strings.Split(dn, ",")[0])) } filter := "(&(objectClass=groupOfUniqueNames)(objectClass=top))" if filterBuilder.Len() > 0 { filter = "(&(objectClass=groupOfUniqueNames)(objectClass=top)(|" + filterBuilder.String() + "))" } organizationsResult, err := l.Search(l.baseDN, scope, filter, fields, nil) if err != nil { return nil, err } list := make([]OrganizationInfo, 0, len(organizationsResult.Entries)) for _, entry := range organizationsResult.Entries { data := OrganizationInfo{ DN: entry.DN, } for _, attr := range entry.Attributes { switch attr.Name { case "businessCategory": //名称 data.Name = strings.Join(attr.Values, ",") case "owner": //负责人 data.Owner = strings.Join(attr.Values, ",") case "uniqueMember": //成员 data.Members = attr.Values } } list = append(list, data) } return list, nil } // AddUserToGroup 添加用户到组织 func (l *Ldap) AddUserToOrganization(organizationDN, userDN string) error { modify := ldap.NewModifyRequest(organizationDN, nil) modify.Add("uniqueMember", []string{userDN}) return l.conn.Modify(modify) } // DelUserFromGroup 将用户从分组删除 func (l *Ldap) RemoveUserFromOrganization(groupDN, userDN string) error { if userDN == l.rootDN { return errors.New("根用户不能从分组删除") } modify := ldap.NewModifyRequest(groupDN, nil) modify.Delete("uniqueMember", []string{userDN}) return l.conn.Modify(modify) }