whatsapp-backend-test / utils /response_util.go
RyZ
feat: adding get user information and refresh token; security: adding csrf verification logic and token rotation;
ca18868
package utils
import (
"errors"
dto "whatsapp-backend/models/dto"
http_error "whatsapp-backend/models/error"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
"gorm.io/gorm"
)
func ResponseOK[Tdata any, TMetaData any](c *gin.Context, metaData TMetaData, data Tdata) {
c.JSON(200, dto.SuccessResponse[Tdata]{
Status: "success",
Data: data,
Message: "Data retrieved Successfully!",
MetaData: metaData,
})
}
func ResponseFAILED[TMetaData any](c *gin.Context, metaData TMetaData, err error) {
if errors.Is(err, http_error.BAD_REQUEST_ERROR) {
c.JSON(400, dto.ErrorResponse{
Status: "error",
Error: err,
Message: "Invalid request format!",
MetaData: metaData,
})
return
} else if errors.Is(err, http_error.INTERNAL_SERVER_ERROR) {
c.JSON(500, dto.ErrorResponse{
Status: "error",
Error: err,
Message: "Internal Server Error!",
MetaData: metaData,
})
return
} else if errors.Is(err, http_error.UNAUTHORIZED) {
c.JSON(401, dto.ErrorResponse{
Status: "error",
Error: err,
Message: "Unauthorized, you don't have permission to access this service!",
MetaData: metaData,
})
return
} else if errors.Is(err, http_error.DATA_NOT_FOUND) || errors.Is(err, gorm.ErrRecordNotFound) {
c.JSON(404, dto.ErrorResponse{
Status: "error",
Error: err,
Message: "There is not data with given credential / given parameter!",
MetaData: metaData,
})
return
} else if errors.Is(err, http_error.TIMEOUT) {
c.JSON(504, dto.ErrorResponse{
Status: "error",
Error: err,
Message: "Server took to long to respond!",
MetaData: metaData,
})
return
} else if errors.Is(err, http_error.FORBIDDEN) || errors.Is(err, http_error.ERR_INVALID_CSRF) {
c.JSON(403, dto.ErrorResponse{
Status: "error",
Error: err,
Message: "Forbidden action!",
MetaData: metaData,
})
return
} else {
// Check for Validation Errors
var validationErrors validator.ValidationErrors
if errors.As(err, &validationErrors) {
friendlyErrors := make([]string, len(validationErrors))
for i, fieldError := range validationErrors {
friendlyErrors[i] = msgForTag(fieldError)
}
c.JSON(400, dto.ErrorResponse{
Status: "error",
Error: friendlyErrors,
Message: "Validation Failed",
MetaData: nil,
})
return
}
if errors.Is(err, http_error.ERR_USER_NOT_FOUND) || errors.Is(err, http_error.ERR_WRONG_PASSWORD) {
c.JSON(401, dto.ErrorResponse{
Status: "error",
Error: err,
Message: err.Error(),
MetaData: metaData,
})
return
} else if errors.Is(err, http_error.ERR_USER_ALREADY_EXISTS) {
c.JSON(409, dto.ErrorResponse{
Status: "error",
Error: err,
Message: err.Error(),
MetaData: metaData,
})
return
}
// Default to 500
c.JSON(500, dto.ErrorResponse{
Status: "error",
Error: err,
Message: err.Error(),
MetaData: metaData,
})
return
}
}
func SendResponse[Tdata any, TMetaData any](c *gin.Context, metaData TMetaData, data Tdata, err error) {
if !c.IsAborted() {
if err != nil {
ResponseFAILED(c, metaData, err)
c.Abort()
return
} else {
ResponseOK(c, metaData, data)
c.Abort()
return
}
}
}
func msgForTag(fe validator.FieldError) string {
switch fe.Tag() {
case "required":
return "This field is required"
case "email":
return "Invalid email format"
case "min":
return fe.Field() + " must be longer than " + fe.Param() + " characters"
case "max":
return fe.Field() + " must be shorter than " + fe.Param() + " characters"
}
return fe.Error() // Default error message
}