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