From facf5a78f4d2ca9201c1141ce180a4bd1c7c8b0a Mon Sep 17 00:00:00 2001 From: Will Norris Date: Fri, 24 May 2013 15:30:08 -0700 Subject: [PATCH] add additional organization related methods adds CheckMemberhsip, CheckPublicMembership, and RemoveMember --- orgs.go | 91 ++++++++++++++++++++++++++------ orgs_test.go | 146 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 221 insertions(+), 16 deletions(-) diff --git a/orgs.go b/orgs.go index 03547cb..c69bb33 100644 --- a/orgs.go +++ b/orgs.go @@ -8,6 +8,7 @@ package github import ( "fmt" + "net/http" "net/url" "strconv" ) @@ -118,34 +119,55 @@ func (s *OrganizationsService) ListPublicMembers(org string) ([]User, error) { return *members, err } -// List the teams for an organization. -func (s *OrganizationsService) ListTeams(org string) ([]Team, error) { - url_ := fmt.Sprintf("orgs/%v/teams", org) +// CheckMembership checks if a user is a member of an organization. +func (s *OrganizationsService) CheckMembership(org, user string) (bool, error) { + url_ := fmt.Sprintf("orgs/%v/members/%v", org, user) req, err := s.client.NewRequest("GET", url_, nil) if err != nil { - return nil, err + return false, err } - teams := new([]Team) - _, err = s.client.Do(req, teams) - return *teams, err + _, err = s.client.Do(req, nil) + if err != nil { + if err, ok := err.(*ErrorResponse); ok && err.Response.StatusCode == http.StatusNotFound { + // The user is not a member of the org. In this one case, we do not pass + // the error through. + return false, nil + } else { + // some other real error occurred + return false, err + } + } + + return err == nil, err } -// Add a user to a team. -func (s *OrganizationsService) AddTeamMember(team int, user string) error { - url_ := fmt.Sprintf("teams/%v/members/%v", team, user) - req, err := s.client.NewRequest("PUT", url_, nil) +// CheckPublicMembership checks if a user is a public member of an organization. +func (s *OrganizationsService) CheckPublicMembership(org, user string) (bool, error) { + url_ := fmt.Sprintf("orgs/%v/public_members/%v", org, user) + req, err := s.client.NewRequest("GET", url_, nil) if err != nil { - return err + return false, err } _, err = s.client.Do(req, nil) - return err + if err != nil { + if err, ok := err.(*ErrorResponse); ok && err.Response.StatusCode == http.StatusNotFound { + // The user is not a member of the org. In this one case, we do not pass + // the error through. + return false, nil + } else { + // some other real error occurred + return false, err + } + } + + return true, nil } -// Remove a user from a team. -func (s *OrganizationsService) RemoveTeamMember(team int, user string) error { - url_ := fmt.Sprintf("teams/%v/members/%v", team, user) +// RemoveMember removes a user from all teams of an organization. +func (s *OrganizationsService) RemoveMember(org, user string) error { + url_ := fmt.Sprintf("orgs/%v/members/%v", org, user) req, err := s.client.NewRequest("DELETE", url_, nil) if err != nil { return err @@ -178,3 +200,40 @@ func (s *OrganizationsService) ConcealMembership(org, user string) error { _, err = s.client.Do(req, nil) return err } + +// List the teams for an organization. +func (s *OrganizationsService) ListTeams(org string) ([]Team, error) { + url_ := fmt.Sprintf("orgs/%v/teams", org) + req, err := s.client.NewRequest("GET", url_, nil) + if err != nil { + return nil, err + } + + teams := new([]Team) + _, err = s.client.Do(req, teams) + return *teams, err +} + +// Add a user to a team. +func (s *OrganizationsService) AddTeamMember(team int, user string) error { + url_ := fmt.Sprintf("teams/%v/members/%v", team, user) + req, err := s.client.NewRequest("PUT", url_, nil) + if err != nil { + return err + } + + _, err = s.client.Do(req, nil) + return err +} + +// Remove a user from a team. +func (s *OrganizationsService) RemoveTeamMember(team int, user string) error { + url_ := fmt.Sprintf("teams/%v/members/%v", team, user) + req, err := s.client.NewRequest("DELETE", url_, nil) + if err != nil { + return err + } + + _, err = s.client.Do(req, nil) + return err +} diff --git a/orgs_test.go b/orgs_test.go index 7406d84..4422788 100644 --- a/orgs_test.go +++ b/orgs_test.go @@ -160,6 +160,152 @@ func TestOrganizationsService_ListPublicMembers(t *testing.T) { } } +func TestOrganizationsService_CheckMembership(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/orgs/o/members/u", func(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" { + t.Errorf("Request method = %v, want %v", r.Method, "GET") + } + }) + + member, err := client.Organizations.CheckMembership("o", "u") + if err != nil { + t.Errorf("Organizations.CheckMembership returned error: %v", err) + } + want := true + if member != want { + t.Errorf("Organizations.CheckMembership returned %+v, want %+v", member, want) + } +} + +// ensure that a 404 response is interpreted as "false" and not an error +func TestOrganizationsService_CheckMembership_notMember(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/orgs/o/members/u", func(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" { + t.Errorf("Request method = %v, want %v", r.Method, "GET") + } + http.Error(w, "", http.StatusNotFound) + }) + + member, err := client.Organizations.CheckMembership("o", "u") + if err != nil { + t.Errorf("Organizations.CheckMembership returned error: %v", err) + } + want := false + if member != want { + t.Errorf("Organizations.CheckMembership returned %+v, want %+v", member, want) + } +} + +// ensure that a 400 response is interpreted as an actual error, and not simply +// as "false" like the above case of a 404 +func TestOrganizationsService_CheckMembership_error(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/orgs/o/members/u", func(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" { + t.Errorf("Request method = %v, want %v", r.Method, "GET") + } + http.Error(w, "BadRequest", http.StatusBadRequest) + }) + + member, err := client.Organizations.CheckMembership("o", "u") + if err == nil { + t.Errorf("Expected HTTP 400 response") + } + want := false + if member != want { + t.Errorf("Organizations.CheckMembership returned %+v, want %+v", member, want) + } +} + +func TestOrganizationsService_CheckPublicMembership(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/orgs/o/public_members/u", func(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" { + t.Errorf("Request method = %v, want %v", r.Method, "GET") + } + }) + + member, err := client.Organizations.CheckPublicMembership("o", "u") + if err != nil { + t.Errorf("Organizations.CheckPublicMembership returned error: %v", err) + } + want := true + if member != want { + t.Errorf("Organizations.CheckPublicMembership returned %+v, want %+v", member, want) + } +} + +// ensure that a 404 response is interpreted as "false" and not an error +func TestOrganizationsService_CheckPublicMembership_notMember(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/orgs/o/public_members/u", func(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" { + t.Errorf("Request method = %v, want %v", r.Method, "GET") + } + http.Error(w, "", http.StatusNotFound) + }) + + member, err := client.Organizations.CheckPublicMembership("o", "u") + if err != nil { + t.Errorf("Organizations.CheckPublicMembership returned error: %v", err) + } + want := false + if member != want { + t.Errorf("Organizations.CheckPublicMembership returned %+v, want %+v", member, want) + } +} + +// ensure that a 400 response is interpreted as an actual error, and not simply +// as "false" like the above case of a 404 +func TestOrganizationsService_CheckPublicMembership_error(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/orgs/o/public_members/u", func(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" { + t.Errorf("Request method = %v, want %v", r.Method, "GET") + } + http.Error(w, "BadRequest", http.StatusBadRequest) + }) + + member, err := client.Organizations.CheckPublicMembership("o", "u") + if err == nil { + t.Errorf("Expected HTTP 400 response") + } + want := false + if member != want { + t.Errorf("Organizations.CheckPublicMembership returned %+v, want %+v", member, want) + } +} + +func TestOrganizationsService_RemoveMember(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/orgs/o/members/u", func(w http.ResponseWriter, r *http.Request) { + if r.Method != "DELETE" { + t.Errorf("Request method = %v, want %v", r.Method, "DELETE") + } + }) + + err := client.Organizations.RemoveMember("o", "u") + if err != nil { + t.Errorf("Organizations.RemoveMember returned error: %v", err) + } +} + func TestOrganizationsService_ListTeams(t *testing.T) { setup() defer teardown()