diff --git a/handlers/login.go b/handlers/login.go index c4da38b..2b5f4a3 100644 --- a/handlers/login.go +++ b/handlers/login.go @@ -48,7 +48,6 @@ func HandleLoginRequest( config *config.Config, logger *zerolog.Logger, conn *sql.DB, - secretKey string, ) http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { diff --git a/handlers/logout.go b/handlers/logout.go new file mode 100644 index 0000000..c8999a2 --- /dev/null +++ b/handlers/logout.go @@ -0,0 +1,62 @@ +package handlers + +import ( + "database/sql" + "net/http" + "projectreshoot/config" + "projectreshoot/cookies" + "projectreshoot/jwt" + + "github.com/pkg/errors" + "github.com/rs/zerolog" +) + +// Retrieve and revoke the user's tokens +func revokeTokens( + config *config.Config, + conn *sql.DB, + r *http.Request, +) error { + // get the tokens from the cookies + atStr, rtStr := cookies.GetTokenStrings(r) + aT, err := jwt.ParseAccessToken(config, conn, atStr) + if err != nil { + return errors.Wrap(err, "jwt.ParseAccessToken") + } + rT, err := jwt.ParseRefreshToken(config, conn, rtStr) + if err != nil { + return errors.Wrap(err, "jwt.ParseRefreshToken") + } + // revoke the refresh token first as the access token expires quicker + // only matters if there is an error revoking the tokens + err = jwt.RevokeToken(conn, rT) + if err != nil { + return errors.Wrap(err, "jwt.RevokeToken") + } + err = jwt.RevokeToken(conn, aT) + if err != nil { + return errors.Wrap(err, "jwt.RevokeToken") + } + return nil +} + +// Handle a logout request +func HandleLogout( + config *config.Config, + logger *zerolog.Logger, + conn *sql.DB, +) http.Handler { + return http.HandlerFunc( + func(w http.ResponseWriter, r *http.Request) { + err := revokeTokens(config, conn, r) + if err != nil { + logger.Error().Err(err).Msg("Error occured on user logout") + w.WriteHeader(http.StatusInternalServerError) + return + } + cookies.DeleteCookie(w, "access", "/") + cookies.DeleteCookie(w, "refresh", "/") + w.Header().Set("HX-Redirect", "/login") + }, + ) +} diff --git a/server/routes.go b/server/routes.go index 866b0e7..8576910 100644 --- a/server/routes.go +++ b/server/routes.go @@ -36,8 +36,9 @@ func addRoutes( config, logger, conn, - config.SecretKey, )) + // Logout + mux.Handle("POST /logout", handlers.HandleLogout(config, logger, conn)) // Profile page } diff --git a/static/css/input.css b/static/css/input.css index eeaeab5..c3b1527 100644 --- a/static/css/input.css +++ b/static/css/input.css @@ -1,12 +1,16 @@ @import url("https://fonts.googleapis.com/css2?family=Ubuntu+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap"); @import "tailwindcss"; +[x-cloak] { + display: none !important; +} @theme inline { --color-rosewater: var(--rosewater); --color-flamingo: var(--flamingo); --color-pink: var(--pink); --color-mauve: var(--mauve); --color-red: var(--red); + --color-dark-red: var(--dark-red); --color-maroon: var(--maroon); --color-peach: var(--peach); --color-yellow: var(--yellow); @@ -35,6 +39,7 @@ --pink: hsl(316, 73%, 69%); --mauve: hsl(266, 85%, 58%); --red: hsl(347, 87%, 44%); + --dark-red: hsl(343, 50%, 82%); --maroon: hsl(355, 76%, 59%); --peach: hsl(22, 99%, 52%); --yellow: hsl(35, 77%, 49%); @@ -64,6 +69,7 @@ --pink: hsl(316, 72%, 86%); --mauve: hsl(267, 84%, 81%); --red: hsl(343, 81%, 75%); + --dark-red: hsl(316, 19%, 27%); --maroon: hsl(350, 65%, 77%); --peach: hsl(23, 92%, 75%); --yellow: hsl(41, 86%, 83%); diff --git a/view/component/errorPopup.templ b/view/component/errorPopup.templ new file mode 100644 index 0000000..968beab --- /dev/null +++ b/view/component/errorPopup.templ @@ -0,0 +1,63 @@ +package component + +templ ErrorPopup() { +
+ An error occured on the server. Please try again later, + or contact an administrator +
+