update
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"OneAuth/cfg"
|
||||
"OneAuth/libs/oerr"
|
||||
"OneAuth/models"
|
||||
"github.com/veypi/OneBD"
|
||||
"github.com/veypi/OneBD/rfc"
|
||||
)
|
||||
|
||||
type Auth struct {
|
||||
Payload *models.PayLoad
|
||||
ignoreMethod map[rfc.Method]bool
|
||||
}
|
||||
|
||||
func (a *Auth) Init(m OneBD.Meta) error {
|
||||
if a.ignoreMethod != nil && a.ignoreMethod[m.Method()] {
|
||||
return nil
|
||||
}
|
||||
a.Payload = new(models.PayLoad)
|
||||
token := m.GetHeader("auth_token")
|
||||
if token == "" {
|
||||
return oerr.NotLogin
|
||||
}
|
||||
ok, err := models.ParseToken(token, cfg.CFG.Key, a.Payload)
|
||||
if ok {
|
||||
return nil
|
||||
}
|
||||
return oerr.NotLogin.Attach(err)
|
||||
}
|
||||
|
||||
func (a *Auth) Ignore(methods ...rfc.Method) {
|
||||
if a.ignoreMethod == nil {
|
||||
a.ignoreMethod = make(map[rfc.Method]bool)
|
||||
}
|
||||
for _, m := range methods {
|
||||
a.ignoreMethod[m] = true
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Auth) CheckAuth(name string, tags ...string) models.AuthLevel {
|
||||
return a.Payload.CheckAuth(name, tags...)
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"OneAuth/libs/auth"
|
||||
"OneAuth/libs/oerr"
|
||||
"OneAuth/libs/tools"
|
||||
"github.com/json-iterator/go"
|
||||
"github.com/veypi/OneBD"
|
||||
"github.com/veypi/OneBD/rfc"
|
||||
"github.com/veypi/utils/log"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var json = jsoniter.ConfigFastest
|
||||
|
||||
type ApiHandler struct {
|
||||
OneBD.BaseHandler
|
||||
auth.Auth
|
||||
}
|
||||
|
||||
func (h *ApiHandler) Init(m OneBD.Meta) error {
|
||||
return tools.MultiIniter(m, &h.BaseHandler, &h.Auth)
|
||||
}
|
||||
|
||||
func (h *ApiHandler) OnResponse(data interface{}) {
|
||||
if h.Meta().Method() == rfc.MethodHead {
|
||||
h.Meta().SetHeader("status", "1")
|
||||
return
|
||||
}
|
||||
p, err := json.Marshal(map[string]interface{}{"status": 1, "content": data})
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Msg("encode json data error")
|
||||
return
|
||||
}
|
||||
h.Meta().Write(p)
|
||||
}
|
||||
|
||||
func (h *ApiHandler) OnError(err error) {
|
||||
log.WithNoCaller.Warn().Err(err).Msg(h.Meta().RequestPath())
|
||||
msg := err.Error()
|
||||
if h.Meta().Method() == rfc.MethodHead {
|
||||
h.Meta().SetHeader("status", "0")
|
||||
h.Meta().SetHeader("code", strconv.Itoa(int(oerr.OfType(msg))))
|
||||
h.Meta().SetHeader("err", msg)
|
||||
} else {
|
||||
p, _ := json.Marshal(map[string]interface{}{"status": 0, "code": oerr.OfType(msg), "err": msg})
|
||||
h.Meta().Write(p)
|
||||
}
|
||||
}
|
||||
|
||||
var ioNumLimit = make(map[string]time.Time)
|
||||
var limitLocker = sync.RWMutex{}
|
||||
|
||||
func (h *ApiHandler) SetAccessDelta(d time.Duration) error {
|
||||
// 尽量对写操作加频率限制
|
||||
now := time.Now()
|
||||
limitLocker.Lock()
|
||||
label := h.Meta().RemoteAddr() + h.Meta().RequestPath()
|
||||
last, ok := ioNumLimit[label]
|
||||
defer func() {
|
||||
ioNumLimit[label] = now
|
||||
limitLocker.Unlock()
|
||||
}()
|
||||
if !ok {
|
||||
return nil
|
||||
} else if now.Sub(last) >= d {
|
||||
return nil
|
||||
}
|
||||
return oerr.AccessTooFast
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
package oerr
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"gorm.io/gorm"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// 错误描述
|
||||
|
||||
type Code uint
|
||||
|
||||
/*
|
||||
|
||||
5位10进制码表示错误, 00000 etc.
|
||||
|
||||
0 代表未知,或不必定义的有通用意义的错误
|
||||
|
||||
## 第1位 错误类型
|
||||
- 1 : 系统级错误 比如 内存申请失败, 系统调用失败,文件打开失败等等
|
||||
- 2 : 数据库错误
|
||||
- 3 : 保留
|
||||
- 4 : 权限错误
|
||||
- 5 : 配置错误
|
||||
- 6 : 参数错误
|
||||
- 7 : 时序(控制)错误
|
||||
|
||||
## 第2位 2级错误类型
|
||||
|
||||
## 第3,4位 具体错误编号
|
||||
|
||||
## 第5位 错误严重程度
|
||||
- 0 : 无任何影响错误,简单重试可以解决
|
||||
- 1 : 无影响错误,重试不可解决
|
||||
- 2 : 有影响用户体验或系统性能错误, 重试可解决
|
||||
- 3 : 有影响用户体验或系统性能错误, 重试不可解决
|
||||
- 4 : 有影响组件功能的错误, 重试可解决
|
||||
- 5 : 有影响组件功能的错误, 重试不可解决
|
||||
- 6 : 有影响服务运行的错误, 重启可解决
|
||||
- 7 : 有影响服务运行的错误,重启不可解决
|
||||
- 8 : 有影响系统运行的错误
|
||||
- 9 : 本不可能发生的错误,例如被人攻击导致数据异常产生的逻辑错误
|
||||
|
||||
*/
|
||||
const (
|
||||
Unknown Code = 0
|
||||
)
|
||||
const (
|
||||
// 2 数据库错误
|
||||
// -1 系统错误
|
||||
// -2 数据读写错误
|
||||
DBErr Code = 20001
|
||||
ResourceCreatedFailed Code = 22012
|
||||
ResourceDuplicated Code = 22021
|
||||
ResourceNotExist Code = 22031
|
||||
)
|
||||
|
||||
const (
|
||||
// 3
|
||||
)
|
||||
|
||||
const (
|
||||
// 4 权限类型错误
|
||||
// 1: 登录权限
|
||||
// 2: 资源操作权限
|
||||
NotLogin Code = 41001
|
||||
LoginExpired Code = 41011
|
||||
PassError Code = 41021
|
||||
DisableLogin Code = 41031
|
||||
AccountNotExist Code = 41041
|
||||
NoAuth Code = 42011
|
||||
)
|
||||
|
||||
// 6 参数类型错误
|
||||
/*
|
||||
-1: 协议参数
|
||||
-2: 接口参数
|
||||
-3: 函数参数
|
||||
-4: 数据依赖错误
|
||||
*/
|
||||
const (
|
||||
MethodNotSupport Code = 61111
|
||||
MethodNotAllowed Code = 61121
|
||||
|
||||
ApiArgsError Code = 62001
|
||||
ApiArgsMissing Code = 62011
|
||||
TableArgsMissing Code = 62021
|
||||
TableArgsErr Code = 62031
|
||||
|
||||
FuncArgsError Code = 63001
|
||||
UrlPatternNotSupport Code = 63117
|
||||
UrlDefinedDuplicate Code = 63127
|
||||
UrlParamDuplicate Code = 63137
|
||||
|
||||
DataError Code = 64009
|
||||
)
|
||||
|
||||
// 7 : 时序(控制)错误
|
||||
/*
|
||||
-1: 访问控制
|
||||
*/
|
||||
|
||||
const (
|
||||
AccessErr Code = 71001
|
||||
AccessTooFast Code = 71010
|
||||
)
|
||||
|
||||
var codeMap = map[Code]string{
|
||||
Unknown: "unknown error",
|
||||
DBErr: "db error",
|
||||
ResourceCreatedFailed: "resource created failed",
|
||||
ResourceDuplicated: "resource duplicated",
|
||||
ResourceNotExist: "Resource not exist",
|
||||
MethodNotSupport: "this http method is not supported",
|
||||
MethodNotAllowed: "this http method is not allowed",
|
||||
ApiArgsError: "base args error",
|
||||
ApiArgsMissing: "missing args",
|
||||
TableArgsMissing: "missing data",
|
||||
TableArgsErr: "invalid table data",
|
||||
FuncArgsError: "func args error",
|
||||
UrlPatternNotSupport: "this router's url pattern is not supported.",
|
||||
UrlDefinedDuplicate: "this router's url has been defined",
|
||||
UrlParamDuplicate: "this param defined in router's url duplicated",
|
||||
DataError: "data error",
|
||||
NotLogin: "not login",
|
||||
LoginExpired: "login expired",
|
||||
DisableLogin: "disabled to login",
|
||||
PassError: "password/account error",
|
||||
AccountNotExist: "account not exist",
|
||||
NoAuth: "no auth to access",
|
||||
AccessErr: "access error",
|
||||
AccessTooFast: "access too fast",
|
||||
}
|
||||
|
||||
func (c Code) Error() string {
|
||||
return strconv.Itoa(int(c)) + ":" + c.String()
|
||||
}
|
||||
|
||||
func (c Code) String() string {
|
||||
s, ok := codeMap[c]
|
||||
if ok && len(s) > 0 {
|
||||
return s
|
||||
}
|
||||
return codeMap[Unknown]
|
||||
}
|
||||
|
||||
// 附加错误详细原因
|
||||
func (c Code) Attach(errs ...error) (e error) {
|
||||
e = c
|
||||
for _, err := range errs {
|
||||
if err != nil {
|
||||
e = &wrapErr{msg: e.Error() + "\n" + err.Error(), err: e}
|
||||
}
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
func (c Code) AttachStr(errs ...string) (e error) {
|
||||
e = c
|
||||
for _, m := range errs {
|
||||
if m != "" {
|
||||
e = &wrapErr{
|
||||
msg: e.Error() + "\n" + m,
|
||||
err: e,
|
||||
}
|
||||
}
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
func OfType(errMsg string) Code {
|
||||
s := ""
|
||||
if gorm.ErrRecordNotFound.Error() == errMsg {
|
||||
return ResourceNotExist
|
||||
}
|
||||
for _, v := range errMsg {
|
||||
if v == ':' {
|
||||
break
|
||||
}
|
||||
s += string(v)
|
||||
}
|
||||
c, _ := strconv.Atoi(s)
|
||||
return Code(c)
|
||||
}
|
||||
|
||||
type wrapErr struct {
|
||||
msg string
|
||||
err error
|
||||
}
|
||||
|
||||
func (w *wrapErr) Error() string {
|
||||
return w.msg
|
||||
}
|
||||
|
||||
func (w *wrapErr) UnWrap() error {
|
||||
return w.err
|
||||
}
|
||||
|
||||
func CheckMultiErr(errs ...error) error {
|
||||
msg := ""
|
||||
for _, e := range errs {
|
||||
if e != nil {
|
||||
msg += e.Error() + "\n"
|
||||
}
|
||||
}
|
||||
if msg != "" {
|
||||
return errors.New(msg)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/veypi/OneBD"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
type Initer interface {
|
||||
Init(OneBD.Meta) error
|
||||
}
|
||||
|
||||
func MultiIniter(m OneBD.Meta, is ...Initer) (err error) {
|
||||
for _, i := range is {
|
||||
err = i.Init(m)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func Query(addr string, query map[string]string, res interface{}) error {
|
||||
u, err := url.Parse(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
paras := &url.Values{}
|
||||
//设置请求参数
|
||||
for k, v := range query {
|
||||
paras.Set(k, v)
|
||||
}
|
||||
u.RawQuery = paras.Encode()
|
||||
resp, err := http.Get(u.String())
|
||||
//关闭资源
|
||||
if resp != nil && resp.Body != nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.NewDecoder(resp.Body).Decode(res)
|
||||
}
|
||||
Reference in New Issue
Block a user