fix: 多级部门同步的问题 (#79)

* fix: dockerfile调整初始化方式
* fix: 多级部门同步的问题
This commit is contained in:
二丫讲梵 2022-07-13 16:43:05 +08:00 committed by GitHub
parent 22f12d8ec8
commit 1d0df89013
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 96 additions and 104 deletions

View File

@ -5,12 +5,13 @@ FROM golang:1.17.10 AS builder
RUN mkdir /app RUN mkdir /app
ADD . /app/ ADD . /app/
WORKDIR /app WORKDIR /app
RUN go build -o go-ldap-admin . RUN sed -i 's@localhost:389@openldap:389@g' /app/config.yml \
&& sed -i 's@host: localhost@host: mysql@g' /app/config.yml && go build -o go-ldap-admin .
FROM centos:centos7 FROM centos:centos7
RUN mkdir /app RUN mkdir /app
WORKDIR /app WORKDIR /app
COPY --from=builder /app/ . COPY --from=builder /app/ .
RUN chmod +x wait go-ldap-admin docker-start.sh && yum -y install vim net-tools telnet wget curl && yum clean all RUN chmod +x wait go-ldap-admin && yum -y install vim net-tools telnet wget curl && yum clean all
CMD [ "sh", "-c", "/app/docker-start.sh" ] CMD ./wait && ./go-ldap-admin

View File

@ -1,11 +0,0 @@
#/bin/bash
# 等待依赖项初始化成功
/app/wait
# 修改配置文件中的连接地址
sed -i 's@localhost:389@openldap:389@g' /app/config.yml
sed -i 's@host: localhost@host: mysql@g' /app/config.yml
# 启动服务
/app/go-ldap-admin

View File

@ -1 +0,0 @@
../../../config.yml

View File

@ -76,7 +76,7 @@ services:
WAIT_HOSTS: mysql:3306, openldap:389 WAIT_HOSTS: mysql:3306, openldap:389
ports: ports:
- 8888:8888 - 8888:8888
# volumes: # 可按需打开此配置,将配置文件挂载到本地,如果挂载需要注意修改本地配置中MySQL与ldap的连接信息 # volumes: # 可按需打开此配置,将配置文件挂载到本地 可在服务运行之后,执行 docker cp go-ldap-admin-server:/app/config.yml ./config 然后再取消改行注释
# - ./config/config.yml:/app/config.yml # - ./config/config.yml:/app/config.yml
depends_on: depends_on:
- mysql - mysql

View File

@ -27,31 +27,31 @@ func (d *FeiShuLogic) SyncFeiShuDepts(c *gin.Context, req interface{}) (data int
if err != nil { if err != nil {
return nil, tools.NewOperationError(fmt.Errorf("转换飞书部门数据失败:%s", err.Error())) return nil, tools.NewOperationError(fmt.Errorf("转换飞书部门数据失败:%s", err.Error()))
} }
// 2.将部门这个数组进行拆分一组是父ID为根的一组是父ID不为根的
var firstDepts []*model.Group // 父ID为根的部门 // 2.将远程数据转换成树
var otherDepts []*model.Group // 父ID不为根的部门 deptTree := GroupListToTree(fmt.Sprintf("%s_0", config.Conf.FeiShu.Flag), depts)
for _, dept := range depts {
if dept.SourceDeptParentId == fmt.Sprintf("%s_0", config.Conf.FeiShu.Flag) { // 3.根据树进行创建
firstDepts = append(firstDepts, dept) err = d.addDepts(deptTree.Children)
} else {
otherDepts = append(otherDepts, dept) return nil, err
}
}
// 3.先写父ID为根的再写父ID不为根的
for _, dept := range firstDepts {
err := d.AddDepts(dept)
if err != nil {
return nil, tools.NewOperationError(fmt.Errorf("SyncFeiShuDepts添加根部门失败%s", err.Error()))
}
} }
for _, dept := range otherDepts { // 添加部门
func (d FeiShuLogic) addDepts(depts []*model.Group) error {
for _, dept := range depts {
err := d.AddDepts(dept) err := d.AddDepts(dept)
if err != nil { if err != nil {
return nil, tools.NewOperationError(fmt.Errorf("SyncFeiShuDepts添加其他部门失败%s", err.Error())) return tools.NewOperationError(fmt.Errorf("DsyncFeiShuDepts添加部门失败: %s", err.Error()))
}
if len(dept.Children) != 0 {
err = d.addDepts(dept.Children)
if err != nil {
return tools.NewOperationError(fmt.Errorf("DsyncFeiShuDepts添加部门失败: %s", err.Error()))
} }
} }
return nil, nil }
return nil
} }
// AddGroup 添加部门数据 // AddGroup 添加部门数据

