154 lines
4.0 KiB
Go
154 lines
4.0 KiB
Go
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"
|
|
"forge.capytal.company/loreddev/x/tinyssert"
|
|
)
|
|
|
|
type userController struct {
|
|
assert tinyssert.Assertions
|
|
templates templates.ITemplate
|
|
service *service.UserService
|
|
|
|
loginPath string
|
|
}
|
|
|
|
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)
|
|
|
|
if r.Method == http.MethodGet {
|
|
err := ctrl.templates.ExecuteTemplate(w, "login", 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
|
|
}
|
|
|
|
// 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{
|
|
Path: "/",
|
|
HttpOnly: true,
|
|
Name: "token",
|
|
Value: token,
|
|
}
|
|
http.SetCookie(w, cookie)
|
|
|
|
http.Redirect(w, r, "/", http.StatusSeeOther)
|
|
}
|
|
|
|
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{
|
|
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
|
|
}
|