Let error handler handle all error logic, logging, and canceling.

This commit is contained in:
mikestefanello 2022-05-17 08:45:18 -04:00
parent 31a3503021
commit ecd0120920
10 changed files with 43 additions and 49 deletions

View file

@ -54,7 +54,7 @@ run:
# Run all tests # Run all tests
.PHONY: test .PHONY: test
test: test:
go test -p 1 ./... go test -count=1 -p 1 ./...
# Run the worker # Run the worker
.PHONY: worker .PHONY: worker
@ -65,4 +65,4 @@ worker:
# Check for direct dependency updates # Check for direct dependency updates
.PHONY: check-updates .PHONY: check-updates
check-updates: check-updates:
go list -u -m -f '{{if not .Indirect}}{{.}}{{end}}' all go list -u -m -f '{{if not .Indirect}}{{.}}{{end}}' all | grep "\["

View file

@ -35,8 +35,7 @@ func (c *Controller) RenderPage(ctx echo.Context, page Page) error {
// Page name is required // Page name is required
if page.Name == "" { if page.Name == "" {
ctx.Logger().Error("page render failed due to missing name") return echo.NewHTTPError(http.StatusInternalServerError, "page render failed due to missing name")
return echo.NewHTTPError(http.StatusInternalServerError)
} }
// Use the app name in configuration if a value was not set // Use the app name in configuration if a value was not set
@ -85,8 +84,7 @@ func (c *Controller) RenderPage(ctx echo.Context, page Page) error {
} }
if err != nil { if err != nil {
ctx.Logger().Errorf("failed to parse and execute templates: %v", err) return c.Fail(err, "failed to parse and execute templates")
return echo.NewHTTPError(http.StatusInternalServerError)
} }
// Set the status code // Set the status code
@ -168,10 +166,6 @@ func (c *Controller) Redirect(ctx echo.Context, route string, routeParams ...int
} }
// Fail is a helper to fail a request by returning a 500 error and logging the error // Fail is a helper to fail a request by returning a 500 error and logging the error
func (c *Controller) Fail(ctx echo.Context, err error, log string) error { func (c *Controller) Fail(err error, log string) error {
if context.IsCanceledError(err) { return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("%s: %v", log, err))
return nil
}
ctx.Logger().Errorf("%s: %v", log, err)
return echo.NewHTTPError(http.StatusInternalServerError)
} }

View file

@ -1,6 +1,7 @@
package middleware package middleware
import ( import (
"fmt"
"net/http" "net/http"
"strconv" "strconv"
@ -25,10 +26,10 @@ func LoadAuthenticatedUser(authClient *services.AuthClient) echo.MiddlewareFunc
c.Set(context.AuthenticatedUserKey, u) c.Set(context.AuthenticatedUserKey, u)
c.Logger().Infof("auth user loaded in to context: %d", u.ID) c.Logger().Infof("auth user loaded in to context: %d", u.ID)
default: default:
if context.IsCanceledError(err) { return echo.NewHTTPError(
return nil http.StatusInternalServerError,
} fmt.Sprintf("error querying for authenticated user: %v", err),
c.Logger().Errorf("error querying for authenticated user: %v", err) )
} }
return next(c) return next(c)
@ -71,11 +72,10 @@ func LoadValidPasswordToken(authClient *services.AuthClient) echo.MiddlewareFunc
msg.Warning(c, "The link is either invalid or has expired. Please request a new one.") msg.Warning(c, "The link is either invalid or has expired. Please request a new one.")
return c.Redirect(http.StatusFound, c.Echo().Reverse("forgot_password")) return c.Redirect(http.StatusFound, c.Echo().Reverse("forgot_password"))
default: default:
if context.IsCanceledError(err) { return echo.NewHTTPError(
return nil http.StatusInternalServerError,
} fmt.Sprintf("error loading password token: %v", err),
c.Logger().Error(err) )
return echo.NewHTTPError(http.StatusInternalServerError)
} }
} }
} }

View file

@ -1,6 +1,7 @@
package middleware package middleware
import ( import (
"fmt"
"net/http" "net/http"
"strconv" "strconv"
@ -32,11 +33,10 @@ func LoadUser(orm *ent.Client) echo.MiddlewareFunc {
case *ent.NotFoundError: case *ent.NotFoundError:
return echo.NewHTTPError(http.StatusNotFound) return echo.NewHTTPError(http.StatusNotFound)
default: default:
if context.IsCanceledError(err) { return echo.NewHTTPError(
return nil http.StatusInternalServerError,
} fmt.Sprintf("error querying user: %v", err),
c.Logger().Error(err) )
return echo.NewHTTPError(http.StatusInternalServerError)
} }
} }
} }

