2022-05-30 10:43:28 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/md5"
|
|
|
|
"encoding/base64"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"log"
|
2022-05-31 09:52:43 +00:00
|
|
|
"strings"
|
|
|
|
"time"
|
2022-05-30 10:43:28 +00:00
|
|
|
|
2022-05-31 09:52:43 +00:00
|
|
|
"github.com/474420502/perfectshutdown"
|
2022-05-30 10:43:28 +00:00
|
|
|
"github.com/474420502/requests"
|
|
|
|
arraystack "github.com/474420502/structure/stack/array"
|
|
|
|
"github.com/go-ldap/ldap/v3"
|
|
|
|
"github.com/tidwall/gjson"
|
|
|
|
)
|
|
|
|
|
|
|
|
var appkey = "dingwzebpctav6l3bvkn"
|
|
|
|
var appsecret = "M_WTqBDk06IS6maj_EHipsvYQe76Led72dTKqceHnVJELJ44KOyG1qV5O6MeX2e_"
|
|
|
|
|
|
|
|
type Department struct {
|
|
|
|
DepartID int64
|
|
|
|
Name string
|
|
|
|
DN []string
|
|
|
|
Sub []*Department
|
|
|
|
Member gjson.Result
|
|
|
|
}
|
|
|
|
|
2022-05-31 09:52:43 +00:00
|
|
|
func LdapMemberAdd(ldapconn *ldap.Conn, dn, name, title, mail, mobile string) bool {
|
|
|
|
req := ldap.NewAddRequest(strings.ReplaceAll(dn, "+", "\\+"), nil)
|
|
|
|
req.Attribute("objectClass", []string{"inetOrgPerson", "organizationalPerson", "person", "top"})
|
|
|
|
req.Attribute("cn", []string{name})
|
|
|
|
req.Attribute("sn", []string{name})
|
|
|
|
req.Attribute("displayName", []string{name})
|
|
|
|
req.Attribute("givenName", []string{name})
|
|
|
|
req.Attribute("title", []string{title})
|
|
|
|
req.Attribute("mail", []string{mail})
|
|
|
|
req.Attribute("telephoneNumber", []string{mobile})
|
|
|
|
md5hash := md5.New()
|
|
|
|
md5hash.Write([]byte(mobile))
|
|
|
|
pwd := base64.StdEncoding.EncodeToString(md5hash.Sum(nil))
|
|
|
|
req.Attribute("userPassword", []string{"{MD5}" + pwd})
|
|
|
|
|
|
|
|
err := ldapconn.Add(req)
|
2022-05-30 10:43:28 +00:00
|
|
|
if err != nil {
|
2022-05-31 09:52:43 +00:00
|
|
|
if ldap.IsErrorAnyOf(err, 68) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
log.Panic(err)
|
2022-05-30 10:43:28 +00:00
|
|
|
}
|
2022-05-31 09:52:43 +00:00
|
|
|
return true
|
|
|
|
}
|
2022-05-30 10:43:28 +00:00
|
|
|
|
2022-05-31 09:52:43 +00:00
|
|
|
func LdapMemberModify(ldapconn *ldap.Conn, dn, name, title, mail, mobile string) bool {
|
|
|
|
|
|
|
|
req := ldap.NewModifyRequest(strings.ReplaceAll(dn, "+", "\\+"), nil)
|
|
|
|
req.Replace("objectClass", []string{"inetOrgPerson", "organizationalPerson", "person", "top"})
|
|
|
|
req.Replace("cn", []string{name})
|
|
|
|
req.Replace("sn", []string{name})
|
|
|
|
req.Replace("displayName", []string{name})
|
|
|
|
req.Replace("givenName", []string{name})
|
|
|
|
req.Replace("title", []string{title})
|
|
|
|
req.Replace("mail", []string{mail})
|
|
|
|
req.Replace("telephoneNumber", []string{mobile})
|
|
|
|
md5hash := md5.New()
|
|
|
|
md5hash.Write([]byte(mobile))
|
|
|
|
pwd := base64.StdEncoding.EncodeToString(md5hash.Sum(nil))
|
|
|
|
req.Replace("userPassword", []string{"{MD5}" + pwd})
|
|
|
|
|
|
|
|
err := ldapconn.Modify(req)
|
2022-05-30 10:43:28 +00:00
|
|
|
if err != nil {
|
2022-05-31 09:52:43 +00:00
|
|
|
log.Panic(err)
|
2022-05-30 10:43:28 +00:00
|
|
|
}
|
2022-05-31 09:52:43 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func LdapGroupAdd(ldapconn *ldap.Conn, cn, description string, uniqueMember []string) bool {
|
|
|
|
// 建 组织 ou=groups,dc=yuandian,dc=com
|
2022-05-30 10:43:28 +00:00
|
|
|
|
2022-05-31 09:52:43 +00:00
|
|
|
req := ldap.NewAddRequest(fmt.Sprintf("cn=%s,ou=groups,dc=yuandian,dc=com", strings.ReplaceAll(cn, "+", "\\+")), nil)
|
|
|
|
req.Attribute("objectClass", []string{"groupOfUniqueNames", "top"})
|
|
|
|
req.Attribute("ou", []string{cn})
|
|
|
|
req.Attribute("cn", []string{cn})
|
|
|
|
req.Attribute("uniqueMember", uniqueMember)
|
|
|
|
req.Attribute("description", []string{description})
|
|
|
|
|
|
|
|
err := ldapconn.Add(req)
|
2022-05-30 10:43:28 +00:00
|
|
|
if err != nil {
|
2022-05-31 09:52:43 +00:00
|
|
|
if ldap.IsErrorAnyOf(err, 68) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
log.Panic(err)
|
2022-05-30 10:43:28 +00:00
|
|
|
}
|
2022-05-31 09:52:43 +00:00
|
|
|
return true
|
|
|
|
}
|
2022-05-30 10:43:28 +00:00
|
|
|
|
2022-05-31 09:52:43 +00:00
|
|
|
func LdapGroupModify(ldapconn *ldap.Conn, cn, description string, uniqueMember []string) {
|
|
|
|
// 建 组织 ou=groups,dc=yuandian,dc=com
|
|
|
|
req := ldap.NewModifyRequest(fmt.Sprintf("cn=%s,ou=groups,dc=yuandian,dc=com", strings.ReplaceAll(cn, "+", "\\+")), nil)
|
|
|
|
req.Replace("objectClass", []string{"groupOfUniqueNames", "top"})
|
|
|
|
req.Replace("ou", []string{cn})
|
|
|
|
req.Replace("cn", []string{cn})
|
|
|
|
req.Replace("uniqueMember", uniqueMember)
|
|
|
|
req.Replace("description", []string{description})
|
2022-05-30 10:43:28 +00:00
|
|
|
|
2022-05-31 09:52:43 +00:00
|
|
|
err := ldapconn.Modify(req)
|
|
|
|
if err != nil {
|
2022-05-30 10:43:28 +00:00
|
|
|
|
2022-05-31 09:52:43 +00:00
|
|
|
log.Panic(err)
|
|
|
|
}
|
|
|
|
}
|
2022-05-30 10:43:28 +00:00
|
|
|
|
2022-05-31 09:52:43 +00:00
|
|
|
func main() {
|
|
|
|
|
|
|
|
pf := perfectshutdown.New()
|
|
|
|
|
|
|
|
pf.Loop(func(index int, cxt *perfectshutdown.PerfectShutdown) {
|
2022-08-11 01:26:56 +00:00
|
|
|
|
2022-05-31 09:52:43 +00:00
|
|
|
ldapconn, err := ldap.DialURL("ldap://ldap.yuandian.com:389")
|
2022-05-30 10:43:28 +00:00
|
|
|
if err != nil {
|
2022-05-31 09:52:43 +00:00
|
|
|
log.Fatal(err)
|
2022-05-30 10:43:28 +00:00
|
|
|
}
|
2022-05-31 09:52:43 +00:00
|
|
|
defer ldapconn.Close()
|
2022-05-30 10:43:28 +00:00
|
|
|
|
2022-05-31 09:52:43 +00:00
|
|
|
err = ldapconn.Bind("cn=admin,dc=yuandian,dc=com", "yuandianldap123")
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
2022-05-30 10:43:28 +00:00
|
|
|
}
|
|
|
|
|
2022-05-31 09:52:43 +00:00
|
|
|
ses := requests.NewSession()
|
|
|
|
tp := ses.Get(fmt.Sprintf("https://oapi.dingtalk.com/gettoken?appkey=%s&appsecret=%s", appkey, appsecret))
|
|
|
|
resp, err := tp.Execute()
|
2022-05-30 10:43:28 +00:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2022-05-31 09:52:43 +00:00
|
|
|
var rjson map[string]any
|
|
|
|
if err := json.Unmarshal(resp.Content(), &rjson); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
token := rjson["access_token"]
|
|
|
|
log.Println(token)
|
|
|
|
|
|
|
|
Root := &Department{DepartID: 1, DN: []string{"dn=yuandian", "dn=com"}}
|
|
|
|
|
|
|
|
stack := arraystack.New[*Department]()
|
|
|
|
stack.Push(Root)
|
|
|
|
|
|
|
|
var persondict map[string]bool = make(map[string]bool)
|
|
|
|
var allperson []string
|
|
|
|
|
|
|
|
for !stack.Empty() {
|
|
|
|
department, _ := stack.Pop()
|
|
|
|
|
|
|
|
// 获取子部门信息
|
|
|
|
tp = ses.Post(fmt.Sprintf("https://oapi.dingtalk.com/topapi/v2/department/listsub?access_token=%s", token))
|
|
|
|
if department.DepartID > 1 {
|
|
|
|
tp.SetBodyAuto(fmt.Sprintf(`{"dept_id": %d}`, department.DepartID))
|
|
|
|
}
|
|
|
|
resp, err = tp.Execute()
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2022-05-30 10:43:28 +00:00
|
|
|
|
2022-05-31 09:52:43 +00:00
|
|
|
listsub := gjson.ParseBytes(resp.Content()).Get("result").Array()
|
|
|
|
for _, sub := range listsub {
|
|
|
|
var dept = &Department{
|
|
|
|
DepartID: sub.Get("dept_id").Int(),
|
|
|
|
Name: sub.Get("name").String(),
|
|
|
|
}
|
|
|
|
stack.Push(dept)
|
|
|
|
department.Sub = append(department.Sub, dept)
|
|
|
|
}
|
|
|
|
|
|
|
|
tp = ses.Post(fmt.Sprintf("https://oapi.dingtalk.com/topapi/v2/user/list?access_token=%s", token))
|
|
|
|
tp.SetBodyAuto(fmt.Sprintf(`{"dept_id": %d, "cursor": 0, "size": 100}`, department.DepartID))
|
|
|
|
resp, err = tp.Execute()
|
2022-05-30 10:43:28 +00:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2022-05-31 09:52:43 +00:00
|
|
|
|
|
|
|
department.Member = gjson.ParseBytes(resp.Content()).Get("result.list")
|
|
|
|
var dnmembers []string
|
|
|
|
// 建人
|
|
|
|
for _, person := range department.Member.Array() {
|
|
|
|
name := person.Get("name").String()
|
|
|
|
mail := person.Get("mail").String()
|
|
|
|
mobile := person.Get("mobile").String()
|
|
|
|
title := person.Get("title").String()
|
|
|
|
if title == "" {
|
|
|
|
title = "未设"
|
|
|
|
}
|
|
|
|
|
|
|
|
dn := fmt.Sprintf("cn=%s,ou=members,dc=yuandian,dc=com", name)
|
|
|
|
|
|
|
|
if !LdapMemberAdd(ldapconn, dn, name, title, mail, mobile) {
|
|
|
|
LdapMemberModify(ldapconn, dn, name, title, mail, mobile)
|
|
|
|
}
|
|
|
|
dnmembers = append(dnmembers, dn)
|
|
|
|
if _, ok := persondict[dn]; !ok {
|
|
|
|
allperson = append(allperson, dn)
|
|
|
|
persondict[dn] = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if department.DepartID > 1 {
|
|
|
|
if len(dnmembers) > 0 {
|
|
|
|
if !LdapGroupAdd(ldapconn, department.Name, department.Name, dnmembers) {
|
|
|
|
LdapGroupModify(ldapconn, department.Name, department.Name, dnmembers)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
log.Println(string(resp.Content()))
|
2022-05-30 10:43:28 +00:00
|
|
|
}
|
|
|
|
|
2022-08-11 01:26:56 +00:00
|
|
|
if len(allperson) > 0 {
|
|
|
|
if !LdapGroupAdd(ldapconn, "源典所有成员", "源典所有成员", allperson) {
|
|
|
|
LdapGroupModify(ldapconn, "源典所有成员", "源典所有成员", allperson)
|
|
|
|
}
|
2022-05-31 09:52:43 +00:00
|
|
|
}
|
2022-08-11 01:26:56 +00:00
|
|
|
|
2022-08-11 01:29:53 +00:00
|
|
|
cxt.Wait(time.Minute * 15)
|
2022-05-31 09:52:43 +00:00
|
|
|
})
|
2022-05-30 10:43:28 +00:00
|
|
|
|
|
|
|
}
|