Skip to content

Commit

Permalink
feat: 添加sql数据补偿能力 (#153)
Browse files Browse the repository at this point in the history
  • Loading branch information
eryajf authored Feb 22, 2023
1 parent 5c099ba commit 07a63e9
Show file tree
Hide file tree
Showing 15 changed files with 333 additions and 44 deletions.
8 changes: 8 additions & 0 deletions controller/group_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,11 @@ func (m *GroupController) SyncOpenLdapDepts(c *gin.Context) {
return logic.OpenLdap.SyncOpenLdapDepts(c, req)
})
}

//同步Sql中的分组信息到ldap
func (m *GroupController) SyncSqlGroups(c *gin.Context) {
req := new(request.SyncSqlGrooupsReq)
Run(c, req, func() (interface{}, interface{}) {
return logic.Sql.SyncSqlGroups(c, req)
})
}
8 changes: 8 additions & 0 deletions controller/user_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,11 @@ func (uc UserController) SyncOpenLdapUsers(c *gin.Context) {
return logic.OpenLdap.SyncOpenLdapUsers(c, req)
})
}

// 同步sql用户信息到ldap
func (uc UserController) SyncSqlUsers(c *gin.Context) {
req := new(request.SyncSqlUserReq)
Run(c, req, func() (interface{}, interface{}) {
return logic.Sql.SyncSqlUsers(c, req)
})
}
12 changes: 12 additions & 0 deletions logic/a_logic.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ var (
WeCom = &WeComLogic{}
FeiShu = &FeiShuLogic{}
OpenLdap = &OpenLdapLogic{}
Sql = &SqlLogic{}
Base = &BaseLogic{}
FieldRelation = &FieldRelationLogic{}

Expand Down Expand Up @@ -364,6 +365,17 @@ func InitCron() {
common.Log.Errorf("启动同步用户的定时任务失败: %v", err)
}
}

// 自动检索未同步数据
_, err := c.AddFunc("0 */2 * * * *", func() {
// 开发调试时调整为10秒执行一次
// _, err := c.AddFunc("*/10 * * * * *", func() {
_ = SearchGroupDiff()
_ = SearchUserDiff()
})
if err != nil {
common.Log.Errorf("启动同步任务状态检查任务失败: %v", err)
}
c.Start()
}

Expand Down
184 changes: 184 additions & 0 deletions logic/sqlToLdap_login.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
package logic

import (
"fmt"

"github.com/eryajf/go-ldap-admin/config"
"github.com/eryajf/go-ldap-admin/model"
"github.com/eryajf/go-ldap-admin/model/request"
"github.com/eryajf/go-ldap-admin/public/tools"
"github.com/eryajf/go-ldap-admin/service/ildap"
"github.com/eryajf/go-ldap-admin/service/isql"
"github.com/gin-gonic/gin"
)

type SqlLogic struct{}

// 同步sql的用户信息到ldap
func (d *SqlLogic) SyncSqlUsers(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) {
r, ok := req.(*request.SyncSqlUserReq)
if !ok {
return nil, ReqAssertErr
}
_ = c
// 1.获取所有用户
for _, id := range r.UserIds {
filter := tools.H{"id": int(id)}
if !isql.User.Exist(filter) {
return nil, tools.NewMySqlError(fmt.Errorf("有用户不存在"))
}
}
users, err := isql.User.GetUserByIds(r.UserIds)
if err != nil {
return nil, tools.NewMySqlError(fmt.Errorf("获取用户信息失败: " + err.Error()))
}
// 2.再将用户添加到ldap
for _, user := range users {
err = ildap.User.Add(&user)
if err != nil {
return nil, tools.NewLdapError(fmt.Errorf("SyncUser向LDAP同步用户失败:" + err.Error()))
}
// 获取用户将要添加的分组
groups, err := isql.Group.GetGroupByIds(tools.StringToSlice(user.DepartmentId, ","))
if err != nil {
return nil, tools.NewMySqlError(fmt.Errorf("根据部门ID获取部门信息失败" + err.Error()))
}
for _, group := range groups {
//根据选择的部门,添加到部门内
err = ildap.Group.AddUserToGroup(group.GroupDN, user.UserDN)
if err != nil {
return nil, tools.NewMySqlError(fmt.Errorf("向Ldap添加用户到分组关系失败:" + err.Error()))
}
}
user.SyncState = 1
err = isql.User.Update(&user)
if err != nil {
return nil, tools.NewLdapError(fmt.Errorf("用户同步完毕之后更新状态失败:" + err.Error()))
}
}

return nil, nil
}

// 同步sql中的分组信息到ldap
func (d *SqlLogic) SyncSqlGroups(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) {
r, ok := req.(*request.SyncSqlGrooupsReq)
if !ok {
return nil, ReqAssertErr
}
_ = c
// 1.获取所有分组
for _, id := range r.GroupIds {
filter := tools.H{"id": int(id)}
if !isql.Group.Exist(filter) {
return nil, tools.NewMySqlError(fmt.Errorf("有分组不存在"))
}
}
groups, err := isql.Group.GetGroupByIds(r.GroupIds)
if err != nil {
return nil, tools.NewMySqlError(fmt.Errorf("获取分组信息失败: " + err.Error()))
}
// 2.再将分组添加到ldap
for _, group := range groups {
err = ildap.Group.Add(group)
if err != nil {
return nil, tools.NewLdapError(fmt.Errorf("SyncUser向LDAP同步分组失败:" + err.Error()))
}
if len(group.Users) > 0 {
for _, user := range group.Users {
if user.UserDN == config.Conf.Ldap.AdminDN {
continue
}
err = ildap.Group.AddUserToGroup(group.GroupDN, user.UserDN)
if err != nil {
return nil, tools.NewLdapError(fmt.Errorf("同步分组之后处理分组内的用户失败:" + err.Error()))
}
}
}
group.SyncState = 1
err = isql.Group.Update(group)
if err != nil {
return nil, tools.NewLdapError(fmt.Errorf("分组同步完毕之后更新状态失败:" + err.Error()))
}
}

return nil, nil
}

// 检索未同步到ldap中的分组
func SearchGroupDiff() (err error) {
// 获取sql中的数据
var sqlGroupList []*model.Group
sqlGroupList, err = isql.Group.ListAll()
if err != nil {
return err
}
// 获取ldap中的数据
var ldapGroupList []*model.Group
ldapGroupList, err = ildap.Group.ListGroupDN()
if err != nil {
return err
}
// 比对两个系统中的数据
groups := diffGroup(sqlGroupList, ldapGroupList)
for _, group := range groups {
if group.GroupDN == config.Conf.Ldap.BaseDN {
continue
}
group.SyncState = 2
err = isql.Group.Update(group)
}
return
}

// 检索未同步到ldap中的用户
func SearchUserDiff() (err error) {
// 获取sql中的数据
var sqlUserList []*model.User
sqlUserList, err = isql.User.ListAll()
if err != nil {
return err
}
// 获取ldap中的数据
var ldapUserList []*model.User
ldapUserList, err = ildap.User.ListUserDN()
if err != nil {
return err
}
// 比对两个系统中的数据
users := diffUser(sqlUserList, ldapUserList)
for _, user := range users {
user.SyncState = 2
err = isql.User.Update(user)
}
return
}

func diffGroup(a, b []*model.Group) (rst []*model.Group) {
var tmp = make(map[string]struct{}, 0)

for _, v := range b {
tmp[v.GroupDN] = struct{}{}
}

for _, v := range a {
if _, ok := tmp[v.GroupDN]; !ok {
rst = append(rst, v)
}
}
return
}
func diffUser(a, b []*model.User) (rst []*model.User) {
var tmp = make(map[string]struct{}, len(a))

for _, v := range b {
tmp[v.UserDN] = struct{}{}
}

for _, v := range a {
if _, ok := tmp[v.UserDN]; !ok {
rst = append(rst, v)
}
}
return
}
3 changes: 2 additions & 1 deletion model/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ type Group struct {
SourceDeptParentId string `gorm:"type:varchar(100);comment:'父部门编号'" json:"sourceDeptParentId"`
SourceUserNum int `gorm:"default:0;comment:'部门下的用户数量,从第三方获取的数据'" json:"source_user_num"`
Children []*Group `gorm:"-" json:"children"`
GroupDN string `gorm:"type:varchar(255);not null;comment:'分组dn'" json:"groupDn"` // 分组在ldap的dn
GroupDN string `gorm:"type:varchar(255);not null;comment:'分组dn'" json:"groupDn"` // 分组在ldap的dn
SyncState uint `gorm:"type:tinyint(1);default:1;comment:'同步状态:1已同步, 2未同步'" json:"syncState"` // 数据到ldap的同步状态
}

