From d152b9f5f823e6659900c819743fd96105c064b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E4=B8=AB=E8=AE=B2=E6=A2=B5?= Date: Tue, 14 Jun 2022 11:17:38 +0800 Subject: [PATCH 1/2] Adjust the project architecture and optimize the code logic. (#17) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: user和group分别添加dn字段,便于辅助前端界面理解 * feat: request与response包内容分配到model目录下,减缩一级目录数量 * 调整钉钉同步架构,改善一些逻辑 * 添加golangci-lint静态扫描 * 调整README内容 Co-authored-by: eryajf --- .github/ISSUE_TEMPLATE/config.yml | 8 + .github/ISSUE_TEMPLATE/issue-template-bug.md | 18 + .../ISSUE_TEMPLATE/issue-template-feature.md | 12 + .github/ISSUE_TEMPLATE/question-report.md | 22 + .github/release-drafter.yml | 39 +- .github/workflows/docker-image.yml | 24 +- .github/workflows/golangci-lint.yml | 17 + .github/workflows/issue.yml | 21 + .gitignore | 3 + Makefile | 5 +- README.md | 240 ++----- config.yml | 24 +- config/config.go | 62 +- controller/api_controller.go | 2 +- controller/base_controller.go | 2 +- controller/group_controller.go | 4 +- controller/menu_controller.go | 2 +- controller/operation_log_controller.go | 2 +- controller/role_controller.go | 2 +- controller/user_controller.go | 2 +- go.mod | 40 +- go.sum | 627 +++++++++++++++--- logic/api_logic.go | 4 +- logic/base_logic.go | 4 +- logic/common_login.go | 167 +++++ logic/dingtakl_logic.go | 574 ---------------- logic/dingtalk_logic.go | 268 ++++++++ logic/group_logic.go | 125 ++-- logic/menu_logic.go | 2 +- logic/operation_log_logic.go | 4 +- logic/role_logic.go | 4 +- logic/user_logic.go | 189 +----- main.go | 24 +- middleware/AuthMiddleware.go | 4 +- middleware/CORSMiddleware.go | 3 +- middleware/OperationLogMiddleware.go | 8 +- middleware/RateLimitMiddleware.go | 2 +- model/group.go | 1 + {svc => model}/request/api_req.go | 0 {svc => model}/request/base_req.go | 0 {svc => model}/request/group_req.go | 0 {svc => model}/request/menu_req.go | 0 {svc => model}/request/operation_log_req.go | 0 {svc => model}/request/role_req.go | 0 {svc => model}/request/user_req.go | 0 {svc => model}/response/api_rsp.go | 0 {svc => model}/response/base_rsp.go | 0 {svc => model}/response/common_rsp.go | 0 {svc => model}/response/group_rsp.go | 0 {svc => model}/response/menu_rsp.go | 0 {svc => model}/response/operation_log_rsp.go | 0 {svc => model}/response/role_rsp.go | 0 {svc => model}/response/user_rsp.go | 0 model/user.go | 39 +- public/client/dingtalk/client.go | 53 ++ public/client/dingtalk/dingtalk.go | 107 +++ public/common/database.go | 2 +- public/common/init_mysql_data.go | 122 ++-- public/common/ldap.go | 2 +- public/tools/slice_cmp.go | 16 +- service/ildap/group_ildap.go | 42 +- service/ildap/user_ildap.go | 31 +- service/isql/api_isql.go | 4 +- service/isql/group_isql.go | 34 +- service/isql/operation_log_isql.go | 2 +- service/isql/role_isql.go | 2 +- service/isql/user_isql.go | 23 +- 67 files changed, 1696 insertions(+), 1344 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/issue-template-bug.md create mode 100644 .github/ISSUE_TEMPLATE/issue-template-feature.md create mode 100644 .github/ISSUE_TEMPLATE/question-report.md create mode 100644 .github/workflows/golangci-lint.yml create mode 100644 .github/workflows/issue.yml create mode 100644 logic/common_login.go delete mode 100644 logic/dingtakl_logic.go create mode 100644 logic/dingtalk_logic.go rename {svc => model}/request/api_req.go (100%) rename {svc => model}/request/base_req.go (100%) rename {svc => model}/request/group_req.go (100%) rename {svc => model}/request/menu_req.go (100%) rename {svc => model}/request/operation_log_req.go (100%) rename {svc => model}/request/role_req.go (100%) rename {svc => model}/request/user_req.go (100%) rename {svc => model}/response/api_rsp.go (100%) rename {svc => model}/response/base_rsp.go (100%) rename {svc => model}/response/common_rsp.go (100%) rename {svc => model}/response/group_rsp.go (100%) rename {svc => model}/response/menu_rsp.go (100%) rename {svc => model}/response/operation_log_rsp.go (100%) rename {svc => model}/response/role_rsp.go (100%) rename {svc => model}/response/user_rsp.go (100%) create mode 100644 public/client/dingtalk/client.go create mode 100644 public/client/dingtalk/dingtalk.go diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..90cb616 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: 📜 官方文档 | GO Ldap Admin Doc + url: http://ldapdoc.eryajf.net + about: 关于项目的功能用法以及设计考量,都会在官网进行呈现,提交问题之前,请先阅读官方文档,如果还不能满足,则再提问题。 | Regarding the functional usage and design considerations of the project, they will be presented on the official website. Before submitting the question, please read the official document first. If it is not satisfied, you will ask the question. + - name: 👀 Github论坛 | GitHub Discussions + url: https://github.com/eryajf/go-ldap-admin/discussions + about: 如果您的问题不是功能或者错误,请转到讨论面板并在提交之前检索您的问题是否已经存在。 | If your question is not a feature or a bug, please go to the discussion panel and retrieve if your question already exists before submitting. diff --git a/.github/ISSUE_TEMPLATE/issue-template-bug.md b/.github/ISSUE_TEMPLATE/issue-template-bug.md new file mode 100644 index 0000000..517ca57 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/issue-template-bug.md @@ -0,0 +1,18 @@ +--- +name: 🐛 错误报告 | Bug Report +about: 请详细描述您使用过程中遇到的问题。| Please describe in detail the problems you encountered in the process of using. +title: "🐛 一些问题。。。 | [Bug] Some problem..." +labels: ["bug"] +--- + + + +#### 您使用的版本? | Your usage version? + +#### 您使用的场景? | Your usage scenarios? + +#### 您做了什么操作? | What did you do? + +#### 您遇到了什么问题? | What are your problems? + +#### 您期望的结果是怎样的? | What is your expected outcome? diff --git a/.github/ISSUE_TEMPLATE/issue-template-feature.md b/.github/ISSUE_TEMPLATE/issue-template-feature.md new file mode 100644 index 0000000..e0003bf --- /dev/null +++ b/.github/ISSUE_TEMPLATE/issue-template-feature.md @@ -0,0 +1,12 @@ +--- +name: 🚀 功能请求 | Feature Request +about: 请详细描述您期望的功能。 | Please describe in detail the features you expect. +title: "🚀 一些功能。。。 | [Feature]Some feature..." +labels: ["enhancement"] +--- + + + +#### 您使用的场景? | 1. Your usage scenarios? + +#### 您期望的结果是怎样的? | 2. What is your expected outcome? diff --git a/.github/ISSUE_TEMPLATE/question-report.md b/.github/ISSUE_TEMPLATE/question-report.md new file mode 100644 index 0000000..0f4a756 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question-report.md @@ -0,0 +1,22 @@ +--- +name: 🙋 问题交流 | Question Report +about: 在文档或讨论中没有回答的使用问题 | Usage question that isn't answered in docs or discussion +title: "🙋 问题交流。。。 | [Question] Some question..." +labels: ["question"] +--- + +## Question Report + +- 搜索打开和关闭的 [GitHub 问题](https://github.com/eryajf/go-ldap-admin/issues) + +请在提交问题之前回答这些问题,谢谢。 | Please answer these questions before submitting them. Thank you. + +### 你使用了哪个版本? | Which version did you use? + +### 预期行为 | Expected behavior + +### 实际行为 | Actual behavior + +### 原因分析(如果可以) | Cause analysis (if possible) + +### 问题重现步骤 | Steps to reproduce the problem \ No newline at end of file diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml index 0a5d792..4f551de 100644 --- a/.github/release-drafter.yml +++ b/.github/release-drafter.yml @@ -1,4 +1,41 @@ +# Configuration for Release Drafter: https://github.com/toolmantim/release-drafter +name-template: 'v$NEXT_PATCH_VERSION 🌈' +tag-template: 'v$NEXT_PATCH_VERSION' +version-template: $MAJOR.$MINOR.$PATCH +# Emoji reference: https://gitmoji.carloscuesta.me/ +categories: + - title: '🚀 Features' + labels: + - 'feature' + - 'enhancement' + - 'kind/feature' + - title: '🐛 Bug Fixes' + labels: + - 'fix' + - 'bugfix' + - 'bug' + - 'regression' + - 'kind/bug' + - title: 📝 Documentation updates + labels: + - documentation + - 'kind/doc' + - title: 👻 Maintenance + labels: + - chore + - dependencies + - 'kind/chore' + - 'kind/dep' + - title: 🚦 Tests + labels: + - test + - tests +exclude-labels: + - reverted + - no-changelog + - skip-changelog + - invalid +change-template: '* $TITLE (#$NUMBER) @$AUTHOR' template: | ## What’s Changed - $CHANGES \ No newline at end of file diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index e38e38b..6bdf0a6 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -23,30 +23,30 @@ jobs: buildx: runs-on: ubuntu-latest steps: - - - name: Checkout + - name: Checkout uses: actions/checkout@v2 + - name: Get current date id: date run: echo "::set-output name=today::$(date +'%Y-%m-%d_%H-%M')" - - - name: Set up QEMU + + - name: Set up QEMU uses: docker/setup-qemu-action@v1 - - - name: Set up Docker Buildx + + - name: Set up Docker Buildx id: buildx uses: docker/setup-buildx-action@v1 - - - name: Available platforms + + - name: Available platforms run: echo ${{ steps.buildx.outputs.platforms }} - - - name: Login to DockerHub + + - name: Login to DockerHub uses: docker/login-action@v1 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Build and push + + - name: Build and push uses: docker/build-push-action@v2 with: context: . diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml new file mode 100644 index 0000000..720ae74 --- /dev/null +++ b/.github/workflows/golangci-lint.yml @@ -0,0 +1,17 @@ +name: golangci-lint + +on: [push, pull_request] + +jobs: + golangci: + name: lint + runs-on: ubuntu-latest + steps: + - uses: actions/setup-go@v3 + with: + go-version: 1.17 + - uses: actions/checkout@v3 + - name: golangci-lint + uses: golangci/golangci-lint-action@v3 + with: + version: v1.46.2 \ No newline at end of file diff --git a/.github/workflows/issue.yml b/.github/workflows/issue.yml new file mode 100644 index 0000000..1d44506 --- /dev/null +++ b/.github/workflows/issue.yml @@ -0,0 +1,21 @@ +name: Issue Reply + +on: + issues: + types: [labeled] + +jobs: + reply-helper: + runs-on: ubuntu-latest + steps: + - name: help wanted + if: github.event.label.name == 'help wanted' || github.event.label.name == 'enhancement' || github.event.label.name == 'bug' || github.event.label.name == 'question' + uses: actions-cool/issues-helper@v3 + with: + actions: 'create-comment' + token: ${{ secrets.ACCESS_TOKEN }} + issue-number: ${{ github.event.issue.number }} + body: | + 您好 @${{ github.event.issue.user.login }}👋,我已收到您的反馈,我将安排时间考虑您提交的信息并进行回复。-- 这条信息是由自动回复的机器人发出的。 + + Hello @${{ github.event.issue.user.login }}. I have received your feedback, and I will arrange time to consider the information you submitted and reply. -- This message is sent by an automatic reply robot. diff --git a/.gitignore b/.gitignore index 1402d76..0c5e605 100644 --- a/.gitignore +++ b/.gitignore @@ -6,10 +6,13 @@ *.dylib .idea .vscode +.token + build.sh logs go-web-mini go-ldap-admin + # Test binary, built with `go test -c` *.test diff --git a/Makefile b/Makefile index d6c6479..553a3bd 100644 --- a/Makefile +++ b/Makefile @@ -10,4 +10,7 @@ build-linux: CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -o go-ldap-admin main.go build-linux-arm: - CGO_ENABLED=0 GOARCH=arm64 GOOS=linux go build -o go-ldap-admin main.go \ No newline at end of file + CGO_ENABLED=0 GOARCH=arm64 GOOS=linux go build -o go-ldap-admin main.go + +lint: + env GOGC=25 golangci-lint run --fix -j 8 -v ./... \ No newline at end of file diff --git a/README.md b/README.md index c964a3d..d0906dc 100644 --- a/README.md +++ b/README.md @@ -1,38 +1,57 @@ -

Go-Ldap-Admin

+

+ + Project logo +

+

Go Ldap Admin

+
-基于Go+Vue实现的openLDAP后台管理项目。 -

-Go version -Gin version -Gorm version -License -

+ + +[![Go Version](https://img.shields.io/github/go-mod/go-version/eryajf-world/go-ldap-admin)](https://github.com/eryajf/go-ldap-admin) +[![Gin Version](https://img.shields.io/badge/Gin-1.6.3-brightgreen)](https://github.com/eryajf/go-ldap-admin) +[![Gorm Version](https://img.shields.io/badge/Gorm-1.20.12-brightgreen)](https://github.com/eryajf/go-ldap-admin) +[![Status](https://img.shields.io/badge/status-active-success.svg)](https://github.com/eryajf/go-ldap-admin) +[![GitHub Issues](https://img.shields.io/github/issues/eryajf/go-ldap-admin.svg)](https://github.com/eryajf/go-ldap-admin/issues) +[![GitHub Pull Requests](https://img.shields.io/github/issues-pr/eryajf/go-ldap-admin)](https://github.com/eryajf/go-ldap-admin/pulls) +[![GitHub Pull Requests](https://img.shields.io/github/stars/eryajf/go-ldap-admin)](https://github.com/eryajf/go-ldap-admin/stargazers) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](/LICENSE) +
+ +--- + +

🌉 基于Go+Vue实现的openLDAP后台管理项目。 +
+

+ **目录** - [在线体验](#%E5%9C%A8%E7%BA%BF%E4%BD%93%E9%AA%8C) - [项目地址](#%E9%A1%B9%E7%9B%AE%E5%9C%B0%E5%9D%80) -- [核心功能](#%E6%A0%B8%E5%BF%83%E5%8A%9F%E8%83%BD) -- [快速开始](#%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B) -- [本地开发](#%E6%9C%AC%E5%9C%B0%E5%BC%80%E5%8F%91) -- [生产部署](#%E7%94%9F%E4%BA%A7%E9%83%A8%E7%BD%B2) +- [文档快链](#%E6%96%87%E6%A1%A3%E5%BF%AB%E9%93%BE) - [感谢](#%E6%84%9F%E8%B0%A2) - [另外](#%E5%8F%A6%E5%A4%96) -- [贡献者](#%E8%B4%A1%E7%8C%AE%E8%80%85) - [加群](#%E5%8A%A0%E7%BE%A4) -- [为什么有这个项目](#%E4%B8%BA%E4%BB%80%E4%B9%88%E6%9C%89%E8%BF%99%E4%B8%AA%E9%A1%B9%E7%9B%AE) +- [捐赠](#%E6%8D%90%E8%B5%A0) +- [贡献者](#%E8%B4%A1%E7%8C%AE%E8%80%85) +- [使用登记](#%E4%BD%BF%E7%94%A8%E7%99%BB%E8%AE%B0) ## 在线体验 -> admin / 123456 +提供在线体验地址如下: -演示地址:[http://demo-go-ldap-admin.eryajf.net](http://demo-go-ldap-admin.eryajf.net) +| 分类 | 地址 | 用户名 | 密码 | +| :-----------: | :----------------------------------------------------------: | :-----------------------: | ------ | +| 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 | + +在线环境可能不稳,如果遇到访问异常,或者数据错乱,请联系我进行修复。 ## 项目地址 @@ -41,151 +60,16 @@ | 后端 | 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 | -## 核心功能 +## 文档快链 -- 基于 GIN WEB API 框架,基于Casbin的 RBAC 访问控制模型,JWT 认证,Validator 参数校验 -- 基于 GORM 的数据库存储 -- 基于 go-ldap 库的主逻辑交互 -- 用户管理 - - 用户的增删改查 -- 分组管理 - - 分组的增删改查 - - 分组内成员的管理 +项目相关介绍,使用,最佳实践等相关内容,都会在官方文档呈现,如有疑问,请先阅读官方文档,以下列举以下常用快链。 -## 快速开始 - -你可以通过docker-compose在本地快速拉起进行体验。 - -快速拉起的容器包括:MySQL-5.7,openLDAP-1.4.0,phpldapadmin-0.9.0,go-ldap-admin-server,go-ldap-admin-ui。 - -服务端口映射如下: - -| Service | Port | -| :-----------: | :-------------------: | -| MySQL | `3307:3306` | -| openLDAP | `389:389` | -| phpldapadmin | `8091:80` | -| go-ldap-admin | `8090:80`,`8888:8888` | - -拉起之前确认是否有与本地端口冲突的情况。 - -``` -$ git clone https://github.com/eryajf/go-ldap-admin.git - -$ cd docs/docker-compose - -$ docker-compose up -d -``` - -当看到容器都正常运行之后,可以在本地进行访问:http://localhost:8090,用户名/密码:admin/123456 -如果想要访问PhpLdapAdmin,则可访问:http://localhost:8091,用户名/密码:cn=admin,dc=eryajf,dc=net/123456 - -`登录页:` - -![](http://t.eryajf.net/imgs/2022/05/17dbe07a137c9b4c.png) - -`首页:` - -![](http://t.eryajf.net/imgs/2022/05/b18c5fbf5ba0e6af.png) - -`用户管理:` - -![](http://t.eryajf.net/imgs/2022/05/f3ae695b703c00c8.png) - -`分组管理:` - -![](http://t.eryajf.net/imgs/2022/05/e49632b76a4327ec.png) - -`分组内成员管理:` - -![](http://t.eryajf.net/imgs/2022/05/f1732540ce0632de.png) - -## 本地开发 - -### 前言准备 - -前提是已准备好MySQL与openLDAP,本地开发建议直接通过docker拉起即可,可参考文档:[https://wiki.eryajf.net/pages/3a0d5f](https://wiki.eryajf.net/pages/3a0d5f)。 - -### 拉取代码 - -``` -# 后端代码 -$ git clone https://github.com/eryajf/go-ldap-admin.git - -# 前端代码 -$ git clone https://github.com/eryajf/go-ldap-admin-ui.git -``` - -后端目录结构: - -``` -├─config # viper读取配置 -├─controller # controller层,响应路由请求的方法 -├─docs # 一些物料信息 -├─logic # 主要的处理逻辑 -├─middleware # 中间件 -├─model # 结构体模型 -├─public # 一些公共的,工具类的放在这里 -├─routes # 所有路由 -├─service # 整合与底层存储交互的方法 -├─svc # 定义入参出参的结构体 -└─test # 跑测试用的 -``` - -### 更改配置 - -``` -# 修改后端配置 -$ cd go-ldap-admin -# 文件路径 config.yml -$ vim config.yml - -# 根据自己本地的情况,调整数据库以及openLDAP等配置信息。 -``` - -### 启动服务 - -``` -# 启动后端 -$ cd go-ldap-admin -$ go mod tidy -$ go run main.go -$ make run - -# 启动前端 -$ cd go-ldap-admin-ui -$ git config --global url."https://".insteadOf git:// -$ npm install --registry=http://registry.npmmirror.com -$ yarn dev -``` - -本地访问:http://localhost:8090,用户名/密码:admin/密码是配置文件中openLDAP中admin的密码。 - -## 生产部署 - -生产环境单独部署,通过Nginx代理服务,配置如下: - -```nginx -server { - listen 80; - server_name demo-go-ldap-admin.eryajf.net; - - root /data/www/web/dist; - - location / { - try_files $uri $uri/ /index.html; - add_header Cache-Control 'no-store'; - } - - location /api/ { - proxy_set_header Host $http_host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_pass http://127.0.0.1:8888; - } -} -``` +- [官网地址](http://ldapdoc.eryajf.net) +- [项目背景](http://ldapdoc.eryajf.net/pages/101948/) +- [快速开始](http://ldapdoc.eryajf.net/pages/706e78/) +- [功能概览](http://ldapdoc.eryajf.net/pages/7a40de/) +- [本地开发](http://ldapdoc.eryajf.net/pages/cb7497/) +- [生产部署](http://ldapdoc.eryajf.net/pages/5769c4/) ## 感谢 @@ -209,9 +93,19 @@ server { - 如果你还有其他想法或者需求,欢迎在issue中交流! - 程序还有很多bug,欢迎各位朋友一起协同共建! + +## 加群 + +如果想要加群交流,可通过搜索 eryajf 添加我的微信,备注 ldap 拉你进群。 + +## 捐赠 + +如果你觉得这个项目对你有帮助,你可以请作者喝杯咖啡 ☕️ [点我](http://ldapdoc.eryajf.net/pages/2b6725/) + ## 贡献者 +
@@ -229,31 +123,9 @@ server {
+ +## 使用登记 -## 加群 - -可通过搜索 eryajf 添加我的微信,备注 ldap 拉你进群。 - -## 为什么有这个项目 - -我曾经经历的公司强依赖openLDAP来作为企业内部员工管理的平台,并通过openLDAP进行各平台的认证打通工作。 - -但成也萧何败也萧何,给运维省力的同时,ldap又是维护不够友好的。 - -在[godap](https://github.com/bradleypeabody/godap)项目中,作者这样描述对ldap的感受: - -> The short version of the story goes like this: I hate LDAP. I used to love it. But I loved it for all the wrong reasons. LDAP is supported as an authentication solution by many different pieces of software. Aside from its de jure standard status, its wide deployment cements it as a de facto standard as well. -> -> However, just because it is a standard doesn't mean it is a great idea. -> -> I'll admit that given its age LDAP has had a good run. I'm sure its authors carefully considered how to construct the protocol and chose ASN.1 and its encoding with all of wellest of well meaning intentions. -> -> The trouble is that with today's Internet, LDAP is just a pain in the ass. You can't call it from your browser. It's not human readable or easy to debug. Tooling is often arcane and confusing. It's way more complicated than what is needed for most simple authentication-only uses. (Yes, I know there are many other uses than authentication - but it's often too complicated for those too.) -> -> Likely owing to the complexity of the protocol, there seems to be virtually no easy to use library to implement the server side of the LDAP protocol that isn't tied in with some complete directory server system; and certainly not in a language as easy to "make it work" as Go. - -他说他对ldap又爱又恨,因为ldap出现的最早,许多的三方软件都兼容支持它,它成了这方面的一个标准。但问题在于,它对于维护者而言,又是复杂麻烦的。就算是有Phpldapadmin这样的平台能够在浏览器维护,但看到那样上古的界面,以及复杂的交互逻辑,仍旧能够把不少人劝退。 - -鉴于此,我开发了这个现代化的openLDAP管理后台。 \ No newline at end of file +如果你所在公司使用了该项目,烦请在这里留下脚印,感谢支持🥳 [点我](https://github.com/eryajf/go-ldap-admin/issues/18) \ No newline at end of file diff --git a/config.yml b/config.yml index 70a02d3..d1b05d6 100644 --- a/config.yml +++ b/config.yml @@ -85,24 +85,34 @@ email: ldap: # ldap服务器地址 ldap-url: ldap://localhost:389 + # ldap服务器基础DN ldap-base-dn: "dc=eryajf,dc=net" + # ldap管理员DN ldap-admin-dn: "cn=admin,dc=eryajf,dc=net" + # ldap管理员密码 ldap-admin-pass: "123456" + # ldap用户OU ldap-user-dn: "ou=people,dc=eryajf,dc=net" - ldap-group-dn: "ou=group,dc=eryajf,dc=net" + # ldap用户初始默认密码 + ldap-user-init-password: "123456" + # 是否允许更改分组DN ldap-group-name-modify: false + # 是否允许更改用户DN ldap-user-name-modify: false dingtalk: + #为了方便数据库存储,防止第三方id重复,故而增加一个前缀(用于用户表和分组表中第三方id存储,加上此处配置的source字段进行区分来源,判断唯一)。长度不超过10. + #因为分组表不可能成为性能瓶颈,故而不再拆分到新的关系表去维护第三方信息,用户表设计同理 + ding-talk-flag: "dingtalk" # 使用之前是需要在钉钉开发者后台(https://open-dev.dingtalk.com/#/index) 创建一个小程序或应用.获取appkey和appsecret,agentId # 目前agent-id尚未使用,先存着后续功能可能会用到 # 由于获取钉钉第一个部门的id默认为1,故而这边需要配置一下钉钉的第一个部门的名称,不去钉钉获取 - ding-talk-app-key: "xxxxxx" - ding-talk-app-secret: "xxxxxxxxxxxxxxxxxxxxxxxxxxx-vhIGL" + ding-talk-app-key: "xxxxxxxxxxxxxxx" + ding-talk-app-secret: "xxxxxxxxxxxxxxxxxxxxxxxxxxxx" ding-talk-agent-id: "12121212" ding-talk-root-ou-name: "钉钉首个部门的名称" - #为了方便数据库存储,防止第三方id重复,故而增加一个前缀(用于用户表和分组表中第三方id存储,加上此处配置的source字段进行区分来源,判断唯一)。长度不超过10. - #因为分组表不可能成为性能瓶颈,故而不再拆分到新的关系表去维护第三方信息,用户表设计同理 - ding-talk-id-source: "dingtalk" - ding-talk-user-init-password: "dingding@123" # 是否开启定时同步钉钉的任务 ding-talk-enable-sync: false +wecom: + flag: "wecom" +feishu: + flag: "feishu" \ No newline at end of file diff --git a/config/config.go b/config/config.go index b2a02f9..f94d256 100644 --- a/config/config.go +++ b/config/config.go @@ -16,15 +16,17 @@ import ( var Conf = new(config) type config struct { - System *SystemConfig `mapstructure:"system" json:"system"` - Logs *LogsConfig `mapstructure:"logs" json:"logs"` - Mysql *MysqlConfig `mapstructure:"mysql" json:"mysql"` - Casbin *CasbinConfig `mapstructure:"casbin" json:"casbin"` - Jwt *JwtConfig `mapstructure:"jwt" json:"jwt"` - RateLimit *RateLimitConfig `mapstructure:"rate-limit" json:"rateLimit"` - Ldap *LdapConfig `mapstructure:"ldap" json:"ldap"` - Email *EmailConfig `mapstructure:"email" json:"email"` - DingTalk *DingTalkConfig `mapstructure:"dingtalk" json:"dingTalk"` + System *SystemConfig `mapstructure:"system" json:"system"` + Logs *LogsConfig `mapstructure:"logs" json:"logs"` + Mysql *MysqlConfig `mapstructure:"mysql" json:"mysql"` + Casbin *CasbinConfig `mapstructure:"casbin" json:"casbin"` + Jwt *JwtConfig `mapstructure:"jwt" json:"jwt"` + RateLimit *RateLimitConfig `mapstructure:"rate-limit" json:"rateLimit"` + Ldap *LdapConfig `mapstructure:"ldap" json:"ldap"` + Email *EmailConfig `mapstructure:"email" json:"email"` + DingTalk *DingTalkConfig `mapstructure:"dingtalk" json:"dingTalk"` + WeComConfig *WeComConfig `mapstructure:"wecom" json:"weCom"` + FeiShuConfig *FeiShuConfig `mapstructure:"feishu" json:"feiShu"` } // 设置读取配置信息 @@ -75,7 +77,10 @@ func RSAReadKeyFromFile(filename string) []byte { defer f.Close() fileInfo, _ := f.Stat() b = make([]byte, fileInfo.Size()) - f.Read(b) + _, err = f.Read(b) + if err != nil { + return b + } return b } @@ -129,14 +134,14 @@ type RateLimitConfig struct { } type LdapConfig struct { - LdapUrl string `mapstructure:"ldap-url" json:"ldapUrl"` - LdapBaseDN string `mapstructure:"ldap-base-dn" json:"ldapBaseDN"` - LdapAdminDN string `mapstructure:"ldap-admin-dn" json:"ldapAdminDN"` - LdapAdminPass string `mapstructure:"ldap-admin-pass" json:"ldapAdminPass"` - LdapUserDN string `mapstructure:"ldap-user-dn" json:"ldapUserDN"` - LdapGroupDN string `mapstructure:"ldap-group-dn" json:"ldapGroupDN"` - LdapGroupNameModify bool `mapstructure:"ldap-group-name-modify" json:"ldapGroupNameModify"` - LdapUserNameModify bool `mapstructure:"ldap-user-name-modify" json:"ldapUserNameModify"` + LdapUrl string `mapstructure:"ldap-url" json:"ldapUrl"` + LdapBaseDN string `mapstructure:"ldap-base-dn" json:"ldapBaseDN"` + LdapAdminDN string `mapstructure:"ldap-admin-dn" json:"ldapAdminDN"` + LdapAdminPass string `mapstructure:"ldap-admin-pass" json:"ldapAdminPass"` + LdapUserDN string `mapstructure:"ldap-user-dn" json:"ldapUserDN"` + LdapUserInitPassword string `mapstructure:"ldap-user-init-password" json:"ldapUserInitPassword"` + LdapGroupNameModify bool `mapstructure:"ldap-group-name-modify" json:"ldapGroupNameModify"` + LdapUserNameModify bool `mapstructure:"ldap-user-name-modify" json:"ldapUserNameModify"` } type EmailConfig struct { Host string `mapstructure:"host" json:"host"` @@ -147,11 +152,18 @@ type EmailConfig struct { } type DingTalkConfig struct { - DingTalkAppKey string `mapstructure:"ding-talk-app-key" json:"dingTalkAppKey"` - DingTalkAppSecret string `mapstructure:"ding-talk-app-secret" json:"dingTalkAppSecret"` - DingTalkAgentId string `mapstructure:"ding-talk-agent-id" json:"dingTalkAgentId"` - DingTalkRootOuName string `mapstructure:"ding-talk-root-ou-name" json:"dingTalkRootOuName"` - DingTalkIdSource string `mapstructure:"ding-talk-id-source" json:"dingTalkIdSource"` - DingTalkUserInitPassword string `mapstructure:"ding-talk-user-init-password" json:"dingTalkUserInitPassword"` - DingTalkEnableSync bool `mapstructure:"ding-talk-enable-sync" json:"dingTalkEnableSync"` + DingTalkAppKey string `mapstructure:"ding-talk-app-key" json:"dingTalkAppKey"` + DingTalkAppSecret string `mapstructure:"ding-talk-app-secret" json:"dingTalkAppSecret"` + DingTalkAgentId string `mapstructure:"ding-talk-agent-id" json:"dingTalkAgentId"` + DingTalkRootOuName string `mapstructure:"ding-talk-root-ou-name" json:"dingTalkRootOuName"` + DingTalkFlag string `mapstructure:"ding-talk-flag" json:"dingTalkFlag"` + DingTalkEnableSync bool `mapstructure:"ding-talk-enable-sync" json:"dingTalkEnableSync"` +} + +type WeComConfig struct { + Flag string `mapstructure:"flag" json:"flag"` +} + +type FeiShuConfig struct { + Flag string `mapstructure:"flag" json:"flag"` } diff --git a/controller/api_controller.go b/controller/api_controller.go index 294f632..b9bd055 100644 --- a/controller/api_controller.go +++ b/controller/api_controller.go @@ -2,7 +2,7 @@ package controller import ( "github.com/eryajf/go-ldap-admin/logic" - "github.com/eryajf/go-ldap-admin/svc/request" + "github.com/eryajf/go-ldap-admin/model/request" "github.com/gin-gonic/gin" ) diff --git a/controller/base_controller.go b/controller/base_controller.go index 038b4ab..48cd83f 100644 --- a/controller/base_controller.go +++ b/controller/base_controller.go @@ -2,7 +2,7 @@ package controller import ( "github.com/eryajf/go-ldap-admin/logic" - "github.com/eryajf/go-ldap-admin/svc/request" + "github.com/eryajf/go-ldap-admin/model/request" "github.com/gin-gonic/gin" ) diff --git a/controller/group_controller.go b/controller/group_controller.go index 017ed56..3aa8cac 100644 --- a/controller/group_controller.go +++ b/controller/group_controller.go @@ -2,7 +2,7 @@ package controller import ( "github.com/eryajf/go-ldap-admin/logic" - "github.com/eryajf/go-ldap-admin/svc/request" + "github.com/eryajf/go-ldap-admin/model/request" "github.com/gin-gonic/gin" ) @@ -85,6 +85,6 @@ func (m *GroupController) RemoveUser(c *gin.Context) { func (m *GroupController) SyncDingTalkDepts(c *gin.Context) { req := new(request.SyncDingTalkDeptsReq) Run(c, req, func() (interface{}, interface{}) { - return logic.DingTalk.DsyncDingTalkDepts(c, req) + return logic.DingTalk.SyncDingTalkDepts(c, req) }) } diff --git a/controller/menu_controller.go b/controller/menu_controller.go index 356a3c0..9707395 100644 --- a/controller/menu_controller.go +++ b/controller/menu_controller.go @@ -2,7 +2,7 @@ package controller import ( "github.com/eryajf/go-ldap-admin/logic" - "github.com/eryajf/go-ldap-admin/svc/request" + "github.com/eryajf/go-ldap-admin/model/request" "github.com/gin-gonic/gin" ) diff --git a/controller/operation_log_controller.go b/controller/operation_log_controller.go index 5fd0709..8856043 100644 --- a/controller/operation_log_controller.go +++ b/controller/operation_log_controller.go @@ -2,7 +2,7 @@ package controller import ( "github.com/eryajf/go-ldap-admin/logic" - "github.com/eryajf/go-ldap-admin/svc/request" + "github.com/eryajf/go-ldap-admin/model/request" "github.com/gin-gonic/gin" ) diff --git a/controller/role_controller.go b/controller/role_controller.go index ab5ed79..2e693a9 100644 --- a/controller/role_controller.go +++ b/controller/role_controller.go @@ -2,7 +2,7 @@ package controller import ( "github.com/eryajf/go-ldap-admin/logic" - "github.com/eryajf/go-ldap-admin/svc/request" + "github.com/eryajf/go-ldap-admin/model/request" "github.com/gin-gonic/gin" ) diff --git a/controller/user_controller.go b/controller/user_controller.go index 6f5923c..4a29803 100644 --- a/controller/user_controller.go +++ b/controller/user_controller.go @@ -2,7 +2,7 @@ package controller import ( "github.com/eryajf/go-ldap-admin/logic" - "github.com/eryajf/go-ldap-admin/svc/request" + "github.com/eryajf/go-ldap-admin/model/request" "github.com/gin-gonic/gin" ) diff --git a/go.mod b/go.mod index 1a98857..f611412 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/appleboy/gin-jwt/v2 v2.6.4 github.com/casbin/casbin/v2 v2.22.0 github.com/casbin/gorm-adapter/v3 v3.1.0 - github.com/fsnotify/fsnotify v1.4.9 + github.com/fsnotify/fsnotify v1.5.4 github.com/gin-gonic/gin v1.6.3 github.com/go-ldap/ldap/v3 v3.4.2 github.com/go-playground/locales v0.14.0 @@ -15,7 +15,7 @@ require ( github.com/juju/ratelimit v1.0.1 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/robfig/cron/v3 v3.0.0 - github.com/spf13/viper v1.7.1 + github.com/spf13/viper v1.11.0 github.com/thoas/go-funk v0.7.0 github.com/zhaoyunxing92/dingtalk/v2 v2.0.7-0.20220601083444-173c10c3f835 go.uber.org/zap v1.19.1 @@ -26,8 +26,14 @@ require ( ) require ( + github.com/BurntSushi/toml v1.1.0 // indirect + github.com/golang/mock v1.6.0 // indirect + github.com/lib/pq v1.10.4 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.0.0 // indirect + github.com/rogpeppe/go-internal v1.8.1 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) require ( @@ -39,7 +45,7 @@ require ( github.com/go-asn1-ber/asn1-ber v1.5.1 // indirect github.com/go-sql-driver/mysql v1.5.0 // indirect github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect - github.com/golang/protobuf v1.4.3 // indirect + github.com/golang/protobuf v1.5.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect github.com/jackc/pgconn v1.8.0 // indirect @@ -51,29 +57,29 @@ require ( github.com/jackc/pgx/v4 v4.10.1 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.1 // indirect - github.com/json-iterator/go v1.1.10 // indirect + github.com/json-iterator/go v1.1.12 // indirect github.com/leodido/go-urn v1.2.1 // indirect - github.com/magiconair/properties v1.8.4 // indirect - github.com/mattn/go-isatty v0.0.12 // indirect - github.com/mitchellh/mapstructure v1.4.1 // indirect + github.com/magiconair/properties v1.8.6 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mozillazg/go-pinyin v0.19.0 - github.com/pelletier/go-toml v1.8.1 // indirect + github.com/pelletier/go-toml v1.9.5 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/spf13/afero v1.5.1 // indirect - github.com/spf13/cast v1.3.1 // indirect + github.com/spf13/afero v1.8.2 // indirect + github.com/spf13/cast v1.4.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.2.0 // indirect github.com/ugorji/go/codec v1.2.3 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect - golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect - golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 // indirect - golang.org/x/text v0.3.6 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect - google.golang.org/protobuf v1.25.0 // indirect + golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect + golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 // indirect + golang.org/x/text v0.3.7 // indirect + golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect + google.golang.org/protobuf v1.28.0 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect - gopkg.in/ini.v1 v1.62.0 // indirect + gopkg.in/ini.v1 v1.66.4 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gorm.io/driver/postgres v1.0.7 // indirect gorm.io/driver/sqlserver v1.0.6 // indirect diff --git a/go.sum b/go.sum index 25e6858..ce93860 100644 --- a/go.sum +++ b/go.sum @@ -3,37 +3,85 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= +cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= +cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c h1:/IBSNwUN8+eKzUzbJPqhK839ygXJ82sde8x3ogr6R28= github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I= +github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/appleboy/gin-jwt/v2 v2.6.4 h1:4YlMh3AjCFnuIRiL27b7TXns7nLx8tU/TiSgh40RRUI= github.com/appleboy/gin-jwt/v2 v2.6.4/go.mod h1:CZpq1cRw+kqi0+yD2CwVw7VGXrrx4AqBdeZnwxVmoAs= github.com/appleboy/gofight/v2 v2.1.2 h1:VOy3jow4vIK8BRQJoC/I9muxyYlJ2yb9ht2hZoS3rf4= github.com/appleboy/gofight/v2 v2.1.2/go.mod h1:frW+U1QZEdDgixycTj4CygQ48yLTUhplt43+Wczp3rw= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/casbin/casbin/v2 v2.21.0/go.mod h1:wUgota0cQbTXE6Vd+KWpg41726jFRi7upxio0sR+Xd0= github.com/casbin/casbin/v2 v2.22.0 h1:1duZ3Fr383ou/6KqRljYNQBw1WWfnXTwofzJ7UBLITc= github.com/casbin/casbin/v2 v2.22.0/go.mod h1:wUgota0cQbTXE6Vd+KWpg41726jFRi7upxio0sR+Xd0= @@ -41,15 +89,27 @@ github.com/casbin/gorm-adapter/v3 v3.1.0 h1:qYjsP40gIjQwS6/yk7x1IkHA4qWWhpB399Dr github.com/casbin/gorm-adapter/v3 v3.1.0/go.mod h1:kaMBsBHluoYwudSbVnism8LhJeVyuuqIb5nWYS/1IBU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -60,13 +120,21 @@ github.com/denisenkom/go-mssqldb v0.9.0 h1:RSohk2RsiZqLZ0zCjtfn3S4Gp4exhpBWHyQ7D github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= +github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= @@ -75,7 +143,10 @@ github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwv github.com/go-asn1-ber/asn1-ber v1.5.1 h1:pDbRAunXzIUXfx4CB2QJFv5IuPiuoW+sWvr/Us009o8= github.com/go-asn1-ber/asn1-ber v1.5.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-ldap/ldap/v3 v3.4.2 h1:zFZKcXKLqZpFMrMQGHeHWKXbDTdNCmhGY9AK41zPh+8= github.com/go-ldap/ldap/v3 v3.4.2/go.mod h1:iYS1MdmrmceOJ1QOTnRXrIs7i3kloqtmGQjRvjKpyMg= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -94,73 +165,124 @@ github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSG github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= +github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= +github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= +github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= +github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= @@ -222,24 +344,24 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.1 h1:g39TucaRWyV3dwDO++eEc6qf8TVIQ/Da48WmqjZ3i7E= github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/juju/ratelimit v1.0.1 h1:+7AIFJVQ0EQgq/K9+0Krm7m530Du7tIz0METWzN0RgY= github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= @@ -255,79 +377,94 @@ github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.8.0 h1:9xohqzkUwzR4Ga4ivdTcawVS89YSDVxXMa3xJX3cGzg= github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY= -github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk= +github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= +github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= +github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mozillazg/go-pinyin v0.19.0 h1:p+J8/kjJ558KPvVGYLvqBhxf8jbZA2exSLCs2uUVN8c= github.com/mozillazg/go-pinyin v0.19.0/go.mod h1:iR4EnMMRXkfpFVV5FMi4FNB6wGq9NV6uDWbUuPhP4Yc= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM= -github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= +github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml/v2 v2.0.0-beta.8/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= +github.com/pelletier/go-toml/v2 v2.0.0 h1:P7Bq0SaI8nsexyay5UAyDo+ICWy5MQPgEZ5+l8JQTKo= +github.com/pelletier/go-toml/v2 v2.0.0/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/robfig/cron/v3 v3.0.0 h1:kQ6Cb7aHOHTSzNVNEhmp8EcWKLb4CbiMW9h9VyIhO4E= github.com/robfig/cron/v3 v3.0.0/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sagikazarmark/crypt v0.5.0/go.mod h1:l+nzl7KWh51rpzp2h7t4MZWyiEWdhNpOAnclKvg+mdA= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= @@ -336,26 +473,17 @@ github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhr github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.5.1 h1:VHu76Lk0LSP1x254maIu2bplkWpfBWI+B+6fdoZprcg= -github.com/spf13/afero v1.5.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= +github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= +github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= +github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk= -github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.11.0 h1:7OX/1FS6n7jHD1zGrZTM7WtY13ZELRyosK4k93oPr44= +github.com/spf13/viper v1.11.0/go.mod h1:djo0X/bA5+tYVoCn+C7cAYJGcVn/qYLFTG8gdUsX7Zk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= @@ -364,8 +492,9 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/thoas/go-funk v0.7.0 h1:GmirKrs6j6zJbhJIficOsz2aAI7700KsU/5YrdHRM1Y= @@ -376,21 +505,32 @@ github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc= github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go v1.2.3 h1:WbFSXLxDFKVN69Sk8t+XHGzVCD7R8UoAATR8NqZgTbk= github.com/ugorji/go v1.2.3/go.mod h1:5l8GZ8hZvmL4uMdy+mhCO1LjswGRYco9Q3HfuisB21A= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.2.3 h1:/mVYEV+Jo3IZKeA5gBngN0AvNnQltEDkR+eQikkWQu0= github.com/ugorji/go/codec v1.2.3/go.mod h1:5FxzDJIgeiWJZslYHPj+LS1dq1ZBQVelZFnjsFGI/Uc= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= github.com/zhaoyunxing92/dingtalk/v2 v2.0.7-0.20220601083444-173c10c3f835 h1:T6/rI54b4nVpQlIDv0iB0hTff4hzlXe63QcBcZ3u73s= github.com/zhaoyunxing92/dingtalk/v2 v2.0.7-0.20220601083444-173c10c3f835/go.mod h1:MSvHUbYR94ffuWbJKFb8yHYyHg3qC/kQ3Hqpr6lK5ko= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd/api/v3 v3.5.2/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= +go.etcd.io/etcd/client/pkg/v3 v3.5.2/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.2/go.mod h1:2D7ZejHVMIfog1221iLSYlQRzrtECw3kz4I4VAQm3qI= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -405,10 +545,10 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= @@ -416,17 +556,26 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA= +golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -436,17 +585,25 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -454,24 +611,76 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -483,34 +692,89 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 h1:siQdpVirKtzPhKl3lZWozZraCFObP8S1v6PRp0bLrtU= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 h1:xHms4gcpe1YE7A3yIllJXP16CMAGuqwO2lX1mTyyRRc= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -520,29 +784,101 @@ golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f h1:GGU+dLjvlC3qDwqYgL6UgRmHXhOOgns0bZu2Ty5mm6U= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= +google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= +google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= +google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= +google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -552,12 +888,98 @@ google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -566,29 +988,34 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE= gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4= +gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= @@ -616,4 +1043,8 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/logic/api_logic.go b/logic/api_logic.go index b88f302..55add64 100644 --- a/logic/api_logic.go +++ b/logic/api_logic.go @@ -4,10 +4,10 @@ import ( "fmt" "github.com/eryajf/go-ldap-admin/model" + "github.com/eryajf/go-ldap-admin/model/request" + "github.com/eryajf/go-ldap-admin/model/response" "github.com/eryajf/go-ldap-admin/public/tools" "github.com/eryajf/go-ldap-admin/service/isql" - "github.com/eryajf/go-ldap-admin/svc/request" - "github.com/eryajf/go-ldap-admin/svc/response" "github.com/gin-gonic/gin" "github.com/thoas/go-funk" diff --git a/logic/base_logic.go b/logic/base_logic.go index dfc6d68..90e1e03 100644 --- a/logic/base_logic.go +++ b/logic/base_logic.go @@ -4,11 +4,11 @@ import ( "fmt" "github.com/eryajf/go-ldap-admin/model" + "github.com/eryajf/go-ldap-admin/model/request" + "github.com/eryajf/go-ldap-admin/model/response" "github.com/eryajf/go-ldap-admin/public/tools" "github.com/eryajf/go-ldap-admin/service/ildap" "github.com/eryajf/go-ldap-admin/service/isql" - "github.com/eryajf/go-ldap-admin/svc/request" - "github.com/eryajf/go-ldap-admin/svc/response" "github.com/gin-gonic/gin" ) diff --git a/logic/common_login.go b/logic/common_login.go new file mode 100644 index 0000000..1bfc18f --- /dev/null +++ b/logic/common_login.go @@ -0,0 +1,167 @@ +package logic + +import ( + "fmt" + + "github.com/eryajf/go-ldap-admin/config" + "github.com/eryajf/go-ldap-admin/model" + "github.com/eryajf/go-ldap-admin/public/tools" + "github.com/eryajf/go-ldap-admin/service/ildap" + "github.com/eryajf/go-ldap-admin/service/isql" +) + +func CommonAddGroup(group *model.Group) error { + // 先在ldap中创建组 + err := ildap.Group.Add(group) + if err != nil { + return err + } + + // 然后在数据库中创建组 + err = isql.Group.Add(group) + if err != nil { + return err + } + + // 默认创建分组之后,需要将admin添加到分组中 + adminInfo := new(model.User) + err = isql.User.Find(tools.H{"id": 1}, adminInfo) + if err != nil { + return err + } + + err = isql.Group.AddUserToGroup(group, []model.User{*adminInfo}) + if err != nil { + return err + } + + return nil +} + +func CommonUpdateGroup(oldGroup, newGroup *model.Group) error { + //若配置了不允许修改分组名称,则不更新分组名称 + if !config.Conf.Ldap.LdapGroupNameModify { + newGroup.GroupName = oldGroup.GroupName + } + + err := ildap.Group.Update(oldGroup, newGroup) + if err != nil { + return err + } + err = isql.Group.Update(newGroup) + if err != nil { + return err + } + return nil +} + +func CommonAddUser(user *model.User, groupId []uint) error { + if user.Departments == "" { + user.Departments = "默认:研发中心" + } + if user.GivenName == "" { + user.GivenName = user.Nickname + } + if user.PostalAddress == "" { + user.PostalAddress = "默认:地球" + } + if user.Position == "" { + user.Position = "默认:技术" + } + if user.Introduction == "" { + user.Introduction = user.Nickname + } + // 先将用户添加到MySQL + err := isql.User.Add(user) + if err != nil { + return tools.NewMySqlError(fmt.Errorf("向MySQL创建用户失败:" + err.Error())) + } + // 再将用户添加到ldap + err = ildap.User.Add(user) + if err != nil { + return tools.NewLdapError(fmt.Errorf("AddUser向LDAP创建用户失败:" + err.Error())) + } + // 获取用户将要添加的分组 + groups, err := isql.Group.GetGroupByIds(groupId) + if err != nil { + return tools.NewMySqlError(fmt.Errorf("根据部门ID获取部门信息失败" + err.Error())) + } + for _, group := range groups { + if group.GroupDN[:3] == "ou=" { + continue + } + // 先将用户和部门信息维护到MySQL + err := isql.Group.AddUserToGroup(group, []model.User{*user}) + if err != nil { + return tools.NewMySqlError(fmt.Errorf("向MySQL添加用户到分组关系失败:" + err.Error())) + } + //根据选择的部门,添加到部门内 + err = ildap.Group.AddUserToGroup(group.GroupDN, user.UserDN) + if err != nil { + return tools.NewMySqlError(fmt.Errorf("向Ldap添加用户到分组关系失败:" + err.Error())) + } + } + return nil +} + +func CommonUpdateUser(oldUser, newUser *model.User, groupId []uint) error { + // 更新用户 + if !config.Conf.Ldap.LdapUserNameModify { + newUser.Username = oldUser.Username + } + + err := ildap.User.Update(oldUser.Username, newUser) + if err != nil { + return tools.NewLdapError(fmt.Errorf("在LDAP更新用户失败:" + err.Error())) + } + + err = isql.User.Update(newUser) + if err != nil { + return tools.NewMySqlError(fmt.Errorf("在MySQL更新用户失败:" + err.Error())) + } + + //判断部门信息是否有变化有变化则更新相应的数据库 + oldDeptIds := tools.StringToSlice(oldUser.DepartmentId, ",") + addDeptIds, removeDeptIds := tools.ArrUintCmp(oldDeptIds, groupId) + + // 先处理添加的部门 + addgroups, err := isql.Group.GetGroupByIds(addDeptIds) + if err != nil { + return tools.NewMySqlError(fmt.Errorf("根据部门ID获取部门信息失败" + err.Error())) + } + for _, group := range addgroups { + if group.GroupDN[:3] == "ou=" { + continue + } + // 先将用户和部门信息维护到MySQL + err := isql.Group.AddUserToGroup(group, []model.User{*newUser}) + if err != nil { + return tools.NewMySqlError(fmt.Errorf("向MySQL添加用户到分组关系失败:" + err.Error())) + } + //根据选择的部门,添加到部门内 + err = ildap.Group.AddUserToGroup(group.GroupDN, newUser.UserDN) + if err != nil { + return tools.NewLdapError(fmt.Errorf("向Ldap添加用户到分组关系失败:" + err.Error())) + } + } + + // 再处理删除的部门 + removegroups, err := isql.Group.GetGroupByIds(removeDeptIds) + if err != nil { + return tools.NewMySqlError(fmt.Errorf("根据部门ID获取部门信息失败" + err.Error())) + } + for _, group := range removegroups { + if group.GroupDN[:3] == "ou=" { + continue + } + err := isql.Group.RemoveUserFromGroup(group, []model.User{*newUser}) + if err != nil { + return tools.NewMySqlError(fmt.Errorf("在MySQL将用户从分组移除失败:" + err.Error())) + } + err = ildap.Group.RemoveUserFromGroup(group.GroupDN, newUser.UserDN) + if err != nil { + return tools.NewMySqlError(fmt.Errorf("在ldap将用户从分组移除失败:" + err.Error())) + } + } + return nil +} diff --git a/logic/dingtakl_logic.go b/logic/dingtakl_logic.go deleted file mode 100644 index 636a072..0000000 --- a/logic/dingtakl_logic.go +++ /dev/null @@ -1,574 +0,0 @@ -package logic - -import ( - "errors" - "fmt" - "github.com/eryajf/go-ldap-admin/config" - "github.com/eryajf/go-ldap-admin/model" - "github.com/eryajf/go-ldap-admin/public/tools" - "github.com/eryajf/go-ldap-admin/service/ildap" - "github.com/eryajf/go-ldap-admin/service/isql" - "github.com/eryajf/go-ldap-admin/svc/request" - "github.com/gin-gonic/gin" - "github.com/mozillazg/go-pinyin" - "github.com/zhaoyunxing92/dingtalk/v2" - dingreq "github.com/zhaoyunxing92/dingtalk/v2/request" - "gorm.io/gorm" - "regexp" - "strconv" - "strings" -) - -type DingTalkLogic struct { -} - -//通过钉钉获取部门信息 -func (d *DingTalkLogic) DsyncDingTalkDepts(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) { - client, err := dingtalk.NewClient(config.Conf.DingTalk.DingTalkAppKey, config.Conf.DingTalk.DingTalkAppSecret) - // 先存根部门信息到数据库和ldap,钉钉根部门id为1,ldap根部门名称为:config.Conf.DingTalk.DingTalkRootOu - r := request.DingGroupAddReq{} - r.GroupName = config.Conf.DingTalk.DingTalkRootOuName - r.GroupType = "ou" - r.ParentId = 0 - r.Remark = "钉钉根部门" - r.Source = config.Conf.DingTalk.DingTalkIdSource - r.SourceDeptId = fmt.Sprintf("%s_%s", config.Conf.DingTalk.DingTalkIdSource, "1") - r.SourceDeptParentId = fmt.Sprintf("%s_%s", config.Conf.DingTalk.DingTalkIdSource, "0") - group, err := d.AddDept(&r) - if err != nil { - return nil, fmt.Sprintf("新增部门失败:部门名称为:%s,钉钉部门id为:%d,错误信息:%s", r.GroupName, r.SourceDeptId, err.Error()) - } - // 获取根部门下的部门信息,进行处理 - reqDept := &dingreq.DeptList{} - reqDept.DeptId = 1 - reqDept.Language = "zh_CN" - err = d.GetSubDepts(client, reqDept, group.ID, r.Source) - if err != nil { - return nil, fmt.Sprintf("DsyncDingTalkDepts同步部门出错:%s", err.Error()) - } - return nil, nil -} - -// 通过钉钉获取部门信息,并存入数据库 -func (d *DingTalkLogic) GetSubDepts(client *dingtalk.DingTalk, req *dingreq.DeptList, pgId uint, source string) error { - // 获取子部门列表 - depts, err := client.GetDeptList(req) - if err != nil { - return errors.New(fmt.Sprintf("GetSubDepts获取部门列表失败:%s", err.Error())) - } - fmt.Println("GetSubDepts获取到的钉钉部门列表:", depts) - // 遍历并处理当前部门信息 - for _, dept := range depts.Depts { - //先判断分组类型,默认为cn,方便应对钉钉动态调整原本没有成员的部门加入成员后,导致我们无法增加 - localDept := request.DingGroupAddReq{ - GroupType: "cn", - ParentId: pgId, - GroupName: dept.Name, - Remark: dept.Name, - Source: config.Conf.DingTalk.DingTalkIdSource, - SourceDeptParentId: fmt.Sprintf("%s_%d", source, dept.ParentId), - SourceDeptId: fmt.Sprintf("%s_%d", source, dept.Id), - SourceUserNum: 0, - } - //获取钉钉方,若部门存在人员信息,则设置为cn类型 - //reqTemp := &dingreq.DeptUserId{} - //reqTemp.DeptId = dept.Id - //repTemp, err := client.GetDeptUserIds(reqTemp) - //if err != nil { - // return errors.New(fmt.Sprintf("GetSubDepts获取部门用户Id列表失败:%s", err.Error())) - //} - //fmt.Println("钉钉部门人员列表:", repTemp) - //if len(repTemp.UserIds) > 0 { - // localDept.GroupType = "cn" - // localDept.SourceUserNum = len(repTemp.UserIds) - //} - // 处理部门入库 - deptTemp, err := d.AddDept(&localDept) - if err != nil { - return errors.New(fmt.Sprintf("GetSubDepts添加部门入库失败:%s", err.Error())) - } - // 递归调用 - sub := &dingreq.DeptList{} - sub.DeptId = dept.Id - sub.Language = "zh_CN" - d.GetSubDepts(client, sub, deptTemp.ID, deptTemp.Source) - } - return nil -} - -//根据现有数据库同步到的部门信息,开启用户同步 -func (d DingTalkLogic) SyncDingTalkUsers(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) { - client, err := dingtalk.NewClient(config.Conf.DingTalk.DingTalkAppKey, config.Conf.DingTalk.DingTalkAppSecret) - //获取数据库里面的钉钉同步过来的部门信息 - r := request.GroupListAllReq{} - r.GroupType = "cn" - r.Source = config.Conf.DingTalk.DingTalkIdSource - depts, err := isql.Group.ListAll(&r) - if err != nil { - return nil, fmt.Sprintf("SyncDingTalkUsers查询本地部门列表失败:", err.Error()) - } - //遍历处理部门,获取钉钉对应的用户信息 - for index, dept := range depts { - fmt.Println(fmt.Sprintf("当前进行的步调为:%d,部门名称为:%s", index, dept.GroupName)) - err = d.AddDeptUser(client, dept, 0) - if err != nil { - return nil, fmt.Sprintf("SyncDingTalkUsers添加部门下用户失败:", err.Error()) - } - } - return nil, nil -} - -//获取并处理钉钉部门下的用户信息入库 -func (d DingTalkLogic) AddDeptUser(client *dingtalk.DingTalk, dept *model.Group, cursor int) error { - // 处理部门下的人员信息 - deptId := strings.Split(dept.SourceDeptId, "_") - tempId, err := strconv.Atoi(deptId[1]) - if err != nil { - return err - } - //方式一:获取部门下用户信息,一次100个,遍历后插入数据库,经过验证,第三方依赖包有问题 - r := dingreq.DeptDetailUserInfo{} - r.DeptId = tempId - r.Language = "zh_CN" - r.Cursor = cursor - r.Size = 100 - //获取钉钉部门人员信息 - rep, err := client.GetDeptDetailUserInfo(&r) - fmt.Println(fmt.Sprintf("当前获取的部门名称为:%s,总用户量为:%d", dept.GroupName, len(rep.DeptDetailUsers))) - if err != nil { - return errors.New(fmt.Sprintf("AddDeptUser获取钉钉部门人员信息失败:%s", err.Error())) - } - //方式二:临时处理方案:获取部门用户id列表,遍历,挨个从钉钉获取用户信息 - //dingr := dingreq.DeptUserId{} - //dingr.DeptId = tempId - //deptUserIds, err := client.GetDeptUserIds(&dingr) - //if err != nil { - // return errors.New(fmt.Sprintf("AddDeptUser通过用户部门id从钉钉获取用户id列表失败:%s", err.Error())) - //} - // 遍历并处理当前部门下的人员信息 - for _, detail := range rep.DeptDetailUsers { - //for index, userId := range deptUserIds.UserIds { - // fmt.Println(fmt.Sprintf("获取到的部门用户数为:%d,正在处理的用户序号为:%d,总Ids为:", len(deptUserIds.UserIds), index)) - // fmt.Println(deptUserIds.UserIds) - // userReq := dingreq.UserDetail{} - // userReq.UserId = userId - // userReq.Language = "zh_CN" - // detail, err := client.GetUserDetail(&userReq) - // if err != nil { - // return errors.New(fmt.Sprintf("AddDeptUser通过用户id从钉钉获取用户详情失败:%s", err.Error())) - // } - // 获取人员信息 - fmt.Println("钉钉人员详情:", detail) - userName := "" - if detail.OrgEmail != "" { - emailstr := strings.Split(detail.OrgEmail, "@") - userName = emailstr[0] - } - if userName == "" && detail.Name != "" { - name := pinyin.LazyConvert(detail.Name, nil) - userName = strings.Join(name, "") - } - if userName == "" && detail.Mobile != "" { - userName = detail.Mobile - } - - if detail.JobNumber == "" { - detail.JobNumber = userName - } - //钉钉部门ids,转换为内部部门id - sourceDeptIds := []string{} - for _, deptId := range detail.DeptIds { - sourceDeptIds = append(sourceDeptIds, fmt.Sprintf("%s_%d", config.Conf.DingTalk.DingTalkIdSource, deptId)) - } - groupIds, err := isql.Group.DingTalkDeptIdsToGroupIds(sourceDeptIds) - if err != nil { - return errors.New(fmt.Sprintf("AddDeptUser转换钉钉部门id到本地分组id出错:%s", err.Error())) - } - user := request.DingUserAddReq{ - Username: userName, - Password: config.Conf.DingTalk.DingTalkUserInitPassword, - Nickname: detail.Name, - GivenName: detail.Name, - Mail: detail.OrgEmail, - JobNumber: detail.JobNumber, - Mobile: detail.Mobile, - Avatar: detail.Avatar, - PostalAddress: detail.WorkPlace, - Departments: dept.GroupName, - Position: detail.Title, - Introduction: detail.Remark, - Status: 1, - DepartmentId: groupIds, - Source: config.Conf.DingTalk.DingTalkIdSource, - SourceUserId: fmt.Sprintf("%s_%s", config.Conf.DingTalk.DingTalkIdSource, detail.UserId), - SourceUnionId: fmt.Sprintf("%s_%s", config.Conf.DingTalk.DingTalkIdSource, detail.UnionId), - } - // 入库 - repUser, err := d.AddUser(&user) - if err != nil { - return errors.New(fmt.Sprintf("AddDeptUser添加用户失败:%s", err.Error())) - } - fmt.Println("入库成功,用户信息为:") - fmt.Println(repUser) - } - if rep.HasMore { - err = d.AddDeptUser(client, dept, rep.NextCursor) - if err != nil { - return errors.New(fmt.Sprintf("AddDeptUser添加用户失败:%s", err.Error())) - } - } - return nil -} - -// AddGroup 添加部门数据 -func (d DingTalkLogic) AddDept(r *request.DingGroupAddReq) (data *model.Group, rspError error) { - // 判断部门名称是否存在 - filter := tools.H{"source_dept_id": r.SourceDeptId} - dept := new(model.Group) - err := isql.Group.Find(filter, dept) - flag := errors.Is(err, gorm.ErrRecordNotFound) - fmt.Println("部门是否存在:", filter, flag) - if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { - return nil, errors.New(fmt.Sprintf("AddDept添加部门失败:%s", err.Error())) - } - //分组不存在,直接创建(此处通过部门名称和第三方id来共同判定唯一,理论上不会出现重复) - if errors.Is(err, gorm.ErrRecordNotFound) { - group := model.Group{ - GroupType: r.GroupType, - ParentId: r.ParentId, - GroupName: r.GroupName, - Remark: r.Remark, - Creator: "system", - Source: r.Source, - SourceDeptParentId: r.SourceDeptParentId, - SourceDeptId: r.SourceDeptId, - SourceUserNum: r.SourceUserNum, - } - pdn := "" - if group.ParentId > 0 { - pdn, err = isql.Group.GetGroupDn(r.ParentId, "") - if err != nil { - return nil, errors.New(fmt.Sprintf("AddDept获取父级部门dn失败:%s", err.Error())) - } - } - err = ildap.Group.Add(&group, pdn) - if err != nil { - return nil, tools.NewLdapError(fmt.Errorf("AddDept向LDAP创建分组失败" + err.Error())) - } - // 创建 - err = isql.Group.Add(&group) - if err != nil { - return nil, tools.NewLdapError(fmt.Errorf("AddDept向MySQL创建分组失败:" + err.Error())) - } - // 默认创建分组之后,需要将admin添加到分组中 - adminInfo := new(model.User) - err = isql.User.Find(tools.H{"id": 1}, adminInfo) - if err != nil { - return nil, errors.New(fmt.Sprintf("AddDept获取admin用户失败:%s", tools.NewMySqlError(err).Error())) - } - - err = isql.Group.AddUserToGroup(&group, []model.User{*adminInfo}) - if err != nil { - return nil, tools.NewMySqlError(fmt.Errorf("AddDept添加用户到分组失败: %s", err.Error())) - } - return &group, nil - } else { //分组存在 - //判断是否名字/备注/钉钉部门ID有修改 - if r.GroupName != dept.GroupName || r.Remark != dept.Remark || r.SourceDeptParentId != dept.SourceDeptParentId || r.SourceUserNum != dept.SourceUserNum { - err = d.UpdateDept(r) - if err != nil { - return nil, errors.New(fmt.Sprintf("AddDept更新部门失败:%s", err.Error())) - } - } - //处理父级部门变化 - if r.SourceDeptParentId != dept.SourceDeptParentId { - // TODO 待处理父级部门变化情况 - } - return dept, nil - } -} - -// UpdateDept 更新部门数据 -func (d DingTalkLogic) UpdateDept(r *request.DingGroupAddReq) error { - oldData := new(model.Group) - filter := tools.H{"source_dept_id": r.SourceDeptId} - err := isql.Group.Find(filter, oldData) - if err != nil { - return errors.New(fmt.Sprintf("UpdateDept获取旧的部门信息失败:%s", tools.NewMySqlError(err).Error())) - } - dept := model.Group{ - Model: oldData.Model, - GroupName: r.GroupName, - Remark: r.Remark, - Creator: "system", - GroupType: oldData.GroupType, - SourceDeptId: r.SourceDeptId, - SourceDeptParentId: r.SourceDeptParentId, - SourceUserNum: r.SourceUserNum, - } - - oldGroupName := oldData.GroupName - oldRemark := oldData.Remark - dn, err := isql.Group.GetGroupDn(oldData.ID, "") - if err != nil { - return errors.New(fmt.Sprintf("UpdateDept不去部门dn失败:%s", tools.NewMySqlError(err).Error())) - } - err = ildap.Group.Update(&dept, dn, oldGroupName, oldRemark) - if err != nil { - return tools.NewLdapError(fmt.Errorf("UpdateDept向LDAP更新分组失败:" + err.Error())) - } - //若配置了不允许修改分组名称,则不更新分组名称 - if !config.Conf.Ldap.LdapGroupNameModify { - dept.GroupName = oldGroupName - } - err = isql.Group.Update(&dept) - if err != nil { - return tools.NewLdapError(fmt.Errorf("UpdateDept向MySQL更新分组失败:" + err.Error())) - } - return nil -} - -// AddUser 添加用户数据 -func (d DingTalkLogic) AddUser(r *request.DingUserAddReq) (data *model.User, rspError error) { - // 兼容处理钉钉异常人员信息,若username,mail,mobile都没有的直接跳过 - if r.Username == "" && r.Mail == "" && r.Mobile == "" { - emptyData := new(model.User) - emptyData.Introduction = fmt.Sprintf("此用户:%s,username,mail,mobile皆为空,跳过入库,请手动置后台添加", r.Nickname) - emptyData.Nickname = r.Nickname - emptyData.SourceUserId = r.SourceUserId - emptyData.Source = r.Source - emptyData.GivenName = r.GivenName - return emptyData, nil - } - - isExist := false - oldData := new(model.User) - if isql.User.Exist(tools.H{"source_user_id": r.SourceUserId}) { - err := isql.User.Find(tools.H{"source_user_id": r.SourceUserId}, oldData) - if err != nil { - return nil, errors.New(fmt.Sprintf("AddUser根据钉钉用户id获取用户失败:%s", err.Error())) - } - isExist = true - } - if !isExist { - if isql.User.Exist(tools.H{"source_union_id": r.SourceUnionId}) { - err := isql.User.Find(tools.H{"source_union_id": r.SourceUnionId}, oldData) - if err != nil { - return nil, errors.New(fmt.Sprintf("AddUser根据钉钉用户unionid获取用户失败:%s", err.Error())) - } - isExist = true - } - } - //if !isExist { - // if r.Mail != "" && isql.User.Exist(tools.H{"mail": r.Mail}) { - // err := isql.User.Find(tools.H{"mail": r.Mail}, oldData) - // if err != nil { - // return nil, errors.New(fmt.Sprintf("AddUser根据钉钉用户mail获取用户失败:%s", err.Error())) - // } - // isExist = true - // } - //} - if !isExist { - if isql.User.Exist(tools.H{"job_number": r.JobNumber}) { - err := isql.User.Find(tools.H{"job_number": r.JobNumber}, oldData) - if err != nil { - return nil, errors.New(fmt.Sprintf("AddUser根据钉钉用户job_number获取用户失败:%s", err.Error())) - } - isExist = true - } - } - if !isExist { - if isql.User.Exist(tools.H{"mobile": r.Mobile}) { - err := isql.User.Find(tools.H{"mobile": r.Mobile}, oldData) - if err != nil { - return nil, errors.New(fmt.Sprintf("AddUser根据钉钉用户mobile获取用户失败:%s", err.Error())) - } - isExist = true - } - } - if !isExist { - //组装用户名 - //先根据钉钉唯一id获取,查看数据库中是否存在 - //不存在,则根据用户名 like 用户名获取尾号最大的账号 - //重新设定用户名 - userData := new(model.User) - err := isql.User.FindTheSameUserName(r.Username, userData) - if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { - } else { - // 找到重名用户, - re := regexp.MustCompile("[0-9]+") - num := re.FindString(userData.Username) - n := 1 - if num != "" { - m, err := strconv.Atoi(num) - if err != nil { - return - } - n = m + 1 - } - r.Username = fmt.Sprintf("%s%d", r.Username, n) - } - } - if isExist { - r.Username = oldData.Username - user, err := d.UpdateUser(r, oldData) - if err != nil { - return nil, errors.New(fmt.Sprintf("AddUser用户已存在,更新用户失败:%s", err.Error())) - } - return user, nil - } - // 根据角色id获取角色 - r.RoleIds = []uint{2} // 默认添加为普通用户角色 - roles, err := isql.Role.GetRolesByIds(r.RoleIds) - if err != nil { - return nil, tools.NewValidatorError(fmt.Errorf("AddUser根据角色ID获取角色信息失败:%s", err.Error())) - } - - var reqRoleSorts []int - for _, role := range roles { - reqRoleSorts = append(reqRoleSorts, int(role.Sort)) - } - deptIds := tools.SliceToString(r.DepartmentId, ",") - user := model.User{ - Username: r.Username, - Password: r.Password, - Nickname: r.Nickname, - GivenName: r.GivenName, - Mail: r.Mail, - JobNumber: r.JobNumber, - Mobile: r.Mobile, - Avatar: r.Avatar, - PostalAddress: r.PostalAddress, - Departments: r.Departments, - Position: r.Position, - Introduction: r.Introduction, - Status: r.Status, - Creator: "system", - DepartmentId: deptIds, - Roles: roles, - Source: r.Source, - SourceUserId: r.SourceUserId, - SourceUnionId: r.SourceUnionId, - } - if user.Introduction == "" { - user.Introduction = r.Nickname - } - if user.JobNumber == "" { - user.JobNumber = r.Mobile - } - //先识别用户选择的部门是否是OU开头 - gdns := make(map[uint]string) - for _, deptId := range r.DepartmentId { - dn, err := isql.Group.GetGroupDn(deptId, "") - if err != nil { - return nil, errors.New(fmt.Sprintf("AddUser根据用户dn信息失败:%s", err.Error())) - } - gdn := fmt.Sprintf("%s,%s", dn, config.Conf.Ldap.LdapBaseDN) - if gdn[:3] == "ou=" { - return nil, errors.New(fmt.Sprintf("AddUser不能添加用户到OU组织单元:%s", gdn)) - } - gdns[deptId] = gdn - } - //先创建用户到默认分组 - err = ildap.User.Add(&user) - if err != nil { - return nil, tools.NewLdapError(fmt.Errorf("AddUser向LDAP创建用户失败:" + err.Error())) - } - isExistUser := false - for deptId, gdn := range gdns { - //根据选择的部门,添加到部门内 - err = ildap.Group.AddUserToGroup(gdn, fmt.Sprintf("uid=%s,%s", user.Username, config.Conf.Ldap.LdapUserDN)) - if err != nil { - return nil, errors.New(fmt.Sprintf("AddUser向部门添加用户失败:%s", err.Error())) - } - if !isExistUser { - err = isql.User.Add(&user) - if err != nil { - return nil, tools.NewMySqlError(fmt.Errorf("向MySQL创建用户失败:" + err.Error())) - } - isExistUser = true - } - //根据部门分配,将用户和部门信息维护到部门关系表里面 - users := []model.User{} - users = append(users, user) - depart := new(model.Group) - filter := tools.H{"id": deptId} - err = isql.Group.Find(filter, depart) - if err != nil { - return nil, tools.NewMySqlError(err) - } - err = isql.Group.AddUserToGroup(depart, users) - if err != nil { - return nil, tools.NewMySqlError(fmt.Errorf("AddUser向MySQL添加用户到分组关系失败:" + err.Error())) - } - } - return &user, nil -} - -// Update 更新数据 -func (d DingTalkLogic) UpdateUser(r *request.DingUserAddReq, oldData *model.User) (data *model.User, rspError error) { - deptIds := tools.SliceToString(r.DepartmentId, ",") - user := model.User{ - Model: oldData.Model, - Username: r.Username, - Nickname: r.Nickname, - GivenName: r.GivenName, - Mail: r.Mail, - JobNumber: r.JobNumber, - Mobile: r.Mobile, - Avatar: r.Avatar, - PostalAddress: r.PostalAddress, - Departments: r.Departments, - Position: r.Position, - Introduction: r.Introduction, - Creator: "system", - DepartmentId: deptIds, - Source: oldData.Source, - Roles: oldData.Roles, - SourceUserId: r.SourceUserId, - SourceUnionId: r.SourceUnionId, - } - if user.Introduction == "" { - user.Introduction = r.Nickname - } - if user.PostalAddress == "" { - user.PostalAddress = "没有填写地址" - } - if user.Position == "" { - user.Position = "技术" - } - if user.JobNumber == "" { - user.JobNumber = r.Mobile - } - err := ildap.User.Update(oldData.Username, &user) - if err != nil { - return nil, tools.NewLdapError(fmt.Errorf("UpdateUser在LDAP更新用户失败:" + err.Error())) - } - - // 更新用户 - if !config.Conf.Ldap.LdapUserNameModify { - user.Username = oldData.Username - } - err = isql.User.Update(&user) - if err != nil { - return nil, tools.NewMySqlError(fmt.Errorf("UpdateUser在MySQL更新用户失败:" + err.Error())) - } - //判断部门信息是否有变化有变化则更新相应的数据库 - oldDeptIds := tools.StringToSlice(oldData.DepartmentId, ",") - addDeptIds, removeDeptIds := tools.ArrUintCmp(oldDeptIds, r.DepartmentId) - for _, deptId := range removeDeptIds { - //从旧组中删除 - err = User.RemoveUserToGroup(deptId, []uint{oldData.ID}) - if err != nil { - return nil, errors.New(fmt.Sprintf("UpdateUser将用户从分组移除失败:%s", err.Error())) - } - } - for _, deptId := range addDeptIds { - //添加到新分组中 - err = User.AddUserToGroup(deptId, []uint{oldData.ID}) - if err != nil { - return nil, errors.New(fmt.Sprintf("UpdateUser将用户添加至分组失败:%s", err.Error())) - } - } - return &user, nil -} diff --git a/logic/dingtalk_logic.go b/logic/dingtalk_logic.go new file mode 100644 index 0000000..4c1f8d7 --- /dev/null +++ b/logic/dingtalk_logic.go @@ -0,0 +1,268 @@ +package logic + +import ( + "fmt" + "strings" + + "github.com/eryajf/go-ldap-admin/config" + "github.com/eryajf/go-ldap-admin/model" + "github.com/eryajf/go-ldap-admin/model/request" + "github.com/eryajf/go-ldap-admin/public/client/dingtalk" + "github.com/eryajf/go-ldap-admin/public/tools" + "github.com/eryajf/go-ldap-admin/service/ildap" + "github.com/eryajf/go-ldap-admin/service/isql" + "github.com/gin-gonic/gin" + "github.com/mozillazg/go-pinyin" +) + +type DingTalkLogic struct { +} + +// TODO: 目前同步没毛病,只有更新还需要再琢磨琢磨 + +//通过钉钉获取部门信息 +func (d *DingTalkLogic) SyncDingTalkDepts(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) { + // 1.获取所有部门 + depts, err := dingtalk.GetDingTalkAllDepts(1) + if err != nil { + return nil, tools.NewOperationError(fmt.Errorf("获取钉钉部门列表失败:%s", err.Error())) + } + // 2.将部门这个数组进行拆分,一组是父ID为1的,一组是父ID不为1的 + var firstDepts []*dingtalk.DingTalkDept // 父ID为1的部门 + var otherDepts []*dingtalk.DingTalkDept // 父ID不为1的部门 + for _, dept := range depts { + if dept.ParentId == 1 { + firstDepts = append(firstDepts, dept) + } else { + otherDepts = append(otherDepts, dept) + } + } + // 3.先写父ID为1的,再写父ID不为1的 + for _, dept := range firstDepts { + err := d.AddDepts(&request.DingGroupAddReq{ + GroupType: "cn", + GroupName: dept.Name, + Remark: dept.Remark, + SourceDeptId: fmt.Sprintf("%s_%d", config.Conf.DingTalk.DingTalkFlag, dept.Id), + Source: config.Conf.DingTalk.DingTalkFlag, + SourceDeptParentId: fmt.Sprintf("%s_%d", config.Conf.DingTalk.DingTalkFlag, 1), + }) + if err != nil { + return nil, tools.NewOperationError(fmt.Errorf("DsyncDingTalkDepts添加根部门失败:%s", err.Error())) + } + } + for _, dept := range otherDepts { + err := d.AddDepts(&request.DingGroupAddReq{ + GroupType: "cn", + GroupName: dept.Name, + Remark: dept.Remark, + SourceDeptId: fmt.Sprintf("%s_%d", config.Conf.DingTalk.DingTalkFlag, dept.Id), + Source: config.Conf.DingTalk.DingTalkFlag, + SourceDeptParentId: fmt.Sprintf("%s_%d", config.Conf.DingTalk.DingTalkFlag, dept.ParentId), + }) + if err != nil { + return nil, tools.NewOperationError(fmt.Errorf("DsyncDingTalkDepts添加根部门失败:%s", err.Error())) + } + } + + return nil, nil +} + +// AddGroup 添加部门数据 +func (d DingTalkLogic) AddDepts(r *request.DingGroupAddReq) error { + // 判断部门名称是否存在 + parentGroup := new(model.Group) + err := isql.Group.Find(tools.H{"source_dept_id": r.SourceDeptParentId}, parentGroup) + if err != nil { + return tools.NewMySqlError(fmt.Errorf("查询父级部门失败:%s", err.Error())) + } + if !isql.Group.Exist(tools.H{"source_dept_id": r.SourceDeptId}) { + groupTmp := model.Group{ + GroupName: r.GroupName, + Remark: r.Remark, + Creator: "system", + GroupType: "cn", + ParentId: parentGroup.ID, + SourceDeptId: r.SourceDeptId, + Source: r.Source, + SourceDeptParentId: r.SourceDeptParentId, + GroupDN: fmt.Sprintf("cn=%s,%s", r.GroupName, parentGroup.GroupDN), + } + err = CommonAddGroup(&groupTmp) + if err != nil { + return tools.NewOperationError(fmt.Errorf("添加部门失败:%s", err.Error())) + } + } + // todo: 分组存在,但是信息有变更的情况,需要考量,但是这种组织架构的调整,通常是比较复杂的情况,这里并不好与之一一对应同步,暂时不做支持 + return nil +} + +//根据现有数据库同步到的部门信息,开启用户同步 +func (d DingTalkLogic) SyncDingTalkUsers(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) { + // 1.获取钉钉用户列表 + users, err := dingtalk.GetDingTalkAllUsers() + if err != nil { + return nil, tools.NewOperationError(fmt.Errorf("SyncDingTalkUsers获取钉钉用户列表失败:%s", err.Error())) + } + // 2.遍历用户,开始写入 + for _, detail := range users { + // 用户名的几种情况 + var userName string + if detail.OrgEmail != "" { + userName = strings.Split(detail.OrgEmail, "@")[0] + } + if userName == "" && detail.Name != "" { + userName = strings.Join(pinyin.LazyConvert(detail.Name, nil), "") + } + if userName == "" && detail.Mobile != "" { + userName = detail.Mobile + } + if userName == "" && detail.Email != "" { + userName = strings.Split(detail.Email, "@")[0] + } + + if detail.OrgEmail == "" { + detail.OrgEmail = detail.Email + } + + // 如果企业内没有工号,则工号用名字占位 + if detail.JobNumber == "" { + detail.JobNumber = detail.Mobile + } + + //钉钉部门ids,转换为内部部门id + var sourceDeptIds []string + for _, deptId := range detail.DeptIds { + sourceDeptIds = append(sourceDeptIds, fmt.Sprintf("%s_%d", config.Conf.DingTalk.DingTalkFlag, deptId)) + } + groupIds, err := isql.Group.DingTalkDeptIdsToGroupIds(sourceDeptIds) + if err != nil { + return nil, tools.NewMySqlError(fmt.Errorf("SyncDingTalkUsers获取钉钉部门ids转换为内部部门id失败:%s", err.Error())) + } + + // 写入用户 + user := request.DingUserAddReq{ + Username: userName, + Password: config.Conf.Ldap.LdapUserInitPassword, + Nickname: detail.Name, + GivenName: detail.Name, + Mail: detail.OrgEmail, + JobNumber: detail.JobNumber, + Mobile: detail.Mobile, + Avatar: detail.Avatar, + PostalAddress: detail.WorkPlace, + // Departments: dept.GroupName, + Position: detail.Title, + Introduction: detail.Remark, + Status: 1, + DepartmentId: groupIds, + Source: config.Conf.DingTalk.DingTalkFlag, + SourceUserId: fmt.Sprintf("%s_%s", config.Conf.DingTalk.DingTalkFlag, detail.UserId), + SourceUnionId: fmt.Sprintf("%s_%s", config.Conf.DingTalk.DingTalkFlag, detail.UnionId), + } + // 入库 + err = d.AddUsers(&user) + if err != nil { + return nil, tools.NewOperationError(fmt.Errorf("SyncDingTalkUsers写入用户失败:%s", err.Error())) + } + } + + // 3.获取钉钉已离职用户id列表 + userIds, err := dingtalk.GetDingTalkLeaveUserIds() + if err != nil { + return nil, tools.NewOperationError(fmt.Errorf("SyncDingTalkUsers获取钉钉离职用户列表失败:%s", err.Error())) + } + // 4.遍历id,开始处理 + for _, uid := range userIds { + user := new(model.User) + err = isql.User.Find(tools.H{"source_user_id": fmt.Sprintf("%s_%s", config.Conf.DingTalk.DingTalkFlag, uid)}, user) + if err != nil { + return nil, tools.NewMySqlError(fmt.Errorf("在MySQL查询用户失败: " + err.Error())) + } + // 先从ldap删除用户 + err = ildap.User.Delete(user.UserDN) + if err != nil { + return nil, tools.NewLdapError(fmt.Errorf("在LDAP删除用户失败" + err.Error())) + } + // 然后更新MySQL中用户状态 + err = isql.User.ChangeStatus(int(user.ID), 2) + if err != nil { + return nil, tools.NewMySqlError(fmt.Errorf("在MySQL更新用户状态失败: " + err.Error())) + } + } + + return nil, nil +} + +// AddUser 添加用户数据 +func (d DingTalkLogic) AddUsers(r *request.DingUserAddReq) error { + // 根据 unionid 查询用户,不存在则创建 + if !isql.User.Exist(tools.H{"source_union_id": r.SourceUnionId}) { + // 根据角色id获取角色 + r.RoleIds = []uint{2} // 默认添加为普通用户角色 + roles, err := isql.Role.GetRolesByIds(r.RoleIds) + if err != nil { + return tools.NewValidatorError(fmt.Errorf("根据角色ID获取角色信息失败:%s", err.Error())) + } + + deptIds := tools.SliceToString(r.DepartmentId, ",") + user := model.User{ + Username: r.Username, + Password: r.Password, + Nickname: r.Nickname, + GivenName: r.GivenName, + Mail: r.Mail, + JobNumber: r.JobNumber, + Mobile: r.Mobile, + Avatar: r.Avatar, + PostalAddress: r.PostalAddress, + Departments: r.Departments, + Position: r.Position, + Introduction: r.Introduction, + Status: r.Status, + Creator: "system", + DepartmentId: deptIds, + Roles: roles, + Source: r.Source, + SourceUserId: r.SourceUserId, + SourceUnionId: r.SourceUnionId, + UserDN: fmt.Sprintf("uid=%s,%s", r.Username, config.Conf.Ldap.LdapUserDN), + } + err = CommonAddUser(&user, r.DepartmentId) + if err != nil { + return err + } + } + // todo: 用户如果存在,则暂时跳过,目前用户名取自邮箱等内容,因为这个不确定性,可能会造成一些逻辑上的问题,因为默认情况下,用户名是无法在ldap中更改的,所以暂时跳过,如果用户有这里的需求,可以根据自己的情况固定用户名的字段,也就可以打开如下的注释了 + // else { + // oldData := new(model.User) + // if err := isql.User.Find(tools.H{"source_union_id": r.SourceUnionId}, oldData); err != nil { + // return err + // } + // if r.Username != oldData.Username || r.Mail != oldData.Mail || r.Mobile != oldData.Mobile { + // user := model.User{ + // Model: oldData.Model, + // Username: r.Username, + // Nickname: r.Nickname, + // GivenName: r.GivenName, + // Mail: r.Mail, + // JobNumber: r.JobNumber, + // Mobile: r.Mobile, + // Avatar: r.Avatar, + // PostalAddress: r.PostalAddress, + // Departments: r.Departments, + // Position: r.Position, + // Introduction: r.Introduction, + // Creator: oldData.Creator, + // DepartmentId: tools.SliceToString(r.DepartmentId, ","), + // Source: oldData.Source, + // Roles: oldData.Roles, + // UserDN: oldData.UserDN, + // } + // if err := CommonUpdateUser(oldData, &user, r.DepartmentId); err != nil { + // return err + // } + // } + // } + return nil +} diff --git a/logic/group_logic.go b/logic/group_logic.go index bd163e3..cabe0b4 100644 --- a/logic/group_logic.go +++ b/logic/group_logic.go @@ -7,11 +7,11 @@ import ( "github.com/eryajf/go-ldap-admin/config" "github.com/eryajf/go-ldap-admin/model" + "github.com/eryajf/go-ldap-admin/model/request" + "github.com/eryajf/go-ldap-admin/model/response" "github.com/eryajf/go-ldap-admin/public/tools" "github.com/eryajf/go-ldap-admin/service/ildap" "github.com/eryajf/go-ldap-admin/service/isql" - "github.com/eryajf/go-ldap-admin/svc/request" - "github.com/eryajf/go-ldap-admin/svc/response" "github.com/gin-gonic/gin" ) @@ -37,28 +37,35 @@ func (l GroupLogic) Add(c *gin.Context, req interface{}) (data interface{}, rspE } group := model.Group{ - GroupType: r.GroupType, - ParentId: r.ParentId, - GroupName: r.GroupName, - Remark: r.Remark, - Creator: ctxUser.Username, - Source: "platform", //默认是平台添加 - SourceDeptId: "platform_0", - SourceDeptParentId: "platform_0", + GroupType: r.GroupType, + ParentId: r.ParentId, + GroupName: r.GroupName, + Remark: r.Remark, + Creator: ctxUser.Username, + Source: "platform", //默认是平台添加 } - pdn := "" - if group.ParentId > 0 { - pdn, err = isql.Group.GetGroupDn(r.ParentId, "") + if r.ParentId == 0 { + group.SourceDeptId = "platform_0" + group.SourceDeptParentId = "platform_0" + group.GroupDN = fmt.Sprintf("%s=%s,%s", r.GroupType, r.GroupName, config.Conf.Ldap.LdapBaseDN) + } else { + parentGroup := new(model.Group) + err := isql.Group.Find(tools.H{"id": r.ParentId}, parentGroup) if err != nil { - return nil, err.Error() + return nil, tools.NewMySqlError(fmt.Errorf("获取父级组信息失败")) } + group.SourceDeptId = "platform_0" + group.SourceDeptParentId = fmt.Sprintf("%s_%d", parentGroup.Source, r.ParentId) + group.GroupDN = fmt.Sprintf("%s=%s,%s", r.GroupType, r.GroupName, parentGroup.GroupDN) } - err = ildap.Group.Add(&group, pdn) + + // 先在ldap中创建组 + err = ildap.Group.Add(&group) if err != nil { return nil, tools.NewLdapError(fmt.Errorf("向LDAP创建分组失败" + err.Error())) } - // 创建 + // 然后在数据库中创建组 err = isql.Group.Add(&group) if err != nil { return nil, tools.NewLdapError(fmt.Errorf("向MySQL创建分组失败")) @@ -146,35 +153,30 @@ func (l GroupLogic) Update(c *gin.Context, req interface{}) (data interface{}, r return nil, tools.NewMySqlError(fmt.Errorf("获取当前登陆用户失败")) } - oldData := new(model.Group) - err = isql.Group.Find(filter, oldData) + oldGroup := new(model.Group) + err = isql.Group.Find(filter, oldGroup) if err != nil { return nil, tools.NewMySqlError(err) } - group := model.Group{ - Model: oldData.Model, + newGroup := model.Group{ + Model: oldGroup.Model, GroupName: r.GroupName, Remark: r.Remark, Creator: ctxUser.Username, - GroupType: oldData.GroupType, + GroupType: oldGroup.GroupType, } - oldGroupName := oldData.GroupName - oldRemark := oldData.Remark - dn, err := isql.Group.GetGroupDn(r.ID, "") - if err != nil { - return nil, err.Error() + //若配置了不允许修改分组名称,则不更新分组名称 + if !config.Conf.Ldap.LdapGroupNameModify { + newGroup.GroupName = oldGroup.GroupName } - err = ildap.Group.Update(&group, dn, oldGroupName, oldRemark) + + err = ildap.Group.Update(oldGroup, &newGroup) if err != nil { return nil, tools.NewLdapError(fmt.Errorf("向LDAP更新分组失败:" + err.Error())) } - //若配置了不允许修改分组名称,则不更新分组名称 - if !config.Conf.Ldap.LdapGroupNameModify { - group.GroupName = oldGroupName - } - err = isql.Group.Update(&group) + err = isql.Group.Update(&newGroup) if err != nil { return nil, tools.NewLdapError(fmt.Errorf("向MySQL更新分组失败")) } @@ -192,7 +194,7 @@ func (l GroupLogic) Delete(c *gin.Context, req interface{}) (data interface{}, r for _, id := range r.GroupIds { filter := tools.H{"id": int(id)} if !isql.Group.Exist(filter) { - return nil, tools.NewMySqlError(fmt.Errorf("分组不存在")) + return nil, tools.NewMySqlError(fmt.Errorf("有分组不存在")) } } @@ -200,28 +202,26 @@ func (l GroupLogic) Delete(c *gin.Context, req interface{}) (data interface{}, r if err != nil { return nil, tools.NewMySqlError(fmt.Errorf("获取分组列表失败: %s", err.Error())) } + for _, group := range groups { // 判断存在子分组,不允许删除 filter := tools.H{"parent_id": int(group.ID)} if isql.Group.Exist(filter) { - return nil, tools.NewMySqlError(fmt.Errorf("存在子分组,不允许删除!")) + return nil, tools.NewMySqlError(fmt.Errorf("存在子分组,请先删除子分组,再执行该分组的删除操作!")) } - dn, err := isql.Group.GetGroupDn(group.ID, "") - if err != nil { - return nil, err.Error() - } - gdn := fmt.Sprintf("%s,%s", dn, config.Conf.Ldap.LdapBaseDN) - err = ildap.Group.Delete(gdn) + + // 删除的时候先从ldap进行删除 + err = ildap.Group.Delete(group.GroupDN) if err != nil { return nil, tools.NewLdapError(fmt.Errorf("向LDAP删除分组失败:" + err.Error())) } } - // 删除接口 - err = isql.Group.Delete(r.GroupIds) + + // 从MySQL中删除 + err = isql.Group.Delete(groups) if err != nil { return nil, tools.NewMySqlError(fmt.Errorf("删除接口失败: %s", err.Error())) } - // TODO: 删除用户组关系 return nil, nil } @@ -251,28 +251,24 @@ func (l GroupLogic) AddUser(c *gin.Context, req interface{}) (data interface{}, return nil, tools.NewMySqlError(fmt.Errorf("获取分组失败: %s", err.Error())) } - for _, user := range users { - gdn, err := isql.Group.GetGroupDn(group.ID, "") - if err != nil { - return nil, err.Error() - } - gdn = fmt.Sprintf("%s,%s", gdn, config.Conf.Ldap.LdapBaseDN) - udn := config.Conf.Ldap.LdapAdminDN - if user.Username != "admin" { - udn = fmt.Sprintf("uid=%s,%s", user.Username, config.Conf.Ldap.LdapUserDN) - } - err = ildap.Group.AddUserToGroup(gdn, udn) - - if err != nil { - return nil, tools.NewLdapError(fmt.Errorf("向LDAP添加用户到分组失败" + err.Error())) - } + if group.GroupDN[:3] == "ou=" { + return nil, tools.NewMySqlError(fmt.Errorf("ou类型的分组不能添加用户")) } + // 先添加到MySQL err = isql.Group.AddUserToGroup(group, users) if err != nil { return nil, tools.NewMySqlError(fmt.Errorf("添加用户到分组失败: %s", err.Error())) } + // 再往ldap添加 + for _, user := range users { + err = ildap.Group.AddUserToGroup(group.GroupDN, user.UserDN) + if err != nil { + return nil, tools.NewLdapError(fmt.Errorf("向LDAP添加用户到分组失败" + err.Error())) + } + } + return nil, nil } @@ -300,17 +296,20 @@ func (l GroupLogic) RemoveUser(c *gin.Context, req interface{}) (data interface{ if err != nil { return nil, tools.NewMySqlError(fmt.Errorf("获取分组失败: %s", err.Error())) } - gdn, err := isql.Group.GetGroupDn(r.GroupID, "") - if err != nil { - return nil, tools.NewMySqlError(fmt.Errorf("获取分组失败: %s", err.Error())) + + if group.GroupDN[:3] == "ou=" { + return nil, tools.NewMySqlError(fmt.Errorf("ou类型的分组内没有用户")) } - gdn = fmt.Sprintf("%s,%s", gdn, config.Conf.Ldap.LdapBaseDN) + + // 先操作ldap for _, user := range users { - err := ildap.Group.RemoveUserFromGroup(gdn, user.Username) + err := ildap.Group.RemoveUserFromGroup(group.GroupDN, user.UserDN) if err != nil { return nil, tools.NewLdapError(fmt.Errorf("将用户从ldap移除失败" + err.Error())) } } + + // 再操作MySQL err = isql.Group.RemoveUserFromGroup(group, users) if err != nil { return nil, tools.NewMySqlError(fmt.Errorf("将用户从MySQL移除失败: %s", err.Error())) diff --git a/logic/menu_logic.go b/logic/menu_logic.go index 8436287..26a0390 100644 --- a/logic/menu_logic.go +++ b/logic/menu_logic.go @@ -4,9 +4,9 @@ import ( "fmt" "github.com/eryajf/go-ldap-admin/model" + "github.com/eryajf/go-ldap-admin/model/request" "github.com/eryajf/go-ldap-admin/public/tools" "github.com/eryajf/go-ldap-admin/service/isql" - "github.com/eryajf/go-ldap-admin/svc/request" "github.com/gin-gonic/gin" ) diff --git a/logic/operation_log_logic.go b/logic/operation_log_logic.go index 7df3973..e89527d 100644 --- a/logic/operation_log_logic.go +++ b/logic/operation_log_logic.go @@ -4,10 +4,10 @@ import ( "fmt" "github.com/eryajf/go-ldap-admin/model" + "github.com/eryajf/go-ldap-admin/model/request" + "github.com/eryajf/go-ldap-admin/model/response" "github.com/eryajf/go-ldap-admin/public/tools" "github.com/eryajf/go-ldap-admin/service/isql" - "github.com/eryajf/go-ldap-admin/svc/request" - "github.com/eryajf/go-ldap-admin/svc/response" "github.com/gin-gonic/gin" ) diff --git a/logic/role_logic.go b/logic/role_logic.go index f6e8ed9..52eaa51 100644 --- a/logic/role_logic.go +++ b/logic/role_logic.go @@ -4,11 +4,11 @@ import ( "fmt" "github.com/eryajf/go-ldap-admin/model" + "github.com/eryajf/go-ldap-admin/model/request" + "github.com/eryajf/go-ldap-admin/model/response" "github.com/eryajf/go-ldap-admin/public/common" "github.com/eryajf/go-ldap-admin/public/tools" "github.com/eryajf/go-ldap-admin/service/isql" - "github.com/eryajf/go-ldap-admin/svc/request" - "github.com/eryajf/go-ldap-admin/svc/response" "github.com/gin-gonic/gin" "github.com/thoas/go-funk" diff --git a/logic/user_logic.go b/logic/user_logic.go index 394ff9b..512b9c7 100644 --- a/logic/user_logic.go +++ b/logic/user_logic.go @@ -1,16 +1,15 @@ package logic import ( - "errors" "fmt" "github.com/eryajf/go-ldap-admin/config" "github.com/eryajf/go-ldap-admin/model" + "github.com/eryajf/go-ldap-admin/model/request" + "github.com/eryajf/go-ldap-admin/model/response" "github.com/eryajf/go-ldap-admin/public/tools" "github.com/eryajf/go-ldap-admin/service/ildap" "github.com/eryajf/go-ldap-admin/service/isql" - "github.com/eryajf/go-ldap-admin/svc/request" - "github.com/eryajf/go-ldap-admin/svc/response" "github.com/gin-gonic/gin" "github.com/thoas/go-funk" @@ -51,7 +50,7 @@ func (l UserLogic) Add(c *gin.Context, req interface{}) (data interface{}, rspEr return nil, tools.NewValidatorError(fmt.Errorf("密码长度至少为6位")) } } else { - r.Password = "123456" + r.Password = config.Conf.Ldap.LdapUserInitPassword } // 当前登陆用户角色排序最小值(最高等级角色)以及当前登陆的用户 @@ -81,7 +80,7 @@ func (l UserLogic) Add(c *gin.Context, req interface{}) (data interface{}, rspEr if currentRoleSortMin >= reqRoleSortMin { return nil, tools.NewValidatorError(fmt.Errorf("用户不能创建比自己等级高的或者相同等级的用户")) } - deptIds := tools.SliceToString(r.DepartmentId, ",") + user := model.User{ Username: r.Username, Password: r.Password, @@ -97,58 +96,19 @@ func (l UserLogic) Add(c *gin.Context, req interface{}) (data interface{}, rspEr Introduction: r.Introduction, Status: r.Status, Creator: ctxUser.Username, - DepartmentId: deptIds, + DepartmentId: tools.SliceToString(r.DepartmentId, ","), Source: r.Source, Roles: roles, + UserDN: fmt.Sprintf("uid=%s,%s", r.Username, config.Conf.Ldap.LdapUserDN), } + if user.Source == "" { user.Source = "platform" } - //先识别用户选择的部门是否是OU开头 - gdns := make(map[uint]string) - for _, deptId := range r.DepartmentId { - dn, err := isql.Group.GetGroupDn(deptId, "") - if err != nil { - return nil, err.Error() - } - gdn := fmt.Sprintf("%s,%s", dn, config.Conf.Ldap.LdapBaseDN) - if gdn[:3] == "ou=" { - return nil, errors.New("不能添加用户到OU组织单元") - } - gdns[deptId] = gdn - } - //先创建用户到默认分组 - err = ildap.User.Add(&user) + + err = CommonAddUser(&user, r.DepartmentId) if err != nil { - return nil, tools.NewLdapError(fmt.Errorf("向LDAP创建用户失败:" + err.Error())) - } - isExistUser := false - for deptId, gdn := range gdns { - //根据选择的部门,添加到部门内 - err = ildap.Group.AddUserToGroup(gdn, fmt.Sprintf("uid=%s,%s", user.Username, config.Conf.Ldap.LdapUserDN)) - if err != nil { - return nil, err.Error() - } - if !isExistUser { - err = isql.User.Add(&user) - if err != nil { - return nil, tools.NewMySqlError(fmt.Errorf("向MySQL创建用户失败:" + err.Error())) - } - isExistUser = true - } - //根据部门分配,将用户和部门信息维护到部门关系表里面 - users := []model.User{} - users = append(users, user) - depart := new(model.Group) - filter := tools.H{"id": deptId} - err = isql.Group.Find(filter, depart) - if err != nil { - return "", tools.NewMySqlError(err) - } - err = isql.Group.AddUserToGroup(depart, users) - if err != nil { - return nil, tools.NewMySqlError(fmt.Errorf("向MySQL添加用户到分组关系失败:" + err.Error())) - } + return nil, tools.NewOperationError(fmt.Errorf("添加用户失败" + err.Error())) } return nil, nil } @@ -233,7 +193,7 @@ func (l UserLogic) Update(c *gin.Context, req interface{}) (data interface{}, rs if err != nil { return nil, tools.NewMySqlError(err) } - deptIds := tools.SliceToString(r.DepartmentId, ",") + user := model.User{ Model: oldData.Model, Username: r.Username, @@ -248,9 +208,10 @@ func (l UserLogic) Update(c *gin.Context, req interface{}) (data interface{}, rs Position: r.Position, Introduction: r.Introduction, Creator: ctxUser.Username, - DepartmentId: deptIds, + DepartmentId: tools.SliceToString(r.DepartmentId, ","), Source: oldData.Source, Roles: roles, + UserDN: oldData.UserDN, } // 判断是更新自己还是更新别人,如果操作的ID与登陆用户的ID一致,则说明操作的是自己 @@ -275,117 +236,13 @@ func (l UserLogic) Update(c *gin.Context, req interface{}) (data interface{}, rs return nil, tools.NewValidatorError(fmt.Errorf("用户不能把别的用户角色等级更新得比自己高或相等")) } } - err = ildap.User.Update(oldData.Username, &user) - if err != nil { - return nil, tools.NewLdapError(fmt.Errorf("在LDAP更新用户失败:" + err.Error())) + if err = CommonUpdateUser(oldData, &user, r.DepartmentId); err != nil { + return nil, tools.NewOperationError(fmt.Errorf("更新用户失败" + err.Error())) } - // 更新用户 - if !config.Conf.Ldap.LdapUserNameModify { - user.Username = oldData.Username - } - err = isql.User.Update(&user) - if err != nil { - return nil, tools.NewMySqlError(fmt.Errorf("在MySQL更新用户失败:" + err.Error())) - } - //判断部门信息是否有变化有变化则更新相应的数据库 - oldDeptIds := tools.StringToSlice(oldData.DepartmentId, ",") - addDeptIds, removeDeptIds := tools.ArrUintCmp(oldDeptIds, r.DepartmentId) - for _, deptId := range removeDeptIds { - //从旧组中删除 - err = l.RemoveUserToGroup(deptId, []uint{r.ID}) - if err != nil { - return nil, err - } - } - for _, deptId := range addDeptIds { - //添加到新分组中 - err = l.AddUserToGroup(deptId, []uint{r.ID}) - if err != nil { - return nil, err - } - } return nil, nil } -// RemoveUser 移除用户 -func (l UserLogic) RemoveUserToGroup(groupId uint, userIds []uint) error { - filter := tools.H{"id": groupId} - - if !isql.Group.Exist(filter) { - return tools.NewMySqlError(fmt.Errorf("分组不存在")) - } - - users, err := isql.User.GetUserByIds(userIds) - if err != nil { - return tools.NewMySqlError(fmt.Errorf("获取用户列表失败: %s", err.Error())) - } - - group := new(model.Group) - err = isql.Group.Find(filter, group) - if err != nil { - return tools.NewMySqlError(fmt.Errorf("获取分组失败: %s", err.Error())) - } - gdn, err := isql.Group.GetGroupDn(groupId, "") - if err != nil { - return tools.NewMySqlError(fmt.Errorf("获取分组失败: %s", err.Error())) - } - gdn = fmt.Sprintf("%s,%s", gdn, config.Conf.Ldap.LdapBaseDN) - for _, user := range users { - err := ildap.Group.RemoveUserFromGroup(gdn, user.Username) - if err != nil { - return tools.NewLdapError(fmt.Errorf("将用户从ldap移除失败" + err.Error())) - } - } - err = isql.Group.RemoveUserFromGroup(group, users) - if err != nil { - return tools.NewMySqlError(fmt.Errorf("将用户从MySQL移除失败: %s", err.Error())) - } - - return nil -} - -//将用户添加到分组中 -func (l UserLogic) AddUserToGroup(groupId uint, userIds []uint) error { - filter := tools.H{"id": groupId} - - if !isql.Group.Exist(filter) { - return tools.NewMySqlError(fmt.Errorf("分组不存在")) - } - - users, err := isql.User.GetUserByIds(userIds) - if err != nil { - return tools.NewMySqlError(fmt.Errorf("获取用户列表失败: %s", err.Error())) - } - - group := new(model.Group) - err = isql.Group.Find(filter, group) - if err != nil { - return tools.NewMySqlError(fmt.Errorf("获取分组失败: %s", err.Error())) - } - for _, user := range users { - gdn, err := isql.Group.GetGroupDn(group.ID, "") - if err != nil { - return err - } - gdn = fmt.Sprintf("%s,%s", gdn, config.Conf.Ldap.LdapBaseDN) - udn := config.Conf.Ldap.LdapAdminDN - if user.Username != "admin" { - udn = fmt.Sprintf("uid=%s,%s", user.Username, config.Conf.Ldap.LdapUserDN) - } - err = ildap.Group.AddUserToGroup(gdn, udn) - - if err != nil { - return tools.NewLdapError(fmt.Errorf("向LDAP添加用户到分组失败" + err.Error())) - } - } - err = isql.Group.AddUserToGroup(group, users) - if err != nil { - return tools.NewMySqlError(fmt.Errorf("添加用户到分组失败: %s", err.Error())) - } - return nil -} - // Delete 删除数据 func (l UserLogic) Delete(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) { r, ok := req.(*request.UserDeleteReq) @@ -394,6 +251,13 @@ func (l UserLogic) Delete(c *gin.Context, req interface{}) (data interface{}, rs } _ = c + for _, id := range r.UserIds { + filter := tools.H{"id": int(id)} + if !isql.User.Exist(filter) { + return nil, tools.NewMySqlError(fmt.Errorf("有用户不存在")) + } + } + // 根据用户ID获取用户角色排序最小值 roleMinSortList, err := isql.User.GetUserMinRoleSortsByIds(r.UserIds) // TODO: 这里应该复用下边的 GetUserByIds 方法 if err != nil || len(roleMinSortList) == 0 { @@ -423,13 +287,16 @@ func (l UserLogic) Delete(c *gin.Context, req interface{}) (data interface{}, rs if err != nil { return nil, tools.NewMySqlError(fmt.Errorf("获取用户信息失败: " + err.Error())) } + + // 先将用户从ldap中删除 for _, user := range users { - err := ildap.User.Delete(user.Username) + err := ildap.User.Delete(user.UserDN) if err != nil { return nil, tools.NewLdapError(fmt.Errorf("在LDAP删除用户失败" + err.Error())) } } + // 再将用户从MySQL中删除 err = isql.User.Delete(r.UserIds) if err != nil { return nil, tools.NewMySqlError(fmt.Errorf("在MySQL删除用户失败: " + err.Error())) @@ -473,7 +340,7 @@ func (l UserLogic) ChangePwd(c *gin.Context, req interface{}) (data interface{}, return nil, tools.NewValidatorError(fmt.Errorf("原密码错误")) } // ldap更新密码时可以直接指定用户DN和新密码即可更改成功 - err = ildap.User.ChangePwd(user.Username, "", r.NewPassword) + err = ildap.User.ChangePwd(user.UserDN, "", r.NewPassword) if err != nil { return nil, tools.NewLdapError(fmt.Errorf("在LDAP更新密码失败" + err.Error())) } @@ -524,7 +391,7 @@ func (l UserLogic) ChangeUserStatus(c *gin.Context, req interface{}) (data inter } if r.Status == 2 { - err = ildap.User.Delete(user.Username) + err = ildap.User.Delete(user.UserDN) if err != nil { return nil, tools.NewLdapError(fmt.Errorf("在LDAP删除用户失败" + err.Error())) } diff --git a/main.go b/main.go index fb29523..cae33bd 100644 --- a/main.go +++ b/main.go @@ -3,14 +3,14 @@ package main import ( "context" "fmt" - "github.com/eryajf/go-ldap-admin/logic" - "github.com/robfig/cron/v3" "net/http" "os" "os/signal" - "syscall" "time" + "github.com/eryajf/go-ldap-admin/logic" + "github.com/robfig/cron/v3" + "github.com/eryajf/go-ldap-admin/config" "github.com/eryajf/go-ldap-admin/middleware" "github.com/eryajf/go-ldap-admin/public/common" @@ -68,16 +68,21 @@ func main() { if config.Conf.DingTalk.DingTalkEnableSync { //启动定时任务 c := cron.New(cron.WithSeconds()) - c.AddFunc("0 1 0 * * *", func() { + _, err := c.AddFunc("0 1 0 * * *", func() { common.Log.Info("每天0点1分0秒执行一次同步钉钉部门和用户信息到ldap") - logic.DingTalk.DsyncDingTalkDepts(nil, nil) + logic.DingTalk.SyncDingTalkDepts(nil, nil) }) + if err != nil { + common.Log.Errorf("启动同步部门的定时任务失败: %v", err) + } //每天凌晨1点执行一次 - c.AddFunc("0 15 0 * * *", func() { + _, err = c.AddFunc("0 15 0 * * *", func() { common.Log.Info("每天凌晨00点15分执行一次同步钉钉部门和用户信息到ldap") logic.DingTalk.SyncDingTalkUsers(nil, nil) }) - + if err != nil { + common.Log.Errorf("启动同步用户的定时任务失败: %v", err) + } c.Start() } @@ -85,11 +90,12 @@ func main() { // Wait for interrupt signal to gracefully shutdown the server with // a timeout of 5 seconds. - quit := make(chan os.Signal) + quit := make(chan os.Signal, 1) // kill (no param) default send syscall.SIGTERM // kill -2 is syscall.SIGINT // kill -9 is syscall.SIGKILL but can't be catch, so don't need add it - signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) + // signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) + signal.Notify(quit, os.Interrupt) <-quit common.Log.Info("Shutting down server...") diff --git a/middleware/AuthMiddleware.go b/middleware/AuthMiddleware.go index b63e81f..d5bffa7 100644 --- a/middleware/AuthMiddleware.go +++ b/middleware/AuthMiddleware.go @@ -11,8 +11,8 @@ import ( "time" - "github.com/eryajf/go-ldap-admin/svc/request" - "github.com/eryajf/go-ldap-admin/svc/response" + "github.com/eryajf/go-ldap-admin/model/request" + "github.com/eryajf/go-ldap-admin/model/response" jwt "github.com/appleboy/gin-jwt/v2" "github.com/gin-gonic/gin" diff --git a/middleware/CORSMiddleware.go b/middleware/CORSMiddleware.go index efa699c..a5d5380 100644 --- a/middleware/CORSMiddleware.go +++ b/middleware/CORSMiddleware.go @@ -14,7 +14,7 @@ func CORSMiddleware() gin.HandlerFunc { method := c.Request.Method //请求方法 origin := c.Request.Header.Get("Origin") //请求头部 var headerKeys []string // 声明请求头keys - for k, _ := range c.Request.Header { + for k := range c.Request.Header { headerKeys = append(headerKeys, k) } headerStr := strings.Join(headerKeys, ", ") @@ -41,5 +41,6 @@ func CORSMiddleware() gin.HandlerFunc { } // 处理请求 c.Next() // 处理请求 + _ = headerStr } } diff --git a/middleware/OperationLogMiddleware.go b/middleware/OperationLogMiddleware.go index a54a3e5..04708d8 100644 --- a/middleware/OperationLogMiddleware.go +++ b/middleware/OperationLogMiddleware.go @@ -31,15 +31,13 @@ func OperationLogMiddleware() gin.HandlerFunc { // 获取当前登录用户 var username string - ctxUser, exists := c.Get("user") - if !exists { - username = "未登录" - } + ctxUser, _ := c.Get("user") user, ok := ctxUser.(model.User) if !ok { username = "未登录" + } else { + username = user.Username } - username = user.Username // 获取访问路径 path := strings.TrimPrefix(c.FullPath(), "/"+config.Conf.System.UrlPathPrefix) diff --git a/middleware/RateLimitMiddleware.go b/middleware/RateLimitMiddleware.go index c5bee72..03fe040 100644 --- a/middleware/RateLimitMiddleware.go +++ b/middleware/RateLimitMiddleware.go @@ -3,7 +3,7 @@ package middleware import ( "time" - "github.com/eryajf/go-ldap-admin/svc/response" + "github.com/eryajf/go-ldap-admin/model/response" "github.com/gin-gonic/gin" "github.com/juju/ratelimit" diff --git a/model/group.go b/model/group.go index e7f9c49..3b55e2d 100644 --- a/model/group.go +++ b/model/group.go @@ -15,4 +15,5 @@ type Group struct { SourceDeptParentId string `gorm:"type:varchar(100);comment:'父部门编号'" json:"sourceDeptParentId"` SourceUserNum int `gorm:"default:0;comment:'部门下的用户数量,从第三方获取的数据'" json:"source_user_num"` Children []*Group `gorm:"-" json:"children"` + GroupDN string `gorm:"type:varchar(255);not null;comment:'分组dn'" json:"groupDn"` // 分组在ldap的dn } diff --git a/svc/request/api_req.go b/model/request/api_req.go similarity index 100% rename from svc/request/api_req.go rename to model/request/api_req.go diff --git a/svc/request/base_req.go b/model/request/base_req.go similarity index 100% rename from svc/request/base_req.go rename to model/request/base_req.go diff --git a/svc/request/group_req.go b/model/request/group_req.go similarity index 100% rename from svc/request/group_req.go rename to model/request/group_req.go diff --git a/svc/request/menu_req.go b/model/request/menu_req.go similarity index 100% rename from svc/request/menu_req.go rename to model/request/menu_req.go diff --git a/svc/request/operation_log_req.go b/model/request/operation_log_req.go similarity index 100% rename from svc/request/operation_log_req.go rename to model/request/operation_log_req.go diff --git a/svc/request/role_req.go b/model/request/role_req.go similarity index 100% rename from svc/request/role_req.go rename to model/request/role_req.go diff --git a/svc/request/user_req.go b/model/request/user_req.go similarity index 100% rename from svc/request/user_req.go rename to model/request/user_req.go diff --git a/svc/response/api_rsp.go b/model/response/api_rsp.go similarity index 100% rename from svc/response/api_rsp.go rename to model/response/api_rsp.go diff --git a/svc/response/base_rsp.go b/model/response/base_rsp.go similarity index 100% rename from svc/response/base_rsp.go rename to model/response/base_rsp.go diff --git a/svc/response/common_rsp.go b/model/response/common_rsp.go similarity index 100% rename from svc/response/common_rsp.go rename to model/response/common_rsp.go diff --git a/svc/response/group_rsp.go b/model/response/group_rsp.go similarity index 100% rename from svc/response/group_rsp.go rename to model/response/group_rsp.go diff --git a/svc/response/menu_rsp.go b/model/response/menu_rsp.go similarity index 100% rename from svc/response/menu_rsp.go rename to model/response/menu_rsp.go diff --git a/svc/response/operation_log_rsp.go b/model/response/operation_log_rsp.go similarity index 100% rename from svc/response/operation_log_rsp.go rename to model/response/operation_log_rsp.go diff --git a/svc/response/role_rsp.go b/model/response/role_rsp.go similarity index 100% rename from svc/response/role_rsp.go rename to model/response/role_rsp.go diff --git a/svc/response/user_rsp.go b/model/response/user_rsp.go similarity index 100% rename from svc/response/user_rsp.go rename to model/response/user_rsp.go diff --git a/model/user.go b/model/user.go index f2f10ae..f5f44c1 100644 --- a/model/user.go +++ b/model/user.go @@ -4,23 +4,24 @@ import "gorm.io/gorm" type User struct { gorm.Model - Username string `gorm:"type:varchar(50);not null;unique;comment:'用户名'" json:"username"` // 用户名 - Password string `gorm:"size:255;not null;comment:'用户密码'" json:"password"` // 用户密码 - Nickname string `gorm:"type:varchar(50);comment:'中文名'" json:"nickname"` // 昵称 - GivenName string `gorm:"type:varchar(50);comment:'花名'" json:"givenName"` // 花名,如果有的话,没有的话用昵称占位 - Mail string `gorm:"type:varchar(100);comment:'邮箱'" json:"mail"` // 邮箱 - JobNumber string `gorm:"type:varchar(20);comment:'工号'" json:"jobNumber"` // 工号 - Mobile string `gorm:"type:varchar(11);not null;unique;comment:'手机号'" json:"mobile"` // 手机号 - Avatar string `gorm:"type:varchar(255);comment:'头像'" json:"avatar"` // 头像 - PostalAddress string `gorm:"type:varchar(255);comment:'地址'" json:"postalAddress"` // 地址 - Departments string `gorm:"type:varchar(128);comment:'部门'" json:"departments"` // 部门 - Position string `gorm:"type:varchar(128);comment:'职位'" json:"position"` // 职位 - Introduction string `gorm:"type:varchar(255);comment:'个人简介'" json:"introduction"` // 个人简介 - Status uint `gorm:"type:tinyint(1);default:1;comment:'状态:1在职, 2离职'" json:"status"` // 状态 - Creator string `gorm:"type:varchar(20);;comment:'创建者'" json:"creator"` // 创建者 - Source string `gorm:"type:varchar(50);comment:'用户来源:dingTalk、weCom、ldap、platform'" json:"source"` // 来源 - DepartmentId string `gorm:"type:varchar(100);not null;comment:'部门id'" json:"departmentId"` // 部门id - Roles []*Role `gorm:"many2many:user_roles" json:"roles"` // 角色 - SourceUserId string `gorm:"type:varchar(100);not null;comment:'第三方用户id'" json:"sourceUserId"` // 第三方用户id - SourceUnionId string `gorm:"type:varchar(100);not null;comment:'第三方唯一unionId'" json:"sourceUnionId"` // 第三方唯一unionId + Username string `gorm:"type:varchar(50);not null;unique;comment:'用户名'" json:"username"` // 用户名 + Password string `gorm:"size:255;not null;comment:'用户密码'" json:"password"` // 用户密码 + Nickname string `gorm:"type:varchar(50);comment:'中文名'" json:"nickname"` // 昵称 + GivenName string `gorm:"type:varchar(50);comment:'花名'" json:"givenName"` // 花名,如果有的话,没有的话用昵称占位 + Mail string `gorm:"type:varchar(100);comment:'邮箱'" json:"mail"` // 邮箱 + JobNumber string `gorm:"type:varchar(20);comment:'工号'" json:"jobNumber"` // 工号 + Mobile string `gorm:"type:varchar(11);not null;unique;comment:'手机号'" json:"mobile"` // 手机号 + Avatar string `gorm:"type:varchar(255);comment:'头像'" json:"avatar"` // 头像 + PostalAddress string `gorm:"type:varchar(255);comment:'地址'" json:"postalAddress"` // 地址 + Departments string `gorm:"type:varchar(128);comment:'部门'" json:"departments"` // 部门 + Position string `gorm:"type:varchar(128);comment:'职位'" json:"position"` // 职位 + Introduction string `gorm:"type:varchar(255);comment:'个人简介'" json:"introduction"` // 个人简介 + Status uint `gorm:"type:tinyint(1);default:1;comment:'状态:1在职, 2离职'" json:"status"` // 状态 + Creator string `gorm:"type:varchar(20);;comment:'创建者'" json:"creator"` // 创建者 + Source string `gorm:"type:varchar(50);comment:'用户来源:dingTalk、wecom、feishu、ldap、platform'" json:"source"` // 来源 + DepartmentId string `gorm:"type:varchar(100);not null;comment:'部门id'" json:"departmentId"` // 部门id + Roles []*Role `gorm:"many2many:user_roles" json:"roles"` // 角色 + SourceUserId string `gorm:"type:varchar(100);not null;comment:'第三方用户id'" json:"sourceUserId"` // 第三方用户id + SourceUnionId string `gorm:"type:varchar(100);not null;comment:'第三方唯一unionId'" json:"sourceUnionId"` // 第三方唯一unionId + UserDN string `gorm:"type:varchar(255);not null;comment:'用户dn'" json:"userDn"` // 用户在ldap的dn } diff --git a/public/client/dingtalk/client.go b/public/client/dingtalk/client.go new file mode 100644 index 0000000..56bd113 --- /dev/null +++ b/public/client/dingtalk/client.go @@ -0,0 +1,53 @@ +package dingtalk + +import ( + "github.com/eryajf/go-ldap-admin/config" + "github.com/eryajf/go-ldap-admin/public/common" + "github.com/zhaoyunxing92/dingtalk/v2" +) + +func InitDingTalkClient() *dingtalk.DingTalk { + dingTalk, err := dingtalk.NewClient(config.Conf.DingTalk.DingTalkAppKey, config.Conf.DingTalk.DingTalkAppSecret) + if err != nil { + common.Log.Error("init dingding client failed, err:%v\n", err) + } + return dingTalk +} + +// 部门结构体 +type DingTalkDept struct { + Id int `json:"dept_id"` // 部门ID + Name string `json:"name"` // 部门名称拼音 + Remark string `json:"remark"` // 部门中文名 + ParentId int `json:"parent_id"` // 父部门ID +} + +// DingTalkUser 部门用户详情 +type DingTalkUser struct { + UserId string `json:"userid"` + UnionId string `json:"unionid"` // 员工在当前开发者企业账号范围内的唯一标识 + Name string `json:"name"` // 员工名称 + Avatar string `json:"avatar"` // 头像 + StateCode string `json:"state_code"` // 国际电话区号 + ManagerUserId string `json:"manager_userid"` // 员工的直属主管 + Mobile string `json:"mobile"` // 手机号码 + HideMobile bool `json:"hide_mobile"` // 是否号码隐藏 + Telephone string `json:"telephone"` // 分机号 + JobNumber string `json:"job_number"` // 员工工号 + Title string `json:"title"` // 职位 + WorkPlace string `json:"work_place"` // 办公地点 + Remark string `json:"remark"` // 备注 + LoginId string `json:"loginId"` // 专属帐号登录名 + DeptIds []int `json:"dept_id_list"` // 所属部门ID列表 + DeptOrder int `json:"dept_order"` // 员工在部门中的排序 + Extension string `json:"extension"` // 员工在对应的部门中的排序 + HiredDate int `json:"hired_date"` // 入职时间 + Active bool `json:"active"` // 是否激活了钉钉 + Admin bool `json:"admin"` //是否为企业的管理员: + Boss bool `json:"boss"` // 是否为企业的老板 + ExclusiveAccount bool `json:"exclusive_account"` // 是否专属帐号 + Leader bool `json:"leader"` // 是否是部门的主管 + ExclusiveAccountType string `json:"exclusive_account_type"` //专属帐号类型:sso:企业自建专属帐号 dingtalk:钉钉自建专属帐号 + OrgEmail string `json:"org_email"` //员工的企业邮箱,如果员工的企业邮箱没有开通,返回信息中不包含该数据 + Email string `json:"email"` //员工邮箱,企业内部应用如果没有返回该字段,需要检查当前应用通讯录权限中邮箱等个人信息权限是否开启,员工信息面板中有邮箱字段值才返回该字段,第三方企业应用不返回该参数 +} diff --git a/public/client/dingtalk/dingtalk.go b/public/client/dingtalk/dingtalk.go new file mode 100644 index 0000000..80f7ab5 --- /dev/null +++ b/public/client/dingtalk/dingtalk.go @@ -0,0 +1,107 @@ +package dingtalk + +import ( + "strings" + + "github.com/mozillazg/go-pinyin" + "github.com/zhaoyunxing92/dingtalk/v2/request" +) + +func GetDingTalkAllDepts(deptId int) (result []*DingTalkDept, err error) { + depts, err := InitDingTalkClient().FetchDeptList(deptId, true, "zh_CN") + if err != nil { + return result, err + } + + for _, dept := range depts.Dept { + result = append(result, &DingTalkDept{ + Id: dept.Id, + Name: strings.Join(pinyin.LazyConvert(dept.Name, nil), ""), + Remark: dept.Name, + ParentId: dept.ParentId, + }) + } + return +} + +func GetDingTalkAllUsers() (result []*DingTalkUser, err error) { + depts, err := GetDingTalkAllDepts(1) + if err != nil { + return nil, err + } + + for _, dept := range depts { + r := request.DeptDetailUserInfo{ + DeptId: dept.Id, + Cursor: 0, + Size: 99, + Language: "zh_CN", + } + for { + //获取钉钉部门人员信息 + rsp, err := InitDingTalkClient().GetDeptDetailUserInfo(&r) + if err != nil { + return nil, err + } + for _, user := range rsp.DeptDetailUsers { + result = append(result, &DingTalkUser{ + UserId: user.UserId, + UnionId: user.UnionId, + Name: user.Name, + Avatar: user.Avatar, + StateCode: user.StateCode, + ManagerUserId: user.ManagerUserId, + Mobile: user.Mobile, + HideMobile: user.HideMobile, + Telephone: user.Telephone, + JobNumber: user.JobNumber, + Title: user.Title, + WorkPlace: user.WorkPlace, + Remark: user.Remark, + LoginId: user.LoginId, + DeptIds: user.DeptIds, + DeptOrder: user.DeptOrder, + Extension: user.Extension, + HiredDate: user.HiredDate, + Active: user.Active, + Admin: user.Admin, + Boss: user.Boss, + ExclusiveAccount: user.ExclusiveAccount, + Leader: user.Leader, + ExclusiveAccountType: user.ExclusiveAccountType, + OrgEmail: user.OrgEmail, + Email: user.Email, + }) + } + if !rsp.HasMore { + break + } + r.Cursor = rsp.NextCursor + } + } + return +} + +func GetDingTalkLeaveUserIds() ([]string, error) { + var ids []string + ReqParm := struct { + Cursor int `json:"cursor"` + Size int `json:"size"` + }{ + Cursor: 0, + Size: 50, + } + + for { + rsp, err := InitDingTalkClient().GetHrmResignEmployeeIds(ReqParm.Cursor, ReqParm.Size) + if err != nil { + return nil, err + } + ids = append(ids, rsp.UserIds...) + if rsp.NextCursor == 0 { + break + } + ReqParm.Cursor = rsp.NextCursor + } + return ids, nil +} diff --git a/public/common/database.go b/public/common/database.go index 120d7cb..dc439d4 100644 --- a/public/common/database.go +++ b/public/common/database.go @@ -63,7 +63,7 @@ func InitMysql() { // 自动迁移表结构 func dbAutoMigrate() { - DB.AutoMigrate( + _ = DB.AutoMigrate( &model.User{}, &model.Role{}, &model.Group{}, diff --git a/public/common/init_mysql_data.go b/public/common/init_mysql_data.go index 0c8634e..e467d62 100644 --- a/public/common/init_mysql_data.go +++ b/public/common/init_mysql_data.go @@ -2,6 +2,7 @@ package common import ( "errors" + "fmt" "github.com/eryajf/go-ldap-admin/config" "github.com/eryajf/go-ldap-admin/model" @@ -228,6 +229,7 @@ func InitData() { Status: 1, Creator: "系统", Roles: roles[:1], + UserDN: config.Conf.Ldap.LdapAdminDN, }, } @@ -618,57 +620,85 @@ func InitData() { newGroups := make([]model.Group, 0) groups := []model.Group{ { - Model: gorm.Model{ID: 1}, - GroupName: "eryajf", - Remark: "二丫讲梵有限公司", - Creator: "系统", - GroupType: "ou", - ParentId: 0, + Model: gorm.Model{ID: 1}, + GroupName: config.Conf.DingTalk.DingTalkFlag + "root", + Remark: "钉钉根部门", + Creator: "system", + GroupType: "ou", + ParentId: 0, + SourceDeptId: fmt.Sprintf("%s_%d", config.Conf.DingTalk.DingTalkFlag, 1), + Source: config.Conf.DingTalk.DingTalkFlag, + SourceDeptParentId: fmt.Sprintf("%s_%d", config.Conf.DingTalk.DingTalkFlag, 0), + GroupDN: fmt.Sprintf("ou=%s,%s", config.Conf.DingTalk.DingTalkFlag+"root", config.Conf.Ldap.LdapBaseDN), }, { - Model: gorm.Model{ID: 2}, - GroupName: "jenkins", - Remark: "Jenkins对应权限组管理", - Creator: "系统", - GroupType: "ou", - ParentId: 0, + Model: gorm.Model{ID: 2}, + GroupName: "wecomroot", + Remark: "企业微信根部门", + Creator: "system", + GroupType: "ou", + ParentId: 0, + SourceDeptId: "wechatwork_1", + Source: "wechatwork", + SourceDeptParentId: "wechatwork_0", + GroupDN: fmt.Sprintf("ou=%s,%s", "wechatworkroot", config.Conf.Ldap.LdapBaseDN), }, { - Model: gorm.Model{ID: 3}, - GroupName: "ceshizu", - Remark: "测试组", - Creator: "系统", - GroupType: "cn", - Users: users[:1], - ParentId: 1, - }, - { - Model: gorm.Model{ID: 4}, - GroupName: "yunweizu", - Remark: "运维组", - Creator: "系统", - GroupType: "cn", - Users: users[:1], - ParentId: 1, - }, - { - Model: gorm.Model{ID: 5}, - GroupName: "test-admin", - Remark: "admin测试环境", - Creator: "系统", - GroupType: "cn", - Users: users[:1], - ParentId: 2, - }, - { - Model: gorm.Model{ID: 6}, - GroupName: "prod-admin", - Remark: "admin正式环境", - Creator: "系统", - GroupType: "cn", - Users: users[:1], - ParentId: 2, + Model: gorm.Model{ID: 3}, + GroupName: "feishuroot", + Remark: "飞书根部门", + Creator: "system", + GroupType: "ou", + ParentId: 0, + SourceDeptId: "feishu_1", + Source: "feishu", + SourceDeptParentId: "feishu_0", + GroupDN: fmt.Sprintf("ou=%s,%s", "feishuroot", config.Conf.Ldap.LdapBaseDN), }, + // { + // Model: gorm.Model{ID: 2}, + // GroupName: "jenkins", + // Remark: "Jenkins对应权限组管理", + // Creator: "系统", + // GroupType: "ou", + // ParentId: 0, + // }, + // { + // Model: gorm.Model{ID: 3}, + // GroupName: "ceshizu", + // Remark: "测试组", + // Creator: "系统", + // GroupType: "cn", + // Users: users[:1], + // ParentId: 1, + // }, + // { + // Model: gorm.Model{ID: 4}, + // GroupName: "yunweizu", + // Remark: "运维组", + // Creator: "系统", + // GroupType: "cn", + // Users: users[:1], + // ParentId: 1, + // }, + // { + // Model: gorm.Model{ID: 5}, + // GroupName: "test-admin", + // Remark: "admin测试环境", + // Creator: "系统", + // GroupType: "cn", + // Users: users[:1], + // ParentId: 2, + // }, + // { + // Model: gorm.Model{ID: 6}, + // GroupName: "prod-admin", + // Remark: "admin正式环境", + // Creator: "系统", + // GroupType: "cn", + // Users: users[:1], + // ParentId: 2, + // }, } for _, group := range groups { diff --git a/public/common/ldap.go b/public/common/ldap.go index 6a2ec71..5b57d5a 100644 --- a/public/common/ldap.go +++ b/public/common/ldap.go @@ -10,7 +10,7 @@ import ( ldap "github.com/go-ldap/ldap/v3" ) -// 全局mysql数据库变量 +// 全局ldap数据库变量 var LDAP *ldap.Conn // Init 初始化连接 diff --git a/public/tools/slice_cmp.go b/public/tools/slice_cmp.go index e378649..be8e1b9 100644 --- a/public/tools/slice_cmp.go +++ b/public/tools/slice_cmp.go @@ -20,9 +20,9 @@ func ArrStrCmp(src []string, dest []string) ([]string, []string) { for _, v := range dest { l := len(mall) mall[v] = 1 - if l != len(mall) { //长度变化,即可以存 - l = len(mall) - } else { //存不了,进并集 + if l != len(mall) { + continue + } else { set = append(set, v) } } @@ -32,7 +32,7 @@ func ArrStrCmp(src []string, dest []string) ([]string, []string) { } //4.此时,mall是补集,所有元素去源中找,找到就是删除的,找不到的必定能在目数组中找到,即新加的 var added, deleted []string - for v, _ := range mall { + for v := range mall { _, exist := msrc[v] if exist { deleted = append(deleted, v) @@ -57,9 +57,9 @@ func ArrUintCmp(src []uint, dest []uint) ([]uint, []uint) { for _, v := range dest { l := len(mall) mall[v] = 1 - if l != len(mall) { //长度变化,即可以存 - l = len(mall) - } else { //存不了,进并集 + if l != len(mall) { + continue + } else { set = append(set, v) } } @@ -69,7 +69,7 @@ func ArrUintCmp(src []uint, dest []uint) ([]uint, []uint) { } //4.此时,mall是补集,所有元素去源中找,找到就是删除 var added, deleted []uint - for v, _ := range mall { + for v := range mall { _, exist := msrc[v] if exist { deleted = append(deleted, v) diff --git a/service/ildap/group_ildap.go b/service/ildap/group_ildap.go index a62c408..04f98e7 100644 --- a/service/ildap/group_ildap.go +++ b/service/ildap/group_ildap.go @@ -2,7 +2,6 @@ package ildap import ( "errors" - "fmt" "github.com/eryajf/go-ldap-admin/config" "github.com/eryajf/go-ldap-admin/model" @@ -14,13 +13,11 @@ import ( type GroupService struct{} // Add 添加资源 -func (x GroupService) Add(g *model.Group, pdn string) error { //organizationalUnit - parentDn := config.Conf.Ldap.LdapBaseDN - if pdn != "" { - parentDn = fmt.Sprintf("%s,%s", pdn, config.Conf.Ldap.LdapBaseDN) +func (x GroupService) Add(g *model.Group) error { //organizationalUnit + if g.Remark == "" { + g.Remark = g.GroupName } - dn := fmt.Sprintf("%s=%s,%s", g.GroupType, g.GroupName, parentDn) - add := ldap.NewAddRequest(dn, nil) + add := ldap.NewAddRequest(g.GroupDN, nil) if g.GroupType == "ou" { add.Attribute("objectClass", []string{"organizationalUnit", "top"}) // 如果定义了 groupOfNAmes,那么必须指定member,否则报错如下:object class 'groupOfNames' requires attribute 'member' } @@ -35,24 +32,16 @@ func (x GroupService) Add(g *model.Group, pdn string) error { //organizationalUn } // UpdateGroup 更新一个分组 -func (x GroupService) Update(g *model.Group, pdn string, oldGroupName, oldRemark string) error { - parentDn := "," + config.Conf.Ldap.LdapBaseDN - if pdn != "" { - parentDn = fmt.Sprintf("%s,%s", pdn, config.Conf.Ldap.LdapBaseDN) - } - //默认更新remark字段 - if g.Remark != oldRemark { - modify := ldap.NewModifyRequest(parentDn, nil) - modify.Replace("description", []string{g.Remark}) - err := common.LDAP.Modify(modify) - if err != nil { - return err - } +func (x GroupService) Update(oldGroup, newGroup *model.Group) error { + modify := ldap.NewModifyRequest(oldGroup.GroupDN, nil) + modify.Replace("description", []string{newGroup.Remark}) + err := common.LDAP.Modify(modify) + if err != nil { + return err } // 如果配置文件允许修改分组名称,且分组名称发生了变化,那么执行修改分组名称 - if config.Conf.Ldap.LdapGroupNameModify && g.GroupName != oldGroupName { - rdn := fmt.Sprintf("%s=%s", g.GroupType, g.GroupName) - modify := ldap.NewModifyDNRequest(parentDn, rdn, true, "") + if config.Conf.Ldap.LdapGroupNameModify && newGroup.GroupName != oldGroup.GroupName { + modify := ldap.NewModifyDNRequest(oldGroup.GroupDN, newGroup.GroupDN, true, "") err := common.LDAP.ModifyDN(modify) if err != nil { return err @@ -62,8 +51,8 @@ func (x GroupService) Update(g *model.Group, pdn string, oldGroupName, oldRemark } // Delete 删除资源 -func (x GroupService) Delete(pdn string) error { - del := ldap.NewDelRequest(pdn, nil) +func (x GroupService) Delete(gdn string) error { + del := ldap.NewDelRequest(gdn, nil) return common.LDAP.Del(del) } @@ -79,8 +68,7 @@ func (x GroupService) AddUserToGroup(dn, udn string) error { } // DelUserFromGroup 将用户从分组删除 -func (x GroupService) RemoveUserFromGroup(gdn, user string) error { - udn := fmt.Sprintf("uid=%s,%s", user, config.Conf.Ldap.LdapUserDN) +func (x GroupService) RemoveUserFromGroup(gdn, udn string) error { newmr := ldap.NewModifyRequest(gdn, nil) newmr.Delete("uniqueMember", []string{udn}) return common.LDAP.Modify(newmr) diff --git a/service/ildap/user_ildap.go b/service/ildap/user_ildap.go index 33c4ccd..7b1ce22 100644 --- a/service/ildap/user_ildap.go +++ b/service/ildap/user_ildap.go @@ -14,22 +14,7 @@ type UserService struct{} // 创建资源 func (x UserService) Add(user *model.User) error { - if user.Departments == "" { - user.Departments = "研发中心" - } - if user.GivenName == "" { - user.GivenName = user.Nickname - } - if user.PostalAddress == "" { - user.PostalAddress = "没有填写地址" - } - if user.Position == "" { - user.Position = "技术" - } - if user.Introduction == "" { - user.Introduction = user.Nickname - } - add := ldap.NewAddRequest(fmt.Sprintf("uid=%s,%s", user.Username, config.Conf.Ldap.LdapUserDN), nil) + add := ldap.NewAddRequest(user.UserDN, nil) add.Attribute("objectClass", []string{"inetOrgPerson"}) add.Attribute("cn", []string{user.Username}) add.Attribute("sn", []string{user.Nickname}) @@ -49,7 +34,7 @@ func (x UserService) Add(user *model.User) error { // Update 更新资源 func (x UserService) Update(oldusername string, user *model.User) error { - modify := ldap.NewModifyRequest(fmt.Sprintf("uid=%s,%s", oldusername, config.Conf.Ldap.LdapUserDN), nil) + modify := ldap.NewModifyRequest(user.UserDN, nil) modify.Replace("cn", []string{user.Nickname}) modify.Replace("sn", []string{oldusername}) modify.Replace("businessCategory", []string{user.Departments}) @@ -73,21 +58,17 @@ func (x UserService) Update(oldusername string, user *model.User) error { } // Delete 删除资源 -func (x UserService) Delete(username string) error { - del := ldap.NewDelRequest(fmt.Sprintf("uid=%s,%s", username, config.Conf.Ldap.LdapUserDN), nil) +func (x UserService) Delete(udn string) error { + del := ldap.NewDelRequest(udn, nil) return common.LDAP.Del(del) } // ChangePwd 修改用户密码,此处旧密码也可以为空,ldap可以直接通过用户DN加上新密码来进行修改 -func (u UserService) ChangePwd(username, oldpasswd, newpasswd string) error { - udn := fmt.Sprintf("uid=%s,%s", username, config.Conf.Ldap.LdapUserDN) - if username == "admin" { - udn = config.Conf.Ldap.LdapAdminDN - } +func (x UserService) ChangePwd(udn, oldpasswd, newpasswd string) error { modifyPass := ldap.NewPasswordModifyRequest(udn, oldpasswd, newpasswd) _, err := common.LDAP.PasswordModify(modifyPass) if err != nil { - return fmt.Errorf("password modify failed for %s, err: %v", username, err) + return fmt.Errorf("password modify failed for %s, err: %v", udn, err) } return nil } diff --git a/service/isql/api_isql.go b/service/isql/api_isql.go index 516426e..d7834c2 100644 --- a/service/isql/api_isql.go +++ b/service/isql/api_isql.go @@ -6,9 +6,9 @@ import ( "strings" "github.com/eryajf/go-ldap-admin/model" + "github.com/eryajf/go-ldap-admin/model/request" "github.com/eryajf/go-ldap-admin/public/common" "github.com/eryajf/go-ldap-admin/public/tools" - "github.com/eryajf/go-ldap-admin/svc/request" "gorm.io/gorm" ) @@ -124,7 +124,7 @@ func (s ApiService) Delete(ids []uint) error { api := new(model.Api) err := s.Find(tools.H{"id": id}, api) if err != nil { - return errors.New(fmt.Sprintf("未获取到ID为%d的用户", id)) + return fmt.Errorf("根据ID获取接口信息失败: %v", err) } apis = append(apis, *api) } diff --git a/service/isql/group_isql.go b/service/isql/group_isql.go index d1bdda7..9a93101 100644 --- a/service/isql/group_isql.go +++ b/service/isql/group_isql.go @@ -6,9 +6,9 @@ import ( "strings" "github.com/eryajf/go-ldap-admin/model" + "github.com/eryajf/go-ldap-admin/model/request" "github.com/eryajf/go-ldap-admin/public/common" "github.com/eryajf/go-ldap-admin/public/tools" - "github.com/eryajf/go-ldap-admin/svc/request" "gorm.io/gorm" ) @@ -87,30 +87,6 @@ func (s GroupService) ListAll(req *request.GroupListAllReq) ([]*model.Group, err return list, err } -// 拼装dn信息 -func (s GroupService) GetGroupDn(groupId uint, oldDn string) (dn string, e error) { - depart := new(model.Group) - filter := tools.H{"id": int(groupId)} - err := s.Find(filter, depart) - if err != nil { - return "", tools.NewMySqlError(err) - } - if oldDn == "" { - dn = fmt.Sprintf("%s=%s", depart.GroupType, depart.GroupName) - } else { - dn = fmt.Sprintf("%s,%s=%s", oldDn, depart.GroupType, depart.GroupName) - } - if depart.ParentId > 0 { - tempDn, err := s.GetGroupDn(depart.ParentId, dn) - if err != nil { - return dn, err - } - dn = tempDn - fmt.Println(tempDn) - } - return dn, nil -} - // GenGroupTree 生成分组树 func GenGroupTree(parentId uint, groups []*model.Group) []*model.Group { tree := make([]*model.Group, 0) @@ -155,8 +131,8 @@ func (s GroupService) Exist(filter map[string]interface{}) bool { } // Delete 批量删除 -func (s GroupService) Delete(ids []uint) error { - return common.DB.Where("id IN (?)", ids).Select("Users").Unscoped().Delete(&model.Group{}).Error +func (s GroupService) Delete(groups []*model.Group) error { + return common.DB.Debug().Select("Users").Unscoped().Delete(&groups).Error } // GetApisById 根据接口ID获取接口列表 @@ -177,12 +153,12 @@ func (s GroupService) RemoveUserFromGroup(group *model.Group, users []model.User // DingTalkDeptIdsToGroupIds 将钉钉部门id转换为分组id func (s GroupService) DingTalkDeptIdsToGroupIds(dingTalkIds []string) (groupIds []uint, err error) { - tempGroups := []model.Group{} + var tempGroups []model.Group err = common.DB.Model(&model.Group{}).Where("source_dept_id IN (?)", dingTalkIds).Find(&tempGroups).Error if err != nil { return nil, err } - tempGroupIds := []uint{} + var tempGroupIds []uint for _, g := range tempGroups { tempGroupIds = append(tempGroupIds, g.ID) } diff --git a/service/isql/operation_log_isql.go b/service/isql/operation_log_isql.go index d3405d8..a2cb0d9 100644 --- a/service/isql/operation_log_isql.go +++ b/service/isql/operation_log_isql.go @@ -6,9 +6,9 @@ import ( "strings" "github.com/eryajf/go-ldap-admin/model" + "github.com/eryajf/go-ldap-admin/model/request" "github.com/eryajf/go-ldap-admin/public/common" "github.com/eryajf/go-ldap-admin/public/tools" - "github.com/eryajf/go-ldap-admin/svc/request" "gorm.io/gorm" ) diff --git a/service/isql/role_isql.go b/service/isql/role_isql.go index 10a1f7e..338e0e7 100644 --- a/service/isql/role_isql.go +++ b/service/isql/role_isql.go @@ -6,9 +6,9 @@ import ( "strings" "github.com/eryajf/go-ldap-admin/model" + "github.com/eryajf/go-ldap-admin/model/request" "github.com/eryajf/go-ldap-admin/public/common" "github.com/eryajf/go-ldap-admin/public/tools" - "github.com/eryajf/go-ldap-admin/svc/request" "gorm.io/gorm" ) diff --git a/service/isql/user_isql.go b/service/isql/user_isql.go index d2076db..8406e68 100644 --- a/service/isql/user_isql.go +++ b/service/isql/user_isql.go @@ -7,9 +7,9 @@ import ( "time" "github.com/eryajf/go-ldap-admin/model" + "github.com/eryajf/go-ldap-admin/model/request" "github.com/eryajf/go-ldap-admin/public/common" "github.com/eryajf/go-ldap-admin/public/tools" - "github.com/eryajf/go-ldap-admin/svc/request" "github.com/gin-gonic/gin" "github.com/patrickmn/go-cache" @@ -197,21 +197,32 @@ func (s UserService) Delete(ids []uint) error { var users []model.User for _, id := range ids { // 根据ID获取用户 + filter := tools.H{"id": id} + user := new(model.User) - err := s.Find(map[string]interface{}{"id": id}, user) + err := s.Find(filter, user) if err != nil { - return errors.New(fmt.Sprintf("未获取到ID为%d的用户", id)) + return fmt.Errorf("获取用户信息失败,err: %v", err) } users = append(users, *user) } - err := common.DB.Select("Roles").Unscoped().Delete(&users).Error - // 删除用户成功,则删除用户信息缓存 - if err == nil { + err := common.DB.Debug().Select("Roles").Unscoped().Delete(&users).Error + if err != nil { + return err + } else { + // 删除用户成功,则删除用户信息缓存 for _, user := range users { userInfoCache.Delete(user.Username) } } + + // 删除用户在group的关联 + err = common.DB.Debug().Exec("DELETE FROM group_users WHERE user_id IN (?)", ids).Error + if err != nil { + return err + } + return err } From 1d2b935cce020bf101f5f499e9111eca084f38b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E4=B8=AB=E8=AE=B2=E6=A2=B5?= Date: Tue, 14 Jun 2022 11:17:51 +0800 Subject: [PATCH 2/2] contrib-readme-action has updated readme --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index d0906dc..f2e5670 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,6 @@ ## 贡献者 -
@@ -123,7 +122,6 @@
- ## 使用登记