Skip to content

Commit 07a63e9

Browse files
authored
feat: 添加sql数据补偿能力 (#153)
1 parent 5c099ba commit 07a63e9

File tree

15 files changed

+333
-44
lines changed

15 files changed

+333
-44
lines changed

controller/group_controller.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,11 @@ func (m *GroupController) SyncOpenLdapDepts(c *gin.Context) {
112112
return logic.OpenLdap.SyncOpenLdapDepts(c, req)
113113
})
114114
}
115+
116+
//同步Sql中的分组信息到ldap
117+
func (m *GroupController) SyncSqlGroups(c *gin.Context) {
118+
req := new(request.SyncSqlGrooupsReq)
119+
Run(c, req, func() (interface{}, interface{}) {
120+
return logic.Sql.SyncSqlGroups(c, req)
121+
})
122+
}

controller/user_controller.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,11 @@ func (uc UserController) SyncOpenLdapUsers(c *gin.Context) {
9696
return logic.OpenLdap.SyncOpenLdapUsers(c, req)
9797
})
9898
}
99+
100+
// 同步sql用户信息到ldap
101+
func (uc UserController) SyncSqlUsers(c *gin.Context) {
102+
req := new(request.SyncSqlUserReq)
103+
Run(c, req, func() (interface{}, interface{}) {
104+
return logic.Sql.SyncSqlUsers(c, req)
105+
})
106+
}

logic/a_logic.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ var (
2727
WeCom = &WeComLogic{}
2828
FeiShu = &FeiShuLogic{}
2929
OpenLdap = &OpenLdapLogic{}
30+
Sql = &SqlLogic{}
3031
Base = &BaseLogic{}
3132
FieldRelation = &FieldRelationLogic{}
3233

@@ -364,6 +365,17 @@ func InitCron() {
364365
common.Log.Errorf("启动同步用户的定时任务失败: %v", err)
365366
}
366367
}
368+
369+
// 自动检索未同步数据
370+
_, err := c.AddFunc("0 */2 * * * *", func() {
371+
// 开发调试时调整为10秒执行一次
372+
// _, err := c.AddFunc("*/10 * * * * *", func() {
373+
_ = SearchGroupDiff()
374+
_ = SearchUserDiff()
375+
})
376+
if err != nil {
377+
common.Log.Errorf("启动同步任务状态检查任务失败: %v", err)
378+
}
367379
c.Start()
368380
}
369381

