gophertype/pkg/controllers/authentication.go

86 lines
2.2 KiB
Go

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, "/")
},
})
}