Skip to content

Commit be335ae

Browse files
committed
Merge pull request piotrmurach#242 from joshsoftware/issue_238
Added API for Add/Update Organization Membership. Refs[piotrmurach#238]
2 parents 87b1fa0 + d0a4807 commit be335ae

7 files changed

Lines changed: 177 additions & 9 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"http_interactions":[{"request":{"method":"put","uri":"https://<BASIC_AUTH>@api.github.com/orgs/CodeCu/memberships/anuja-joshi?access_token=<TOKEN>","body":{"encoding":"UTF-8","base64_string":"eyJyb2xlIjoiYWRtaW4ifQ==\n"},"headers":{"Accept":["application/vnd.github.v3+json,application/vnd.github.beta+json;q=0.5,application/json;q=0.1"],"Accept-Charset":["utf-8"],"User-Agent":["Github API Ruby Gem 0.12.4"],"Content-Type":["application/json"],"Accept-Encoding":["gzip;q=1.0,deflate;q=0.6,identity;q=0.3"]}},"response":{"status":{"code":200,"message":"OK"},"headers":{"Server":["GitHub.com"],"Date":["Sat, 03 Oct 2015 12:40:22 GMT"],"Content-Type":["application/json; charset=utf-8"],"Transfer-Encoding":["chunked"],"Status":["200 OK"],"X-Ratelimit-Limit":["5000"],"X-Ratelimit-Remaining":["4982"],"X-Ratelimit-Reset":["1443878521"],"Cache-Control":["private, max-age=60, s-maxage=60"],"Etag":["W/\"587ba2cea74984bad492f0d7d7100c7c\""],"Vary":["Accept, Authorization, Cookie, X-GitHub-OTP","Accept-Encoding"],"X-Github-Media-Type":["github.v3; format=json"],"X-Xss-Protection":["1; mode=block"],"X-Frame-Options":["deny"],"Content-Security-Policy":["default-src 'none'"],"Access-Control-Allow-Credentials":["true"],"Access-Control-Expose-Headers":["ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval"],"Access-Control-Allow-Origin":["*"],"X-Github-Request-Id":["728F85FA:1336B:84A54D8:560FCCB5"],"Strict-Transport-Security":["max-age=31536000; includeSubdomains; preload"],"X-Content-Type-Options":["nosniff"],"X-Served-By":["7f48e2f7761567e923121f17538d7a6d"]},"body":{"encoding":"UTF-8","base64_string":"eyJ1cmwiOiJodHRwczovL2FwaS5naXRodWIuY29tL29yZ3MvQ29kZUN1L21l\nbWJlcnNoaXBzL2FudWphLWpvc2hpIiwic3RhdGUiOiJhY3RpdmUiLCJyb2xl\nIjoiYWRtaW4iLCJvcmdhbml6YXRpb25fdXJsIjoiaHR0cHM6Ly9hcGkuZ2l0\naHViLmNvbS9vcmdzL0NvZGVDdSIsIm9yZ2FuaXphdGlvbiI6eyJsb2dpbiI6\nIkNvZGVDdSIsImlkIjoxNDE0NjY2OSwidXJsIjoiaHR0cHM6Ly9hcGkuZ2l0\naHViLmNvbS9vcmdzL0NvZGVDdSIsInJlcG9zX3VybCI6Imh0dHBzOi8vYXBp\nLmdpdGh1Yi5jb20vb3Jncy9Db2RlQ3UvcmVwb3MiLCJldmVudHNfdXJsIjoi\naHR0cHM6Ly9hcGkuZ2l0aHViLmNvbS9vcmdzL0NvZGVDdS9ldmVudHMiLCJt\nZW1iZXJzX3VybCI6Imh0dHBzOi8vYXBpLmdpdGh1Yi5jb20vb3Jncy9Db2Rl\nQ3UvbWVtYmVyc3svbWVtYmVyfSIsInB1YmxpY19tZW1iZXJzX3VybCI6Imh0\ndHBzOi8vYXBpLmdpdGh1Yi5jb20vb3Jncy9Db2RlQ3UvcHVibGljX21lbWJl\ncnN7L21lbWJlcn0iLCJhdmF0YXJfdXJsIjoiaHR0cHM6Ly9hdmF0YXJzLmdp\ndGh1YnVzZXJjb250ZW50LmNvbS91LzE0MTQ2NjY5P3Y9MyIsImRlc2NyaXB0\naW9uIjpudWxsfSwidXNlciI6eyJsb2dpbiI6ImFudWphLWpvc2hpIiwiaWQi\nOjUxMjQwNDIsImF2YXRhcl91cmwiOiJodHRwczovL2F2YXRhcnMuZ2l0aHVi\ndXNlcmNvbnRlbnQuY29tL3UvNTEyNDA0Mj92PTMiLCJncmF2YXRhcl9pZCI6\nIiIsInVybCI6Imh0dHBzOi8vYXBpLmdpdGh1Yi5jb20vdXNlcnMvYW51amEt\nam9zaGkiLCJodG1sX3VybCI6Imh0dHBzOi8vZ2l0aHViLmNvbS9hbnVqYS1q\nb3NoaSIsImZvbGxvd2Vyc191cmwiOiJodHRwczovL2FwaS5naXRodWIuY29t\nL3VzZXJzL2FudWphLWpvc2hpL2ZvbGxvd2VycyIsImZvbGxvd2luZ191cmwi\nOiJodHRwczovL2FwaS5naXRodWIuY29tL3VzZXJzL2FudWphLWpvc2hpL2Zv\nbGxvd2luZ3svb3RoZXJfdXNlcn0iLCJnaXN0c191cmwiOiJodHRwczovL2Fw\naS5naXRodWIuY29tL3VzZXJzL2FudWphLWpvc2hpL2dpc3Rzey9naXN0X2lk\nfSIsInN0YXJyZWRfdXJsIjoiaHR0cHM6Ly9hcGkuZ2l0aHViLmNvbS91c2Vy\ncy9hbnVqYS1qb3NoaS9zdGFycmVkey9vd25lcn17L3JlcG99Iiwic3Vic2Ny\naXB0aW9uc191cmwiOiJodHRwczovL2FwaS5naXRodWIuY29tL3VzZXJzL2Fu\ndWphLWpvc2hpL3N1YnNjcmlwdGlvbnMiLCJvcmdhbml6YXRpb25zX3VybCI6\nImh0dHBzOi8vYXBpLmdpdGh1Yi5jb20vdXNlcnMvYW51amEtam9zaGkvb3Jn\ncyIsInJlcG9zX3VybCI6Imh0dHBzOi8vYXBpLmdpdGh1Yi5jb20vdXNlcnMv\nYW51amEtam9zaGkvcmVwb3MiLCJldmVudHNfdXJsIjoiaHR0cHM6Ly9hcGku\nZ2l0aHViLmNvbS91c2Vycy9hbnVqYS1qb3NoaS9ldmVudHN7L3ByaXZhY3l9\nIiwicmVjZWl2ZWRfZXZlbnRzX3VybCI6Imh0dHBzOi8vYXBpLmdpdGh1Yi5j\nb20vdXNlcnMvYW51amEtam9zaGkvcmVjZWl2ZWRfZXZlbnRzIiwidHlwZSI6\nIlVzZXIiLCJzaXRlX2FkbWluIjpmYWxzZX19\n"},"http_version":null},"recorded_at":"Sat, 03 Oct 2015 12:40:22 GMT"}],"recorded_with":"VCR 2.6.0"}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"http_interactions":[{"request":{"method":"put","uri":"https://<BASIC_AUTH>@api.github.com/orgs/CodeCu/memberships/anujaware?access_token=<TOKEN>","body":{"encoding":"UTF-8","base64_string":"eyJyb2xlIjoibWVtYmVyIn0=\n"},"headers":{"Accept":["application/vnd.github.v3+json,application/vnd.github.beta+json;q=0.5,application/json;q=0.1"],"Accept-Charset":["utf-8"],"User-Agent":["Github API Ruby Gem 0.12.4"],"Content-Type":["application/json"],"Accept-Encoding":["gzip;q=1.0,deflate;q=0.6,identity;q=0.3"]}},"response":{"status":{"code":200,"message":"OK"},"headers":{"Server":["GitHub.com"],"Date":["Sat, 03 Oct 2015 12:40:20 GMT"],"Content-Type":["application/json; charset=utf-8"],"Transfer-Encoding":["chunked"],"Status":["200 OK"],"X-Ratelimit-Limit":["5000"],"X-Ratelimit-Remaining":["4983"],"X-Ratelimit-Reset":["1443878521"],"Cache-Control":["private, max-age=60, s-maxage=60"],"Etag":["W/\"20837e0876109f789503d390ad3035b9\""],"Vary":["Accept, Authorization, Cookie, X-GitHub-OTP","Accept-Encoding"],"X-Github-Media-Type":["github.v3; format=json"],"X-Xss-Protection":["1; mode=block"],"X-Frame-Options":["deny"],"Content-Security-Policy":["default-src 'none'"],"Access-Control-Allow-Credentials":["true"],"Access-Control-Expose-Headers":["ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval"],"Access-Control-Allow-Origin":["*"],"X-Github-Request-Id":["728F85FA:1336E:E3BC0A3:560FCCB3"],"Strict-Transport-Security":["max-age=31536000; includeSubdomains; preload"],"X-Content-Type-Options":["nosniff"],"X-Served-By":["76d9828c7e4f1d910f7ba069e90ce976"]},"body":{"encoding":"UTF-8","base64_string":"eyJ1cmwiOiJodHRwczovL2FwaS5naXRodWIuY29tL29yZ3MvQ29kZUN1L21l\nbWJlcnNoaXBzL2FudWphd2FyZSIsInN0YXRlIjoicGVuZGluZyIsInJvbGUi\nOiJtZW1iZXIiLCJvcmdhbml6YXRpb25fdXJsIjoiaHR0cHM6Ly9hcGkuZ2l0\naHViLmNvbS9vcmdzL0NvZGVDdSIsIm9yZ2FuaXphdGlvbiI6eyJsb2dpbiI6\nIkNvZGVDdSIsImlkIjoxNDE0NjY2OSwidXJsIjoiaHR0cHM6Ly9hcGkuZ2l0\naHViLmNvbS9vcmdzL0NvZGVDdSIsInJlcG9zX3VybCI6Imh0dHBzOi8vYXBp\nLmdpdGh1Yi5jb20vb3Jncy9Db2RlQ3UvcmVwb3MiLCJldmVudHNfdXJsIjoi\naHR0cHM6Ly9hcGkuZ2l0aHViLmNvbS9vcmdzL0NvZGVDdS9ldmVudHMiLCJt\nZW1iZXJzX3VybCI6Imh0dHBzOi8vYXBpLmdpdGh1Yi5jb20vb3Jncy9Db2Rl\nQ3UvbWVtYmVyc3svbWVtYmVyfSIsInB1YmxpY19tZW1iZXJzX3VybCI6Imh0\ndHBzOi8vYXBpLmdpdGh1Yi5jb20vb3Jncy9Db2RlQ3UvcHVibGljX21lbWJl\ncnN7L21lbWJlcn0iLCJhdmF0YXJfdXJsIjoiaHR0cHM6Ly9hdmF0YXJzLmdp\ndGh1YnVzZXJjb250ZW50LmNvbS91LzE0MTQ2NjY5P3Y9MyIsImRlc2NyaXB0\naW9uIjpudWxsfSwidXNlciI6eyJsb2dpbiI6ImFudWphd2FyZSIsImlkIjo1\nNjIwNDgsImF2YXRhcl91cmwiOiJodHRwczovL2F2YXRhcnMuZ2l0aHVidXNl\ncmNvbnRlbnQuY29tL3UvNTYyMDQ4P3Y9MyIsImdyYXZhdGFyX2lkIjoiIiwi\ndXJsIjoiaHR0cHM6Ly9hcGkuZ2l0aHViLmNvbS91c2Vycy9hbnVqYXdhcmUi\nLCJodG1sX3VybCI6Imh0dHBzOi8vZ2l0aHViLmNvbS9hbnVqYXdhcmUiLCJm\nb2xsb3dlcnNfdXJsIjoiaHR0cHM6Ly9hcGkuZ2l0aHViLmNvbS91c2Vycy9h\nbnVqYXdhcmUvZm9sbG93ZXJzIiwiZm9sbG93aW5nX3VybCI6Imh0dHBzOi8v\nYXBpLmdpdGh1Yi5jb20vdXNlcnMvYW51amF3YXJlL2ZvbGxvd2luZ3svb3Ro\nZXJfdXNlcn0iLCJnaXN0c191cmwiOiJodHRwczovL2FwaS5naXRodWIuY29t\nL3VzZXJzL2FudWphd2FyZS9naXN0c3svZ2lzdF9pZH0iLCJzdGFycmVkX3Vy\nbCI6Imh0dHBzOi8vYXBpLmdpdGh1Yi5jb20vdXNlcnMvYW51amF3YXJlL3N0\nYXJyZWR7L293bmVyfXsvcmVwb30iLCJzdWJzY3JpcHRpb25zX3VybCI6Imh0\ndHBzOi8vYXBpLmdpdGh1Yi5jb20vdXNlcnMvYW51amF3YXJlL3N1YnNjcmlw\ndGlvbnMiLCJvcmdhbml6YXRpb25zX3VybCI6Imh0dHBzOi8vYXBpLmdpdGh1\nYi5jb20vdXNlcnMvYW51amF3YXJlL29yZ3MiLCJyZXBvc191cmwiOiJodHRw\nczovL2FwaS5naXRodWIuY29tL3VzZXJzL2FudWphd2FyZS9yZXBvcyIsImV2\nZW50c191cmwiOiJodHRwczovL2FwaS5naXRodWIuY29tL3VzZXJzL2FudWph\nd2FyZS9ldmVudHN7L3ByaXZhY3l9IiwicmVjZWl2ZWRfZXZlbnRzX3VybCI6\nImh0dHBzOi8vYXBpLmdpdGh1Yi5jb20vdXNlcnMvYW51amF3YXJlL3JlY2Vp\ndmVkX2V2ZW50cyIsInR5cGUiOiJVc2VyIiwic2l0ZV9hZG1pbiI6ZmFsc2V9\nfQ==\n"},"http_version":null},"recorded_at":"Sat, 03 Oct 2015 12:40:20 GMT"}],"recorded_with":"VCR 2.6.0"}

