123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- package main
- import (
- "bufio"
- "bytes"
- "crypto/tls"
- "fmt"
- "log"
- "os"
- "github.com/sethvargo/go-password/password"
- gomail "gopkg.in/gomail.v2"
- ldap "gopkg.in/ldap.v2"
- "text/template"
- tpl_util "gogs.carducci-dante.gov.it/andrea.fazzi/karmen/util/template"
- karmen_client "gogs.carducci-dante.gov.it/karmen/client"
- "gogs.carducci-dante.gov.it/karmen/core/orm"
- karmen_ldap "gogs.carducci-dante.gov.it/karmen/ldap"
- )
- const (
- Remove = iota + 1
- Add
- Update
- )
- type Action struct {
- Id int
- Type int
- }
- var actDict = map[int]string{
- 1: "REMOVE",
- 2: "ADD",
- 3: "UPDATE",
- }
- func diff(dst []string, src []string, excludes []string) map[string]*Action {
- actions := make(map[string]*Action)
- for id, el := range dst {
- if !excluded(excludes, el) {
- actions[el] = &Action{id, Remove}
- }
- }
- for id, el := range src {
- _, ok := actions[el]
- if !ok {
- actions[el] = &Action{id, Add}
- continue
- }
- actions[el] = &Action{id, Update}
- }
- return actions
- }
- func entriesToSliceFunc(elements []*ldap.Entry, fn func(*ldap.Entry) string) (result []string) {
- for _, el := range elements {
- result = append(result, fn(el))
- }
- return result
- }
- func teachersToSliceFunc(elements []*orm.Teacher, fn func(*orm.Teacher) string) (result []string) {
- for _, el := range elements {
- result = append(result, fn(el))
- }
- return result
- }
- func excluded(excludes []string, name string) bool {
- for _, excluded := range excludes {
- if name == excluded {
- return true
- }
- }
- return false
- }
- func filterTeachers(teachers []*orm.Teacher, excludes []string) []*orm.Teacher {
- fTeachers := teachers[:0]
- for _, t := range teachers {
- if t.Name != "Senza nome" && !excluded(excludes, t.CompleteName()) {
- fTeachers = append(fTeachers, t)
- }
- }
- return fTeachers
- }
- func sendMail(teacher *orm.Teacher, tpl *template.Template, dryRun bool) error {
- var buf bytes.Buffer
- err := tpl.Execute(&buf, teacher)
- if err != nil {
- return err
- }
- log.Printf("Send mail to %s", teacher.AltEmail)
- if !dryRun {
- m := gomail.NewMessage()
- m.SetHeader("From", "karmen@carducci-dante.gov.it")
- m.SetHeader("To", teacher.AltEmail)
- //m.SetHeader("To", "segreteria.automatica@carducci-dante.gov.it")
- m.SetHeader("Subject", "Credenziali servizi informatici del Liceo \"Carducci-Dante\" di Trieste")
- m.SetBody("text/plain", buf.String())
- d := gomail.NewDialer("mail.carducci-dante.gov.it", 25, "karmen", `Kq&&mZ3s5Bdg>"*V~"X+`)
- d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
- if err := d.DialAndSend(m); err != nil {
- return err
- }
- }
- return nil
- }
- func syncTeachers(ldapClient *karmen_ldap.Client, karmenClient *karmen_client.Client, ldapTeachers []*ldap.Entry, teachers []*orm.Teacher, excludes []string, mailTpl *template.Template) error {
- actions := diff(
- entriesToSliceFunc(ldapTeachers, func(entry *ldap.Entry) string { return entry.DN }),
- teachersToSliceFunc(teachers, func(t *orm.Teacher) string { return ldapClient.TeacherDN(t) }),
- excludes,
- )
- for el, act := range actions {
- switch act.Type {
- case Remove:
- err := ldapClient.DeleteByDN(el)
- if err != nil {
- return err
- }
- case Add:
- teacher := teachers[act.Id]
- log.Printf("ADD teacher %s", teacher.CompleteName())
- password, err := password.Generate(8, 2, 0, false, true)
- if err != nil {
- return err
- }
- teacher.PlainPassword = password
- err = ldapClient.AddTeacher(teacher)
- if err != nil {
- panic(err)
- }
- if !teacher.MailSent {
- log.Printf("Sending credentials to %s, pw is %s", teacher.AltEmail, teacher.PlainPassword)
- err = sendMail(teacher, mailTpl, false)
- if err != nil {
- return err
- }
- teacher.MailSent = true
- err = karmenClient.UpdateTeacher(teacher)
- if err != nil {
- return err
- }
- }
- // case Update:
- // // teacher := teachers[act.Id]
- // // log.Printf("UPDATE teacher %s", teacher.CompleteName())
- // // err = ldapClient.UpdateTeacher(teacher)
- // // if err != nil {
- // // panic(err)
- // // }
- }
- }
- return nil
- }
- func syncMailingList(ldapClient *karmen_ldap.Client, teachers []*orm.Teacher, excludes []string, groupDN string) error {
- entries, err := ldapClient.GroupMembers(groupDN)
- if err != nil {
- return err
- }
- actions := diff(
- entries[0].Attributes[0].Values,
- teachersToSliceFunc(teachers, func(t *orm.Teacher) string { return ldapClient.TeacherDN(t) }),
- excludes,
- )
- for el, act := range actions {
- switch act.Type {
- case Remove:
- log.Printf("REMOVE teacher %s from %s", el, groupDN)
- ldapClient.RemoveTeacherFromGroupByMemberValue(el, groupDN)
- case Add:
- log.Printf("ADD teacher %s to %s", el, groupDN)
- teacher := teachers[act.Id]
- err = ldapClient.AddTeacherToGroup(teacher, groupDN)
- if err != nil {
- panic(err)
- }
- }
- }
- return nil
- }
- func syncTeachersGroup(ldapClient *karmen_ldap.Client, teachers []*orm.Teacher, excludes []string, groupDN string) error {
- entries, err := ldapClient.GroupMembers(groupDN)
- if err != nil {
- return err
- }
- actions := diff(
- entries[0].Attributes[0].Values,
- teachersToSliceFunc(teachers, func(t *orm.Teacher) string { return t.GenerateUsername() }),
- excludes,
- )
- for el, act := range actions {
- switch act.Type {
- case Remove:
- log.Printf("REMOVE teacher %s from %s", el, groupDN)
- ldapClient.RemoveTeacherFromGroupByMemberValue(el, groupDN)
- case Add:
- log.Printf("ADD teacher %s to %s", el, groupDN)
- teacher := teachers[act.Id]
- err = ldapClient.AddTeacherToGroup(teacher, groupDN)
- if err != nil {
- panic(err)
- }
- }
- }
- return nil
- }
- func main() {
- log.Printf("Connecting to karmen at %s...", "https://karmen.andreafazzi.eu")
- karmenClient, err := karmen_client.Dial("https://karmen.andreafazzi.eu", "admin", "aolieVooju")
- if err != nil {
- panic(err)
- }
- teachers, err := karmenClient.GetTeachers()
- if err != nil {
- panic(err)
- }
- departments, err := karmenClient.GetDepartments()
- if err != nil {
- panic(err)
- }
- conf := &karmen_ldap.Config{
- Domain: "carducci-dante.gov.it",
- AdminCN: "admin",
- AdminPassword: "CDlinux2016",
- TeachersDN: "ou=Docenti,ou=Persone",
- GroupsDN: "ou=Gruppi",
- PeopleDN: "ou=Persone",
- MailDirPath: "/var/mail/carducci-dante.gov.it",
- MailQuota: "10240",
- FirstUIDNumber: "5000",
- MailGIDNumber: "5000",
- }
- log.Printf("Connecting to LDAP at %s...", "ldap.carducci-dante.gov.it:389")
- ldapClient, err := karmen_ldap.NewClient("ldap.carducci-dante.gov.it:389", conf)
- if err != nil {
- panic(err)
- }
- log.Println("Getting LDAP registered teachers...")
- ldapTeachers, err := ldapClient.Teachers()
- if err != nil {
- panic(err)
- }
- excludes := make([]string, 0)
- log.Print("Read excludes...")
- f, err := os.Open("./excludes.txt")
- defer f.Close()
- if err != nil {
- log.Println(err)
- } else {
- scanner := bufio.NewScanner(f)
- for scanner.Scan() {
- excludes = append(excludes, scanner.Text())
- }
- if err := scanner.Err(); err != nil {
- panic(err)
- }
- }
- tpl, err := tpl_util.LoadTextTemplate("mail.tpl")
- if err != nil {
- panic(err)
- }
- fTeachers := filterTeachers(teachers, excludes)
- err = syncTeachers(ldapClient, karmenClient, ldapTeachers, fTeachers, excludes, tpl)
- if err != nil {
- panic(err)
- }
- for _, department := range departments {
- group := fmt.Sprintf("cn=%s,ou=Mailing Lists", department.Name)
- err = syncMailingList(ldapClient, filterTeachers(department.Teachers, excludes), excludes, group)
- if err != nil {
- panic(err)
- }
- group = fmt.Sprintf("cn=%s,ou=Dipartimenti", department.Name)
- err = syncTeachersGroup(ldapClient, filterTeachers(department.Teachers, excludes), excludes, group)
- if err != nil {
- panic(err)
- }
- }
- err = syncTeachersGroup(ldapClient, fTeachers, excludes, "cn=Docenti")
- if err != nil {
- panic(err)
- }
- }
|