chore: complete Shangwutong connector integration

This commit is contained in:
Rogee
2026-08-04 18:00:10 +08:00
parent 4611c0201f
commit 3d7ff5a6b1
8 changed files with 215 additions and 26 deletions
+32 -8
View File
@@ -237,14 +237,38 @@ func RegisterRoutes(
// Long-lived Connector service principal routes are intentionally outside
// the user JWT group and accept only a dedicated PlatformApp Bearer token.
if handlers.ShangwutongConnector != nil {
connector := engine.Group("/api/v1/connector/shangwutong")
connector.Use(middleware.ConnectorServiceAuth(db))
connector.GET("/inboxes", handlers.ShangwutongConnector.ListInboxes)
connector.GET("/inboxes/:inbox_id", handlers.ShangwutongConnector.GetInbox)
connector.PUT("/inboxes/:inbox_id/status", handlers.ShangwutongConnector.UpdateInboxStatus)
connector.PUT("/inboxes/:inbox_id/messages/:message_id/status", handlers.ShangwutongConnector.UpdateMessageStatus)
}
// Register routes unconditionally so route parity tests catch accidental removals;
// nil handler checks live inside each closure.
connector := engine.Group("/api/v1/connector/shangwutong")
connector.Use(middleware.ConnectorServiceAuth(db))
connector.GET("/inboxes", func(c *gin.Context) {
if handlers == nil || handlers.ShangwutongConnector == nil {
webhookProviderUnavailable(c)
return
}
handlers.ShangwutongConnector.ListInboxes(c)
})
connector.GET("/inboxes/:inbox_id", func(c *gin.Context) {
if handlers == nil || handlers.ShangwutongConnector == nil {
webhookProviderUnavailable(c)
return
}
handlers.ShangwutongConnector.GetInbox(c)
})
connector.PUT("/inboxes/:inbox_id/status", func(c *gin.Context) {
if handlers == nil || handlers.ShangwutongConnector == nil {
webhookProviderUnavailable(c)
return
}
handlers.ShangwutongConnector.UpdateInboxStatus(c)
})
connector.PUT("/inboxes/:inbox_id/messages/:message_id/status", func(c *gin.Context) {
if handlers == nil || handlers.ShangwutongConnector == nil {
webhookProviderUnavailable(c)
return
}
handlers.ShangwutongConnector.UpdateMessageStatus(c)
})
// API v1 routes — authenticated, account-scoped
apiV1 := engine.Group("/api/v1")
+21 -8
View File
@@ -63,6 +63,10 @@ func TestRegisterRoutesBootsWithChatwootParityConflictGroups(t *testing.T) {
"GET /tiktok/callback",
"GET /app",
"GET /app/*params",
"GET /api/v1/connector/shangwutong/inboxes",
"GET /api/v1/connector/shangwutong/inboxes/:inbox_id",
"PUT /api/v1/connector/shangwutong/inboxes/:inbox_id/status",
"PUT /api/v1/connector/shangwutong/inboxes/:inbox_id/messages/:message_id/status",
"GET /api/v1/accounts/:account_id/captain/assistants/tools",
"GET /api/v1/accounts/:account_id/captain/assistants/:assistant_id",
"PATCH /api/v1/accounts/:account_id/captain/assistants/:assistant_id",
@@ -207,15 +211,24 @@ func TestWebhookNilHandlerReturnsProviderUnavailable(t *testing.T) {
nil,
)
w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodPost, "/webhooks/telegram/bot-token", nil)
engine.ServeHTTP(w, req)
if w.Code != http.StatusServiceUnavailable {
t.Fatalf("expected status %d, got %d", http.StatusServiceUnavailable, w.Code)
cases := []struct {
method string
path string
}{
{method: http.MethodPost, path: "/webhooks/telegram/bot-token"},
{method: http.MethodGet, path: "/api/v1/connector/shangwutong/inboxes"},
}
if strings.Contains(w.Body.String(), "not implemented") || strings.Contains(w.Body.String(), "placeholder") {
t.Fatalf("nil webhook fallback returned placeholder body: %s", w.Body.String())
for _, tc := range cases {
w := httptest.NewRecorder()
req := httptest.NewRequest(tc.method, tc.path, nil)
engine.ServeHTTP(w, req)
if w.Code != http.StatusServiceUnavailable && w.Code != http.StatusUnauthorized {
t.Fatalf("%s %s expected unavailable/auth failure, got %d", tc.method, tc.path, w.Code)
}
if strings.Contains(w.Body.String(), "not implemented") || strings.Contains(w.Body.String(), "placeholder") {
t.Fatalf("nil webhook fallback returned placeholder body: %s", w.Body.String())
}
}
}