features/orgs/members.feature

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,30 @@ Feature: Members API
5555
| true |
5656
When I make request within a cassette named "orgs/members/member_public_true"
5757
Then the response should be true
58+
59+
Scenario: Add/Update Organization Membership (unaffiliated user)
60+
61+
Given I want to grant_organization_membership resource with the following params:
62+
| org | username |
63+
| CodeCu | anujaware |
64+
And I pass the following request options:
65+
| role |
66+
| member |
67+
When I make request within a cassette named "orgs/members/grant_organization_membership_unaffiliated_user"
68+
Then the response status should be 200
69+
And the response type should be JSON
70+
And the response should not be empty
71+
72+
73+
Scenario: Add/Update Organization Membership (already member)
74+
75+
Given I want to grant_organization_membership resource with the following params:
76+
| org | username |
77+
| CodeCu | anuja-joshi |
78+
And I pass the following request options:
79+
| role |
80+
| admin |
81+
When I make request within a cassette named "orgs/members/grant_organization_membership_already_member"
82+
Then the response status should be 200
83+
And the response type should be JSON
84+
And the response should not be empty

lib/github_api/client/orgs/members.rb

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ def list(*args)
3939
org_name = arguments.org_name
4040

4141
response = if params.delete('public')
42-
get_request("/orgs/#{org_name}/public_members", params)
43-
else
44-
get_request("/orgs/#{org_name}/members", params)
45-
end
42+
get_request("/orgs/#{org_name}/public_members", params)
43+
else
44+
get_request("/orgs/#{org_name}/members", params)
45+
end
4646
return response unless block_given?
4747
response.each { |el| yield el }
4848
end
@@ -67,15 +67,15 @@ def member?(*args)
6767
user = arguments.user
6868

