From 4fdc035e2ccbb5a2091c8b376aecdf6987d52cce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E4=B8=AB=E8=AE=B2=E6=A2=B5?= Date: Sun, 15 Oct 2023 21:04:26 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E9=80=9A=E8=BF=87?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=E6=8E=A7=E5=88=B6=E6=98=AF?= =?UTF-8?q?=E5=90=A6=E5=90=8C=E6=AD=A5=E6=9B=B4=E6=96=B0IM=E4=B8=AD?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E4=BF=A1=E6=81=AF=E7=9A=84=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=20(#259)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: eryajf --- .github/pull-request-template.md | 6 ++-- CONTRIBUTING.md | 11 ++++++ README.md | 38 ++++++++++----------- config.yml | 21 ++++++------ config/config.go | 49 ++++++++++++++------------- logic/dingtalk_logic.go | 57 +++++++++++++++++++++++++++++++ logic/feishu_logic.go | 58 ++++++++++++++++++++++++++++++++ logic/wecom_logic.go | 58 ++++++++++++++++++++++++++++++++ 8 files changed, 243 insertions(+), 55 deletions(-) create mode 100644 CONTRIBUTING.md diff --git a/.github/pull-request-template.md b/.github/pull-request-template.md index 6ed8154..6f52f56 100644 --- a/.github/pull-request-template.md +++ b/.github/pull-request-template.md @@ -2,12 +2,12 @@ **在提出此拉取请求时,我确认了以下几点(请复选框):** -- [ ] 我已阅读并理解[贡献者指南]()。 +- [ ] 我已阅读并理解[贡献者指南](https://github.com/eryajf/go-ldap-admin/blob/main/CONTRIBUTING.md)。 - [ ] 我已检查没有与此请求重复的拉取请求。 - [ ] 我已经考虑过,并确认这份呈件对其他人很有价值。 - [ ] 我接受此提交可能不会被使用,并根据维护人员的意愿关闭拉取请求。 -**填写PR内容:** +**填写 PR 内容:** - -- \ No newline at end of file +- diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..e31f79a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,11 @@ +# 贡献者指南 + +欢迎反馈、bug 报告和拉取请求,可点击[issue](https://github.com/eryajf/go-ldap-admin/issues) 提交. + +如果你是第一次进行 GitHub 协作,可参阅: [协同开发流程](https://howtosos.eryajf.net/HowToStartOpenSource/01-basic-content/03-collaborative-development-process.html) + +1. 项目使用`golangci-lint`进行检测,提交 pr 之前请在本地执行 `make lint` 并通过。 + +2. 如非必要,尽可能谨慎新增配置文件,以免造成升级时产生意料之外的问题。 + +3. 注意一些功能调整,如何涉及到前端页面调整,尽可能两个 pr 有所关联,否则不好合并。 diff --git a/README.md b/README.md index a11b141..22db9ff 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,9 @@
-

- Project logo + Project logo

@@ -42,31 +41,31 @@ `go-ldap-admin`旨在为`OpenLDAP`服务端提供一个简单易用,清晰美观的现代化管理后台。 -> 在完成针对`OpenLDAP`的管理能力之下,支持对`钉钉`,`企业微信`,`飞书`的集成,用户可以选择手动或者自动同步组织架构以及员工信息到平台中,让`go-ldap-admin`项目成为打通企业IM与企业内网应用之间的桥梁。 +> 在完成针对`OpenLDAP`的管理能力之下,支持对`钉钉`,`企业微信`,`飞书`的集成,用户可以选择手动或者自动同步组织架构以及员工信息到平台中,让`go-ldap-admin`项目成为打通企业 IM 与企业内网应用之间的桥梁。 ## 🏊 在线体验 提供在线体验地址如下: -| 分类 | 地址 | 用户名 | 密码 | -| :-----------: | :----------------------------------------------------------: | :-----------------------: | ------ | -| go-ldap-admin | [http://demo-go-ldap-admin.eryajf.net](http://demo-go-ldap-admin.eryajf.net) | admin | 123456 | +| 分类 | 地址 | 用户名 | 密码 | +| :-----------: | :--------------------------------------------------------------------------------------: | :-----------------------: | ------ | +| go-ldap-admin | [http://demo-go-ldap-admin.eryajf.net](http://demo-go-ldap-admin.eryajf.net) | admin | 123456 | | phpLdapAdmin | [http://demo-go-ldap-admin.eryajf.net:8091/](http://demo-go-ldap-admin.eryajf.net:8091/) | cn=admin,dc=eryajf,dc=net | 123456 | 在线环境可能不稳,如果遇到访问异常,或者数据错乱,请联系我进行修复。 **页面功能概览:** -| ![登录页](https://cdn.staticaly.com/gh/eryajf/tu/main/img/image_20220724_165411.png) | ![首页](https://cdn.staticaly.com/gh/eryajf/tu/main/img/image_20220724_165545.png) | -| :----------------------------------------------------------: | ------------------------------------------------------------ | -| ![用户管理](https://cdn.staticaly.com/gh/eryajf/tu/main/img/image_20220724_165623.png) | ![分组管理](https://cdn.staticaly.com/gh/eryajf/tu/main/img/image_20220724_165701.png) | -| ![字段关系管理](https://cdn.staticaly.com/gh/eryajf/tu/main/img/image_20220724_165853.png) | ![菜单管理](https://cdn.staticaly.com/gh/eryajf/tu/main/img/image_20220724_165954.png) | -| ![接口管理](https://cdn.staticaly.com/gh/eryajf/tu/main/img/image_20220724_170015.png) | ![操作日志](https://cdn.staticaly.com/gh/eryajf/tu/main/img/image_20220724_170035.png) | +| ![登录页](https://cdn.jsdelivr.net/gh/eryajf/tu/img/image_20220724_165411.png) | ![首页](https://cdn.jsdelivr.net/gh/eryajf/tu/img/image_20220724_165545.png) | +| :----------------------------------------------------------------------------------: | -------------------------------------------------------------------------------- | +| ![用户管理](https://cdn.jsdelivr.net/gh/eryajf/tu/img/image_20220724_165623.png) | ![分组管理](https://cdn.jsdelivr.net/gh/eryajf/tu/img/image_20220724_165701.png) | +| ![字段关系管理](https://cdn.jsdelivr.net/gh/eryajf/tu/img/image_20220724_165853.png) | ![菜单管理](https://cdn.jsdelivr.net/gh/eryajf/tu/img/image_20220724_165954.png) | +| ![接口管理](https://cdn.jsdelivr.net/gh/eryajf/tu/img/image_20220724_170015.png) | ![操作日志](https://cdn.jsdelivr.net/gh/eryajf/tu/img/image_20220724_170035.png) | ## 👨‍💻 项目地址 -| 分类 | GitHub | Gitee | -| :--: | :--------------------------------------------------: | :-------------------------------------------------: | +| 分类 | GitHub | Gitee | +| :--: | :--------------------------------------------: | :-------------------------------------------------: | | 后端 | https://github.com/eryajf/go-ldap-admin.git | https://gitee.com/eryajf-world/go-ldap-admin.git | | 前端 | https://github.com/eryajf/go-ldap-admin-ui.git | https://gitee.com/eryajf-world/go-ldap-admin-ui.git | @@ -83,7 +82,7 @@ ## 🥰 感谢 -感谢如下优秀的项目,没有这些项目,不可能会有go-ldap-admin: +感谢如下优秀的项目,没有这些项目,不可能会有 go-ldap-admin: - 后端技术栈 - [Gin-v1.6.3](https://github.com/gin-gonic/gin) @@ -92,6 +91,7 @@ - [Go-ldap-v3.4.2](https://github.com/go-ldap/ldap) - [Casbin-v2.22.0](https://github.com/casbin/casbin) - 前端技术栈 + - [axios](https://github.com/axios/axios) - [element-ui](https://github.com/ElemeFE/element) @@ -100,8 +100,8 @@ ## 🤗 另外 -- 如果觉得项目不错,麻烦动动小手点个⭐️star⭐️! -- 如果你还有其他想法或者需求,欢迎在issue中交流! +- 如果觉得项目不错,麻烦动动小手点个 ⭐️star⭐️! +- 如果你还有其他想法或者需求,欢迎在 issue 中交流! ## 🤑 捐赠 @@ -109,11 +109,11 @@ ## 📝 使用登记 -如果你所在公司使用了该项目,烦请在这里留下脚印,感谢支持🥳 [点我](https://github.com/eryajf/go-ldap-admin/issues/18) +如果你所在公司使用了该项目,烦请在这里留下脚印,感谢支持 🥳 [点我](https://github.com/eryajf/go-ldap-admin/issues/18) ## 💎 优秀软件推荐 -- [🦄 ConsulManager:高效易用的Consul Web运维平台](https://github.com/starsliao/ConsulManager) +- [🦄 ConsulManager:高效易用的 Consul Web 运维平台](https://github.com/starsliao/ConsulManager) ## 🤝 贡献者 @@ -185,4 +185,4 @@ - \ No newline at end of file + diff --git a/config.yml b/config.yml index 017c9a9..cea701b 100644 --- a/config.yml +++ b/config.yml @@ -41,9 +41,9 @@ mysql: # 数据库名 database: go_ldap_admin # 主机地址 - host: localhost + host: kaiyuan # 端口 - port: 3306 + port: 3307 # 连接字符串参数 query: parseTime=True&loc=Local&timeout=10000ms # 是否打印日志 @@ -117,10 +117,10 @@ dingtalk: enable-sync: false # 是否开启定时同步钉钉的任务 dept-sync-time: "0 30 2 * * *" # 部门同步任务的时间点 * * * * * * 秒 分 时 日 月 周, 请把时间设置在凌晨 1 ~ 5 点 user-sync-time: "0 30 3 * * *" # 用户同步任务的时间点 * * * * * * 秒 分 时 日 月 周, 请把时间设置在凌晨 1 ~ 5 点,注意请把用户同步的任务滞后于部门同步时间,比如部门为2点,则用户为3点 - dept-list: #部门列表,不设置则使用公司根部门,在开头加^表示不同步此部门,只需配置需要同步的部门ID - #- "1" #根组织ID - - "48456726" #需要同步的部门ID - #- "^61213417" #不同步的ID,不配置即只同步上一ID + dept-list: # 配置要同步的部门列表,配置留空则同步所有部门,在开头加^表示不同步此部门 + #- "48456726" # 需要同步的部门ID + #- "^61213417" # 不需要同步的部门ID + is-update-syncd: false # 当钉钉用户的邮箱,手机号,部门等信息更新之后,是否同步更新,默认为false,如果你不了解这个字段的含义,则不建议开启 wecom: # 配置获取详细文档参考:http://ldapdoc.eryajf.net/pages/cf1698/ flag: "wecom" # 作为微信在平台的标识 @@ -130,6 +130,7 @@ wecom: enable-sync: false # 是否开启定时同步企业微信的任务 dept-sync-time: "0 30 2 * * *" # 部门同步任务的时间点 * * * * * * 秒 分 时 日 月 周, 请把时间设置在凌晨 1 ~ 5 点 user-sync-time: "0 30 3 * * *" # 用户同步任务的时间点 * * * * * * 秒 分 时 日 月 周, 请把时间设置在凌晨 1 ~ 5 点,注意请把用户同步的任务滞后于部门同步时间,比如部门为2点,则用户为3点 + is-update-syncd: false # 当企微用户的邮箱,手机号,部门等信息更新之后,是否同步更新,默认为false,如果你不了解这个字段的含义,则不建议开启 feishu: # 配置获取详细文档参考:http://ldapdoc.eryajf.net/pages/83c90b/ flag: "feishu" # 作为飞书在平台的标识 @@ -138,7 +139,7 @@ feishu: enable-sync: false # 是否开启定时同步飞书的任务 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 + dept-list: # 配置要同步的部门列表,配置留空则同步所有部门,在开头加^表示不同步此部门 + #- "48456726" # 需要同步的部门ID + #- "^61213417" # 不需要同步的部门ID + is-update-syncd: false # 当飞书用户的邮箱,手机号,部门等信息更新之后,是否同步更新,默认为false,如果你不了解这个字段的含义,则不建议开启 \ No newline at end of file diff --git a/config/config.go b/config/config.go index e918858..03df010 100644 --- a/config/config.go +++ b/config/config.go @@ -159,33 +159,36 @@ type EmailConfig struct { } type DingTalkConfig struct { - AppKey string `mapstructure:"app-key" json:"appKey"` - AppSecret string `mapstructure:"app-secret" json:"appSecret"` - AgentId string `mapstructure:"agent-id" json:"agentId"` - RootOuName string `mapstructure:"root-ou-name" json:"rootOuName"` - Flag string `mapstructure:"flag" json:"flag"` - 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"` + AppKey string `mapstructure:"app-key" json:"appKey"` + AppSecret string `mapstructure:"app-secret" json:"appSecret"` + AgentId string `mapstructure:"agent-id" json:"agentId"` + RootOuName string `mapstructure:"root-ou-name" json:"rootOuName"` + Flag string `mapstructure:"flag" json:"flag"` + 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"` + IsUpdateSyncd bool `mapstructure:"is-update-syncd" json:"isUpdateSyncd"` } type WeComConfig struct { - Flag string `mapstructure:"flag" json:"flag"` - CorpID string `mapstructure:"corp-id" json:"corpId"` - AgentID int `mapstructure:"agent-id" json:"agentId"` - CorpSecret string `mapstructure:"corp-secret" json:"corpSecret"` - 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"` + CorpID string `mapstructure:"corp-id" json:"corpId"` + AgentID int `mapstructure:"agent-id" json:"agentId"` + CorpSecret string `mapstructure:"corp-secret" json:"corpSecret"` + EnableSync bool `mapstructure:"enable-sync" json:"enableSync"` + DeptSyncTime string `mapstructure:"dept-sync-time" json:"deptSyncTime"` + UserSyncTime string `mapstructure:"user-sync-time" json:"userSyncTime"` + IsUpdateSyncd bool `mapstructure:"is-update-syncd" json:"isUpdateSyncd"` } 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"` - DeptList []string `mapstructure:"dept-list" json:"deptList"` + 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"` + IsUpdateSyncd bool `mapstructure:"is-update-syncd" json:"isUpdateSyncd"` } diff --git a/logic/dingtalk_logic.go b/logic/dingtalk_logic.go index 435eb45..083279a 100644 --- a/logic/dingtalk_logic.go +++ b/logic/dingtalk_logic.go @@ -158,6 +158,63 @@ func (d DingTalkLogic) AddUsers(user *model.User) error { if err != nil { return tools.NewOperationError(fmt.Errorf("添加用户: %s, 失败: %s", user.Username, err.Error())) } + } else { + if config.Conf.DingTalk.IsUpdateSyncd { + // 先获取用户信息 + oldData := new(model.User) + err = isql.User.Find(tools.H{"user_dn": user.UserDN}, oldData) + if err != nil { + return err + } + // 获取用户将要添加的分组 + groups, err := isql.Group.GetGroupByIds(tools.StringToSlice(user.DepartmentId, ",")) + if err != nil { + return tools.NewMySqlError(fmt.Errorf("根据部门ID获取部门信息失败" + err.Error())) + } + var deptTmp string + for _, group := range groups { + deptTmp = deptTmp + group.GroupName + "," + } + user.Model = oldData.Model + user.Roles = oldData.Roles + user.Creator = oldData.Creator + user.Source = oldData.Source + user.Password = oldData.Password + user.UserDN = oldData.UserDN + user.Departments = strings.TrimRight(deptTmp, ",") + + // 用户信息的预置处理 + if user.Nickname == "" { + user.Nickname = oldData.Nickname + } + if user.GivenName == "" { + user.GivenName = user.Nickname + } + if user.Introduction == "" { + user.Introduction = user.Nickname + } + if user.Mail == "" { + user.Mail = oldData.Mail + } + if user.JobNumber == "" { + user.JobNumber = oldData.JobNumber + } + if user.Departments == "" { + user.Departments = oldData.Departments + } + if user.Position == "" { + user.Position = oldData.Position + } + if user.PostalAddress == "" { + user.PostalAddress = oldData.PostalAddress + } + if user.Mobile == "" { + user.Mobile = oldData.Mobile + } + if err = CommonUpdateUser(oldData, user, tools.StringToSlice(user.DepartmentId, ",")); err != nil { + return err + } + } } return nil } diff --git a/logic/feishu_logic.go b/logic/feishu_logic.go index 9ee2a81..0dbf79a 100644 --- a/logic/feishu_logic.go +++ b/logic/feishu_logic.go @@ -160,6 +160,64 @@ func (d FeiShuLogic) AddUsers(user *model.User) error { if err != nil { return tools.NewOperationError(fmt.Errorf("添加用户: %s, 失败: %s", user.Username, err.Error())) } + } else { + // 此处逻辑未经实际验证,如在使用中有问题,请反馈 + if config.Conf.FeiShu.IsUpdateSyncd { + // 先获取用户信息 + oldData := new(model.User) + err = isql.User.Find(tools.H{"user_dn": user.UserDN}, oldData) + if err != nil { + return err + } + // 获取用户将要添加的分组 + groups, err := isql.Group.GetGroupByIds(tools.StringToSlice(user.DepartmentId, ",")) + if err != nil { + return tools.NewMySqlError(fmt.Errorf("根据部门ID获取部门信息失败" + err.Error())) + } + var deptTmp string + for _, group := range groups { + deptTmp = deptTmp + group.GroupName + "," + } + user.Model = oldData.Model + user.Roles = oldData.Roles + user.Creator = oldData.Creator + user.Source = oldData.Source + user.Password = oldData.Password + user.UserDN = oldData.UserDN + user.Departments = strings.TrimRight(deptTmp, ",") + + // 用户信息的预置处理 + if user.Nickname == "" { + user.Nickname = oldData.Nickname + } + if user.GivenName == "" { + user.GivenName = user.Nickname + } + if user.Introduction == "" { + user.Introduction = user.Nickname + } + if user.Mail == "" { + user.Mail = oldData.Mail + } + if user.JobNumber == "" { + user.JobNumber = oldData.JobNumber + } + if user.Departments == "" { + user.Departments = oldData.Departments + } + if user.Position == "" { + user.Position = oldData.Position + } + if user.PostalAddress == "" { + user.PostalAddress = oldData.PostalAddress + } + if user.Mobile == "" { + user.Mobile = oldData.Mobile + } + if err = CommonUpdateUser(oldData, user, tools.StringToSlice(user.DepartmentId, ",")); err != nil { + return err + } + } } return nil } diff --git a/logic/wecom_logic.go b/logic/wecom_logic.go index ec0d3cb..51640d5 100644 --- a/logic/wecom_logic.go +++ b/logic/wecom_logic.go @@ -175,6 +175,64 @@ func (d WeComLogic) AddUsers(user *model.User) error { if err != nil { return tools.NewOperationError(fmt.Errorf("添加用户: %s, 失败: %s", user.Username, err.Error())) } + } else { + // 此处逻辑未经实际验证,如在使用中有问题,请反馈 + if config.Conf.WeCom.IsUpdateSyncd { + // 先获取用户信息 + oldData := new(model.User) + err = isql.User.Find(tools.H{"user_dn": user.UserDN}, oldData) + if err != nil { + return err + } + // 获取用户将要添加的分组 + groups, err := isql.Group.GetGroupByIds(tools.StringToSlice(user.DepartmentId, ",")) + if err != nil { + return tools.NewMySqlError(fmt.Errorf("根据部门ID获取部门信息失败" + err.Error())) + } + var deptTmp string + for _, group := range groups { + deptTmp = deptTmp + group.GroupName + "," + } + user.Model = oldData.Model + user.Roles = oldData.Roles + user.Creator = oldData.Creator + user.Source = oldData.Source + user.Password = oldData.Password + user.UserDN = oldData.UserDN + user.Departments = strings.TrimRight(deptTmp, ",") + + // 用户信息的预置处理 + if user.Nickname == "" { + user.Nickname = oldData.Nickname + } + if user.GivenName == "" { + user.GivenName = user.Nickname + } + if user.Introduction == "" { + user.Introduction = user.Nickname + } + if user.Mail == "" { + user.Mail = oldData.Mail + } + if user.JobNumber == "" { + user.JobNumber = oldData.JobNumber + } + if user.Departments == "" { + user.Departments = oldData.Departments + } + if user.Position == "" { + user.Position = oldData.Position + } + if user.PostalAddress == "" { + user.PostalAddress = oldData.PostalAddress + } + if user.Mobile == "" { + user.Mobile = oldData.Mobile + } + if err = CommonUpdateUser(oldData, user, tools.StringToSlice(user.DepartmentId, ",")); err != nil { + return err + } + } } return nil }