mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-07 05:55:44 +01:00
merged 2.0.0-m3
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
package sonia.scm;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class BadRequestException extends ExceptionWithContext {
|
||||
public BadRequestException(List<ContextEntry> context, String message) {
|
||||
super(context, message);
|
||||
}
|
||||
}
|
||||
@@ -40,13 +40,14 @@ import java.util.Collections;
|
||||
* @author Sebastian Sdorra
|
||||
* @version 1.6
|
||||
*/
|
||||
public class NotSupportedFeatureException extends ExceptionWithContext {
|
||||
@SuppressWarnings("squid:MaximumInheritanceDepth") // exceptions have a deep inheritance depth themselves; therefore we accept this here
|
||||
public class FeatureNotSupportedException extends BadRequestException {
|
||||
|
||||
private static final long serialVersionUID = 256498734456613496L;
|
||||
|
||||
private static final String CODE = "9SR8G0kmU1";
|
||||
|
||||
public NotSupportedFeatureException(String feature)
|
||||
public FeatureNotSupportedException(String feature)
|
||||
{
|
||||
super(Collections.emptyList(),createMessage(feature));
|
||||
}
|
||||
@@ -38,7 +38,7 @@ package sonia.scm.repository;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.NotSupportedFeatureException;
|
||||
import sonia.scm.FeatureNotSupportedException;
|
||||
import sonia.scm.SCMContextProvider;
|
||||
import sonia.scm.event.ScmEventBus;
|
||||
|
||||
@@ -167,12 +167,12 @@ public abstract class AbstractRepositoryHandler<C extends RepositoryConfig>
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws NotSupportedFeatureException
|
||||
* @throws FeatureNotSupportedException
|
||||
*/
|
||||
@Override
|
||||
public ImportHandler getImportHandler()
|
||||
{
|
||||
throw new NotSupportedFeatureException("import");
|
||||
throw new FeatureNotSupportedException("import");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -36,7 +36,7 @@ package sonia.scm.repository;
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.Handler;
|
||||
import sonia.scm.NotSupportedFeatureException;
|
||||
import sonia.scm.FeatureNotSupportedException;
|
||||
import sonia.scm.plugin.ExtensionPoint;
|
||||
|
||||
/**
|
||||
@@ -59,9 +59,9 @@ public interface RepositoryHandler
|
||||
* @return {@link ImportHandler} for the repository type of this handler
|
||||
* @since 1.12
|
||||
*
|
||||
* @throws NotSupportedFeatureException
|
||||
* @throws FeatureNotSupportedException
|
||||
*/
|
||||
public ImportHandler getImportHandler() throws NotSupportedFeatureException;
|
||||
public ImportHandler getImportHandler() throws FeatureNotSupportedException;
|
||||
|
||||
/**
|
||||
* Returns informations about the version of the RepositoryHandler.
|
||||
|
||||
@@ -38,7 +38,7 @@ package sonia.scm.repository.api;
|
||||
import com.google.common.base.Preconditions;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.NotSupportedFeatureException;
|
||||
import sonia.scm.FeatureNotSupportedException;
|
||||
import sonia.scm.repository.Feature;
|
||||
import sonia.scm.repository.spi.DiffCommand;
|
||||
import sonia.scm.repository.spi.DiffCommandRequest;
|
||||
@@ -203,7 +203,7 @@ public final class DiffCommandBuilder
|
||||
public DiffCommandBuilder setAncestorChangeset(String revision)
|
||||
{
|
||||
if (!supportedFeatures.contains(Feature.INCOMING_REVISION)) {
|
||||
throw new NotSupportedFeatureException(Feature.INCOMING_REVISION.name());
|
||||
throw new FeatureNotSupportedException(Feature.INCOMING_REVISION.name());
|
||||
}
|
||||
request.setAncestorChangeset(revision);
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ import com.google.common.base.Objects;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.NotSupportedFeatureException;
|
||||
import sonia.scm.FeatureNotSupportedException;
|
||||
import sonia.scm.cache.Cache;
|
||||
import sonia.scm.cache.CacheManager;
|
||||
import sonia.scm.repository.Changeset;
|
||||
@@ -410,7 +410,7 @@ public final class LogCommandBuilder
|
||||
*/
|
||||
public LogCommandBuilder setAncestorChangeset(String ancestorChangeset) {
|
||||
if (!supportedFeatures.contains(Feature.INCOMING_REVISION)) {
|
||||
throw new NotSupportedFeatureException(Feature.INCOMING_REVISION.name());
|
||||
throw new FeatureNotSupportedException(Feature.INCOMING_REVISION.name());
|
||||
}
|
||||
request.setAncestorChangeset(ancestorChangeset);
|
||||
return this;
|
||||
|
||||
@@ -80,8 +80,20 @@ public interface AccessToken {
|
||||
*/
|
||||
Date getExpiration();
|
||||
|
||||
/**
|
||||
* Returns refresh expiration of token.
|
||||
*
|
||||
* @return refresh expiration
|
||||
*/
|
||||
Optional<Date> getRefreshExpiration();
|
||||
|
||||
/**
|
||||
* Returns id of the parent key.
|
||||
*
|
||||
* @return parent key id
|
||||
*/
|
||||
Optional<String> getParentKey();
|
||||
|
||||
/**
|
||||
* Returns the scope of the token. The scope is able to reduce the permissions of the subject in the context of this
|
||||
* token. For example we could issue a token which can only be used to read a single repository. for more informations
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package sonia.scm.security;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* Generates cookies and invalidates access token cookies.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public interface AccessTokenCookieIssuer {
|
||||
|
||||
/**
|
||||
* Creates a cookie for token authentication and attaches it to the response.
|
||||
*
|
||||
* @param request http servlet request
|
||||
* @param response http servlet response
|
||||
* @param accessToken access token
|
||||
*/
|
||||
void authenticate(HttpServletRequest request, HttpServletResponse response, AccessToken accessToken);
|
||||
/**
|
||||
* Invalidates the authentication cookie.
|
||||
*
|
||||
* @param request http servlet request
|
||||
* @param response http servlet response
|
||||
*/
|
||||
void invalidate(HttpServletRequest request, HttpServletResponse response);
|
||||
|
||||
}
|
||||
@@ -164,7 +164,7 @@ public class DefaultCipherHandler implements CipherHandler {
|
||||
String result = null;
|
||||
|
||||
try {
|
||||
byte[] encodedInput = Base64.getDecoder().decode(value);
|
||||
byte[] encodedInput = Base64.getUrlDecoder().decode(value);
|
||||
byte[] salt = new byte[SALT_LENGTH];
|
||||
byte[] encoded = new byte[encodedInput.length - SALT_LENGTH];
|
||||
|
||||
@@ -221,7 +221,7 @@ public class DefaultCipherHandler implements CipherHandler {
|
||||
System.arraycopy(salt, 0, result, 0, SALT_LENGTH);
|
||||
System.arraycopy(encodedInput, 0, result, SALT_LENGTH,
|
||||
result.length - SALT_LENGTH);
|
||||
res = new String(Base64.getEncoder().encode(result), ENCODING);
|
||||
res = new String(Base64.getUrlEncoder().encode(result), ENCODING);
|
||||
} catch (IOException | GeneralSecurityException ex) {
|
||||
throw new CipherException("could not encode string", ex);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,10 @@
|
||||
|
||||
package sonia.scm.store;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static java.util.Optional.ofNullable;
|
||||
|
||||
/**
|
||||
* ConfigurationStore for configuration objects. <strong>Note:</strong> the default
|
||||
* implementation use JAXB to marshall the configuration objects.
|
||||
@@ -50,7 +54,17 @@ public interface ConfigurationStore<T>
|
||||
*
|
||||
* @return configuration object from store
|
||||
*/
|
||||
public T get();
|
||||
T get();
|
||||
|
||||
/**
|
||||
* Returns the configuration object from store.
|
||||
*
|
||||
*
|
||||
* @return configuration object from store
|
||||
*/
|
||||
default Optional<T> getOptional() {
|
||||
return ofNullable(get());
|
||||
}
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
@@ -60,5 +74,5 @@ public interface ConfigurationStore<T>
|
||||
*
|
||||
* @param obejct configuration object to store
|
||||
*/
|
||||
public void set(T obejct);
|
||||
void set(T object);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,10 @@
|
||||
|
||||
package sonia.scm.store;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static java.util.Optional.ofNullable;
|
||||
|
||||
/**
|
||||
* Base class for {@link BlobStore} and {@link DataStore}.
|
||||
*
|
||||
@@ -67,4 +71,16 @@ public interface MultiEntryStore<T> {
|
||||
* @return item with the given id
|
||||
*/
|
||||
public T get(String id);
|
||||
|
||||
/**
|
||||
* Returns the item with the given id from the store.
|
||||
*
|
||||
*
|
||||
* @param id id of the item to return
|
||||
*
|
||||
* @return item with the given id
|
||||
*/
|
||||
default Optional<T> getOptional(String id) {
|
||||
return ofNullable(get(id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package sonia.scm.user;
|
||||
|
||||
import sonia.scm.BadRequestException;
|
||||
import sonia.scm.ContextEntry;
|
||||
import sonia.scm.ExceptionWithContext;
|
||||
|
||||
public class ChangePasswordNotAllowedException extends ExceptionWithContext {
|
||||
@SuppressWarnings("squid:MaximumInheritanceDepth") // exceptions have a deep inheritance depth themselves; therefore we accept this here
|
||||
public class ChangePasswordNotAllowedException extends BadRequestException {
|
||||
|
||||
private static final String CODE = "9BR7qpDAe1";
|
||||
public static final String WRONG_USER_TYPE = "User of type %s are not allowed to change password";
|
||||
public static final String WRONG_USER_TYPE = "Users of type %s are not allowed to change password";
|
||||
|
||||
public ChangePasswordNotAllowedException(ContextEntry.ContextBuilder context, String type) {
|
||||
super(context.build(), String.format(WRONG_USER_TYPE, type));
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package sonia.scm.user;
|
||||
|
||||
import sonia.scm.BadRequestException;
|
||||
import sonia.scm.ContextEntry;
|
||||
import sonia.scm.ExceptionWithContext;
|
||||
|
||||
public class InvalidPasswordException extends ExceptionWithContext {
|
||||
@SuppressWarnings("squid:MaximumInheritanceDepth") // exceptions have a deep inheritance depth themselves; therefore we accept this here
|
||||
public class InvalidPasswordException extends BadRequestException {
|
||||
|
||||
private static final String CODE = "8YR7aawFW1";
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package sonia.scm.web;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static sonia.scm.web.VndMediaType.REPOSITORY;
|
||||
import static sonia.scm.web.VndMediaType.REPOSITORY_COLLECTION;
|
||||
|
||||
public abstract class AbstractRepositoryJsonEnricher extends JsonEnricherBase {
|
||||
|
||||
public AbstractRepositoryJsonEnricher(ObjectMapper objectMapper) {
|
||||
super(objectMapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enrich(JsonEnricherContext context) {
|
||||
if (resultHasMediaType(REPOSITORY, context)) {
|
||||
JsonNode repositoryNode = context.getResponseEntity();
|
||||
enrichRepositoryNode(repositoryNode);
|
||||
} else if (resultHasMediaType(REPOSITORY_COLLECTION, context)) {
|
||||
JsonNode repositoryCollectionNode = context.getResponseEntity().get("_embedded").withArray("repositories");
|
||||
repositoryCollectionNode.elements().forEachRemaining(this::enrichRepositoryNode);
|
||||
}
|
||||
}
|
||||
|
||||
private void enrichRepositoryNode(JsonNode repositoryNode) {
|
||||
String namespace = repositoryNode.get("namespace").asText();
|
||||
String name = repositoryNode.get("name").asText();
|
||||
|
||||
enrichRepositoryNode(repositoryNode, namespace, name);
|
||||
}
|
||||
|
||||
protected abstract void enrichRepositoryNode(JsonNode repositoryNode, String namespace, String name);
|
||||
|
||||
protected void addLink(JsonNode repositoryNode, String linkName, String link) {
|
||||
JsonNode hrefNode = createObject(singletonMap("href", value(link)));
|
||||
addPropertyNode(repositoryNode.get("_links"), linkName, hrefNode);
|
||||
}
|
||||
}
|
||||
25
scm-core/src/main/java/sonia/scm/xml/XmlInstantAdapter.java
Normal file
25
scm-core/src/main/java/sonia/scm/xml/XmlInstantAdapter.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package sonia.scm.xml;
|
||||
|
||||
import javax.xml.bind.annotation.adapters.XmlAdapter;
|
||||
import java.time.Instant;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
|
||||
/**
|
||||
* JAXB adapter for {@link Instant} objects.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class XmlInstantAdapter extends XmlAdapter<String, Instant> {
|
||||
|
||||
@Override
|
||||
public String marshal(Instant instant) {
|
||||
return DateTimeFormatter.ISO_INSTANT.format(instant);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant unmarshal(String text) {
|
||||
TemporalAccessor parsed = DateTimeFormatter.ISO_INSTANT.parse(text);
|
||||
return Instant.from(parsed);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package sonia.scm.web;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.io.Resources;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.api.v2.resources.ScmPathInfoStore;
|
||||
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class AbstractRepositoryJsonEnricherTest {
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
private AbstractRepositoryJsonEnricher linkEnricher;
|
||||
private JsonNode rootNode;
|
||||
|
||||
@BeforeEach
|
||||
void globalSetUp() {
|
||||
ScmPathInfoStore pathInfoStore = new ScmPathInfoStore();
|
||||
pathInfoStore.set(() -> URI.create("/"));
|
||||
|
||||
linkEnricher = new AbstractRepositoryJsonEnricher(objectMapper) {
|
||||
@Override
|
||||
protected void enrichRepositoryNode(JsonNode repositoryNode, String namespace, String name) {
|
||||
addLink(repositoryNode, "new-link", "/somewhere");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldEnrichRepositories() throws IOException {
|
||||
URL resource = Resources.getResource("sonia/scm/repository/repository-001.json");
|
||||
rootNode = objectMapper.readTree(resource);
|
||||
|
||||
JsonEnricherContext context = new JsonEnricherContext(
|
||||
URI.create("/"),
|
||||
MediaType.valueOf(VndMediaType.REPOSITORY),
|
||||
rootNode
|
||||
);
|
||||
|
||||
linkEnricher.enrich(context);
|
||||
|
||||
String configLink = context.getResponseEntity()
|
||||
.get("_links")
|
||||
.get("new-link")
|
||||
.get("href")
|
||||
.asText();
|
||||
|
||||
assertThat(configLink).isEqualTo("/somewhere");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldEnrichAllRepositories() throws IOException {
|
||||
URL resource = Resources.getResource("sonia/scm/repository/repository-collection-001.json");
|
||||
rootNode = objectMapper.readTree(resource);
|
||||
|
||||
JsonEnricherContext context = new JsonEnricherContext(
|
||||
URI.create("/"),
|
||||
MediaType.valueOf(VndMediaType.REPOSITORY_COLLECTION),
|
||||
rootNode
|
||||
);
|
||||
|
||||
linkEnricher.enrich(context);
|
||||
|
||||
context.getResponseEntity()
|
||||
.get("_embedded")
|
||||
.withArray("repositories")
|
||||
.elements()
|
||||
.forEachRemaining(node -> {
|
||||
String configLink = node
|
||||
.get("_links")
|
||||
.get("new-link")
|
||||
.get("href")
|
||||
.asText();
|
||||
|
||||
assertThat(configLink).isEqualTo("/somewhere");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotModifyObjectsWithUnsupportedMediaType() throws IOException {
|
||||
URL resource = Resources.getResource("sonia/scm/repository/repository-001.json");
|
||||
rootNode = objectMapper.readTree(resource);
|
||||
JsonEnricherContext context = new JsonEnricherContext(
|
||||
URI.create("/"),
|
||||
MediaType.valueOf(VndMediaType.USER),
|
||||
rootNode
|
||||
);
|
||||
|
||||
linkEnricher.enrich(context);
|
||||
|
||||
boolean hasNewPullRequestLink = context.getResponseEntity()
|
||||
.get("_links")
|
||||
.has("new-link");
|
||||
|
||||
assertThat(hasNewPullRequestLink).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package sonia.scm.xml;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junitpioneer.jupiter.TempDirectory;
|
||||
|
||||
import javax.xml.bind.JAXB;
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Instant;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
@ExtendWith(TempDirectory.class)
|
||||
class XmlInstantAdapterTest {
|
||||
|
||||
@Test
|
||||
void shouldMarshalAndUnmarshalInstant(@TempDirectory.TempDir Path tempDirectory) {
|
||||
Path path = tempDirectory.resolve("instant.xml");
|
||||
|
||||
Instant instant = Instant.now();
|
||||
InstantObject object = new InstantObject(instant);
|
||||
JAXB.marshal(object, path.toFile());
|
||||
|
||||
InstantObject unmarshaled = JAXB.unmarshal(path.toFile(), InstantObject.class);
|
||||
assertEquals(instant, unmarshaled.instant);
|
||||
}
|
||||
|
||||
@XmlRootElement(name = "instant-object")
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public static class InstantObject {
|
||||
|
||||
@XmlJavaTypeAdapter(XmlInstantAdapter.class)
|
||||
private Instant instant;
|
||||
|
||||
public InstantObject() {
|
||||
}
|
||||
|
||||
InstantObject(Instant instant) {
|
||||
this.instant = instant;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"creationDate": "2018-11-09T09:48:32.732Z",
|
||||
"description": "Handling static webresources made easy",
|
||||
"healthCheckFailures": [],
|
||||
"lastModified": "2018-11-09T09:49:20.973Z",
|
||||
"namespace": "scmadmin",
|
||||
"name": "web-resources",
|
||||
"archived": false,
|
||||
"type": "git",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources"
|
||||
},
|
||||
"delete": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources"
|
||||
},
|
||||
"update": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources"
|
||||
},
|
||||
"permissions": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/permissions/"
|
||||
},
|
||||
"protocol": [
|
||||
{
|
||||
"href": "http://localhost:8081/scm/repo/scmadmin/web-resources",
|
||||
"name": "http"
|
||||
}
|
||||
],
|
||||
"tags": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/tags/"
|
||||
},
|
||||
"branches": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/branches/"
|
||||
},
|
||||
"changesets": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/changesets/"
|
||||
},
|
||||
"sources": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/sources/"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
{
|
||||
"page": 0,
|
||||
"pageTotal": 1,
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/?page=0&pageSize=10"
|
||||
},
|
||||
"first": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/?page=0&pageSize=10"
|
||||
},
|
||||
"last": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/?page=0&pageSize=10"
|
||||
},
|
||||
"create": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/"
|
||||
}
|
||||
},
|
||||
"_embedded": {
|
||||
"repositories": [
|
||||
{
|
||||
"creationDate": "2018-11-09T09:48:32.732Z",
|
||||
"description": "Handling static webresources made easy",
|
||||
"healthCheckFailures": [],
|
||||
"lastModified": "2018-11-09T09:49:20.973Z",
|
||||
"namespace": "scmadmin",
|
||||
"name": "web-resources",
|
||||
"archived": false,
|
||||
"type": "git",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources"
|
||||
},
|
||||
"delete": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources"
|
||||
},
|
||||
"update": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources"
|
||||
},
|
||||
"permissions": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/permissions/"
|
||||
},
|
||||
"protocol": [
|
||||
{
|
||||
"href": "http://localhost:8081/scm/repo/scmadmin/web-resources",
|
||||
"name": "http"
|
||||
}
|
||||
],
|
||||
"tags": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/tags/"
|
||||
},
|
||||
"branches": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/branches/"
|
||||
},
|
||||
"changesets": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/changesets/"
|
||||
},
|
||||
"sources": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/sources/"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"creationDate": "2018-11-09T09:48:32.732Z",
|
||||
"description": "Handling static webresources made easy",
|
||||
"healthCheckFailures": [],
|
||||
"lastModified": "2018-11-09T09:49:20.973Z",
|
||||
"namespace": "scmadmin",
|
||||
"name": "web-resources",
|
||||
"archived": false,
|
||||
"type": "git",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources"
|
||||
},
|
||||
"delete": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources"
|
||||
},
|
||||
"update": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources"
|
||||
},
|
||||
"permissions": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/permissions/"
|
||||
},
|
||||
"protocol": [
|
||||
{
|
||||
"href": "http://localhost:8081/scm/repo/scmadmin/web-resources",
|
||||
"name": "http"
|
||||
}
|
||||
],
|
||||
"tags": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/tags/"
|
||||
},
|
||||
"branches": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/branches/"
|
||||
},
|
||||
"changesets": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/changesets/"
|
||||
},
|
||||
"sources": {
|
||||
"href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/sources/"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -58,8 +58,6 @@ public abstract class FileBasedStoreFactory {
|
||||
private RepositoryLocationResolver repositoryLocationResolver;
|
||||
private Store store;
|
||||
|
||||
private File storeDirectory;
|
||||
|
||||
protected FileBasedStoreFactory(SCMContextProvider contextProvider , RepositoryLocationResolver repositoryLocationResolver, Store store) {
|
||||
this.contextProvider = contextProvider;
|
||||
this.repositoryLocationResolver = repositoryLocationResolver;
|
||||
@@ -75,7 +73,7 @@ public abstract class FileBasedStoreFactory {
|
||||
}
|
||||
|
||||
protected File getStoreLocation(String name, Class type, Repository repository) {
|
||||
if (storeDirectory == null) {
|
||||
File storeDirectory;
|
||||
if (repository != null) {
|
||||
LOG.debug("create store with type: {}, name: {} and repository: {}", type, name, repository.getNamespaceAndName());
|
||||
storeDirectory = this.getStoreDirectory(store, repository);
|
||||
@@ -84,8 +82,7 @@ public abstract class FileBasedStoreFactory {
|
||||
storeDirectory = this.getStoreDirectory(store);
|
||||
}
|
||||
IOUtil.mkdirs(storeDirectory);
|
||||
}
|
||||
return new File(this.storeDirectory, name);
|
||||
return new File(storeDirectory, name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -42,8 +42,20 @@ package sonia.scm.store;
|
||||
*/
|
||||
public class InMemoryConfigurationStoreFactory implements ConfigurationStoreFactory {
|
||||
|
||||
private ConfigurationStore store;
|
||||
|
||||
public InMemoryConfigurationStoreFactory() {
|
||||
}
|
||||
|
||||
public InMemoryConfigurationStoreFactory(ConfigurationStore store) {
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationStore getStore(TypedStoreParameters storeParameters) {
|
||||
if (store != null) {
|
||||
return store;
|
||||
}
|
||||
return new InMemoryConfigurationStore<>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package sonia.scm.store;
|
||||
|
||||
import sonia.scm.security.KeyGenerator;
|
||||
import sonia.scm.security.UUIDKeyGenerator;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* In memory store implementation of {@link DataStore}.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*
|
||||
* @param <T> type of stored object
|
||||
*/
|
||||
public class InMemoryDataStore<T> implements DataStore<T> {
|
||||
|
||||
private final Map<String, T> store = new HashMap<>();
|
||||
private KeyGenerator generator = new UUIDKeyGenerator();
|
||||
|
||||
@Override
|
||||
public String put(T item) {
|
||||
String key = generator.createKey();
|
||||
store.put(key, item);
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(String id, T item) {
|
||||
store.put(id, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, T> getAll() {
|
||||
return Collections.unmodifiableMap(store);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
store.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(String id) {
|
||||
store.remove(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get(String id) {
|
||||
return store.get(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package sonia.scm.store;
|
||||
|
||||
/**
|
||||
* In memory configuration store factory for testing purposes.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class InMemoryDataStoreFactory implements DataStoreFactory {
|
||||
|
||||
private InMemoryDataStore store;
|
||||
|
||||
public InMemoryDataStoreFactory() {
|
||||
}
|
||||
|
||||
public InMemoryDataStoreFactory(InMemoryDataStore store) {
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> DataStore<T> getStore(TypedStoreParameters<T> storeParameters) {
|
||||
if (store != null) {
|
||||
return store;
|
||||
}
|
||||
return new InMemoryDataStore<>();
|
||||
}
|
||||
}
|
||||
@@ -63,8 +63,9 @@ class ConfigurationBinder {
|
||||
|
||||
|
||||
// route for global configuration, passes the current repository to component
|
||||
const RepoRoute = ({ url, repository }) => {
|
||||
return this.route(url + to, <RepositoryComponent repository={repository}/>);
|
||||
const RepoRoute = ({url, repository}) => {
|
||||
const link = repository._links[linkName].href
|
||||
return this.route(url + to, <RepositoryComponent repository={repository} link={link}/>);
|
||||
};
|
||||
|
||||
// bind config route to extension point
|
||||
|
||||
@@ -114,7 +114,7 @@ class RepositoryRoot extends React.Component<Props> {
|
||||
return (
|
||||
<Page title={repository.namespace + "/" + repository.name}>
|
||||
<div className="columns">
|
||||
<div className="column is-three-quarters">
|
||||
<div className="column is-three-quarters is-clipped">
|
||||
<Switch>
|
||||
<Route
|
||||
path={url}
|
||||
|
||||
@@ -119,7 +119,9 @@ class FileTree extends React.Component<Props> {
|
||||
<th className="is-hidden-mobile">
|
||||
{t("sources.file-tree.lastModified")}
|
||||
</th>
|
||||
<th>{t("sources.file-tree.description")}</th>
|
||||
<th className="is-hidden-mobile">
|
||||
{t("sources.file-tree.description")}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
@@ -6,10 +6,14 @@ import FileSize from "./FileSize";
|
||||
import FileIcon from "./FileIcon";
|
||||
import { Link } from "react-router-dom";
|
||||
import type { File } from "@scm-manager/ui-types";
|
||||
import classNames from "classnames";
|
||||
|
||||
const styles = {
|
||||
iconColumn: {
|
||||
width: "16px"
|
||||
},
|
||||
wordBreakMinWidth: {
|
||||
minWidth: "10em"
|
||||
}
|
||||
};
|
||||
|
||||
@@ -71,12 +75,14 @@ class FileTreeLeaf extends React.Component<Props> {
|
||||
return (
|
||||
<tr>
|
||||
<td className={classes.iconColumn}>{this.createFileIcon(file)}</td>
|
||||
<td>{this.createFileName(file)}</td>
|
||||
<td className={classNames(classes.wordBreakMinWidth, "is-word-break")}>{this.createFileName(file)}</td>
|
||||
<td className="is-hidden-mobile">{fileSize}</td>
|
||||
<td className="is-hidden-mobile">
|
||||
<DateFromNow date={file.lastModified} />
|
||||
</td>
|
||||
<td>{file.description}</td>
|
||||
<td className={classNames(classes.wordBreakMinWidth, "is-word-break", "is-hidden-mobile")}>
|
||||
{file.description}
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -41,6 +41,13 @@ const styles = {
|
||||
isVerticalCenter: {
|
||||
display: "flex",
|
||||
alignItems: "center"
|
||||
},
|
||||
wordBreak: {
|
||||
WebkitHyphens: "auto",
|
||||
MozHyphens: "auto",
|
||||
MsHyphens: "auto",
|
||||
hypens: "auto",
|
||||
wordBreak: "break-all",
|
||||
}
|
||||
};
|
||||
|
||||
@@ -93,7 +100,7 @@ class Content extends React.Component<Props, State> {
|
||||
classes.marginInHeader
|
||||
)}
|
||||
/>
|
||||
<span>{file.name}</span>
|
||||
<span className={classes.wordBreak}>{file.name}</span>
|
||||
</div>
|
||||
<div className="media-right">{selector}</div>
|
||||
</article>
|
||||
@@ -125,11 +132,11 @@ class Content extends React.Component<Props, State> {
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{t("sources.content.path")}</td>
|
||||
<td>{file.path}</td>
|
||||
<td className={classes.wordBreak}>{file.path}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{t("sources.content.branch")}</td>
|
||||
<td>{revision}</td>
|
||||
<td className={classes.wordBreak}>{revision}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{t("sources.content.size")}</td>
|
||||
@@ -141,7 +148,7 @@ class Content extends React.Component<Props, State> {
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{t("sources.content.description")}</td>
|
||||
<td>{description}</td>
|
||||
<td className={classes.wordBreak}>{description}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -27,6 +27,14 @@ $blue: #33B2E8;
|
||||
padding: 0 0 0 3.8em !important;
|
||||
}
|
||||
|
||||
.is-word-break {
|
||||
-webkit-hyphens: auto;
|
||||
-moz-hyphens: auto;
|
||||
-ms-hyphens: auto;
|
||||
hyphens: auto;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.main {
|
||||
min-height: calc(100vh - 260px);
|
||||
}
|
||||
|
||||
@@ -79,14 +79,14 @@ import sonia.scm.repository.spi.HookEventFacade;
|
||||
import sonia.scm.repository.xml.XmlRepositoryDAO;
|
||||
import sonia.scm.schedule.QuartzScheduler;
|
||||
import sonia.scm.schedule.Scheduler;
|
||||
import sonia.scm.security.AccessTokenCookieIssuer;
|
||||
import sonia.scm.security.AuthorizationChangedEventProducer;
|
||||
import sonia.scm.security.CipherHandler;
|
||||
import sonia.scm.security.CipherUtil;
|
||||
import sonia.scm.security.ConfigurableLoginAttemptHandler;
|
||||
import sonia.scm.security.DefaultJwtAccessTokenRefreshStrategy;
|
||||
import sonia.scm.security.DefaultAccessTokenCookieIssuer;
|
||||
import sonia.scm.security.DefaultKeyGenerator;
|
||||
import sonia.scm.security.DefaultSecuritySystem;
|
||||
import sonia.scm.security.JwtAccessTokenRefreshStrategy;
|
||||
import sonia.scm.security.KeyGenerator;
|
||||
import sonia.scm.security.LoginAttemptHandler;
|
||||
import sonia.scm.security.SecuritySystem;
|
||||
@@ -320,6 +320,7 @@ public class ScmServletModule extends ServletModule
|
||||
// bind events
|
||||
// bind(LastModifiedUpdateListener.class);
|
||||
|
||||
bind(AccessTokenCookieIssuer.class).to(DefaultAccessTokenCookieIssuer.class);
|
||||
bind(PushStateDispatcher.class).toProvider(PushStateDispatcherProvider.class);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package sonia.scm.api.rest;
|
||||
|
||||
import sonia.scm.BadRequestException;
|
||||
import sonia.scm.api.v2.resources.ExceptionWithContextToErrorDtoMapper;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.ext.Provider;
|
||||
|
||||
@Provider
|
||||
public class BadRequestExceptionMapper extends ContextualExceptionMapper<BadRequestException> {
|
||||
@Inject
|
||||
public BadRequestExceptionMapper(ExceptionWithContextToErrorDtoMapper mapper) {
|
||||
super(BadRequestException.class, Response.Status.BAD_REQUEST, mapper);
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ import org.apache.shiro.SecurityUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.NotFoundException;
|
||||
import sonia.scm.NotSupportedFeatureException;
|
||||
import sonia.scm.FeatureNotSupportedException;
|
||||
import sonia.scm.Type;
|
||||
import sonia.scm.api.rest.RestActionUploadResult;
|
||||
import sonia.scm.api.v2.resources.RepositoryResource;
|
||||
@@ -394,7 +394,7 @@ public class RepositoryImportResource
|
||||
|
||||
response = Response.ok(result).build();
|
||||
}
|
||||
catch (NotSupportedFeatureException ex)
|
||||
catch (FeatureNotSupportedException ex)
|
||||
{
|
||||
logger
|
||||
.warn(
|
||||
@@ -609,7 +609,7 @@ public class RepositoryImportResource
|
||||
types.add(t);
|
||||
}
|
||||
}
|
||||
catch (NotSupportedFeatureException ex)
|
||||
catch (FeatureNotSupportedException ex)
|
||||
{
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
@@ -711,7 +711,7 @@ public class RepositoryImportResource
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (NotSupportedFeatureException ex)
|
||||
catch (FeatureNotSupportedException ex)
|
||||
{
|
||||
throw new WebApplicationException(ex, Response.Status.BAD_REQUEST);
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
package sonia.scm.api.v2;
|
||||
|
||||
import sonia.scm.NotSupportedFeatureException;
|
||||
import sonia.scm.api.rest.ContextualExceptionMapper;
|
||||
import sonia.scm.api.v2.resources.ExceptionWithContextToErrorDtoMapper;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.ext.Provider;
|
||||
|
||||
@Provider
|
||||
public class NotSupportedFeatureExceptionMapper extends ContextualExceptionMapper<NotSupportedFeatureException> {
|
||||
@Inject
|
||||
public NotSupportedFeatureExceptionMapper(ExceptionWithContextToErrorDtoMapper mapper) {
|
||||
super(NotSupportedFeatureException.class, Response.Status.BAD_REQUEST, mapper);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import sonia.scm.api.rest.ContextualExceptionMapper;
|
||||
import sonia.scm.user.ChangePasswordNotAllowedException;
|
||||
import sonia.scm.user.InvalidPasswordException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.ext.Provider;
|
||||
|
||||
@Provider
|
||||
public class ChangePasswordNotAllowedExceptionMapper extends ContextualExceptionMapper<ChangePasswordNotAllowedException> {
|
||||
@Inject
|
||||
public ChangePasswordNotAllowedExceptionMapper(ExceptionWithContextToErrorDtoMapper mapper) {
|
||||
super(ChangePasswordNotAllowedException.class, Response.Status.BAD_REQUEST, mapper);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import sonia.scm.api.rest.ContextualExceptionMapper;
|
||||
import sonia.scm.user.InvalidPasswordException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.ext.Provider;
|
||||
|
||||
@Provider
|
||||
public class InvalidPasswordExceptionMapper extends ContextualExceptionMapper<InvalidPasswordException> {
|
||||
|
||||
@Inject
|
||||
public InvalidPasswordExceptionMapper(ExceptionWithContextToErrorDtoMapper mapper) {
|
||||
super(InvalidPasswordException.class, Response.Status.BAD_REQUEST, mapper);
|
||||
}
|
||||
}
|
||||
@@ -51,12 +51,12 @@ import java.util.concurrent.TimeUnit;
|
||||
* @author Sebastian Sdorra
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public final class AccessTokenCookieIssuer {
|
||||
public final class DefaultAccessTokenCookieIssuer implements AccessTokenCookieIssuer {
|
||||
|
||||
/**
|
||||
* the logger for AccessTokenCookieIssuer
|
||||
* the logger for DefaultAccessTokenCookieIssuer
|
||||
*/
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AccessTokenCookieIssuer.class);
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DefaultAccessTokenCookieIssuer.class);
|
||||
|
||||
private final ScmConfiguration configuration;
|
||||
|
||||
@@ -66,7 +66,7 @@ public final class AccessTokenCookieIssuer {
|
||||
* @param configuration scm main configuration
|
||||
*/
|
||||
@Inject
|
||||
public AccessTokenCookieIssuer(ScmConfiguration configuration) {
|
||||
public DefaultAccessTokenCookieIssuer(ScmConfiguration configuration) {
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
@@ -87,6 +87,7 @@ public final class JwtAccessToken implements AccessToken {
|
||||
return ofNullable(claims.get(REFRESHABLE_UNTIL_CLAIM_KEY, Date.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getParentKey() {
|
||||
return ofNullable(claims.get(PARENT_TOKEN_ID_CLAIM_KEY).toString());
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import sonia.scm.security.AccessToken;
|
||||
import sonia.scm.security.AccessTokenBuilder;
|
||||
import sonia.scm.security.AccessTokenBuilderFactory;
|
||||
import sonia.scm.security.AccessTokenCookieIssuer;
|
||||
import sonia.scm.security.DefaultAccessTokenCookieIssuer;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -46,7 +47,7 @@ public class AuthenticationResourceTest {
|
||||
@Mock
|
||||
private AccessTokenBuilder accessTokenBuilder;
|
||||
|
||||
private AccessTokenCookieIssuer cookieIssuer = new AccessTokenCookieIssuer(mock(ScmConfiguration.class));
|
||||
private AccessTokenCookieIssuer cookieIssuer = new DefaultAccessTokenCookieIssuer(mock(ScmConfiguration.class));
|
||||
|
||||
private static final String AUTH_JSON_TRILLIAN = "{\n" +
|
||||
"\t\"cookie\": true,\n" +
|
||||
|
||||
@@ -4,9 +4,9 @@ import org.jboss.resteasy.core.Dispatcher;
|
||||
import org.jboss.resteasy.mock.MockDispatcherFactory;
|
||||
import sonia.scm.api.rest.AlreadyExistsExceptionMapper;
|
||||
import sonia.scm.api.rest.AuthorizationExceptionMapper;
|
||||
import sonia.scm.api.rest.BadRequestExceptionMapper;
|
||||
import sonia.scm.api.rest.ConcurrentModificationExceptionMapper;
|
||||
import sonia.scm.api.v2.NotFoundExceptionMapper;
|
||||
import sonia.scm.api.v2.NotSupportedFeatureExceptionMapper;
|
||||
|
||||
public class DispatcherMock {
|
||||
public static Dispatcher createDispatcher(Object resource) {
|
||||
@@ -18,9 +18,7 @@ public class DispatcherMock {
|
||||
dispatcher.getProviderFactory().register(new ConcurrentModificationExceptionMapper(mapper));
|
||||
dispatcher.getProviderFactory().registerProvider(AuthorizationExceptionMapper.class);
|
||||
dispatcher.getProviderFactory().register(new InternalRepositoryExceptionMapper(mapper));
|
||||
dispatcher.getProviderFactory().register(new ChangePasswordNotAllowedExceptionMapper(mapper));
|
||||
dispatcher.getProviderFactory().register(new InvalidPasswordExceptionMapper(mapper));
|
||||
dispatcher.getProviderFactory().register(new NotSupportedFeatureExceptionMapper(mapper));
|
||||
dispatcher.getProviderFactory().register(new BadRequestExceptionMapper(mapper));
|
||||
return dispatcher;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,11 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AccessTokenCookieIssuerTest {
|
||||
public class DefaultAccessTokenCookieIssuerTest {
|
||||
|
||||
private ScmConfiguration configuration;
|
||||
|
||||
private AccessTokenCookieIssuer issuer;
|
||||
private DefaultAccessTokenCookieIssuer issuer;
|
||||
|
||||
@Mock
|
||||
private HttpServletRequest request;
|
||||
@@ -41,7 +41,7 @@ public class AccessTokenCookieIssuerTest {
|
||||
@Before
|
||||
public void setUp() {
|
||||
configuration = new ScmConfiguration();
|
||||
issuer = new AccessTokenCookieIssuer(configuration);
|
||||
issuer = new DefaultAccessTokenCookieIssuer(configuration);
|
||||
}
|
||||
|
||||
@Test
|
||||
Reference in New Issue
Block a user