Skip to content

feat: feishu用户导入支持指定部门列表open_department_id #186

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,5 +132,9 @@ feishu:
app-id: "xxxxxxx" # 飞书的app-id
app-secret: "xxxxxxxxxxx" # 飞书的app-secret
enable-sync: false # 是否开启定时同步飞书的任务
dept-sync-time: "0 30 2 * * *" # 部门同步任务的时间点 * * * * * * 秒 分 时 日 月 周, 请把时间设置在凌晨 1 ~ 5 点
user-sync-time: "0 30 3 * * *" # 用户同步任务的时间点 * * * * * * 秒 分 时 日 月 周, 请把时间设置在凌晨 1 ~ 5 点,注意请把用户同步的任务滞后于部门同步时间,比如部门为2点,则用户为3点
dept-sync-time: "0 20 0 * * *" # 部门同步任务的时间点 * * * * * * 秒 分 时 日 月 周, 请把时间设置在凌晨 1 ~ 5 点
user-sync-time: "0 40 0 * * *" # 用户同步任务的时间点 * * * * * * 秒 分 时 日 月 周, 请把时间设置在凌晨 1 ~ 5 点,注意请把用户同步的任务滞后于部门同步时间,比如部门为2点,则用户为3点
dept-list: #部门列表,不设置则使用公司根部门,如果不希望添加子部门,在开头加上^
# - "^od-xxx"
# - "od-xxx"
enable-bot-inform: false
13 changes: 7 additions & 6 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,11 @@ type WeComConfig struct {
}

type FeiShuConfig struct {
Flag string `mapstructure:"flag" json:"flag"`
AppID string `mapstructure:"app-id" json:"appId"`
AppSecret string `mapstructure:"app-secret" json:"appSecret"`
EnableSync bool `mapstructure:"enable-sync" json:"enableSync"`
DeptSyncTime string `mapstructure:"dept-sync-time" json:"deptSyncTime"`
UserSyncTime string `mapstructure:"user-sync-time" json:"userSyncTime"`
Flag string `mapstructure:"flag" json:"flag"`
AppID string `mapstructure:"app-id" json:"appId"`
AppSecret string `mapstructure:"app-secret" json:"appSecret"`
EnableSync bool `mapstructure:"enable-sync" json:"enableSync"`
DeptSyncTime string `mapstructure:"dept-sync-time" json:"deptSyncTime"`
UserSyncTime string `mapstructure:"user-sync-time" json:"userSyncTime"`
DeptList []string `mapstructure:"dept-list" json:"deptList"`
}
4 changes: 2 additions & 2 deletions logic/feishu_logic.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
type FeiShuLogic struct {
}

