feat: feishu用户导入支持指定部门列表open_department_id (#186)
This commit is contained in:
parent
6074b38639
commit
b7c22666f4
|
@ -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
|
||||||
|
|
|
@ -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"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ import (
|
||||||
type FeiShuLogic struct {
|
type FeiShuLogic struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
//通过飞书获取部门信息
|
// 通过飞书获取部门信息
|
||||||
func (d *FeiShuLogic) SyncFeiShuDepts(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) {
|
func (d *FeiShuLogic) SyncFeiShuDepts(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) {
|
||||||
// 1.获取所有部门
|
// 1.获取所有部门
|
||||||
deptSource, err := feishu.GetAllDepts()
|
deptSource, err := feishu.GetAllDepts()
|
||||||
|
@ -80,7 +80,7 @@ func (d FeiShuLogic) AddDepts(group *model.Group) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//根据现有数据库同步到的部门信息,开启用户同步
|
// 根据现有数据库同步到的部门信息,开启用户同步
|
||||||
func (d FeiShuLogic) SyncFeiShuUsers(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) {
|
func (d FeiShuLogic) SyncFeiShuUsers(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) {
|
||||||
// 1.获取飞书用户列表
|
// 1.获取飞书用户列表
|
||||||
staffSource, err := feishu.GetAllUsers()
|
staffSource, err := feishu.GetAllUsers()
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue