Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 32 additions & 7 deletions cmd/onecli/apps.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,23 +160,48 @@ func (c *AppsRemoveCmd) Run(out *output.Writer) error {

// AppsDisconnectCmd is `onecli apps disconnect`.
type AppsDisconnectCmd struct {
Provider string `required:"" help:"Provider name (e.g. 'github', 'gmail')."`
DryRun bool `optional:"" name:"dry-run" help:"Validate the request without executing it."`
Provider string `required:"" help:"Provider name (e.g. 'github', 'gmail')."`
ConnectionID string `optional:"" name:"connection-id" help:"Connection ID to disconnect (required if multiple connections exist)."`
DryRun bool `optional:"" name:"dry-run" help:"Validate the request without executing it."`
}

func (c *AppsDisconnectCmd) Run(out *output.Writer) error {
if err := validate.ResourceID(c.Provider); err != nil {
return fmt.Errorf("invalid provider: %w", err)
}
if c.DryRun {
return out.WriteDryRun("Would disconnect app", map[string]string{"provider": c.Provider})
}
client, err := newClient()
if err != nil {
return err
}
if err := client.DisconnectApp(newContext(), c.Provider); err != nil {

connectionID := c.ConnectionID
if connectionID == "" {
connections, err := client.ListConnectionsByProvider(newContext(), c.Provider)
if err != nil {
return err
}
if len(connections) == 0 {
return fmt.Errorf("no connections found for %s", c.Provider)
}
if len(connections) > 1 {
out.Stderr(fmt.Sprintf("Multiple connections found for %s:", c.Provider))
for _, conn := range connections {
label := conn.Label
if label == "" {
label = conn.ID
}
out.Stderr(fmt.Sprintf(" %s %s (%s)", conn.ID, label, conn.Status))
}
return fmt.Errorf("specify --connection-id to disconnect a specific connection")
}
connectionID = connections[0].ID
}

if c.DryRun {
return out.WriteDryRun("Would disconnect app", map[string]string{"provider": c.Provider, "connectionId": connectionID})
}
if err := client.DisconnectApp(newContext(), connectionID); err != nil {
return err
}
return out.Write(map[string]string{"status": "disconnected", "provider": c.Provider})
return out.Write(map[string]string{"status": "disconnected", "provider": c.Provider, "connectionId": connectionID})
}
41 changes: 33 additions & 8 deletions internal/api/apps.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ type AppConfig struct {

// AppConnection is the OAuth connection status.
type AppConnection struct {
ID string `json:"id"`
Provider string `json:"provider"`
Label string `json:"label,omitempty"`
Status string `json:"status"`
Scopes []string `json:"scopes"`
ConnectedAt string `json:"connectedAt"`
Expand Down Expand Up @@ -55,6 +58,36 @@ func (c *Client) GetApp(ctx context.Context, provider string) (*App, error) {
return &app, nil
}

// ListConnections returns all app connections for the current project.
func (c *Client) ListConnections(ctx context.Context) ([]AppConnection, error) {
var resp struct {
Connections []AppConnection `json:"connections"`
}
if err := c.do(ctx, http.MethodGet, "/v1/apps/connections", nil, &resp); err != nil {
return nil, fmt.Errorf("listing connections: %w", err)
}
return resp.Connections, nil
}

// ListConnectionsByProvider returns app connections for a specific provider.
func (c *Client) ListConnectionsByProvider(ctx context.Context, provider string) ([]AppConnection, error) {
var resp struct {
Connections []AppConnection `json:"connections"`
}
if err := c.do(ctx, http.MethodGet, "/v1/apps/connections/"+provider, nil, &resp); err != nil {
return nil, fmt.Errorf("listing connections for %s: %w", provider, err)
}
return resp.Connections, nil
}

// DisconnectApp removes an app connection by ID.
func (c *Client) DisconnectApp(ctx context.Context, connectionID string) error {
if err := c.do(ctx, http.MethodDelete, "/v1/apps/connections/"+connectionID, nil, nil); err != nil {
return fmt.Errorf("disconnecting app: %w", err)
}
return nil
}

// ConfigureApp saves BYOC credentials for a provider.
func (c *Client) ConfigureApp(ctx context.Context, provider string, input ConfigAppInput) error {
var resp SuccessResponse
Expand All @@ -71,11 +104,3 @@ func (c *Client) UnconfigureApp(ctx context.Context, provider string) error {
}
return nil
}

// DisconnectApp removes the OAuth connection for a provider.
func (c *Client) DisconnectApp(ctx context.Context, provider string) error {
if err := c.do(ctx, http.MethodDelete, "/v1/apps/"+provider+"/connection", nil, nil); err != nil {
return fmt.Errorf("disconnecting app: %w", err)
}
return nil
}
Loading