use json.Marshal provided with validation

This commit is contained in:
dhax 2019-01-08 23:07:17 +01:00
parent cd7d44fcd8
commit 2d7f6be830
5 changed files with 40 additions and 56 deletions

View file

@ -120,7 +120,7 @@ func (rs *AccountResource) create(w http.ResponseWriter, r *http.Request) {
if err := rs.Store.Create(data.Account); err != nil { if err := rs.Store.Create(data.Account); err != nil {
switch err.(type) { switch err.(type) {
case validation.Errors: case validation.Errors:
render.Render(w, r, ErrValidation(ErrAccountValidation, err)) render.Render(w, r, ErrValidation(ErrAccountValidation, err.(validation.Errors)))
return return
} }
render.Render(w, r, ErrInvalidRequest(err)) render.Render(w, r, ErrInvalidRequest(err))
@ -145,7 +145,7 @@ func (rs *AccountResource) update(w http.ResponseWriter, r *http.Request) {
if err := rs.Store.Update(acc); err != nil { if err := rs.Store.Update(acc); err != nil {
switch err.(type) { switch err.(type) {
case validation.Errors: case validation.Errors:
render.Render(w, r, ErrValidation(ErrAccountValidation, err)) render.Render(w, r, ErrValidation(ErrAccountValidation, err.(validation.Errors)))
return return
} }
render.Render(w, r, ErrInvalidRequest(err)) render.Render(w, r, ErrInvalidRequest(err))

View file

@ -1,10 +1,10 @@
package admin package admin
import ( import (
"encoding/json"
"net/http" "net/http"
"github.com/go-chi/render" "github.com/go-chi/render"
validation "github.com/go-ozzo/ozzo-validation"
) )
// ErrResponse renderer type for handling all sorts of errors. // ErrResponse renderer type for handling all sorts of errors.
@ -15,6 +15,7 @@ type ErrResponse struct {
StatusText string `json:"status"` // user-level status message StatusText string `json:"status"` // user-level status message
AppCode int64 `json:"code,omitempty"` // application-specific error code AppCode int64 `json:"code,omitempty"` // application-specific error code
ErrorText string `json:"error,omitempty"` // application-level error message, for debugging ErrorText string `json:"error,omitempty"` // application-level error message, for debugging
ValidationErrors validation.Errors `json:"errors,omitempty"` // user level model validation errors
} }
// Render sets the application-specific error code in AppCode. // Render sets the application-specific error code in AppCode.
@ -43,29 +44,14 @@ func ErrRender(err error) render.Renderer {
} }
} }
// ErrValidationResponse renderer for handling validation errors.
type ErrValidationResponse struct {
*ErrResponse
Errors string `json:"errors,omitempty"`
}
// Render sets the application-specific error code in AppCode.
func (ev *ErrValidationResponse) Render(w http.ResponseWriter, r *http.Request) error {
render.Status(r, ev.ErrResponse.HTTPStatusCode)
return nil
}
// ErrValidation returns status 422 Unprocessable Entity stating validation errors. // ErrValidation returns status 422 Unprocessable Entity stating validation errors.
func ErrValidation(err error, valErrors error) render.Renderer { func ErrValidation(err error, valErr validation.Errors) render.Renderer {
b, _ := json.Marshal(valErrors) return &ErrResponse{
return &ErrValidationResponse{
&ErrResponse{
Err: err, Err: err,
HTTPStatusCode: http.StatusUnprocessableEntity, HTTPStatusCode: http.StatusUnprocessableEntity,
StatusText: http.StatusText(http.StatusUnprocessableEntity), StatusText: http.StatusText(http.StatusUnprocessableEntity),
ErrorText: err.Error(), ErrorText: err.Error(),
}, ValidationErrors: valErr,
string(b),
} }
} }

View file

@ -2,6 +2,7 @@ package app
import ( import (
"context" "context"
"errors"
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
@ -14,6 +15,11 @@ import (
"github.com/dhax/go-base/auth/pwdless" "github.com/dhax/go-base/auth/pwdless"
) )
// The list of error types returned from account resource.
var (
ErrAccountValidation = errors.New("account validation error")
)
// AccountStore defines database operations for account. // AccountStore defines database operations for account.
type AccountStore interface { type AccountStore interface {
Get(id int) (*pwdless.Account, error) Get(id int) (*pwdless.Account, error)
@ -103,7 +109,7 @@ func (rs *AccountResource) update(w http.ResponseWriter, r *http.Request) {
if err := rs.Store.Update(acc); err != nil { if err := rs.Store.Update(acc); err != nil {
switch err.(type) { switch err.(type) {
case validation.Errors: case validation.Errors:
render.Render(w, r, ErrValidation(err)) render.Render(w, r, ErrValidation(ErrAccountValidation, err.(validation.Errors)))
return return
} }
render.Render(w, r, ErrRender(err)) render.Render(w, r, ErrRender(err))

View file

@ -1,10 +1,10 @@
package app package app
import ( import (
"encoding/json"
"net/http" "net/http"
"github.com/go-chi/render" "github.com/go-chi/render"
validation "github.com/go-ozzo/ozzo-validation"
) )
// ErrResponse renderer type for handling all sorts of errors. // ErrResponse renderer type for handling all sorts of errors.
@ -15,6 +15,7 @@ type ErrResponse struct {
StatusText string `json:"status"` // user-level status message StatusText string `json:"status"` // user-level status message
AppCode int64 `json:"code,omitempty"` // application-specific error code AppCode int64 `json:"code,omitempty"` // application-specific error code
ErrorText string `json:"error,omitempty"` // application-level error message, for debugging ErrorText string `json:"error,omitempty"` // application-level error message, for debugging
ValidationErrors validation.Errors `json:"errors,omitempty"` // user level model validation errors
} }
// Render sets the application-specific error code in AppCode. // Render sets the application-specific error code in AppCode.
@ -33,29 +34,14 @@ func ErrInvalidRequest(err error) render.Renderer {
} }
} }
// ErrValidationResponse renderer for handling validation errors.
type ErrValidationResponse struct {
*ErrResponse
Errors string `json:"errors,omitempty"`
}
// Render sets the application-specific error code in AppCode.
func (ev *ErrValidationResponse) Render(w http.ResponseWriter, r *http.Request) error {
render.Status(r, ev.ErrResponse.HTTPStatusCode)
return nil
}
// ErrValidation returns status 422 Unprocessable Entity stating validation errors. // ErrValidation returns status 422 Unprocessable Entity stating validation errors.
func ErrValidation(valErrors error) render.Renderer { func ErrValidation(err error, valErr validation.Errors) render.Renderer {
b, _ := json.Marshal(valErrors) return &ErrResponse{
return &ErrValidationResponse{ Err: err,
&ErrResponse{
Err: nil,
HTTPStatusCode: http.StatusUnprocessableEntity, HTTPStatusCode: http.StatusUnprocessableEntity,
StatusText: http.StatusText(http.StatusUnprocessableEntity), StatusText: http.StatusText(http.StatusUnprocessableEntity),
ErrorText: "object validation error", ErrorText: err.Error(),
}, ValidationErrors: valErr,
string(b),
} }
} }

View file

@ -2,6 +2,7 @@ package app
import ( import (
"context" "context"
"errors"
"net/http" "net/http"
"github.com/dhax/go-base/auth/jwt" "github.com/dhax/go-base/auth/jwt"
@ -11,6 +12,11 @@ import (
validation "github.com/go-ozzo/ozzo-validation" validation "github.com/go-ozzo/ozzo-validation"
) )
// The list of error types returned from account resource.
var (
ErrProfileValidation = errors.New("profile validation error")
)
// ProfileStore defines database operations for a profile. // ProfileStore defines database operations for a profile.
type ProfileStore interface { type ProfileStore interface {
Get(accountID int) (*models.Profile, error) Get(accountID int) (*models.Profile, error)
@ -85,7 +91,7 @@ func (rs *ProfileResource) update(w http.ResponseWriter, r *http.Request) {
if err := rs.Store.Update(p); err != nil { if err := rs.Store.Update(p); err != nil {
switch err.(type) { switch err.(type) {
case validation.Errors: case validation.Errors:
render.Render(w, r, ErrValidation(err)) render.Render(w, r, ErrValidation(ErrProfileValidation, err.(validation.Errors)))
return return
} }
render.Render(w, r, ErrRender(err)) render.Render(w, r, ErrRender(err))