package myvalidator import ( "errors" "fmt" "net/http" "git.artlef.fr/bibliomane/internal/appcontext" "git.artlef.fr/bibliomane/internal/i18nresource" "github.com/gin-gonic/gin" "github.com/go-playground/validator/v10" "gorm.io/gorm" ) type HttpError struct { StatusCode int Err error } func ValidateId(db *gorm.DB, id uint, value any) error { //id = 0 means empty id, so no check if id == 0 { return nil } record := map[string]any{} result := db.Model(value).First(&record, id) if result.Error == nil { return nil } if errors.Is(result.Error, gorm.ErrRecordNotFound) { return HttpError{ StatusCode: http.StatusNotFound, Err: fmt.Errorf("Id %d could not be found for model %s", id, value), } } else { return HttpError{ StatusCode: http.StatusInternalServerError, Err: result.Error, } } } func ReturnErrorsAsJsonResponse(ac *appcontext.AppContext, err error) { var httpError HttpError var ve validator.ValidationErrors if errors.As(err, &ve) { ac.C.JSON(http.StatusBadRequest, getValidationErrors(ac, &ve)) } else if errors.As(err, &httpError) { ac.C.JSON(httpError.StatusCode, gin.H{"error": httpError.Err.Error()}) } else { ac.C.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) } } func (h HttpError) Error() string { return fmt.Sprintf("%d: err %v", h.StatusCode, h.Err) } type apiValidationError struct { Field string `json:"field"` Err string `json:"error"` } func getValidationErrors(ac *appcontext.AppContext, ve *validator.ValidationErrors) []apiValidationError { errors := make([]apiValidationError, len(*ve)) for i, fe := range *ve { errors[i] = apiValidationError{ Field: fe.Field(), Err: computeValidationMessage(ac, &fe), } } return errors } func computeValidationMessage(ac *appcontext.AppContext, fe *validator.FieldError) string { tag := (*fe).Tag() switch tag { case "required": return i18nresource.GetTranslatedMessage(ac, "ValidationRequired") case "min": return fmt.Sprintf(i18nresource.GetTranslatedMessage(ac, "ValidationTooShort"), (*fe).Param()) case "max": return fmt.Sprintf(i18nresource.GetTranslatedMessage(ac, "ValidationTooLong"), (*fe).Param()) case "lte": return fmt.Sprintf(i18nresource.GetTranslatedMessage(ac, "ValidationLowerThan"), (*fe).Param()) case "gte": return fmt.Sprintf(i18nresource.GetTranslatedMessage(ac, "ValidationGreaterThan"), (*fe).Param()) default: return fmt.Sprintf(i18nresource.GetTranslatedMessage(ac, "ValidationPropertyFail"), tag) } }