From 253d2e9782284c7050805da736385c197b9ba034 Mon Sep 17 00:00:00 2001 From: Rob Loranger Date: Fri, 13 Sep 2019 12:32:14 -0700 Subject: [PATCH 1/3] add accounts command in wf this adds a new sub command accounts, which will list all currently authenticated user accounts grouped by hostname --- cmd/wf/commands.go | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ cmd/wf/main.go | 10 +++++++ go.mod | 1 + go.sum | 4 +++ 4 files changed, 93 insertions(+) diff --git a/cmd/wf/commands.go b/cmd/wf/commands.go index 1a9e6c4..b3cb57f 100644 --- a/cmd/wf/commands.go +++ b/cmd/wf/commands.go @@ -2,10 +2,13 @@ package main import ( "fmt" + "io/ioutil" "os" "path/filepath" "strings" + "text/tabwriter" + "github.com/hashicorp/go-multierror" "github.com/writeas/writeas-cli/api" "github.com/writeas/writeas-cli/commands" "github.com/writeas/writeas-cli/config" @@ -196,3 +199,78 @@ func cmdLogOut(c *cli.Context) error { return nil } + +func cmdAccounts(c *cli.Context) error { + // get user config dir + userDir := config.UserDataDir(c.App.ExtraInfo()["configDir"]) + // load defaults + cfg, err := config.LoadConfig(userDir) + if err != nil { + return cli.NewExitError("Could not load default user configuration", 1) + } + defaultUser := cfg.Default.User + defaultHost := cfg.Default.Host + if parts := strings.Split(defaultHost, "://"); len(parts) > 1 { + defaultHost = parts[1] + } + // get each host dir + files, err := ioutil.ReadDir(userDir) + if err != nil { + return cli.NewExitError("Could not read user configuration directory", 1) + } + // accounts will be a slice of slices of string. the first string in + // a subslice should always be the hostname + accounts := [][]string{} + for _, file := range files { + if file.IsDir() { + dirName := file.Name() + // get each user in host dir + users, err := usersFromDir(filepath.Join(userDir, dirName)) + if err != nil { + log.Info(c, "Failed to get users from %s: %v", dirName, err) + continue + } + if len(users) != 0 { + // append the slice of users as a new slice in accounts w/ the host prepended + accounts = append(accounts, append([]string{dirName}, users...)) + } + } + } + + // print out all logged in accounts + tw := tabwriter.NewWriter(os.Stdout, 10, 2, 2, ' ', tabwriter.TabIndent) + if len(accounts) == 0 { + fmt.Fprintf(tw, "%s\t", "No authenticated accounts found.") + } + for _, userList := range accounts { + host := userList[0] + for _, username := range userList[1:] { + if host == defaultHost && username == defaultUser { + fmt.Fprintf(tw, "[%s]\t%s (default)\n", host, username) + continue + } + fmt.Fprintf(tw, "[%s]\t%s\n", host, username) + } + } + return tw.Flush() +} + +func usersFromDir(path string) ([]string, error) { + users := make([]string, 0, 4) + files, err := ioutil.ReadDir(path) + if err != nil { + return nil, err + } + var errs error + for _, file := range files { + if file.IsDir() { + _, err := os.Stat(filepath.Join(path, file.Name(), "user.json")) + if err != nil { + err = multierror.Append(errs, err) + continue + } + users = append(users, file.Name()) + } + } + return users, errs +} diff --git a/cmd/wf/main.go b/cmd/wf/main.go index 7cce4c9..ac726cf 100644 --- a/cmd/wf/main.go +++ b/cmd/wf/main.go @@ -207,6 +207,16 @@ func main() { }, }, }, { + Name: "accounts", + Usage: "List all currently logged in accounts", + Action: cmdAccounts, + Flags: []cli.Flag{ + cli.BoolFlag{ + Name: "verbose, v", + Usage: "Make the operation more talkative", + }, + }, + }, { Name: "auth", Usage: "Authenticate with a WriteFreely instance", Action: cmdAuth, diff --git a/go.mod b/go.mod index 90d8f91..f03be5d 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ require ( github.com/atotto/clipboard v0.1.1 github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e // indirect + github.com/hashicorp/go-multierror v1.0.0 github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c github.com/jtolds/gls v4.2.1+incompatible // indirect github.com/microcosm-cc/bluemonday v1.0.1 // indirect diff --git a/go.sum b/go.sum index 86825a8..449244e 100644 --- a/go.sum +++ b/go.sum @@ -12,6 +12,10 @@ github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg= github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c h1:kQWxfPIHVLbgLzphqk3QUflDy9QdksZR4ygR807bpy0= github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= From 139a14154b44cc02e35fc3f527dd65bf553425d8 Mon Sep 17 00:00:00 2001 From: Rob Loranger Date: Fri, 13 Sep 2019 12:32:14 -0700 Subject: [PATCH 2/3] add accounts command in wf this adds a new sub command accounts, which will list all currently authenticated user accounts grouped by hostname --- cmd/wf/commands.go | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ cmd/wf/main.go | 10 +++++++ go.mod | 1 + go.sum | 4 +++ 4 files changed, 93 insertions(+) diff --git a/cmd/wf/commands.go b/cmd/wf/commands.go index 1a9e6c4..b3cb57f 100644 --- a/cmd/wf/commands.go +++ b/cmd/wf/commands.go @@ -2,10 +2,13 @@ package main import ( "fmt" + "io/ioutil" "os" "path/filepath" "strings" + "text/tabwriter" + "github.com/hashicorp/go-multierror" "github.com/writeas/writeas-cli/api" "github.com/writeas/writeas-cli/commands" "github.com/writeas/writeas-cli/config" @@ -196,3 +199,78 @@ func cmdLogOut(c *cli.Context) error { return nil } + +func cmdAccounts(c *cli.Context) error { + // get user config dir + userDir := config.UserDataDir(c.App.ExtraInfo()["configDir"]) + // load defaults + cfg, err := config.LoadConfig(userDir) + if err != nil { + return cli.NewExitError("Could not load default user configuration", 1) + } + defaultUser := cfg.Default.User + defaultHost := cfg.Default.Host + if parts := strings.Split(defaultHost, "://"); len(parts) > 1 { + defaultHost = parts[1] + } + // get each host dir + files, err := ioutil.ReadDir(userDir) + if err != nil { + return cli.NewExitError("Could not read user configuration directory", 1) + } + // accounts will be a slice of slices of string. the first string in + // a subslice should always be the hostname + accounts := [][]string{} + for _, file := range files { + if file.IsDir() { + dirName := file.Name() + // get each user in host dir + users, err := usersFromDir(filepath.Join(userDir, dirName)) + if err != nil { + log.Info(c, "Failed to get users from %s: %v", dirName, err) + continue + } + if len(users) != 0 { + // append the slice of users as a new slice in accounts w/ the host prepended + accounts = append(accounts, append([]string{dirName}, users...)) + } + } + } + + // print out all logged in accounts + tw := tabwriter.NewWriter(os.Stdout, 10, 2, 2, ' ', tabwriter.TabIndent) + if len(accounts) == 0 { + fmt.Fprintf(tw, "%s\t", "No authenticated accounts found.") + } + for _, userList := range accounts { + host := userList[0] + for _, username := range userList[1:] { + if host == defaultHost && username == defaultUser { + fmt.Fprintf(tw, "[%s]\t%s (default)\n", host, username) + continue + } + fmt.Fprintf(tw, "[%s]\t%s\n", host, username) + } + } + return tw.Flush() +} + +func usersFromDir(path string) ([]string, error) { + users := make([]string, 0, 4) + files, err := ioutil.ReadDir(path) + if err != nil { + return nil, err + } + var errs error + for _, file := range files { + if file.IsDir() { + _, err := os.Stat(filepath.Join(path, file.Name(), "user.json")) + if err != nil { + err = multierror.Append(errs, err) + continue + } + users = append(users, file.Name()) + } + } + return users, errs +} diff --git a/cmd/wf/main.go b/cmd/wf/main.go index ef9d8f7..5729d44 100644 --- a/cmd/wf/main.go +++ b/cmd/wf/main.go @@ -207,6 +207,16 @@ func main() { }, }, }, { + Name: "accounts", + Usage: "List all currently logged in accounts", + Action: cmdAccounts, + Flags: []cli.Flag{ + cli.BoolFlag{ + Name: "verbose, v", + Usage: "Make the operation more talkative", + }, + }, + }, { Name: "auth", Usage: "Authenticate with a WriteFreely instance", Action: cmdAuth, diff --git a/go.mod b/go.mod index 90d8f91..f03be5d 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ require ( github.com/atotto/clipboard v0.1.1 github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e // indirect + github.com/hashicorp/go-multierror v1.0.0 github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c github.com/jtolds/gls v4.2.1+incompatible // indirect github.com/microcosm-cc/bluemonday v1.0.1 // indirect diff --git a/go.sum b/go.sum index 86825a8..449244e 100644 --- a/go.sum +++ b/go.sum @@ -12,6 +12,10 @@ github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg= github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c h1:kQWxfPIHVLbgLzphqk3QUflDy9QdksZR4ygR807bpy0= github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= From c9f20e27f7110451d7ae93959a201f144ab20c38 Mon Sep 17 00:00:00 2001 From: Matt Baer Date: Fri, 20 Sep 2019 13:57:59 -0400 Subject: [PATCH 3/3] Have `accounts` print nothing when unauth'd This replicates behavior elsewhere, where we don't output anything if there is no information to show. Instead, the "no accounts" message will only show if the user supplies a -v / --verbose flag. --- cmd/wf/commands.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/wf/commands.go b/cmd/wf/commands.go index b3cb57f..c55157c 100644 --- a/cmd/wf/commands.go +++ b/cmd/wf/commands.go @@ -239,8 +239,8 @@ func cmdAccounts(c *cli.Context) error { // print out all logged in accounts tw := tabwriter.NewWriter(os.Stdout, 10, 2, 2, ' ', tabwriter.TabIndent) - if len(accounts) == 0 { - fmt.Fprintf(tw, "%s\t", "No authenticated accounts found.") + if len(accounts) == 0 && (c.Bool("v") || c.Bool("verbose") || c.GlobalBool("v") || c.GlobalBool("verbose")) { + fmt.Fprintf(tw, "%s\t", "No authenticated accounts found.\n") } for _, userList := range accounts { host := userList[0]