diff --git a/api/api.go b/api/api.go index 7a238cb..aefb50a 100644 --- a/api/api.go +++ b/api/api.go @@ -66,6 +66,7 @@ type handler struct { tokenService *auth.TokenService oauthProviders map[string]auth.OAuthProvider oauthFrontendURL string + publicURL string } type mfaChallenge struct { @@ -188,6 +189,13 @@ func WithOAuthProviders(providers map[string]auth.OAuthProvider) Option { } } +// WithServerPublicURL configures the public URL of the account service. +func WithServerPublicURL(url string) Option { + return func(h *handler) { + h.publicURL = url + } +} + // WithOAuthFrontendURL configures the frontend URL for OAuth2 redirects. func WithOAuthFrontendURL(url string) Option { return func(h *handler) { @@ -253,6 +261,8 @@ func RegisterRoutes(r *gin.Engine, opts ...Option) { authProtected.POST("/mfa/disable", h.disableMFA) authProtected.GET("/mfa/status", h.mfaStatus) + authProtected.GET("/agent/nodes", h.listAgentNodes) + authProtected.POST("/password/reset", h.requestPasswordReset) authProtected.POST("/password/reset/confirm", h.confirmPasswordReset) diff --git a/api/user_agents.go b/api/user_agents.go new file mode 100644 index 0000000..bcacce3 --- /dev/null +++ b/api/user_agents.go @@ -0,0 +1,56 @@ +package api + +import ( + "net/http" + "net/url" + "strconv" + + "github.com/gin-gonic/gin" +) + +type vlessNode struct { + Name string `json:"name"` + Address string `json:"address"` + Port int `json:"port,omitempty"` + Users []string `json:"users,omitempty"` + Transport string `json:"transport,omitempty"` + Path string `json:"path,omitempty"` + Mode string `json:"mode,omitempty"` + Security string `json:"security,omitempty"` +} + +func (h *handler) listAgentNodes(c *gin.Context) { + // For now, valid nodes are derived from the server's public URL. + // We currently assume the server itself exposes a VLESS/XHTTP endpoint. + // In the future, we might retrieve this from the agent registry if agents report their public IPs. + + nodes := make([]vlessNode, 0) + + if h.publicURL != "" { + u, err := url.Parse(h.publicURL) + if err == nil { + hostname := u.Hostname() + portStr := u.Port() + port := 443 + if portStr != "" { + if p, err := strconv.Atoi(portStr); err == nil { + port = p + } + } else if u.Scheme == "http" { + port = 80 + } + + // Add "Global Acceleration" node (representing the main server) + nodes = append(nodes, vlessNode{ + Name: "Global Acceleration", + Address: hostname, + Port: port, // Default port, client will adjust based on transport if needed + Transport: "xhttp", + Path: "/split", + Security: "tls", + }) + } + } + + c.JSON(http.StatusOK, nodes) +} diff --git a/cmd/accountsvc/main.go b/cmd/accountsvc/main.go index 98a9685..279cfd4 100644 --- a/cmd/accountsvc/main.go +++ b/cmd/accountsvc/main.go @@ -290,7 +290,10 @@ func runServer(ctx context.Context, cfg *config.Config, logger *slog.Logger) err api.WithEmailVerification(cfg.Auth.Enable), api.WithTokenService(tokenService), api.WithOAuthProviders(oauthProviders), + api.WithTokenService(tokenService), + api.WithOAuthProviders(oauthProviders), api.WithOAuthFrontendURL(cfg.Auth.OAuth.FrontendURL), + api.WithServerPublicURL(cfg.Server.PublicURL), ) if agentRegistry != nil {