diff --git a/src/main/java/com/cdancy/bitbucket/rest/domain/repository/Group.java b/src/main/java/com/cdancy/bitbucket/rest/domain/repository/Group.java new file mode 100644 index 00000000..7c51ad58 --- /dev/null +++ b/src/main/java/com/cdancy/bitbucket/rest/domain/repository/Group.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.cdancy.bitbucket.rest.domain.repository; + +import com.google.auto.value.AutoValue; +import org.jclouds.json.SerializedNames; + +@AutoValue +public abstract class Group { + + public abstract String name(); + + @SerializedNames({"name"}) + public static Group create(String name) { + return new AutoValue_Group(name); + } +} diff --git a/src/main/java/com/cdancy/bitbucket/rest/domain/repository/Permissions.java b/src/main/java/com/cdancy/bitbucket/rest/domain/repository/Permissions.java new file mode 100644 index 00000000..b0a44ddb --- /dev/null +++ b/src/main/java/com/cdancy/bitbucket/rest/domain/repository/Permissions.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.cdancy.bitbucket.rest.domain.repository; + +import com.cdancy.bitbucket.rest.domain.pullrequest.User; +import com.google.auto.value.AutoValue; +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.json.SerializedNames; + +@AutoValue +public abstract class Permissions { + + public enum PermissionsType { + REPO_ADMIN, + REPO_WRITE, + REPO_READ + } + + @Nullable + public abstract User user(); + + @Nullable + public abstract Group group(); + + public abstract PermissionsType permission(); + + @SerializedNames({"user", "group", "permission"}) + public static Permissions create(User user, Group group, PermissionsType type) { + return new AutoValue_Permissions(user, group, type); + } +} diff --git a/src/main/java/com/cdancy/bitbucket/rest/domain/repository/PermissionsPage.java b/src/main/java/com/cdancy/bitbucket/rest/domain/repository/PermissionsPage.java new file mode 100644 index 00000000..749d9731 --- /dev/null +++ b/src/main/java/com/cdancy/bitbucket/rest/domain/repository/PermissionsPage.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.cdancy.bitbucket.rest.domain.repository; + +import com.cdancy.bitbucket.rest.domain.common.Error; +import com.cdancy.bitbucket.rest.domain.common.ErrorsHolder; +import com.cdancy.bitbucket.rest.domain.common.Page; +import com.cdancy.bitbucket.rest.utils.Utils; +import com.google.auto.value.AutoValue; +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.json.SerializedNames; + +import java.util.List; + +@AutoValue +public abstract class PermissionsPage implements Page, ErrorsHolder { + + @SerializedNames({ "start", "limit", "size", "nextPageStart", "isLastPage", "values", "errors" }) + public static PermissionsPage create(int start, int limit, int size, int nextPageStart, boolean isLastPage, + @Nullable List values, @Nullable List errors) { + return new AutoValue_PermissionsPage(start, limit, size, nextPageStart, isLastPage, + Utils.nullToEmpty(values), Utils.nullToEmpty(errors)); + } +} diff --git a/src/main/java/com/cdancy/bitbucket/rest/fallbacks/BitbucketFallbacks.java b/src/main/java/com/cdancy/bitbucket/rest/fallbacks/BitbucketFallbacks.java index beb6a077..488e8fae 100644 --- a/src/main/java/com/cdancy/bitbucket/rest/fallbacks/BitbucketFallbacks.java +++ b/src/main/java/com/cdancy/bitbucket/rest/fallbacks/BitbucketFallbacks.java @@ -43,6 +43,7 @@ import com.cdancy.bitbucket.rest.domain.pullrequest.ChangePage; import com.cdancy.bitbucket.rest.domain.pullrequest.CommentPage; import com.cdancy.bitbucket.rest.domain.pullrequest.MergeStatus; +import com.cdancy.bitbucket.rest.domain.repository.PermissionsPage; import com.cdancy.bitbucket.rest.domain.repository.Repository; import com.cdancy.bitbucket.rest.domain.tags.Tag; import org.jclouds.Fallback; @@ -195,6 +196,15 @@ public Object createOrPropagate(Throwable throwable) throws Exception { } } + public static final class PermissionsPageOnError implements Fallback { + public Object createOrPropagate(Throwable throwable) throws Exception { + if (checkNotNull(throwable, "throwable") != null) { + return createPermissionsPageFromErrors(getErrors(throwable.getMessage())); + } + throw propagate(throwable); + } + } + public static final class ProjectOnError implements Fallback { public Object createOrPropagate(Throwable throwable) throws Exception { if (checkNotNull(throwable, "throwable") != null) { @@ -323,6 +333,10 @@ public static RepositoryPage createRepositoryPageFromErrors(List errors) return RepositoryPage.create(-1, -1, -1, -1, true, null, errors); } + public static PermissionsPage createPermissionsPageFromErrors(List errors) { + return PermissionsPage.create(-1, -1, -1, -1, true, null, errors); + } + public static Project createProjectFromErrors(List errors) { return Project.create(null, -1, null, null, false, null, null, errors); } diff --git a/src/main/java/com/cdancy/bitbucket/rest/features/RepositoryApi.java b/src/main/java/com/cdancy/bitbucket/rest/features/RepositoryApi.java index e0f22ecd..3dbbb17d 100644 --- a/src/main/java/com/cdancy/bitbucket/rest/features/RepositoryApi.java +++ b/src/main/java/com/cdancy/bitbucket/rest/features/RepositoryApi.java @@ -29,6 +29,7 @@ import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; +import com.cdancy.bitbucket.rest.domain.repository.PermissionsPage; import org.jclouds.javax.annotation.Nullable; import org.jclouds.rest.annotations.BinderParam; import org.jclouds.rest.annotations.Fallback; @@ -82,4 +83,15 @@ boolean delete(@PathParam("project") String project, RepositoryPage list(@PathParam("project") String project, @Nullable @QueryParam("start") Integer start, @Nullable @QueryParam("limit") Integer limit); + + @Named("repository:list-Permissions-Group") + @Documentation({"https://developer.atlassian.com/static/rest/bitbucket-server/5.0.0/bitbucket-rest.html#idm45659054969200"}) + @Consumes(MediaType.APPLICATION_JSON) + @Path("/{project}/repos/{repo}/permissions/groups") + @Fallback(BitbucketFallbacks.PermissionsPageOnError.class) + @GET + PermissionsPage listPermissionsGroup(@PathParam("project") String project, + @PathParam("repo") String repo, + @Nullable @QueryParam("start") Integer start, + @Nullable @QueryParam("limit") Integer limit); } diff --git a/src/test/java/com/cdancy/bitbucket/rest/features/RepositoryApiLiveTest.java b/src/test/java/com/cdancy/bitbucket/rest/features/RepositoryApiLiveTest.java index 9d267970..2ace0197 100644 --- a/src/test/java/com/cdancy/bitbucket/rest/features/RepositoryApiLiveTest.java +++ b/src/test/java/com/cdancy/bitbucket/rest/features/RepositoryApiLiveTest.java @@ -21,6 +21,7 @@ import java.util.List; +import com.cdancy.bitbucket.rest.domain.repository.PermissionsPage; import org.assertj.core.api.Condition; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; @@ -112,6 +113,12 @@ public void testCreateRepositoryWithIllegalName() { assertThat(repository.errors().isEmpty()).isFalse(); } + @Test(dependsOnMethods = "testGetRepository") + public void testListPermissionGroup() { + PermissionsPage permissionsPage = api().listPermissionsGroup(projectKey, repoKey, 0, 100); + assertThat(permissionsPage.values()).isEmpty(); + } + @AfterClass public void fin() { boolean success = api.projectApi().delete(projectKey); diff --git a/src/test/java/com/cdancy/bitbucket/rest/features/RepositoryApiMockTest.java b/src/test/java/com/cdancy/bitbucket/rest/features/RepositoryApiMockTest.java index e3da7ba9..19e6bdac 100644 --- a/src/test/java/com/cdancy/bitbucket/rest/features/RepositoryApiMockTest.java +++ b/src/test/java/com/cdancy/bitbucket/rest/features/RepositoryApiMockTest.java @@ -21,6 +21,7 @@ import java.util.Map; +import com.cdancy.bitbucket.rest.domain.repository.PermissionsPage; import org.testng.annotations.Test; import com.cdancy.bitbucket.rest.BitbucketApi; @@ -220,7 +221,7 @@ public void testGetRepositoryListWithLimit() throws Exception { server.shutdown(); } } - + public void testGetRepositoryListNonExistent() throws Exception { MockWebServer server = mockEtcdJavaWebServer(); @@ -238,4 +239,52 @@ public void testGetRepositoryListNonExistent() throws Exception { server.shutdown(); } } + + public void testListPermissionGroup() throws Exception { + MockWebServer server = mockEtcdJavaWebServer(); + + server.enqueue(new MockResponse().setBody(payloadFromResource("/repository-permission-group.json")).setResponseCode(200)); + BitbucketApi baseApi = api(server.getUrl("/")); + RepositoryApi api = baseApi.repositoryApi(); + try { + String projectKey = "PRJ1"; + String repoKey = "1234"; + PermissionsPage permissionsPage = api.listPermissionsGroup(projectKey, repoKey, 0, 100); + assertThat(permissionsPage).isNotNull(); + assertThat(permissionsPage.errors()).isEmpty(); + assertThat(permissionsPage.size() == 1).isTrue(); + assertThat(permissionsPage.values().get(0).user() == null).isTrue(); + assertThat(permissionsPage.values().get(0).group().name().equals("test12345")).isTrue(); + + Map queryParams = ImmutableMap.of("limit", 100, "start", 0); + assertSent(server, "GET", "/rest/api/" + BitbucketApiMetadata.API_VERSION + + "/projects/" + projectKey + "/repos/" + repoKey + "/permissions/groups", queryParams); + } finally { + baseApi.close(); + server.shutdown(); + } + } + + public void testListPermissionGroupOnError() throws Exception { + MockWebServer server = mockEtcdJavaWebServer(); + + server.enqueue(new MockResponse().setBody(payloadFromResource("/repository-permission-group-error.json")).setResponseCode(404)); + BitbucketApi baseApi = api(server.getUrl("/")); + RepositoryApi api = baseApi.repositoryApi(); + try { + String projectKey = "PRJ1"; + String repoKey = "1234"; + PermissionsPage permissionsPage = api.listPermissionsGroup(projectKey, repoKey, 0, 100); + assertThat(permissionsPage).isNotNull(); + assertThat(permissionsPage.values()).isEmpty(); + assertThat(permissionsPage.errors()).isNotEmpty(); + + Map queryParams = ImmutableMap.of("limit", 100, "start", 0); + assertSent(server, "GET", "/rest/api/" + BitbucketApiMetadata.API_VERSION + + "/projects/" + projectKey + "/repos/" + repoKey + "/permissions/groups", queryParams); + } finally { + baseApi.close(); + server.shutdown(); + } + } } diff --git a/src/test/resources/repository-permission-group-error.json b/src/test/resources/repository-permission-group-error.json new file mode 100644 index 00000000..112bc94d --- /dev/null +++ b/src/test/resources/repository-permission-group-error.json @@ -0,0 +1,9 @@ +{ + "errors": [ + { + "context": null, + "exceptionName": "com.atlassian.bitbucket.project.NoSuchProjectException", + "message": "Project test123 does not exist." + } + ] +} \ No newline at end of file diff --git a/src/test/resources/repository-permission-group.json b/src/test/resources/repository-permission-group.json new file mode 100644 index 00000000..f60102ab --- /dev/null +++ b/src/test/resources/repository-permission-group.json @@ -0,0 +1,14 @@ +{ + "isLastPage": true, + "limit": 25, + "size": 1, + "start": 0, + "values": [ + { + "group": { + "name": "test12345" + }, + "permission": "REPO_WRITE" + } + ] +} \ No newline at end of file