View File

@ -21,69 +21,63 @@ func (d *OpenLdapLogic) SyncOpenLdapDepts(c *gin.Context, req interface{}) (data
if err != nil { if err != nil {
return nil, tools.NewOperationError(fmt.Errorf("获取ldap部门列表失败%s", err.Error())) return nil, tools.NewOperationError(fmt.Errorf("获取ldap部门列表失败%s", err.Error()))
} }
// 2.将部门这个数组进行拆分一组是父ID为根的一组是父ID不为根的 groups := make([]*model.Group, 0)
var firstDepts []*openldap.Dept // 父ID为根的部门
var otherDepts []*openldap.Dept // 父ID不为根的部门
for _, dept := range depts { for _, dept := range depts {
if dept.ParentId == "openldap_0" { groups = append(groups, &model.Group{
firstDepts = append(firstDepts, dept)
} else {
otherDepts = append(otherDepts, dept)
}
}
// 3.先写父ID为根的再写父ID不为根的
for _, dept := range firstDepts {
err := d.AddDepts(&model.Group{
GroupName: dept.Name, GroupName: dept.Name,
Remark: dept.Remark, Remark: dept.Remark,
Creator: "system",
GroupType: "cn",
SourceDeptId: dept.Id, SourceDeptId: dept.Id,
Source: "openldap",
SourceDeptParentId: dept.ParentId, SourceDeptParentId: dept.ParentId,
ParentId: 0,
GroupDN: dept.DN, GroupDN: dept.DN,
}) })
if err != nil {
return nil, tools.NewOperationError(fmt.Errorf("SyncOpenLdapDepts添加根部门失败%s", err.Error()))
} }
// 2.将远程数据转换成树
deptTree := GroupListToTree("0", groups)
// 3.根据树进行创建
err = d.addDepts(deptTree.Children)
return nil, err
} }
for _, dept := range otherDepts { // 添加部门
// 判断部门名称是否存在 func (d OpenLdapLogic) addDepts(depts []*model.Group) error {
parentGroup := new(model.Group) for _, dept := range depts {
err := isql.Group.Find(tools.H{"source_dept_id": dept.ParentId}, parentGroup) err := d.AddDepts(dept)
if err != nil { if err != nil {
return nil, tools.NewMySqlError(fmt.Errorf("查询父级部门失败:%s", err.Error())) return tools.NewOperationError(fmt.Errorf("DsyncOpenLdapDepts添加部门失败: %s", err.Error()))
} }
err = d.AddDepts(&model.Group{ if len(dept.Children) != 0 {
GroupName: dept.Name, err = d.addDepts(dept.Children)
Remark: dept.Remark,
Creator: "system",
GroupType: "cn",
SourceDeptId: dept.Id,
Source: "openldap",
SourceDeptParentId: dept.ParentId,
GroupDN: dept.DN,
ParentId: parentGroup.ID,
})
if err != nil { if err != nil {
return nil, tools.NewOperationError(fmt.Errorf("SyncOpenLdapDepts添加其他部门失败%s", err.Error())) return tools.NewOperationError(fmt.Errorf("DsyncOpenLdapDepts添加部门失败: %s", err.Error()))
} }
} }
return nil, nil }
return nil
} }
// AddGroup 添加部门数据 // AddGroup 添加部门数据
func (d OpenLdapLogic) AddDepts(group *model.Group) error { func (d OpenLdapLogic) AddDepts(group *model.Group) error {
// 在数据库中创建组 // 判断部门名称是否存在
parentGroup := new(model.Group)
err := isql.Group.Find(tools.H{"source_dept_id": group.SourceDeptParentId}, parentGroup)
if err != nil {
return tools.NewMySqlError(fmt.Errorf("查询父级部门失败:%s", err.Error()))
}
if !isql.Group.Exist(tools.H{"source_dept_id": group.SourceDeptId}) { if !isql.Group.Exist(tools.H{"source_dept_id": group.SourceDeptId}) {
// 此时的 group 已经附带了Build后动态关联好的字段接下来将一些确定性的其他字段值添加上就可以创建这个分组了
group.Creator = "system"
group.GroupType = "cn"
group.ParentId = parentGroup.ID
group.Source = "openldap"
err := isql.Group.Add(group) err := isql.Group.Add(group)
if err != nil { if err != nil {
return err return err
} }
} }
return nil return nil
} }
//根据现有数据库同步到的部门信息,开启用户同步 //根据现有数据库同步到的部门信息,开启用户同步

