Create resources for namespaces

This commit is contained in:
René Pfeuffer
2020-09-03 10:56:38 +02:00
parent 4d09f71d40
commit 4457cd08b8
15 changed files with 567 additions and 15 deletions

View File

@@ -24,15 +24,11 @@
package sonia.scm.repository;
//~--- non-JDK imports --------------------------------------------------------
import sonia.scm.TypeManager;
import java.io.IOException;
import java.util.Collection;
//~--- JDK imports ------------------------------------------------------------
/**
* The central class for managing {@link Repository} objects.
* This class is a singleton and is available via injection.
@@ -49,7 +45,7 @@ public interface RepositoryManager
* @param event hook event
* @since 2.0.0
*/
public void fireHookEvent(RepositoryHookEvent event);
void fireHookEvent(RepositoryHookEvent event);
/**
* Imports an existing {@link Repository}.
@@ -58,9 +54,7 @@ public interface RepositoryManager
* @param repository {@link Repository} to import
* @throws IOException
*/
public void importRepository(Repository repository) throws IOException;
//~--- get methods ----------------------------------------------------------
void importRepository(Repository repository) throws IOException;
/**
* Returns a {@link Repository} by its namespace and name or
@@ -70,14 +64,14 @@ public interface RepositoryManager
* @return {@link Repository} by its namespace and name or null
* if the {@link Repository} could not be found
*/
public Repository get(NamespaceAndName namespaceAndName);
Repository get(NamespaceAndName namespaceAndName);
/**
* Returns all configured repository types.
*
* @return all configured repository types
*/
public Collection<RepositoryType> getConfiguredTypes();
Collection<RepositoryType> getConfiguredTypes();
/**
* Returns a {@link RepositoryHandler} by the given type (hg, git, svn ...).
@@ -86,7 +80,7 @@ public interface RepositoryManager
* @return {@link RepositoryHandler} by the given type
*/
@Override
public RepositoryHandler getHandler(String type);
RepositoryHandler getHandler(String type);
/**
* @param repository the repository {@link Repository}
@@ -94,5 +88,12 @@ public interface RepositoryManager
* @param newName the new repository name
* @return {@link Repository} the renamed repository
*/
public Repository rename(Repository repository, String newNameSpace, String newName);
Repository rename(Repository repository, String newNameSpace, String newName);
/**
* Returns all namespaces.
*
* @return all namespaces
*/
Collection<String> getAllNamespaces();
}

View File

@@ -131,6 +131,11 @@ public class RepositoryManagerDecorator
return decorated.rename(repository, newNamespace, newName);
}
@Override
public Collection<String> getAllNamespaces() {
return decorated.getAllNamespaces();
}
//~--- fields ---------------------------------------------------------------
/**

View File

@@ -44,6 +44,7 @@ public class VndMediaType {
public static final String GROUP = PREFIX + "group" + SUFFIX;
public static final String AUTOCOMPLETE = PREFIX + "autocomplete" + SUFFIX;
public static final String REPOSITORY = PREFIX + "repository" + SUFFIX;
public static final String NAMESPACE = PREFIX + "namespace" + SUFFIX;
public static final String REPOSITORY_PERMISSION = PREFIX + "repositoryPermission" + SUFFIX;
public static final String CHANGESET = PREFIX + "changeset" + SUFFIX;
public static final String CHANGESET_COLLECTION = PREFIX + "changesetCollection" + SUFFIX;
@@ -57,6 +58,7 @@ public class VndMediaType {
public static final String USER_COLLECTION = PREFIX + "userCollection" + SUFFIX;
public static final String GROUP_COLLECTION = PREFIX + "groupCollection" + SUFFIX;
public static final String REPOSITORY_COLLECTION = PREFIX + "repositoryCollection" + SUFFIX;
public static final String NAMESPACE_COLLECTION = PREFIX + "namespaceCollection" + SUFFIX;
public static final String BRANCH_COLLECTION = PREFIX + "branchCollection" + SUFFIX;
public static final String CONFIG = PREFIX + "config" + SUFFIX;
public static final String REPOSITORY_VERB_COLLECTION = PREFIX + "repositoryVerbCollection" + SUFFIX;

View File

@@ -0,0 +1,77 @@
/*
* MIT License
*
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
*
* 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 sonia.scm.api.v2.resources;
import de.otto.edison.hal.HalRepresentation;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.web.VndMediaType;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
public class NamespaceCollectionResource {
private final RepositoryManager manager;
private final NamespaceCollectionToDtoMapper repositoryCollectionToDtoMapper;
@Inject
public NamespaceCollectionResource(RepositoryManager manager, NamespaceCollectionToDtoMapper repositoryCollectionToDtoMapper) {
this.manager = manager;
this.repositoryCollectionToDtoMapper = repositoryCollectionToDtoMapper;
}
/**
* Returns all namespaces.
*/
@GET
@Path("")
@Produces(VndMediaType.NAMESPACE_COLLECTION)
@Operation(summary = "List of namespaces", description = "Returns all namespaces.", tags = "Namespace")
@ApiResponse(
responseCode = "200",
description = "success",
content = @Content(
mediaType = VndMediaType.NAMESPACE_COLLECTION,
schema = @Schema(implementation = CollectionDto.class)
)
)
@ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials")
@ApiResponse(
responseCode = "500",
description = "internal server error",
content = @Content(
mediaType = VndMediaType.ERROR_TYPE,
schema = @Schema(implementation = ErrorDto.class)
))
public HalRepresentation getAll() {
return repositoryCollectionToDtoMapper.map(manager.getAllNamespaces());
}
}

