diff options
Diffstat (limited to '')
-rw-r--r-- | internal/webui/login.go | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/internal/webui/login.go b/internal/webui/login.go new file mode 100644 index 0000000..c0eb109 --- /dev/null +++ b/internal/webui/login.go @@ -0,0 +1,85 @@ +package webui + +import ( + "fmt" + "html/template" + "net/http" + "regexp" + + "git.adyxax.org/adyxax/trains/pkg/database" + "git.adyxax.org/adyxax/trains/pkg/model" +) + +const sessionCookieName = "session-trains-webui" + +var validUsername = regexp.MustCompile(`^[a-zA-Z]\w*$`) +var validPassword = regexp.MustCompile(`^.+$`) + +var loginTemplate = template.Must(template.ParseFS(templatesFS, "html/base.html", "html/login.html")) + +// The login handler of the webui +func loginHandler(e *env, w http.ResponseWriter, r *http.Request) error { + if r.URL.Path == "/login" { + _, err := tryAndResumeSession(e, r) + if err == nil { + // already logged in + http.Redirect(w, r, "/", http.StatusFound) + return nil + } + if r.Method == http.MethodPost { + r.ParseForm() + // username + username, ok := r.Form["username"] + if !ok { + return newStatusError(http.StatusBadRequest, fmt.Errorf("No username field in POST")) + } + if len(username) != 1 { + return newStatusError(http.StatusBadRequest, fmt.Errorf("Invalid multiple username fields in POST")) + } + if ok := validUsername.MatchString(username[0]); !ok { + return newStatusError(http.StatusBadRequest, fmt.Errorf("Invalid username field in POST")) + } + // password + password, ok := r.Form["password"] + if !ok { + return newStatusError(http.StatusBadRequest, fmt.Errorf("No password field in POST")) + } + if len(password) != 1 { + return newStatusError(http.StatusBadRequest, fmt.Errorf("Invalid multiple password fields in POST")) + } + if ok := validPassword.MatchString(password[0]); !ok { + return newStatusError(http.StatusBadRequest, fmt.Errorf("Invalid password field in POST")) + } + // try to login + user, err := e.dbEnv.Login(&model.UserLogin{Username: username[0], Password: password[0]}) + if err != nil { + switch e := err.(type) { + case *database.PasswordError: + // TODO : handle in page + return e + case *database.QueryError: + return e + default: + return e + } + } + token, err := e.dbEnv.CreateSession(user) + if err != nil { + return newStatusError(http.StatusInternalServerError, err) + } + cookie := http.Cookie{Name: sessionCookieName, Value: *token, Path: "/", HttpOnly: true, SameSite: http.SameSiteStrictMode, MaxAge: 3600000} + http.SetCookie(w, &cookie) + http.Redirect(w, r, "/", http.StatusFound) + return nil + } else { + p := Page{Title: "Login"} + err := loginTemplate.ExecuteTemplate(w, "login.html", p) + if err != nil { + return newStatusError(http.StatusInternalServerError, err) + } + return nil + } + } else { + return newStatusError(http.StatusNotFound, fmt.Errorf("Invalid path in loginHandler")) + } +} |