Skip to content

Commit

Permalink
workspace management (continued)
Browse files Browse the repository at this point in the history
  • Loading branch information
rusq committed Nov 1, 2022
1 parent f9717e8 commit 215629e
Show file tree
Hide file tree
Showing 10 changed files with 307 additions and 38 deletions.
12 changes: 8 additions & 4 deletions cmd/slackdump/internal/golang/base/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,20 @@ under certain conditions. Read LICENSE for more information.
var exitStatus = SNoError
var exitMu sync.Mutex

func SetExitStatus(n int) {
func SetExitStatus(n StatusCode) {
exitMu.Lock()
if exitStatus < n {
exitStatus = n
}
exitMu.Unlock()
}

func SetExitStatusMsg(status int, message any) {
fmt.Fprintln(os.Stderr, message)
func SetExitStatusMsg(status StatusCode, message any) {
if status == SNoError {
fmt.Fprintln(os.Stderr, message)
} else {
fmt.Fprintf(os.Stderr, "ERR-%03[1]d (%[1]s): %[2]s\n", status, message)
}
SetExitStatus(status)
}

Expand All @@ -102,7 +106,7 @@ func Exit() {
for _, f := range atExitFuncs {
f()
}
os.Exit(exitStatus)
os.Exit(int(exitStatus))
}

// Runnable reports whether the command can be run; otherwise
Expand Down
8 changes: 7 additions & 1 deletion cmd/slackdump/internal/golang/base/status.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package base

// StatusCode is the code returned to the OS.
//
//go:generate stringer -type StatusCode -trimprefix S
type StatusCode uint8

// Status codes returned by the main executable.
const (
SNoError = iota
SNoError StatusCode = iota
SGenericError
SInvalidParameters
SHelpRequested
SAuthError
SApplicationError
SWorkspaceError
SCacheError
SUserError
)
31 changes: 31 additions & 0 deletions cmd/slackdump/internal/golang/base/statuscode_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 16 additions & 8 deletions cmd/slackdump/internal/workspace/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,10 @@ New allows you to authenticate in an existing Slack Workspace.
}

func runWspNew(ctx context.Context, cmd *base.Command, args []string) {
if cfg.Workspace == "" {
if args[0] == "" {
base.SetExitStatusMsg(base.SInvalidParameters, "workspace name must be specified")
return
}
cfg.Workspace = args[0]
wsp, err := argsWorkspace(args)
if err != nil {
base.SetExitStatusMsg(base.SInvalidParameters, err.Error())
return
}

m, err := appauth.NewManager(cfg.CacheDir())
Expand All @@ -38,10 +36,20 @@ func runWspNew(ctx context.Context, cmd *base.Command, args []string) {
Token: cfg.SlackToken,
Cookie: cfg.SlackCookie,
}
prov, err := m.Auth(ctx, cfg.Workspace, creds)
prov, err := m.Auth(ctx, wsp, creds)
if err != nil {
base.SetExitStatusMsg(base.SAuthError, err)
return
}
fmt.Printf("Success: added workspace %q of type %q\n", cfg.Workspace, prov.Type())
fmt.Printf("Success: added workspace %q of type %q\n", wsp, prov.Type())
}

func argsWorkspace(args []string) (string, error) {
if cfg.Workspace != "" {
return cfg.Workspace, nil
}
if len(args) > 0 && args[0] != "" {
return args[0], nil
}
return "", appauth.ErrNameRequired
}
116 changes: 116 additions & 0 deletions cmd/slackdump/internal/workspace/del.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package workspace

import (
"context"
"fmt"
"strings"

"github.com/rusq/slackdump/v2/cmd/slackdump/internal/cfg"
"github.com/rusq/slackdump/v2/cmd/slackdump/internal/golang/base"
"github.com/rusq/slackdump/v2/internal/app/appauth"
)

var CmdWspDel = &base.Command{
UsageLine: "slackdump workspace del [flags]",
Short: "deletes the saved workspace login information",
Long: `
Del can be used to delete the Slack Workspace login information (forgets the
workspace).
If the workspace login information is deleted, you will need to re-authorize
in that Slack Workspace by running "slackdump workspace new <name>".
`,
CustomFlags: false,
FlagMask: cfg.OmitAll,
PrintFlags: true,
}

func init() {
CmdWspDel.Run = runWspDel
}

var (
delAll = CmdWspDel.Flag.Bool("a", false, "delete all workspaces")
delConfirm = CmdWspDel.Flag.Bool("y", false, "answer yes to all questions")
)

func runWspDel(ctx context.Context, cmd *base.Command, args []string) {
if *delAll {
delAllWsp()
} else {
delOneWsp(args)
}
}

func delAllWsp() {
m, err := appauth.NewManager(cfg.CacheDir())
if err != nil {
base.SetExitStatusMsg(base.SCacheError, err.Error())
return
}

workspaces, err := m.List()
if err != nil {
base.SetExitStatusMsg(base.SApplicationError, err.Error())
}

if !*delConfirm && !yesno("This will delete ALL workspaces") {
base.SetExitStatusMsg(base.SNoError, "operation cancelled")
return
}
for _, name := range workspaces {
if err := m.Delete(name); err != nil {
base.SetExitStatusMsg(base.SCacheError, err.Error())
return
}
fmt.Printf("workspace %q deleted\n", name)
}
}

func delOneWsp(args []string) {
wsp, err := argsWorkspace(args)
if err != nil {
base.SetExitStatusMsg(base.SInvalidParameters, err.Error())
return
}

m, err := appauth.NewManager(cfg.CacheDir())
if err != nil {
base.SetExitStatusMsg(base.SCacheError, err.Error())
return
}

if !m.Exists(wsp) {
base.SetExitStatusMsg(base.SUserError, "workspace does not exist")
return
}

if !*delConfirm && !yesno(fmt.Sprintf("workspace %q is about to be deleted", wsp)) {
base.SetExitStatusMsg(base.SNoError, "operation cancelled")
return
}

if err := m.Delete(wsp); err != nil {
base.SetExitStatusMsg(base.SApplicationError, err.Error())
return
}
fmt.Printf("workspace %q deleted\n", wsp)
}

func yesno(message string) bool {
for {
fmt.Print(message, "? (y/N) ")
var resp string
fmt.Scanln(&resp)
resp = strings.TrimSpace(resp)
if len(resp) > 0 {
switch strings.ToLower(resp)[0] {
case 'y':
return true
case 'n':
return false
}
}
fmt.Println("Please answer yes or no and press Enter or Return.")
}
}
82 changes: 76 additions & 6 deletions cmd/slackdump/internal/workspace/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,19 @@ package workspace

import (
"context"
"errors"
"fmt"
"os"
"runtime/trace"
"text/tabwriter"

"github.com/slack-go/slack"

"github.com/rusq/slackdump/v2"
"github.com/rusq/slackdump/v2/cmd/slackdump/internal/cfg"
"github.com/rusq/slackdump/v2/cmd/slackdump/internal/golang/base"
"github.com/rusq/slackdump/v2/internal/app/appauth"
"github.com/rusq/slackdump/v2/logger"
)

var CmdWspList = &base.Command{
Expand All @@ -19,8 +27,11 @@ List allows to list Slack Workspaces, that you have previously authenticated in.
PrintFlags: true,
}

const timeLayout = "2006-01-02 15:04:05"

var (
bare = CmdWspList.Flag.Bool("b", false, "bare output format (just names)")
all = CmdWspList.Flag.Bool("a", false, "all information, including user")
)

func init() {
Expand All @@ -37,27 +48,83 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
formatter := printFull
if *bare {
formatter = printBare
} else if *all {
formatter = printAll
}

entries, err := m.List()
if err != nil {
base.SetExitStatusMsg(base.SCacheError, err)
if errors.Is(err, appauth.ErrNoWorkspaces) {
base.SetExitStatusMsg(base.SUserError, "no authenticated workspaces, please run \"slackdump workspace new\"")
} else {
base.SetExitStatusMsg(base.SCacheError, err)
}
return
}
current, err := m.Current()
if err != nil {
base.SetExitStatusMsg(base.SWorkspaceError, fmt.Sprintf("error getting the current workspace: %s", err))
return
if !errors.Is(err, appauth.ErrNoDefault) {
base.SetExitStatusMsg(base.SWorkspaceError, fmt.Sprintf("error getting the current workspace: %s", err))
return
}
current = entries[0]
if err := m.Select(current); err != nil {
base.SetExitStatusMsg(base.SWorkspaceError, fmt.Sprintf("error setting the current workspace: %s", err))
return
}

}

formatter(m, current, entries)
}

const defMark = "=>"

func printAll(m *appauth.Manager, current string, wsps []string) {
ctx, task := trace.NewTask(context.Background(), "printAll")
defer task.End()

tw := tabwriter.NewWriter(os.Stdout, 2, 8, 1, ' ', 0)
defer tw.Flush()

fmt.Fprintln(tw,
"C\tname\tfilename\tmodified\tteam\tuser\terror\n"+
"-\t-------\t------------\t-------------------\t---------\t--------\t-----")
cfg.SlackOptions.Logger = logger.Silent
cfg.SlackOptions.NoUserCache = true
for _, name := range wsps {
curr := ""
if current == name {
curr = "*"
}
fi, err := m.FileInfo(name)
if err != nil {
fmt.Fprintf(tw, "%s\t%s\t\t\t\t\t%s\n", curr, name, err)
continue
}
info, err := userInfo(ctx, m, name)
if err != nil {
fmt.Fprintf(tw, "%s\t%s\t%s\t%s\t\t\t%s\n", curr, name, fi.Name(), fi.ModTime().Format(timeLayout), err)
continue
}
fmt.Fprintf(tw, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", curr, name, fi.Name(), fi.ModTime().Format(timeLayout), info.Team, info.User, "OK")
}
}

func userInfo(ctx context.Context, m *appauth.Manager, name string) (*slack.AuthTestResponse, error) {
prov, err := m.Auth(ctx, name, appauth.SlackCreds{})
if err != nil {
return nil, err
}
sess, err := slackdump.NewWithOptions(ctx, prov, cfg.SlackOptions)
if err != nil {
return nil, err
}
return sess.Client().AuthTest()
}

func printFull(m *appauth.Manager, current string, wsps []string) {
fmt.Printf("Workspaces in %q:\n\n", cfg.CacheDir())

for _, name := range wsps {
fmt.Println("\t" + formatWsp(m, current, name))
}
Expand All @@ -68,7 +135,7 @@ func formatWsp(m *appauth.Manager, current string, name string) string {
timestamp := "unknown"
filename := "-"
if fi, err := m.FileInfo(name); err == nil {
timestamp = fi.ModTime().Format("2006-01-02 15:04:05")
timestamp = fi.ModTime().Format(timeLayout)
filename = fi.Name()
}
if name == current {
Expand All @@ -80,8 +147,11 @@ func formatWsp(m *appauth.Manager, current string, name string) string {
return fmt.Sprintf("%s (file: %s, last modified: %s)", name, filename, timestamp)
}

func printBare(_ *appauth.Manager, _ string, workspaces []string) {
func printBare(_ *appauth.Manager, current string, workspaces []string) {
for _, name := range workspaces {
if current == name {
fmt.Print("*")
}
fmt.Println(name)
}
}
3 changes: 0 additions & 3 deletions cmd/slackdump/internal/workspace/reset.go

This file was deleted.

1 change: 1 addition & 0 deletions cmd/slackdump/internal/workspace/workspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,6 @@ Workspaces are stored in cache directory on this device:
CmdWspNew,
CmdWspList,
CmdWspSelect,
CmdWspDel,
},
}
Loading

0 comments on commit 215629e

Please sign in to comment.