github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/apiserver/usermanager/usermanager.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package usermanager
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/errors"
    10  	"github.com/juju/loggo"
    11  	"github.com/juju/names"
    12  
    13  	"github.com/juju/juju/apiserver/common"
    14  	"github.com/juju/juju/apiserver/params"
    15  	"github.com/juju/juju/state"
    16  )
    17  
    18  var logger = loggo.GetLogger("juju.apiserver.usermanager")
    19  
    20  func init() {
    21  	common.RegisterStandardFacade("UserManager", 0, NewUserManagerAPI)
    22  }
    23  
    24  // UserManager defines the methods on the usermanager API end point.
    25  type UserManager interface {
    26  	AddUser(args params.AddUsers) (params.AddUserResults, error)
    27  	DisableUser(args params.Entities) (params.ErrorResults, error)
    28  	EnableUser(args params.Entities) (params.ErrorResults, error)
    29  	SetPassword(args params.EntityPasswords) (params.ErrorResults, error)
    30  	UserInfo(args params.UserInfoRequest) (params.UserInfoResults, error)
    31  }
    32  
    33  // UserManagerAPI implements the user manager interface and is the concrete
    34  // implementation of the api end point.
    35  type UserManagerAPI struct {
    36  	state      *state.State
    37  	authorizer common.Authorizer
    38  	check      *common.BlockChecker
    39  }
    40  
    41  var _ UserManager = (*UserManagerAPI)(nil)
    42  
    43  func NewUserManagerAPI(
    44  	st *state.State,
    45  	resources *common.Resources,
    46  	authorizer common.Authorizer,
    47  ) (*UserManagerAPI, error) {
    48  	if !authorizer.AuthClient() {
    49  		return nil, common.ErrPerm
    50  	}
    51  
    52  	return &UserManagerAPI{
    53  		state:      st,
    54  		authorizer: authorizer,
    55  		check:      common.NewBlockChecker(st),
    56  	}, nil
    57  }
    58  
    59  func (api *UserManagerAPI) permissionCheck(user names.UserTag) error {
    60  	// TODO(thumper): PERMISSIONS Change this permission check when we have
    61  	// real permissions. For now, only the owner of the initial environment is
    62  	// able to add users.
    63  	initialEnv, err := api.state.StateServerEnvironment()
    64  	if err != nil {
    65  		return errors.Trace(err)
    66  	}
    67  	if user != initialEnv.Owner() {
    68  		return errors.Trace(common.ErrPerm)
    69  	}
    70  	return nil
    71  }
    72  
    73  // AddUser adds a user.
    74  func (api *UserManagerAPI) AddUser(args params.AddUsers) (params.AddUserResults, error) {
    75  	result := params.AddUserResults{
    76  		Results: make([]params.AddUserResult, len(args.Users)),
    77  	}
    78  	if err := api.check.ChangeAllowed(); err != nil {
    79  		return result, errors.Trace(err)
    80  	}
    81  
    82  	if len(args.Users) == 0 {
    83  		return result, nil
    84  	}
    85  	loggedInUser, err := api.getLoggedInUser()
    86  	if err != nil {
    87  		return result, errors.Wrap(err, common.ErrPerm)
    88  	}
    89  	// TODO(thumper): PERMISSIONS Change this permission check when we have
    90  	// real permissions. For now, only the owner of the initial environment is
    91  	// able to add users.
    92  	if err := api.permissionCheck(loggedInUser); err != nil {
    93  		return result, errors.Trace(err)
    94  	}
    95  	for i, arg := range args.Users {
    96  		user, err := api.state.AddUser(arg.Username, arg.DisplayName, arg.Password, loggedInUser.Id())
    97  		if err != nil {
    98  			err = errors.Annotate(err, "failed to create user")
    99  			result.Results[i].Error = common.ServerError(err)
   100  		} else {
   101  			result.Results[i].Tag = user.Tag().String()
   102  		}
   103  	}
   104  	return result, nil
   105  }
   106  
   107  func (api *UserManagerAPI) getUser(tag string) (*state.User, error) {
   108  	userTag, err := names.ParseUserTag(tag)
   109  	if err != nil {
   110  		return nil, errors.Trace(err)
   111  	}
   112  	user, err := api.state.User(userTag)
   113  	if err != nil {
   114  		return nil, errors.Wrap(err, common.ErrPerm)
   115  	}
   116  	return user, nil
   117  }
   118  
   119  // EnableUser enables one or more users.  If the user is already enabled,
   120  // the action is consided a success.
   121  func (api *UserManagerAPI) EnableUser(users params.Entities) (params.ErrorResults, error) {
   122  	if err := api.check.ChangeAllowed(); err != nil {
   123  		return params.ErrorResults{}, errors.Trace(err)
   124  	}
   125  	return api.enableUserImpl(users, "enable", (*state.User).Enable)
   126  }
   127  
   128  // DisableUser disables one or more users.  If the user is already disabled,
   129  // the action is consided a success.
   130  func (api *UserManagerAPI) DisableUser(users params.Entities) (params.ErrorResults, error) {
   131  	if err := api.check.ChangeAllowed(); err != nil {
   132  		return params.ErrorResults{}, errors.Trace(err)
   133  	}
   134  	return api.enableUserImpl(users, "disable", (*state.User).Disable)
   135  }
   136  
   137  func (api *UserManagerAPI) enableUserImpl(args params.Entities, action string, method func(*state.User) error) (params.ErrorResults, error) {
   138  	result := params.ErrorResults{
   139  		Results: make([]params.ErrorResult, len(args.Entities)),
   140  	}
   141  	if len(args.Entities) == 0 {
   142  		return result, nil
   143  	}
   144  	loggedInUser, err := api.getLoggedInUser()
   145  	if err != nil {
   146  		return result, errors.Wrap(err, common.ErrPerm)
   147  	}
   148  	// TODO(thumper): PERMISSIONS Change this permission check when we have
   149  	// real permissions. For now, only the owner of the initial environment is
   150  	// able to add users.
   151  	if err := api.permissionCheck(loggedInUser); err != nil {
   152  		return result, errors.Trace(err)
   153  	}
   154  
   155  	for i, arg := range args.Entities {
   156  		user, err := api.getUser(arg.Tag)
   157  		if err != nil {
   158  			result.Results[i].Error = common.ServerError(err)
   159  			continue
   160  		}
   161  		err = method(user)
   162  		if err != nil {
   163  			result.Results[i].Error = common.ServerError(errors.Errorf("failed to %s user: %s", action, err))
   164  		}
   165  	}
   166  	return result, nil
   167  }
   168  
   169  // UserInfo returns information on a user.
   170  func (api *UserManagerAPI) UserInfo(request params.UserInfoRequest) (params.UserInfoResults, error) {
   171  	var results params.UserInfoResults
   172  	var infoForUser = func(user *state.User) params.UserInfoResult {
   173  		var lastLogin *time.Time
   174  		userLastLogin, err := user.LastLogin()
   175  		if err != nil {
   176  			if !state.IsNeverLoggedInError(err) {
   177  				logger.Debugf("error getting last login: %v", err)
   178  			}
   179  		} else {
   180  			lastLogin = &userLastLogin
   181  		}
   182  		return params.UserInfoResult{
   183  			Result: &params.UserInfo{
   184  				Username:       user.Name(),
   185  				DisplayName:    user.DisplayName(),
   186  				CreatedBy:      user.CreatedBy(),
   187  				DateCreated:    user.DateCreated(),
   188  				LastConnection: lastLogin,
   189  				Disabled:       user.IsDisabled(),
   190  			},
   191  		}
   192  	}
   193  
   194  	argCount := len(request.Entities)
   195  	if argCount == 0 {
   196  		users, err := api.state.AllUsers(request.IncludeDisabled)
   197  		if err != nil {
   198  			return results, errors.Trace(err)
   199  		}
   200  		for _, user := range users {
   201  			results.Results = append(results.Results, infoForUser(user))
   202  		}
   203  		return results, nil
   204  	}
   205  
   206  	results.Results = make([]params.UserInfoResult, argCount)
   207  	for i, arg := range request.Entities {
   208  		user, err := api.getUser(arg.Tag)
   209  		if err != nil {
   210  			results.Results[i].Error = common.ServerError(err)
   211  			continue
   212  		}
   213  		results.Results[i] = infoForUser(user)
   214  	}
   215  
   216  	return results, nil
   217  }
   218  
   219  func (api *UserManagerAPI) setPassword(loggedInUser names.UserTag, arg params.EntityPassword, adminUser bool) error {
   220  	user, err := api.getUser(arg.Tag)
   221  	if err != nil {
   222  		return errors.Trace(err)
   223  	}
   224  	if loggedInUser != user.UserTag() && !adminUser {
   225  		return errors.Trace(common.ErrPerm)
   226  	}
   227  	if arg.Password == "" {
   228  		return errors.New("can not use an empty password")
   229  	}
   230  	err = user.SetPassword(arg.Password)
   231  	if err != nil {
   232  		return errors.Annotate(err, "failed to set password")
   233  	}
   234  	return nil
   235  }
   236  
   237  // SetPassword changes the stored password for the specified users.
   238  func (api *UserManagerAPI) SetPassword(args params.EntityPasswords) (params.ErrorResults, error) {
   239  	if err := api.check.ChangeAllowed(); err != nil {
   240  		return params.ErrorResults{}, errors.Trace(err)
   241  	}
   242  	result := params.ErrorResults{
   243  		Results: make([]params.ErrorResult, len(args.Changes)),
   244  	}
   245  	if len(args.Changes) == 0 {
   246  		return result, nil
   247  	}
   248  	loggedInUser, err := api.getLoggedInUser()
   249  	if err != nil {
   250  		return result, common.ErrPerm
   251  	}
   252  	permErr := api.permissionCheck(loggedInUser)
   253  	adminUser := permErr == nil
   254  	for i, arg := range args.Changes {
   255  		if err := api.setPassword(loggedInUser, arg, adminUser); err != nil {
   256  			result.Results[i].Error = common.ServerError(err)
   257  		}
   258  	}
   259  	return result, nil
   260  }
   261  
   262  func (api *UserManagerAPI) getLoggedInUser() (names.UserTag, error) {
   263  	switch tag := api.authorizer.GetAuthTag().(type) {
   264  	case names.UserTag:
   265  		return tag, nil
   266  	default:
   267  		return names.UserTag{}, errors.New("authorizer not a user")
   268  	}
   269  }