- Updated the registration process to utilize NodeID instead of TaiID, allowing for server-generated TaiIDs. - Implemented additional fields in the registration request, including DisplayName and improved error handling for missing parameters. - Enhanced the connection logic for registered nodes, ensuring proper client binding and logging for better traceability. - Introduced new methods for extracting and managing extra claims in OAuth tokens, improving the flexibility of user identification. Made-with: Cursor
203 lines
5.7 KiB
Go
203 lines
5.7 KiB
Go
package openapi
|
|
|
|
import (
|
|
"path/filepath"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/yaoapp/gou/application"
|
|
"github.com/yaoapp/yao/config"
|
|
"github.com/yaoapp/yao/openapi/agent"
|
|
"github.com/yaoapp/yao/openapi/app"
|
|
"github.com/yaoapp/yao/openapi/captcha"
|
|
"github.com/yaoapp/yao/openapi/chat"
|
|
"github.com/yaoapp/yao/openapi/dsl"
|
|
"github.com/yaoapp/yao/openapi/file"
|
|
"github.com/yaoapp/yao/openapi/hello"
|
|
openintegrations "github.com/yaoapp/yao/openapi/integrations"
|
|
"github.com/yaoapp/yao/openapi/job"
|
|
"github.com/yaoapp/yao/openapi/kb"
|
|
"github.com/yaoapp/yao/openapi/llm"
|
|
"github.com/yaoapp/yao/openapi/mcp"
|
|
"github.com/yaoapp/yao/openapi/messenger"
|
|
"github.com/yaoapp/yao/openapi/nodes"
|
|
"github.com/yaoapp/yao/openapi/oauth"
|
|
"github.com/yaoapp/yao/openapi/oauth/acl"
|
|
"github.com/yaoapp/yao/openapi/oauth/types"
|
|
"github.com/yaoapp/yao/openapi/otp"
|
|
"github.com/yaoapp/yao/openapi/response"
|
|
"github.com/yaoapp/yao/openapi/sandbox"
|
|
"github.com/yaoapp/yao/openapi/team"
|
|
openapiTrace "github.com/yaoapp/yao/openapi/trace"
|
|
"github.com/yaoapp/yao/openapi/user"
|
|
openapiWorkspace "github.com/yaoapp/yao/openapi/workspace"
|
|
taiapi "github.com/yaoapp/yao/tai/api"
|
|
taitunnel "github.com/yaoapp/yao/tai/tunnel"
|
|
)
|
|
|
|
// Server is the OpenAPI server
|
|
var Server *OpenAPI = nil
|
|
|
|
// OpenAPI is the OpenAPI server
|
|
type OpenAPI struct {
|
|
Config *Config // OpenAPI configuration
|
|
OAuth types.OAuth // OAuth service interface
|
|
}
|
|
|
|
// Load loads the OpenAPI server from the configuration
|
|
func Load(appConfig config.Config) (*OpenAPI, error) {
|
|
|
|
var configPath string = filepath.Join("openapi", "openapi.yao")
|
|
var configRaw, err = application.App.Read(configPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Parse the configuration
|
|
var config Config
|
|
err = application.Parse(configPath, configRaw, &config)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Convert the configuration to an OAuth configuration
|
|
oauthConfig, err := config.OAuthConfig(appConfig)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Create the OAuth service
|
|
oauthService, err := oauth.NewService(oauthConfig)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Set the secure cookie configuration for the response package
|
|
// This determines whether to use __Host- prefix and Secure flag for cookies
|
|
response.SetSecureCookieEnabled(oauthConfig.Security.SecureCookie)
|
|
|
|
// Load user configurations
|
|
err = user.Load(appConfig)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Load the ACL enforcer
|
|
_, err = acl.Load(&acl.Config{
|
|
Enabled: true,
|
|
PathPrefix: config.BaseURL,
|
|
Cache: oauthConfig.Cache,
|
|
Provider: oauthConfig.UserProvider,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Initialize OTP service (shares the OAuth store)
|
|
otp.NewService(oauthService.GetStore(), oauthService.GetKeyPrefix())
|
|
|
|
// Create the OpenAPI server
|
|
Server = &OpenAPI{Config: &config, OAuth: oauthService}
|
|
return Server, nil
|
|
}
|
|
|
|
// Attach attaches the OpenAPI server to the router
|
|
func (openapi *OpenAPI) Attach(router *gin.Engine) {
|
|
|
|
// Ignore if the OpenAPI server is not configured
|
|
if openapi.Config == nil {
|
|
return
|
|
}
|
|
|
|
// Basic Groups
|
|
baseURL := openapi.Config.BaseURL
|
|
group := router.Group(baseURL)
|
|
|
|
// Well-known handlers
|
|
openapi.attachWellKnown(router)
|
|
|
|
// Models ( LLM Agent )
|
|
group.GET("/models", openapi.OAuth.Guard, agent.GetModels)
|
|
|
|
// Get Model Details ( LLM Agent )
|
|
group.GET("/models/:model_name", openapi.OAuth.Guard, agent.GetModelDetails)
|
|
|
|
// OAuth handlers
|
|
openapi.attachOAuth(group)
|
|
|
|
// Hello World handlers
|
|
hello.Attach(group.Group("/helloworld"), openapi.OAuth)
|
|
|
|
// DSL handlers
|
|
dsl.Attach(group.Group("/dsl"), openapi.OAuth)
|
|
|
|
// File handlers
|
|
file.Attach(group.Group("/file"), openapi.OAuth)
|
|
|
|
// Knowledge Base handlers
|
|
kb.Attach(group.Group("/kb"), openapi.OAuth)
|
|
|
|
// Job Management handlers
|
|
job.Attach(group.Group("/job"), openapi.OAuth)
|
|
|
|
// Chat handlers
|
|
chat.Attach(group.Group("/chat"), openapi.OAuth)
|
|
|
|
// Captcha handlers
|
|
captcha.Attach(group.Group("/captcha"), openapi.OAuth)
|
|
|
|
// User handlers
|
|
user.Attach(group.Group("/user"), openapi.OAuth)
|
|
|
|
// Team handlers
|
|
team.Attach(group.Group("/team"), openapi.OAuth)
|
|
|
|
// Messenger webhook handlers
|
|
messenger.Attach(group.Group("/messenger"), openapi.OAuth)
|
|
|
|
// Integrations webhook handlers (public, no OAuth - external platforms push here)
|
|
openintegrations.Attach(group.Group("/integrations"))
|
|
|
|
// Agent handlers
|
|
agent.Attach(group.Group("/agent"), openapi.OAuth)
|
|
|
|
// LLM Provider handlers
|
|
llm.Attach(group.Group("/llm"), openapi.OAuth)
|
|
|
|
// MCP Server handlers
|
|
mcp.Attach(group.Group("/mcp"), openapi.OAuth)
|
|
|
|
// Trace handlers
|
|
openapiTrace.Attach(group.Group("/trace"), openapi.OAuth)
|
|
|
|
// App handlers (menu, etc.)
|
|
app.Attach(group.Group("/app"), openapi.OAuth)
|
|
|
|
// OTP handlers (passwordless authentication)
|
|
otp.Attach(group.Group("/otp"), openapi.OAuth)
|
|
|
|
// Sandbox handlers (VNC proxy + management CRUD)
|
|
sandbox.SetPathPrefix(baseURL)
|
|
sandboxGroup := group.Group("/sandbox")
|
|
sandbox.Attach(sandboxGroup, openapi.OAuth)
|
|
sandbox.AttachManage(sandboxGroup)
|
|
|
|
// Workspace handlers
|
|
openapiWorkspace.Attach(group.Group("/workspace"), openapi.OAuth)
|
|
|
|
// Tai nodes handlers
|
|
nodes.Attach(group.Group("/nodes"), openapi.OAuth)
|
|
|
|
// Tai tunnel WebSocket and reverse proxy routes
|
|
group.GET("/ws/tai", taitunnel.HandleControl)
|
|
group.GET("/ws/tai/data/:channel_id", taitunnel.HandleData)
|
|
group.Any("/tai/:taiID/proxy/*path", taitunnel.HandleProxy)
|
|
group.GET("/tai/:taiID/vnc/*path", taitunnel.HandleVNC)
|
|
|
|
// Tai direct registration API (uses /tai-nodes/ prefix to avoid routing conflict with /tai/:taiID/)
|
|
group.POST("/tai-nodes/register", taiapi.HandleRegister)
|
|
group.POST("/tai-nodes/heartbeat", taiapi.HandleHeartbeat)
|
|
group.DELETE("/tai-nodes/register/:tai_id", taiapi.HandleUnregister)
|
|
|
|
// Custom handlers (Defined by developer)
|
|
|
|
}
|