Permalink
Browse files

Merge pull request #6932 from perrito666/admin_cant_grant_foreign_2.1

Fixed model listing for admin user for 2.1.

Admin user needs to see all models when listing,
list models is not the nicest method and does a direct
query to mongo which returns a partial set of models
owned by the calling user.

## QA steps
* Bootstrap juju
* create a user and grant add-model to said user
* login with the user and create a model
* create a second user.
* grant write to the second user on the model owned by the first user.
* all should work.

## Bug reference

https://bugs.launchpad.net/juju/+bug/1650643
  • Loading branch information...
2 parents aacad05 + 4f9399d commit 49316b23b7d1eadbb1119372e02081468ad6ab5a @jujubot jujubot committed Feb 7, 2017
Showing with 27 additions and 3 deletions.
  1. +2 −2 apiserver/modelmanager/modelmanager_test.go
  2. +25 −1 state/modeluser.go
@@ -876,10 +876,10 @@ func (s *modelManagerStateSuite) TestListModelsAdminSelf(c *gc.C) {
func (s *modelManagerStateSuite) TestListModelsAdminListsOther(c *gc.C) {
user := s.AdminUserTag(c)
s.setAPIUser(c, user)
- other := names.NewUserTag("external@remote")
+ other := names.NewUserTag("admin")
result, err := s.modelmanager.ListModels(params.Entity{Tag: other.String()})
c.Assert(err, jc.ErrorIsNil)
- c.Assert(result.UserModels, gc.HasLen, 0)
+ c.Assert(result.UserModels, gc.HasLen, 1)
}
func (s *modelManagerStateSuite) TestListModelsDenied(c *gc.C) {
View
@@ -193,9 +193,33 @@ func (e *UserModel) LastConnection() (time.Time, error) {
return lastConnDoc.LastConnection, nil
}
+// allUserModels returns a list of all models with the user they belong to.
+func (st *State) allUserModels() ([]*UserModel, error) {
+ models, err := st.AllModels()
+ if err != nil {
+ return nil, errors.Trace(err)
+ }
+ var result []*UserModel
+ for _, model := range models {
+ result = append(result, &UserModel{Model: model, User: model.Owner()})
+ }
+ return result, nil
+}
+
// ModelsForUser returns a list of models that the user
// is able to access.
func (st *State) ModelsForUser(user names.UserTag) ([]*UserModel, error) {
+ // Consider the controller permissions overriding Model permission, for
+ // this case the only relevant one is superuser.
+ // The mgo query below wont work for superuser case because it needs at
+ // least one model user per model.
+ access, err := st.UserAccess(user, st.controllerTag)
+ if err == nil && access.Access == permission.SuperuserAccess {
+ return st.allUserModels()
+ }
+ if err != nil && !errors.IsNotFound(err) {
+ return nil, errors.Trace(err)
+ }
// Since there are no groups at this stage, the simplest way to get all
// the models that a particular user can see is to look through the
// model user collection. A raw collection is required to support
@@ -204,7 +228,7 @@ func (st *State) ModelsForUser(user names.UserTag) ([]*UserModel, error) {
defer userCloser()
var userSlice []userAccessDoc
- err := modelUsers.Find(bson.D{{"user", user.Id()}}).Select(bson.D{{"object-uuid", 1}, {"_id", 1}}).All(&userSlice)
+ err = modelUsers.Find(bson.D{{"user", user.Id()}}).Select(bson.D{{"object-uuid", 1}, {"_id", 1}}).All(&userSlice)
if err != nil {
return nil, err
}

0 comments on commit 49316b2

Please sign in to comment.