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

This commit is contained in:
ckyoung123421 2023-04-10 21:23:24 +08:00 committed by GitHub
parent 6074b38639
commit b7c22666f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 169 additions and 38 deletions

View File

@ -132,5 +132,9 @@ feishu:
app-id: "xxxxxxx" # 飞书的app-id app-id: "xxxxxxx" # 飞书的app-id
app-secret: "xxxxxxxxxxx" # 飞书的app-secret app-secret: "xxxxxxxxxxx" # 飞书的app-secret
enable-sync: false # 是否开启定时同步飞书的任务 enable-sync: false # 是否开启定时同步飞书的任务
dept-sync-time: "0 30 2 * * *" # 部门同步任务的时间点 * * * * * * 秒 分 时 日 月 周, 请把时间设置在凌晨 1 ~ 5 点 dept-sync-time: "0 20 0 * * *" # 部门同步任务的时间点 * * * * * * 秒 分 时 日 月 周, 请把时间设置在凌晨 1 ~ 5 点
user-sync-time: "0 30 3 * * *" # 用户同步任务的时间点 * * * * * * 秒 分 时 日 月 周, 请把时间设置在凌晨 1 ~ 5 点,注意请把用户同步的任务滞后于部门同步时间,比如部门为2点,则用户为3点 user-sync-time: "0 40 0 * * *" # 用户同步任务的时间点 * * * * * * 秒 分 时 日 月 周, 请把时间设置在凌晨 1 ~ 5 点,注意请把用户同步的任务滞后于部门同步时间,比如部门为2点,则用户为3点
dept-list: #部门列表,不设置则使用公司根部门,如果不希望添加子部门,在开头加上^
# - "^od-xxx"
# - "od-xxx"
enable-bot-inform: false

View File

@ -186,4 +186,5 @@ type FeiShuConfig struct {
EnableSync bool `mapstructure:"enable-sync" json:"enableSync"` EnableSync bool `mapstructure:"enable-sync" json:"enableSync"`
DeptSyncTime string `mapstructure:"dept-sync-time" json:"deptSyncTime"` DeptSyncTime string `mapstructure:"dept-sync-time" json:"deptSyncTime"`
UserSyncTime string `mapstructure:"user-sync-time" json:"userSyncTime"` UserSyncTime string `mapstructure:"user-sync-time" json:"userSyncTime"`
DeptList []string `mapstructure:"dept-list" json:"deptList"`
} }

View File

@ -16,18 +16,24 @@ func GetAllDepts() (ret []map[string]interface{}, err error) {
var ( var (
fetchChild bool = true fetchChild bool = true
pageSize int64 = 50 pageSize int64 = 50
pageToken string = ""
// DeptID lark.DepartmentIDType = "department_id"
) )
if len(config.Conf.FeiShu.DeptList) == 0 {
req := lark.GetDepartmentListReq{ req := lark.GetDepartmentListReq{
// DepartmentIDType: &DeptID,
PageToken: &pageToken,
FetchChild: &fetchChild, FetchChild: &fetchChild,
PageSize: &pageSize, PageSize: &pageSize,
DepartmentID: "0"} DepartmentID: "0",
}
for { for {
res, _, err := InitFeiShuClient().Contact.GetDepartmentList(context.TODO(), &req) res, _, err := InitFeiShuClient().Contact.GetDepartmentList(context.TODO(), &req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
for _, dept := range res.Items { for _, dept := range res.Items {
ele := make(map[string]interface{}) ele := make(map[string]interface{})
ele["name"] = dept.Name ele["name"] = dept.Name
@ -42,7 +48,91 @@ func GetAllDepts() (ret []map[string]interface{}, err error) {
if !res.HasMore { if !res.HasMore {
break break
} }
req.PageToken = &res.PageToken pageToken = res.PageToken
}
} 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
}
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
}
}
}
} }
return return
} }
@ -52,6 +142,8 @@ func GetAllDepts() (ret []map[string]interface{}, err error) {
func GetAllUsers() (ret []map[string]interface{}, err error) { func GetAllUsers() (ret []map[string]interface{}, err error) {
var ( var (
pageSize int64 = 50 pageSize int64 = 50
pageToken string = ""
// deptidtype lark.DepartmentIDType = "department_id"
) )
depts, err := GetAllDepts() depts, err := GetAllDepts()
if err != nil { if err != nil {
@ -59,7 +151,7 @@ func GetAllUsers() (ret []map[string]interface{}, err error) {
} }
deptids := make([]string, 0) deptids := make([]string, 0)
deptids = append(deptids, "0") // 0 代表根部门 // deptids = append(deptids, "0")
for _, dept := range depts { for _, dept := range depts {
deptids = append(deptids, dept["open_department_id"].(string)) deptids = append(deptids, dept["open_department_id"].(string))
} }
@ -67,7 +159,8 @@ func GetAllUsers() (ret []map[string]interface{}, err error) {
for _, deptid := range deptids { for _, deptid := range deptids {
req := lark.GetUserListReq{ req := lark.GetUserListReq{
PageSize: &pageSize, PageSize: &pageSize,
PageToken: new(string), PageToken: &pageToken,
// DepartmentIDType: &deptidtype,
DepartmentID: deptid, DepartmentID: deptid,
} }
for { for {
@ -112,7 +205,7 @@ func GetAllUsers() (ret []map[string]interface{}, err error) {
if !res.HasMore { if !res.HasMore {
break break
} }
req.PageToken = &res.PageToken pageToken = res.PageToken
} }
} }
return return

View File

@ -74,6 +74,39 @@ func (x UserService) Update(oldusername string, user *model.User) error {
return nil 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 删除资源 // Delete 删除资源
func (x UserService) Delete(udn string) error { func (x UserService) Delete(udn string) error {
del := ldap.NewDelRequest(udn, nil) del := ldap.NewDelRequest(udn, nil)