mirror of
https://github.com/crawlab-team/crawlab.git
synced 2026-01-21 17:21:09 +01:00
Backend:
improve
- AuthMiddleware 注入当前用户的信息
- 增加Context服务支持快捷获取当前登录者信息
- 重构Login/GetMe接口逻辑避免重复的数据库查询
- 规范化error信息声明(向下兼容,旧代码可逐渐迁移规范化)
- 修正部分不符合规范的代码
This commit is contained in:
5
backend/constants/context.go
Normal file
5
backend/constants/context.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package constants
|
||||
|
||||
const (
|
||||
ContextUser = "currentUser"
|
||||
)
|
||||
8
backend/constants/errors.go
Normal file
8
backend/constants/errors.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package constants
|
||||
|
||||
import "crawlab/errors"
|
||||
|
||||
var (
|
||||
//users
|
||||
ErrorUserNotFound = errors.NewBusinessError(10001, "user not found.")
|
||||
)
|
||||
43
backend/errors/errors.go
Normal file
43
backend/errors/errors.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package errors
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Scope int
|
||||
|
||||
const (
|
||||
ScopeSystem Scope = 1
|
||||
ScopeBusiness Scope = 2
|
||||
)
|
||||
|
||||
type OPError struct {
|
||||
Message string
|
||||
Code int
|
||||
Scope Scope
|
||||
}
|
||||
|
||||
func (O OPError) Error() string {
|
||||
var scope string
|
||||
switch O.Scope {
|
||||
case ScopeSystem:
|
||||
scope = "system"
|
||||
break
|
||||
case ScopeBusiness:
|
||||
scope = "business"
|
||||
}
|
||||
return fmt.Sprintf("%s : %d -> %s.", scope, O.Code, O.Message)
|
||||
}
|
||||
|
||||
func NewSystemOPError(code int, message string) *OPError {
|
||||
return &OPError{
|
||||
Message: message,
|
||||
Code: code,
|
||||
Scope: ScopeSystem,
|
||||
}
|
||||
}
|
||||
func NewBusinessError(code int, message string) *OPError {
|
||||
return &OPError{
|
||||
Message: message,
|
||||
Code: code,
|
||||
Scope: ScopeBusiness,
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,7 @@ func AuthorizationMiddleware() gin.HandlerFunc {
|
||||
return
|
||||
}
|
||||
}
|
||||
c.Set(constants.ContextUser, &user)
|
||||
|
||||
// 校验成功
|
||||
c.Next()
|
||||
|
||||
@@ -113,7 +113,7 @@ func PutSchedule(c *gin.Context) {
|
||||
func DeleteSchedule(c *gin.Context) {
|
||||
id := bson.ObjectIdHex("5d429e6c19f7abede924fee2")
|
||||
for _, sch := range scheduleList {
|
||||
if sch.Id == bson.ObjectId(id) {
|
||||
if sch.Id == id {
|
||||
fmt.Println("delete a schedule")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"crawlab/constants"
|
||||
"crawlab/model"
|
||||
"crawlab/services"
|
||||
"crawlab/services/context"
|
||||
"crawlab/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/globalsign/mgo/bson"
|
||||
@@ -171,7 +172,7 @@ func Login(c *gin.Context) {
|
||||
}
|
||||
|
||||
// 获取token
|
||||
tokenStr, err := services.GetToken(user.Username)
|
||||
tokenStr, err := services.MakeToken(&user)
|
||||
if err != nil {
|
||||
HandleError(http.StatusUnauthorized, c, errors.New("not authorized"))
|
||||
return
|
||||
@@ -185,20 +186,16 @@ func Login(c *gin.Context) {
|
||||
}
|
||||
|
||||
func GetMe(c *gin.Context) {
|
||||
// 获取token string
|
||||
tokenStr := c.GetHeader("Authorization")
|
||||
|
||||
// 校验token
|
||||
user, err := services.CheckToken(tokenStr)
|
||||
if err != nil {
|
||||
HandleError(http.StatusUnauthorized, c, errors.New("not authorized"))
|
||||
ctx := context.WithGinContext(c)
|
||||
user := ctx.User()
|
||||
if user == nil {
|
||||
ctx.FailedWithError(constants.ErrorUserNotFound, http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
user.Password = ""
|
||||
|
||||
c.JSON(http.StatusOK, Response{
|
||||
Status: "ok",
|
||||
Message: "success",
|
||||
Data: user,
|
||||
})
|
||||
ctx.Success(struct {
|
||||
*model.User
|
||||
Password string `json:"password,omitempty"`
|
||||
}{
|
||||
User: user,
|
||||
}, nil)
|
||||
}
|
||||
|
||||
73
backend/services/context/context.go
Normal file
73
backend/services/context/context.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"crawlab/constants"
|
||||
"crawlab/errors"
|
||||
"crawlab/model"
|
||||
"fmt"
|
||||
"github.com/apex/log"
|
||||
"github.com/gin-gonic/gin"
|
||||
errors2 "github.com/pkg/errors"
|
||||
"net/http"
|
||||
"runtime/debug"
|
||||
)
|
||||
|
||||
type Context struct {
|
||||
*gin.Context
|
||||
}
|
||||
|
||||
func (c *Context) User() *model.User {
|
||||
userIfe, exists := c.Get(constants.ContextUser)
|
||||
if !exists {
|
||||
return nil
|
||||
}
|
||||
user, ok := userIfe.(*model.User)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return user
|
||||
}
|
||||
func (c *Context) Success(data interface{}, meta interface{}) {
|
||||
if meta == nil {
|
||||
meta = gin.H{}
|
||||
}
|
||||
if data == nil {
|
||||
data = gin.H{}
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"status": "ok",
|
||||
"message": "success",
|
||||
"data": data,
|
||||
"error": "",
|
||||
})
|
||||
}
|
||||
func (c *Context) FailedWithError(err error, httpCode ...int) {
|
||||
|
||||
var code = 200
|
||||
if len(httpCode) > 0 {
|
||||
code = httpCode[0]
|
||||
}
|
||||
log.Errorf("handle error:" + err.Error())
|
||||
debug.PrintStack()
|
||||
switch errors2.Cause(err).(type) {
|
||||
case errors.OPError:
|
||||
c.AbortWithStatusJSON(code, gin.H{
|
||||
"status": "ok",
|
||||
"message": "error",
|
||||
"error": err.Error(),
|
||||
})
|
||||
break
|
||||
default:
|
||||
fmt.Println("deprecated....")
|
||||
c.AbortWithStatusJSON(code, gin.H{
|
||||
"status": "ok",
|
||||
"message": "error",
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func WithGinContext(context *gin.Context) *Context {
|
||||
return &Context{Context: context}
|
||||
}
|
||||
@@ -230,7 +230,7 @@ func ReadFileByStep(filePath string, handle func([]byte, *mgo.GridFile), fileCre
|
||||
for {
|
||||
switch nr, err := f.Read(s[:]); true {
|
||||
case nr < 0:
|
||||
fmt.Fprintf(os.Stderr, "cat: error reading: %s\n", err.Error())
|
||||
_, _ = fmt.Fprintf(os.Stderr, "cat: error reading: %s\n", err.Error())
|
||||
debug.PrintStack()
|
||||
case nr == 0: // EOF
|
||||
return nil
|
||||
@@ -238,7 +238,6 @@ func ReadFileByStep(filePath string, handle func([]byte, *mgo.GridFile), fileCre
|
||||
handle(s[0:nr], fileCreate)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 发布所有爬虫
|
||||
|
||||
@@ -5,11 +5,9 @@ import (
|
||||
"crawlab/model"
|
||||
"crawlab/utils"
|
||||
"errors"
|
||||
"github.com/apex/log"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/globalsign/mgo/bson"
|
||||
"github.com/spf13/viper"
|
||||
"runtime/debug"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -24,28 +22,38 @@ func InitUserService() error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetToken(username string) (tokenStr string, err error) {
|
||||
user, err := model.GetUserByUsername(username)
|
||||
if err != nil {
|
||||
log.Errorf(err.Error())
|
||||
debug.PrintStack()
|
||||
return
|
||||
}
|
||||
|
||||
func MakeToken(user *model.User) (tokenStr string, err error) {
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
|
||||
"id": user.Id,
|
||||
"username": user.Username,
|
||||
"nbf": time.Now().Unix(),
|
||||
})
|
||||
|
||||
tokenStr, err = token.SignedString([]byte(viper.GetString("server.secret")))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
return token.SignedString([]byte(viper.GetString("server.secret")))
|
||||
|
||||
}
|
||||
|
||||
//func GetToken(username string) (tokenStr string, err error) {
|
||||
// user, err := model.GetUserByUsername(username)
|
||||
// if err != nil {
|
||||
// log.Errorf(err.Error())
|
||||
// debug.PrintStack()
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
|
||||
// "id": user.Id,
|
||||
// "username": user.Username,
|
||||
// "nbf": time.Now().Unix(),
|
||||
// })
|
||||
//
|
||||
// tokenStr, err = token.SignedString([]byte(viper.GetString("server.secret")))
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
// return
|
||||
//}
|
||||
|
||||
func SecretFunc() jwt.Keyfunc {
|
||||
return func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(viper.GetString("server.secret")), nil
|
||||
|
||||
Reference in New Issue
Block a user