新增钉钉手动和定时同步到ldap相关功能 (#7)
This commit is contained in:
parent
9226e659cd
commit
9fab5ee504
|
@ -92,3 +92,12 @@ ldap:
|
||||||
ldap-group-dn: "ou=group,dc=eryajf,dc=net"
|
ldap-group-dn: "ou=group,dc=eryajf,dc=net"
|
||||||
ldap-group-name-modify: false
|
ldap-group-name-modify: false
|
||||||
ldap-user-name-modify: false
|
ldap-user-name-modify: false
|
||||||
|
dingtalk:
|
||||||
|
ding-talk-app-key: "xxxxxx"
|
||||||
|
ding-talk-app-secret: "xxxxxxxxxxxxxxxxxxxxxxxxxxx-vhIGL"
|
||||||
|
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"
|
||||||
|
|
|
@ -24,6 +24,7 @@ type config struct {
|
||||||
RateLimit *RateLimitConfig `mapstructure:"rate-limit" json:"rateLimit"`
|
RateLimit *RateLimitConfig `mapstructure:"rate-limit" json:"rateLimit"`
|
||||||
Ldap *LdapConfig `mapstructure:"ldap" json:"ldap"`
|
Ldap *LdapConfig `mapstructure:"ldap" json:"ldap"`
|
||||||
Email *EmailConfig `mapstructure:"email" json:"email"`
|
Email *EmailConfig `mapstructure:"email" json:"email"`
|
||||||
|
DingTalk *DingTalkConfig `mapstructure:"dingtalk" json:"dingTalk"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置读取配置信息
|
// 设置读取配置信息
|
||||||
|
@ -144,3 +145,12 @@ type EmailConfig struct {
|
||||||
Pass string `mapstructure:"pass" json:"pass"`
|
Pass string `mapstructure:"pass" json:"pass"`
|
||||||
From string `mapstructure:"from" json:"from"`
|
From string `mapstructure:"from" json:"from"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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"`
|
||||||
|
}
|
||||||
|
|
|
@ -80,3 +80,11 @@ func (m *GroupController) RemoveUser(c *gin.Context) {
|
||||||
return logic.Group.RemoveUser(c, req)
|
return logic.Group.RemoveUser(c, req)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//同步钉钉部门信息
|
||||||
|
func (m *GroupController) SyncDingTalkDepts(c *gin.Context) {
|
||||||
|
req := new(request.SyncDingTalkDeptsReq)
|
||||||
|
Run(c, req, func() (interface{}, interface{}) {
|
||||||
|
return logic.DingTalk.DsyncDingTalkDepts(c, req)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -64,3 +64,11 @@ func (uc UserController) GetUserInfo(c *gin.Context) {
|
||||||
return logic.User.GetUserInfo(c, req)
|
return logic.User.GetUserInfo(c, req)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 同步钉钉用户信息
|
||||||
|
func (uc UserController) SyncDingTalkUsers(c *gin.Context) {
|
||||||
|
req := new(request.SyncDingUserReq)
|
||||||
|
Run(c, req, func() (interface{}, interface{}) {
|
||||||
|
return logic.DingTalk.SyncDingTalkUsers(c, req)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -14,8 +14,10 @@ require (
|
||||||
github.com/go-playground/validator/v10 v10.9.0
|
github.com/go-playground/validator/v10 v10.9.0
|
||||||
github.com/juju/ratelimit v1.0.1
|
github.com/juju/ratelimit v1.0.1
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
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.7.1
|
||||||
github.com/thoas/go-funk v0.7.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
|
go.uber.org/zap v1.19.1
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
||||||
|
|
10
go.sum
10
go.sum
|
@ -298,8 +298,9 @@ github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNC
|
||||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
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.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
|
||||||
github.com/pkg/errors v0.8.1/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.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
@ -314,6 +315,8 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
|
||||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
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/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/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
|
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 v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
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.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||||
|
@ -381,6 +384,8 @@ github.com/ugorji/go/codec v1.2.3/go.mod h1:5FxzDJIgeiWJZslYHPj+LS1dq1ZBQVelZFnj
|
||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
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/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/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
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.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
|
@ -582,9 +587,8 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
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.2/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.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||||
gopkg.in/yaml.v2 v2.2.8/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=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|
|
@ -15,5 +15,6 @@ var (
|
||||||
Role = &RoleLogic{}
|
Role = &RoleLogic{}
|
||||||
Menu = &MenuLogic{}
|
Menu = &MenuLogic{}
|
||||||
OperationLog = &OperationLogLogic{}
|
OperationLog = &OperationLogLogic{}
|
||||||
|
DingTalk = &DingTalkLogic{}
|
||||||
Base = &BaseLogic{}
|
Base = &BaseLogic{}
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,535 @@
|
||||||
|
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/zhaoyunxing92/dingtalk/v2"
|
||||||
|
dingreq "github.com/zhaoyunxing92/dingtalk/v2/request"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"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 {
|
||||||
|
//先判断分组类型
|
||||||
|
localDept := request.DingGroupAddReq{
|
||||||
|
GroupType: "ou",
|
||||||
|
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 := detail.Mobile
|
||||||
|
if detail.OrgEmail != "" {
|
||||||
|
emailstr := strings.Split(detail.OrgEmail, "@")
|
||||||
|
userName = emailstr[0]
|
||||||
|
}
|
||||||
|
//钉钉部门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) {
|
||||||
|
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{"username": r.Username}) {
|
||||||
|
err := isql.User.Find(tools.H{"username": r.Username}, oldData)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New(fmt.Sprintf("AddUser根据钉钉用户username获取用户失败:%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 {
|
||||||
|
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
|
||||||
|
}
|
|
@ -42,6 +42,9 @@ func (l GroupLogic) Add(c *gin.Context, req interface{}) (data interface{}, rspE
|
||||||
GroupName: r.GroupName,
|
GroupName: r.GroupName,
|
||||||
Remark: r.Remark,
|
Remark: r.Remark,
|
||||||
Creator: ctxUser.Username,
|
Creator: ctxUser.Username,
|
||||||
|
Source: "platform", //默认是平台添加
|
||||||
|
SourceDeptId: "platform_0",
|
||||||
|
SourceDeptParentId: "platform_0",
|
||||||
}
|
}
|
||||||
pdn := ""
|
pdn := ""
|
||||||
if group.ParentId > 0 {
|
if group.ParentId > 0 {
|
||||||
|
@ -114,7 +117,7 @@ func (l GroupLogic) GetTree(c *gin.Context, req interface{}) (data interface{},
|
||||||
_ = c
|
_ = c
|
||||||
|
|
||||||
var groups []*model.Group
|
var groups []*model.Group
|
||||||
groups, err := isql.Group.List(r)
|
groups, err := isql.Group.ListTree(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, tools.NewMySqlError(fmt.Errorf("获取资源列表失败: " + err.Error()))
|
return nil, tools.NewMySqlError(fmt.Errorf("获取资源列表失败: " + err.Error()))
|
||||||
}
|
}
|
||||||
|
@ -219,6 +222,7 @@ func (l GroupLogic) Delete(c *gin.Context, req interface{}) (data interface{}, r
|
||||||
return nil, tools.NewMySqlError(fmt.Errorf("删除接口失败: %s", err.Error()))
|
return nil, tools.NewMySqlError(fmt.Errorf("删除接口失败: %s", err.Error()))
|
||||||
}
|
}
|
||||||
// TODO: 删除用户组关系
|
// TODO: 删除用户组关系
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
15
main.go
15
main.go
|
@ -3,6 +3,8 @@ package main
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/eryajf/go-ldap-admin/logic"
|
||||||
|
"github.com/robfig/cron/v3"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
@ -63,6 +65,19 @@ func main() {
|
||||||
common.Log.Fatalf("listen: %s\n", err)
|
common.Log.Fatalf("listen: %s\n", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
//启动定时任务
|
||||||
|
c := cron.New(cron.WithSeconds())
|
||||||
|
c.AddFunc("0 1 0 * * *", func() {
|
||||||
|
common.Log.Info("每天0点1分0秒执行一次同步钉钉部门和用户信息到ldap")
|
||||||
|
logic.DingTalk.DsyncDingTalkDepts(nil, nil)
|
||||||
|
})
|
||||||
|
//每天凌晨1点执行一次
|
||||||
|
c.AddFunc("0 15 0 * * *", func() {
|
||||||
|
common.Log.Info("每天凌晨00点15分执行一次同步钉钉部门和用户信息到ldap")
|
||||||
|
logic.DingTalk.SyncDingTalkUsers(nil, nil)
|
||||||
|
})
|
||||||
|
|
||||||
|
c.Start()
|
||||||
|
|
||||||
common.Log.Info(fmt.Sprintf("Server is running at %s:%d/%s", host, port, config.Conf.System.UrlPathPrefix))
|
common.Log.Info(fmt.Sprintf("Server is running at %s:%d/%s", host, port, config.Conf.System.UrlPathPrefix))
|
||||||
|
|
||||||
|
|
|
@ -10,5 +10,9 @@ type Group struct {
|
||||||
GroupType string `gorm:"type:varchar(20);comment:'分组类型:cn、ou'" json:"groupType"`
|
GroupType string `gorm:"type:varchar(20);comment:'分组类型:cn、ou'" json:"groupType"`
|
||||||
Users []*User `gorm:"many2many:group_users" json:"users"`
|
Users []*User `gorm:"many2many:group_users" json:"users"`
|
||||||
ParentId uint `gorm:"default:0;comment:'父组编号(编号为0时表示根组)'" json:"parentId"`
|
ParentId uint `gorm:"default:0;comment:'父组编号(编号为0时表示根组)'" json:"parentId"`
|
||||||
|
SourceDeptId string `gorm:"type:varchar(100);comment:'部门编号'" json:"sourceDeptId"`
|
||||||
|
Source string `gorm:"type:varchar(20);comment:'来源:dingTalk、weCom、ldap、platform'" json:"source"`
|
||||||
|
SourceDeptParentId string `gorm:"type:varchar(100);comment:'父部门编号'" json:"sourceDeptParentId"`
|
||||||
|
SourceUserNum int `gorm:"default:0;comment:'部门下的用户数量,从第三方获取的数据'" json:"source_user_num"`
|
||||||
Children []*Group `gorm:"-" json:"children"`
|
Children []*Group `gorm:"-" json:"children"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,4 +21,6 @@ type User struct {
|
||||||
Source string `gorm:"type:varchar(50);comment:'用户来源:dingTalk、weCom、ldap、platform'" json:"source"` // 来源
|
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
|
DepartmentId string `gorm:"type:varchar(100);not null;comment:'部门id'" json:"departmentId"` // 部门id
|
||||||
Roles []*Role `gorm:"many2many:user_roles" json:"roles"` // 角色
|
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
|
||||||
}
|
}
|
||||||
|
|
|
@ -324,6 +324,13 @@ func InitData() {
|
||||||
Remark: "更改用户在职状态",
|
Remark: "更改用户在职状态",
|
||||||
Creator: "系统",
|
Creator: "系统",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Method: "POST",
|
||||||
|
Path: "/user/syncDingTalkUsers",
|
||||||
|
Category: "user",
|
||||||
|
Remark: "从钉钉拉取用户信息",
|
||||||
|
Creator: "系统",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Method: "GET",
|
Method: "GET",
|
||||||
Path: "/group/list",
|
Path: "/group/list",
|
||||||
|
@ -387,6 +394,13 @@ func InitData() {
|
||||||
Remark: "获取不在分组内的用户列表",
|
Remark: "获取不在分组内的用户列表",
|
||||||
Creator: "系统",
|
Creator: "系统",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Method: "POST",
|
||||||
|
Path: "/group/syncDingTalkDepts",
|
||||||
|
Category: "group",
|
||||||
|
Remark: "从钉钉拉取部门信息",
|
||||||
|
Creator: "系统",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Method: "GET",
|
Method: "GET",
|
||||||
Path: "/role/list",
|
Path: "/role/list",
|
||||||
|
@ -555,10 +569,12 @@ func InitData() {
|
||||||
"/user/info",
|
"/user/info",
|
||||||
"/user/list",
|
"/user/list",
|
||||||
"/user/changePwd",
|
"/user/changePwd",
|
||||||
|
"/user/syncDingTalkUsers",
|
||||||
"/group/list",
|
"/group/list",
|
||||||
"/group/tree",
|
"/group/tree",
|
||||||
"/group/useringroup",
|
"/group/useringroup",
|
||||||
"/group/usernoingroup",
|
"/group/usernoingroup",
|
||||||
|
"/group/syncDingTalkDepts",
|
||||||
"/role/list",
|
"/role/list",
|
||||||
"/role/getmenulist",
|
"/role/getmenulist",
|
||||||
"/role/getapilist",
|
"/role/getapilist",
|
||||||
|
|
|
@ -25,6 +25,7 @@ func InitGroupRoutes(r *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) g
|
||||||
|
|
||||||
group.GET("/useringroup", controller.Group.UserInGroup)
|
group.GET("/useringroup", controller.Group.UserInGroup)
|
||||||
group.GET("/usernoingroup", controller.Group.UserNoInGroup)
|
group.GET("/usernoingroup", controller.Group.UserNoInGroup)
|
||||||
|
group.POST("/syncDingTalkDepts", controller.Group.SyncDingTalkDepts)
|
||||||
}
|
}
|
||||||
|
|
||||||
return r
|
return r
|
||||||
|
|
|
@ -23,6 +23,7 @@ func InitUserRoutes(r *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) gi
|
||||||
user.POST("/delete", controller.User.Delete) // 删除用户
|
user.POST("/delete", controller.User.Delete) // 删除用户
|
||||||
user.POST("/changePwd", controller.User.ChangePwd) // 修改用户密码
|
user.POST("/changePwd", controller.User.ChangePwd) // 修改用户密码
|
||||||
user.POST("/changeUserStatus", controller.User.ChangeUserStatus) // 修改用户状态
|
user.POST("/changeUserStatus", controller.User.ChangeUserStatus) // 修改用户状态
|
||||||
|
user.POST("/syncDingTalkUsers", controller.User.SyncDingTalkUsers) // 同步用户
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,8 @@ func (x UserService) Add(user *model.User) error {
|
||||||
}
|
}
|
||||||
add := ldap.NewAddRequest(fmt.Sprintf("uid=%s,%s", user.Username, config.Conf.Ldap.LdapUserDN), nil)
|
add := ldap.NewAddRequest(fmt.Sprintf("uid=%s,%s", user.Username, config.Conf.Ldap.LdapUserDN), nil)
|
||||||
add.Attribute("objectClass", []string{"inetOrgPerson"})
|
add.Attribute("objectClass", []string{"inetOrgPerson"})
|
||||||
add.Attribute("cn", []string{user.Nickname})
|
add.Attribute("cn", []string{user.Username})
|
||||||
add.Attribute("sn", []string{user.Username})
|
add.Attribute("sn", []string{user.Nickname})
|
||||||
add.Attribute("businessCategory", []string{user.Departments})
|
add.Attribute("businessCategory", []string{user.Departments})
|
||||||
add.Attribute("departmentNumber", []string{user.Position})
|
add.Attribute("departmentNumber", []string{user.Position})
|
||||||
add.Attribute("description", []string{user.Introduction})
|
add.Attribute("description", []string{user.Introduction})
|
||||||
|
|
|
@ -34,6 +34,59 @@ func (s GroupService) List(req *request.GroupListReq) ([]*model.Group, error) {
|
||||||
return list, err
|
return list, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// List 获取数据列表
|
||||||
|
func (s GroupService) ListTree(req *request.GroupListReq) ([]*model.Group, error) {
|
||||||
|
var list []*model.Group
|
||||||
|
db := common.DB.Model(&model.Group{}).Order("created_at DESC")
|
||||||
|
|
||||||
|
groupName := strings.TrimSpace(req.GroupName)
|
||||||
|
if groupName != "" {
|
||||||
|
db = db.Where("group_name LIKE ?", fmt.Sprintf("%%%s%%", groupName))
|
||||||
|
}
|
||||||
|
groupRemark := strings.TrimSpace(req.Remark)
|
||||||
|
if groupRemark != "" {
|
||||||
|
db = db.Where("remark LIKE ?", fmt.Sprintf("%%%s%%", groupRemark))
|
||||||
|
}
|
||||||
|
|
||||||
|
pageReq := tools.NewPageOption(req.PageNum, req.PageSize)
|
||||||
|
err := db.Offset(pageReq.PageNum).Limit(pageReq.PageSize).Find(&list).Error
|
||||||
|
return list, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// List 获取数据列表
|
||||||
|
func (s GroupService) ListAll(req *request.GroupListAllReq) ([]*model.Group, error) {
|
||||||
|
var list []*model.Group
|
||||||
|
db := common.DB.Model(&model.Group{}).Order("created_at DESC")
|
||||||
|
|
||||||
|
groupName := strings.TrimSpace(req.GroupName)
|
||||||
|
if groupName != "" {
|
||||||
|
db = db.Where("group_name LIKE ?", fmt.Sprintf("%%%s%%", groupName))
|
||||||
|
}
|
||||||
|
groupRemark := strings.TrimSpace(req.Remark)
|
||||||
|
if groupRemark != "" {
|
||||||
|
db = db.Where("remark LIKE ?", fmt.Sprintf("%%%s%%", groupRemark))
|
||||||
|
}
|
||||||
|
groupType := strings.TrimSpace(req.GroupType)
|
||||||
|
if groupType != "" {
|
||||||
|
db = db.Where("group_type = ?", groupType)
|
||||||
|
}
|
||||||
|
source := strings.TrimSpace(req.Source)
|
||||||
|
if source != "" {
|
||||||
|
db = db.Where("source = ?", source)
|
||||||
|
}
|
||||||
|
sourceDeptId := strings.TrimSpace(req.SourceDeptId)
|
||||||
|
if sourceDeptId != "" {
|
||||||
|
db = db.Where("source_dept_id = ?", sourceDeptId)
|
||||||
|
}
|
||||||
|
sourceDeptParentId := strings.TrimSpace(req.SourceDeptParentId)
|
||||||
|
if sourceDeptParentId != "" {
|
||||||
|
db = db.Where("source_dept_parent_id = ?", sourceDeptParentId)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := db.Find(&list).Error
|
||||||
|
return list, err
|
||||||
|
}
|
||||||
|
|
||||||
// 拼装dn信息
|
// 拼装dn信息
|
||||||
func (s GroupService) GetGroupDn(groupId uint, oldDn string) (dn string, e error) {
|
func (s GroupService) GetGroupDn(groupId uint, oldDn string) (dn string, e error) {
|
||||||
depart := new(model.Group)
|
depart := new(model.Group)
|
||||||
|
@ -121,3 +174,17 @@ func (s GroupService) AddUserToGroup(group *model.Group, users []model.User) err
|
||||||
func (s GroupService) RemoveUserFromGroup(group *model.Group, users []model.User) error {
|
func (s GroupService) RemoveUserFromGroup(group *model.Group, users []model.User) error {
|
||||||
return common.DB.Model(&group).Association("Users").Delete(users)
|
return common.DB.Model(&group).Association("Users").Delete(users)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DingTalkDeptIdsToGroupIds 将钉钉部门id转换为分组id
|
||||||
|
func (s GroupService) DingTalkDeptIdsToGroupIds(dingTalkIds []string) (groupIds []uint, err error) {
|
||||||
|
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{}
|
||||||
|
for _, g := range tempGroups {
|
||||||
|
tempGroupIds = append(tempGroupIds, g.ID)
|
||||||
|
}
|
||||||
|
return tempGroupIds, nil
|
||||||
|
}
|
||||||
|
|
|
@ -232,7 +232,7 @@ func (s UserService) ChangePwd(username string, hashNewPasswd string) error {
|
||||||
} else {
|
} else {
|
||||||
// 没有缓存就获取用户信息缓存
|
// 没有缓存就获取用户信息缓存
|
||||||
var user model.User
|
var user model.User
|
||||||
common.DB.Where("username = ?", username).First(&user)
|
common.DB.Where("username = ?", username).Preload("Roles").First(&user)
|
||||||
userInfoCache.Set(username, user, cache.DefaultExpiration)
|
userInfoCache.Set(username, user, cache.DefaultExpiration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,16 @@ type GroupListReq struct {
|
||||||
PageSize int `json:"pageSize" form:"pageSize"`
|
PageSize int `json:"pageSize" form:"pageSize"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GroupListAllReq 获取资源列表结构体,不分页
|
||||||
|
type GroupListAllReq struct {
|
||||||
|
GroupName string `json:"groupName" form:"groupName"`
|
||||||
|
GroupType string `json:"groupType" form:"groupType"`
|
||||||
|
Remark string `json:"remark" form:"remark"`
|
||||||
|
Source string `json:"source" form:"source"`
|
||||||
|
SourceDeptId string `json:"sourceDeptId"`
|
||||||
|
SourceDeptParentId string `json:"SourceDeptParentId"`
|
||||||
|
}
|
||||||
|
|
||||||
// GroupAddReq 添加资源结构体
|
// GroupAddReq 添加资源结构体
|
||||||
type GroupAddReq struct {
|
type GroupAddReq struct {
|
||||||
GroupType string `json:"groupType" validate:"required,min=1,max=20"`
|
GroupType string `json:"groupType" validate:"required,min=1,max=20"`
|
||||||
|
@ -17,6 +27,19 @@ type GroupAddReq struct {
|
||||||
Remark string `json:"remark" validate:"min=0,max=100"` // 分组的中文描述
|
Remark string `json:"remark" validate:"min=0,max=100"` // 分组的中文描述
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DingTalkGroupAddReq 添加钉钉资源结构体
|
||||||
|
type DingGroupAddReq struct {
|
||||||
|
GroupType string `json:"groupType" validate:"required,min=1,max=20"`
|
||||||
|
GroupName string `json:"groupName" validate:"required,min=1,max=20"`
|
||||||
|
//父级Id 大于等于0 必填
|
||||||
|
ParentId uint `json:"parentId" validate:"omitempty,min=0"`
|
||||||
|
Remark string `json:"remark" validate:"min=0,max=100"` // 分组的中文描述
|
||||||
|
SourceDeptId string `json:"sourceDeptId"`
|
||||||
|
Source string `json:"source"`
|
||||||
|
SourceDeptParentId string `json:"SourceDeptParentId"`
|
||||||
|
SourceUserNum int `json:"sourceUserNum"`
|
||||||
|
}
|
||||||
|
|
||||||
// GroupUpdateReq 更新资源结构体
|
// GroupUpdateReq 更新资源结构体
|
||||||
type GroupUpdateReq struct {
|
type GroupUpdateReq struct {
|
||||||
ID uint `json:"id" form:"id" validate:"required"`
|
ID uint `json:"id" form:"id" validate:"required"`
|
||||||
|
@ -58,3 +81,7 @@ type UserNoInGroupReq struct {
|
||||||
GroupID uint `json:"groupId" form:"groupId" validate:"required"`
|
GroupID uint `json:"groupId" form:"groupId" validate:"required"`
|
||||||
Nickname string `json:"nickname" form:"nickname"`
|
Nickname string `json:"nickname" form:"nickname"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SyncDingTalkDeptsReq 同步钉钉部门信息
|
||||||
|
type SyncDingTalkDeptsReq struct {
|
||||||
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ type UserAddReq struct {
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
Nickname string `json:"nickname" validate:"required,min=0,max=20"`
|
Nickname string `json:"nickname" validate:"required,min=0,max=20"`
|
||||||
GivenName string `json:"givenName" validate:"min=0,max=20"`
|
GivenName string `json:"givenName" validate:"min=0,max=20"`
|
||||||
Mail string `json:"mail" validate:"required,min=0,max=20"`
|
Mail string `json:"mail" validate:"required,min=0,max=100"`
|
||||||
JobNumber string `json:"jobNumber" validate:"required,min=0,max=20"`
|
JobNumber string `json:"jobNumber" validate:"required,min=0,max=20"`
|
||||||
PostalAddress string `json:"postalAddress" validate:"min=0,max=255"`
|
PostalAddress string `json:"postalAddress" validate:"min=0,max=255"`
|
||||||
Departments string `json:"departments" validate:"min=0,max=255"`
|
Departments string `json:"departments" validate:"min=0,max=255"`
|
||||||
|
@ -20,13 +20,35 @@ type UserAddReq struct {
|
||||||
RoleIds []uint `json:"roleIds" validate:"required"`
|
RoleIds []uint `json:"roleIds" validate:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DingUserAddReq 钉钉用户创建资源结构体
|
||||||
|
type DingUserAddReq struct {
|
||||||
|
Username string `json:"username" validate:"required,min=2,max=20"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
Nickname string `json:"nickname" validate:"required,min=0,max=20"`
|
||||||
|
GivenName string `json:"givenName" validate:"min=0,max=20"`
|
||||||
|
Mail string `json:"mail" validate:"required,min=0,max=100"`
|
||||||
|
JobNumber string `json:"jobNumber" validate:"required,min=0,max=20"`
|
||||||
|
PostalAddress string `json:"postalAddress" validate:"min=0,max=255"`
|
||||||
|
Departments string `json:"departments" validate:"min=0,max=255"`
|
||||||
|
Position string `json:"position" validate:"min=0,max=255"`
|
||||||
|
Mobile string `json:"mobile" validate:"required,checkMobile"`
|
||||||
|
Avatar string `json:"avatar"`
|
||||||
|
Introduction string `json:"introduction" validate:"min=0,max=255"`
|
||||||
|
Status uint `json:"status" validate:"oneof=1 2"`
|
||||||
|
DepartmentId []uint `json:"departmentId" validate:"required"`
|
||||||
|
Source string `json:"source" validate:"min=0,max=20"`
|
||||||
|
RoleIds []uint `json:"roleIds" validate:"required"`
|
||||||
|
SourceUserId string `json:"sourceUserId"` // 第三方用户id
|
||||||
|
SourceUnionId string `json:"sourceUnionId"` // 第三方唯一unionId
|
||||||
|
}
|
||||||
|
|
||||||
// UserUpdateReq 更新资源结构体
|
// UserUpdateReq 更新资源结构体
|
||||||
type UserUpdateReq struct {
|
type UserUpdateReq struct {
|
||||||
ID uint `json:"id" validate:"required"`
|
ID uint `json:"id" validate:"required"`
|
||||||
Username string `json:"username" validate:"required,min=2,max=20"`
|
Username string `json:"username" validate:"required,min=2,max=20"`
|
||||||
Nickname string `json:"nickname" validate:"min=0,max=20"`
|
Nickname string `json:"nickname" validate:"min=0,max=20"`
|
||||||
GivenName string `json:"givenName" validate:"min=0,max=20"`
|
GivenName string `json:"givenName" validate:"min=0,max=20"`
|
||||||
Mail string `json:"mail" validate:"min=0,max=20"`
|
Mail string `json:"mail" validate:"min=0,max=100"`
|
||||||
JobNumber string `json:"jobNumber" validate:"min=0,max=20"`
|
JobNumber string `json:"jobNumber" validate:"min=0,max=20"`
|
||||||
PostalAddress string `json:"postalAddress" validate:"min=0,max=255"`
|
PostalAddress string `json:"postalAddress" validate:"min=0,max=255"`
|
||||||
Departments string `json:"departments" validate:"min=0,max=255"`
|
Departments string `json:"departments" validate:"min=0,max=255"`
|
||||||
|
@ -60,6 +82,10 @@ type UserChangeUserStatusReq struct {
|
||||||
type UserGetUserInfoReq struct {
|
type UserGetUserInfoReq struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 同步钉钉用户信息
|
||||||
|
type SyncDingUserReq struct {
|
||||||
|
}
|
||||||
|
|
||||||
// UserListReq 获取用户列表结构体
|
// UserListReq 获取用户列表结构体
|
||||||
type UserListReq struct {
|
type UserListReq struct {
|
||||||
Username string `json:"username" form:"username"`
|
Username string `json:"username" form:"username"`
|
||||||
|
|
Loading…
Reference in New Issue