mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-13 17:05:43 +01:00
Merged 2.0.0-m3 into feature/global_config_v2_endpoint
This commit is contained in:
@@ -38,7 +38,6 @@ package sonia.scm;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.multibindings.Multibinder;
|
||||
import com.google.inject.name.Names;
|
||||
import com.google.inject.servlet.RequestScoped;
|
||||
import com.google.inject.servlet.ServletModule;
|
||||
import com.google.inject.throwingproviders.ThrowingProviderBinder;
|
||||
@@ -57,16 +56,8 @@ import sonia.scm.group.xml.XmlGroupDAO;
|
||||
import sonia.scm.io.DefaultFileSystem;
|
||||
import sonia.scm.io.FileSystem;
|
||||
import sonia.scm.net.SSLContextProvider;
|
||||
import sonia.scm.net.ahc.AdvancedHttpClient;
|
||||
import sonia.scm.net.ahc.ContentTransformer;
|
||||
import sonia.scm.net.ahc.DefaultAdvancedHttpClient;
|
||||
import sonia.scm.net.ahc.JsonContentTransformer;
|
||||
import sonia.scm.net.ahc.XmlContentTransformer;
|
||||
import sonia.scm.plugin.DefaultPluginLoader;
|
||||
import sonia.scm.plugin.DefaultPluginManager;
|
||||
import sonia.scm.plugin.ExtensionProcessor;
|
||||
import sonia.scm.plugin.PluginLoader;
|
||||
import sonia.scm.plugin.PluginManager;
|
||||
import sonia.scm.net.ahc.*;
|
||||
import sonia.scm.plugin.*;
|
||||
import sonia.scm.repository.*;
|
||||
import sonia.scm.repository.api.HookContextFactory;
|
||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
@@ -78,32 +69,12 @@ import sonia.scm.resources.ResourceManager;
|
||||
import sonia.scm.resources.ScriptResourceServlet;
|
||||
import sonia.scm.schedule.QuartzScheduler;
|
||||
import sonia.scm.schedule.Scheduler;
|
||||
import sonia.scm.security.AuthorizationChangedEventProducer;
|
||||
import sonia.scm.security.CipherHandler;
|
||||
import sonia.scm.security.CipherUtil;
|
||||
import sonia.scm.security.ConfigurableLoginAttemptHandler;
|
||||
import sonia.scm.security.DefaultKeyGenerator;
|
||||
import sonia.scm.security.DefaultSecuritySystem;
|
||||
import sonia.scm.security.KeyGenerator;
|
||||
import sonia.scm.security.LoginAttemptHandler;
|
||||
import sonia.scm.security.SecuritySystem;
|
||||
import sonia.scm.store.BlobStoreFactory;
|
||||
import sonia.scm.store.ConfigurationEntryStoreFactory;
|
||||
import sonia.scm.store.ConfigurationStoreFactory;
|
||||
import sonia.scm.store.DataStoreFactory;
|
||||
import sonia.scm.store.FileBlobStoreFactory;
|
||||
import sonia.scm.store.JAXBConfigurationEntryStoreFactory;
|
||||
import sonia.scm.store.JAXBConfigurationStoreFactory;
|
||||
import sonia.scm.store.JAXBDataStoreFactory;
|
||||
import sonia.scm.security.*;
|
||||
import sonia.scm.store.*;
|
||||
import sonia.scm.template.MustacheTemplateEngine;
|
||||
import sonia.scm.template.TemplateEngine;
|
||||
import sonia.scm.template.TemplateEngineFactory;
|
||||
import sonia.scm.template.TemplateServlet;
|
||||
import sonia.scm.url.RestJsonUrlProvider;
|
||||
import sonia.scm.url.RestXmlUrlProvider;
|
||||
import sonia.scm.url.UrlProvider;
|
||||
import sonia.scm.url.UrlProviderFactory;
|
||||
import sonia.scm.url.WebUIUrlProvider;
|
||||
import sonia.scm.user.DefaultUserManager;
|
||||
import sonia.scm.user.UserDAO;
|
||||
import sonia.scm.user.UserManager;
|
||||
@@ -223,7 +194,9 @@ public class ScmServletModule extends ServletModule
|
||||
|
||||
ScmConfiguration config = getScmConfiguration();
|
||||
CipherUtil cu = CipherUtil.getInstance();
|
||||
|
||||
|
||||
bind(NamespaceStrategy.class).toProvider(NamespaceStrategyProvider.class);
|
||||
|
||||
// bind repository provider
|
||||
ThrowingProviderBinder.create(binder()).bind(
|
||||
RepositoryProvider.class, Repository.class).to(
|
||||
@@ -303,17 +276,6 @@ public class ScmServletModule extends ServletModule
|
||||
bind(ResourceManager.class, DefaultResourceManager.class);
|
||||
}
|
||||
|
||||
// bind url provider staff
|
||||
bind(UrlProvider.class).annotatedWith(
|
||||
Names.named(UrlProviderFactory.TYPE_RESTAPI_JSON)).toProvider(
|
||||
RestJsonUrlProvider.class);
|
||||
bind(UrlProvider.class).annotatedWith(
|
||||
Names.named(UrlProviderFactory.TYPE_RESTAPI_XML)).toProvider(
|
||||
RestXmlUrlProvider.class);
|
||||
bind(UrlProvider.class).annotatedWith(
|
||||
Names.named(UrlProviderFactory.TYPE_WUI)).toProvider(
|
||||
WebUIUrlProvider.class);
|
||||
|
||||
// bind repository service factory
|
||||
bind(RepositoryServiceFactory.class);
|
||||
|
||||
@@ -351,10 +313,10 @@ public class ScmServletModule extends ServletModule
|
||||
// bind events
|
||||
// bind(LastModifiedUpdateListener.class);
|
||||
|
||||
Class<? extends NamespaceStrategy> namespaceStrategy = extensionProcessor.byExtensionPoint(NamespaceStrategy.class).iterator().next();
|
||||
bind(NamespaceStrategy.class, namespaceStrategy);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
|
||||
@@ -48,13 +48,8 @@ import sonia.scm.util.AssertUtil;
|
||||
import sonia.scm.util.HttpUtil;
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
import javax.ws.rs.core.CacheControl;
|
||||
import javax.ws.rs.core.EntityTag;
|
||||
import javax.ws.rs.core.GenericEntity;
|
||||
import javax.ws.rs.core.Request;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.*;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.beans.BeanInfo;
|
||||
import java.beans.IntrospectionException;
|
||||
import java.beans.Introspector;
|
||||
|
||||
@@ -47,22 +47,8 @@ import sonia.scm.group.GroupException;
|
||||
import sonia.scm.group.GroupManager;
|
||||
import sonia.scm.security.Role;
|
||||
|
||||
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;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.GenericEntity;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Request;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import javax.ws.rs.*;
|
||||
import javax.ws.rs.core.*;
|
||||
import java.util.Collection;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
@@ -50,15 +50,7 @@ import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.NotSupportedFeatuerException;
|
||||
import sonia.scm.Type;
|
||||
import sonia.scm.api.rest.RestActionUploadResult;
|
||||
import sonia.scm.repository.AdvancedImportHandler;
|
||||
import sonia.scm.repository.ImportHandler;
|
||||
import sonia.scm.repository.ImportResult;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryAlreadyExistsException;
|
||||
import sonia.scm.repository.RepositoryException;
|
||||
import sonia.scm.repository.RepositoryHandler;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.repository.RepositoryType;
|
||||
import sonia.scm.repository.*;
|
||||
import sonia.scm.repository.api.Command;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
@@ -66,21 +58,8 @@ import sonia.scm.repository.api.UnbundleCommandBuilder;
|
||||
import sonia.scm.security.Role;
|
||||
import sonia.scm.util.IOUtil;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.FormParam;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.GenericEntity;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import javax.ws.rs.*;
|
||||
import javax.ws.rs.core.*;
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
@@ -543,7 +522,8 @@ public class RepositoryImportResource
|
||||
|
||||
try
|
||||
{
|
||||
repository = new Repository(null, type, name);
|
||||
// TODO #8783
|
||||
// repository = new Repository(null, type, name);
|
||||
manager.create(repository);
|
||||
}
|
||||
catch (RepositoryAlreadyExistsException ex)
|
||||
@@ -738,7 +718,8 @@ public class RepositoryImportResource
|
||||
{
|
||||
for (String repositoryName : repositoryNames)
|
||||
{
|
||||
Repository repository = manager.get(type, repositoryName);
|
||||
// TODO #8783
|
||||
/*Repository repository = null; //manager.get(type, repositoryName);
|
||||
|
||||
if (repository != null)
|
||||
{
|
||||
@@ -748,7 +729,7 @@ public class RepositoryImportResource
|
||||
{
|
||||
logger.warn("could not find imported repository {}",
|
||||
repositoryName);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,51 +46,16 @@ import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authz.AuthorizationException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.repository.BlameResult;
|
||||
import sonia.scm.repository.Branches;
|
||||
import sonia.scm.repository.BrowserResult;
|
||||
import sonia.scm.repository.Changeset;
|
||||
import sonia.scm.repository.ChangesetPagingResult;
|
||||
import sonia.scm.repository.HealthChecker;
|
||||
import sonia.scm.repository.Permission;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryException;
|
||||
import sonia.scm.repository.RepositoryIsNotArchivedException;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.repository.RepositoryNotFoundException;
|
||||
import sonia.scm.repository.Tags;
|
||||
import sonia.scm.repository.api.BlameCommandBuilder;
|
||||
import sonia.scm.repository.api.BrowseCommandBuilder;
|
||||
import sonia.scm.repository.api.CatCommandBuilder;
|
||||
import sonia.scm.repository.api.CommandNotSupportedException;
|
||||
import sonia.scm.repository.api.DiffCommandBuilder;
|
||||
import sonia.scm.repository.api.DiffFormat;
|
||||
import sonia.scm.repository.api.LogCommandBuilder;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
import sonia.scm.repository.*;
|
||||
import sonia.scm.repository.api.*;
|
||||
import sonia.scm.util.AssertUtil;
|
||||
import sonia.scm.util.HttpUtil;
|
||||
import sonia.scm.util.IOUtil;
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
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;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.GenericEntity;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Request;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.*;
|
||||
import javax.ws.rs.core.*;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import javax.ws.rs.core.StreamingOutput;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -556,42 +521,6 @@ public class RepositoryResource extends AbstractManagerResource<Repository, Repo
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Repository} with the specified type and name.
|
||||
*
|
||||
* @param type the type of the repository
|
||||
* @param name the name of the repository
|
||||
*
|
||||
* @return the {@link Repository} with the specified type and name
|
||||
*/
|
||||
@GET
|
||||
@Path("{type: [a-z]+}/{name: .*}")
|
||||
@StatusCodes({
|
||||
@ResponseCode(code = 200, condition = "success"),
|
||||
@ResponseCode(code = 404, condition = "not found, no repository with the specified type and name available"),
|
||||
@ResponseCode(code = 500, condition = "internal server error")
|
||||
})
|
||||
@TypeHint(Repository.class)
|
||||
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
public Response getByTypeAndName(@PathParam("type") String type,
|
||||
@PathParam("name") String name)
|
||||
{
|
||||
Response response;
|
||||
Repository repository = repositoryManager.get(type, name);
|
||||
|
||||
if (repository != null)
|
||||
{
|
||||
prepareForReturn(repository);
|
||||
response = Response.ok(repository).build();
|
||||
}
|
||||
else
|
||||
{
|
||||
response = Response.status(Response.Status.NOT_FOUND).build();
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Changeset} from the given repository
|
||||
* with the specified revision.
|
||||
|
||||
@@ -44,8 +44,6 @@ import com.google.inject.Inject;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.repository.RepositoryTypePredicate;
|
||||
import sonia.scm.url.UrlProvider;
|
||||
import sonia.scm.url.UrlProviderFactory;
|
||||
import sonia.scm.util.HttpUtil;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
@@ -106,19 +104,15 @@ public class RepositoryRootResource
|
||||
*/
|
||||
@GET
|
||||
@Produces(MediaType.TEXT_HTML)
|
||||
public Viewable renderRepositoriesRoot(@Context HttpServletRequest request,
|
||||
@PathParam("type") final String type)
|
||||
throws IOException
|
||||
public Viewable renderRepositoriesRoot(@Context HttpServletRequest request, @PathParam("type") final String type)
|
||||
{
|
||||
String baseUrl = HttpUtil.getCompleteUrl(request);
|
||||
UrlProvider uiUrlProvider = UrlProviderFactory.createUrlProvider(baseUrl,
|
||||
UrlProviderFactory.TYPE_WUI);
|
||||
//J-
|
||||
Collection<RepositoryTemplateElement> unsortedRepositories =
|
||||
Collections2.transform(
|
||||
Collections2.filter(
|
||||
repositoryManager.getAll(), new RepositoryTypePredicate(type))
|
||||
, new RepositoryTransformFunction(uiUrlProvider, baseUrl)
|
||||
, new RepositoryTransformFunction(baseUrl)
|
||||
);
|
||||
|
||||
List<RepositoryTemplateElement> repositories = Ordering.from(
|
||||
@@ -149,43 +143,16 @@ public class RepositoryRootResource
|
||||
*
|
||||
*
|
||||
* @param repository
|
||||
* @param uiUrlProvider
|
||||
* @param baseUrl
|
||||
*/
|
||||
public RepositoryTemplateElement(Repository repository,
|
||||
UrlProvider uiUrlProvider, String baseUrl)
|
||||
public RepositoryTemplateElement(Repository repository, String baseUrl)
|
||||
{
|
||||
this.repository = repository;
|
||||
this.urlProvider = uiUrlProvider;
|
||||
this.baseUrl = baseUrl;
|
||||
}
|
||||
|
||||
//~--- get methods --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getCommitUrl()
|
||||
{
|
||||
return urlProvider.getRepositoryUrlProvider().getChangesetUrl(
|
||||
repository.getId(), 0, 20);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getDetailUrl()
|
||||
{
|
||||
return urlProvider.getRepositoryUrlProvider().getDetailUrl(
|
||||
repository.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -208,18 +175,6 @@ public class RepositoryRootResource
|
||||
return repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getSourceUrl()
|
||||
{
|
||||
return urlProvider.getRepositoryUrlProvider().getBrowseUrl(
|
||||
repository.getId(), null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -239,8 +194,6 @@ public class RepositoryRootResource
|
||||
/** Field description */
|
||||
private Repository repository;
|
||||
|
||||
/** Field description */
|
||||
private UrlProvider urlProvider;
|
||||
}
|
||||
|
||||
|
||||
@@ -284,20 +237,8 @@ public class RepositoryRootResource
|
||||
implements Function<Repository, RepositoryTemplateElement>
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param request
|
||||
* @param repositoryManager
|
||||
* @param urlProvider
|
||||
* @param baseUrl
|
||||
*/
|
||||
public RepositoryTransformFunction(UrlProvider urlProvider, String baseUrl)
|
||||
public RepositoryTransformFunction(String baseUrl)
|
||||
{
|
||||
this.urlProvider = urlProvider;
|
||||
this.baseUrl = baseUrl;
|
||||
}
|
||||
|
||||
@@ -314,15 +255,12 @@ public class RepositoryRootResource
|
||||
@Override
|
||||
public RepositoryTemplateElement apply(Repository repository)
|
||||
{
|
||||
return new RepositoryTemplateElement(repository, urlProvider, baseUrl);
|
||||
return new RepositoryTemplateElement(repository, baseUrl);
|
||||
}
|
||||
|
||||
//~--- fields -------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private String baseUrl;
|
||||
|
||||
/** Field description */
|
||||
private UrlProvider urlProvider;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,21 +50,8 @@ import sonia.scm.user.UserManager;
|
||||
import sonia.scm.util.AssertUtil;
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.GenericEntity;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Request;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import javax.ws.rs.*;
|
||||
import javax.ws.rs.core.*;
|
||||
import java.util.Collection;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import javax.ws.rs.FormParam;
|
||||
import java.util.List;
|
||||
|
||||
public class AuthenticationRequestDto {
|
||||
|
||||
@FormParam("grant_type")
|
||||
@JsonProperty("grant_type")
|
||||
private String grantType;
|
||||
|
||||
@FormParam("username")
|
||||
private String username;
|
||||
|
||||
@FormParam("password")
|
||||
private String password;
|
||||
|
||||
@FormParam("cookie")
|
||||
private boolean cookie;
|
||||
|
||||
@FormParam("scope")
|
||||
private List<String> scope;
|
||||
|
||||
public String getGrantType() {
|
||||
return grantType;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public boolean isCookie() {
|
||||
return cookie;
|
||||
}
|
||||
|
||||
public List<String> getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
// password is currently the only valid grant_type
|
||||
return "password".equals(grantType) && !Strings.isNullOrEmpty(username) && !Strings.isNullOrEmpty(password);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
||||
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.security.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.ws.rs.*;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
@Path(AuthenticationResource.PATH)
|
||||
public class AuthenticationResource {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AuthenticationResource.class);
|
||||
|
||||
static final String PATH = "v2/auth";
|
||||
|
||||
private final AccessTokenBuilderFactory tokenBuilderFactory;
|
||||
private final AccessTokenCookieIssuer cookieIssuer;
|
||||
|
||||
@Inject
|
||||
public AuthenticationResource(AccessTokenBuilderFactory tokenBuilderFactory, AccessTokenCookieIssuer cookieIssuer)
|
||||
{
|
||||
this.tokenBuilderFactory = tokenBuilderFactory;
|
||||
this.cookieIssuer = cookieIssuer;
|
||||
}
|
||||
|
||||
|
||||
@POST
|
||||
@Path("access_token")
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@StatusCodes({
|
||||
@ResponseCode(code = 200, condition = "success"),
|
||||
@ResponseCode(code = 400, condition = "bad request, required parameter is missing"),
|
||||
@ResponseCode(code = 401, condition = "unauthorized, the specified username or password is wrong"),
|
||||
@ResponseCode(code = 500, condition = "internal server error")
|
||||
})
|
||||
public Response authenticateViaForm(
|
||||
@Context HttpServletRequest request,
|
||||
@Context HttpServletResponse response,
|
||||
@BeanParam AuthenticationRequestDto authentication
|
||||
) {
|
||||
return authenticate(request, response, authentication);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("access_token")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@StatusCodes({
|
||||
@ResponseCode(code = 200, condition = "success"),
|
||||
@ResponseCode(code = 400, condition = "bad request, required parameter is missing"),
|
||||
@ResponseCode(code = 401, condition = "unauthorized, the specified username or password is wrong"),
|
||||
@ResponseCode(code = 500, condition = "internal server error")
|
||||
})
|
||||
public Response authenticateViaJSONBody(
|
||||
@Context HttpServletRequest request,
|
||||
@Context HttpServletResponse response,
|
||||
AuthenticationRequestDto authentication
|
||||
) {
|
||||
return authenticate(request, response, authentication);
|
||||
}
|
||||
|
||||
private Response authenticate(
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
AuthenticationRequestDto authentication
|
||||
) {
|
||||
if (!authentication.isValid()) {
|
||||
return Response.status(Response.Status.BAD_REQUEST).build();
|
||||
}
|
||||
|
||||
Response res;
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
|
||||
try
|
||||
{
|
||||
subject.login(Tokens.createAuthenticationToken(request, authentication.getUsername(), authentication.getPassword()));
|
||||
|
||||
AccessTokenBuilder tokenBuilder = tokenBuilderFactory.create();
|
||||
if ( authentication.getScope() != null ) {
|
||||
tokenBuilder.scope(Scope.valueOf(authentication.getScope()));
|
||||
}
|
||||
|
||||
AccessToken token = tokenBuilder.build();
|
||||
|
||||
if (authentication.isCookie()) {
|
||||
cookieIssuer.authenticate(request, response, token);
|
||||
res = Response.noContent().build();
|
||||
} else {
|
||||
res = Response.ok( token.compact() ).build();
|
||||
}
|
||||
}
|
||||
catch (AuthenticationException ex)
|
||||
{
|
||||
if (LOG.isTraceEnabled())
|
||||
{
|
||||
LOG.trace("authentication failed for user ".concat(authentication.getUsername()), ex);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.warn("authentication failed for user {}", authentication.getUsername());
|
||||
}
|
||||
|
||||
// TODO DisabledAccountException, ExcessiveAttemptsException for ui?
|
||||
|
||||
return Response.status(Response.Status.UNAUTHORIZED).build();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("access_token")
|
||||
@StatusCodes({
|
||||
@ResponseCode(code = 204, condition = "success"),
|
||||
@ResponseCode(code = 500, condition = "internal server error")
|
||||
})
|
||||
public Response logout(@Context HttpServletRequest request, @Context HttpServletResponse response)
|
||||
{
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
|
||||
subject.logout();
|
||||
|
||||
// remove authentication cookie
|
||||
cookieIssuer.invalidate(request, response);
|
||||
|
||||
// TODO anonymous access ??
|
||||
return Response.noContent().build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import de.otto.edison.hal.HalRepresentation;
|
||||
import de.otto.edison.hal.Links;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
public class ConfigDto extends HalRepresentation {
|
||||
|
||||
private String proxyPassword;
|
||||
private int proxyPort;
|
||||
private String proxyServer;
|
||||
private String proxyUser;
|
||||
private boolean enableProxy;
|
||||
private String realmDescription;
|
||||
private boolean enableRepositoryArchive;
|
||||
private boolean disableGroupingGrid;
|
||||
private String dateFormat;
|
||||
private boolean anonymousAccessEnabled;
|
||||
private Set<String> adminGroups;
|
||||
private Set<String> adminUsers;
|
||||
private String baseUrl;
|
||||
private boolean forceBaseUrl;
|
||||
private int loginAttemptLimit;
|
||||
private Set<String> proxyExcludes;
|
||||
private boolean skipFailedAuthenticators;
|
||||
private String pluginUrl;
|
||||
private long loginAttemptLimitTimeout;
|
||||
private boolean enabledXsrfProtection;
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("squid:S1185") // We want to have this method available in this package
|
||||
protected HalRepresentation add(Links links) {
|
||||
return super.add(links);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
|
||||
// Mapstruct does not support parameterized (i.e. non-default) constructors. Thus, we need to use field injection.
|
||||
@SuppressWarnings("squid:S3306")
|
||||
@Mapper
|
||||
public abstract class ConfigDtoToScmConfigurationMapper {
|
||||
|
||||
public abstract ScmConfiguration map(ConfigDto dto);
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
||||
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
|
||||
import com.webcohesion.enunciate.metadata.rs.TypeHint;
|
||||
import sonia.scm.config.ConfigurationPermissions;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.util.ScmConfigurationUtil;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
@Path(ConfigResource.CONFIG_PATH_V2)
|
||||
public class ConfigResource {
|
||||
|
||||
static final String CONFIG_PATH_V2 = "v2/config";
|
||||
private final ConfigDtoToScmConfigurationMapper dtoToConfigMapper;
|
||||
private final ScmConfigurationToConfigDtoMapper configToDtoMapper;
|
||||
private final ScmConfiguration configuration;
|
||||
|
||||
@Inject
|
||||
public ConfigResource(ConfigDtoToScmConfigurationMapper dtoToConfigMapper, ScmConfigurationToConfigDtoMapper configToDtoMapper, ScmConfiguration configuration) {
|
||||
this.dtoToConfigMapper = dtoToConfigMapper;
|
||||
this.configToDtoMapper = configToDtoMapper;
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the global scm config.
|
||||
*/
|
||||
@GET
|
||||
@Path("")
|
||||
@Produces(VndMediaType.CONFIG)
|
||||
@TypeHint(UserDto.class)
|
||||
@StatusCodes({
|
||||
@ResponseCode(code = 200, condition = "success"),
|
||||
@ResponseCode(code = 401, condition = "not authenticated / invalid credentials"),
|
||||
@ResponseCode(code = 403, condition = "not authorized, the current user has no privileges to read the global config"),
|
||||
@ResponseCode(code = 500, condition = "internal server error")
|
||||
})
|
||||
public Response get() {
|
||||
|
||||
// We do this permission check in Resource and not in ScmConfiguration, because it must be available for reading
|
||||
// from within the code (plugins, etc.), but not for the whole anonymous world outside.
|
||||
ConfigurationPermissions.read(configuration).check();
|
||||
|
||||
return Response.ok(configToDtoMapper.map(configuration)).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies the global scm config.
|
||||
*
|
||||
* @param configDto new global scm configuration as DTO
|
||||
*/
|
||||
@PUT
|
||||
@Path("")
|
||||
@Consumes(VndMediaType.CONFIG)
|
||||
@StatusCodes({
|
||||
@ResponseCode(code = 201, condition = "update success"),
|
||||
@ResponseCode(code = 401, condition = "not authenticated / invalid credentials"),
|
||||
@ResponseCode(code = 403, condition = "not authorized, the current user has no privileges to update the global config"),
|
||||
@ResponseCode(code = 500, condition = "internal server error")
|
||||
})
|
||||
@TypeHint(TypeHint.NO_CONTENT.class)
|
||||
public Response update(ConfigDto configDto, @Context UriInfo uriInfo) {
|
||||
|
||||
// This *could* be moved to ScmConfiguration or ScmConfigurationUtil classes.
|
||||
// But to where to check? load() or store()? Leave it for now, SCMv1 legacy that can be cleaned up later.
|
||||
ConfigurationPermissions.write(configuration).check();
|
||||
|
||||
ScmConfiguration config = dtoToConfigMapper.map(configDto);
|
||||
synchronized (ScmConfiguration.class) {
|
||||
configuration.load(config);
|
||||
ScmConfigurationUtil.getInstance().store(configuration);
|
||||
}
|
||||
|
||||
return Response.noContent().build();
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,13 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
||||
import com.webcohesion.enunciate.metadata.rs.ResponseHeader;
|
||||
import com.webcohesion.enunciate.metadata.rs.ResponseHeaders;
|
||||
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
|
||||
import com.webcohesion.enunciate.metadata.rs.TypeHint;
|
||||
import com.webcohesion.enunciate.metadata.rs.*;
|
||||
import sonia.scm.group.Group;
|
||||
import sonia.scm.group.GroupException;
|
||||
import sonia.scm.group.GroupManager;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.*;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
@@ -9,13 +9,7 @@ import sonia.scm.group.GroupManager;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.*;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
public class GroupResource {
|
||||
|
||||
@@ -15,6 +15,9 @@ public class MapperModule extends AbstractModule {
|
||||
bind(GroupToGroupDtoMapper.class).to(Mappers.getMapper(GroupToGroupDtoMapper.class).getClass());
|
||||
bind(GroupCollectionToDtoMapper.class);
|
||||
|
||||
bind(ScmConfigurationToConfigDtoMapper.class).to(Mappers.getMapper(ScmConfigurationToConfigDtoMapper.class).getClass());
|
||||
bind(ConfigDtoToScmConfigurationMapper.class).to(Mappers.getMapper(ConfigDtoToScmConfigurationMapper.class).getClass());
|
||||
|
||||
bind(RepositoryToRepositoryDtoMapper.class).to(Mappers.getMapper(RepositoryToRepositoryDtoMapper.class).getClass());
|
||||
bind(RepositoryDtoToRepositoryMapper.class).to(Mappers.getMapper(RepositoryDtoToRepositoryMapper.class).getClass());
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
||||
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
|
||||
import com.webcohesion.enunciate.metadata.rs.TypeHint;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserException;
|
||||
import sonia.scm.user.UserManager;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.Request;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
|
||||
@Path(MeResource.ME_PATH_V2)
|
||||
public class MeResource {
|
||||
static final String ME_PATH_V2 = "v2/me/";
|
||||
|
||||
private final UserToUserDtoMapper userToDtoMapper;
|
||||
|
||||
private final IdResourceManagerAdapter<User, UserDto, UserException> adapter;
|
||||
@Inject
|
||||
public MeResource(UserToUserDtoMapper userToDtoMapper, UserManager manager) {
|
||||
this.userToDtoMapper = userToDtoMapper;
|
||||
this.adapter = new IdResourceManagerAdapter<>(manager, User.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently logged in user or a 401 if user is not logged in
|
||||
*/
|
||||
@GET
|
||||
@Path("")
|
||||
@Produces(VndMediaType.USER)
|
||||
@TypeHint(UserDto.class)
|
||||
@StatusCodes({
|
||||
@ResponseCode(code = 200, condition = "success"),
|
||||
@ResponseCode(code = 401, condition = "not authenticated / invalid credentials"),
|
||||
@ResponseCode(code = 500, condition = "internal server error")
|
||||
})
|
||||
public Response get(@Context Request request, @Context UriInfo uriInfo) {
|
||||
|
||||
String id = (String) SecurityUtils.getSubject().getPrincipals().getPrimaryPrincipal();
|
||||
return adapter.get(id, userToDtoMapper::map);
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,13 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
||||
import com.webcohesion.enunciate.metadata.rs.ResponseHeader;
|
||||
import com.webcohesion.enunciate.metadata.rs.ResponseHeaders;
|
||||
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
|
||||
import com.webcohesion.enunciate.metadata.rs.TypeHint;
|
||||
import com.webcohesion.enunciate.metadata.rs.*;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryException;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.*;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
public class RepositoryCollectionResource {
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import org.mapstruct.AfterMapping;
|
||||
import org.mapstruct.Context;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.MappingTarget;
|
||||
import org.mapstruct.*;
|
||||
import sonia.scm.repository.Repository;
|
||||
|
||||
@Mapper
|
||||
|
||||
@@ -10,13 +10,7 @@ import sonia.scm.web.VndMediaType;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.*;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@@ -76,7 +76,7 @@ class ResourceLinks {
|
||||
return userLinkBuilder.method("getUserResource").parameters(name).method("delete").parameters().href();
|
||||
}
|
||||
|
||||
String update(String name) {
|
||||
String update(String name) {
|
||||
return userLinkBuilder.method("getUserResource").parameters(name).method("update").parameters().href();
|
||||
}
|
||||
}
|
||||
@@ -101,6 +101,26 @@ class ResourceLinks {
|
||||
}
|
||||
}
|
||||
|
||||
ConfigLinks config() {
|
||||
return new ConfigLinks(uriInfoStore.get());
|
||||
}
|
||||
|
||||
static class ConfigLinks {
|
||||
private final LinkBuilder configLinkBuilder;
|
||||
|
||||
ConfigLinks(UriInfo uriInfo) {
|
||||
configLinkBuilder = new LinkBuilder(uriInfo, ConfigResource.class);
|
||||
}
|
||||
|
||||
String self() {
|
||||
return configLinkBuilder.method("get").parameters().href();
|
||||
}
|
||||
|
||||
String update() {
|
||||
return configLinkBuilder.method("update").parameters().href();
|
||||
}
|
||||
}
|
||||
|
||||
public RepositoryLinks repository() {
|
||||
return new RepositoryLinks(uriInfoStore.get());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import de.otto.edison.hal.Links;
|
||||
import org.mapstruct.AfterMapping;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.MappingTarget;
|
||||
import sonia.scm.config.ConfigurationPermissions;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static de.otto.edison.hal.Link.link;
|
||||
import static de.otto.edison.hal.Links.linkingTo;
|
||||
|
||||
// Mapstruct does not support parameterized (i.e. non-default) constructors. Thus, we need to use field injection.
|
||||
@SuppressWarnings("squid:S3306")
|
||||
@Mapper
|
||||
public abstract class ScmConfigurationToConfigDtoMapper {
|
||||
|
||||
@Inject
|
||||
private ResourceLinks resourceLinks;
|
||||
|
||||
public abstract ConfigDto map(ScmConfiguration config);
|
||||
|
||||
@AfterMapping
|
||||
void appendLinks(ScmConfiguration config, @MappingTarget ConfigDto target) {
|
||||
Links.Builder linksBuilder = linkingTo().self(resourceLinks.config().self());
|
||||
if (ConfigurationPermissions.write(config).isPermitted()) {
|
||||
linksBuilder.single(link("update", resourceLinks.config().update()));
|
||||
}
|
||||
target.add(linksBuilder.build());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,23 +1,13 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
||||
import com.webcohesion.enunciate.metadata.rs.ResponseHeader;
|
||||
import com.webcohesion.enunciate.metadata.rs.ResponseHeaders;
|
||||
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
|
||||
import com.webcohesion.enunciate.metadata.rs.TypeHint;
|
||||
import com.webcohesion.enunciate.metadata.rs.*;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserException;
|
||||
import sonia.scm.user.UserManager;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.*;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
@@ -9,13 +9,7 @@ import sonia.scm.user.UserManager;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.*;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
public class UserResource {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import de.otto.edison.hal.Links;
|
||||
import org.mapstruct.AfterMapping;
|
||||
import org.mapstruct.Mapper;
|
||||
@@ -21,6 +22,11 @@ public abstract class UserToUserDtoMapper extends BaseMapper<User, UserDto> {
|
||||
@Inject
|
||||
private ResourceLinks resourceLinks;
|
||||
|
||||
@VisibleForTesting
|
||||
void setResourceLinks(ResourceLinks resourceLinks) {
|
||||
this.resourceLinks = resourceLinks;
|
||||
}
|
||||
|
||||
@AfterMapping
|
||||
void removePassword(@MappingTarget UserDto target) {
|
||||
target.setPassword(UserResource.DUMMY_PASSWORT);
|
||||
|
||||
@@ -49,6 +49,7 @@ import sonia.scm.security.Role;
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
// TODO before releasing v2, delete this filter (we use Permission objects now)
|
||||
@WebElement(
|
||||
value = Filters.PATTERN_CONFIG,
|
||||
morePatterns = {
|
||||
|
||||
@@ -44,6 +44,7 @@ import org.apache.shiro.subject.Subject;
|
||||
import sonia.scm.Priority;
|
||||
import sonia.scm.SCMContext;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.security.SecurityRequests;
|
||||
import sonia.scm.web.filter.HttpFilter;
|
||||
import sonia.scm.web.filter.SecurityHttpServletRequestWrapper;
|
||||
|
||||
@@ -69,45 +70,20 @@ public class SecurityFilter extends HttpFilter
|
||||
@VisibleForTesting
|
||||
static final String ATTRIBUTE_REMOTE_USER = "principal";
|
||||
|
||||
/** Field description */
|
||||
public static final String URL_AUTHENTICATION = "/api/rest/auth";
|
||||
private final ScmConfiguration configuration;
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param configuration
|
||||
*/
|
||||
@Inject
|
||||
public SecurityFilter(ScmConfiguration configuration)
|
||||
{
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @param chain
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Override
|
||||
protected void doFilter(HttpServletRequest request,
|
||||
HttpServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
String uri =
|
||||
request.getRequestURI().substring(request.getContextPath().length());
|
||||
|
||||
if (!uri.startsWith(URL_AUTHENTICATION))
|
||||
if (!SecurityRequests.isAuthenticationRequest(request))
|
||||
{
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
if (hasPermission(subject))
|
||||
@@ -139,16 +115,6 @@ public class SecurityFilter extends HttpFilter
|
||||
}
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param subject
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected boolean hasPermission(Subject subject)
|
||||
{
|
||||
return ((configuration != null)
|
||||
@@ -173,8 +139,4 @@ public class SecurityFilter extends HttpFilter
|
||||
return username;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** scm configuration */
|
||||
private final ScmConfiguration configuration;
|
||||
}
|
||||
|
||||
@@ -52,12 +52,7 @@ import sonia.scm.util.CollectionAppender;
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
package sonia.scm.repository;
|
||||
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import sonia.scm.plugin.Extension;
|
||||
|
||||
/**
|
||||
* The DefaultNamespaceStrategy returns the username of the currently logged in user as namespace.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@Extension
|
||||
public class DefaultNamespaceStrategy implements NamespaceStrategy{
|
||||
public class DefaultNamespaceStrategy implements NamespaceStrategy {
|
||||
|
||||
@Override
|
||||
public String getNamespace() {
|
||||
return "42";
|
||||
return SecurityUtils.getSubject().getPrincipal().toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,30 +42,14 @@ import com.google.inject.Singleton;
|
||||
import org.apache.shiro.concurrent.SubjectAwareExecutorService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.ArgumentIsInvalidException;
|
||||
import sonia.scm.ConfigurationException;
|
||||
import sonia.scm.HandlerEventType;
|
||||
import sonia.scm.ManagerDaoAdapter;
|
||||
import sonia.scm.SCMContextProvider;
|
||||
import sonia.scm.Type;
|
||||
import sonia.scm.*;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.security.KeyGenerator;
|
||||
import sonia.scm.util.AssertUtil;
|
||||
import sonia.scm.util.CollectionAppender;
|
||||
import sonia.scm.util.HttpUtil;
|
||||
import sonia.scm.util.IOUtil;
|
||||
import sonia.scm.util.Util;
|
||||
import sonia.scm.util.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
@@ -126,7 +110,7 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
|
||||
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
public void close() {
|
||||
executorService.shutdown();
|
||||
|
||||
for (RepositoryHandler handler : handlerMap.values()) {
|
||||
@@ -177,40 +161,16 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
|
||||
getHandler(toDelete).delete(toDelete);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repository
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
@Override
|
||||
public void importRepository(Repository repository)
|
||||
throws RepositoryException, IOException {
|
||||
create(repository, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
@Override
|
||||
public void init(SCMContextProvider context) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repository
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
@Override
|
||||
public void modify(Repository repository) throws RepositoryException {
|
||||
logger.info("modify repository {} of type {}", repository.getName(), repository.getType());
|
||||
@@ -226,23 +186,13 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repository
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
@Override
|
||||
public void refresh(Repository repository)
|
||||
throws RepositoryException {
|
||||
AssertUtil.assertIsNotNull(repository);
|
||||
RepositoryPermissions.read(repository).check();
|
||||
|
||||
Repository fresh = repositoryDAO.get(repository.getType(),
|
||||
repository.getName());
|
||||
Repository fresh = repositoryDAO.get(repository.getNamespaceAndName());
|
||||
|
||||
if (fresh != null) {
|
||||
fresh.copyProperties(repository);
|
||||
@@ -251,16 +201,7 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
|
||||
}
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Repository get(String id) {
|
||||
AssertUtil.assertIsNotEmpty(id);
|
||||
@@ -276,21 +217,13 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
|
||||
return repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param type
|
||||
* @param name
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Repository get(String type, String name) {
|
||||
AssertUtil.assertIsNotEmpty(type);
|
||||
AssertUtil.assertIsNotEmpty(name);
|
||||
public Repository get(NamespaceAndName namespaceAndName) {
|
||||
AssertUtil.assertIsNotNull(namespaceAndName);
|
||||
AssertUtil.assertIsNotEmpty(namespaceAndName.getNamespace());
|
||||
AssertUtil.assertIsNotEmpty(namespaceAndName.getName());
|
||||
|
||||
Repository repository = repositoryDAO.get(type, name);
|
||||
Repository repository = repositoryDAO.get(namespaceAndName);
|
||||
|
||||
if (repository != null) {
|
||||
RepositoryPermissions.read(repository).check();
|
||||
@@ -300,14 +233,6 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
|
||||
return repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param comparator
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Collection<Repository> getAll(Comparator<Repository> comparator) {
|
||||
List<Repository> repositories = Lists.newArrayList();
|
||||
@@ -330,28 +255,12 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
|
||||
return repositories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Collection<Repository> getAll() {
|
||||
return getAll(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param comparator
|
||||
* @param start
|
||||
* @param limit
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
|
||||
@Override
|
||||
public Collection<Repository> getAll(Comparator<Repository> comparator,
|
||||
int start, int limit) {
|
||||
@@ -369,26 +278,11 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
|
||||
}, start, limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param start
|
||||
* @param limit
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Collection<Repository> getAll(int start, int limit) {
|
||||
return getAll(null, start, limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Collection<Type> getConfiguredTypes() {
|
||||
List<Type> validTypes = Lists.newArrayList();
|
||||
@@ -402,14 +296,6 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
|
||||
return validTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param request
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Repository getFromRequest(HttpServletRequest request) {
|
||||
AssertUtil.assertIsNotNull(request);
|
||||
@@ -417,17 +303,28 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
|
||||
return getFromUri(HttpUtil.getStrippedURI(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param type
|
||||
* @param uri
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Repository getFromTypeAndUri(String type, String uri) {
|
||||
public Repository getFromUri(String uri) {
|
||||
AssertUtil.assertIsNotEmpty(uri);
|
||||
|
||||
if (uri.startsWith(HttpUtil.SEPARATOR_PATH)) {
|
||||
uri = uri.substring(1);
|
||||
}
|
||||
|
||||
int typeSeparator = uri.indexOf(HttpUtil.SEPARATOR_PATH);
|
||||
Repository repository = null;
|
||||
|
||||
if (typeSeparator > 0) {
|
||||
String type = uri.substring(0, typeSeparator);
|
||||
|
||||
uri = uri.substring(typeSeparator + 1);
|
||||
repository = getFromTypeAndUri(type, uri);
|
||||
}
|
||||
|
||||
return repository;
|
||||
}
|
||||
|
||||
private Repository getFromTypeAndUri(String type, String uri) {
|
||||
if (Strings.isNullOrEmpty(type)) {
|
||||
throw new ArgumentIsInvalidException("argument type is required");
|
||||
}
|
||||
@@ -464,80 +361,21 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
|
||||
return repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param uri
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Repository getFromUri(String uri) {
|
||||
AssertUtil.assertIsNotEmpty(uri);
|
||||
|
||||
if (uri.startsWith(HttpUtil.SEPARATOR_PATH)) {
|
||||
uri = uri.substring(1);
|
||||
}
|
||||
|
||||
int typeSeperator = uri.indexOf(HttpUtil.SEPARATOR_PATH);
|
||||
Repository repository = null;
|
||||
|
||||
if (typeSeperator > 0) {
|
||||
String type = uri.substring(0, typeSeperator);
|
||||
|
||||
uri = uri.substring(typeSeperator + 1);
|
||||
repository = getFromTypeAndUri(type, uri);
|
||||
}
|
||||
|
||||
return repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param type
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public RepositoryHandler getHandler(String type) {
|
||||
return handlerMap.get(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Long getLastModified() {
|
||||
return repositoryDAO.getLastModified();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Collection<Type> getTypes() {
|
||||
return types;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param contextProvider
|
||||
* @param handler
|
||||
*/
|
||||
private void addHandler(SCMContextProvider contextProvider,
|
||||
RepositoryHandler handler) {
|
||||
AssertUtil.assertIsNotNull(handler);
|
||||
@@ -561,19 +399,6 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
|
||||
types.add(type);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repository
|
||||
*
|
||||
* @return
|
||||
*
|
||||
*
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
private RepositoryHandler getHandler(Repository repository)
|
||||
throws RepositoryException {
|
||||
String type = repository.getType();
|
||||
|
||||
@@ -33,7 +33,7 @@ package sonia.scm.repository;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import com.github.legman.Subscribe;
|
||||
import com.google.inject.Inject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -32,14 +32,15 @@
|
||||
|
||||
package sonia.scm.repository;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.inject.Inject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.util.HttpUtil;
|
||||
import sonia.scm.util.Util;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.util.HttpUtil;
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* RepositoryMatcher is able to check if a repository matches the requested path.
|
||||
@@ -83,9 +84,24 @@ public final class RepositoryMatcher {
|
||||
}
|
||||
|
||||
private boolean isPathMatching(Repository repository, String path) {
|
||||
return getPathMatcherForType(repository.getType()).isPathMatching(repository, path);
|
||||
|
||||
String namespace = extractNamespace(path);
|
||||
String remainingPath = path.substring(namespace.length() + 1);
|
||||
|
||||
return getPathMatcherForType(repository.getType()).isPathMatching(repository, remainingPath);
|
||||
}
|
||||
|
||||
|
||||
private String extractNamespace(String path) {
|
||||
if (path.startsWith(HttpUtil.SEPARATOR_PATH)) {
|
||||
path = path.substring(1);
|
||||
}
|
||||
int namespaceSeparator = path.indexOf(HttpUtil.SEPARATOR_PATH);
|
||||
if (namespaceSeparator > 0) {
|
||||
return path.substring(0, namespaceSeparator);
|
||||
}
|
||||
throw new IllegalArgumentException("no namespace in path " + path);
|
||||
}
|
||||
|
||||
private RepositoryPathMatcher getPathMatcherForType(String type) {
|
||||
RepositoryPathMatcher pathMatcher = pathMatchers.get(type);
|
||||
if (pathMatcher == null) {
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
*/
|
||||
package sonia.scm.security;
|
||||
|
||||
import com.github.legman.Subscribe;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.EagerSingleton;
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package sonia.scm.security;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Created by masuewer on 04.07.18.
|
||||
*/
|
||||
public final class SecurityRequests {
|
||||
|
||||
private static final Pattern URI_LOGIN_PATTERN = Pattern.compile("/api/rest(?:/v2)?/auth/access_token");
|
||||
|
||||
private SecurityRequests() {}
|
||||
|
||||
public static boolean isAuthenticationRequest(HttpServletRequest request) {
|
||||
String uri = request.getRequestURI().substring(request.getContextPath().length());
|
||||
return isAuthenticationRequest(uri);
|
||||
}
|
||||
|
||||
public static boolean isAuthenticationRequest(String uri) {
|
||||
return URI_LOGIN_PATTERN.matcher(uri).matches();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.url;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class RestJsonUrlProvider implements Provider<UrlProvider>
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param configuration
|
||||
*/
|
||||
@Inject
|
||||
public RestJsonUrlProvider(ScmConfiguration configuration)
|
||||
{
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public UrlProvider get()
|
||||
{
|
||||
return UrlProviderFactory.createUrlProvider(configuration.getBaseUrl(),
|
||||
UrlProviderFactory.TYPE_RESTAPI_JSON);
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private ScmConfiguration configuration;
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.url;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class RestXmlUrlProvider implements Provider<UrlProvider>
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param configuration
|
||||
*/
|
||||
@Inject
|
||||
public RestXmlUrlProvider(ScmConfiguration configuration)
|
||||
{
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public UrlProvider get()
|
||||
{
|
||||
return UrlProviderFactory.createUrlProvider(configuration.getBaseUrl(),
|
||||
UrlProviderFactory.TYPE_RESTAPI_XML);
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private ScmConfiguration configuration;
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.url;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class WebUIUrlProvider implements Provider<UrlProvider>
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param configuration
|
||||
*/
|
||||
@Inject
|
||||
public WebUIUrlProvider(ScmConfiguration configuration)
|
||||
{
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public UrlProvider get()
|
||||
{
|
||||
return UrlProviderFactory.createUrlProvider(configuration.getBaseUrl(),
|
||||
UrlProviderFactory.TYPE_WUI);
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private ScmConfiguration configuration;
|
||||
}
|
||||
@@ -40,6 +40,7 @@ import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.EagerSingleton;
|
||||
import sonia.scm.HandlerEventType;
|
||||
import sonia.scm.ManagerDaoAdapter;
|
||||
import sonia.scm.SCMContextProvider;
|
||||
@@ -67,7 +68,7 @@ import java.util.List;
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@Singleton
|
||||
@Singleton @EagerSingleton
|
||||
public class DefaultUserManager extends AbstractUserManager
|
||||
{
|
||||
|
||||
|
||||
@@ -36,24 +36,22 @@ package sonia.scm.web.security;
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import sonia.scm.Priority;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.filter.Filters;
|
||||
import sonia.scm.filter.WebElement;
|
||||
import sonia.scm.web.filter.AuthenticationFilter;
|
||||
import sonia.scm.security.SecurityRequests;
|
||||
import sonia.scm.web.WebTokenGenerator;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.Set;
|
||||
import sonia.scm.web.filter.AuthenticationFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Filter to handle authentication for the rest api of SCM-Manager.
|
||||
@@ -66,9 +64,6 @@ import javax.servlet.http.HttpServletResponse;
|
||||
public class ApiAuthenticationFilter extends AuthenticationFilter
|
||||
{
|
||||
|
||||
/** login uri */
|
||||
public static final String URI_LOGIN = "/api/rest/auth/access_token";
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -104,7 +99,7 @@ public class ApiAuthenticationFilter extends AuthenticationFilter
|
||||
throws IOException, ServletException
|
||||
{
|
||||
// skip filter on login resource
|
||||
if (request.getRequestURI().contains(URI_LOGIN))
|
||||
if (SecurityRequests.isAuthenticationRequest(request))
|
||||
{
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user