Extract connector complete handler from NewMux
Reduce closure size in NewMux by extracting the /connectors/complete handler into a dedicated handleConnectorComplete function. Cache r.URL.Query() into a local variable to avoid repeated parsing. Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
This commit is contained in:
@@ -149,91 +149,108 @@ func NewMux(
|
|||||||
http.Redirect(w, r, redirectURL, http.StatusSeeOther)
|
http.Redirect(w, r, redirectURL, http.StatusSeeOther)
|
||||||
})
|
})
|
||||||
|
|
||||||
r.Get("/connectors/complete", func(w http.ResponseWriter, r *http.Request) {
|
r.Get("/connectors/complete", handleConnectorComplete(
|
||||||
stateToken := r.URL.Query().Get("state")
|
logger,
|
||||||
if stateToken == "" {
|
baseURL,
|
||||||
httpserver.RenderError(w, http.StatusBadRequest, fmt.Errorf("missing state parameter"))
|
proboSvc,
|
||||||
return
|
connectorRegistry,
|
||||||
}
|
safeRedirect,
|
||||||
|
))
|
||||||
provider, err := connector.ExtractProviderFromState(stateToken)
|
|
||||||
if err != nil {
|
|
||||||
httpserver.RenderError(w, http.StatusBadRequest, fmt.Errorf("cannot extract provider from state: %w", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var connectorProvider coredata.ConnectorProvider
|
|
||||||
if err := connectorProvider.Scan(provider); err != nil {
|
|
||||||
httpserver.RenderError(w, http.StatusBadRequest, fmt.Errorf("unsupported provider: %q", provider))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
connection, state, err := connectorRegistry.CompleteWithState(r.Context(), provider, r)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("cannot complete connector: %w", err))
|
|
||||||
}
|
|
||||||
|
|
||||||
organizationID, err := gid.ParseGID(state.OrganizationID)
|
|
||||||
if err != nil {
|
|
||||||
httpserver.RenderError(w, http.StatusBadRequest, fmt.Errorf("cannot parse organization ID from state: %w", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
svc := proboSvc.WithTenant(organizationID.TenantID())
|
|
||||||
|
|
||||||
var cnnctr *coredata.Connector
|
|
||||||
|
|
||||||
// If a connector_id was passed in the state, this is a
|
|
||||||
// reconnection — update the existing connector's token.
|
|
||||||
if state.ConnectorID != "" {
|
|
||||||
connectorID, err := gid.ParseGID(state.ConnectorID)
|
|
||||||
if err != nil {
|
|
||||||
httpserver.RenderError(w, http.StatusBadRequest, fmt.Errorf("cannot parse connector ID from state: %w", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cnnctr, err = svc.Connectors.Reconnect(r.Context(), connectorID, connection)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("cannot reconnect connector: %w", err))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cnnctr, err = svc.Connectors.Create(
|
|
||||||
r.Context(),
|
|
||||||
probo.CreateConnectorRequest{
|
|
||||||
OrganizationID: organizationID,
|
|
||||||
Provider: connectorProvider,
|
|
||||||
Protocol: coredata.ConnectorProtocol(connection.Type()),
|
|
||||||
Connection: connection,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("cannot create connector: %w", err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append connector_id to the redirect URL so frontend can create the bridge
|
|
||||||
redirectURL := state.ContinueURL
|
|
||||||
if redirectURL == "" {
|
|
||||||
redirectURL = baseURL.WithPath("/organizations/" + organizationID.String()).MustString()
|
|
||||||
}
|
|
||||||
|
|
||||||
parsedURL, err := url.Parse(redirectURL)
|
|
||||||
if err != nil {
|
|
||||||
logger.ErrorCtx(r.Context(), "cannot parse redirect URL", log.Error(err))
|
|
||||||
parsedURL, _ = url.Parse(baseURL.WithPath("/organizations/" + organizationID.String()).MustString())
|
|
||||||
}
|
|
||||||
q := parsedURL.Query()
|
|
||||||
q.Set("connector_id", cnnctr.ID.String())
|
|
||||||
q.Set("provider", string(connectorProvider))
|
|
||||||
parsedURL.RawQuery = q.Encode()
|
|
||||||
|
|
||||||
safeRedirect.Redirect(w, r, parsedURL.String(), "/", http.StatusSeeOther)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleConnectorComplete(
|
||||||
|
logger *log.Logger,
|
||||||
|
baseURL *baseurl.BaseURL,
|
||||||
|
proboSvc *probo.Service,
|
||||||
|
connectorRegistry *connector.ConnectorRegistry,
|
||||||
|
safeRedirect *saferedirect.SafeRedirect,
|
||||||
|
) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
query := r.URL.Query()
|
||||||
|
|
||||||
|
stateToken := query.Get("state")
|
||||||
|
if stateToken == "" {
|
||||||
|
httpserver.RenderError(w, http.StatusBadRequest, fmt.Errorf("missing state parameter"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
provider, err := connector.ExtractProviderFromState(stateToken)
|
||||||
|
if err != nil {
|
||||||
|
httpserver.RenderError(w, http.StatusBadRequest, fmt.Errorf("cannot extract provider from state: %w", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var connectorProvider coredata.ConnectorProvider
|
||||||
|
if err := connectorProvider.Scan(provider); err != nil {
|
||||||
|
httpserver.RenderError(w, http.StatusBadRequest, fmt.Errorf("unsupported provider: %q", provider))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
connection, state, err := connectorRegistry.CompleteWithState(r.Context(), provider, r)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("cannot complete connector: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
organizationID, err := gid.ParseGID(state.OrganizationID)
|
||||||
|
if err != nil {
|
||||||
|
httpserver.RenderError(w, http.StatusBadRequest, fmt.Errorf("cannot parse organization ID from state: %w", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
svc := proboSvc.WithTenant(organizationID.TenantID())
|
||||||
|
|
||||||
|
var cnnctr *coredata.Connector
|
||||||
|
|
||||||
|
// If a connector_id was passed in the state, this is a
|
||||||
|
// reconnection — update the existing connector's token.
|
||||||
|
if state.ConnectorID != "" {
|
||||||
|
connectorID, err := gid.ParseGID(state.ConnectorID)
|
||||||
|
if err != nil {
|
||||||
|
httpserver.RenderError(w, http.StatusBadRequest, fmt.Errorf("cannot parse connector ID from state: %w", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cnnctr, err = svc.Connectors.Reconnect(r.Context(), connectorID, connection)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("cannot reconnect connector: %w", err))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cnnctr, err = svc.Connectors.Create(
|
||||||
|
r.Context(),
|
||||||
|
probo.CreateConnectorRequest{
|
||||||
|
OrganizationID: organizationID,
|
||||||
|
Provider: connectorProvider,
|
||||||
|
Protocol: coredata.ConnectorProtocol(connection.Type()),
|
||||||
|
Connection: connection,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("cannot create connector: %w", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
redirectURL := state.ContinueURL
|
||||||
|
if redirectURL == "" {
|
||||||
|
redirectURL = baseURL.WithPath("/organizations/" + organizationID.String()).MustString()
|
||||||
|
}
|
||||||
|
|
||||||
|
parsedURL, err := url.Parse(redirectURL)
|
||||||
|
if err != nil {
|
||||||
|
logger.ErrorCtx(r.Context(), "cannot parse redirect URL", log.Error(err))
|
||||||
|
parsedURL, _ = url.Parse(baseURL.WithPath("/organizations/" + organizationID.String()).MustString())
|
||||||
|
}
|
||||||
|
q := parsedURL.Query()
|
||||||
|
q.Set("connector_id", cnnctr.ID.String())
|
||||||
|
q.Set("provider", string(connectorProvider))
|
||||||
|
parsedURL.RawQuery = q.Encode()
|
||||||
|
|
||||||
|
safeRedirect.Redirect(w, r, parsedURL.String(), "/", http.StatusSeeOther)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Resolver) ProboService(ctx context.Context, tenantID gid.TenantID) *probo.TenantService {
|
func (r *Resolver) ProboService(ctx context.Context, tenantID gid.TenantID) *probo.TenantService {
|
||||||
return r.probo.WithTenant(tenantID)
|
return r.probo.WithTenant(tenantID)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user