Nuestro burocrata preferido: Sam Lowry https://lowry.sindominio.net
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
lowry/server/add_user.go

242 lines
6.0 KiB

package server
import (
"crypto/rand"
"encoding/base64"
"fmt"
"log"
"net/http"
"regexp"
"git.sindominio.net/sindominio/lowry/ldap"
"github.com/gorilla/mux"
)
var (
validName = regexp.MustCompile(`^[a-z0-9][a-z0-9_\-]*$`)
// See https://ldpreload.com/blog/names-to-reserve
reservedNames = map[string]bool{
"abuse": true,
"abuso": true,
"admin": true,
"administrator": true,
"administrador": true,
"autoconfig": true,
"broadcasthost": true,
"crossdomain.xml": true,
"clientaccesspolicy.xml": true,
"css": true,
"favicon.ico": true,
"ftp": true,
"hostmaster": true,
"html": true,
"imap": true,
"img": true,
"info": true,
"is": true,
"isatap": true,
"it": true,
"js": true,
"javascript": true,
"localdomain": true,
"localhost": true,
"mail": true,
"mailer-daemon": true,
"marketing": true,
"mis": true,
"news": true,
"nobody": true,
"noc": true,
"noreply": true,
"no-reply": true,
"pop": true,
"pop3": true,
"postmaster": true,
"pub": true,
"public": true,
"public_html": true,
"robots.txt": true,
"root": true,
"sales": true,
"sd": true,
"security": true,
"sindominio": true,
"ssladmin": true,
"ssladministrator": true,
"sslwebmaster": true,
"stadisticas": true,
"stats": true,
"statistics": true,
"soporte": true,
"support": true,
"sysadmin": true,
"usenet": true,
"uucp": true,
"webmaster": true,
"www": true,
"wpad": true,
".well-known": true,
}
)
func (s *server) listInvitesHandler(w http.ResponseWriter, r *http.Request) {
response := s.newResponse("invites", w, r)
invites, err := s.db.ListUserInvites(response.User)
if err != nil {
log.Printf("An error has ocurred listing invites: %v", err)
s.errorHandler(w, r)
return
}
response.execute(invites)
}
func (s *server) deleteInviteHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
invite := vars["invite"]
response := s.newResponse("invites", w, r)
user, err := s.db.InviteHost(invite)
if err != nil {
log.Printf("An error has ocurred getting invite: %v", err)
s.errorHandler(w, r)
return
}
if user != response.User {
log.Printf("No owner attemp to delete an invite, user: %s, invite: %s", response.User, invite)
s.forbiddenHandler(w, r)
return
}
err = s.db.DelInvite(invite)
if err != nil {
log.Printf("An error has ocurred deleting invite %s: %v", invite, err)
s.errorHandler(w, r)
return
}
http.Redirect(w, r, r.Referer(), http.StatusFound)
}
func (s *server) createInviteHandler(w http.ResponseWriter, r *http.Request) {
response := s.newResponse("invite", w, r)
if response.Role != ldap.Sindominante {
log.Printf("Non sindominante attemp to create an invite, user: %s", response.User)
s.forbiddenHandler(w, r)
return
}
buff := make([]byte, 9)
_, err := rand.Read(buff)
if err != nil {
log.Printf("An error has ocurred generating a random invite: %v", err)
s.addUserGroupHandler(w, r)
return
}
invite := base64.URLEncoding.EncodeToString(buff)
err = s.db.AddInvite(invite, response.User)
if err != nil {
log.Printf("An error has ocurred storing the invite (%s - %s): %v", invite, response.User, err)
s.addUserGroupHandler(w, r)
return
}
inviteURL := fmt.Sprintf("https://%v/adduser/%v", r.Host, invite)
response.execute(struct {
InviteURL string
}{inviteURL})
}
func (s *server) addUserHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
invite := vars["invite"]
if !s.db.IsInviteValid(invite) {
log.Printf("Invalid invite code: %s", invite)
s.forbiddenHandler(w, r)
return
}
response := s.newResponse("adduser", w, r)
if r.Method != "POST" {
response.execute("")
return
}
name := r.FormValue("name")
pass := r.FormValue("password")
pass2 := r.FormValue("password2")
if pass != pass2 {
response.execute("WrongPass")
return
}
if name == "" || pass == "" {
response.execute("empty")
return
}
if !validUserName(name) {
log.Println("Can't create user ", name, ": invalid name")
response.execute("exists")
return
}
_, err := s.ldap.GetUser(name)
if err == nil {
log.Println("Can't create user ", name, ": already exists")
response.execute("exists")
return
}
err = s.ldap.AddGroup(name)
if err != nil {
log.Println("Error adding group: ", err)
s.errorHandler(w, r)
return
}
group, err := s.ldap.GetGroup(name)
if err != nil {
log.Println("Error getting group: ", err)
s.errorHandler(w, r)
return
}
err = s.ldap.AddUser(name, pass, group.GID)
if err != nil {
log.Println("Error adding user: ", err)
s.errorHandler(w, r)
return
}
host, err := s.db.InviteHost(invite)
if err != nil {
log.Println("Error getting invite host: ", err)
} else {
err = s.db.AddAccount(name, host)
if err != nil {
log.Println("Error adding account: ", err)
}
}
err = s.db.DelInvite(invite)
if err != nil {
log.Println("Error deleting invite: ", err)
}
err = s.mail.Send([]string{name}, "wellcome", name)
if err != nil {
log.Println("Error sending wellcome mail: ", err)
}
response = s.newResponse("adduser_success", w, r)
response.execute("name")
}
func validUserName(name string) bool {
if len(name) < 3 {
return false
}
if reservedNames[name] {
return false
}
return validName.MatchString(name)
}