Skip to content

Commit ebdbf8f

Browse files
authored
Merge pull request #1187 from t0m4uk1991/myself_app_installations
Add getAppInstallations(/user/installations) method on GHMyself
2 parents 81f23e8 + 689b2f7 commit ebdbf8f

File tree

10 files changed

+357
-0
lines changed

10 files changed

+357
-0
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package org.kohsuke.github;
2+
3+
import java.net.MalformedURLException;
4+
import java.util.Iterator;
5+
6+
import javax.annotation.Nonnull;
7+
8+
/**
9+
* Iterable for GHAppInstallation listing.
10+
*/
11+
class GHAppInstallationsIterable extends PagedIterable<GHAppInstallation> {
12+
public static final String APP_INSTALLATIONS_URL = "/user/installations";
13+
private final transient GitHub root;
14+
private GHAppInstallationsPage result;
15+
16+
public GHAppInstallationsIterable(GitHub root) {
17+
this.root = root;
18+
}
19+
20+
@Nonnull
21+
@Override
22+
public PagedIterator<GHAppInstallation> _iterator(int pageSize) {
23+
try {
24+
final GitHubRequest request = root.createRequest().withUrlPath(APP_INSTALLATIONS_URL).build();
25+
return new PagedIterator<>(
26+
adapt(GitHubPageIterator.create(root.getClient(), GHAppInstallationsPage.class, request, pageSize)),
27+
null);
28+
} catch (MalformedURLException e) {
29+
throw new GHException("Malformed URL", e);
30+
}
31+
}
32+
33+
protected Iterator<GHAppInstallation[]> adapt(final Iterator<GHAppInstallationsPage> base) {
34+
return new Iterator<GHAppInstallation[]>() {
35+
public boolean hasNext() {
36+
return base.hasNext();
37+
}
38+
39+
public GHAppInstallation[] next() {
40+
GHAppInstallationsPage v = base.next();
41+
if (result == null) {
42+
result = v;
43+
}
44+
return v.getInstallations();
45+
}
46+
};
47+
}
48+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package org.kohsuke.github;
2+
3+
/**
4+
* Represents the one page of GHAppInstallations.
5+
*/
6+
class GHAppInstallationsPage {
7+
private int total_count;
8+
private GHAppInstallation[] installations;
9+
10+
public int getTotalCount() {
11+
return total_count;
12+
}
13+
14+
GHAppInstallation[] getInstallations() {
15+
return installations;
16+
}
17+
}

src/main/java/org/kohsuke/github/GHMyself.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,4 +239,18 @@ public GHMembership getMembership(GHOrganization o) throws IOException {
239239
//// new Requester(root,ApiVersion.V3).withCredential().to("/user/emails");
240240
// root.retrieveWithAuth3()
241241
// }
242+
243+
/**
244+
* Lists installations of your GitHub App that the authenticated user has explicit permission to access. You must
245+
* use a user-to-server OAuth access token, created for a user who has authorized your GitHub App, to access this
246+
* endpoint.
247+
*
248+
* @return the paged iterable
249+
* @see <a href=
250+
* "https://docs.github.com/en/rest/reference/apps#list-app-installations-accessible-to-the-user-access-token">List
251+
* app installations accessible to the user access token</a>
252+
*/
253+
public PagedIterable<GHAppInstallation> getAppInstallations() {
254+
return new GHAppInstallationsIterable(root);
255+
}
242256
}

src/test/java/org/kohsuke/github/AppTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,20 @@ public void testFetchPullRequestAsList() throws Exception {
384384
assertThat(prs, is(not(empty())));
385385
}
386386

387+
@Test
388+
public void testGetAppInstallations() throws Exception {
389+
// To generate test data user-to-server OAuth access token was used
390+
// For more details pls read
391+
// https://docs.github.com/en/developers/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps#identifying-users-on-your-site
392+
final PagedIterable<GHAppInstallation> appInstallation = gitHub.getMyself().getAppInstallations();
393+
394+
assertThat(appInstallation.toList(), is(not(empty())));
395+
assertThat(appInstallation.toList().size(), is(1));
396+
final GHAppInstallation ghAppInstallation = appInstallation.toList().get(0);
397+
assertThat(ghAppInstallation.getAppId(), is(122478L));
398+
assertThat(ghAppInstallation.getAccount().getLogin(), is("t0m4uk1991"));
399+
}
400+
387401
@Ignore("Needs mocking check")
388402
@Test
389403
public void testRepoPermissions() throws Exception {
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"login": "t0m4uk1991",
3+
"id": 6698785,
4+
"node_id": "MDQ6VXNlcjY2OTg3ODU=",
5+
"avatar_url": "https://avatars.githubusercontent.com/u/6698785?v=4",
6+
"gravatar_id": "",
7+
"url": "https://api.github.com/users/t0m4uk1991",
8+
"html_url": "https://github.com/t0m4uk1991",
9+
"followers_url": "https://api.github.com/users/t0m4uk1991/followers",
10+
"following_url": "https://api.github.com/users/t0m4uk1991/following{/other_user}",
11+
"gists_url": "https://api.github.com/users/t0m4uk1991/gists{/gist_id}",
12+
"starred_url": "https://api.github.com/users/t0m4uk1991/starred{/owner}{/repo}",
13+
"subscriptions_url": "https://api.github.com/users/t0m4uk1991/subscriptions",
14+
"organizations_url": "https://api.github.com/users/t0m4uk1991/orgs",
15+
"repos_url": "https://api.github.com/users/t0m4uk1991/repos",
16+
"events_url": "https://api.github.com/users/t0m4uk1991/events{/privacy}",
17+
"received_events_url": "https://api.github.com/users/t0m4uk1991/received_events",
18+
"type": "User",
19+
"site_admin": false,
20+
"name": null,
21+
"company": null,
22+
"blog": "https://t0m4uk1991.github.io",
23+
"location": "Ukraine",
24+
"email": "[email protected]",
25+
"hireable": true,
26+
"bio": null,
27+
"twitter_username": null,
28+
"public_repos": 14,
29+
"public_gists": 10,
30+
"followers": 2,
31+
"following": 2,
32+
"created_at": "2014-02-16T20:43:03Z",
33+
"updated_at": "2021-06-21T14:53:32Z"
34+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"login": "t0m4uk1991",
3+
"id": 6698785,
4+
"node_id": "MDQ6VXNlcjY2OTg3ODU=",
5+
"avatar_url": "https://avatars.githubusercontent.com/u/6698785?v=4",
6+
"gravatar_id": "",
7+
"url": "https://api.github.com/users/t0m4uk1991",
8+
"html_url": "https://github.com/t0m4uk1991",
9+
"followers_url": "https://api.github.com/users/t0m4uk1991/followers",
10+
"following_url": "https://api.github.com/users/t0m4uk1991/following{/other_user}",
11+
"gists_url": "https://api.github.com/users/t0m4uk1991/gists{/gist_id}",
12+
"starred_url": "https://api.github.com/users/t0m4uk1991/starred{/owner}{/repo}",
13+
"subscriptions_url": "https://api.github.com/users/t0m4uk1991/subscriptions",
14+
"organizations_url": "https://api.github.com/users/t0m4uk1991/orgs",
15+
"repos_url": "https://api.github.com/users/t0m4uk1991/repos",
16+
"events_url": "https://api.github.com/users/t0m4uk1991/events{/privacy}",
17+
"received_events_url": "https://api.github.com/users/t0m4uk1991/received_events",
18+
"type": "User",
19+
"site_admin": false,
20+
"name": null,
21+
"company": null,
22+
"blog": "https://t0m4uk1991.github.io",
23+
"location": "Ukraine",
24+
"email": "[email protected]",
25+
"hireable": true,
26+
"bio": null,
27+
"twitter_username": null,
28+
"public_repos": 14,
29+
"public_gists": 10,
30+
"followers": 2,
31+
"following": 2,
32+
"created_at": "2014-02-16T20:43:03Z",
33+
"updated_at": "2021-06-21T14:53:32Z"
34+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"total_count": 1,
3+
"installations": [
4+
{
5+
"id": 17761138,
6+
"account": {
7+
"login": "t0m4uk1991",
8+
"id": 6698785,
9+
"node_id": "MDQ6VXNlcjY2OTg3ODU=",
10+
"avatar_url": "https://avatars.githubusercontent.com/u/6698785?v=4",
11+
"gravatar_id": "",
12+
"url": "https://api.github.com/users/t0m4uk1991",
13+
"html_url": "https://github.com/t0m4uk1991",
14+
"followers_url": "https://api.github.com/users/t0m4uk1991/followers",
15+
"following_url": "https://api.github.com/users/t0m4uk1991/following{/other_user}",
16+
"gists_url": "https://api.github.com/users/t0m4uk1991/gists{/gist_id}",
17+
"starred_url": "https://api.github.com/users/t0m4uk1991/starred{/owner}{/repo}",
18+
"subscriptions_url": "https://api.github.com/users/t0m4uk1991/subscriptions",
19+
"organizations_url": "https://api.github.com/users/t0m4uk1991/orgs",
20+
"repos_url": "https://api.github.com/users/t0m4uk1991/repos",
21+
"events_url": "https://api.github.com/users/t0m4uk1991/events{/privacy}",
22+
"received_events_url": "https://api.github.com/users/t0m4uk1991/received_events",
23+
"type": "User",
24+
"site_admin": false
25+
},
26+
"repository_selection": "selected",
27+
"access_tokens_url": "https://api.github.com/app/installations/17761138/access_tokens",
28+
"repositories_url": "https://api.github.com/installation/repositories",
29+
"html_url": "https://github.com/settings/installations/17761138",
30+
"app_id": 122478,
31+
"app_slug": "hub4j-github-api-test",
32+
"target_id": 6698785,
33+
"target_type": "User",
34+
"permissions": {
35+
"metadata": "read",
36+
"administration": "read"
37+
},
38+
"events": [],
39+
"created_at": "2021-06-21T17:39:33.000+03:00",
40+
"updated_at": "2021-06-21T17:39:33.000+03:00",
41+
"single_file_name": null,
42+
"has_multiple_single_files": false,
43+
"single_file_paths": [],
44+
"suspended_by": null,
45+
"suspended_at": null
46+
}
47+
]
48+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
{
2+
"id": "04c78e0b-2ca2-4f06-b281-956eaba032bd",
3+
"name": "user",
4+
"request": {
5+
"url": "/user",
6+
"method": "GET",
7+
"headers": {
8+
"Accept": {
9+
"equalTo": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2"
10+
}
11+
}
12+
},
13+
"response": {
14+
"status": 200,
15+
"bodyFileName": "user-1.json",
16+
"headers": {
17+
"Server": "GitHub.com",
18+
"Date": "Mon, 21 Jun 2021 20:51:32 GMT",
19+
"Content-Type": "application/json; charset=utf-8",
20+
"Cache-Control": "private, max-age=60, s-maxage=60",
21+
"Vary": [
22+
"Accept, Authorization, Cookie, X-GitHub-OTP",
23+
"Accept-Encoding, Accept, X-Requested-With"
24+
],
25+
"ETag": "W/\"e9e4780f1b19e9323e73a0f5690bf7b59ee956f536ee5a303eb8657423123051\"",
26+
"Last-Modified": "Mon, 21 Jun 2021 14:53:32 GMT",
27+
"X-OAuth-Scopes": "",
28+
"X-Accepted-OAuth-Scopes": "",
29+
"x-oauth-client-id": "Iv1.d1d44ef7894694c0",
30+
"X-GitHub-Media-Type": "unknown, github.v3",
31+
"X-RateLimit-Limit": "5000",
32+
"X-RateLimit-Remaining": "4999",
33+
"X-RateLimit-Reset": "1624312292",
34+
"X-RateLimit-Used": "1",
35+
"X-RateLimit-Resource": "core",
36+
"Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload",
37+
"X-Frame-Options": "deny",
38+
"X-Content-Type-Options": "nosniff",
39+
"X-XSS-Protection": "0",
40+
"Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin",
41+
"Content-Security-Policy": "default-src 'none'",
42+
"X-GitHub-Request-Id": "2B69:2FF5:2E0782:302E02:60D0FBD4"
43+
}
44+
},
45+
"uuid": "04c78e0b-2ca2-4f06-b281-956eaba032bd",
46+
"persistent": true,
47+
"scenarioName": "scenario-1-user",
48+
"requiredScenarioState": "Started",
49+
"newScenarioState": "scenario-1-user-2",
50+
"insertionIndex": 1
51+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"id": "c209281c-5bd1-405a-9dc7-34227ec4d5ae",
3+
"name": "user",
4+
"request": {
5+
"url": "/user",
6+
"method": "GET",
7+
"headers": {
8+
"Accept": {
9+
"equalTo": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2"
10+
}
11+
}
12+
},
13+
"response": {
14+
"status": 200,
15+
"bodyFileName": "user-2.json",
16+
"headers": {
17+
"Server": "GitHub.com",
18+
"Date": "Mon, 21 Jun 2021 20:51:33 GMT",
19+
"Content-Type": "application/json; charset=utf-8",
20+
"Cache-Control": "private, max-age=60, s-maxage=60",
21+
"Vary": [
22+
"Accept, Authorization, Cookie, X-GitHub-OTP",
23+
"Accept-Encoding, Accept, X-Requested-With"
24+
],
25+
"ETag": "W/\"e9e4780f1b19e9323e73a0f5690bf7b59ee956f536ee5a303eb8657423123051\"",
26+
"Last-Modified": "Mon, 21 Jun 2021 14:53:32 GMT",
27+
"X-OAuth-Scopes": "",
28+
"X-Accepted-OAuth-Scopes": "",
29+
"x-oauth-client-id": "Iv1.d1d44ef7894694c0",
30+
"X-GitHub-Media-Type": "unknown, github.v3",
31+
"X-RateLimit-Limit": "5000",
32+
"X-RateLimit-Remaining": "4997",
33+
"X-RateLimit-Reset": "1624312292",
34+
"X-RateLimit-Used": "3",
35+
"X-RateLimit-Resource": "core",
36+
"Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload",
37+
"X-Frame-Options": "deny",
38+
"X-Content-Type-Options": "nosniff",
39+
"X-XSS-Protection": "0",
40+
"Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin",
41+
"Content-Security-Policy": "default-src 'none'",
42+
"X-GitHub-Request-Id": "04D3:4B1B:1F3F8F:200584:60D0FBD4"
43+
}
44+
},
45+
"uuid": "c209281c-5bd1-405a-9dc7-34227ec4d5ae",
46+
"persistent": true,
47+
"scenarioName": "scenario-1-user",
48+
"requiredScenarioState": "scenario-1-user-2",
49+
"insertionIndex": 2
50+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"id": "179e0b84-8037-4d0b-9833-c8ef1b226592",
3+
"name": "user_installations",
4+
"request": {
5+
"url": "/user/installations",
6+
"method": "GET",
7+
"headers": {
8+
"Accept": {
9+
"equalTo": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2"
10+
}
11+
}
12+
},
13+
"response": {
14+
"status": 200,
15+
"bodyFileName": "user_installations-3.json",
16+
"headers": {
17+
"Server": "GitHub.com",
18+
"Date": "Mon, 21 Jun 2021 20:51:33 GMT",
19+
"Content-Type": "application/json; charset=utf-8",
20+
"Cache-Control": "private, max-age=60, s-maxage=60",
21+
"Vary": [
22+
"Accept, Authorization, Cookie, X-GitHub-OTP",
23+
"Accept-Encoding, Accept, X-Requested-With"
24+
],
25+
"ETag": "W/\"05762b67c1a69e46ee710171fdb32872b44904cc7c68a7617c134a6c5eee2b13\"",
26+
"X-OAuth-Scopes": "",
27+
"X-Accepted-OAuth-Scopes": "",
28+
"x-oauth-client-id": "Iv1.d1d44ef7894694c0",
29+
"X-GitHub-Media-Type": "unknown, github.v3",
30+
"X-RateLimit-Limit": "5000",
31+
"X-RateLimit-Remaining": "4996",
32+
"X-RateLimit-Reset": "1624312292",
33+
"X-RateLimit-Used": "4",
34+
"X-RateLimit-Resource": "core",
35+
"Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload",
36+
"X-Frame-Options": "deny",
37+
"X-Content-Type-Options": "nosniff",
38+
"X-XSS-Protection": "0",
39+
"Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin",
40+
"Content-Security-Policy": "default-src 'none'",
41+
"X-GitHub-Request-Id": "0A50:20B4:B38D2B:B6B016:60D0FBD5"
42+
}
43+
},
44+
"uuid": "179e0b84-8037-4d0b-9833-c8ef1b226592",
45+
"persistent": true,
46+
"insertionIndex": 3
47+
}

0 commit comments

Comments
 (0)