View File

@@ -0,0 +1,57 @@
/*
* MIT License
*
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
*
* 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 sonia.scm.api.v2.resources;
import de.otto.edison.hal.Embedded;
import de.otto.edison.hal.HalRepresentation;
import javax.inject.Inject;
import java.util.Collection;
import static de.otto.edison.hal.Embedded.embeddedBuilder;
import static de.otto.edison.hal.Links.linkingTo;
import static java.util.stream.Collectors.toList;
public class NamespaceCollectionToDtoMapper {
private final NamespaceToNamespaceDtoMapper namespaceMapper;
private final ResourceLinks links;
@Inject
public NamespaceCollectionToDtoMapper(NamespaceToNamespaceDtoMapper namespaceMapper, ResourceLinks links) {
this.namespaceMapper = namespaceMapper;
this.links = links;
}
public HalRepresentation map(Collection<String> namespaces) {
Embedded namespaceDtos = embeddedBuilder()
.with("namespaces", namespaces.stream().map(namespaceMapper::map).collect(toList()))
.build();
return new HalRepresentation(
linkingTo().self(links.namespaceCollection().self()).build(),
namespaceDtos
);
}
}

View File

@@ -0,0 +1,42 @@
/*
* MIT License
*
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
*
* 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 sonia.scm.api.v2.resources;
import de.otto.edison.hal.HalRepresentation;
import de.otto.edison.hal.Links;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class NamespaceDto extends HalRepresentation {
private String namespace;
public NamespaceDto(String namespace, Links links) {
super(links);
this.namespace = namespace;
}
}

View File

@@ -0,0 +1,100 @@
/*
* MIT License
*
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
*
* 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 sonia.scm.api.v2.resources;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.web.VndMediaType;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import static sonia.scm.ContextEntry.ContextBuilder.entity;
import static sonia.scm.NotFoundException.notFound;
public class NamespaceResource {
private final RepositoryManager manager;
private final NamespaceToNamespaceDtoMapper namespaceMapper;
@Inject
public NamespaceResource(RepositoryManager manager, NamespaceToNamespaceDtoMapper namespaceMapper) {
this.manager = manager;
this.namespaceMapper = namespaceMapper;
}
/**
* Returns a namespace.
*
* @param namespace the requested namespace
*/
@GET
@Path("")
@Produces(VndMediaType.NAMESPACE)
@Operation(summary = "Get single namespace", description = "Returns the namespace for the given name.", tags = "Namespace")
@ApiResponse(
responseCode = "200",
description = "success",
content = @Content(
mediaType = VndMediaType.NAMESPACE,
schema = @Schema(implementation = NamespaceDto.class)
)
)
@ApiResponse(
responseCode = "401",
description = "not authenticated / invalid credentials"
)
@ApiResponse(
responseCode = "404",
description = "not found, no namespace with the specified name available",
content = @Content(
mediaType = VndMediaType.ERROR_TYPE,
schema = @Schema(implementation = ErrorDto.class)
)
)
@ApiResponse(
responseCode = "500",
description = "internal server error",
content = @Content(
mediaType = VndMediaType.ERROR_TYPE,
schema = @Schema(implementation = ErrorDto.class)
)
)
public NamespaceDto get(@PathParam("namespace") String namespace) {
return manager.getAllNamespaces()
.stream()
.filter(n -> n.equals(namespace))
.map(namespaceMapper::map)
.findFirst()
.orElseThrow(() -> notFound(entity("Namespace", namespace)));
}
}

