fusenapi/server/ldap-admin/internal/logic/getldaporganizationslogic.go
laodaming 8c45de4d25 fix
2023-11-24 11:45:56 +08:00

161 lines
4.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package logic
import (
"fmt"
"fusenapi/utils/basic"
"github.com/go-ldap/ldap/v3"
"net/http"
"sort"
"strings"
"context"
"fusenapi/server/ldap-admin/internal/svc"
"fusenapi/server/ldap-admin/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetLdapOrganizationsLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetLdapOrganizationsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetLdapOrganizationsLogic {
return &GetLdapOrganizationsLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
// 处理进入前逻辑w,r
// func (l *GetLdapOrganizationsLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
// }
type DNItem struct {
Attribute map[string]interface{} `json:"attribute"`
MemberCount int `json:"member_count"`
OwnerName string `json:"owner_name"`
OwnerDN string `json:"owner_dn"`
Level int `json:"level"`
DN string `json:"dn"`
ParentDN string `json:"parent_dn"`
Sort int `json:"sort"`
Child []*DNItem `json:"child"`
}
func (l *GetLdapOrganizationsLogic) GetLdapOrganizations(req *types.Request, r *http.Request) (resp *basic.Response) {
if !l.svcCtx.Ldap.VerifyAuthority(r) {
return resp.SetStatusWithMessage(basic.CodeUnAuth, "无权限,请联系管理员开通")
}
//从ldap获取组织架构数据
rootCn := strings.Split(l.svcCtx.Config.Ldap.RootDN, ",")
if len(rootCn) == 0 {
return resp.SetStatusWithMessage(basic.CodeServiceErr, "root用户DN未设置")
}
peopleDNSlice := strings.Split(l.svcCtx.Config.Ldap.PeopleGroupDN, ",")
if len(peopleDNSlice) <= 1 {
return resp.SetStatusWithMessage(basic.CodeServiceErr, "基础用户组的DN未配置")
}
filter := "(&(objectClass=groupOfUniqueNames)(objectClass=top))"
fields := []string{"businessCategory", "owner", "dn", "uniqueMember"}
searchResult, err := l.svcCtx.Ldap.Search(l.svcCtx.Config.Ldap.BaseDN, ldap.ScopeWholeSubtree, filter, fields, nil)
if err != nil {
return resp.SetStatusWithMessage(basic.CodeServiceErr, "查询失败:"+err.Error())
}
mapDN := make(map[string]*DNItem)
sortNum := 0
ownerFilterBuilder := strings.Builder{}
//每个DN存入map
ownerDN := ""
for _, v := range searchResult.Entries {
sortNum++
attribute := make(map[string]interface{})
memberCount := 0
for _, attr := range v.Attributes {
//判断是否有成员(不包含root用户所以判断大于1)
if attr.Name == "uniqueMember" {
memberCount = len(attr.Values) - 1 //不包含root用户
continue
}
if attr.Name == "owner" && len(attr.Values) != 0 { //负责人
ownerDN = attr.Values[0]
//解析用户DN只需要提取cn
userCn := strings.Split(attr.Values[0], ",")[0]
ownerFilterBuilder.WriteString(fmt.Sprintf("(%s)", userCn))
}
attribute[attr.Name] = strings.Join(attr.Values, ",")
}
dnSlice := strings.ReplaceAll(v.DN, ","+l.svcCtx.Config.Ldap.BaseDN, "") //把最顶级的组织去掉
level := len(strings.Split(dnSlice, ","))
data := &DNItem{
DN: v.DN,
ParentDN: "",
Level: level,
MemberCount: memberCount,
Attribute: attribute,
OwnerDN: ownerDN,
Sort: sortNum,
Child: make([]*DNItem, 0, 100),
}
mapDN[v.DN] = data
}
ownerFilters := ownerFilterBuilder.String()
if ownerFilters != "" {
ownerFilters = "(|" + ownerFilterBuilder.String() + ")"
//获取负责人列表信息
ldapOwnerList, err := l.svcCtx.Ldap.GetLdapBaseTeamUsersByParams(ownerFilters)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "获取部门负责人失败,"+err.Error())
}
//把负责人塞到对应部门中
for _, v := range mapDN {
for _, owner := range ldapOwnerList {
if v.OwnerDN == owner.UserDN {
v.OwnerName = owner.UserName
}
}
}
}
//组织树形层级关系
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
}
//有父级
parentDN := strings.Join(sl[1:], ",")
if parent, ok := mapDN[parentDN]; ok {
v.ParentDN = parentDN
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, "success", list)
}
// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
// func (l *GetLdapOrganizationsLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
// // httpx.OkJsonCtx(r.Context(), w, resp)
// }