aboutsummaryrefslogtreecommitdiff
path: root/invite.go
diff options
context:
space:
mode:
Diffstat (limited to 'invite.go')
-rw-r--r--invite.go144
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) {
+}