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