github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/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: ¶ms.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 }