//通过飞书获取部门信息
// 通过飞书获取部门信息
func (d *FeiShuLogic) SyncFeiShuDepts(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) {
// 1.获取所有部门
deptSource, err := feishu.GetAllDepts()
Expand Down Expand Up @@ -80,7 +80,7 @@ func (d FeiShuLogic) AddDepts(group *model.Group) error {
return nil
}

//根据现有数据库同步到的部门信息,开启用户同步
// 根据现有数据库同步到的部门信息,开启用户同步
func (d FeiShuLogic) SyncFeiShuUsers(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) {
// 1.获取飞书用户列表
staffSource, err := feishu.GetAllUsers()
Expand Down
149 changes: 121 additions & 28 deletions public/client/feishu/feishu.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,35 +14,125 @@ import (
// GetAllDepts 获取所有部门
func GetAllDepts() (ret []map[string]interface{}, err error) {
var (
fetchChild bool = true
pageSize int64 = 50
fetchChild bool = true
pageSize int64 = 50
pageToken string = ""
// DeptID lark.DepartmentIDType = "department_id"
)

req := lark.GetDepartmentListReq{
FetchChild: &fetchChild,
PageSize: &pageSize,
DepartmentID: "0"}
if len(config.Conf.FeiShu.DeptList) == 0 {
req := lark.GetDepartmentListReq{
// DepartmentIDType: &DeptID,
PageToken: &pageToken,
FetchChild: &fetchChild,
PageSize: &pageSize,
DepartmentID: "0",
}
for {
res, _, err := InitFeiShuClient().Contact.GetDepartmentList(context.TODO(), &req)
if err != nil {
return nil, err
}

for {
res, _, err := InitFeiShuClient().Contact.GetDepartmentList(context.TODO(), &req)
if err != nil {
return nil, err
for _, dept := range res.Items {
ele := make(map[string]interface{})
ele["name"] = dept.Name
ele["custom_name_pinyin"] = tools.ConvertToPinYin(dept.Name)
ele["parent_department_id"] = dept.ParentDepartmentID
ele["department_id"] = dept.DepartmentID
ele["open_department_id"] = dept.OpenDepartmentID
ele["leader_user_id"] = dept.LeaderUserID
ele["unit_ids"] = dept.UnitIDs
ret = append(ret, ele)
}
if !res.HasMore {
break
}
pageToken = res.PageToken
}
for _, dept := range res.Items {
ele := make(map[string]interface{})
ele["name"] = dept.Name
ele["custom_name_pinyin"] = tools.ConvertToPinYin(dept.Name)
ele["parent_department_id"] = dept.ParentDepartmentID
ele["department_id"] = dept.DepartmentID
ele["open_department_id"] = dept.OpenDepartmentID
ele["leader_user_id"] = dept.LeaderUserID
ele["unit_ids"] = dept.UnitIDs
ret = append(ret, ele)
} else {
//使用dept-list来一个一个添加部门,开头为^的不添加子部门
isInDeptList := func(id string) bool {
for _, v := range config.Conf.FeiShu.DeptList {
if strings.HasPrefix(v, "^") {
v = v[1:]
}
if id == v {
return true
}
}
return false
}
if !res.HasMore {
break
dep_append_norepeat := func(ret []map[string]interface{}, dept map[string]interface{}) []map[string]interface{} {
for _, v := range ret {
if v["open_department_id"] == dept["open_department_id"] {
return ret
}
}
return append(ret, dept)
}
for _, dep_s := range config.Conf.FeiShu.DeptList {
dept_id := dep_s
no_add_children := false
if strings.HasPrefix(dep_s, "^") {
no_add_children = true
dept_id = dep_s[1:]
}
req := lark.GetDepartmentReq{
DepartmentID: dept_id,
}
res, _, err := InitFeiShuClient().Contact.GetDepartment(context.TODO(), &req)
if err != nil {
return nil, err
}
ele := make(map[string]interface{})

ele["name"] = res.Department.Name
ele["custom_name_pinyin"] = tools.ConvertToPinYin(res.Department.Name)
if isInDeptList(res.Department.ParentDepartmentID) {
ele["parent_department_id"] = res.Department.ParentDepartmentID
} else {
ele["parent_department_id"] = "0"
}
ele["department_id"] = res.Department.DepartmentID
ele["open_department_id"] = res.Department.OpenDepartmentID
ele["leader_user_id"] = res.Department.LeaderUserID
ele["unit_ids"] = res.Department.UnitIDs
ret = dep_append_norepeat(ret, ele)

if !no_add_children {
pageToken = ""
req := lark.GetDepartmentListReq{
// DepartmentIDType: &DeptID,
PageToken: &pageToken,
FetchChild: &fetchChild,
PageSize: &pageSize,
DepartmentID: dept_id,
}
for {
res, _, err := InitFeiShuClient().Contact.GetDepartmentList(context.TODO(), &req)
if err != nil {
return nil, err
}

for _, dept := range res.Items {
ele := make(map[string]interface{})
ele["name"] = dept.Name
ele["custom_name_pinyin"] = tools.ConvertToPinYin(dept.Name)
ele["parent_department_id"] = dept.ParentDepartmentID
ele["department_id"] = dept.DepartmentID
ele["open_department_id"] = dept.OpenDepartmentID
ele["leader_user_id"] = dept.LeaderUserID
ele["unit_ids"] = dept.UnitIDs
ret = dep_append_norepeat(ret, ele)
}
if !res.HasMore {
break
}
pageToken = res.PageToken
}
}
}
req.PageToken = &res.PageToken
}
return
}
Expand All @@ -51,23 +141,26 @@ func GetAllDepts() (ret []map[string]interface{}, err error) {
// GetAllUsers 获取所有员工信息
func GetAllUsers() (ret []map[string]interface{}, err error) {
var (
pageSize int64 = 50
pageSize int64 = 50
pageToken string = ""
// deptidtype lark.DepartmentIDType = "department_id"
)
depts, err := GetAllDepts()
if err != nil {
return nil, err
}

deptids := make([]string, 0)
deptids = append(deptids, "0") // 0 代表根部门
// deptids = append(deptids, "0")
for _, dept := range depts {
deptids = append(deptids, dept["open_department_id"].(string))
}

for _, deptid := range deptids {
req := lark.GetUserListReq{
PageSize: &pageSize,
PageToken: new(string),
PageSize: &pageSize,
PageToken: &pageToken,
// DepartmentIDType: &deptidtype,
DepartmentID: deptid,
}
for {
Expand Down Expand Up @@ -112,7 +205,7 @@ func GetAllUsers() (ret []map[string]interface{}, err error) {
if !res.HasMore {
break
}
req.PageToken = &res.PageToken
pageToken = res.PageToken
}
}
return
Expand Down
33 changes: 33 additions & 0 deletions service/ildap/user_ildap.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,39 @@ func (x UserService) Update(oldusername string, user *model.User) error {
return nil
}

func (x UserService) Exist(filter map[string]interface{}) (bool, error) {
filter_str := ""
for key, value := range filter {
filter_str += fmt.Sprintf("(%s=%s)", key, value)
}
search_filter := fmt.Sprintf("(&(|(objectClass=inetOrgPerson)(objectClass=simpleSecurityObject))%s)", filter_str)
// Construct query request
searchRequest := ldap.NewSearchRequest(
config.Conf.Ldap.BaseDN, // This is basedn, we will start searching from this node.
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, // Here several parameters are respectively scope, derefAliases, sizeLimit, timeLimit, typesOnly
search_filter, // This is Filter for LDAP query
[]string{"DN"}, // Here are the attributes returned by the query, provided as an array. If empty, all attributes are returned
nil,
)

// 获取 LDAP 连接
conn, err := common.GetLDAPConn()
defer common.PutLADPConn(conn)
if err != nil {
return false, err
}
var sr *ldap.SearchResult
// Search through ldap built-in search
sr, err = conn.Search(searchRequest)
if err != nil {
return false, err
}
if len(sr.Entries) > 0 {
return true, nil
}
return false, nil
}

// Delete 删除资源
func (x UserService) Delete(udn string) error {
del := ldap.NewDelRequest(udn, nil)
Expand Down