Add comprehensive integration capabilities to Pop CLI: - Multi-account support with named profiles - Webhook management with signature verification - External PGP key management (import/export/encrypt/decrypt/sign/verify) - CLI plugin system for extensibility - Complete documentation in README.md All compilation errors fixed and build verified CLEAN. Security review delegated to FRE-5202. Co-Authored-By: Paperclip <noreply@paperclip.ing>
211 lines
5.5 KiB
Go
211 lines
5.5 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"text/tabwriter"
|
|
|
|
"github.com/frenocorp/pop/internal/accounts"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
func accountsCmd() *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: "accounts",
|
|
Short: "Manage multiple ProtonMail accounts",
|
|
Long: `Add, list, switch, and remove named ProtonMail account profiles.`,
|
|
}
|
|
|
|
cmd.AddCommand(accountsListCmd())
|
|
cmd.AddCommand(accountsAddCmd())
|
|
cmd.AddCommand(accountsRemoveCmd())
|
|
cmd.AddCommand(accountsDefaultCmd())
|
|
cmd.AddCommand(accountsShowCmd())
|
|
|
|
return cmd
|
|
}
|
|
|
|
func accountsListCmd() *cobra.Command {
|
|
return &cobra.Command{
|
|
Use: "list",
|
|
Short: "List all configured accounts",
|
|
Long: `Show all saved ProtonMail account profiles.`,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
store, err := accounts.NewAccountsStore()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create accounts store: %w", err)
|
|
}
|
|
|
|
accts, err := store.LoadAccounts()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to load accounts: %w", err)
|
|
}
|
|
|
|
if len(accts) == 0 {
|
|
fmt.Println("No accounts configured. Use 'pop accounts add' to create one.")
|
|
return nil
|
|
}
|
|
|
|
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
|
fmt.Fprintln(w, "Name\tEmail\tDefault\tAPI Base\tCreated")
|
|
fmt.Fprintln(w, "----\t-----\t-------\t--------\t-------")
|
|
|
|
for _, acc := range accts {
|
|
def := "-"
|
|
if acc.Default {
|
|
def = "*"
|
|
}
|
|
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n",
|
|
acc.Name, acc.Email, def, acc.APIBaseURL, acc.CreatedAt)
|
|
}
|
|
|
|
return w.Flush()
|
|
},
|
|
}
|
|
}
|
|
|
|
func accountsAddCmd() *cobra.Command {
|
|
var name, email, apiURL string
|
|
var isDefault bool
|
|
|
|
cmd := &cobra.Command{
|
|
Use: "add <name>",
|
|
Short: "Add a new account profile",
|
|
Long: `Add a named ProtonMail account profile for multi-account support.`,
|
|
Args: cobra.MaximumNArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
accountName := name
|
|
if len(args) > 0 && args[0] != "" {
|
|
accountName = args[0]
|
|
}
|
|
if accountName == "" {
|
|
return fmt.Errorf("account name is required")
|
|
}
|
|
if email == "" {
|
|
return fmt.Errorf("email is required (--email)")
|
|
}
|
|
|
|
store, err := accounts.NewAccountsStore()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create accounts store: %w", err)
|
|
}
|
|
|
|
if err := store.AddAccount(accountName, email, apiURL, isDefault); err != nil {
|
|
return fmt.Errorf("failed to add account: %w", err)
|
|
}
|
|
|
|
fmt.Printf("Added account: %s (%s)\n", accountName, email)
|
|
if isDefault {
|
|
fmt.Println("Set as default account")
|
|
}
|
|
return nil
|
|
},
|
|
}
|
|
|
|
cmd.Flags().StringVar(&name, "name", "", "Account name (or pass as positional argument)")
|
|
cmd.Flags().StringVarP(&email, "email", "e", "", "ProtonMail email address")
|
|
cmd.Flags().StringVar(&apiURL, "api-url", "", "Custom API base URL")
|
|
cmd.Flags().BoolVarP(&isDefault, "default", "d", false, "Set as default account")
|
|
_ = cmd.MarkFlagRequired("email")
|
|
|
|
return cmd
|
|
}
|
|
|
|
func accountsRemoveCmd() *cobra.Command {
|
|
return &cobra.Command{
|
|
Use: "remove <name>",
|
|
Short: "Remove an account profile",
|
|
Long: `Remove a named ProtonMail account profile.`,
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
accountName := args[0]
|
|
|
|
store, err := accounts.NewAccountsStore()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create accounts store: %w", err)
|
|
}
|
|
|
|
if err := store.RemoveAccount(accountName); err != nil {
|
|
return fmt.Errorf("failed to remove account: %w", err)
|
|
}
|
|
|
|
fmt.Printf("Removed account: %s\n", accountName)
|
|
return nil
|
|
},
|
|
}
|
|
}
|
|
|
|
func accountsDefaultCmd() *cobra.Command {
|
|
var setName string
|
|
|
|
cmd := &cobra.Command{
|
|
Use: "default [name]",
|
|
Short: "Get or set the default account",
|
|
Long: `Show the current default account, or set a new default.`,
|
|
Args: cobra.MaximumNArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
store, err := accounts.NewAccountsStore()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create accounts store: %w", err)
|
|
}
|
|
|
|
if setName == "" && len(args) > 0 {
|
|
setName = args[0]
|
|
}
|
|
|
|
if setName != "" {
|
|
if err := store.SetDefaultAccount(setName); err != nil {
|
|
return fmt.Errorf("failed to set default account: %w", err)
|
|
}
|
|
fmt.Printf("Set default account to: %s\n", setName)
|
|
return nil
|
|
}
|
|
|
|
acct, err := store.GetAccount("")
|
|
if err != nil {
|
|
return fmt.Errorf("no default account: %w", err)
|
|
}
|
|
fmt.Printf("Default account: %s (%s)\n", acct.Name, acct.Email)
|
|
return nil
|
|
},
|
|
}
|
|
|
|
cmd.Flags().StringVar(&setName, "set", "", "Set default account to this name")
|
|
|
|
return cmd
|
|
}
|
|
|
|
func accountsShowCmd() *cobra.Command {
|
|
return &cobra.Command{
|
|
Use: "show <name>",
|
|
Short: "Show account details",
|
|
Long: `Display details for a specific account profile.`,
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
accountName := args[0]
|
|
|
|
store, err := accounts.NewAccountsStore()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create accounts store: %w", err)
|
|
}
|
|
|
|
acct, err := store.GetAccount(accountName)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get account: %w", err)
|
|
}
|
|
|
|
fmt.Printf("Name: %s\n", acct.Name)
|
|
fmt.Printf("Email: %s\n", acct.Email)
|
|
fmt.Printf("UID: %s\n", acct.UID)
|
|
fmt.Printf("API Base: %s\n", acct.APIBaseURL)
|
|
fmt.Printf("Default: %t\n", acct.Default)
|
|
fmt.Printf("Created: %s\n", acct.CreatedAt)
|
|
if acct.LastUsedAt != "" {
|
|
fmt.Printf("Last Used: %s\n", acct.LastUsedAt)
|
|
}
|
|
|
|
return nil
|
|
},
|
|
}
|
|
}
|