create endpoint for branch deletion

This commit is contained in:
Eduard Heimbuch
2020-11-10 15:35:32 +01:00
parent a6ec38ec27
commit 2fab771740
2 changed files with 108 additions and 2 deletions

View File

@@ -47,6 +47,7 @@ import sonia.scm.web.VndMediaType;
import javax.inject.Inject;
import javax.validation.Valid;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
@@ -57,6 +58,7 @@ import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.net.URI;
import java.util.Optional;
import static sonia.scm.AlreadyExistsException.alreadyExists;
import static sonia.scm.ContextEntry.ContextBuilder.entity;
@@ -308,4 +310,50 @@ public class BranchRootResource {
return Response.status(Response.Status.BAD_REQUEST).build();
}
}
/**
* Deletes a branch.
*
* <strong>Note:</strong> This method requires "repository" privilege.
*
* @param branch the name of the branch to delete.
*/
@DELETE
@Path("{branch}")
@Operation(summary = "Delete branch", description = "Deletes the given branch.", tags = "Repository")
@ApiResponse(responseCode = "204", description = "delete success or nothing to delete")
@ApiResponse(responseCode = "400", description = "the default branch cannot be deleted")
@ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials")
@ApiResponse(responseCode = "403", description = "not authorized, the current user has no privileges to modify the repository")
@ApiResponse(
responseCode = "500",
description = "internal server error",
content = @Content(
mediaType = VndMediaType.ERROR_TYPE,
schema = @Schema(implementation = ErrorDto.class)
)
)
public Response delete(@PathParam("namespace") String namespace,
@PathParam("name") String name,
@PathParam("branch") String branch) {
try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) {
RepositoryPermissions.modify(repositoryService.getRepository()).check();
Optional<Branch> branchToBeDeleted = repositoryService.getBranchesCommand().getBranches().getBranches().stream()
.filter(b -> b.getName().equalsIgnoreCase(branch))
.findFirst();
if (branchToBeDeleted.isPresent()) {
if (branchToBeDeleted.get().isDefaultBranch()) {
return Response.status(400).build();
} else {
repositoryService.getBranchCommand().delete(branch);
}
}
} catch (IOException e) {
return Response.serverError().build();
}
return Response.noContent().build();
}
}

View File

@@ -24,8 +24,8 @@
package sonia.scm.api.v2.resources;
import com.google.inject.util.Providers;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.support.SubjectThreadState;
import org.apache.shiro.util.ThreadContext;
@@ -56,11 +56,12 @@ import sonia.scm.web.RestDispatcher;
import sonia.scm.web.VndMediaType;
import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.time.Instant;
import java.util.Date;
import java.util.List;
import java.util.Set;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
@@ -68,6 +69,7 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@@ -271,6 +273,62 @@ public class BranchRootResourceTest extends RepositoryTestBase {
verify(branchCommandBuilder, never()).branch(anyString());
}
@Test
public void shouldNotDeleteBranchIfNotPermitted() throws IOException, URISyntaxException {
doThrow(AuthorizationException.class).when(subject).checkPermission("repository:modify:repoId");
when(branchesCommandBuilder.getBranches()).thenReturn(new Branches(Branch.normalBranch("suspicious", "0")));
MockHttpRequest request = MockHttpRequest
.delete("/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + "space/repo/branches/suspicious");
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
assertEquals(403, response.getStatus());
verify(branchCommandBuilder, never()).delete("suspicious");
}
@Test
public void shouldNotDeleteDefaultBranch() throws IOException, URISyntaxException {
when(branchesCommandBuilder.getBranches()).thenReturn(new Branches(Branch.defaultBranch("main", "0")));
MockHttpRequest request = MockHttpRequest
.delete("/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + "space/repo/branches/main");
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
assertEquals(400, response.getStatus());
}
@Test
public void shouldDeleteBranch() throws IOException, URISyntaxException {
when(branchesCommandBuilder.getBranches()).thenReturn(new Branches(Branch.normalBranch("suspicious", "0")));
MockHttpRequest request = MockHttpRequest
.delete("/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + "space/repo/branches/suspicious");
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
assertEquals(204, response.getStatus());
verify(branchCommandBuilder).delete("suspicious");
}
@Test
public void shouldAnswer204IfNothingWasDeleted() throws IOException, URISyntaxException {
when(branchesCommandBuilder.getBranches()).thenReturn(new Branches());
MockHttpRequest request = MockHttpRequest
.delete("/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + "space/repo/branches/suspicious");
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
assertEquals(204, response.getStatus());
verify(branchCommandBuilder, never()).delete(anyString());
}
private Branch createBranch(String existing_branch) {
return Branch.normalBranch(existing_branch, REVISION);
}