feat: 调整错误返回

This commit is contained in:
ssongliu 2022-08-09 15:06:12 +08:00
parent 1632a58792
commit d8192c3b07
13 changed files with 80 additions and 71 deletions

View file

@ -4,6 +4,8 @@ import (
"net/http"
"strconv"
"github.com/pkg/errors"
"github.com/1Panel-dev/1Panel/app/dto"
"github.com/1Panel-dev/1Panel/constant"
"github.com/1Panel-dev/1Panel/i18n"
@ -32,7 +34,23 @@ func GeneratePaginationFromReq(c *gin.Context) (dto.PageInfo, bool) {
func ErrorWithDetail(ctx *gin.Context, code int, msgKey string, err error) {
res := dto.Response{
Code: code,
Msg: i18n.GetMsgWithMap(msgKey, map[string]interface{}{"detail": err}),
Msg: "",
}
if msgKey == constant.ErrTypeInternalServer {
switch {
case errors.Is(err, constant.ErrRecordExist):
res.Msg = i18n.GetMsgWithMap("ErrRecordExist", map[string]interface{}{"detail": err})
case errors.Is(constant.ErrRecordNotFound, err):
res.Msg = i18n.GetMsgWithMap("ErrRecordNotFound", map[string]interface{}{"detail": err})
case errors.Is(constant.ErrStructTransform, err):
res.Msg = i18n.GetMsgWithMap("ErrStructTransform", map[string]interface{}{"detail": err})
case errors.Is(constant.ErrCaptchaCode, err):
res.Msg = i18n.GetMsgWithMap("ErrCaptchaCode", map[string]interface{}{"detail": err})
default:
res.Msg = i18n.GetMsgWithMap(msgKey, map[string]interface{}{"detail": err})
}
} else {
res.Msg = i18n.GetMsgWithMap(msgKey, map[string]interface{}{"detail": err})
}
ctx.JSON(http.StatusOK, res)
ctx.Abort()

View file

@ -1,7 +1,7 @@
package v1
import (
"errors"
"github.com/pkg/errors"
"github.com/1Panel-dev/1Panel/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/app/dto"
@ -16,15 +16,15 @@ type BaseApi struct{}
func (b *BaseApi) Login(c *gin.Context) {
var req dto.Login
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeParamInReqBody, err)
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeParamValid, err)
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := captcha.VerifyCode(req.CaptchaID, req.Captcha); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeParamInReqBody, errors.New("captcha code error"))
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
@ -47,11 +47,11 @@ func (b *BaseApi) Captcha(c *gin.Context) {
func (b *BaseApi) Register(c *gin.Context) {
var req dto.UserCreate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeParamInReqBody, err)
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeParamValid, err)
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := userService.Register(req); err != nil {
@ -64,7 +64,7 @@ func (b *BaseApi) Register(c *gin.Context) {
func (b *BaseApi) GetUserList(c *gin.Context) {
pagenation, isOK := helper.GeneratePaginationFromReq(c)
if !isOK {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeParamInReqQuery, constant.ErrPageParam)
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, constant.ErrPageGenerate)
return
}
@ -83,11 +83,11 @@ func (b *BaseApi) GetUserList(c *gin.Context) {
func (b *BaseApi) DeleteUser(c *gin.Context) {
var req dto.OperationWithName
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeParamInReqBody, err)
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeParamValid, err)
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
@ -101,11 +101,11 @@ func (b *BaseApi) DeleteUser(c *gin.Context) {
func (b *BaseApi) UpdateUser(c *gin.Context) {
var req dto.UserUpdate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeParamInReqBody, err)
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeParamValid, err)
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
@ -121,7 +121,7 @@ func (b *BaseApi) UpdateUser(c *gin.Context) {
func (b *BaseApi) GetUserInfo(c *gin.Context) {
name, ok := c.Params.Get("name")
if !ok {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeParamInReqQuery, errors.New("error name"))
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error name"))
return
}

View file

@ -6,7 +6,7 @@ import (
type UserCreate struct {
Name string `json:"name" validate:"name,required"`
Password string `json:"password" validate:"password,required"`
Password string `json:"password" validate:"required"`
Email string `json:"email" validate:"required,email"`
}

View file

@ -1,7 +1,7 @@
package service
import (
"errors"
"github.com/pkg/errors"
"github.com/1Panel-dev/1Panel/app/dto"
"github.com/1Panel-dev/1Panel/app/model"
@ -11,8 +11,6 @@ import (
"github.com/1Panel-dev/1Panel/utils/jwt"
"github.com/gin-gonic/gin"
"github.com/jinzhu/copier"
"gorm.io/gorm"
)
type UserService struct{}
@ -38,7 +36,7 @@ func (u *UserService) Get(name string) (*dto.UserBack, error) {
}
var dtoUser dto.UserBack
if err := copier.Copy(&dtoUser, &user); err != nil {
return nil, constant.ErrCopyTransform
return nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
}
return &dtoUser, err
}
@ -49,7 +47,7 @@ func (u *UserService) Page(page, size int) (int64, interface{}, error) {
for _, user := range users {
var item dto.UserBack
if err := copier.Copy(&item, &user); err != nil {
return 0, nil, constant.ErrCopyTransform
return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
}
dtoUsers = append(dtoUsers, item)
}
@ -59,10 +57,11 @@ func (u *UserService) Page(page, size int) (int64, interface{}, error) {
func (u *UserService) Register(userDto dto.UserCreate) error {
var user model.User
if err := copier.Copy(&user, &userDto); err != nil {
return constant.ErrCopyTransform
return errors.WithMessage(constant.ErrStructTransform, err.Error())
}
if !errors.Is(global.DB.Where("name = ?", user.Name).First(&user).Error, gorm.ErrRecordNotFound) {
return constant.ErrRecordExist
_ = global.DB.Where("name = ?", user.Name).First(&user).Error
if user.ID != 0 {
return errors.Wrap(constant.ErrRecordExist, "data exist")
}
return userRepo.Create(&user)
}
@ -70,7 +69,7 @@ func (u *UserService) Register(userDto dto.UserCreate) error {
func (u *UserService) Login(c *gin.Context, info dto.Login) (*dto.UserLoginInfo, error) {
user, err := userRepo.Get(commonRepo.WithByName(info.Name))
if err != nil {
return nil, err
return nil, errors.WithMessage(constant.ErrRecordNotFound, err.Error())
}
pass, err := encrypt.StringDecrypt(user.Password)
if err != nil {

View file

@ -14,24 +14,22 @@ const (
CodeErrHeader = 406
)
// internal
var (
ErrTypeToken = "ErrToken"
ErrTypeTokenExpired = "ErrTokenExpired"
ErrCaptchaCode = errors.New("ErrCaptchaCode")
ErrRecordExist = errors.New("ErrRecordExist")
ErrRecordNotFound = errors.New("ErrRecordNotFound")
ErrStructTransform = errors.New("ErrStructTransform")
ErrTypeParamInReqBody = "ErrParamInReqBody"
ErrTypeParamInReqQuery = "ErrParamInReqQuery"
ErrTypeInternalServer = "ErrInternalServer"
ErrTypeParamValid = "ErrParamValid"
ErrTokenParse = errors.New("ErrTokenParse")
ErrPageGenerate = errors.New("generate page info failed")
)
// api
var (
ErrTokenExpired = errors.New("token is expired")
ErrTokenNotValidYet = errors.New("token not active yet")
ErrTokenMalformed = errors.New("that's not even a token")
ErrTokenInvalid = errors.New("couldn't handle this token")
ErrCaptchaCode = errors.New("captcha code error")
ErrPageParam = errors.New("paging parameter error")
ErrRecordExist = errors.New("record already exists")
ErrCopyTransform = errors.New("type conversion failure")
ErrTypeInternalServer = "ErrInternalServer"
ErrTypeInvalidParams = "ErrInvalidParams"
ErrTypeToken = "ErrToken"
ErrTypeTokenTimeOut = "ErrTokenTimeOut"
)

View file

@ -16,7 +16,6 @@ require (
github.com/mojocn/base64Captcha v1.3.5
github.com/natefinch/lumberjack v2.0.0+incompatible
github.com/nicksnyder/go-i18n/v2 v2.1.2
github.com/pelletier/go-toml/v2 v2.0.2
github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.9.0
github.com/spf13/viper v1.12.0
@ -24,6 +23,7 @@ require (
github.com/swaggo/gin-swagger v1.5.1
github.com/swaggo/swag v1.8.4
golang.org/x/text v0.3.7
gopkg.in/yaml.v2 v2.4.0
gorm.io/driver/mysql v1.3.5
gorm.io/driver/sqlite v1.3.6
gorm.io/gorm v1.23.8
@ -57,6 +57,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.2 // indirect
github.com/spf13/afero v1.8.2 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
@ -71,6 +72,5 @@ require (
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/ini.v1 v1.66.4 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

View file

@ -6,8 +6,8 @@ import (
ginI18n "github.com/gin-contrib/i18n"
"github.com/gin-gonic/gin"
"github.com/nicksnyder/go-i18n/v2/i18n"
"github.com/pelletier/go-toml/v2"
"golang.org/x/text/language"
"gopkg.in/yaml.v2"
)
func GetMsg(msg string) string {
@ -40,8 +40,8 @@ func GinI18nLocalize() gin.HandlerFunc {
RootPath: "./lang",
AcceptLanguage: []language.Tag{language.Chinese, language.English},
DefaultLanguage: language.Chinese,
FormatBundleFile: "toml",
UnmarshalFunc: toml.Unmarshal,
FormatBundleFile: "yaml",
UnmarshalFunc: yaml.Unmarshal,
Loader: &ginI18n.EmbedLoader{FS: fs},
}),
ginI18n.WithGetLngHandle(

View file

@ -1,3 +0,0 @@
#common
InvalidParams = "parameter validation error {.detail}"
JwtNotFound = ""

View file

@ -0,0 +1,9 @@
ErrInvalidParams: "Request parameter error: {{ .detail }}"
ErrToken: "Token information is incorrect.: {{ .detail }}"
ErrTokenParse: "Token generation error: {{ .detail }}"
ErrTokenTimeOut: "Login information is out of date: {{ .detail }}"
ErrCaptchaCode: "The verification code information is incorrect"
ErrInternalServer: "Service internal error: {{ .detail }}"
ErrRecordExist: "Record already exists: {{ .detail }}"
ErrRecordNotFound: "Records not found: {{ .detail }}"
ErrStructTransform: "Type conversion failure: {{ .detail }}"

View file

@ -1,8 +0,0 @@
#common
ErrInvalidParams = "请求参数错误: {.detail}"
ErrTokenTimeOut = "登陆信息已过期: {.detail}"
ErrCaptchaCode = "错误的验证码信息"
ErrRecordExist = "记录已存在: {.detail}"
ErrRecordNotFound = "记录未能找到: {.detail}"
ErrStructTransform = "类型转换失败: {.detail}"
ErrInternalServer = "服务内部错误: {.detail}"

View file

@ -0,0 +1,9 @@
ErrInvalidParams: "请求参数错误: {{ .detail }}"
ErrToken: "Token 信息错误: {{ .detail }}"
ErrTokenParse: "Token 生成错误: {{ .detail }}"
ErrTokenTimeOut: "登陆信息已过期: {{ .detail }}"
ErrCaptchaCode: "错误的验证码信息"
ErrInternalServer: "服务内部错误: {{ .detail }}"
ErrRecordExist: "记录已存在: {{ .detail }}"
ErrRecordNotFound: "记录未能找到: {{ .detail }}"
ErrStructTransform: "类型转换失败: {{ .detail }}"

View file

@ -23,7 +23,7 @@ func JwtAuth() gin.HandlerFunc {
j := jwtUtils.NewJWT()
claims, err := j.ParseToken(token)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrUnauthorized, constant.ErrTypeToken, err)
helper.ErrorWithDetail(c, constant.CodeErrUnauthorized, constant.ErrTypeInternalServer, err)
return
}
if claims.ExpiresAt.Unix()-time.Now().Unix() < claims.BufferTime {

View file

@ -62,24 +62,11 @@ func (j *JWT) ParseToken(tokenStr string) (*JwtRequest, error) {
token, err := jwt.ParseWithClaims(tokenStr, &JwtRequest{}, func(token *jwt.Token) (interface{}, error) {
return j.SigningKey, nil
})
if err != nil {
if ve, ok := err.(*jwt.ValidationError); ok {
if ve.Errors&jwt.ValidationErrorMalformed != 0 {
return nil, constant.ErrTokenMalformed
} else if ve.Errors&jwt.ValidationErrorExpired != 0 {
return nil, constant.ErrTokenExpired
} else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
return nil, constant.ErrTokenNotValidYet
} else {
return nil, constant.ErrTokenInvalid
}
}
}
if token == nil {
return nil, constant.ErrTokenInvalid
if err != nil || token == nil {
return nil, constant.ErrTokenParse
}
if claims, ok := token.Claims.(*JwtRequest); ok && token.Valid {
return claims, nil
}
return nil, constant.ErrTokenInvalid
return nil, constant.ErrTokenParse
}