diff options
Diffstat (limited to 'invite.go')
-rw-r--r-- | invite.go | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/invite.go b/invite.go new file mode 100644 index 0000000..d078642 --- /dev/null +++ b/invite.go @@ -0,0 +1,144 @@ +package main + +import ( + "fmt" + "html/template" + "net/http" + "regexp" + "strings" + + "github.com/go-ldap/ldap/v3" +) + +func checkInviterLogin(w http.ResponseWriter, r *http.Request) *LoginStatus { + login := checkLogin(w, r) + if login == nil { + return nil + } + + if !login.CanInvite { + http.Error(w, "Not authorized to invite new users.", http.StatusUnauthorized) + return nil + } + + return login +} + +type NewAccountData struct { + Username string + DisplayName string + GivenName string + Surname string + + ErrorUsernameTaken bool + ErrorInvalidUsername bool + ErrorPasswordTooShort bool + ErrorPasswordMismatch bool + ErrorMessage string + WarningMessage string + Success bool +} + +func handleInviteNewAccount(w http.ResponseWriter, r *http.Request) { + templateInviteNewAccount := template.Must(template.ParseFiles("templates/layout.html", "templates/invite_new_account.html")) + + login := checkInviterLogin(w, r) + if login == nil { + return + } + + data := &NewAccountData{} + + if r.Method == "POST" { + r.ParseForm() + + data.Username = strings.TrimSpace(strings.Join(r.Form["username"], "")) + data.DisplayName = strings.TrimSpace(strings.Join(r.Form["displayname"], "")) + data.GivenName = strings.TrimSpace(strings.Join(r.Form["givenname"], "")) + data.Surname = strings.TrimSpace(strings.Join(r.Form["surname"], "")) + + password1 := strings.Join(r.Form["password"], "") + password2 := strings.Join(r.Form["password2"], "") + + tryCreateAccount(login.conn, data, password1, password2) + } + + templateInviteNewAccount.Execute(w, data) +} + +func tryCreateAccount(l *ldap.Conn, data *NewAccountData, pass1 string, pass2 string) { + // Check if username is correct + if match, err := regexp.MatchString("^[a-zA-Z0-9._-]+$", data.Username); !(err == nil && match) { + data.ErrorInvalidUsername = true + } + + // Check if user exists + userDn := config.UserNameAttr + "=" + data.Username + "," + config.UserBaseDN + searchRq := ldap.NewSearchRequest( + userDn, + ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false, + "(objectclass=*)", + []string{"dn"}, + nil) + + sr, err := l.Search(searchRq) + if err != nil { + data.ErrorMessage = err.Error() + return + } + + if len(sr.Entries) > 0 { + data.ErrorUsernameTaken = true + return + } + + // Check that password is long enough + if len(pass1) < 8 { + data.ErrorPasswordTooShort = true + return + } + + if pass1 != pass2 { + data.ErrorPasswordMismatch = true + return + } + + // Actually create user + req := ldap.NewAddRequest(userDn, nil) + req.Attribute("objectclass", []string{"inetOrgPerson", "organizationalPerson", "person", "top"}) + req.Attribute("structuralobjectclass", []string{"inetOrgPerson"}) + req.Attribute("userpassword", []string{SSHAEncode([]byte(pass1))}) + if len(data.DisplayName) > 0 { + req.Attribute("displayname", []string{data.DisplayName}) + } + if len(data.GivenName) > 0 { + req.Attribute("givenname", []string{data.GivenName}) + } + if len(data.Surname) > 0 { + req.Attribute("sn", []string{data.Surname}) + } + if len(config.InvitedMailFormat) > 0 { + email := strings.ReplaceAll(config.InvitedMailFormat, "{}", data.Username) + req.Attribute("mail", []string{email}) + } + + err = l.Add(req) + if err != nil { + data.ErrorMessage = err.Error() + return + } + + for _, group := range config.InvitedAutoGroups { + req := ldap.NewModifyRequest(group, nil) + req.Add("member", []string{userDn}) + err = l.Modify(req) + if err != nil { + data.WarningMessage += fmt.Sprintf("Cannot add to %s: %s\n", group, err.Error()) + } + } + + data.Success = true +} + +func handleInviteSendCode(w http.ResponseWriter, r *http.Request) { +} |