diff --git a/src/api/http/api.go b/src/api/http/api.go index 28c1925541..cfe7ca224f 100644 --- a/src/api/http/api.go +++ b/src/api/http/api.go @@ -848,14 +848,14 @@ func (self *HttpServer) listDbUsers(w libhttp.ResponseWriter, r *libhttp.Request db := r.URL.Query().Get(":db") self.tryAsDbUserAndClusterAdmin(w, r, func(u common.User) (int, interface{}) { - names, err := self.userManager.ListDbUsers(u, db) + dbUsers, err := self.userManager.ListDbUsers(u, db) if err != nil { return errorToStatusCode(err), err.Error() } - users := make([]*User, 0, len(names)) - for _, name := range names { - users = append(users, &User{name}) + users := make([]*UserDetail, 0, len(dbUsers)) + for _, dbUser := range dbUsers { + users = append(users, &UserDetail{dbUser.GetName(), dbUser.IsDbAdmin(db)}) } return libhttp.StatusOK, users }) @@ -871,8 +871,7 @@ func (self *HttpServer) showDbUser(w libhttp.ResponseWriter, r *libhttp.Request) return errorToStatusCode(err), err.Error() } - userDetail := &UserDetail{username, user.IsDbAdmin(db)} - fmt.Println(userDetail) + userDetail := &UserDetail{user.GetName(), user.IsDbAdmin(db)} return libhttp.StatusOK, userDetail }) diff --git a/src/api/http/api_test.go b/src/api/http/api_test.go index c33c5af7a4..7e6e8d9d43 100644 --- a/src/api/http/api_test.go +++ b/src/api/http/api_test.go @@ -178,9 +178,10 @@ func (self *ApiSuite) SetUpSuite(c *C) { }, }, } + self.manager = &MockUserManager{ clusterAdmins: []string{"root"}, - dbUsers: map[string][]string{"db1": []string{"db_user1"}}, + dbUsers: map[string]map[string]MockDbUser{"db1": map[string]MockDbUser{"db_user1": {Name: "db_user1", IsAdmin: false}}}, } self.engine = &MockEngine{} dir := c.MkDir() @@ -738,10 +739,11 @@ func (self *ApiSuite) TestDbUsersIndex(c *C) { defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) c.Assert(err, IsNil) - users := []*User{} + users := []*UserDetail{} err = json.Unmarshal(body, &users) c.Assert(err, IsNil) - c.Assert(users, DeepEquals, []*User{&User{"db_user1"}}) + c.Assert(users, HasLen, 1) + c.Assert(users[0], DeepEquals, &UserDetail{"db_user1", false}) } func (self *ApiSuite) TestDbUserShow(c *C) { diff --git a/src/api/http/mock_user_manager_test.go b/src/api/http/mock_user_manager_test.go index fa2c357de6..82c3930d0f 100644 --- a/src/api/http/mock_user_manager_test.go +++ b/src/api/http/mock_user_manager_test.go @@ -12,18 +12,41 @@ type Operation struct { isAdmin bool } -type MockUser struct { - common.User +type MockDbUser struct { Name string IsAdmin bool } -func (self MockUser) IsDbAdmin(_ string) bool { +func (self MockDbUser) GetName() string { + return self.Name +} + +func (self MockDbUser) IsDeleted() bool { + return false +} + +func (self MockDbUser) IsClusterAdmin() bool { + return false +} + +func (self MockDbUser) IsDbAdmin(_ string) bool { return self.IsAdmin } +func (self MockDbUser) GetDb() string { + return "" +} + +func (self MockDbUser) HasWriteAccess(_ string) bool { + return true +} + +func (self MockDbUser) HasReadAccess(_ string) bool { + return true +} + type MockUserManager struct { - dbUsers map[string][]string + dbUsers map[string]map[string]MockDbUser clusterAdmins []string ops []*Operation } @@ -99,10 +122,21 @@ func (self *MockUserManager) ListClusterAdmins(requester common.User) ([]string, return self.clusterAdmins, nil } -func (self *MockUserManager) ListDbUsers(requester common.User, db string) ([]string, error) { - return self.dbUsers[db], nil +func (self *MockUserManager) ListDbUsers(requester common.User, db string) ([]common.User, error) { + dbUsers := self.dbUsers[db] + users := make([]common.User, 0, len(dbUsers)) + for _, user := range dbUsers { + users = append(users, user) + } + + return users, nil } func (self *MockUserManager) GetDbUser(requester common.User, db, username string) (common.User, error) { - return MockUser{Name: username, IsAdmin: false}, nil + dbUsers := self.dbUsers[db] + if dbUser, ok := dbUsers[username]; ok { + return MockDbUser{Name: dbUser.GetName(), IsAdmin: dbUser.IsDbAdmin(db)}, nil + } else { + return nil, fmt.Errorf("'%s' is not a valid username for database '%s'", username, db) + } } diff --git a/src/coordinator/cluster_configuration.go b/src/coordinator/cluster_configuration.go index 32d27ad9b1..b5b3bf78f0 100644 --- a/src/coordinator/cluster_configuration.go +++ b/src/coordinator/cluster_configuration.go @@ -420,15 +420,17 @@ func (self *ClusterConfiguration) GetContinuousQueries(db string) []*ContinuousQ return self.continuousQueries[db] } -func (self *ClusterConfiguration) GetDbUsers(db string) (names []string) { +func (self *ClusterConfiguration) GetDbUsers(db string) []*dbUser { self.usersLock.RLock() defer self.usersLock.RUnlock() dbUsers := self.dbUsers[db] + users := make([]*dbUser, 0, len(dbUsers)) for name, _ := range dbUsers { - names = append(names, name) + fmt.Println(name) + users = append(users, dbUsers[name]) } - return + return users } func (self *ClusterConfiguration) GetDbUser(db, username string) *dbUser { diff --git a/src/coordinator/coordinator.go b/src/coordinator/coordinator.go index 8929e16cd2..8a2399c81f 100644 --- a/src/coordinator/coordinator.go +++ b/src/coordinator/coordinator.go @@ -1225,7 +1225,7 @@ func (self *CoordinatorImpl) DeleteDbUser(requester common.User, db, username st return self.raftServer.SaveDbUser(user) } -func (self *CoordinatorImpl) ListDbUsers(requester common.User, db string) ([]string, error) { +func (self *CoordinatorImpl) ListDbUsers(requester common.User, db string) ([]*dbUser, error) { if !requester.IsClusterAdmin() && !requester.IsDbAdmin(db) { return nil, common.NewAuthorizationError("Insufficient permissions") } @@ -1233,7 +1233,7 @@ func (self *CoordinatorImpl) ListDbUsers(requester common.User, db string) ([]st return self.clusterConfiguration.GetDbUsers(db), nil } -func (self *CoordinatorImpl) GetDbUser(requester common.User, db string, username string) (common.User, error) { +func (self *CoordinatorImpl) GetDbUser(requester common.User, db string, username string) (*dbUser, error) { if !requester.IsClusterAdmin() && !requester.IsDbAdmin(db) { return nil, common.NewAuthorizationError("Insufficient permissions") } diff --git a/src/coordinator/coordinator_test.go b/src/coordinator/coordinator_test.go index 46ba8151dc..190d10e489 100644 --- a/src/coordinator/coordinator_test.go +++ b/src/coordinator/coordinator_test.go @@ -387,7 +387,9 @@ func (self *CoordinatorSuite) TestAdminOperations(c *C) { // can list db users dbUsers, err := coordinator.ListDbUsers(root, "db1") c.Assert(err, IsNil) - c.Assert(dbUsers, DeepEquals, []string{"db_user"}) + c.Assert(dbUsers, HasLen, 1) + c.Assert(dbUsers[0].GetName(), Equals, "db_user") + c.Assert(dbUsers[0].IsDbAdmin("db1"), Equals, true) // can delete cluster admins and db users c.Assert(coordinator.DeleteDbUser(root, "db1", "db_user"), IsNil) @@ -487,11 +489,10 @@ func (self *CoordinatorSuite) TestDbAdminOperations(c *C) { // can get db users admins, err := coordinator.ListDbUsers(dbUser, "db1") c.Assert(err, IsNil) - adminsSet := map[string]bool{} - for _, admin := range admins { - adminsSet[admin] = true - } - c.Assert(adminsSet, DeepEquals, map[string]bool{"db_user": true, "db_user2": true}) + c.Assert(admins[0].GetName(), Equals, "db_user") + c.Assert(admins[0].IsDbAdmin("db1"), Equals, true) + c.Assert(admins[1].GetName(), Equals, "db_user2") + c.Assert(admins[1].IsDbAdmin("db1"), Equals, true) // cannot create db users for a different db c.Assert(coordinator.CreateDbUser(dbUser, "db2", "db_user"), NotNil) diff --git a/src/coordinator/interface.go b/src/coordinator/interface.go index c28027818c..b6685e2d4e 100644 --- a/src/coordinator/interface.go +++ b/src/coordinator/interface.go @@ -55,7 +55,7 @@ type UserManager interface { // Change db user's password. It's an error if requester isn't a cluster admin or db admin ChangeDbUserPassword(requester common.User, db, username, password string) error // list cluster admins. only a cluster admin or the db admin can list the db users - ListDbUsers(requester common.User, db string) ([]string, error) + ListDbUsers(requester common.User, db string) ([]common.User, error) GetDbUser(requester common.User, db, username string) (common.User, error) // make user a db admin for 'db'. It's an error if the requester // isn't a db admin or cluster admin or if user isn't a db user