6969
response = if params.delete('public')
70-
get_request("/orgs/#{org_name}/public_members/#{user}", params)
71-
else
72-
get_request("/orgs/#{org_name}/members/#{user}", params)
73-
end
70+
get_request("/orgs/#{org_name}/public_members/#{user}", params)
71+
else
72+
get_request("/orgs/#{org_name}/members/#{user}", params)
73+
end
7474
response.status == 204
7575
rescue Github::Error::NotFound
7676
false
77-
end
7877

78+
end
7979
# Remove a member
8080
#
8181
# Removing a user from this list will remove them from all teams and
@@ -121,5 +121,21 @@ def conceal(*args)
121121
delete_request("/orgs/#{arguments.org_name}/public_members/#{arguments.user}", arguments.params)
122122
end
123123
alias :conceal_membership :conceal
124+
125+
# Add/update user’s membership with organization
126+
#
127+
# @example
128+
# github = Github.new oauth_token: '...'
129+
# github.orgs.members.grant_organization_membership 'org-name', 'member-name', {role: 'role'}
130+
#
131+
# role is optional and can be member / admin. default - member
132+
#
133+
# @api public
134+
def grant_organization_membership(*args)
135+
params = arguments(args, required: [:org, :username]).params
136+
org = arguments.org
137+
username = arguments.username
138+
response= put_request("/orgs/#{org}/memberships/#{username}", params)
139+
end
124140
end # Client::Orgs::Members
125141
end # Github
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"url": "https://api.github.com/orgs/CodeCu/memberships/anuja-joshi",
3+
"state": "active",
4+
"role": "admin",
5+
"organization_url": "https://api.github.com/orgs/CodeCu",
6+
"organization": {
7+
"login": "CodeCu",
8+
"id": 14146669,
9+
"url": "https://api.github.com/orgs/CodeCu",
10+
"repos_url": "https://api.github.com/orgs/CodeCu/repos",
11+
"events_url": "https://api.github.com/orgs/CodeCu/events",
12+
"members_url": "https://api.github.com/orgs/CodeCu/members{/member}",
13+
"public_members_url": "https://api.github.com/orgs/CodeCu/public_members{/member}",
14+
"avatar_url": "https://avatars.githubusercontent.com/u/14146669?v=3",
15+
"description": null
16+
},
17+
"user": {
18+
"login": "anuja-joshi",
19+
"id": 5124042,
20+
"avatar_url": "https://avatars.githubusercontent.com/u/5124042?v=3",
21+
"gravatar_id": "",
22+
"url": "https://api.github.com/users/anuja-joshi",
23+
"html_url": "https://github.com/anuja-joshi",
24+
"followers_url": "https://api.github.com/users/anuja-joshi/followers",
25+
"following_url": "https://api.github.com/users/anuja-joshi/following{/other_user}",
26+
"gists_url": "https://api.github.com/users/anuja-joshi/gists{/gist_id}",
27+
"starred_url": "https://api.github.com/users/anuja-joshi/starred{/owner}{/repo}",
28+
"subscriptions_url": "https://api.github.com/users/anuja-joshi/subscriptions",
29+
"organizations_url": "https://api.github.com/users/anuja-joshi/orgs",
30+
"repos_url": "https://api.github.com/users/anuja-joshi/repos",
31+
"events_url": "https://api.github.com/users/anuja-joshi/events{/privacy}",
32+
"received_events_url": "https://api.github.com/users/anuja-joshi/received_events",
33+
"type": "User",
34+
"site_admin": false
35+
}
36+
}
37+
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"url": "https://api.github.com/orgs/CodeCu/memberships/anujaware",
3+
"state": "pending",
4+
"role": "member",
5+
"organization_url": "https://api.github.com/orgs/CodeCu",
6+
"organization": {
7+
"login": "CodeCu",
8+
"id": 14146669,
9+
"url": "https://api.github.com/orgs/CodeCu",
10+
"repos_url": "https://api.github.com/orgs/CodeCu/repos",
11+
"events_url": "https://api.github.com/orgs/CodeCu/events",
12+
"members_url": "https://api.github.com/orgs/CodeCu/members{/member}",
13+
"public_members_url": "https://api.github.com/orgs/CodeCu/public_members{/member}",
14+
"avatar_url": "https://avatars.githubusercontent.com/u/14146669?v=3",
15+
"description": null
16+
},
17+
"user": {
18+
"login": "anujaware",
19+
"id": 562048,
20+
"avatar_url": "https://avatars.githubusercontent.com/u/562048?v=3",
21+
"gravatar_id": "",
22+
"url": "https://api.github.com/users/anujaware",
23+
"html_url": "https://github.com/anujaware",
24+
"followers_url": "https://api.github.com/users/anujaware/followers",
25+
"following_url": "https://api.github.com/users/anujaware/following{/other_user}",
26+
"gists_url": "https://api.github.com/users/anujaware/gists{/gist_id}",
27+
"starred_url": "https://api.github.com/users/anujaware/starred{/owner}{/repo}",
28+
"subscriptions_url": "https://api.github.com/users/anujaware/subscriptions",
29+
"organizations_url": "https://api.github.com/users/anujaware/orgs",
30+
"repos_url": "https://api.github.com/users/anujaware/repos",
31+
"events_url": "https://api.github.com/users/anujaware/events{/privacy}",
32+
"received_events_url": "https://api.github.com/users/anujaware/received_events",
33+
"type": "User",
34+
"site_admin": false
35+
}
36+
}
37+
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# encoding: utf-8
2+
3+
require 'spec_helper'
4+
5+
describe Github::Client::Orgs::Members, '#grant_organization_membership' do
6+
let(:org) { 'CodeCu' }
7+
let(:status) { 200 }
8+
9+
before {
10+
stub_put(request_path).with(inputs).to_return(:body => body, :status => status,
11+
:headers => {:content_type => "application/json; charset=utf-8"})
12+
}
13+
14+
context 'Add/update organization membership - unaffiliated user' do
15+
16+
let(:username) { 'anujaware' }
17+
let(:request_path) { "/orgs/#{org}/memberships/#{username}" }
18+
let(:body) { fixture('orgs/membership_to_unaffiliated_user.json') }
19+
let(:inputs) {{role: 'member'}}
20+
21+
it 'should create organization membership with pending state' do
22+
response = subject.grant_organization_membership org, username, inputs
23+
expect(response.state).to eq 'pending'
24+
end
25+
26+
it 'should create organization membership with role member' do
27+
response = subject.grant_organization_membership org, username, inputs
28+
expect(response.role).to eq 'member'
29+
end
30+
end
31+
32+
context 'Add/update organization membership - affiliated user' do
33+
34+
let(:username) { 'anuja-joshi' }
35+
let(:request_path) { "/orgs/#{org}/memberships/#{username}" }
36+
let(:body) { fixture('orgs/membership_to_affilliated_user.json') }
37+
let(:inputs) {{role: 'admin'}}
38+
39+
it 'should create organization membership with active state' do
40+
response = subject.grant_organization_membership org, username, inputs
41+
expect(response.state).to eq 'active'
42+
end
43+
44+
it 'should update organization membership with role admin' do
45+
response = subject.grant_organization_membership org, username, inputs
46+
expect(response.role).to eq 'admin'
47+
end
48+
end
49+
end # grant_organization_membership

0 commit comments

Comments
 (0)