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  }