From ccb42d32499ee1fcfe7dc9711f5e82eb5a9176b2 Mon Sep 17 00:00:00 2001 From: Jesse Glick Date: Fri, 16 Dec 2016 18:02:28 -0500 Subject: [PATCH 1/3] [JENKINS-36240] Added GHRepository.getPermission(String). --- .../java/org/kohsuke/github/GHPermission.java | 53 +++++++++++++++++++ .../java/org/kohsuke/github/GHRepository.java | 12 +++++ .../java/org/kohsuke/github/Requester.java | 11 ++-- .../org/kohsuke/github/RepositoryTest.java | 25 +++++++++ 4 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/GHPermission.java diff --git a/src/main/java/org/kohsuke/github/GHPermission.java b/src/main/java/org/kohsuke/github/GHPermission.java new file mode 100644 index 000000000..8bc28c719 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHPermission.java @@ -0,0 +1,53 @@ +/* + * The MIT License + * + * Copyright 2016 CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.kohsuke.github; + +/** + * Permission for a user in a repository. + * @see API + */ +public class GHPermission { + + private String permission; + private GHUser user; + + /** + * @return one of {@code admin}, {@code write}, {@code read}, or {@code none} + */ + public String getPermission() { + return permission; + } + + public GHUser getUser() { + return user; + } + + void wrapUp(GitHub root) { + if (user != null) { + user.root = root; + } + } + +} diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index f34ea8500..d3af91a21 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -480,6 +480,18 @@ public class GHRepository extends GHObject { return r; } + /** + * Obtain permission for a given user in this repository. + * @param user a {@link GHUser#getLogin} + * @throws FileNotFoundException under some conditions (e.g., private repo you can see but are not an admin of); treat as unknown + * @throws HttpException with a 403 under other conditions (e.g., public repo you have no special rights to); treat as unknown + */ + public GHPermission getPermission(String user) throws IOException { + GHPermission perm = root.retrieve().withHeader("Accept", "application/vnd.github.korra-preview").to(getApiTailUrl("collaborators/" + user + "/permission"), GHPermission.class); + perm.wrapUp(root); + return perm; + } + /** * If this repository belongs to an organization, return a set of teams. */ diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 70c48940c..2eb3f282f 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -598,11 +598,16 @@ class Requester { InputStream es = wrapStream(uc.getErrorStream()); try { if (es!=null) { + String error = IOUtils.toString(es, "UTF-8"); if (e instanceof FileNotFoundException) { // pass through 404 Not Found to allow the caller to handle it intelligently - throw (IOException) new FileNotFoundException(IOUtils.toString(es, "UTF-8")).initCause(e); - } else - throw (IOException) new IOException(IOUtils.toString(es, "UTF-8")).initCause(e); + throw (IOException) new FileNotFoundException(error).initCause(e); + } else if (e instanceof HttpException) { + HttpException http = (HttpException) e; + throw (IOException) new HttpException(error, http.getResponseCode(), http.getResponseMessage(), http.getUrl(), e); + } else { + throw (IOException) new IOException(error).initCause(e); + } } else throw e; } finally { diff --git a/src/test/java/org/kohsuke/github/RepositoryTest.java b/src/test/java/org/kohsuke/github/RepositoryTest.java index dae2892a4..21625fbf8 100644 --- a/src/test/java/org/kohsuke/github/RepositoryTest.java +++ b/src/test/java/org/kohsuke/github/RepositoryTest.java @@ -1,9 +1,11 @@ package org.kohsuke.github; +import java.io.FileNotFoundException; import org.junit.Test; import org.kohsuke.github.GHRepository.Contributor; import java.io.IOException; +import org.junit.Ignore; /** * @author Kohsuke Kawaguchi @@ -40,6 +42,29 @@ public class RepositoryTest extends AbstractGitHubApiTestBase { assertTrue(kohsuke); } + @Ignore("depends on who runs this test whether it can pass or not") + @Test + public void getPermission() throws Exception { + GHRepository r = gitHub.getOrganization("cloudbeers").getRepository("yolo"); + assertEquals("admin", r.getPermission("jglick").getPermission()); + assertEquals("read", r.getPermission("dude").getPermission()); + r = gitHub.getOrganization("cloudbees").getRepository("private-repo-not-writable-by-me"); + try { + r.getPermission("jglick"); + fail(); + } catch (FileNotFoundException x) { + x.printStackTrace(); // good + } + r = gitHub.getOrganization("apache").getRepository("groovy"); + try { + r.getPermission("jglick"); + fail(); + } catch (HttpException x) { + x.printStackTrace(); // good + assertEquals(403, x.getResponseCode()); + } + } + private GHRepository getRepository() throws IOException { return gitHub.getOrganization("github-api-test-org").getRepository("jenkins"); } From 6bfeb54f3c5116e241ad8ddd130667cd398bf459 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 9 Jan 2017 16:14:30 -0800 Subject: [PATCH 2/3] Just exposing permission type enum until there's more to this relation than one property --- src/main/java/org/kohsuke/github/GHPermission.java | 8 +++++++- .../java/org/kohsuke/github/GHPermissionType.java | 11 +++++++++++ src/main/java/org/kohsuke/github/GHRepository.java | 13 +++++++++++-- 3 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/GHPermissionType.java diff --git a/src/main/java/org/kohsuke/github/GHPermission.java b/src/main/java/org/kohsuke/github/GHPermission.java index 8bc28c719..51a808dfc 100644 --- a/src/main/java/org/kohsuke/github/GHPermission.java +++ b/src/main/java/org/kohsuke/github/GHPermission.java @@ -24,11 +24,13 @@ package org.kohsuke.github; +import java.util.Locale; + /** * Permission for a user in a repository. * @see API */ -public class GHPermission { +/*package*/ class GHPermission { private String permission; private GHUser user; @@ -40,6 +42,10 @@ public class GHPermission { return permission; } + public GHPermissionType getPermissionType() { + return Enum.valueOf(GHPermissionType.class, permission.toUpperCase(Locale.ENGLISH)); + } + public GHUser getUser() { return user; } diff --git a/src/main/java/org/kohsuke/github/GHPermissionType.java b/src/main/java/org/kohsuke/github/GHPermissionType.java new file mode 100644 index 000000000..d3e2bd090 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHPermissionType.java @@ -0,0 +1,11 @@ +package org.kohsuke.github; + +/** + * @author Kohsuke Kawaguchi + */ +public enum GHPermissionType { + ADMIN, + WRITE, + READ, + NONE +} diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index d3af91a21..cca1d7a8e 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -486,10 +486,19 @@ public class GHRepository extends GHObject { * @throws FileNotFoundException under some conditions (e.g., private repo you can see but are not an admin of); treat as unknown * @throws HttpException with a 403 under other conditions (e.g., public repo you have no special rights to); treat as unknown */ - public GHPermission getPermission(String user) throws IOException { + public GHPermissionType getPermission(String user) throws IOException { GHPermission perm = root.retrieve().withHeader("Accept", "application/vnd.github.korra-preview").to(getApiTailUrl("collaborators/" + user + "/permission"), GHPermission.class); perm.wrapUp(root); - return perm; + return perm.getPermissionType(); + } + + /** + * Obtain permission for a given user in this repository. + * @throws FileNotFoundException under some conditions (e.g., private repo you can see but are not an admin of); treat as unknown + * @throws HttpException with a 403 under other conditions (e.g., public repo you have no special rights to); treat as unknown + */ + public GHPermissionType getPermission(GHUser u) throws IOException { + return getPermission(u.getLogin()); } /** From d1c900a6206ddbeb78616a92841b0667a08a8a11 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 9 Jan 2017 16:18:40 -0800 Subject: [PATCH 3/3] Marking the fact that these APIs are still in preview and subject to change --- src/main/java/org/kohsuke/github/GHRepository.java | 4 +++- src/main/java/org/kohsuke/github/Previews.java | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index cca1d7a8e..3235fea3c 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -486,8 +486,9 @@ public class GHRepository extends GHObject { * @throws FileNotFoundException under some conditions (e.g., private repo you can see but are not an admin of); treat as unknown * @throws HttpException with a 403 under other conditions (e.g., public repo you have no special rights to); treat as unknown */ + @Deprecated @Preview public GHPermissionType getPermission(String user) throws IOException { - GHPermission perm = root.retrieve().withHeader("Accept", "application/vnd.github.korra-preview").to(getApiTailUrl("collaborators/" + user + "/permission"), GHPermission.class); + GHPermission perm = root.retrieve().withPreview(KORRA).to(getApiTailUrl("collaborators/" + user + "/permission"), GHPermission.class); perm.wrapUp(root); return perm.getPermissionType(); } @@ -497,6 +498,7 @@ public class GHRepository extends GHObject { * @throws FileNotFoundException under some conditions (e.g., private repo you can see but are not an admin of); treat as unknown * @throws HttpException with a 403 under other conditions (e.g., public repo you have no special rights to); treat as unknown */ + @Deprecated @Preview public GHPermissionType getPermission(GHUser u) throws IOException { return getPermission(u.getLogin()); } diff --git a/src/main/java/org/kohsuke/github/Previews.java b/src/main/java/org/kohsuke/github/Previews.java index f95a28b42..238b062b8 100644 --- a/src/main/java/org/kohsuke/github/Previews.java +++ b/src/main/java/org/kohsuke/github/Previews.java @@ -7,4 +7,5 @@ package org.kohsuke.github; static final String LOKI = "application/vnd.github.loki-preview+json"; static final String DRAX = "application/vnd.github.drax-preview+json"; static final String SQUIRREL_GIRL = "application/vnd.github.squirrel-girl-preview"; + static final String KORRA = "application/vnd.github.korra-preview"; }