From 4c83126ed6ea601f692aa7315093c64cc8aad09c Mon Sep 17 00:00:00 2001 From: Haelnorr Date: Sat, 22 Feb 2025 17:12:02 +1100 Subject: [PATCH 1/8] Updated prod deploy to use new deploy script --- .github/workflows/deploy_production.yaml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy_production.yaml b/.github/workflows/deploy_production.yaml index aafd99f..058d43d 100644 --- a/.github/workflows/deploy_production.yaml +++ b/.github/workflows/deploy_production.yaml @@ -33,11 +33,15 @@ jobs: - name: Build the binary run: make build SUFFIX=-production-$GITHUB_SHA + - name: Build the migration binary + run: make migrate SUFFIX=-production-$GITHUB_SHA + - name: Deploy to Server env: USER: deploy HOST: projectreshoot.com DIR: /home/deploy/releases/production + MIG_DIR: /home/deploy/migration-bin DEPLOY_SSH_PRIVATE_KEY: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }} run: | mkdir -p ~/.ssh @@ -49,7 +53,13 @@ jobs: echo " UserKnownHostsFile /dev/null" >> ~/.ssh/config ssh -i ~/.ssh/id_ed25519 $USER@$HOST mkdir -p $DIR - scp -i ~/.ssh/id_ed25519 projectreshoot-production-${GITHUB_SHA} $USER@$HOST:$DIR - ssh -i ~/.ssh/id_ed25519 $USER@$HOST 'bash -s' < ./deploy/deploy_production.sh $GITHUB_SHA + ssh -i ~/.ssh/id_ed25519 $USER@$HOST mkdir -p $MIG_DIR + scp -i ~/.ssh/id_ed25519 prmigrate-production-${GITHUB_SHA} $USER@$HOST:$MIG_DIR + + scp -i ~/.ssh/id_ed25519 ./deploy/db/backup.sh $USER@$HOST:$MIG_DIR + scp -i ~/.ssh/id_ed25519 ./deploy/db/migrate.sh $USER@$HOST:$MIG_DIR + scp -i ~/.ssh/id_ed25519 ./deploy/db/migrationcleanup.sh $USER@$HOST:$MIG_DIR + + ssh -i ~/.ssh/id_ed25519 $USER@$HOST 'bash -s' < ./deploy/deploy.sh $GITHUB_SHA production From c52d546fb1bf9eb8d4d2cb669ae25e14f015550d Mon Sep 17 00:00:00 2001 From: Haelnorr Date: Sat, 22 Feb 2025 17:12:36 +1100 Subject: [PATCH 2/8] Deleted old deploy scripts --- deploy/deploy_production.sh | 94 ------------------------------------- deploy/deploy_staging.sh | 94 ------------------------------------- 2 files changed, 188 deletions(-) delete mode 100644 deploy/deploy_production.sh delete mode 100644 deploy/deploy_staging.sh diff --git a/deploy/deploy_production.sh b/deploy/deploy_production.sh deleted file mode 100644 index bc47915..0000000 --- a/deploy/deploy_production.sh +++ /dev/null @@ -1,94 +0,0 @@ -#!/bin/bash - -# Exit on error -set -e - -# Check if commit hash is passed as an argument -if [ -z "$1" ]; then - echo "Usage: $0 " - exit 1 -fi - -COMMIT_HASH=$1 -RELEASES_DIR="/home/deploy/releases/production" -DEPLOY_BIN="/home/deploy/production/projectreshoot" -SERVICE_NAME="projectreshoot" -BINARY_NAME="projectreshoot-production-${COMMIT_HASH}" -declare -a PORTS=("3000" "3001" "3002") - -# Check if the binary exists -if [ ! -f "${RELEASES_DIR}/${BINARY_NAME}" ]; then - echo "Binary ${BINARY_NAME} not found in ${RELEASES_DIR}" - exit 1 -fi - -# Keep a reference to the previous binary from the symlink -if [ -L "${DEPLOY_BIN}" ]; then - PREVIOUS=$(readlink -f $DEPLOY_BIN) - echo "Current binary is ${PREVIOUS}, saved for rollback." -else - echo "No symbolic link found, no previous binary to backup." - PREVIOUS="" -fi - -rollback_deployment() { - if [ -n "$PREVIOUS" ]; then - echo "Rolling back to previous binary: ${PREVIOUS}" - ln -sfn "${PREVIOUS}" "${DEPLOY_BIN}" - else - echo "No previous binary to roll back to." - fi - - # wait to restart the services - sleep 10 - - # Restart all services with the previous binary - for port in "${PORTS[@]}"; do - SERVICE="${SERVICE_NAME}@${port}.service" - echo "Restarting $SERVICE..." - sudo systemctl restart $SERVICE - done - - echo "Rollback completed." -} - -# Copy the binary to the deployment directory -echo "Promoting ${BINARY_NAME} to ${DEPLOY_BIN}..." -ln -sf "${RELEASES_DIR}/${BINARY_NAME}" "${DEPLOY_BIN}" - -WAIT_TIME=5 -restart_service() { - local port=$1 - local SERVICE="${SERVICE_NAME}@${port}.service" - echo "Restarting ${SERVICE}..." - - # Restart the service - if ! sudo systemctl restart "$SERVICE"; then - echo "Error: Failed to restart ${SERVICE}. Rolling back deployment." - - # Call the rollback function - rollback_deployment - exit 1 - fi - - # Wait a few seconds to allow the service to fully start - echo "Waiting for ${SERVICE} to fully start..." - sleep $WAIT_TIME - - # Check the status of the service - if ! systemctl is-active --quiet "${SERVICE}"; then - echo "Error: ${SERVICE} failed to start correctly. Rolling back deployment." - - # Call the rollback function - rollback_deployment - exit 1 - fi - - echo "${SERVICE}.service restarted successfully." -} - -for port in "${PORTS[@]}"; do - restart_service $port -done - -echo "Deployment completed successfully." diff --git a/deploy/deploy_staging.sh b/deploy/deploy_staging.sh deleted file mode 100644 index 3ada4c5..0000000 --- a/deploy/deploy_staging.sh +++ /dev/null @@ -1,94 +0,0 @@ -#!/bin/bash - -# Exit on error -set -e - -# Check if commit hash is passed as an argument -if [ -z "$1" ]; then - echo "Usage: $0 " - exit 1 -fi - -COMMIT_HASH=$1 -RELEASES_DIR="/home/deploy/releases/staging" -DEPLOY_BIN="/home/deploy/staging/projectreshoot" -SERVICE_NAME="staging.projectreshoot" -BINARY_NAME="projectreshoot-staging-${COMMIT_HASH}" -declare -a PORTS=("3005" "3006" "3007") - -# Check if the binary exists -if [ ! -f "${RELEASES_DIR}/${BINARY_NAME}" ]; then - echo "Binary ${BINARY_NAME} not found in ${RELEASES_DIR}" - exit 1 -fi - -# Keep a reference to the previous binary from the symlink -if [ -L "${DEPLOY_BIN}" ]; then - PREVIOUS=$(readlink -f $DEPLOY_BIN) - echo "Current binary is ${PREVIOUS}, saved for rollback." -else - echo "No symbolic link found, no previous binary to backup." - PREVIOUS="" -fi - -rollback_deployment() { - if [ -n "$PREVIOUS" ]; then - echo "Rolling back to previous binary: ${PREVIOUS}" - ln -sfn "${PREVIOUS}" "${DEPLOY_BIN}" - else - echo "No previous binary to roll back to." - fi - - # wait to restart the services - sleep 10 - - # Restart all services with the previous binary - for port in "${PORTS[@]}"; do - SERVICE="${SERVICE_NAME}@${port}.service" - echo "Restarting $SERVICE..." - sudo systemctl restart $SERVICE - done - - echo "Rollback completed." -} - -# Copy the binary to the deployment directory -echo "Promoting ${BINARY_NAME} to ${DEPLOY_BIN}..." -ln -sf "${RELEASES_DIR}/${BINARY_NAME}" "${DEPLOY_BIN}" - -WAIT_TIME=5 -restart_service() { - local port=$1 - local SERVICE="${SERVICE_NAME}@${port}.service" - echo "Restarting ${SERVICE}..." - - # Restart the service - if ! sudo systemctl restart "$SERVICE"; then - echo "Error: Failed to restart ${SERVICE}. Rolling back deployment." - - # Call the rollback function - rollback_deployment - exit 1 - fi - - # Wait a few seconds to allow the service to fully start - echo "Waiting for ${SERVICE} to fully start..." - sleep $WAIT_TIME - - # Check the status of the service - if ! systemctl is-active --quiet "${SERVICE}"; then - echo "Error: ${SERVICE} failed to start correctly. Rolling back deployment." - - # Call the rollback function - rollback_deployment - exit 1 - fi - - echo "${SERVICE}.service restarted successfully." -} - -for port in "${PORTS[@]}"; do - restart_service $port -done - -echo "Deployment completed successfully." From 21d54520553d518616f9b5187ac23dc333098795 Mon Sep 17 00:00:00 2001 From: Haelnorr Date: Sat, 22 Feb 2025 17:54:34 +1100 Subject: [PATCH 3/8] Changed remote_addr to use X-Forwarded-For header --- middleware/logging.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleware/logging.go b/middleware/logging.go index fe9caf2..472d716 100644 --- a/middleware/logging.go +++ b/middleware/logging.go @@ -44,7 +44,7 @@ func Logging(logger *zerolog.Logger, next http.Handler) http.Handler { Str("method", r.Method). Str("resource", r.URL.Path). Dur("time_elapsed", time.Since(start)). - Str("remote_addr", r.RemoteAddr). + Str("remote_addr", r.Header.Get("X-Forwarded-For")). Msg("Served") }) } From 9410056dfb9abfe611353531028e8f45ca01e194 Mon Sep 17 00:00:00 2001 From: Haelnorr Date: Sat, 22 Feb 2025 19:36:17 +1100 Subject: [PATCH 4/8] Updated caddyfile to use rate limiting and connection limits --- deploy/caddy/Caddyfile | 62 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/deploy/caddy/Caddyfile b/deploy/caddy/Caddyfile index 7f29089..b0f4573 100644 --- a/deploy/caddy/Caddyfile +++ b/deploy/caddy/Caddyfile @@ -1,12 +1,58 @@ projectreshoot.com { - reverse_proxy localhost:3000 localhost:3001 localhost:3002 { - health_uri /healthz - fail_duration 30s - } + rate_limit { + zone auth { + match { + method POST + path /login /register + } + key {remote_host} + events 4 + window 1m + } + zone client { + key {remote_host} + events 100 + window 1m + } + } + reverse_proxy localhost:3000 localhost:3001 localhost:3002 { + transport http { + max_conns_per_host 10 + } + health_uri /healthz + fail_duration 30s + } + log { + output file /var/log/caddy/access.log + } } + staging.projectreshoot.com { - reverse_proxy localhost:3005 localhost:3006 localhost:3007 { - health_uri /healthz - fail_duration 30s - } + rate_limit { + zone auth { + match { + method POST + path /login /register + } + key {remote_host} + events 4 + window 1m + } + zone client { + key {remote_host} + events 100 + window 1m + } + } + reverse_proxy localhost:3005 localhost:3006 localhost:3007 { + transport http { + max_conns_per_host 10 + } + health_uri /healthz + fail_duration 30s + } + log { + output file /var/log/caddy/access-staging.log + } } + From c9fd1c8af0750c1ab22b44c688b8a6cf18b4dcbe Mon Sep 17 00:00:00 2001 From: Haelnorr Date: Sat, 22 Feb 2025 20:02:27 +1100 Subject: [PATCH 5/8] Fixed null user being returned if id not in database --- db/user_functions.go | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/db/user_functions.go b/db/user_functions.go index 28d30ad..6dd76d4 100644 --- a/db/user_functions.go +++ b/db/user_functions.go @@ -56,21 +56,21 @@ func fetchUserData( return rows, nil } -// Scan the next row into the provided user pointer. Calls rows.Next() and -// assumes only row in the result. Providing a rows object with more than 1 -// row may result in undefined behaviour. +// Calls rows.Next() and scans the row into the provided user pointer. +// Will error if no row available func scanUserRow(user *User, rows *sql.Rows) error { - for rows.Next() { - err := rows.Scan( - &user.ID, - &user.Username, - &user.Password_hash, - &user.Created_at, - &user.Bio, - ) - if err != nil { - return errors.Wrap(err, "rows.Scan") - } + if !rows.Next() { + return errors.New("User not found") + } + err := rows.Scan( + &user.ID, + &user.Username, + &user.Password_hash, + &user.Created_at, + &user.Bio, + ) + if err != nil { + return errors.Wrap(err, "rows.Scan") } return nil } From 41c195507d152bdc734147b2a7c38a882cac4146 Mon Sep 17 00:00:00 2001 From: Haelnorr Date: Sat, 22 Feb 2025 20:05:16 +1100 Subject: [PATCH 6/8] Updated go version to 1.24.0 --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 16638f8..f15482c 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module projectreshoot -go 1.23.5 +go 1.24.0 require ( github.com/a-h/templ v0.3.833 From 0a3796914f99915b524f757ce08a0cf0043c54d1 Mon Sep 17 00:00:00 2001 From: Haelnorr Date: Sat, 22 Feb 2025 20:06:17 +1100 Subject: [PATCH 7/8] Fixed labels for login/register form 'form="email"' should be username --- view/component/form/loginform.templ | 2 +- view/component/form/registerform.templ | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/view/component/form/loginform.templ b/view/component/form/loginform.templ index d6fa4a8..4407288 100644 --- a/view/component/form/loginform.templ +++ b/view/component/form/loginform.templ @@ -33,7 +33,7 @@ templ LoginForm(loginError string) {
diff --git a/view/component/form/registerform.templ b/view/component/form/registerform.templ index 7344b00..4775e2b 100644 --- a/view/component/form/registerform.templ +++ b/view/component/form/registerform.templ @@ -38,7 +38,7 @@ templ RegisterForm(registerError string) { >
From f34c1c11aae9adccbd87f283f9a7ea35e4f97d44 Mon Sep 17 00:00:00 2001 From: Haelnorr Date: Sat, 22 Feb 2025 20:34:09 +1100 Subject: [PATCH 8/8] Cleaned up middleware/route handlers --- {handlers => handler}/account.go | 12 ++-- {handlers => handler}/errorpage.go | 2 +- {handlers => handler}/index.go | 4 +- {handlers => handler}/login.go | 6 +- {handlers => handler}/logout.go | 4 +- {handlers => handler}/page.go | 2 +- {handlers => handler}/profile.go | 4 +- {handlers => handler}/reauthenticatate.go | 4 +- {handlers => handler}/register.go | 6 +- {handlers => handler}/static.go | 4 +- {handlers => handler}/withtransaction.go | 2 +- middleware/authentication.go | 4 +- middleware/logging.go | 4 +- middleware/pageprotection.go | 8 +-- middleware/pageprotection_test.go | 2 +- middleware/reauthentication.go | 2 +- middleware/reauthentication_test.go | 4 +- server/routes.go | 80 ++++++----------------- 18 files changed, 58 insertions(+), 96 deletions(-) rename {handlers => handler}/account.go (96%) rename {handlers => handler}/errorpage.go (97%) rename {handlers => handler}/index.go (88%) rename {handlers => handler}/login.go (96%) rename {handlers => handler}/logout.go (98%) rename {handlers => handler}/page.go (94%) rename {handlers => handler}/profile.go (75%) rename {handlers => handler}/reauthenticatate.go (98%) rename {handlers => handler}/register.go (96%) rename {handlers => handler}/static.go (93%) rename {handlers => handler}/withtransaction.go (96%) diff --git a/handlers/account.go b/handler/account.go similarity index 96% rename from handlers/account.go rename to handler/account.go index f9d60fc..5236e1e 100644 --- a/handlers/account.go +++ b/handler/account.go @@ -1,4 +1,4 @@ -package handlers +package handler import ( "context" @@ -16,7 +16,7 @@ import ( ) // Renders the account page on the 'General' subpage -func HandleAccountPage() http.Handler { +func AccountPage() http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { cookie, err := r.Cookie("subpage") @@ -30,7 +30,7 @@ func HandleAccountPage() http.Handler { } // Handles a request to change the subpage for the Accou/accountnt page -func HandleAccountSubpage() http.Handler { +func AccountSubpage() http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { r.ParseForm() @@ -42,7 +42,7 @@ func HandleAccountSubpage() http.Handler { } // Handles a request to change the users username -func HandleChangeUsername( +func ChangeUsername( logger *zerolog.Logger, conn *db.SafeConn, ) http.Handler { @@ -88,7 +88,7 @@ func HandleChangeUsername( } // Handles a request to change the users bio -func HandleChangeBio( +func ChangeBio( logger *zerolog.Logger, conn *db.SafeConn, ) http.Handler { @@ -144,7 +144,7 @@ func validateChangePassword( } // Handles a request to change the users password -func HandleChangePassword( +func ChangePassword( logger *zerolog.Logger, conn *db.SafeConn, ) http.Handler { diff --git a/handlers/errorpage.go b/handler/errorpage.go similarity index 97% rename from handlers/errorpage.go rename to handler/errorpage.go index 8f04001..19aa760 100644 --- a/handlers/errorpage.go +++ b/handler/errorpage.go @@ -1,4 +1,4 @@ -package handlers +package handler import ( "net/http" diff --git a/handlers/index.go b/handler/index.go similarity index 88% rename from handlers/index.go rename to handler/index.go index 4c22dc6..f7e09bf 100644 --- a/handlers/index.go +++ b/handler/index.go @@ -1,4 +1,4 @@ -package handlers +package handler import ( "net/http" @@ -8,7 +8,7 @@ import ( // Handles responses to the / path. Also serves a 404 Page for paths that // don't have explicit handlers -func HandleRoot() http.Handler { +func Root() http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { diff --git a/handlers/login.go b/handler/login.go similarity index 96% rename from handlers/login.go rename to handler/login.go index 0acef1b..f366447 100644 --- a/handlers/login.go +++ b/handler/login.go @@ -1,4 +1,4 @@ -package handlers +package handler import ( "context" @@ -49,7 +49,7 @@ func checkRememberMe(r *http.Request) bool { // Handles an attempted login request. On success will return a HTMX redirect // and on fail will return the login form again, passing the error to the // template for user feedback -func HandleLoginRequest( +func LoginRequest( config *config.Config, logger *zerolog.Logger, conn *db.SafeConn, @@ -97,7 +97,7 @@ func HandleLoginRequest( // Handles a request to view the login page. Will attempt to set "pagefrom" // cookie so a successful login can redirect the user to the page they came -func HandleLoginPage(trustedHost string) http.Handler { +func LoginPage(trustedHost string) http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { cookies.SetPageFrom(w, r, trustedHost) diff --git a/handlers/logout.go b/handler/logout.go similarity index 98% rename from handlers/logout.go rename to handler/logout.go index b93db43..7a14572 100644 --- a/handlers/logout.go +++ b/handler/logout.go @@ -1,4 +1,4 @@ -package handlers +package handler import ( "context" @@ -80,7 +80,7 @@ func revokeTokens( } // Handle a logout request -func HandleLogout( +func Logout( config *config.Config, logger *zerolog.Logger, conn *db.SafeConn, diff --git a/handlers/page.go b/handler/page.go similarity index 94% rename from handlers/page.go rename to handler/page.go index 223ff78..36d38eb 100644 --- a/handlers/page.go +++ b/handler/page.go @@ -1,4 +1,4 @@ -package handlers +package handler import ( "net/http" diff --git a/handlers/profile.go b/handler/profile.go similarity index 75% rename from handlers/profile.go rename to handler/profile.go index 91f381f..51763ea 100644 --- a/handlers/profile.go +++ b/handler/profile.go @@ -1,11 +1,11 @@ -package handlers +package handler import ( "net/http" "projectreshoot/view/page" ) -func HandleProfilePage() http.Handler { +func ProfilePage() http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { page.Profile().Render(r.Context(), w) diff --git a/handlers/reauthenticatate.go b/handler/reauthenticatate.go similarity index 98% rename from handlers/reauthenticatate.go rename to handler/reauthenticatate.go index 6adb3f2..6bf7317 100644 --- a/handlers/reauthenticatate.go +++ b/handler/reauthenticatate.go @@ -1,4 +1,4 @@ -package handlers +package handler import ( "context" @@ -99,7 +99,7 @@ func validatePassword( } // Handle request to reauthenticate (i.e. make token fresh again) -func HandleReauthenticate( +func Reauthenticate( logger *zerolog.Logger, config *config.Config, conn *db.SafeConn, diff --git a/handlers/register.go b/handler/register.go similarity index 96% rename from handlers/register.go rename to handler/register.go index dc4e856..2599ef5 100644 --- a/handlers/register.go +++ b/handler/register.go @@ -1,4 +1,4 @@ -package handlers +package handler import ( "context" @@ -44,7 +44,7 @@ func validateRegistration( return user, nil } -func HandleRegisterRequest( +func RegisterRequest( config *config.Config, logger *zerolog.Logger, conn *db.SafeConn, @@ -93,7 +93,7 @@ func HandleRegisterRequest( // Handles a request to view the login page. Will attempt to set "pagefrom" // cookie so a successful login can redirect the user to the page they came -func HandleRegisterPage(trustedHost string) http.Handler { +func RegisterPage(trustedHost string) http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { cookies.SetPageFrom(w, r, trustedHost) diff --git a/handlers/static.go b/handler/static.go similarity index 93% rename from handlers/static.go rename to handler/static.go index bc198dd..8b3c542 100644 --- a/handlers/static.go +++ b/handler/static.go @@ -1,4 +1,4 @@ -package handlers +package handler import ( "net/http" @@ -42,7 +42,7 @@ func (f neuteredReaddirFile) Readdir(count int) ([]os.FileInfo, error) { // Handles requests for static files, without allowing access to the // directory viewer and returning 404 if an exact file is not found -func HandleStatic(staticFS *http.FileSystem) http.Handler { +func StaticFS(staticFS *http.FileSystem) http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { nfs := justFilesFilesystem{*staticFS} diff --git a/handlers/withtransaction.go b/handler/withtransaction.go similarity index 96% rename from handlers/withtransaction.go rename to handler/withtransaction.go index c5e23d0..37b709e 100644 --- a/handlers/withtransaction.go +++ b/handler/withtransaction.go @@ -1,4 +1,4 @@ -package handlers +package handler import ( "context" diff --git a/middleware/authentication.go b/middleware/authentication.go index fc2125d..6c192ea 100644 --- a/middleware/authentication.go +++ b/middleware/authentication.go @@ -10,7 +10,7 @@ import ( "projectreshoot/contexts" "projectreshoot/cookies" "projectreshoot/db" - "projectreshoot/handlers" + "projectreshoot/handler" "projectreshoot/jwt" "github.com/pkg/errors" @@ -119,7 +119,7 @@ func Authentication( // Failed to start transaction, skip auth logger.Warn().Err(err). Msg("Skipping Auth - unable to start a transaction") - handlers.ErrorPage(http.StatusServiceUnavailable, w, r) + handler.ErrorPage(http.StatusServiceUnavailable, w, r) return } user, err := getAuthenticatedUser(config, ctx, tx, w, r) diff --git a/middleware/logging.go b/middleware/logging.go index 472d716..ae6616b 100644 --- a/middleware/logging.go +++ b/middleware/logging.go @@ -3,7 +3,7 @@ package middleware import ( "net/http" "projectreshoot/contexts" - "projectreshoot/handlers" + "projectreshoot/handler" "time" "github.com/rs/zerolog" @@ -31,7 +31,7 @@ func Logging(logger *zerolog.Logger, next http.Handler) http.Handler { } start, err := contexts.GetStartTime(r.Context()) if err != nil { - handlers.ErrorPage(http.StatusInternalServerError, w, r) + handler.ErrorPage(http.StatusInternalServerError, w, r) return } wrapped := &wrappedWriter{ diff --git a/middleware/pageprotection.go b/middleware/pageprotection.go index 3a5c14e..7f104c0 100644 --- a/middleware/pageprotection.go +++ b/middleware/pageprotection.go @@ -3,15 +3,15 @@ package middleware import ( "net/http" "projectreshoot/contexts" - "projectreshoot/handlers" + "projectreshoot/handler" ) // Checks if the user is set in the context and shows 401 page if not logged in -func RequiresLogin(next http.Handler) http.Handler { +func LoginReq(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { user := contexts.GetUser(r.Context()) if user == nil { - handlers.ErrorPage(http.StatusUnauthorized, w, r) + handler.ErrorPage(http.StatusUnauthorized, w, r) return } next.ServeHTTP(w, r) @@ -20,7 +20,7 @@ func RequiresLogin(next http.Handler) http.Handler { // Checks if the user is set in the context and redirects them to profile if // they are logged in -func RequiresLogout(next http.Handler) http.Handler { +func LogoutReq(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { user := contexts.GetUser(r.Context()) if user != nil { diff --git a/middleware/pageprotection_test.go b/middleware/pageprotection_test.go index 6150f72..93414f8 100644 --- a/middleware/pageprotection_test.go +++ b/middleware/pageprotection_test.go @@ -33,7 +33,7 @@ func TestPageLoginRequired(t *testing.T) { var maint uint32 atomic.StoreUint32(&maint, 0) // Add the middleware and create the server - loginRequiredHandler := RequiresLogin(testHandler) + loginRequiredHandler := LoginReq(testHandler) authHandler := Authentication(logger, cfg, sconn, loginRequiredHandler, &maint) server := httptest.NewServer(authHandler) defer server.Close() diff --git a/middleware/reauthentication.go b/middleware/reauthentication.go index 41fad65..b1fdb93 100644 --- a/middleware/reauthentication.go +++ b/middleware/reauthentication.go @@ -6,7 +6,7 @@ import ( "time" ) -func RequiresFresh( +func FreshReq( next http.Handler, ) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/middleware/reauthentication_test.go b/middleware/reauthentication_test.go index bfb40e8..646a557 100644 --- a/middleware/reauthentication_test.go +++ b/middleware/reauthentication_test.go @@ -33,8 +33,8 @@ func TestReauthRequired(t *testing.T) { var maint uint32 atomic.StoreUint32(&maint, 0) // Add the middleware and create the server - reauthRequiredHandler := RequiresFresh(testHandler) - loginRequiredHandler := RequiresLogin(reauthRequiredHandler) + reauthRequiredHandler := FreshReq(testHandler) + loginRequiredHandler := LoginReq(reauthRequiredHandler) authHandler := Authentication(logger, cfg, sconn, loginRequiredHandler, &maint) server := httptest.NewServer(authHandler) defer server.Close() diff --git a/server/routes.go b/server/routes.go index eac1e17..8462e72 100644 --- a/server/routes.go +++ b/server/routes.go @@ -5,7 +5,7 @@ import ( "projectreshoot/config" "projectreshoot/db" - "projectreshoot/handlers" + "projectreshoot/handler" "projectreshoot/middleware" "projectreshoot/view/page" @@ -20,82 +20,44 @@ func addRoutes( conn *db.SafeConn, staticFS *http.FileSystem, ) { + route := mux.Handle + loggedIn := middleware.LoginReq + loggedOut := middleware.LogoutReq + fresh := middleware.FreshReq + // Health check mux.HandleFunc("GET /healthz", func(http.ResponseWriter, *http.Request) {}) // Static files - mux.Handle("GET /static/", http.StripPrefix("/static/", handlers.HandleStatic(staticFS))) + route("GET /static/", http.StripPrefix("/static/", handler.StaticFS(staticFS))) // Index page and unhandled catchall (404) - mux.Handle("GET /", handlers.HandleRoot()) + route("GET /", handler.Root()) // Static content, unprotected pages - mux.Handle("GET /about", handlers.HandlePage(page.About())) + route("GET /about", handler.HandlePage(page.About())) // Login page and handlers - mux.Handle("GET /login", - middleware.RequiresLogout( - handlers.HandleLoginPage(config.TrustedHost), - )) - mux.Handle("POST /login", - middleware.RequiresLogout( - handlers.HandleLoginRequest( - config, - logger, - conn, - ))) + route("GET /login", loggedOut(handler.LoginPage(config.TrustedHost))) + route("POST /login", loggedOut(handler.LoginRequest(config, logger, conn))) // Register page and handlers - mux.Handle("GET /register", - middleware.RequiresLogout( - handlers.HandleRegisterPage(config.TrustedHost), - )) - mux.Handle("POST /register", - middleware.RequiresLogout( - handlers.HandleRegisterRequest( - config, - logger, - conn, - ))) + route("GET /register", loggedOut(handler.RegisterPage(config.TrustedHost))) + route("POST /register", loggedOut(handler.RegisterRequest(config, logger, conn))) // Logout - mux.Handle("POST /logout", handlers.HandleLogout(config, logger, conn)) + route("POST /logout", handler.Logout(config, logger, conn)) // Reauthentication request - mux.Handle("POST /reauthenticate", - middleware.RequiresLogin( - handlers.HandleReauthenticate(logger, config, conn), - )) + route("POST /reauthenticate", loggedIn(handler.Reauthenticate(logger, config, conn))) // Profile page - mux.Handle("GET /profile", - middleware.RequiresLogin( - handlers.HandleProfilePage(), - )) + route("GET /profile", loggedIn(handler.ProfilePage())) // Account page - mux.Handle("GET /account", - middleware.RequiresLogin( - handlers.HandleAccountPage(), - )) - mux.Handle("POST /account-select-page", - middleware.RequiresLogin( - handlers.HandleAccountSubpage(), - )) - mux.Handle("POST /change-username", - middleware.RequiresLogin( - middleware.RequiresFresh( - handlers.HandleChangeUsername(logger, conn), - ), - )) - mux.Handle("POST /change-bio", - middleware.RequiresLogin( - handlers.HandleChangeBio(logger, conn), - )) - mux.Handle("POST /change-password", - middleware.RequiresLogin( - middleware.RequiresFresh( - handlers.HandleChangePassword(logger, conn), - ), - )) + route("GET /account", loggedIn(handler.AccountPage())) + route("POST /account-select-page", loggedIn(handler.AccountSubpage())) + route("POST /change-username", loggedIn(fresh(handler.ChangeUsername(logger, conn)))) + route("POST /change-bio", loggedIn(handler.ChangeBio(logger, conn))) + route("POST /change-password", loggedIn(fresh(handler.ChangePassword(logger, conn)))) }