diff --git a/model/gmodel/a_test.go b/model/gmodel/a_test.go new file mode 100644 index 00000000..def666f6 --- /dev/null +++ b/model/gmodel/a_test.go @@ -0,0 +1,23 @@ +package gmodel + +import ( + "log" + "testing" + + "github.com/tidwall/gjson" +) + +func TestCase1(t *testing.T) { + v := `{"base": {"mobile": "18588505404", "company": "fusen", "last_name": "sm", "first_name": "h", "resetaurant": "boy"}, "sub_status": {"notification_email": {"newseleter": false, "order_update": false}, "notification_phone": {"newseleter": true, "order_update": false}}, "logo_selected": {"logo_url": "https://fusenstorage.s3.us-east-2.amazonaws.com/d163cba052dc03e7684a4fa8574a17c629e08b6cd0f47f9c239866949365f807", "logo_selected_id": 5018, "merchant_category": 10, "template_tag_selected": {"color": [["#25211F"], ["#1E1916"]], "version": "2", "template_tag": "C6", "selected_index": 0}}}` + + // log.Println(userId, guestId, v) + if logoSelected := gjson.Get(v, "logo_selected"); logoSelected.Exists() { + log.Println(logoSelected) + log.Println(logoSelected.Get("version")) + if ver := logoSelected.Get("version"); ver.Exists() && ver.String() == versionML { + log.Println(ver) + } + } + + // gjson.Get(content, "logo_selected") +} diff --git a/model/gmodel/fs_user_info_logic.go b/model/gmodel/fs_user_info_logic.go index 17ba0982..bb4eeaed 100644 --- a/model/gmodel/fs_user_info_logic.go +++ b/model/gmodel/fs_user_info_logic.go @@ -8,7 +8,9 @@ import ( "fmt" "fusenapi/utils/fssql" "fusenapi/utils/handlers" + "log" + "github.com/tidwall/gjson" "gorm.io/gorm" ) @@ -113,26 +115,19 @@ func (m *FsUserInfoModel) GetProfile(ctx context.Context, pkey string, userId in return m.getDefaultProfile(ctx, tname) } - if logoSelected, ok := info["logo_selected"]; ok { - if version, ok := logoSelected.(map[string]any)["version"]; ok { - if ver, ok := version.(string); ok { - if ver != versionML { - defaultUserInfo, err := m.getDefaultProfile(ctx, tname) - if err != nil { - return nil, err - } - info["logo_selected"] = defaultUserInfo["logo_selected"] - } - } + if logoSelected := gjson.Get(v, "logo_selected"); logoSelected.Exists() { + if ver := logoSelected.Get("template_tag_selected.version"); ver.Exists() && ver.String() == versionML { + log.Println(ver) + return info, nil } - } else { - defaultUserInfo, err := m.getDefaultProfile(ctx, tname) - if err != nil { - return nil, err - } - info["logo_selected"] = defaultUserInfo["logo_selected"] } + defaultUserInfo, err := m.getDefaultProfile(ctx, tname) + if err != nil { + return nil, err + } + info["logo_selected"] = defaultUserInfo["logo_selected"] + return info, nil } diff --git a/server/ldap-admin/internal/logic/createldaporganizationlogic.go b/server/ldap-admin/internal/logic/createldaporganizationlogic.go index c662e47f..6d0d86ad 100644 --- a/server/ldap-admin/internal/logic/createldaporganizationlogic.go +++ b/server/ldap-admin/internal/logic/createldaporganizationlogic.go @@ -3,6 +3,7 @@ package logic import ( "fusenapi/utils/basic" "fusenapi/utils/chinese_to_pinyin" + "fusenapi/utils/email" "net/http" "strings" @@ -37,30 +38,31 @@ func (l *CreateLdapOrganizationLogic) CreateLdapOrganization(req *types.CreateLd if !l.svcCtx.Ldap.VerifyAuthority(r) { return resp.SetStatusWithMessage(basic.CodeUnAuth, "无权限,请联系管理员开通") } - req.OrganizationEnName = strings.Trim(req.OrganizationEnName, " ") req.ParentOrganizationDN = strings.Trim(req.ParentOrganizationDN, " ") - req.BusinessCategory = strings.Trim(req.BusinessCategory, " ") - if len(strings.Split(req.OrganizationEnName, ",")) != 1 { - return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "参数错误,组织英文名不符合规范") - } - //转拼音比较下 - if req.OrganizationEnName != chinese_to_pinyin.ChineseToPinyin(req.OrganizationEnName) { - return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "参数错误,组织英文名不能包含中文") + req.OrganizationName = strings.Trim(req.OrganizationName, " ") + if req.OrganizationName == "" { + return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "组织名不能为空") } if req.ParentOrganizationDN == "" { req.ParentOrganizationDN = l.svcCtx.Config.Ldap.BaseDN //不传则是第一层级 } - if req.BusinessCategory == "" { - return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "参数错误,组织分类名不能为空") + if len(req.OwnerDN) <= 3 || req.OwnerDN[:3] != "cn=" { + return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "无效的用户DN") } + cnEmail := strings.Split(req.OwnerDN, ",")[0][3:] + if !email.IsEmailValid(cnEmail) { + return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "错误的用户cn") + } + organizationNamePinyin := chinese_to_pinyin.ChineseToPinyin(req.OrganizationName) //组装organization dn - organizationDN := "ou=" + req.OrganizationEnName + "," + req.ParentOrganizationDN + organizationDN := "ou=" + organizationNamePinyin + "," + req.ParentOrganizationDN err := l.svcCtx.Ldap.Create(organizationDN, map[string][]string{ "objectClass": {"top", "groupOfUniqueNames"}, - "cn": {req.OrganizationEnName}, - "ou": {req.OrganizationEnName}, - "businessCategory": {req.BusinessCategory}, - "uniqueMember": {l.svcCtx.Config.Ldap.RootDN}, //创建groupOfUniqueNames对象类型需要至少一个member,把root加进去 + "owner": {req.OwnerDN}, //负责人DN + "cn": {organizationNamePinyin}, + "ou": {organizationNamePinyin}, + "businessCategory": {req.OrganizationName}, + "uniqueMember": {req.OwnerDN}, //必须有一个初始的成员 }) if err != nil { logx.Error(err) diff --git a/server/ldap-admin/internal/logic/getldaporganizationslogic.go b/server/ldap-admin/internal/logic/getldaporganizationslogic.go index 80da8855..2fc516b7 100644 --- a/server/ldap-admin/internal/logic/getldaporganizationslogic.go +++ b/server/ldap-admin/internal/logic/getldaporganizationslogic.go @@ -1,6 +1,7 @@ package logic import ( + "fmt" "fusenapi/utils/basic" "github.com/go-ldap/ldap/v3" "net/http" @@ -33,13 +34,15 @@ func NewGetLdapOrganizationsLogic(ctx context.Context, svcCtx *svc.ServiceContex // func (l *GetLdapOrganizationsLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) { // } type DNItem struct { - Attribute map[string]interface{} `json:"attribute"` - MemberCount int `json:"member_count"` - Level int `json:"level"` - DN string `json:"dn"` - ParentDN string `json:"parent_dn"` - Sort int `json:"sort"` - Child []*DNItem `json:"child"` + MemberCount int `json:"member_count"` + OrganizationName string `json:"organization_name"` + OwnerName string `json:"owner_name"` + OwnerDN string `json:"owner_dn"` + Level int `json:"level"` + OrganizationDN string `json:"organization_dn"` + ParentOrganizationDN string `json:"parent_organization_dn"` + Sort int `json:"sort"` + Child []*DNItem `json:"child"` } func (l *GetLdapOrganizationsLogic) GetLdapOrganizations(req *types.Request, r *http.Request) (resp *basic.Response) { @@ -57,36 +60,65 @@ func (l *GetLdapOrganizationsLogic) GetLdapOrganizations(req *types.Request, r * return resp.SetStatusWithMessage(basic.CodeServiceErr, "基础用户组的DN未配置") } filter := "(&(objectClass=groupOfUniqueNames)(objectClass=top))" - fields := []string{"businessCategory", "dn", "uniqueMember"} + 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 + memberCount := 0 //成员数 + departmentName := "" //部门名称 for _, attr := range v.Attributes { - //判断是否有成员(不包含root用户所以判断大于1) - if attr.Name == "uniqueMember" { + switch attr.Name { + case "uniqueMember": memberCount = len(attr.Values) - continue + case "owner": + if len(attr.Values) == 0 { + continue + } + ownerDN = attr.Values[0] + //解析用户DN,只需要提取cn + userCn := strings.Split(attr.Values[0], ",")[0] + ownerFilterBuilder.WriteString(fmt.Sprintf("(%s)", userCn)) + case "businessCategory": + departmentName = strings.Join(attr.Values, ",") } - attribute[attr.Name] = strings.Join(attr.Values, ",") } dnSlice := strings.ReplaceAll(v.DN, ","+l.svcCtx.Config.Ldap.BaseDN, "") //把最顶级的组织去掉 level := len(strings.Split(dnSlice, ",")) - mapDN[v.DN] = &DNItem{ - DN: v.DN, - ParentDN: "", - Level: level, - MemberCount: memberCount, - Attribute: attribute, - Sort: sortNum, - Child: make([]*DNItem, 0, 100), + data := &DNItem{ + OrganizationDN: v.DN, + OrganizationName: departmentName, + Level: level, + MemberCount: memberCount, + 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 + } + } } } //组织树形层级关系 @@ -104,7 +136,7 @@ func (l *GetLdapOrganizationsLogic) GetLdapOrganizations(req *types.Request, r * //有父级 parentDN := strings.Join(sl[1:], ",") if parent, ok := mapDN[parentDN]; ok { - v.ParentDN = parentDN + v.ParentOrganizationDN = parentDN parent.Child = append(parent.Child, v) //排序 sort.Slice(parent.Child, func(i, j int) bool { diff --git a/server/ldap-admin/internal/logic/getldapuserslogic.go b/server/ldap-admin/internal/logic/getldapuserslogic.go index 195f98d3..ebf1f3e1 100644 --- a/server/ldap-admin/internal/logic/getldapuserslogic.go +++ b/server/ldap-admin/internal/logic/getldapuserslogic.go @@ -38,7 +38,12 @@ func (l *GetLdapUsersLogic) GetLdapUsers(req *types.GetLdapUsersReq, r *http.Req } req.PageCookie = strings.Trim(req.PageCookie, " ") pageSize := uint32(20) - list, cookie, err := l.svcCtx.Ldap.GetLdapBaseTeamUserList(pageSize, req.PageCookie) + filter := "(objectClass=person)" + //有关键词就模糊搜索 + if req.UserName != "" { + filter = "(&(objectClass=person)(sn=*" + req.UserName + "*))" + } + list, cookie, err := l.svcCtx.Ldap.GetLdapBaseTeamUserList(pageSize, filter, req.PageCookie) if err != nil { logx.Error(err) return resp.SetStatusWithMessage(basic.CodeServiceErr, "查询用户列表报错,"+err.Error()) diff --git a/server/ldap-admin/internal/logic/updateldaporganizationlogic.go b/server/ldap-admin/internal/logic/updateldaporganizationlogic.go index 623940b2..1ed13404 100644 --- a/server/ldap-admin/internal/logic/updateldaporganizationlogic.go +++ b/server/ldap-admin/internal/logic/updateldaporganizationlogic.go @@ -44,7 +44,7 @@ func (l *UpdateLdapOrganizationLogic) UpdateLdapOrganization(req *types.UpdateLd return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "参数错误,无效的组织DN") } if err := l.svcCtx.Ldap.Update(req.OrganizationDN, map[string][]string{ - "businessCategory": {req.BusinessCategory}, + "businessCategory": {req.OrganizationName}, }); err != nil { logx.Error(err) return resp.SetStatusWithMessage(basic.CodeServiceErr, "更新ldap组织失败,"+err.Error()) diff --git a/server/ldap-admin/internal/types/types.go b/server/ldap-admin/internal/types/types.go index 8a119fe8..deffe809 100644 --- a/server/ldap-admin/internal/types/types.go +++ b/server/ldap-admin/internal/types/types.go @@ -133,9 +133,9 @@ type MenuItem struct { } type CreateLdapOrganizationReq struct { - OrganizationEnName string `json:"organization_en_name"` //组织英文名 - BusinessCategory string `json:"business_category"` //组织类别 - ParentOrganizationDN string `json:"parent_organization_dn"` //父级dn + OrganizationName string `json:"organization_name"` //组织名 + ParentOrganizationDN string `json:"parent_organization_dn,optional"` //父级dn + OwnerDN string `json:"owner_dn,optional"` //负责人dn } type DeleteLdapOrganizationReq struct { @@ -144,7 +144,7 @@ type DeleteLdapOrganizationReq struct { type UpdateLdapOrganizationReq struct { OrganizationDN string `json:"organization_dn"` //组织dn - BusinessCategory string `json:"business_category"` //组织分类名称 + OrganizationName string `json:"organization_name"` //组织分类名称 } type CreateLdapUserReq struct { @@ -224,6 +224,7 @@ type GetLdapOrganizationMembersItem struct { type GetLdapUsersReq struct { PageCookie string `form:"page_cookie,optional"` //下一页分页游标,传空/不传就是第一页 + UserName string `form:"user_name,optional"` //用户名用于模糊搜索 } type GetLdapUsersRsp struct { diff --git a/server_api/ldap-admin.api b/server_api/ldap-admin.api index 8e5c3dfd..82eace84 100644 --- a/server_api/ldap-admin.api +++ b/server_api/ldap-admin.api @@ -22,11 +22,11 @@ service ldap-admin { //删除权限组 @handler DeleteLdapGroupHandler post /api/ldap-admin/delete_ldap_group(DeleteLdapGroupReq) returns (response); - + //权限组授权 @handler SetLdapGroupAuthHandler post /api/ldap-admin/set_ldap_group_auth(SetLdapGroupAuthReq) returns (response); - + //权限组授权用户 @handler SetLdapGroupUserHandler post /api/ldap-admin/set_ldap_group_user(SetLdapGroupUserReq) returns (response); @@ -39,7 +39,7 @@ service ldap-admin { //删除API @handler DeleteApiHandler post /api/ldap-admin/delete_api(DeleteApiReq) returns (response); - + //保存菜单 @handler SaveMenuHandler post /api/ldap-admin/save_menu(SaveMenuReq) returns (response); @@ -221,9 +221,9 @@ type MenuItem { } //增加ldap组织 type CreateLdapOrganizationReq { - OrganizationEnName string `json:"organization_en_name"` //组织英文名 - BusinessCategory string `json:"business_category"` //组织类别 - ParentOrganizationDN string `json:"parent_organization_dn"` //父级dn + OrganizationName string `json:"organization_name"` //组织名 + ParentOrganizationDN string `json:"parent_organization_dn,optional"` //父级dn + OwnerDN string `json:"owner_dn,optional"` //负责人dn } //删除ldap组织 type DeleteLdapOrganizationReq { @@ -232,7 +232,7 @@ type DeleteLdapOrganizationReq { //修改ldap组织 type UpdateLdapOrganizationReq { OrganizationDN string `json:"organization_dn"` //组织dn - BusinessCategory string `json:"business_category"` //组织分类名称 + OrganizationName string `json:"organization_name"` //组织分类名称 } //添加ldap用户帐号 type CreateLdapUserReq { @@ -309,6 +309,7 @@ type GetLdapOrganizationMembersItem { //获取基础用户组中成员列表 type GetLdapUsersReq { PageCookie string `form:"page_cookie,optional"` //下一页分页游标,传空/不传就是第一页 + UserName string `form:"user_name,optional"` //用户名用于模糊搜索 } type GetLdapUsersRsp { List []GetLdapUsersItem `json:"list"` diff --git a/utils/ldap_lib/ldap_user.go b/utils/ldap_lib/ldap_user.go index 3e61fe90..a245d8f7 100644 --- a/utils/ldap_lib/ldap_user.go +++ b/utils/ldap_lib/ldap_user.go @@ -84,12 +84,12 @@ func (l *Ldap) GetLdapUserInfo(userDN string) (*LdapUserInfo, error) { } // 获取基础组用户列表 -func (l *Ldap) GetLdapBaseTeamUserList(pageSize uint32, pageCookie string) ([]LdapUserInfo, string, error) { +func (l *Ldap) GetLdapBaseTeamUserList(pageSize uint32, filter, pageCookie string) ([]LdapUserInfo, string, error) { pageCookieBytes, err := hex.DecodeString(pageCookie) if err != nil { return nil, "", err } - result, err := l.SearchWithPaging(l.peopleGroupDN, ldap.ScopeWholeSubtree, "(objectClass=person)", nil, pageSize, string(pageCookieBytes)) + result, err := l.SearchWithPaging(l.peopleGroupDN, ldap.ScopeWholeSubtree, filter, nil, pageSize, string(pageCookieBytes)) if err != nil { return nil, "", err }