package controllers import ( "net/http" "git.kirsle.net/apps/gophertype/pkg/authentication" "git.kirsle.net/apps/gophertype/pkg/console" "git.kirsle.net/apps/gophertype/pkg/constants" "git.kirsle.net/apps/gophertype/pkg/glue" "git.kirsle.net/apps/gophertype/pkg/models" "git.kirsle.net/apps/gophertype/pkg/ratelimit" "git.kirsle.net/apps/gophertype/pkg/responses" "git.kirsle.net/apps/gophertype/pkg/session" "github.com/albrow/forms" ) func init() { glue.Register(glue.Endpoint{ Path: "/login", Methods: []string{"GET", "POST"}, Handler: func(w http.ResponseWriter, r *http.Request) { // Template variables. v := responses.NewTemplateVars(w, r) // POST handler: create the admin account. for r.Method == http.MethodPost { form, _ := forms.Parse(r) v.FormValues = form.Values // Validate form parameters. val := form.Validator() val.Require("email") val.MatchEmail("email") val.Require("password") if val.HasErrors() { v.ValidationError = val.ErrorMap() break } // Rate limit failed login attempts. limiter := &ratelimit.Limiter{ Namespace: "login", ID: form.Get("email"), Limit: constants.LoginRateLimit, Window: constants.LoginRateLimitWindow, CooldownAt: constants.LoginRateLimitCooldownAt, Cooldown: constants.LoginRateLimitCooldown, } // Check authentication. user, err := models.Users.AuthenticateUser(form.Get("email"), form.Get("password")) if err != nil { if err := limiter.Ping(); err != nil { v.Error = err break } v.Error = err break } if err := limiter.Clear(); err != nil { console.Error("Failed to clear the login rate limiter: %s", err) } _ = user authentication.Login(w, r, user) session.Flash(w, r, "Signed in!") responses.Redirect(w, r, "/") // TODO: next URL return } responses.RenderTemplate(w, r, "_builtin/users/login.gohtml", v) }, }) glue.Register(glue.Endpoint{ Path: "/logout", Handler: func(w http.ResponseWriter, r *http.Request) { authentication.Logout(w, r) session.Flash(w, r, "Signed out!") responses.Redirect(w, r, "/") }, }) }