logic/sqlToLdap_login.go

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
package logic
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/eryajf/go-ldap-admin/config"
7+
"github.com/eryajf/go-ldap-admin/model"
8+
"github.com/eryajf/go-ldap-admin/model/request"
9+
"github.com/eryajf/go-ldap-admin/public/tools"
10+
"github.com/eryajf/go-ldap-admin/service/ildap"
11+
"github.com/eryajf/go-ldap-admin/service/isql"
12+
"github.com/gin-gonic/gin"
13+
)
14+
15+
type SqlLogic struct{}
16+
17+
// 同步sql的用户信息到ldap
18+
func (d *SqlLogic) SyncSqlUsers(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) {
19+
r, ok := req.(*request.SyncSqlUserReq)
20+
if !ok {
21+
return nil, ReqAssertErr
22+
}
23+
_ = c
24+
// 1.获取所有用户
25+
for _, id := range r.UserIds {
26+
filter := tools.H{"id": int(id)}
27+
if !isql.User.Exist(filter) {
28+
return nil, tools.NewMySqlError(fmt.Errorf("有用户不存在"))
29+
}
30+
}
31+
users, err := isql.User.GetUserByIds(r.UserIds)
32+
if err != nil {
33+
return nil, tools.NewMySqlError(fmt.Errorf("获取用户信息失败: " + err.Error()))
34+
}
35+
// 2.再将用户添加到ldap
36+
for _, user := range users {
37+
err = ildap.User.Add(&user)
38+
if err != nil {
39+
return nil, tools.NewLdapError(fmt.Errorf("SyncUser向LDAP同步用户失败:" + err.Error()))
40+
}
41+
// 获取用户将要添加的分组
42+
groups, err := isql.Group.GetGroupByIds(tools.StringToSlice(user.DepartmentId, ","))
43+
if err != nil {
44+
return nil, tools.NewMySqlError(fmt.Errorf("根据部门ID获取部门信息失败" + err.Error()))
45+
}
46+
for _, group := range groups {
47+
//根据选择的部门,添加到部门内
48+
err = ildap.Group.AddUserToGroup(group.GroupDN, user.UserDN)
49+
if err != nil {
50+
return nil, tools.NewMySqlError(fmt.Errorf("向Ldap添加用户到分组关系失败:" + err.Error()))
51+
}
52+
}
53+
user.SyncState = 1
54+
err = isql.User.Update(&user)
55+
if err != nil {
56+
return nil, tools.NewLdapError(fmt.Errorf("用户同步完毕之后更新状态失败:" + err.Error()))
57+
}
58+
}
59+
60+
return nil, nil
61+
}
62+
63+
// 同步sql中的分组信息到ldap
64+
func (d *SqlLogic) SyncSqlGroups(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) {
65+
r, ok := req.(*request.SyncSqlGrooupsReq)
66+
if !ok {
67+
return nil, ReqAssertErr
68+
}
69+
_ = c
70+
// 1.获取所有分组
71+
for _, id := range r.GroupIds {
72+
filter := tools.H{"id": int(id)}
73+
if !isql.Group.Exist(filter) {
74+
return nil, tools.NewMySqlError(fmt.Errorf("有分组不存在"))
75+
}
76+
}
77+
groups, err := isql.Group.GetGroupByIds(r.GroupIds)
78+
if err != nil {
79+
return nil, tools.NewMySqlError(fmt.Errorf("获取分组信息失败: " + err.Error()))
80+
}
81+
// 2.再将分组添加到ldap
82+
for _, group := range groups {
83+
err = ildap.Group.Add(group)
84+
if err != nil {
85+
return nil, tools.NewLdapError(fmt.Errorf("SyncUser向LDAP同步分组失败:" + err.Error()))
86+
}
87+
if len(group.Users) > 0 {
88+
for _, user := range group.Users {
89+
if user.UserDN == config.Conf.Ldap.AdminDN {
90+
continue
91+
}
92+
err = ildap.Group.AddUserToGroup(group.GroupDN, user.UserDN)
93+
if err != nil {
94+
return nil, tools.NewLdapError(fmt.Errorf("同步分组之后处理分组内的用户失败:" + err.Error()))
95+
}
96+
}
97+
}
98+
group.SyncState = 1
99+
err = isql.Group.Update(group)
100+
if err != nil {
101+
return nil, tools.NewLdapError(fmt.Errorf("分组同步完毕之后更新状态失败:" + err.Error()))
102+
}
103+
}
104+
105+
return nil, nil
106+
}
107+
108+
// 检索未同步到ldap中的分组
109+
func SearchGroupDiff() (err error) {
110+
// 获取sql中的数据
111+
var sqlGroupList []*model.Group
112+
sqlGroupList, err = isql.Group.ListAll()
113+
if err != nil {
114+
return err
115+
}
116+
// 获取ldap中的数据
117+
var ldapGroupList []*model.Group
118+
ldapGroupList, err = ildap.Group.ListGroupDN()
119+
if err != nil {
120+
return err
121+
}
122+
// 比对两个系统中的数据
123+
groups := diffGroup(sqlGroupList, ldapGroupList)
124+
for _, group := range groups {
125+
if group.GroupDN == config.Conf.Ldap.BaseDN {
126+
continue
127+
}
128+
group.SyncState = 2
129+
err = isql.Group.Update(group)
130+
}
131+
return
132+
}
133+
134+
// 检索未同步到ldap中的用户
135+
func SearchUserDiff() (err error) {
136+
// 获取sql中的数据
137+
var sqlUserList []*model.User
138+
sqlUserList, err = isql.User.ListAll()
139+
if err != nil {
140+
return err
141+
}
142+
// 获取ldap中的数据
143+
var ldapUserList []*model.User
144+
ldapUserList, err = ildap.User.ListUserDN()
145+
if err != nil {
146+
return err
147+
}
148+
// 比对两个系统中的数据
149+
users := diffUser(sqlUserList, ldapUserList)
150+
for _, user := range users {
151+
user.SyncState = 2
152+
err = isql.User.Update(user)
153+
}
154+
return
155+
}
156+
157+
func diffGroup(a, b []*model.Group) (rst []*model.Group) {
158+
var tmp = make(map[string]struct{}, 0)
159+
160+
for _, v := range b {
161+
tmp[v.GroupDN] = struct{}{}
162+
}
163+
164+
for _, v := range a {
165+
if _, ok := tmp[v.GroupDN]; !ok {
166+
rst = append(rst, v)
167+
}
168+
}
169+
return
170+
}
171+
func diffUser(a, b []*model.User) (rst []*model.User) {
172+
var tmp = make(map[string]struct{}, len(a))
173+
174+
for _, v := range b {
175+
tmp[v.UserDN] = struct{}{}
176+
}
177+
178+
for _, v := range a {
179+
if _, ok := tmp[v.UserDN]; !ok {
180+
rst = append(rst, v)
181+
}
182+
}
183+
return
184+
}

model/group.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ type Group struct {
1717
SourceDeptParentId string `gorm:"type:varchar(100);comment:'父部门编号'" json:"sourceDeptParentId"`
1818
SourceUserNum int `gorm:"default:0;comment:'部门下的用户数量,从第三方获取的数据'" json:"source_user_num"`
1919
Children []*Group `gorm:"-" json:"children"`
20-
GroupDN string `gorm:"type:varchar(255);not null;comment:'分组dn'" json:"groupDn"` // 分组在ldap的dn
20+
GroupDN string `gorm:"type:varchar(255);not null;comment:'分组dn'" json:"groupDn"` // 分组在ldap的dn
21+
SyncState uint `gorm:"type:tinyint(1);default:1;comment:'同步状态:1已同步, 2未同步'" json:"syncState"` // 数据到ldap的同步状态
2122
}
2223