View File

@@ -0,0 +1,64 @@
/*
* MIT License
*
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
*
* 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 sonia.scm.api.v2.resources;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.tags.Tag;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.ws.rs.Path;
/**
* RESTful Web Service Resource to manage namespaces.
*/
@OpenAPIDefinition(
tags = {
@Tag(name = "Namespace", description = "Namespace related endpoints")
}
)
@Path(NamespaceRootResource.NAMESPACE_PATH_V2)
public class NamespaceRootResource {
static final String NAMESPACE_PATH_V2 = "v2/namespaces/";
private final Provider<NamespaceCollectionResource> namespaceCollectionResource;
private final Provider<NamespaceResource> namespaceResource;
@Inject
public NamespaceRootResource(Provider<NamespaceCollectionResource> namespaceCollectionResource, Provider<NamespaceResource> namespaceResource) {
this.namespaceCollectionResource = namespaceCollectionResource;
this.namespaceResource = namespaceResource;
}
@Path("{namespace}")
public NamespaceResource getNamespaceResource() {
return namespaceResource.get();
}
@Path("")
public NamespaceCollectionResource getNamespaceCollectionResource() {
return namespaceCollectionResource.get();
}
}

View File

@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.api.v2.resources;
import de.otto.edison.hal.Links;
@@ -48,8 +48,8 @@ public class NamespaceStrategyResource {
static final String PATH = "v2/namespaceStrategies";
private Set<NamespaceStrategy> namespaceStrategies;
private Provider<NamespaceStrategy> namespaceStrategyProvider;
private final Set<NamespaceStrategy> namespaceStrategies;
private final Provider<NamespaceStrategy> namespaceStrategyProvider;
@Inject
public NamespaceStrategyResource(Set<NamespaceStrategy> namespaceStrategies, Provider<NamespaceStrategy> namespaceStrategyProvider) {

View File

@@ -0,0 +1,43 @@
/*
* MIT License
*
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
*
* 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 sonia.scm.api.v2.resources;
import javax.inject.Inject;
import static de.otto.edison.hal.Links.linkingTo;
class NamespaceToNamespaceDtoMapper {
private final ResourceLinks links;
@Inject
NamespaceToNamespaceDtoMapper(ResourceLinks links) {
this.links = links;
}
NamespaceDto map(String namespace) {
return new NamespaceDto(namespace, linkingTo().self(links.namespace().self(namespace)).build());
}
}

View File

@@ -876,4 +876,36 @@ class ResourceLinks {
return permissionsLinkBuilder.method("getAll").parameters().href();
}
}
public NamespaceCollectionLinks namespaceCollection() {
return new NamespaceCollectionLinks(scmPathInfoStore.get());
}
static class NamespaceCollectionLinks {
private final LinkBuilder namespaceCollectionLinkBuilder;
NamespaceCollectionLinks(ScmPathInfo scmPathInfo) {
this.namespaceCollectionLinkBuilder = new LinkBuilder(scmPathInfo, NamespaceRootResource.class, NamespaceCollectionResource.class);
}
String self() {
return namespaceCollectionLinkBuilder.method("getNamespaceCollectionResource").parameters().method("getAll").parameters().href();
}
}
public NamespaceLinks namespace() {
return new NamespaceLinks(scmPathInfoStore.get());
}
static class NamespaceLinks {
private final LinkBuilder namespaceLinkBuilder;
NamespaceLinks(ScmPathInfo scmPathInfo) {
this.namespaceLinkBuilder = new LinkBuilder(scmPathInfo, NamespaceRootResource.class, NamespaceResource.class);
}
String self(String namespace) {
return namespaceLinkBuilder.method("getNamespaceResource").parameters().method("get").parameters(namespace).href();
}
}
}

View File

@@ -61,6 +61,7 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.function.Predicate;
import static java.util.stream.Collectors.toSet;
import static sonia.scm.AlreadyExistsException.alreadyExists;
import static sonia.scm.ContextEntry.ContextBuilder.entity;
import static sonia.scm.NotFoundException.notFound;
@@ -330,6 +331,13 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
return getAll(null, start, limit);
}
@Override
public Collection<String> getAllNamespaces() {
return getAll().stream()
.map(Repository::getNamespace)
.collect(toSet());
}
@Override
public Collection<RepositoryType> getConfiguredTypes() {
List<RepositoryType> validTypes = Lists.newArrayList();

View File

@@ -0,0 +1,106 @@
/*
* MIT License
*
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
*
* 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 sonia.scm.api.v2.resources;
import org.jboss.resteasy.mock.MockHttpRequest;
import org.jboss.resteasy.mock.MockHttpResponse;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.web.RestDispatcher;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import static com.google.inject.util.Providers.of;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class NamespaceRootResourceTest {
@Mock
RepositoryManager repositoryManager;
RestDispatcher dispatcher = new RestDispatcher();
MockHttpResponse response = new MockHttpResponse();
ResourceLinks links = ResourceLinksMock.createMock(URI.create("/"));
@BeforeEach
void setUpResources() {
NamespaceToNamespaceDtoMapper namespaceMapper = new NamespaceToNamespaceDtoMapper(links);
NamespaceCollectionToDtoMapper namespaceCollectionToDtoMapper = new NamespaceCollectionToDtoMapper(namespaceMapper, links);
NamespaceCollectionResource namespaceCollectionResource = new NamespaceCollectionResource(repositoryManager, namespaceCollectionToDtoMapper);
NamespaceResource namespaceResource = new NamespaceResource(repositoryManager, namespaceMapper);
dispatcher.addSingletonResource(new NamespaceRootResource(of(namespaceCollectionResource), of(namespaceResource)));
}
@Test
void shouldReturnAllNamespaces() throws URISyntaxException, UnsupportedEncodingException {
when(repositoryManager.getAllNamespaces()).thenReturn(asList("hitchhiker", "space"));
MockHttpRequest request = MockHttpRequest.get("/" + NamespaceRootResource.NAMESPACE_PATH_V2);
dispatcher.invoke(request, response);
assertThat(response.getStatus()).isEqualTo(200);
assertThat(response.getContentAsString())
.contains("\"self\":{\"href\":\"/v2/namespaces/\"}")
.contains("\"_embedded\"")
.contains("\"namespace\":\"hitchhiker\"")
.contains("\"namespace\":\"space\"");
}
@Test
void shouldReturnSingleNamespace() throws URISyntaxException, UnsupportedEncodingException {
when(repositoryManager.getAllNamespaces()).thenReturn(asList("hitchhiker", "space"));
MockHttpRequest request = MockHttpRequest.get("/" + NamespaceRootResource.NAMESPACE_PATH_V2 + "space");
dispatcher.invoke(request, response);
assertThat(response.getStatus()).isEqualTo(200);
assertThat(response.getContentAsString())
.contains("\"namespace\":\"space\"")
.contains("\"self\":{\"href\":\"/v2/namespaces/space\"}");
}
@Test
void shouldHandleUnknownNamespace() throws URISyntaxException, UnsupportedEncodingException {
when(repositoryManager.getAllNamespaces()).thenReturn(asList("hitchhiker", "space"));
MockHttpRequest request = MockHttpRequest.get("/" + NamespaceRootResource.NAMESPACE_PATH_V2 + "unknown");
dispatcher.invoke(request, response);
assertThat(response.getStatus()).isEqualTo(404);
}
}

View File

@@ -76,6 +76,8 @@ public class ResourceLinksMock {
lenient().when(resourceLinks.repositoryRoleCollection()).thenReturn(new ResourceLinks.RepositoryRoleCollectionLinks(pathInfo));
lenient().when(resourceLinks.namespaceStrategies()).thenReturn(new ResourceLinks.NamespaceStrategiesLinks(pathInfo));
lenient().when(resourceLinks.annotate()).thenReturn(new ResourceLinks.AnnotateLinks(pathInfo));
lenient().when(resourceLinks.namespace()).thenReturn(new ResourceLinks.NamespaceLinks(pathInfo));
lenient().when(resourceLinks.namespaceCollection()).thenReturn(new ResourceLinks.NamespaceCollectionLinks(pathInfo));
return resourceLinks;
}

View File

@@ -33,6 +33,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.inject.util.Providers;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.util.ThreadContext;
import org.assertj.core.api.Assertions;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -444,6 +445,18 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
assertEquals("hitchhiker", changedRepo.getNamespace());
}
@Test
public void shouldReturnDistinctNamespaces() {
createTestRepository();
createSecondTestRepository();
Collection<String> namespaces = ((RepositoryManager) manager).getAllNamespaces();
Assertions.assertThat(namespaces)
.hasSize(1)
.contains("default_namespace");
}
//~--- methods --------------------------------------------------------------
@Override