View File

@ -28,34 +28,31 @@ func (d *WeComLogic) SyncWeComDepts(c *gin.Context, req interface{}) (data inter
if err != nil { if err != nil {
return nil, tools.NewOperationError(fmt.Errorf("转换企业微信部门数据失败:%s", err.Error())) return nil, tools.NewOperationError(fmt.Errorf("转换企业微信部门数据失败:%s", err.Error()))
} }
// 2.将部门这个数组进行拆分一组是父ID为1的一组是父ID不为1的
var firstDepts []*model.Group // 父ID为1的部门 // 2.将远程数据转换成树
var otherDepts []*model.Group // 父ID不为1的部门 deptTree := GroupListToTree(fmt.Sprintf("%s_1", config.Conf.WeCom.Flag), depts)
for _, dept := range depts {
if dept.SourceDeptId == fmt.Sprintf("%s_1", config.Conf.WeCom.Flag) { // 跳过ID为1的根部门由系统配置的根部门进行占位 // 3.根据树进行创建
continue err = d.addDepts(deptTree.Children)
}
if dept.SourceDeptParentId == fmt.Sprintf("%s_1", config.Conf.WeCom.Flag) { return nil, err
firstDepts = append(firstDepts, dept)
} else {
otherDepts = append(otherDepts, dept)
}
}
// 3.先写父ID为1的再写父ID不为1的
for _, dept := range firstDepts {
err := d.AddDepts(dept)
if err != nil {
return nil, tools.NewOperationError(fmt.Errorf("SyncWeComDepts添加根部门失败%s", err.Error()))
}
} }
for _, dept := range otherDepts { // 添加部门
func (d WeComLogic) addDepts(depts []*model.Group) error {
for _, dept := range depts {
err := d.AddDepts(dept) err := d.AddDepts(dept)
if err != nil { if err != nil {
return nil, tools.NewOperationError(fmt.Errorf("SyncWeComDepts添加其他部门失败%s", err.Error())) return tools.NewOperationError(fmt.Errorf("DsyncWeComDepts添加部门失败: %s", err.Error()))
}
if len(dept.Children) != 0 {
err = d.addDepts(dept.Children)
if err != nil {
return tools.NewOperationError(fmt.Errorf("DsyncWeComDepts添加部门失败: %s", err.Error()))
} }
} }
return nil, nil }
return nil
} }
// AddGroup 添加部门数据 // AddGroup 添加部门数据

View File

