diff --git a/internal/bootstrap/server.go b/internal/bootstrap/server.go index eedbc8f..0ea614d 100644 --- a/internal/bootstrap/server.go +++ b/internal/bootstrap/server.go @@ -13,6 +13,7 @@ import ( "cs-agent/internal/controllers/third" "cs-agent/internal/middleware" "cs-agent/internal/pkg/config" + "cs-agent/internal/services" "github.com/kataras/iris/v12" "github.com/kataras/iris/v12/middleware/cors" @@ -91,13 +92,17 @@ func addRouter(app *iris.Application) { mcpHandler.ServeHTTP(w, r) }))) - app.Get("/api/dashboard/ws", middleware.AuthMiddleware, middleware.DashboardWsMiddleware) - app.Get("/api/open/im/ws", middleware.OpenImWsMiddleware) + mvc.Configure(app.Party("/api/ws"), func(m *mvc.Application) { + m.Router.Get("/dashboard", middleware.AuthMiddleware, services.WsService.HandleDashboardWS) + m.Router.Get("/open", services.WsService.HandleOpenWS) + }) mvc.Configure(app.Party("/api"), func(m *mvc.Application) { m.Party("/auth").Handle(new(api.AuthController)) m.Party("/channel").Handle(new(api.ChannelController)) + // m.Router.Get("/ws", middleware.OpenImWsMiddleware) + m.Party("/conversation", middleware.ExternalInfoMiddleware).Handle(new(api.ConversationController)) m.Party("/message", middleware.ExternalInfoMiddleware).Handle(new(api.MessageController)) }) diff --git a/internal/middleware/ws_middleware.go b/internal/middleware/ws_middleware.go deleted file mode 100644 index 6266d71..0000000 --- a/internal/middleware/ws_middleware.go +++ /dev/null @@ -1,50 +0,0 @@ -package middleware - -import ( - "cs-agent/internal/pkg/openidentity" - "cs-agent/internal/services" - "log/slog" - - "github.com/kataras/iris/v12" - "github.com/mlogclub/simple/web" -) - -func DashboardWsMiddleware(ctx iris.Context) { - principal := services.AuthService.GetAuthPrincipal(ctx) - if principal == nil { - if _, err := services.AuthService.Authenticate(ctx); err != nil { - _ = ctx.StopWithJSON(iris.StatusUnauthorized, web.JsonError(err)) - return - } - principal = services.AuthService.GetAuthPrincipal(ctx) - } - if err := services.WsService.UpgradeAdminConnection(ctx, principal); err != nil { - slog.Error("upgrade admin websocket failed", "error", err, "path", ctx.Path()) - ctx.StopExecution() - return - } -} - -func OpenImWsMiddleware(ctx iris.Context) { - channel := services.ChannelService.GetEnabledChannel(ctx) - if channel == nil { - _ = ctx.StopWithJSON(iris.StatusBadRequest, web.JsonErrorMsg("接入渠道不存在或已停用")) - return - } - - principal := services.AuthService.GetAuthPrincipal(ctx) - var external *openidentity.ExternalInfo - if principal == nil { - ext, err := openidentity.GetExternalInfo(ctx) - if err != nil { - _ = ctx.StopWithJSON(iris.StatusUnauthorized, web.JsonError(err)) - return - } - external = ext - } - if err := services.WsService.UpgradeUserConnection(ctx, principal, external); err != nil { - slog.Error("upgrade open im websocket failed", "error", err, "path", ctx.Path(), "channelId", channel.ChannelID, "channel_id", channel.ID) - ctx.StopExecution() - return - } -} diff --git a/internal/services/ws_service.go b/internal/services/ws_service.go index e2f9da9..7fc7cfa 100644 --- a/internal/services/ws_service.go +++ b/internal/services/ws_service.go @@ -4,6 +4,7 @@ import ( "cs-agent/internal/models" "cs-agent/internal/pkg/dto" "cs-agent/internal/pkg/enums" + "cs-agent/internal/pkg/errorsx" "cs-agent/internal/pkg/openidentity" "cs-agent/internal/pkg/utils" "encoding/json" @@ -17,6 +18,7 @@ import ( "github.com/gorilla/websocket" "github.com/kataras/iris/v12" + "github.com/mlogclub/simple/web" ) var WsService = newWsService() @@ -38,14 +40,43 @@ func newWsService() *wsService { } } -// UpgradeUserConnection 开放 IM 用户侧 WebSocket。 -// principal 非空时表示站内用户;否则应传入 external(IM 访客)。二者勿混用为同一业务身份。 -func (s *wsService) UpgradeUserConnection(ctx iris.Context, principal *dto.AuthPrincipal, external *openidentity.ExternalInfo) error { - return s.upgradeConnection(ctx, principal, external, realtimeRoleUser) +func (s *wsService) HandleDashboardWS(ctx iris.Context) { + principal := AuthService.GetAuthPrincipal(ctx) + if principal == nil { + _ = ctx.StopWithJSON(iris.StatusUnauthorized, web.JsonError(errorsx.Unauthorized("未登录或登录已过期"))) + return + } + if err := s.upgradeConnection(ctx, principal, nil, realtimeRoleAdmin); err != nil { + slog.Error("upgrade admin websocket failed", "error", err, "path", ctx.Path()) + ctx.StopExecution() + return + } } -func (s *wsService) UpgradeAdminConnection(ctx iris.Context, principal *dto.AuthPrincipal) error { - return s.upgradeConnection(ctx, principal, nil, realtimeRoleAdmin) +func (s *wsService) HandleOpenWS(ctx iris.Context) { + channel := ChannelService.GetEnabledChannel(ctx) + if channel == nil { + _ = ctx.StopWithJSON(iris.StatusBadRequest, web.JsonErrorMsg("接入渠道不存在或已停用")) + return + } + + var ( + principal = AuthService.GetAuthPrincipal(ctx) + external *openidentity.ExternalInfo + ) + if principal == nil { + ext, err := openidentity.GetExternalInfo(ctx) + if err != nil { + _ = ctx.StopWithJSON(iris.StatusUnauthorized, web.JsonError(err)) + return + } + external = ext + } + if err := s.upgradeConnection(ctx, principal, external, realtimeRoleUser); err != nil { + slog.Error("upgrade open im websocket failed", "error", err, "path", ctx.Path(), "channelId", channel.ChannelID, "channel_id", channel.ID) + ctx.StopExecution() + return + } } func (s *wsService) upgradeConnection(ctx iris.Context, principal *dto.AuthPrincipal, external *openidentity.ExternalInfo, role string) error { diff --git a/web/lib/api/admin.ts b/web/lib/api/admin.ts index 31fb25a..ad0b0a9 100644 --- a/web/lib/api/admin.ts +++ b/web/lib/api/admin.ts @@ -542,7 +542,7 @@ export function createAdminWebSocketUrl() { const params = new URLSearchParams({ accessToken: session.accessToken, }) - return `${baseUrl}/api/dashboard/ws?${params.toString()}` + return `${baseUrl}/api/ws/dashboard?${params.toString()}` } export function fetchChannels( diff --git a/web/lib/im-realtime.ts b/web/lib/im-realtime.ts index 5f418a5..2d48573 100644 --- a/web/lib/im-realtime.ts +++ b/web/lib/im-realtime.ts @@ -32,6 +32,6 @@ export function createImRealtimeConnection() { ? `&externalName=${encodeURIComponent(externalName)}` : "" return new WebSocket( - `${baseUrl}/api/open/im/ws?externalId=${externalId}&externalSource=${externalSource}&channelId=${channelId}${nameQuery}` + `${baseUrl}/api/ws/open?externalId=${externalId}&externalSource=${externalSource}&channelId=${channelId}${nameQuery}` ) }