github.com/keybase/client/go@v0.0.0-20240520164431-4f512a4c85a3/client/cmd_account_lockdown.go (about)

     1  // Copyright 2018 Keybase, Inc. All rights reserved. Use of
     2  // this source code is governed by the included BSD license.
     3  
     4  package client
     5  
     6  import (
     7  	"errors"
     8  	"fmt"
     9  	"text/tabwriter"
    10  
    11  	"golang.org/x/net/context"
    12  
    13  	"github.com/keybase/cli"
    14  	"github.com/keybase/client/go/libcmdline"
    15  	"github.com/keybase/client/go/libkb"
    16  	keybase1 "github.com/keybase/client/go/protocol/keybase1"
    17  )
    18  
    19  type CmdAccountLockdown struct {
    20  	libkb.Contextified
    21  	SetLockdownMode *bool
    22  	History         bool
    23  	Force           bool
    24  }
    25  
    26  func NewCmdAccountLockdown(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Command {
    27  	cmd := &CmdAccountLockdown{
    28  		Contextified: libkb.NewContextified(g),
    29  	}
    30  	flags := []cli.Flag{
    31  		cli.BoolFlag{
    32  			Name:  "enable",
    33  			Usage: "Enable account lockdown mode.",
    34  		},
    35  		cli.BoolFlag{
    36  			Name:  "disable",
    37  			Usage: "Disable account lockdown mode.",
    38  		},
    39  		cli.BoolFlag{
    40  			Name:  "history",
    41  			Usage: "Print history of lockdown mode changes.",
    42  		},
    43  		cli.BoolFlag{
    44  			Name:  "force, f",
    45  			Usage: "Don't prompt.",
    46  		},
    47  	}
    48  	return cli.Command{
    49  		Name:  "lockdown",
    50  		Usage: "Manage account lockdown mode",
    51  		Flags: flags,
    52  		Action: func(c *cli.Context) {
    53  			cl.ChooseCommand(cmd, "lockdown", c)
    54  		},
    55  		Description: `When lockdown mode is enabled for an account, some operations are
    56     blocked for website sessions, including (but not limited to):
    57         - account delete or reset,
    58         - posting signatures,
    59         - changing password or email address,
    60         - changing profile information or profile picture.
    61  
    62     These actions are still possible using the Keybase client.`,
    63  	}
    64  }
    65  
    66  func (c *CmdAccountLockdown) ParseArgv(ctx *cli.Context) error {
    67  	if len(ctx.Args()) > 0 {
    68  		args0 := ctx.Args()[0]
    69  		if args0 == "enable" || args0 == "disable" {
    70  			return fmt.Errorf("did you mean: keybase account lockdown --%s", args0)
    71  		}
    72  		return errors.New("this command does not take any positional arguments, only flags")
    73  	}
    74  
    75  	enable := ctx.Bool("enable")
    76  	disable := ctx.Bool("disable")
    77  	if enable && disable {
    78  		return errors.New("Both --enable and --disable flags are passed which is invalid")
    79  	} else if enable {
    80  		val := true
    81  		c.SetLockdownMode = &val
    82  	} else if disable {
    83  		val := false
    84  		c.SetLockdownMode = &val
    85  	}
    86  
    87  	c.History = ctx.Bool("history")
    88  	c.Force = ctx.Bool("force")
    89  	return nil
    90  }
    91  
    92  func (c *CmdAccountLockdown) Run() error {
    93  	cli, err := GetAccountClient(c.G())
    94  	if err != nil {
    95  		return err
    96  	}
    97  
    98  	tui := c.G().UI.GetTerminalUI()
    99  
   100  	enabledGreen := func() string { return ColorString(c.G(), "green", "enabled") }
   101  	disabledYellow := func() string { return ColorString(c.G(), "yellow", "disabled") }
   102  
   103  	if c.SetLockdownMode != nil {
   104  		res, err := cli.GetLockdownMode(context.Background(), 0)
   105  		if err != nil {
   106  			return err
   107  		}
   108  
   109  		if res.Status == *c.SetLockdownMode {
   110  			if res.Status {
   111  				_, _ = tui.PrintfUnescaped("Lockdown mode is already %s. Nothing to do.\n", enabledGreen())
   112  			} else {
   113  				_, _ = tui.PrintfUnescaped("Lockdown mode is already %s. Nothing to do.\n", disabledYellow())
   114  			}
   115  			return nil
   116  		}
   117  
   118  		if !c.Force {
   119  			var prompt string
   120  			if *c.SetLockdownMode {
   121  				prompt = fmt.Sprintf("Do you want to %s lockdown mode?", ColorString(c.G(), "green", "ENABLE"))
   122  			} else {
   123  				prompt = fmt.Sprintf("Do you want to %s lockdown mode?", ColorString(c.G(), "red", "DISABLE"))
   124  			}
   125  
   126  			ok, err := tui.PromptYesNo(PromptDescriptorChangeLockdownMode, prompt, libkb.PromptDefaultNo)
   127  			if err != nil {
   128  				return err
   129  			}
   130  			if !ok {
   131  				c.G().Log.CDebugf(context.TODO(), "CmdAccountLockdown: user aborted via prompt")
   132  				return NotConfirmedError{}
   133  			}
   134  		}
   135  
   136  		err = cli.SetLockdownMode(context.Background(), keybase1.SetLockdownModeArg{
   137  			Enabled: *c.SetLockdownMode,
   138  		})
   139  		if err != nil {
   140  			return err
   141  		}
   142  	} else {
   143  		fmt.Fprintf(tui.ErrorWriter(), "Learn more about lockdown mode: `%s`\n", ColorString(c.G(), "bold", "keybase account lockdown -h"))
   144  	}
   145  
   146  	res, err := cli.GetLockdownMode(context.Background(), 0)
   147  	if err != nil {
   148  		return err
   149  	}
   150  	tui.Printf("Lockdown mode is: ")
   151  	if res.Status {
   152  		_, _ = tui.PrintfUnescaped("%s\n", enabledGreen())
   153  	} else {
   154  		_, _ = tui.PrintfUnescaped("%s\n", disabledYellow())
   155  	}
   156  
   157  	if c.History {
   158  		tabw := new(tabwriter.Writer)
   159  		tabw.Init(tui.OutputWriter(), 0, 8, 4, ' ', 0)
   160  		fmt.Fprintf(tabw, "Changed to:\tChange time:\tDevice:\n")
   161  		for _, v := range res.History {
   162  			var status string
   163  			if v.Status {
   164  				status = "enabled"
   165  			} else {
   166  				status = "disabled"
   167  			}
   168  			fmt.Fprintf(tabw, "%s\t%s\t%s (%s)\n", status, keybase1.FormatTime(v.CreationTime), v.DeviceName, v.DeviceID)
   169  		}
   170  		tabw.Flush()
   171  	}
   172  
   173  	return nil
   174  }
   175  
   176  func (c *CmdAccountLockdown) GetUsage() libkb.Usage {
   177  	return libkb.Usage{
   178  		API:       true,
   179  		KbKeyring: true,
   180  		Config:    true,
   181  	}
   182  }