Skip to content
This repository has been archived by the owner on Apr 26, 2021. It is now read-only.

Commit

Permalink
gandalftest: implement revokeAccess in the testing server
Browse files Browse the repository at this point in the history
  • Loading branch information
Francisco Souza committed Feb 10, 2015
1 parent 4bbc2c0 commit 9de5824
Show file tree
Hide file tree
Showing 2 changed files with 184 additions and 32 deletions.
104 changes: 72 additions & 32 deletions gandalftest/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (

"github.com/gorilla/pat"
"github.com/tsuru/gandalf/repository"
"github.com/tsuru/tsuru/errors"
"golang.org/x/crypto/ssh"
)

Expand Down Expand Up @@ -106,6 +107,7 @@ func (s *GandalfServer) buildMuxer() {
s.muxer.Post("/user", http.HandlerFunc(s.createUser))
s.muxer.Delete("/user/{name}", http.HandlerFunc(s.removeUser))
s.muxer.Post("/repository/grant", http.HandlerFunc(s.grantAccess))
s.muxer.Delete("/repository/revoke", http.HandlerFunc(s.revokeAccess))
s.muxer.Post("/repository", http.HandlerFunc(s.createRepository))
s.muxer.Delete("/repository/{name}", http.HandlerFunc(s.removeRepository))
s.muxer.Get("/repository/{name}", http.HandlerFunc(s.getRepository))
Expand Down Expand Up @@ -204,45 +206,47 @@ func (s *GandalfServer) getRepository(w http.ResponseWriter, r *http.Request) {

func (s *GandalfServer) grantAccess(w http.ResponseWriter, r *http.Request) {
readOnly := r.URL.Query().Get("readonly") == "yes"
defer r.Body.Close()
var params map[string][]string
err := json.NewDecoder(r.Body).Decode(&params)
repositories, users, err := s.validateAccessRequest(r)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
users := params["users"]
if len(users) < 1 {
http.Error(w, "missing users", http.StatusBadRequest)
http.Error(w, err.Message, err.Code)
return
}
repositories := params["repositories"]
if len(repositories) < 1 {
http.Error(w, "missing repositories", http.StatusBadRequest)
return
}
for _, user := range users {
_, index := s.findUser(user)
if index < 0 {
http.Error(w, fmt.Sprintf("user %q not found", user), http.StatusNotFound)
return
}
}
for _, repository := range repositories {
_, index := s.findRepository(repository)
if index < 0 {
http.Error(w, fmt.Sprintf("repository %q not found", repository), http.StatusNotFound)
return
repo, index := s.findRepository(repository)
for _, user := range users {
if s.checkUserAccess(repo, user, readOnly) < 0 {
if readOnly {
repo.ReadOnlyUsers = append(repo.ReadOnlyUsers, user)
} else {
repo.Users = append(repo.Users, user)
}
}
}
s.repoLock.Lock()
s.repos[index] = repo
s.repoLock.Unlock()
}
}

func (s *GandalfServer) revokeAccess(w http.ResponseWriter, r *http.Request) {
readOnly := r.URL.Query().Get("readonly") == "yes"
repositories, users, err := s.validateAccessRequest(r)
if err != nil {
http.Error(w, err.Message, err.Code)
return
}
for _, repository := range repositories {
repo, index := s.findRepository(repository)
for _, user := range users {
if !s.checkUserAccess(repo, user, readOnly) {
if index := s.checkUserAccess(repo, user, readOnly); index > -1 {
if readOnly {
repo.ReadOnlyUsers = append(repo.ReadOnlyUsers, user)
last := len(repo.ReadOnlyUsers) - 1
repo.ReadOnlyUsers[index] = repo.ReadOnlyUsers[last]
repo.ReadOnlyUsers = repo.ReadOnlyUsers[:last]
} else {
repo.Users = append(repo.Users, user)
last := len(repo.Users) - 1
repo.Users[index] = repo.Users[last]
repo.Users = repo.Users[:last]
}
}
}
Expand All @@ -252,6 +256,42 @@ func (s *GandalfServer) grantAccess(w http.ResponseWriter, r *http.Request) {
}
}

func (s *GandalfServer) validateAccessRequest(r *http.Request) (repositories []string, users []string, err *errors.HTTP) {
defer r.Body.Close()
var params map[string][]string
jerr := json.NewDecoder(r.Body).Decode(&params)
if jerr != nil {
return nil, nil, &errors.HTTP{Code: http.StatusBadRequest, Message: jerr.Error()}
}
users = params["users"]
if len(users) < 1 {
return nil, nil, &errors.HTTP{Code: http.StatusBadRequest, Message: "missing users"}
}
repositories = params["repositories"]
if len(repositories) < 1 {
return nil, nil, &errors.HTTP{Code: http.StatusBadRequest, Message: "missing repositories"}
}
for _, user := range users {
_, index := s.findUser(user)
if index < 0 {
return nil, nil, &errors.HTTP{
Code: http.StatusNotFound,
Message: fmt.Sprintf("user %q not found", user),
}
}
}
for _, repository := range repositories {
_, index := s.findRepository(repository)
if index < 0 {
return nil, nil, &errors.HTTP{
Code: http.StatusNotFound,
Message: fmt.Sprintf("repository %q not found", repository),
}
}
}
return repositories, users, nil
}

func (s *GandalfServer) addKeys(w http.ResponseWriter, r *http.Request) {
userName := r.URL.Query().Get(":name")
var keys map[string]string
Expand Down Expand Up @@ -342,17 +382,17 @@ func (s *GandalfServer) findUser(name string) (userName string, index int) {
return "", -1
}

func (s *GandalfServer) checkUserAccess(repo repository.Repository, user string, readOnly bool) bool {
func (s *GandalfServer) checkUserAccess(repo repository.Repository, user string, readOnly bool) int {
list := repo.Users
if readOnly {
list = repo.ReadOnlyUsers
}
for _, userName := range list {
for i, userName := range list {
if userName == user {
return true
return i
}
}
return false
return -1
}

func (s *GandalfServer) findRepository(name string) (repository.Repository, int) {
Expand Down
112 changes: 112 additions & 0 deletions gandalftest/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,118 @@ func (s *S) TestGrantAccessRepositoryMissingRepositories(c *check.C) {
c.Assert(recorder.Body.String(), check.Equals, "missing repositories\n")
}

func (s *S) TestRevokeAccess(c *check.C) {
server, err := NewServer("127.0.0.1:0")
c.Assert(err, check.IsNil)
defer server.Stop()
server.repos = []repository.Repository{
{Name: "somerepo", Users: []string{"user1", "user3"}},
{Name: "otherrepo", Users: []string{"user2", "user3"}},
{Name: "myrepo", Users: []string{"user1", "user2"}},
}
server.users = []string{"user1", "user2", "user3"}
recorder := httptest.NewRecorder()
body := strings.NewReader(`{"users":["user1","user2"],"repositories":["somerepo","myrepo"]}`)
request, _ := http.NewRequest("DELETE", "/repository/revoke", body)
server.ServeHTTP(recorder, request)
c.Assert(recorder.Code, check.Equals, http.StatusOK)
c.Assert(server.repos[0].Users, check.DeepEquals, []string{"user3"})
c.Assert(server.repos[1].Users, check.DeepEquals, []string{"user2","user3"})
c.Assert(server.repos[2].Users, check.HasLen, 0)
}

func (s *S) TestRevokeAccessReadOnly(c *check.C) {
server, err := NewServer("127.0.0.1:0")
c.Assert(err, check.IsNil)
defer server.Stop()
server.repos = []repository.Repository{
{Name: "somerepo", ReadOnlyUsers: []string{"user1", "user3"}},
{Name: "otherrepo", ReadOnlyUsers: []string{"user2", "user3"}},
{Name: "myrepo", ReadOnlyUsers: []string{"user1", "user2"}},
}
server.users = []string{"user1", "user2", "user3"}
recorder := httptest.NewRecorder()
body := strings.NewReader(`{"users":["user1","user2"],"repositories":["somerepo","myrepo"]}`)
request, _ := http.NewRequest("DELETE", "/repository/revoke?readonly=yes", body)
server.ServeHTTP(recorder, request)
c.Assert(recorder.Code, check.Equals, http.StatusOK)
c.Assert(server.repos[0].ReadOnlyUsers, check.DeepEquals, []string{"user3"})
c.Assert(server.repos[1].ReadOnlyUsers, check.DeepEquals, []string{"user2","user3"})
c.Assert(server.repos[2].ReadOnlyUsers, check.HasLen, 0)
}

func (s *S) TestRevokeAccessUserNotFound(c *check.C) {
server, err := NewServer("127.0.0.1:0")
c.Assert(err, check.IsNil)
defer server.Stop()
server.repos = []repository.Repository{
{Name: "somerepo", Users: []string{"user1", "user3"}},
{Name: "otherrepo", Users: []string{"user2", "user3"}},
{Name: "myrepo", Users: []string{"user1", "user2"}},
}
server.users = []string{"user1", "user2", "user3"}
recorder := httptest.NewRecorder()
body := strings.NewReader(`{"users":["user1","user4"],"repositories":["somerepo","myrepo"]}`)
request, _ := http.NewRequest("DELETE", "/repository/revoke", body)
server.ServeHTTP(recorder, request)
c.Assert(recorder.Code, check.Equals, http.StatusNotFound)
c.Assert(recorder.Body.String(), check.Equals, `user "user4" not found`+"\n")
}

func (s *S) TestRevokeAccessRepositoryNotFound(c *check.C) {
server, err := NewServer("127.0.0.1:0")
c.Assert(err, check.IsNil)
defer server.Stop()
server.repos = []repository.Repository{
{Name: "somerepo", Users: []string{"user1", "user3"}},
{Name: "otherrepo", Users: []string{"user2", "user3"}},
{Name: "myrepo", Users: []string{"user1", "user2"}},
}
server.users = []string{"user1", "user2", "user3"}
recorder := httptest.NewRecorder()
body := strings.NewReader(`{"users":["user1","user2"],"repositories":["somerepo","sumrepo"]}`)
request, _ := http.NewRequest("DELETE", "/repository/revoke", body)
server.ServeHTTP(recorder, request)
c.Assert(recorder.Code, check.Equals, http.StatusNotFound)
c.Assert(recorder.Body.String(), check.Equals, `repository "sumrepo" not found`+"\n")
}

func (s *S) TestRevokeAccessMissingUsers(c *check.C) {
server, err := NewServer("127.0.0.1:0")
c.Assert(err, check.IsNil)
defer server.Stop()
server.repos = []repository.Repository{
{Name: "somerepo", Users: []string{"user1", "user3"}},
{Name: "otherrepo", Users: []string{"user2", "user3"}},
{Name: "myrepo", Users: []string{"user1", "user2"}},
}
server.users = []string{"user1", "user2", "user3"}
recorder := httptest.NewRecorder()
body := strings.NewReader(`{"repositories":["somerepo","myrepo"]}`)
request, _ := http.NewRequest("DELETE", "/repository/revoke", body)
server.ServeHTTP(recorder, request)
c.Assert(recorder.Code, check.Equals, http.StatusBadRequest)
c.Assert(recorder.Body.String(), check.Equals, "missing users\n")
}

func (s *S) TestRevokeAccessMissingRepositories(c *check.C) {
server, err := NewServer("127.0.0.1:0")
c.Assert(err, check.IsNil)
defer server.Stop()
server.repos = []repository.Repository{
{Name: "somerepo", Users: []string{"user1", "user3"}},
{Name: "otherrepo", Users: []string{"user2", "user3"}},
{Name: "myrepo", Users: []string{"user1", "user2"}},
}
server.users = []string{"user1", "user2", "user3"}
recorder := httptest.NewRecorder()
body := strings.NewReader(`{"users":["user1","user2"]}`)
request, _ := http.NewRequest("DELETE", "/repository/revoke", body)
server.ServeHTTP(recorder, request)
c.Assert(recorder.Code, check.Equals, http.StatusBadRequest)
c.Assert(recorder.Body.String(), check.Equals, "missing repositories\n")
}

func (s *S) TestPrepareFailure(c *check.C) {
server, err := NewServer("127.0.0.1:0")
c.Assert(err, check.IsNil)
Expand Down

0 comments on commit 9de5824

Please sign in to comment.