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