添加企业微信的同步能力 (#30)
This commit is contained in:
parent
b29200aec9
commit
56f2cda6dd
|
@ -107,6 +107,11 @@ dingtalk:
|
||||||
agent-id: "12121212" # 目前agent-id未使用到,可忽略
|
agent-id: "12121212" # 目前agent-id未使用到,可忽略
|
||||||
enable-sync: false # 是否开启定时同步钉钉的任务
|
enable-sync: false # 是否开启定时同步钉钉的任务
|
||||||
wecom:
|
wecom:
|
||||||
flag: "wecom"
|
# 配置获取详细文档参考:http://ldapdoc.eryajf.net/pages/cf1698/
|
||||||
|
flag: "wecom" # 作为微信在平台的标识
|
||||||
|
corp-id: "xxxx" # 企业微信企业ID
|
||||||
|
agent-id: 1000003 # 企业微信中创建的应用ID
|
||||||
|
corp-secret: "xxxxx" # 企业微信中创建的应用secret
|
||||||
|
enable-sync: false # 是否开启定时同步企业微信的任务
|
||||||
feishu:
|
feishu:
|
||||||
flag: "feishu"
|
flag: "feishu"
|
|
@ -161,7 +161,10 @@ type DingTalkConfig struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type WeComConfig struct {
|
type WeComConfig struct {
|
||||||
Flag string `mapstructure:"flag" json:"flag"`
|
Flag string `mapstructure:"flag" json:"flag"`
|
||||||
|
CorpID string `mapstructure:"corp-id" json:"corpId"`
|
||||||
|
AgentID int `mapstructure:"agent-id" json:"agentId"`
|
||||||
|
CorpSecret string `mapstructure:"corp-secret" json:"corpSecret"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type FeiShuConfig struct {
|
type FeiShuConfig struct {
|
||||||
|
|
|
@ -88,3 +88,11 @@ func (m *GroupController) SyncDingTalkDepts(c *gin.Context) {
|
||||||
return logic.DingTalk.SyncDingTalkDepts(c, req)
|
return logic.DingTalk.SyncDingTalkDepts(c, req)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//同步企业微信部门信息
|
||||||
|
func (m *GroupController) SyncWeComDepts(c *gin.Context) {
|
||||||
|
req := new(request.SyncWeComDeptsReq)
|
||||||
|
Run(c, req, func() (interface{}, interface{}) {
|
||||||
|
return logic.WeCom.SyncWeComDepts(c, req)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -72,3 +72,11 @@ func (uc UserController) SyncDingTalkUsers(c *gin.Context) {
|
||||||
return logic.DingTalk.SyncDingTalkUsers(c, req)
|
return logic.DingTalk.SyncDingTalkUsers(c, req)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 同步企业微信用户信息
|
||||||
|
func (uc UserController) SyncWeComUsers(c *gin.Context) {
|
||||||
|
req := new(request.SyncWeComUserReq)
|
||||||
|
Run(c, req, func() (interface{}, interface{}) {
|
||||||
|
return logic.WeCom.SyncWeComUsers(c, req)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
5
go.mod
5
go.mod
|
@ -11,7 +11,7 @@ require (
|
||||||
github.com/go-ldap/ldap/v3 v3.4.2
|
github.com/go-ldap/ldap/v3 v3.4.2
|
||||||
github.com/go-playground/locales v0.14.0
|
github.com/go-playground/locales v0.14.0
|
||||||
github.com/go-playground/universal-translator v0.18.0
|
github.com/go-playground/universal-translator v0.18.0
|
||||||
github.com/go-playground/validator/v10 v10.9.0
|
github.com/go-playground/validator/v10 v10.10.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/robfig/cron/v3 v3.0.0
|
||||||
|
@ -25,6 +25,8 @@ require (
|
||||||
gorm.io/gorm v1.20.12
|
gorm.io/gorm v1.20.12
|
||||||
)
|
)
|
||||||
|
|
||||||
|
require github.com/wenerme/go-wecom v0.0.0-20220617125121-2ee950da3e63
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/BurntSushi/toml v1.1.0 // indirect
|
github.com/BurntSushi/toml v1.1.0 // indirect
|
||||||
github.com/golang/mock v1.6.0 // indirect
|
github.com/golang/mock v1.6.0 // indirect
|
||||||
|
@ -33,6 +35,7 @@ require (
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.0.0 // indirect
|
github.com/pelletier/go-toml/v2 v2.0.0 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.8.1 // indirect
|
github.com/rogpeppe/go-internal v1.8.1 // indirect
|
||||||
|
github.com/wenerme/go-req v0.0.0-20210907160348-d822e81276bb // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
14
go.sum
14
go.sum
|
@ -142,6 +142,10 @@ github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
|
||||||
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.1 h1:pDbRAunXzIUXfx4CB2QJFv5IuPiuoW+sWvr/Us009o8=
|
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-asn1-ber/asn1-ber v1.5.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||||
|
github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8=
|
||||||
|
github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||||
|
github.com/go-chi/render v1.0.1 h1:4/5tis2cKaNdnv9zFLfXzcquC9HbeZgCnxGnKrltBS8=
|
||||||
|
github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
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-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-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
@ -160,8 +164,9 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+
|
||||||
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
|
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
|
||||||
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
||||||
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
|
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
|
||||||
github.com/go-playground/validator/v10 v10.9.0 h1:NgTtmN58D0m8+UuxtYmGztBJB7VnPgjj221I1QHci2A=
|
|
||||||
github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
||||||
|
github.com/go-playground/validator/v10 v10.10.0 h1:I7mrTYv78z8k8VXa/qJlOlEXn/nBh+BF8dHX5nt/dr0=
|
||||||
|
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
||||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
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-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/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
|
@ -466,6 +471,7 @@ github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThC
|
||||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
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/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/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||||
|
github.com/sbzhu/weworkapi_golang v0.0.0-20210525081115-1799804a7c8d/go.mod h1:gLXVYg36wlOl44Uh8Uw0aDiNMcZNnV+tzZq1FBj+f6A=
|
||||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
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=
|
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
|
||||||
github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc h1:jUIKcSPO9MoMJBbEoyE/RJoE8vz7Mb8AjvifMMwSyvY=
|
github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc h1:jUIKcSPO9MoMJBbEoyE/RJoE8vz7Mb8AjvifMMwSyvY=
|
||||||
|
@ -512,6 +518,10 @@ github.com/ugorji/go v1.2.3/go.mod h1:5l8GZ8hZvmL4uMdy+mhCO1LjswGRYco9Q3HfuisB21
|
||||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
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 h1:/mVYEV+Jo3IZKeA5gBngN0AvNnQltEDkR+eQikkWQu0=
|
||||||
github.com/ugorji/go/codec v1.2.3/go.mod h1:5FxzDJIgeiWJZslYHPj+LS1dq1ZBQVelZFnjsFGI/Uc=
|
github.com/ugorji/go/codec v1.2.3/go.mod h1:5FxzDJIgeiWJZslYHPj+LS1dq1ZBQVelZFnjsFGI/Uc=
|
||||||
|
github.com/wenerme/go-req v0.0.0-20210907160348-d822e81276bb h1:4/6Qqg+E8z98SCi21dFnhL6goSWOYMunJkMc+YanrEw=
|
||||||
|
github.com/wenerme/go-req v0.0.0-20210907160348-d822e81276bb/go.mod h1:aQUkMiMp1qZkuSsdu2Vy2ZQK33cPNVmyWFzXatfP+Y4=
|
||||||
|
github.com/wenerme/go-wecom v0.0.0-20220617125121-2ee950da3e63 h1:wRIOQxBR5XbUZVMKziAjCnlnDhdAjVjBmLsUSn/j/+M=
|
||||||
|
github.com/wenerme/go-wecom v0.0.0-20220617125121-2ee950da3e63/go.mod h1:Jz7prkOPdCbWbT5bOQOFkZUQp7pqEc8yiWaCgOVWPH0=
|
||||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
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.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
@ -564,6 +574,7 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
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-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-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA=
|
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/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-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
@ -747,6 +758,7 @@ golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/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-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-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/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-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-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-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
|
|
@ -16,5 +16,6 @@ var (
|
||||||
Menu = &MenuLogic{}
|
Menu = &MenuLogic{}
|
||||||
OperationLog = &OperationLogLogic{}
|
OperationLog = &OperationLogLogic{}
|
||||||
DingTalk = &DingTalkLogic{}
|
DingTalk = &DingTalkLogic{}
|
||||||
|
WeCom = &WeComLogic{}
|
||||||
Base = &BaseLogic{}
|
Base = &BaseLogic{}
|
||||||
)
|
)
|
||||||
|
|
|
@ -23,7 +23,7 @@ type DingTalkLogic struct {
|
||||||
//通过钉钉获取部门信息
|
//通过钉钉获取部门信息
|
||||||
func (d *DingTalkLogic) SyncDingTalkDepts(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) {
|
func (d *DingTalkLogic) SyncDingTalkDepts(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) {
|
||||||
// 1.获取所有部门
|
// 1.获取所有部门
|
||||||
depts, err := dingtalk.GetDingTalkAllDepts(1)
|
depts, err := dingtalk.GetAllDepts(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, tools.NewOperationError(fmt.Errorf("获取钉钉部门列表失败:%s", err.Error()))
|
return nil, tools.NewOperationError(fmt.Errorf("获取钉钉部门列表失败:%s", err.Error()))
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ func (d DingTalkLogic) AddDepts(r *request.DingGroupAddReq) error {
|
||||||
//根据现有数据库同步到的部门信息,开启用户同步
|
//根据现有数据库同步到的部门信息,开启用户同步
|
||||||
func (d DingTalkLogic) SyncDingTalkUsers(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) {
|
func (d DingTalkLogic) SyncDingTalkUsers(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) {
|
||||||
// 1.获取钉钉用户列表
|
// 1.获取钉钉用户列表
|
||||||
users, err := dingtalk.GetDingTalkAllUsers()
|
users, err := dingtalk.GetAllUsers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, tools.NewOperationError(fmt.Errorf("SyncDingTalkUsers获取钉钉用户列表失败:%s", err.Error()))
|
return nil, tools.NewOperationError(fmt.Errorf("SyncDingTalkUsers获取钉钉用户列表失败:%s", err.Error()))
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ func (d DingTalkLogic) SyncDingTalkUsers(c *gin.Context, req interface{}) (data
|
||||||
for _, deptId := range detail.DeptIds {
|
for _, deptId := range detail.DeptIds {
|
||||||
sourceDeptIds = append(sourceDeptIds, fmt.Sprintf("%s_%d", config.Conf.DingTalk.Flag, deptId))
|
sourceDeptIds = append(sourceDeptIds, fmt.Sprintf("%s_%d", config.Conf.DingTalk.Flag, deptId))
|
||||||
}
|
}
|
||||||
groupIds, err := isql.Group.DingTalkDeptIdsToGroupIds(sourceDeptIds)
|
groupIds, err := isql.Group.DeptIdsToGroupIds(sourceDeptIds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, tools.NewMySqlError(fmt.Errorf("SyncDingTalkUsers获取钉钉部门ids转换为内部部门id失败:%s", err.Error()))
|
return nil, tools.NewMySqlError(fmt.Errorf("SyncDingTalkUsers获取钉钉部门ids转换为内部部门id失败:%s", err.Error()))
|
||||||
}
|
}
|
||||||
|
@ -168,7 +168,7 @@ func (d DingTalkLogic) SyncDingTalkUsers(c *gin.Context, req interface{}) (data
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3.获取钉钉已离职用户id列表
|
// 3.获取钉钉已离职用户id列表
|
||||||
userIds, err := dingtalk.GetDingTalkLeaveUserIds()
|
userIds, err := dingtalk.GetLeaveUserIds()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, tools.NewOperationError(fmt.Errorf("SyncDingTalkUsers获取钉钉离职用户列表失败:%s", err.Error()))
|
return nil, tools.NewOperationError(fmt.Errorf("SyncDingTalkUsers获取钉钉离职用户列表失败:%s", err.Error()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,281 @@
|
||||||
|
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/wechat"
|
||||||
|
"github.com/mozillazg/go-pinyin"
|
||||||
|
"github.com/wenerme/go-wecom/wecom"
|
||||||
|
|
||||||
|
"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"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WeComLogic struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
//通过企业微信获取部门信息
|
||||||
|
func (d *WeComLogic) SyncWeComDepts(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) {
|
||||||
|
// 1.获取所有部门
|
||||||
|
depts, err := wechat.GetAllDepts()
|
||||||
|
if err != nil {
|
||||||
|
return nil, tools.NewOperationError(fmt.Errorf("获取企业微信部门列表失败:%s", err.Error()))
|
||||||
|
}
|
||||||
|
// 2.将部门这个数组进行拆分,一组是父ID为1的,一组是父ID不为1的
|
||||||
|
var firstDepts []wecom.ListDepartmentResponseItem // 父ID为1的部门
|
||||||
|
var otherDepts []wecom.ListDepartmentResponseItem // 父ID不为1的部门
|
||||||
|
for _, dept := range depts {
|
||||||
|
if dept.ID == 1 { // 跳过ID为1的根部门,由系统配置的根部门进行占位
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
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.WeComGroupAddReq{
|
||||||
|
GroupType: "cn",
|
||||||
|
GroupName: strings.Join(pinyin.LazyConvert(dept.Name, nil), ""),
|
||||||
|
Remark: dept.Name,
|
||||||
|
SourceDeptId: fmt.Sprintf("%s_%d", config.Conf.WeCom.Flag, dept.ID),
|
||||||
|
Source: config.Conf.WeCom.Flag,
|
||||||
|
SourceDeptParentId: fmt.Sprintf("%s_%d", config.Conf.WeCom.Flag, 1),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, tools.NewOperationError(fmt.Errorf("SyncWeComDepts添加根部门失败:%s", err.Error()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, dept := range otherDepts {
|
||||||
|
err := d.AddDepts(&request.WeComGroupAddReq{
|
||||||
|
GroupType: "cn",
|
||||||
|
GroupName: strings.Join(pinyin.LazyConvert(dept.Name, nil), ""),
|
||||||
|
Remark: dept.Name,
|
||||||
|
SourceDeptId: fmt.Sprintf("%s_%d", config.Conf.WeCom.Flag, dept.ID),
|
||||||
|
Source: config.Conf.WeCom.Flag,
|
||||||
|
SourceDeptParentId: fmt.Sprintf("%s_%d", config.Conf.WeCom.Flag, dept.ParentID),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, tools.NewOperationError(fmt.Errorf("SyncWeComDepts添加根部门失败:%s", err.Error()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddGroup 添加部门数据
|
||||||
|
func (d WeComLogic) AddDepts(r *request.WeComGroupAddReq) 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 WeComLogic) SyncWeComUsers(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) {
|
||||||
|
// 1.获取企业微信用户列表
|
||||||
|
users, err := wechat.GetAllUsers()
|
||||||
|
if err != nil {
|
||||||
|
return nil, tools.NewOperationError(fmt.Errorf("SyncWeComUsers获取企业微信用户列表失败:%s", err.Error()))
|
||||||
|
}
|
||||||
|
// 2.将用户拆分成两组,一组状态为1的在职正常用户,一组状态为2的禁用账户
|
||||||
|
// 此问题在企业微信这里没有统一的定论
|
||||||
|
// 有的公司是员工离职,直接在企业微信后台删除(企业微信又没有对应接口拿到已经被删除的用户)
|
||||||
|
// 也有公司是在后台禁用账号,这两者不同,处理方式也不一样
|
||||||
|
// 目前先以第二种为准,判断用户状态字段来判断用户是否离职
|
||||||
|
var liveUsers []wecom.ListUserResponseItem
|
||||||
|
var leaveUsers []wecom.ListUserResponseItem
|
||||||
|
for _, user := range users {
|
||||||
|
if user.Status == 1 {
|
||||||
|
liveUsers = append(liveUsers, user)
|
||||||
|
}
|
||||||
|
if user.Status == 2 {
|
||||||
|
leaveUsers = append(leaveUsers, user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 2.遍历用户,开始写入
|
||||||
|
for _, detail := range liveUsers {
|
||||||
|
// 用户名的几种情况
|
||||||
|
var userName string
|
||||||
|
if detail.Email != "" {
|
||||||
|
userName = strings.Split(detail.Email, "@")[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.BizMail == "" {
|
||||||
|
detail.BizMail = detail.Email
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果企业内没有工号,则工号用名字占位
|
||||||
|
// if detail.JobNumber == "" {
|
||||||
|
// detail.JobNumber = detail.Mobile
|
||||||
|
// }
|
||||||
|
|
||||||
|
//企业微信部门ids,转换为内部部门id
|
||||||
|
var sourceDeptIds []string
|
||||||
|
for _, deptId := range detail.Department {
|
||||||
|
sourceDeptIds = append(sourceDeptIds, fmt.Sprintf("%s_%d", config.Conf.WeCom.Flag, deptId))
|
||||||
|
}
|
||||||
|
groupIds, err := isql.Group.DeptIdsToGroupIds(sourceDeptIds)
|
||||||
|
if err != nil {
|
||||||
|
return nil, tools.NewMySqlError(fmt.Errorf("SyncWeComUsers获取企业微信部门ids转换为内部部门id失败:%s", err.Error()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写入用户
|
||||||
|
user := request.WeComUserAddReq{
|
||||||
|
Username: userName,
|
||||||
|
Password: config.Conf.Ldap.UserInitPassword,
|
||||||
|
Nickname: detail.Name,
|
||||||
|
GivenName: detail.Name,
|
||||||
|
Mail: detail.BizMail,
|
||||||
|
JobNumber: detail.Name, // 工号暂用名字替代
|
||||||
|
Mobile: detail.Mobile,
|
||||||
|
Avatar: detail.Avatar,
|
||||||
|
PostalAddress: detail.Address,
|
||||||
|
// Departments: dept.GroupName,
|
||||||
|
Position: detail.Position,
|
||||||
|
Introduction: detail.Name,
|
||||||
|
Status: 1,
|
||||||
|
DepartmentId: groupIds,
|
||||||
|
Source: config.Conf.WeCom.Flag,
|
||||||
|
SourceUserId: fmt.Sprintf("%s_%s", config.Conf.WeCom.Flag, detail.UserID),
|
||||||
|
SourceUnionId: fmt.Sprintf("%s_%s", config.Conf.WeCom.Flag, detail.UserID),
|
||||||
|
}
|
||||||
|
// 入库
|
||||||
|
err = d.AddUsers(&user)
|
||||||
|
if err != nil {
|
||||||
|
return nil, tools.NewOperationError(fmt.Errorf("SyncWeComUsers写入用户失败:%s", err.Error()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3.获取企业微信已离职用户id列表
|
||||||
|
// 4.遍历id,开始处理
|
||||||
|
for _, userTmp := range leaveUsers {
|
||||||
|
user := new(model.User)
|
||||||
|
err = isql.User.Find(tools.H{"source_user_id": fmt.Sprintf("%s_%s", config.Conf.WeCom.Flag, userTmp.UserID)}, 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 WeComLogic) AddUsers(r *request.WeComUserAddReq) 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.UserDN),
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
|
@ -40,6 +40,19 @@ type DingGroupAddReq struct {
|
||||||
SourceUserNum int `json:"sourceUserNum"`
|
SourceUserNum int `json:"sourceUserNum"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WeComGroupAddReq 添加企业微信资源结构体
|
||||||
|
type WeComGroupAddReq 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"`
|
||||||
|
@ -85,3 +98,7 @@ type UserNoInGroupReq struct {
|
||||||
// SyncDingTalkDeptsReq 同步钉钉部门信息
|
// SyncDingTalkDeptsReq 同步钉钉部门信息
|
||||||
type SyncDingTalkDeptsReq struct {
|
type SyncDingTalkDeptsReq struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SyncWeComDeptsReq 同步企业微信部门信息
|
||||||
|
type SyncWeComDeptsReq struct {
|
||||||
|
}
|
||||||
|
|
|
@ -42,6 +42,28 @@ type DingUserAddReq struct {
|
||||||
SourceUnionId string `json:"sourceUnionId"` // 第三方唯一unionId
|
SourceUnionId string `json:"sourceUnionId"` // 第三方唯一unionId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WeComUserAddReq 企业微信用户创建资源结构体
|
||||||
|
type WeComUserAddReq 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"`
|
||||||
|
@ -82,10 +104,14 @@ type UserChangeUserStatusReq struct {
|
||||||
type UserGetUserInfoReq struct {
|
type UserGetUserInfoReq struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 同步钉钉用户信息
|
// SyncDingUserReq 同步钉钉用户信息
|
||||||
type SyncDingUserReq struct {
|
type SyncDingUserReq struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SyncWeComUserReq 同步企业微信用户信息
|
||||||
|
type SyncWeComUserReq struct {
|
||||||
|
}
|
||||||
|
|
||||||
// UserListReq 获取用户列表结构体
|
// UserListReq 获取用户列表结构体
|
||||||
type UserListReq struct {
|
type UserListReq struct {
|
||||||
Username string `json:"username" form:"username"`
|
Username string `json:"username" form:"username"`
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"github.com/zhaoyunxing92/dingtalk/v2/request"
|
"github.com/zhaoyunxing92/dingtalk/v2/request"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetDingTalkAllDepts(deptId int) (result []*DingTalkDept, err error) {
|
func GetAllDepts(deptId int) (result []*DingTalkDept, err error) {
|
||||||
depts, err := InitDingTalkClient().FetchDeptList(deptId, true, "zh_CN")
|
depts, err := InitDingTalkClient().FetchDeptList(deptId, true, "zh_CN")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, err
|
return result, err
|
||||||
|
@ -24,8 +24,8 @@ func GetDingTalkAllDepts(deptId int) (result []*DingTalkDept, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDingTalkAllUsers() (result []*DingTalkUser, err error) {
|
func GetAllUsers() (result []*DingTalkUser, err error) {
|
||||||
depts, err := GetDingTalkAllDepts(1)
|
depts, err := GetAllDepts(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ func GetDingTalkAllUsers() (result []*DingTalkUser, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDingTalkLeaveUserIds() ([]string, error) {
|
func GetLeaveUserIds() ([]string, error) {
|
||||||
var ids []string
|
var ids []string
|
||||||
ReqParm := struct {
|
ReqParm := struct {
|
||||||
Cursor int `json:"cursor"`
|
Cursor int `json:"cursor"`
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
package wechat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/eryajf/go-ldap-admin/config"
|
||||||
|
"github.com/wenerme/go-wecom/wecom"
|
||||||
|
)
|
||||||
|
|
||||||
|
func InitWeComClient() *wecom.Client {
|
||||||
|
client := wecom.NewClient(wecom.Conf{
|
||||||
|
CorpID: config.Conf.WeCom.CorpID,
|
||||||
|
AgentID: config.Conf.WeCom.AgentID,
|
||||||
|
CorpSecret: config.Conf.WeCom.CorpSecret,
|
||||||
|
})
|
||||||
|
return client
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package wechat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/wenerme/go-wecom/wecom"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetAllDepts 获取所有部门
|
||||||
|
func GetAllDepts() ([]wecom.ListDepartmentResponseItem, error) {
|
||||||
|
depts, err := InitWeComClient().ListDepartment(
|
||||||
|
&wecom.ListDepartmentRequest{},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return depts.Department, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAllDepts 获取所有部门
|
||||||
|
func GetAllUsers() ([]wecom.ListUserResponseItem, error) {
|
||||||
|
depts, err := GetAllDepts()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var us []wecom.ListUserResponseItem
|
||||||
|
for _, dept := range depts {
|
||||||
|
users, err := InitWeComClient().ListUser(
|
||||||
|
&wecom.ListUserRequest{
|
||||||
|
DepartmentID: strconv.Itoa(dept.ID),
|
||||||
|
FetchChild: "1",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
us = append(us, users.UserList...)
|
||||||
|
}
|
||||||
|
return us, nil
|
||||||
|
}
|
|
@ -333,6 +333,13 @@ func InitData() {
|
||||||
Remark: "从钉钉拉取用户信息",
|
Remark: "从钉钉拉取用户信息",
|
||||||
Creator: "系统",
|
Creator: "系统",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Method: "POST",
|
||||||
|
Path: "/user/syncWeComUsers",
|
||||||
|
Category: "user",
|
||||||
|
Remark: "从企业微信拉取用户信息",
|
||||||
|
Creator: "系统",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Method: "GET",
|
Method: "GET",
|
||||||
Path: "/group/list",
|
Path: "/group/list",
|
||||||
|
@ -403,6 +410,13 @@ func InitData() {
|
||||||
Remark: "从钉钉拉取部门信息",
|
Remark: "从钉钉拉取部门信息",
|
||||||
Creator: "系统",
|
Creator: "系统",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Method: "POST",
|
||||||
|
Path: "/group/syncWeComDepts",
|
||||||
|
Category: "group",
|
||||||
|
Remark: "从企业微信拉取部门信息",
|
||||||
|
Creator: "系统",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Method: "GET",
|
Method: "GET",
|
||||||
Path: "/role/list",
|
Path: "/role/list",
|
||||||
|
@ -572,11 +586,13 @@ func InitData() {
|
||||||
"/user/list",
|
"/user/list",
|
||||||
"/user/changePwd",
|
"/user/changePwd",
|
||||||
"/user/syncDingTalkUsers",
|
"/user/syncDingTalkUsers",
|
||||||
|
"/user/syncWeComUsers",
|
||||||
"/group/list",
|
"/group/list",
|
||||||
"/group/tree",
|
"/group/tree",
|
||||||
"/group/useringroup",
|
"/group/useringroup",
|
||||||
"/group/usernoingroup",
|
"/group/usernoingroup",
|
||||||
"/group/syncDingTalkDepts",
|
"/group/syncDingTalkDepts",
|
||||||
|
"/group/syncWeComkDepts",
|
||||||
"/role/list",
|
"/role/list",
|
||||||
"/role/getmenulist",
|
"/role/getmenulist",
|
||||||
"/role/getapilist",
|
"/role/getapilist",
|
||||||
|
|
|
@ -25,7 +25,9 @@ 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)
|
|
||||||
|
group.POST("/syncDingTalkDepts", controller.Group.SyncDingTalkDepts) // 同步部门
|
||||||
|
group.POST("/syncWeComDepts", controller.Group.SyncWeComDepts) // 同步部门
|
||||||
}
|
}
|
||||||
|
|
||||||
return r
|
return r
|
||||||
|
|
|
@ -16,14 +16,16 @@ func InitUserRoutes(r *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) gi
|
||||||
// 开启casbin鉴权中间件
|
// 开启casbin鉴权中间件
|
||||||
user.Use(middleware.CasbinMiddleware())
|
user.Use(middleware.CasbinMiddleware())
|
||||||
{
|
{
|
||||||
user.GET("/info", controller.User.GetUserInfo) // 暂时未完成
|
user.GET("/info", controller.User.GetUserInfo) // 暂时未完成
|
||||||
user.GET("/list", controller.User.List) // 用户列表
|
user.GET("/list", controller.User.List) // 用户列表
|
||||||
user.POST("/add", controller.User.Add) // 添加用户
|
user.POST("/add", controller.User.Add) // 添加用户
|
||||||
user.POST("/update", controller.User.Update) // 更新用户
|
user.POST("/update", controller.User.Update) // 更新用户
|
||||||
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) // 同步用户
|
user.POST("/syncDingTalkUsers", controller.User.SyncDingTalkUsers) // 同步用户
|
||||||
|
user.POST("/syncWeComUsers", controller.User.SyncWeComUsers) // 同步用户
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,10 +151,10 @@ func (s GroupService) RemoveUserFromGroup(group *model.Group, users []model.User
|
||||||
return common.DB.Model(&group).Association("Users").Delete(users)
|
return common.DB.Model(&group).Association("Users").Delete(users)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DingTalkDeptIdsToGroupIds 将钉钉部门id转换为分组id
|
// DeptIdsToGroupIds 将企业IM部门id转换为MySQL分组id
|
||||||
func (s GroupService) DingTalkDeptIdsToGroupIds(dingTalkIds []string) (groupIds []uint, err error) {
|
func (s GroupService) DeptIdsToGroupIds(ids []string) (groupIds []uint, err error) {
|
||||||
var tempGroups []model.Group
|
var tempGroups []model.Group
|
||||||
err = common.DB.Model(&model.Group{}).Where("source_dept_id IN (?)", dingTalkIds).Find(&tempGroups).Error
|
err = common.DB.Model(&model.Group{}).Where("source_dept_id IN (?)", ids).Find(&tempGroups).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue