start implementation of repository permissions

This commit is contained in:
Sebastian Sdorra
2015-07-09 20:29:07 +02:00
parent 480a188763
commit 6dd765e3be
22 changed files with 730 additions and 701 deletions

View File

@@ -0,0 +1,61 @@
/**
* Copyright (c) 2014, 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.api.rest;
//~--- non-JDK imports --------------------------------------------------------
import org.apache.shiro.authz.AuthorizationException;
//~--- JDK imports ------------------------------------------------------------
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
/**
*
* @author Sebastian Sdorra
* @since 2.0.0
*/
@Provider
public class AuthorizationExceptionMapper
extends StatusExceptionMapper<AuthorizationException>
{
/**
* Constructs ...
*
*/
public AuthorizationExceptionMapper()
{
super(AuthorizationException.class, Response.Status.FORBIDDEN);
}
}

View File

@@ -36,6 +36,7 @@ package sonia.scm.api.rest.resources;
//~--- non-JDK imports --------------------------------------------------------
import org.apache.commons.beanutils.BeanComparator;
import org.apache.shiro.authz.AuthorizationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -44,7 +45,6 @@ import sonia.scm.LastModifiedAware;
import sonia.scm.Manager;
import sonia.scm.ModelObject;
import sonia.scm.api.rest.RestExceptionResult;
import sonia.scm.security.ScmSecurityException;
import sonia.scm.util.AssertUtil;
import sonia.scm.util.HttpUtil;
import sonia.scm.util.Util;
@@ -71,7 +71,7 @@ import javax.ws.rs.core.UriInfo;
* @param <E>
*/
public abstract class AbstractManagerResource<T extends ModelObject,
E extends Exception>
E extends Exception>
{
/** the logger for AbstractManagerResource */
@@ -102,7 +102,7 @@ public abstract class AbstractManagerResource<T extends ModelObject,
* @return
*/
protected abstract GenericEntity<Collection<T>> createGenericEntity(
Collection<T> items);
Collection<T> items);
//~--- get methods ----------------------------------------------------------
@@ -140,7 +140,7 @@ public abstract class AbstractManagerResource<T extends ModelObject,
{
preCreate(item);
Response response = null;
Response response;
try
{
@@ -153,7 +153,7 @@ public abstract class AbstractManagerResource<T extends ModelObject,
uriInfo.getAbsolutePath().resolve(
getPathPart().concat("/").concat(id))).build();
}
catch (ScmSecurityException ex)
catch (AuthorizationException ex)
{
logger.warn("create is not allowd", ex);
response = Response.status(Status.FORBIDDEN).build();
@@ -189,7 +189,7 @@ public abstract class AbstractManagerResource<T extends ModelObject,
manager.delete(item);
response = Response.noContent().build();
}
catch (ScmSecurityException ex)
catch (AuthorizationException ex)
{
logger.warn("delete not allowd", ex);
response = Response.status(Response.Status.FORBIDDEN).build();
@@ -228,7 +228,7 @@ public abstract class AbstractManagerResource<T extends ModelObject,
manager.modify(item);
response = Response.noContent().build();
}
catch (ScmSecurityException ex)
catch (AuthorizationException ex)
{
logger.warn("update not allowd", ex);
response = Response.status(Response.Status.FORBIDDEN).build();
@@ -293,7 +293,7 @@ public abstract class AbstractManagerResource<T extends ModelObject,
* @return
*/
public Response getAll(Request request, int start, int limit, String sortby,
boolean desc)
boolean desc)
{
Collection<T> items = fetchItems(sortby, desc, start, limit);
@@ -376,7 +376,7 @@ public abstract class AbstractManagerResource<T extends ModelObject,
protected Response createErrorResonse(Throwable throwable)
{
return createErrorResonse(Status.INTERNAL_SERVER_ERROR,
throwable.getMessage(), throwable);
throwable.getMessage(), throwable);
}
/**
@@ -404,10 +404,10 @@ public abstract class AbstractManagerResource<T extends ModelObject,
* @return
*/
protected Response createErrorResonse(Status status, String message,
Throwable throwable)
Throwable throwable)
{
return Response.status(status).entity(new RestExceptionResult(message,
throwable)).build();
throwable)).build();
}
/**
@@ -486,7 +486,7 @@ public abstract class AbstractManagerResource<T extends ModelObject,
* @return
*/
private <I> Response createCacheResponse(Request request,
LastModifiedAware timeItem, I item)
LastModifiedAware timeItem, I item)
{
return createCacheResponse(request, timeItem, item, item);
}
@@ -504,7 +504,7 @@ public abstract class AbstractManagerResource<T extends ModelObject,
* @return
*/
private <I> Response createCacheResponse(Request request,
LastModifiedAware timeItem, Object entityItem, I item)
LastModifiedAware timeItem, Object entityItem, I item)
{
Response.ResponseBuilder builder = null;
Date lastModified = getLastModified(timeItem);
@@ -568,7 +568,7 @@ public abstract class AbstractManagerResource<T extends ModelObject,
* @return
*/
private Collection<T> fetchItems(String sortby, boolean desc, int start,
int limit)
int limit)
{
AssertUtil.assertPositive(start);

View File

@@ -55,7 +55,6 @@ import sonia.scm.repository.Changeset;
import sonia.scm.repository.ChangesetPagingResult;
import sonia.scm.repository.HealthChecker;
import sonia.scm.repository.Permission;
import sonia.scm.repository.PermissionType;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryException;
import sonia.scm.repository.RepositoryIsNotArchivedException;
@@ -71,8 +70,6 @@ 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.security.RepositoryPermission;
import sonia.scm.security.ScmSecurityException;
import sonia.scm.util.AssertUtil;
import sonia.scm.util.HttpUtil;
import sonia.scm.util.IOUtil;
@@ -103,6 +100,7 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.StreamingOutput;
import javax.ws.rs.core.UriInfo;
import org.apache.shiro.authz.AuthorizationException;
/**
*
@@ -196,7 +194,7 @@ public class RepositoryResource
@Override
public Response delete(@PathParam("id") String id)
{
Response response = null;
Response response;
Repository repository = manager.get(id);
if (repository != null)
@@ -213,12 +211,12 @@ public class RepositoryResource
logger.warn("non archived repository could not be deleted", ex);
response = Response.status(Response.Status.PRECONDITION_FAILED).build();
}
catch (ScmSecurityException ex)
catch (AuthorizationException ex)
{
logger.warn("delete not allowed", ex);
response = Response.status(Response.Status.FORBIDDEN).build();
}
catch (Exception ex)
catch (RepositoryException | IOException ex)
{
logger.error("error during create", ex);
response = createErrorResonse(ex);
@@ -263,12 +261,7 @@ public class RepositoryResource
logger.warn("could not find repository ".concat(id), ex);
response = Response.status(Status.NOT_FOUND).build();
}
catch (RepositoryException ex)
{
logger.error("error occured during health check", ex);
response = Response.serverError().build();
}
catch (IOException ex)
catch (RepositoryException | IOException ex)
{
logger.error("error occured during health check", ex);
response = Response.serverError().build();
@@ -610,7 +603,7 @@ public class RepositoryResource
public Response getByTypeAndName(@PathParam("type") String type,
@PathParam("name") String name)
{
Response response = null;
Response response;
Repository repository = repositoryManager.get(type, name);
if (repository != null)
@@ -690,11 +683,7 @@ public class RepositoryResource
}
else
{
if (logger.isWarnEnabled())
{
logger.warn("id or revision is empty");
}
logger.warn("id or revision is empty");
response = Response.status(Status.BAD_REQUEST).build();
}
@@ -745,7 +734,7 @@ public class RepositoryResource
try
{
ChangesetPagingResult changesets = null;
ChangesetPagingResult changesets;
service = servicefactory.create(id);
@@ -819,9 +808,9 @@ public class RepositoryResource
public Response getContent(@PathParam("id") String id,
@QueryParam("revision") String revision, @QueryParam("path") String path)
{
Response response = null;
StreamingOutput output = null;
RepositoryService service = null;
Response response;
StreamingOutput output;
RepositoryService service;
try
{
@@ -905,8 +894,8 @@ public class RepositoryResource
*/
HttpUtil.checkForCRLFInjection(revision);
RepositoryService service = null;
Response response = null;
RepositoryService service;
Response response;
try
{
@@ -1062,7 +1051,8 @@ public class RepositoryResource
@Override
protected Repository prepareForReturn(Repository repository)
{
if (isOwner(repository))
if (SecurityUtils.getSubject().isPermitted(
"repository:modify:".concat(repository.getId())))
{
if (repository.getPermissions() == null)
{
@@ -1071,11 +1061,8 @@ public class RepositoryResource
}
else
{
if (logger.isTraceEnabled())
{
logger.trace("remove properties and permissions from repository, "
+ "because the user is not privileged");
}
logger.trace("remove properties and permissions from repository, "
+ "because the user is not privileged");
repository.setProperties(null);
repository.setPermissions(null);
@@ -1147,22 +1134,7 @@ public class RepositoryResource
return getContentDispositionName(name);
}
/**
* Method description
*
*
* @param repository
*
* @return
*/
private boolean isOwner(Repository repository)
{
return SecurityUtils.getSubject().isPermitted(
new RepositoryPermission(repository, PermissionType.OWNER));
}
//~--- fields ---------------------------------------------------------------
/** Field description */