func (g *Group) SetGroupName(groupName string) {
Expand Down
6 changes: 6 additions & 0 deletions model/request/group_req.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ type GroupListReq struct {
Remark string `json:"remark" form:"remark"`
PageNum int `json:"pageNum" form:"pageNum"`
PageSize int `json:"pageSize" form:"pageSize"`
SyncState uint `json:"syncState" form:"syncState" `
}

// GroupListAllReq 获取资源列表结构体,不分页
Expand Down Expand Up @@ -110,3 +111,8 @@ type SyncFeiShuDeptsReq struct {
// SyncOpenLdapDeptsReq 同步原ldap部门信息
type SyncOpenLdapDeptsReq struct {
}

// SyncOpenLdapDeptsReq 同步原ldap部门信息
type SyncSqlGrooupsReq struct {
GroupIds []uint `json:"groupIds" validate:"required"`
}
4 changes: 4 additions & 0 deletions model/request/user_req.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ type SyncFeiShuUserReq struct {
// SyncOpenLdapUserReq 同步ldap用户信息
type SyncOpenLdapUserReq struct {
}
type SyncSqlUserReq struct {
UserIds []uint `json:"userIds" validate:"required"`
}

// UserListReq 获取用户列表结构体
type UserListReq struct {
Expand All @@ -128,6 +131,7 @@ type UserListReq struct {
GivenName string `json:"givenName" form:"givenName"`
DepartmentId []uint `json:"departmentId" form:"departmentId"`
Status uint `json:"status" form:"status" `
SyncState uint `json:"syncState" form:"syncState" `
PageNum int `json:"pageNum" form:"pageNum"`
PageSize int `json:"pageSize" form:"pageSize"`
}
Expand Down
1 change: 1 addition & 0 deletions model/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type User struct {
SourceUserId string `gorm:"type:varchar(100);not null;comment:'第三方用户id'" json:"sourceUserId"` // 第三方用户id
SourceUnionId string `gorm:"type:varchar(100);not null;comment:'第三方唯一unionId'" json:"sourceUnionId"` // 第三方唯一unionId
UserDN string `gorm:"type:varchar(255);not null;comment:'用户dn'" json:"userDn"` // 用户在ldap的dn
SyncState uint `gorm:"type:tinyint(1);default:1;comment:'同步状态:1已同步, 2未同步'" json:"syncState"` // 数据到ldap的同步状态
}

func (u *User) SetUserName(userName string) {
Expand Down
14 changes: 14 additions & 0 deletions public/common/init_mysql_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,13 @@ func InitData() {
Remark: "从openldap拉取用户信息",
Creator: "系统",
},
{
Method: "POST",
Path: "/user/syncSqlUsers",
Category: "user",
Remark: "将数据库中的用户同步到Ldap",
Creator: "系统",
},
{
Method: "GET",
Path: "/group/list",
Expand Down Expand Up @@ -459,6 +466,13 @@ func InitData() {
Remark: "从openldap拉取部门信息",
Creator: "系统",
},
{
Method: "POST",
Path: "/group/syncSqlGroups",
Category: "group",
Remark: "将数据库中的分组同步到Ldap",
Creator: "系统",
},
{
Method: "GET",
Path: "/role/list",
Expand Down
9 changes: 5 additions & 4 deletions routes/group_routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ func InitGroupRoutes(r *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) g
group.GET("/useringroup", controller.Group.UserInGroup)
group.GET("/usernoingroup", controller.Group.UserNoInGroup)

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

return r
Expand Down
9 changes: 5 additions & 4 deletions routes/user_routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ func InitUserRoutes(r *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) gi
user.POST("/changePwd", controller.User.ChangePwd) // 修改用户密码
user.POST("/changeUserStatus", controller.User.ChangeUserStatus) // 修改用户状态

user.POST("/syncDingTalkUsers", controller.User.SyncDingTalkUsers) // 同步用户
user.POST("/syncWeComUsers", controller.User.SyncWeComUsers) // 同步用户
user.POST("/syncFeiShuUsers", controller.User.SyncFeiShuUsers) // 同步用户
user.POST("/syncOpenLdapUsers", controller.User.SyncOpenLdapUsers) // 同步用户
user.POST("/syncDingTalkUsers", controller.User.SyncDingTalkUsers) // 同步钉钉用户到平台
user.POST("/syncWeComUsers", controller.User.SyncWeComUsers) // 同步企业微信用户到平台
user.POST("/syncFeiShuUsers", controller.User.SyncFeiShuUsers) // 同步飞书用户到平台
user.POST("/syncOpenLdapUsers", controller.User.SyncOpenLdapUsers) // 同步Ldap用户到平台
user.POST("/syncSqlUsers", controller.User.SyncSqlUsers) // 同步Sql用户到Ldap
}
return r
}
Loading

0 comments on commit 07a63e9

Please sign in to comment.