github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/juju/user/info.go (about) 1 // Copyright 2012-2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for infos. 3 4 package user 5 6 import ( 7 "github.com/juju/clock" 8 "github.com/juju/cmd" 9 "github.com/juju/errors" 10 "github.com/juju/gnuflag" 11 "gopkg.in/juju/names.v2" 12 13 "github.com/juju/juju/api/usermanager" 14 "github.com/juju/juju/apiserver/params" 15 jujucmd "github.com/juju/juju/cmd" 16 "github.com/juju/juju/cmd/juju/common" 17 "github.com/juju/juju/cmd/modelcmd" 18 "github.com/juju/juju/cmd/output" 19 ) 20 21 var helpSummary = ` 22 Show information about a user.`[1:] 23 24 var helpDetails = ` 25 By default, the YAML format is used and the user name is the current 26 user. 27 28 29 Examples: 30 juju show-user 31 juju show-user jsmith 32 juju show-user --format json 33 juju show-user --format yaml 34 35 See also: 36 add-user 37 register 38 users`[1:] 39 40 // UserInfoAPI defines the API methods that the info command uses. 41 type UserInfoAPI interface { 42 UserInfo([]string, usermanager.IncludeDisabled) ([]params.UserInfo, error) 43 Close() error 44 } 45 46 // infoCommandBase is a common base for 'juju show-user' and 'juju users'. 47 type infoCommandBase struct { 48 modelcmd.ControllerCommandBase 49 api UserInfoAPI 50 clock clock.Clock 51 exactTime bool 52 out cmd.Output 53 } 54 55 func (c *infoCommandBase) SetFlags(f *gnuflag.FlagSet) { 56 f.BoolVar(&c.exactTime, "exact-time", false, "Use full timestamp for connection times") 57 } 58 59 func NewShowUserCommand() cmd.Command { 60 return modelcmd.WrapController(&infoCommand{ 61 infoCommandBase: infoCommandBase{ 62 clock: clock.WallClock, 63 }, 64 }) 65 } 66 67 // infoCommand retrieves information about a single user. 68 type infoCommand struct { 69 infoCommandBase 70 Username string 71 } 72 73 // UserInfo defines the serialization behaviour of the user information. 74 type UserInfo struct { 75 Username string `yaml:"user-name" json:"user-name"` 76 DisplayName string `yaml:"display-name,omitempty" json:"display-name,omitempty"` 77 Access string `yaml:"access" json:"access"` 78 DateCreated string `yaml:"date-created,omitempty" json:"date-created,omitempty"` 79 LastConnection string `yaml:"last-connection,omitempty" json:"last-connection,omitempty"` 80 Disabled bool `yaml:"disabled,omitempty" json:"disabled,omitempty"` 81 } 82 83 // Info implements Command.Info. 84 func (c *infoCommand) Info() *cmd.Info { 85 return jujucmd.Info(&cmd.Info{ 86 Name: "show-user", 87 Args: "[<user name>]", 88 Purpose: helpSummary, 89 Doc: helpDetails, 90 }) 91 } 92 93 // SetFlags implements Command.SetFlags. 94 func (c *infoCommand) SetFlags(f *gnuflag.FlagSet) { 95 c.infoCommandBase.SetFlags(f) 96 c.out.AddFlags(f, "yaml", output.DefaultFormatters) 97 } 98 99 // Init implements Command.Init. 100 func (c *infoCommand) Init(args []string) (err error) { 101 c.Username, err = cmd.ZeroOrOneArgs(args) 102 return err 103 } 104 105 func (c *infoCommandBase) getUserInfoAPI() (UserInfoAPI, error) { 106 if c.api != nil { 107 return c.api, nil 108 } 109 return c.NewUserManagerAPIClient() 110 } 111 112 // Run implements Command.Run. 113 func (c *infoCommand) Run(ctx *cmd.Context) (err error) { 114 client, err := c.getUserInfoAPI() 115 if err != nil { 116 return err 117 } 118 defer client.Close() 119 username := c.Username 120 if username == "" { 121 accountDetails, err := c.CurrentAccountDetails() 122 if err != nil { 123 return err 124 } 125 username = accountDetails.User 126 } 127 result, err := client.UserInfo([]string{username}, false) 128 if err != nil { 129 return err 130 } 131 // Don't output the params type, be explicit. We convert before checking 132 // length because we want to reuse the conversion function, and we are 133 // pretty sure that there is one value there. 134 output := c.apiUsersToUserInfoSlice(result) 135 if len(output) != 1 { 136 return errors.Errorf("expected 1 result, got %d", len(output)) 137 } 138 return c.out.Write(ctx, output[0]) 139 } 140 141 func (c *infoCommandBase) apiUsersToUserInfoSlice(users []params.UserInfo) []UserInfo { 142 var output []UserInfo 143 var now = c.clock.Now() 144 for _, info := range users { 145 outInfo := UserInfo{ 146 Username: info.Username, 147 DisplayName: info.DisplayName, 148 Access: info.Access, 149 Disabled: info.Disabled, 150 } 151 // TODO(wallyworld) record login information about external users. 152 if names.NewUserTag(info.Username).IsLocal() { 153 outInfo.LastConnection = common.LastConnection(info.LastConnection, now, c.exactTime) 154 if c.exactTime { 155 outInfo.DateCreated = info.DateCreated.String() 156 } else { 157 outInfo.DateCreated = common.UserFriendlyDuration(info.DateCreated, now) 158 } 159 } 160 output = append(output, outInfo) 161 } 162 163 return output 164 }