@ -61,7 +61,7 @@ func GetAllDepts() (ret []*Dept, err error) {
ele.Id = strings.Split(strings.Split(v.DN, ",")[0], "=")[1] ele.Id = strings.Split(strings.Split(v.DN, ",")[0], "=")[1]
ele.Remark = v.GetAttributeValue("description") ele.Remark = v.GetAttributeValue("description")
if len(strings.Split(v.DN, ","))-len(strings.Split(config.Conf.Ldap.BaseDN, ",")) == 1 { if len(strings.Split(v.DN, ","))-len(strings.Split(config.Conf.Ldap.BaseDN, ",")) == 1 {
ele.ParentId = "openldap_0" ele.ParentId = "0"
} else { } else {
ele.ParentId = strings.Split(strings.Split(v.DN, ",")[1], "=")[1] ele.ParentId = strings.Split(strings.Split(v.DN, ",")[1], "=")[1]
} }

View File

@ -702,35 +702,47 @@ func InitData() {
groups := []model.Group{ groups := []model.Group{
{ {
Model: gorm.Model{ID: 1}, Model: gorm.Model{ID: 1},
GroupName: "root",
Remark: "Base",
Creator: "system",
GroupType: "ou",
ParentId: 0,
SourceDeptId: "0",
Source: "openldap",
SourceDeptParentId: "0",
GroupDN: config.Conf.Ldap.BaseDN,
},
{
Model: gorm.Model{ID: 2},
GroupName: config.Conf.DingTalk.Flag + "root", GroupName: config.Conf.DingTalk.Flag + "root",
Remark: "钉钉根部门", Remark: "钉钉根部门",
Creator: "system", Creator: "system",
GroupType: "ou", GroupType: "ou",
ParentId: 0, ParentId: 1,
SourceDeptId: fmt.Sprintf("%s_%d", config.Conf.DingTalk.Flag, 1), SourceDeptId: fmt.Sprintf("%s_%d", config.Conf.DingTalk.Flag, 1),
Source: config.Conf.DingTalk.Flag, Source: config.Conf.DingTalk.Flag,
SourceDeptParentId: fmt.Sprintf("%s_%d", config.Conf.DingTalk.Flag, 0), SourceDeptParentId: fmt.Sprintf("%s_%d", config.Conf.DingTalk.Flag, 0),
GroupDN: fmt.Sprintf("ou=%s,%s", config.Conf.DingTalk.Flag+"root", config.Conf.Ldap.BaseDN), GroupDN: fmt.Sprintf("ou=%s,%s", config.Conf.DingTalk.Flag+"root", config.Conf.Ldap.BaseDN),
}, },
{ {
Model: gorm.Model{ID: 2}, Model: gorm.Model{ID: 3},
GroupName: "wecomroot", GroupName: "wecomroot",
Remark: "企业微信根部门", Remark: "企业微信根部门",
Creator: "system", Creator: "system",
GroupType: "ou", GroupType: "ou",
ParentId: 0, ParentId: 1,
SourceDeptId: fmt.Sprintf("%s_%d", config.Conf.WeCom.Flag, 1), SourceDeptId: fmt.Sprintf("%s_%d", config.Conf.WeCom.Flag, 1),
Source: config.Conf.WeCom.Flag, Source: config.Conf.WeCom.Flag,
SourceDeptParentId: fmt.Sprintf("%s_%d", config.Conf.WeCom.Flag, 0), SourceDeptParentId: fmt.Sprintf("%s_%d", config.Conf.WeCom.Flag, 0),
GroupDN: fmt.Sprintf("ou=%s,%s", config.Conf.WeCom.Flag+"root", config.Conf.Ldap.BaseDN), GroupDN: fmt.Sprintf("ou=%s,%s", config.Conf.WeCom.Flag+"root", config.Conf.Ldap.BaseDN),
}, },
{ {
Model: gorm.Model{ID: 3}, Model: gorm.Model{ID: 4},
GroupName: config.Conf.FeiShu.Flag + "root", GroupName: config.Conf.FeiShu.Flag + "root",
Remark: "飞书根部门", Remark: "飞书根部门",
Creator: "system", Creator: "system",
GroupType: "ou", GroupType: "ou",
ParentId: 0, ParentId: 1,
SourceDeptId: fmt.Sprintf("%s_%d", config.Conf.FeiShu.Flag, 0), SourceDeptId: fmt.Sprintf("%s_%d", config.Conf.FeiShu.Flag, 0),
Source: config.Conf.FeiShu.Flag, Source: config.Conf.FeiShu.Flag,
SourceDeptParentId: fmt.Sprintf("%s_%d", config.Conf.FeiShu.Flag, 0), SourceDeptParentId: fmt.Sprintf("%s_%d", config.Conf.FeiShu.Flag, 0),