Files
comicverse/router/user.go

154 lines
4.0 KiB
Go
Raw Normal View History

2025-05-30 18:05:40 -03:00
package router
import (
"errors"
"net/http"
"forge.capytal.company/capytalcode/project-comicverse/service"
"forge.capytal.company/capytalcode/project-comicverse/templates"
"forge.capytal.company/loreddev/x/smalltrip/exception"
"forge.capytal.company/loreddev/x/smalltrip/middleware"
2025-05-30 18:05:40 -03:00
"forge.capytal.company/loreddev/x/tinyssert"
)
type userController struct {
assert tinyssert.Assertions
templates templates.ITemplate
service *service.UserService
loginPath string
2025-05-30 18:05:40 -03:00
}
func newUserController(
service *service.UserService,
templates templates.ITemplate,
assert tinyssert.Assertions,
) userController {
return userController{
assert: assert,
templates: templates,
service: service,
}
}
func (ctrl userController) login(w http.ResponseWriter, r *http.Request) {
ctrl.assert.NotNil(ctrl.templates)
ctrl.assert.NotNil(ctrl.service)
2025-05-30 18:05:40 -03:00
if r.Method == http.MethodGet {
err := ctrl.templates.ExecuteTemplate(w, "login", nil)
2025-05-30 18:05:40 -03:00
if err != nil {
exception.InternalServerError(err).ServeHTTP(w, r)
}
return
}
if r.Method != http.MethodPost {
exception.MethodNotAllowed([]string{http.MethodGet, http.MethodPost}).
ServeHTTP(w, r)
return
}
user, passwd := r.FormValue("username"), r.FormValue("password")
if user == "" {
exception.BadRequest(errors.New(`missing "username" form value`)).ServeHTTP(w, r)
2025-05-30 18:05:40 -03:00
return
}
if passwd == "" {
exception.BadRequest(errors.New(`missing "password" form value`)).ServeHTTP(w, r)
return
}
// TODO: Move token issuing to it's own service, make UserService.Login just return the user
token, _, err := ctrl.service.Login(user, passwd)
if errors.Is(err, service.ErrNotFound) {
exception.NotFound(exception.WithError(errors.New("user not found"))).ServeHTTP(w, r)
return
} else if err != nil {
exception.InternalServerError(err).ServeHTTP(w, r)
return
}
// TODO: harden the cookie policy to the same domain
cookie := &http.Cookie{
2025-06-09 19:19:00 -03:00
Path: "/",
HttpOnly: true,
Name: "token",
Value: token,
}
http.SetCookie(w, cookie)
http.Redirect(w, r, "/", http.StatusSeeOther)
2025-05-30 18:05:40 -03:00
}
func (ctrl userController) register(w http.ResponseWriter, r *http.Request) {
ctrl.assert.NotNil(ctrl.templates)
ctrl.assert.NotNil(ctrl.service)
if r.Method == http.MethodGet {
err := ctrl.templates.ExecuteTemplate(w, "register", nil)
if err != nil {
exception.InternalServerError(err).ServeHTTP(w, r)
}
return
}
if r.Method != http.MethodPost {
exception.MethodNotAllowed([]string{http.MethodGet, http.MethodPost}).ServeHTTP(w, r)
return
}
user, passwd := r.FormValue("username"), r.FormValue("password")
if user == "" {
exception.BadRequest(errors.New(`missing "username" form value`)).ServeHTTP(w, r)
return
}
if passwd == "" {
exception.BadRequest(errors.New(`missing "password" form value`)).ServeHTTP(w, r)
return
}
_, err := ctrl.service.Register(user, passwd)
if err != nil {
exception.InternalServerError(err).ServeHTTP(w, r)
return
}
// TODO: Move token issuing to it's own service, make UserService.Login just return the user
token, _, err := ctrl.service.Login(user, passwd)
if err == service.ErrNotFound {
exception.NotFound(exception.WithError(errors.New("user not found"))).ServeHTTP(w, r)
return
} else if err != nil {
exception.InternalServerError(err).ServeHTTP(w, r)
return
}
// TODO: harden the cookie policy to the same domain
cookie := &http.Cookie{
2025-06-09 19:19:00 -03:00
Path: "/",
HttpOnly: true,
Name: "token",
Value: token,
}
http.SetCookie(w, cookie)
http.Redirect(w, r, "/", http.StatusSeeOther)
}
func (ctrl userController) authMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if ctrl.isLogged(r) {
http.Redirect(w, r, ctrl.loginPath, http.StatusTemporaryRedirect)
}
next.ServeHTTP(w, r)
})
}
var _ middleware.Middleware = userController{}.authMiddleware
func (ctrl userController) isLogged(r *http.Request) bool {
// TODO: Check if token in valid (depends on token service being implemented)
cs := r.CookiesNamed("token")
return len(cs) > 0
}