289 lines
7.6 KiB
Go
289 lines
7.6 KiB
Go
package socket
|
|
|
|
import (
|
|
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/middleware"
|
|
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/model/app_manage/node"
|
|
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/model/app_manage/project_info"
|
|
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/model/app_manage/script_info"
|
|
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/model/user"
|
|
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/service"
|
|
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/service/app_manage/base_service"
|
|
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/pkg/log"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/golang/glog"
|
|
"github.com/gorilla/websocket"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
)
|
|
|
|
var upgrader = websocket.Upgrader{
|
|
ReadBufferSize: 1024,
|
|
WriteBufferSize: 1024,
|
|
CheckOrigin: func(r *http.Request) bool {
|
|
return true // 允许任何来源的连接
|
|
},
|
|
}
|
|
|
|
// 自定义WebSocket中间件
|
|
func WsHandshakeInterceptor(c *gin.Context) {
|
|
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
|
|
if err != nil {
|
|
c.AbortWithError(http.StatusBadRequest, err)
|
|
return
|
|
}
|
|
defer conn.Close()
|
|
|
|
// 这里可以添加额外的逻辑,如身份验证等
|
|
handshakeOk, permissionMsg := beforeHandshake(c)
|
|
if !handshakeOk {
|
|
conn.WriteMessage(websocket.TextMessage, []byte(permissionMsg))
|
|
conn.Close()
|
|
return
|
|
}
|
|
|
|
// 将连接信息传递给下一个处理程序
|
|
c.Set("wsConn", conn)
|
|
c.Next()
|
|
afterHandshake(c)
|
|
}
|
|
|
|
// beforeHandshake is called before the WebSocket handshake.
|
|
func beforeHandshake(c *gin.Context) (bool, string) {
|
|
var attributes = map[string]interface{}{}
|
|
request := c.Request
|
|
// Extract parameters from the request
|
|
params, _ := url.ParseQuery(request.URL.RawQuery)
|
|
rawToken := params.Get("userId")
|
|
userObj := service.CheckUser(c, rawToken)
|
|
if userObj == nil {
|
|
attributes["permissionMsg"] = "用户不存在"
|
|
return false, "用户不存在"
|
|
}
|
|
|
|
workspaceId := params.Get("workspaceId")
|
|
attributes["workspaceId"] = workspaceId
|
|
|
|
userObject, exist := c.Get(middleware.LoginUserKey)
|
|
if !exist {
|
|
glog.Fatal("Authorization middleware should work together with Authentication middleware")
|
|
return false, "用户不存在"
|
|
}
|
|
|
|
userModel := userObject.(*user.UserObj)
|
|
hasAuth := checkNode(c, attributes, userModel)
|
|
handlerType := c.Query("type")
|
|
if !hasAuth || handlerType == "" {
|
|
attributes["permissionMsg"] = "未匹配到合适的处理类型"
|
|
return false, "未匹配到合适的处理类型: " + handlerType
|
|
}
|
|
|
|
if !checkHandlerType(c, attributes, handlerType, userModel) {
|
|
attributes["permissionMsg"] = "未找到匹配的数据"
|
|
return false, "未找到匹配的数据"
|
|
}
|
|
|
|
// Check permissions
|
|
permissionMsg := checkPermission(c, attributes, userModel, handlerType)
|
|
if len(permissionMsg) > 0 {
|
|
attributes["permissionMsg"] = permissionMsg
|
|
return false, permissionMsg
|
|
}
|
|
|
|
// Get client IP
|
|
ip := c.ClientIP()
|
|
attributes["ip"] = ip
|
|
|
|
// Get user agent
|
|
userAgent := request.Header.Get("User-Agent")
|
|
attributes["User-Agent"] = userAgent
|
|
attributes["userInfo"] = userModel
|
|
|
|
// 放入attributes
|
|
c.Set("attributes", attributes)
|
|
return true, ""
|
|
}
|
|
|
|
func afterHandshake(c *gin.Context) {
|
|
return
|
|
}
|
|
|
|
// checkNode 验证 node 权限
|
|
func checkNode(c *gin.Context, attributes map[string]interface{}, userModel *user.UserObj) bool {
|
|
// 验证 node 权限
|
|
nodeId := c.Query("nodeId")
|
|
// server script时不需要 nodeInfo
|
|
if nodeId != "system" {
|
|
nodeById := node.GetNodeById(nodeId)
|
|
if nodeById.Id == "" {
|
|
return false
|
|
}
|
|
|
|
workspace := base_service.CheckUserWorkspace(nodeById.WorkspaceId, userModel)
|
|
if !workspace {
|
|
return false
|
|
}
|
|
|
|
attributes["nodeInfo"] = nodeById
|
|
}
|
|
return true
|
|
}
|
|
|
|
const (
|
|
Console = "console"
|
|
NodeScript = "nodeScript"
|
|
Script = "script"
|
|
)
|
|
|
|
// checkHandlerType checks the handler type and populates the attributes map accordingly.
|
|
func checkHandlerType(c *gin.Context, attributes map[string]interface{}, handlerType string, userModel *user.UserObj) bool {
|
|
switch handlerType {
|
|
case Console:
|
|
dataItem := checkData(handlerType, userModel, c)
|
|
if dataItem == nil {
|
|
return false
|
|
}
|
|
attributes["projectId"] = dataItem.(project_info.ProjectInfo).ProjectId
|
|
attributes["dataItem"] = dataItem
|
|
case NodeScript:
|
|
dataItem := checkData(handlerType, userModel, c)
|
|
if dataItem == nil {
|
|
return false
|
|
}
|
|
attributes["scriptId"] = dataItem.(script_info.NodeScriptCacheModel).ScriptId
|
|
attributes["dataItem"] = dataItem
|
|
case Script:
|
|
dataItem := checkData(handlerType, userModel, c)
|
|
if dataItem == nil {
|
|
return false
|
|
}
|
|
attributes["scriptId"] = dataItem.(script_info.ScriptModel).Id
|
|
attributes["dataItem"] = dataItem
|
|
default:
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
// checkData checks the data based on the handler type.
|
|
func checkData(handlerType string, userModel *user.UserObj, c *gin.Context) interface{} {
|
|
id := c.Query("id")
|
|
|
|
switch handlerType {
|
|
case "console":
|
|
project, err := project_info.GetProjectById(id)
|
|
if err != nil || project.Id == "" {
|
|
log.Errorf("project not found: %v", err)
|
|
return nil
|
|
}
|
|
|
|
workspace := base_service.CheckUserWorkspace(project.WorkspaceId, userModel)
|
|
if !workspace {
|
|
log.Errorf("user not in workspace: %v", err)
|
|
return false
|
|
}
|
|
return project
|
|
|
|
case "nodeScript":
|
|
nodeScript, err := script_info.GetNodeScriptById(id)
|
|
if err != nil || nodeScript.Id == "" {
|
|
log.Errorf("nodeScript not found: %v", err)
|
|
return nil
|
|
}
|
|
|
|
workspace := base_service.CheckUserWorkspace(nodeScript.WorkspaceId, userModel)
|
|
if !workspace {
|
|
log.Errorf("user not in workspace: %v", err)
|
|
return nil
|
|
}
|
|
return nodeScript
|
|
|
|
case "script":
|
|
script, err := script_info.GetServerScriptModelById(id)
|
|
if err != nil || script.Id == "" {
|
|
log.Errorf("script not found: %v", err)
|
|
return nil
|
|
}
|
|
|
|
workspace := base_service.CheckUserWorkspace(script.WorkspaceId, userModel)
|
|
if !workspace {
|
|
log.Errorf("user not in workspace: %v", err)
|
|
return nil
|
|
}
|
|
|
|
return script
|
|
|
|
default:
|
|
log.Errorf("invalid handler type: %v", handlerType)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// checkPermission checks the user's permission based on the provided information.
|
|
func checkPermission(c *gin.Context, attributes map[string]interface{}, userInfo *user.UserObj, handlerType string) string {
|
|
var dataItem, nodeInfo interface{}
|
|
if v, ok := attributes["dataItem"]; ok {
|
|
dataItem = v
|
|
}
|
|
if v, ok := attributes["nodeInfo"]; ok {
|
|
nodeInfo = v
|
|
}
|
|
optData := dataItem
|
|
if dataItem == nil {
|
|
optData = nodeInfo
|
|
}
|
|
|
|
workspaceId := ""
|
|
if optData != nil {
|
|
switch handlerType {
|
|
case Console:
|
|
if m, ok := optData.(project_info.ProjectInfo); ok {
|
|
workspaceId = m.WorkspaceId
|
|
}
|
|
case NodeScript:
|
|
if m, ok := optData.(script_info.NodeScriptCacheModel); ok {
|
|
workspaceId = m.WorkspaceId
|
|
}
|
|
case Script:
|
|
if m, ok := optData.(script_info.ScriptModel); ok {
|
|
workspaceId = m.WorkspaceId
|
|
}
|
|
}
|
|
}
|
|
|
|
useWorkspaceId := workspaceId
|
|
if strings.EqualFold(workspaceId, "GLOBAL") {
|
|
useWorkspaceId = c.Query("workspaceId")
|
|
} else {
|
|
if !strings.EqualFold(workspaceId, c.Query("workspaceId")) {
|
|
return "数据工作空间和操作工作空间不一致"
|
|
}
|
|
useWorkspaceId = workspaceId
|
|
}
|
|
|
|
if useWorkspaceId == "" {
|
|
return "没有找到数据对应的工作空间,不能进行操作"
|
|
}
|
|
//optData.SetWorkspaceId(useWorkspaceId)
|
|
//switch handlerType {
|
|
//case Console:
|
|
// if m, ok := optData.(project_info.ProjectInfo); ok {
|
|
// m.WorkspaceId = useWorkspaceId
|
|
// }
|
|
//case NodeScript:
|
|
// if m, ok := optData.(script_info.NodeScriptCacheModel); ok {
|
|
// m.WorkspaceId = useWorkspaceId
|
|
// }
|
|
//case Script:
|
|
// if m, ok := optData.(script_info.ScriptModel); ok {
|
|
// m.WorkspaceId = useWorkspaceId
|
|
// }
|
|
//}
|
|
|
|
if userInfo.AdminRole == 1 {
|
|
return ""
|
|
}
|
|
|
|
return ""
|
|
}
|