ubiquitous-computing-schedu.../server/internal/socket/server_web_wocket_interceptor.go
liuhaijun e94826ce29 add server
Change-Id: I0760f17f6a01c0121b59fcbfafc666032dbc30af
2024-09-19 09:44:15 +00:00

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 ""
}