Skip to content

Commit dc09550

Browse files
committed
endpoint to get github organization membership role
1 parent fda52b1 commit dc09550

File tree

16 files changed

+222
-19
lines changed

16 files changed

+222
-19
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99
- Support Head and Base sha for GitHub pull request, from [@bradrydzewski](https://github.com/bradrydzewski).
1010
- Support Before sha for Bitbucket, from [@jkdev81](https://github.com/jkdev81).
1111
- Support for creating GitHub deployment hooks, from [@bradrydzewski](https://github.com/bradrydzewski).
12+
- Endpoint to get organization membership for GitHub, from [@bradrydzewski](https://github.com/bradrydzewski).
1213

1314
### Fixed
1415
- Fix issue getting a GitLab commit by ref, from [@bradrydzewski](https://github.com/bradrydzewski).

LICENSE

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,52 @@
1-
BSD 3-Clause License
1+
BSD-2-Clause-Patent
22

33
Copyright (c) 2017, Drone.IO Inc.
44
All rights reserved.
55

66
Redistribution and use in source and binary forms, with or without
77
modification, are permitted provided that the following conditions are met:
88

9-
* Redistributions of source code must retain the above copyright notice, this
10-
list of conditions and the following disclaimer.
9+
1. Redistributions of source code must retain the above copyright notice,
10+
this list of conditions and the following disclaimer.
1111

12-
* Redistributions in binary form must reproduce the above copyright notice,
13-
this list of conditions and the following disclaimer in the documentation
14-
and/or other materials provided with the distribution.
12+
2. Redistributions in binary form must reproduce the above copyright notice,
13+
this list of conditions and the following disclaimer in the documentation
14+
and/or other materials provided with the distribution.
1515

16-
* Neither the name of the copyright holder nor the names of its
17-
contributors may be used to endorse or promote products derived from
18-
this software without specific prior written permission.
16+
Subject to the terms and conditions of this license, each copyright holder
17+
and contributor hereby grants to those receiving rights under this license
18+
a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
19+
(except for failure to satisfy the conditions of this license) patent
20+
license to make, have made, use, offer to sell, sell, import, and otherwise
21+
transfer this software, where such license applies only to those patent
22+
claims, already acquired or hereafter acquired, licensable by such copyright
23+
holder or contributor that are necessarily infringed by:
24+
25+
(a) their Contribution(s) (the licensed copyrights of copyright holders and
26+
non-copyrightable additions of contributors, in source or binary form)
27+
alone; or
28+
29+
(b) combination of their Contribution(s) with the work of authorship to
30+
which such Contribution(s) was added by such copyright holder or
31+
contributor, if, at the time the Contribution is added, such addition
32+
causes such combination to be necessarily infringed. The patent license
33+
shall not apply to any other combinations which include the
34+
Contribution.
35+
36+
Except as expressly stated above, no rights or licenses from any copyright
37+
holder or contributor is granted under this license, whether expressly, by
38+
implication, estoppel or otherwise.
39+
40+
DISCLAIMER
1941

2042
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2143
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22-
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23-
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24-
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25-
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26-
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27-
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28-
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29-
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45+
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
46+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
47+
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
48+
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
49+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
50+
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51+
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
52+
POSSIBILITY OF SUCH DAMAGE.

scm/const.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,25 @@ func (d Driver) String() (s string) {
141141
return "unknown"
142142
}
143143
}
144+
145+
// Role defines membership roles.
146+
type Role int
147+
148+
// Role values.
149+
const (
150+
RoleUndefined Role = iota
151+
RoleMember
152+
RoleAdmin
153+
)
154+
155+
// String returns the string representation of Role.
156+
func (r Role) String() (s string) {
157+
switch r {
158+
case RoleMember:
159+
return "member"
160+
case RoleAdmin:
161+
return "admin"
162+
default:
163+
return "unknown"
164+
}
165+
}

scm/driver/bitbucket/org.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ func (s *organizationService) Find(ctx context.Context, name string) (*scm.Organ
2222
return convertOrganization(out), res, err
2323
}
2424

25+
func (s *organizationService) FindMembership(ctx context.Context, name, username string) (*scm.Membership, *scm.Response, error) {
26+
return nil, nil, scm.ErrNotSupported
27+
}
28+
2529
func (s *organizationService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Organization, *scm.Response, error) {
2630
path := fmt.Sprintf("2.0/teams?%s", encodeListRoleOptions(opts))
2731
out := new(organizationList)

scm/driver/gitea/org.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ func (s *organizationService) Find(ctx context.Context, name string) (*scm.Organ
2222
return convertOrg(out), res, err
2323
}
2424

25+
func (s *organizationService) FindMembership(ctx context.Context, name, username string) (*scm.Membership, *scm.Response, error) {
26+
return nil, nil, scm.ErrNotSupported
27+
}
28+
2529
func (s *organizationService) List(ctx context.Context, _ scm.ListOptions) ([]*scm.Organization, *scm.Response, error) {
2630
var out []*org
2731
res, err := s.client.do(ctx, "GET", "api/v1/user/orgs", nil, &out)

scm/driver/gitea/org_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ func TestOrgFind(t *testing.T) {
4141
}
4242
}
4343

44+
func TestOrganizationFindMembership(t *testing.T) {
45+
client, _ := New("https://try.gitea.io")
46+
_, _, err := client.Organizations.FindMembership(context.Background(), "gogits", "jcitizen")
47+
if err != scm.ErrNotSupported {
48+
t.Errorf("Expect Not Supported error")
49+
}
50+
}
51+
4452
func TestOrgList(t *testing.T) {
4553
defer gock.Off()
4654

scm/driver/github/org.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ func (s *organizationService) Find(ctx context.Context, name string) (*scm.Organ
2222
return convertOrganization(out), res, err
2323
}
2424

25+
func (s *organizationService) FindMembership(ctx context.Context, name, username string) (*scm.Membership, *scm.Response, error) {
26+
path := fmt.Sprintf("orgs/%s/memberships/%s", name, username)
27+
out := new(membership)
28+
res, err := s.client.do(ctx, "GET", path, nil, out)
29+
return convertMembership(out), res, err
30+
}
31+
2532
func (s *organizationService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Organization, *scm.Response, error) {
2633
path := fmt.Sprintf("user/orgs?%s", encodeListOptions(opts))
2734
out := []*organization{}
@@ -42,9 +49,31 @@ type organization struct {
4249
Avatar string `json:"avatar_url"`
4350
}
4451

52+
type membership struct {
53+
State string `json:"state"`
54+
Role string `json:"role"`
55+
}
56+
4557
func convertOrganization(from *organization) *scm.Organization {
4658
return &scm.Organization{
4759
Name: from.Login,
4860
Avatar: from.Avatar,
4961
}
5062
}
63+
64+
func convertMembership(from *membership) *scm.Membership {
65+
to := new(scm.Membership)
66+
switch from.State {
67+
case "active":
68+
to.Active = true
69+
}
70+
switch from.Role {
71+
case "admin":
72+
to.Role = scm.RoleAdmin
73+
case "member":
74+
to.Role = scm.RoleMember
75+
default:
76+
to.Role = scm.RoleUndefined
77+
}
78+
return to
79+
}

scm/driver/github/org_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,36 @@ func TestOrganizationFind(t *testing.T) {
4646
t.Run("Rate", testRate(res))
4747
}
4848

49+
func TestOrganizationFindMembership(t *testing.T) {
50+
defer gock.Off()
51+
52+
gock.New("https://api.github.com").
53+
Get("/orgs/github/memberships/octocat").
54+
Reply(200).
55+
Type("application/json").
56+
SetHeaders(mockHeaders).
57+
File("testdata/membership.json")
58+
59+
client := NewDefault()
60+
got, res, err := client.Organizations.FindMembership(context.Background(), "github", "octocat")
61+
if err != nil {
62+
t.Error(err)
63+
return
64+
}
65+
66+
want := new(scm.Membership)
67+
raw, _ := ioutil.ReadFile("testdata/membership.json.golden")
68+
json.Unmarshal(raw, want)
69+
70+
if diff := cmp.Diff(got, want); diff != "" {
71+
t.Errorf("Unexpected Results")
72+
t.Log(diff)
73+
}
74+
75+
t.Run("Request", testRequest(res))
76+
t.Run("Rate", testRate(res))
77+
}
78+
4979
func TestOrganizationList(t *testing.T) {
5080
defer gock.Off()
5181

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"url": "https://api.github.com/orgs/github/memberships/octocat",
3+
"state": "active",
4+
"role": "admin",
5+
"organization_url": "https://api.github.com/orgs/github",
6+
"user": {
7+
"login": "octocat",
8+
"id": 817538,
9+
"node_id": "MDQ6VXNlcjgxNzUzOA==",
10+
"avatar_url": "https://avatars1.githubusercontent.com/u/817538?v=4",
11+
"gravatar_id": "",
12+
"url": "https://api.github.com/users/octocat",
13+
"html_url": "https://github.com/octocat",
14+
"followers_url": "https://api.github.com/users/octocat/followers",
15+
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
16+
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
17+
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
18+
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
19+
"organizations_url": "https://api.github.com/users/octocat/orgs",
20+
"repos_url": "https://api.github.com/users/octocat/repos",
21+
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
22+
"received_events_url": "https://api.github.com/users/octocat/received_events",
23+
"type": "User",
24+
"site_admin": false
25+
},
26+
"organization": {
27+
"login": "github",
28+
"id": 2181346,
29+
"node_id": "MDEyOk9yZ2FuaXphdGlvbjIxODEzNDY=",
30+
"url": "https://api.github.com/orgs/github",
31+
"repos_url": "https://api.github.com/orgs/github/repos",
32+
"events_url": "https://api.github.com/orgs/github/events",
33+
"hooks_url": "https://api.github.com/orgs/github/hooks",
34+
"issues_url": "https://api.github.com/orgs/github/issues",
35+
"members_url": "https://api.github.com/orgs/github/members{/member}",
36+
"public_members_url": "https://api.github.com/orgs/github/public_members{/member}",
37+
"avatar_url": "https://avatars1.githubusercontent.com/u/2181346?v=4",
38+
"description": ""
39+
}
40+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"Active": true,
3+
"Role": 2
4+
}

0 commit comments

Comments
 (0)