View file

@ -41,11 +41,11 @@ func (c *contact) Post(ctx echo.Context) error {
// Parse the form values // Parse the form values
if err := ctx.Bind(&form); err != nil { if err := ctx.Bind(&form); err != nil {
return c.Fail(ctx, err, "unable to bind form") return c.Fail(err, "unable to bind form")
} }
if err := form.Submission.Process(ctx, form); err != nil { if err := form.Submission.Process(ctx, form); err != nil {
return c.Fail(ctx, err, "unable to process form submission") return c.Fail(err, "unable to process form submission")
} }
if !form.Submission.HasErrors() { if !form.Submission.HasErrors() {
@ -57,7 +57,7 @@ func (c *contact) Post(ctx echo.Context) error {
Send(ctx) Send(ctx)
if err != nil { if err != nil {
return c.Fail(ctx, err, "unable to send email") return c.Fail(err, "unable to send email")
} }
} }

View file

@ -50,11 +50,11 @@ func (c *forgotPassword) Post(ctx echo.Context) error {
// Parse the form values // Parse the form values
if err := ctx.Bind(&form); err != nil { if err := ctx.Bind(&form); err != nil {
return c.Fail(ctx, err, "unable to parse forgot password form") return c.Fail(err, "unable to parse forgot password form")
} }
if err := form.Submission.Process(ctx, form); err != nil { if err := form.Submission.Process(ctx, form); err != nil {
return c.Fail(ctx, err, "unable to process form submission") return c.Fail(err, "unable to process form submission")
} }
if form.Submission.HasErrors() { if form.Submission.HasErrors() {
@ -72,13 +72,13 @@ func (c *forgotPassword) Post(ctx echo.Context) error {
return succeed() return succeed()
case nil: case nil:
default: default:
return c.Fail(ctx, err, "error querying user during forgot password") return c.Fail(err, "error querying user during forgot password")
} }
// Generate the token // Generate the token
token, pt, err := c.Container.Auth.GeneratePasswordResetToken(ctx, u.ID) token, pt, err := c.Container.Auth.GeneratePasswordResetToken(ctx, u.ID)
if err != nil { if err != nil {
return c.Fail(ctx, err, "error generating password reset token") return c.Fail(err, "error generating password reset token")
} }
ctx.Logger().Infof("generated password reset token for user %d", u.ID) ctx.Logger().Infof("generated password reset token for user %d", u.ID)
@ -93,7 +93,7 @@ func (c *forgotPassword) Post(ctx echo.Context) error {
Send(ctx) Send(ctx)
if err != nil { if err != nil {
return c.Fail(ctx, err, "error sending password reset email") return c.Fail(err, "error sending password reset email")
} }
return succeed() return succeed()

View file

@ -52,11 +52,11 @@ func (c *login) Post(ctx echo.Context) error {
// Parse the form values // Parse the form values
if err := ctx.Bind(&form); err != nil { if err := ctx.Bind(&form); err != nil {
return c.Fail(ctx, err, "unable to parse login form") return c.Fail(err, "unable to parse login form")
} }
if err := form.Submission.Process(ctx, form); err != nil { if err := form.Submission.Process(ctx, form); err != nil {
return c.Fail(ctx, err, "unable to process form submission") return c.Fail(err, "unable to process form submission")
} }
if form.Submission.HasErrors() { if form.Submission.HasErrors() {
@ -74,7 +74,7 @@ func (c *login) Post(ctx echo.Context) error {
return authFailed() return authFailed()
case nil: case nil:
default: default:
return c.Fail(ctx, err, "error querying user during login") return c.Fail(err, "error querying user during login")
} }
// Check if the password is correct // Check if the password is correct
@ -86,7 +86,7 @@ func (c *login) Post(ctx echo.Context) error {
// Log the user in // Log the user in
err = c.Container.Auth.Login(ctx, u.ID) err = c.Container.Auth.Login(ctx, u.ID)
if err != nil { if err != nil {
return c.Fail(ctx, err, "unable to log in user") return c.Fail(err, "unable to log in user")
} }
msg.Success(ctx, fmt.Sprintf("Welcome back, <strong>%s</strong>. You are now logged in.", u.Name)) msg.Success(ctx, fmt.Sprintf("Welcome back, <strong>%s</strong>. You are now logged in.", u.Name))

View file

@ -45,11 +45,11 @@ func (c *register) Post(ctx echo.Context) error {
// Parse the form values // Parse the form values
if err := ctx.Bind(&form); err != nil { if err := ctx.Bind(&form); err != nil {
return c.Fail(ctx, err, "unable to parse register form") return c.Fail(err, "unable to parse register form")
} }
if err := form.Submission.Process(ctx, form); err != nil { if err := form.Submission.Process(ctx, form); err != nil {
return c.Fail(ctx, err, "unable to process form submission") return c.Fail(err, "unable to process form submission")
} }
if form.Submission.HasErrors() { if form.Submission.HasErrors() {
@ -59,7 +59,7 @@ func (c *register) Post(ctx echo.Context) error {
// Hash the password // Hash the password
pwHash, err := c.Container.Auth.HashPassword(form.Password) pwHash, err := c.Container.Auth.HashPassword(form.Password)
if err != nil { if err != nil {
return c.Fail(ctx, err, "unable to hash password") return c.Fail(err, "unable to hash password")
} }
// Attempt creating the user // Attempt creating the user
@ -77,7 +77,7 @@ func (c *register) Post(ctx echo.Context) error {
msg.Warning(ctx, "A user with this email address already exists. Please log in.") msg.Warning(ctx, "A user with this email address already exists. Please log in.")
return c.Redirect(ctx, "login") return c.Redirect(ctx, "login")
default: default:
return c.Fail(ctx, err, "unable to create user") return c.Fail(err, "unable to create user")
} }
// Log the user in // Log the user in

View file

@ -41,11 +41,11 @@ func (c *resetPassword) Post(ctx echo.Context) error {
// Parse the form values // Parse the form values
if err := ctx.Bind(&form); err != nil { if err := ctx.Bind(&form); err != nil {
return c.Fail(ctx, err, "unable to parse password reset form") return c.Fail(err, "unable to parse password reset form")
} }
if err := form.Submission.Process(ctx, form); err != nil { if err := form.Submission.Process(ctx, form); err != nil {
return c.Fail(ctx, err, "unable to process form submission") return c.Fail(err, "unable to process form submission")
} }
if form.Submission.HasErrors() { if form.Submission.HasErrors() {
@ -55,7 +55,7 @@ func (c *resetPassword) Post(ctx echo.Context) error {
// Hash the new password // Hash the new password
hash, err := c.Container.Auth.HashPassword(form.Password) hash, err := c.Container.Auth.HashPassword(form.Password)
if err != nil { if err != nil {
return c.Fail(ctx, err, "unable to hash password") return c.Fail(err, "unable to hash password")
} }
// Get the requesting user // Get the requesting user
@ -68,13 +68,13 @@ func (c *resetPassword) Post(ctx echo.Context) error {
Save(ctx.Request().Context()) Save(ctx.Request().Context())
if err != nil { if err != nil {
return c.Fail(ctx, err, "unable to update password") return c.Fail(err, "unable to update password")
} }
// Delete all password tokens for this user // Delete all password tokens for this user
err = c.Container.Auth.DeletePasswordTokens(ctx, usr.ID) err = c.Container.Auth.DeletePasswordTokens(ctx, usr.ID)
if err != nil { if err != nil {
return c.Fail(ctx, err, "unable to delete password tokens") return c.Fail(err, "unable to delete password tokens")
} }
msg.Success(ctx, "Your password has been updated.") msg.Success(ctx, "Your password has been updated.")

View file

@ -41,7 +41,7 @@ func (c *verifyEmail) Get(ctx echo.Context) error {
Only(ctx.Request().Context()) Only(ctx.Request().Context())
if err != nil { if err != nil {
return c.Fail(ctx, err, "query failed loading email verification token user") return c.Fail(err, "query failed loading email verification token user")
} }
} }
@ -53,7 +53,7 @@ func (c *verifyEmail) Get(ctx echo.Context) error {
Save(ctx.Request().Context()) Save(ctx.Request().Context())
if err != nil { if err != nil {
return c.Fail(ctx, err, "failed to set user as verified") return c.Fail(err, "failed to set user as verified")
} }
} }