github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/cmd/juju/user/logout.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package user 5 6 import ( 7 "github.com/juju/cmd" 8 "github.com/juju/errors" 9 "github.com/juju/gnuflag" 10 11 "github.com/juju/juju/cmd/modelcmd" 12 "github.com/juju/juju/jujuclient" 13 ) 14 15 const logoutDoc = ` 16 If another client has logged in as the same user, they will remain logged 17 in. This command only affects the local client. 18 19 The command will fail if the user has not yet set a password 20 (` + "`juju change-user-password`" + `). This scenario is only possible after 21 ` + "`juju bootstrap`" + `since ` + "`juju register`" + ` sets a password. The 22 failing behaviour can be overridden with the '--force' option. 23 24 If the same user is logged in with another client system, that user session 25 will not be affected by this command; it only affects the local client. 26 27 By default, the controller is the current controller. 28 29 Examples: 30 juju logout 31 32 See also: 33 change-user-password 34 login 35 36 ` 37 38 // NewLogoutCommand returns a new cmd.Command to handle "juju logout". 39 func NewLogoutCommand() cmd.Command { 40 return modelcmd.WrapController(&logoutCommand{}) 41 } 42 43 // logoutCommand changes the password for a user. 44 type logoutCommand struct { 45 modelcmd.ControllerCommandBase 46 Force bool 47 } 48 49 // Info implements Command.Info. 50 func (c *logoutCommand) Info() *cmd.Info { 51 return &cmd.Info{ 52 Name: "logout", 53 Purpose: "Logs a Juju user out of a controller.", 54 Doc: logoutDoc, 55 } 56 } 57 58 // Init implements Command.Init. 59 func (c *logoutCommand) Init(args []string) error { 60 return cmd.CheckEmpty(args) 61 } 62 63 // SetFlags implements Command.SetFlags. 64 func (c *logoutCommand) SetFlags(f *gnuflag.FlagSet) { 65 c.ControllerCommandBase.SetFlags(f) 66 f.BoolVar(&c.Force, "force", false, "Force logout when a locally recorded password is detected") 67 } 68 69 // Run implements Command.Run. 70 func (c *logoutCommand) Run(ctx *cmd.Context) error { 71 controllerName := c.ControllerName() 72 store := c.ClientStore() 73 if err := c.logout(store, controllerName); err != nil { 74 return errors.Trace(err) 75 } 76 77 // Count the number of logged-into controllers to inform the user. 78 var loggedInCount int 79 controllers, err := store.AllControllers() 80 if err != nil { 81 return errors.Trace(err) 82 } 83 for name := range controllers { 84 if name == controllerName { 85 continue 86 } 87 _, err := store.AccountDetails(name) 88 if errors.IsNotFound(err) { 89 continue 90 } else if err != nil { 91 return errors.Trace(err) 92 } 93 loggedInCount++ 94 } 95 switch loggedInCount { 96 case 0: 97 ctx.Infof("Logged out. You are no longer logged into any controllers.") 98 case 1: 99 ctx.Infof("Logged out. You are still logged into 1 controller.") 100 default: 101 ctx.Infof("Logged out. You are still logged into %d controllers.", loggedInCount) 102 } 103 return nil 104 } 105 106 func (c *logoutCommand) logout(store jujuclient.ClientStore, controllerName string) error { 107 accountDetails, err := store.AccountDetails(controllerName) 108 if errors.IsNotFound(err) { 109 // Not logged in; nothing else to do. 110 return nil 111 } else if err != nil { 112 return errors.Trace(err) 113 } 114 115 // We first ensure that the user has a macaroon, which implies 116 // they know their password. If they have just bootstrapped, 117 // they will have a randomly generated password which they will 118 // be unaware of. 119 if accountDetails.Password != "" && !c.Force { 120 return errors.New(`preventing account loss 121 122 It appears that you have not changed the password for 123 your account. If this is the case, change the password 124 first before logging out, so that you can log in again 125 afterwards. To change your password, run the command 126 "juju change-user-password". 127 128 If you are sure you want to log out, and it is safe to 129 clear the credentials from the client, then you can run 130 this command again with the "--force" flag. 131 `) 132 } 133 134 // Remove the account credentials. 135 if err := store.RemoveAccount(controllerName); err != nil { 136 return errors.Annotate(err, "failed to clear credentials") 137 } 138 return nil 139 }