2324
func (g *Group) SetGroupName(groupName string) {

model/request/group_req.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ type GroupListReq struct {
66
Remark string `json:"remark" form:"remark"`
77
PageNum int `json:"pageNum" form:"pageNum"`
88
PageSize int `json:"pageSize" form:"pageSize"`
9+
SyncState uint `json:"syncState" form:"syncState" `
910
}
1011

1112
// GroupListAllReq 获取资源列表结构体,不分页
@@ -110,3 +111,8 @@ type SyncFeiShuDeptsReq struct {
110111
// SyncOpenLdapDeptsReq 同步原ldap部门信息
111112
type SyncOpenLdapDeptsReq struct {
112113
}
114+
115+
// SyncOpenLdapDeptsReq 同步原ldap部门信息
116+
type SyncSqlGrooupsReq struct {
117+
GroupIds []uint `json:"groupIds" validate:"required"`
118+
}

model/request/user_req.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ type SyncFeiShuUserReq struct {
119119
// SyncOpenLdapUserReq 同步ldap用户信息
120120
type SyncOpenLdapUserReq struct {
121121
}
122+
type SyncSqlUserReq struct {
123+
UserIds []uint `json:"userIds" validate:"required"`
124+
}
122125

123126
// UserListReq 获取用户列表结构体
124127
type UserListReq struct {
@@ -128,6 +131,7 @@ type UserListReq struct {
128131
GivenName string `json:"givenName" form:"givenName"`
129132
DepartmentId []uint `json:"departmentId" form:"departmentId"`
130133
Status uint `json:"status" form:"status" `
134+
SyncState uint `json:"syncState" form:"syncState" `
131135
PageNum int `json:"pageNum" form:"pageNum"`
132136
PageSize int `json:"pageSize" form:"pageSize"`
133137
}

model/user.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type User struct {
2424
SourceUserId string `gorm:"type:varchar(100);not null;comment:'第三方用户id'" json:"sourceUserId"` // 第三方用户id
2525
SourceUnionId string `gorm:"type:varchar(100);not null;comment:'第三方唯一unionId'" json:"sourceUnionId"` // 第三方唯一unionId
2626
UserDN string `gorm:"type:varchar(255);not null;comment:'用户dn'" json:"userDn"` // 用户在ldap的dn
27+
SyncState uint `gorm:"type:tinyint(1);default:1;comment:'同步状态:1已同步, 2未同步'" json:"syncState"` // 数据到ldap的同步状态
2728
}
2829

2930
func (u *User) SetUserName(userName string) {

public/common/init_mysql_data.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,13 @@ func InitData() {
368368
Remark: "从openldap拉取用户信息",
369369
Creator: "系统",
370370
},
371+
{
372+
Method: "POST",
373+
Path: "/user/syncSqlUsers",
374+
Category: "user",
375+
Remark: "将数据库中的用户同步到Ldap",
376+
Creator: "系统",
377+
},
371378
{
372379
Method: "GET",
373380
Path: "/group/list",
@@ -459,6 +466,13 @@ func InitData() {
459466
Remark: "从openldap拉取部门信息",
460467
Creator: "系统",
461468
},
469+
{
470+
Method: "POST",
471+
Path: "/group/syncSqlGroups",
472+
Category: "group",
473+
Remark: "将数据库中的分组同步到Ldap",
474+
Creator: "系统",
475+
},
462476
{
463477
Method: "GET",
464478
Path: "/role/list",

routes/group_routes.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,11 @@ func InitGroupRoutes(r *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) g
2626
group.GET("/useringroup", controller.Group.UserInGroup)
2727
group.GET("/usernoingroup", controller.Group.UserNoInGroup)
2828

29-
group.POST("/syncDingTalkDepts", controller.Group.SyncDingTalkDepts) // 同步部门
30-
group.POST("/syncWeComDepts", controller.Group.SyncWeComDepts) // 同步部门
31-
group.POST("/syncFeiShuDepts", controller.Group.SyncFeiShuDepts) // 同步部门
32-
group.POST("/syncOpenLdapDepts", controller.Group.SyncOpenLdapDepts) // 同步部门
29+
group.POST("/syncDingTalkDepts", controller.Group.SyncDingTalkDepts) // 同步钉钉部门到平台
30+
group.POST("/syncWeComDepts", controller.Group.SyncWeComDepts) // 同步企业微信部门到平台
31+
group.POST("/syncFeiShuDepts", controller.Group.SyncFeiShuDepts) // 同步飞书部门到平台
32+
group.POST("/syncOpenLdapDepts", controller.Group.SyncOpenLdapDepts) // 同步ldap的分组到平台InitGroupRoutes
33+
group.POST("/syncSqlGroups", controller.Group.SyncSqlGroups) // 同步Sql分组到Ldap
3334
}
3435

3536
return r

0 commit comments

Comments
 (0)