package logic import ( "context" "fusenapi/utils/auth" "fusenapi/utils/basic" "github.com/go-ldap/ldap/v3" "log" "sort" "strings" "fusenapi/server/ldap-admin/internal/svc" "fusenapi/server/ldap-admin/internal/types" "github.com/zeromicro/go-zero/core/logx" ) type GetDepartmentsLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext } func NewGetDepartmentsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetDepartmentsLogic { return &GetDepartmentsLogic{ Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx, } } // 处理进入前逻辑w,r // func (l *GetDepartmentsLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) { // } type mapDnItem struct { Attribute map[string]interface{} `json:"attribute"` DN string `json:"dn"` Sort int `json:"sort"` Child []*mapDnItem `json:"child"` } func (l *GetDepartmentsLogic) GetDepartments(req *types.Request, userinfo *auth.UserInfo) (resp *basic.Response) { // todo 从ldap获取组织架构数据 searchBase := "dc=fusen,dc=com" // 创建搜索请求 searchRequest := ldap.NewSearchRequest( searchBase, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, "(objectClass=*)", []string{ /*"cn", "sn", "givenName", "mail", "telephoneNumber", "department", "title"*/ }, nil, ) // 执行搜索请求 searchResult, err := l.svcCtx.Ldap.Search(searchRequest) if err != nil { log.Fatal(err) } mapDN := make(map[string]*mapDnItem) sortNum := 0 for _, v := range searchResult.Entries { sortNum++ attribute := make(map[string]interface{}) for _, attr := range v.Attributes { if attr.Name == "objectClass" { mapObjectClass := make(map[string]struct{}) for _, objectClassItem := range attr.Values { mapObjectClass[objectClassItem] = struct{}{} } attribute[attr.Name] = mapObjectClass } else { attribute[attr.Name] = strings.Join(attr.Values, ",") } } mapDN[v.DN] = &mapDnItem{ DN: v.DN, Attribute: attribute, Sort: sortNum, Child: make([]*mapDnItem, 0, 100), } } //组织层级关系 minLevel := 0 for dn, v := range mapDN { sl := strings.Split(dn, ",") lensl := len(sl) if lensl < minLevel || minLevel == 0 { minLevel = lensl } //没有父级 if lensl <= 1 { continue } //有父级 parentKey := strings.Join(sl[1:], ",") if parent, ok := mapDN[parentKey]; ok { parent.Child = append(parent.Child, v) //排序 sort.Slice(parent.Child, func(i, j int) bool { return parent.Child[i].Sort < parent.Child[j].Sort }) } } //只获取最顶层 list := make([]interface{}, 0, len(mapDN)) for dn, v := range mapDN { sl := strings.Split(dn, ",") if len(sl) == minLevel { list = append(list, v) } } return resp.SetStatusWithMessage(basic.CodeOK, "", list) } /* dn: dc=fusen,dc=com o : [fusen com] dc : [fusen] objectClass : [top dcObject organization] dn: cn=root,dc=fusen,dc=com cn : [root] objectClass : [organizationalRole] description : [Directory Manager] dn: ou=People,dc=fusen,dc=com ou : [People] objectClass : [top organizationalUnit] telephoneNumber : [aabb] dn: ou=Group,dc=fusen,dc=com ou : [Group] objectClass : [top organizationalUnit] dn: uid=fsuser,ou=People,dc=fusen,dc=com uid : [fsuser] cn : [fsuser] sn : [fsuser] mail : [fsuser@fusen.com] objectClass : [person organizationalPerson inetOrgPerson posixAccount top shadowAccount] userPassword : [{crypt}$6$fpyhuX7q$XBAA2URfWZCYZRLQpzzqucuFymrYvJL/NXztQ6/ug89GHvfN.OCUOGOZzyoKZwgF/LXToY5Wmqf9Yb0JoQbkL1] shadowLastChange : [19674] shadowMin : [0] shadowMax : [99999] shadowWarning : [7] loginShell : [/bin/bash] uidNumber : [1000] gidNumber : [1000] homeDirectory : [/home/fsuser] dn: uid=fstest,ou=People,dc=fusen,dc=com uid : [fstest] cn : [fstest] sn : [fstest] mail : [fstest@fusen.com] objectClass : [person organizationalPerson inetOrgPerson posixAccount top shadowAccount] userPassword : [{crypt}$6$SYX2T3.y$OvYYU08PG8g.4SvI3A4MHSzfK5qSZeqB/2StqXxtd0E/RAENXFXBQH4bvkjLsbcDQMMobkzoyRyVJZv5xcK3r0] shadowLastChange : [19674] shadowMin : [0] shadowMax : [99999] shadowWarning : [7] loginShell : [/bin/bash] uidNumber : [1001] gidNumber : [1001] homeDirectory : [/home/fstest] mobile : [17557283677] dn: cn=fusen,ou=Group,dc=fusen,dc=com objectClass : [posixGroup top] cn : [fusen] userPassword : [{crypt}x] gidNumber : [1000] dn: cn=fusen2,ou=Group,dc=fusen,dc=com objectClass : [posixGroup top] cn : [fusen2] userPassword : [{crypt}x] gidNumber : [1001] dn: cn=gitlab,ou=Group,dc=fusen,dc=com objectClass : [top groupOfNames] cn : [gitlab] member : [uid=testuser,ou=People,dc=funsen,dc=com] */