diff --git a/scm-core/src/main/java/sonia/scm/ScmState.java b/scm-core/src/main/java/sonia/scm/ScmState.java index cd36aa707c..84fb07a1f7 100644 --- a/scm-core/src/main/java/sonia/scm/ScmState.java +++ b/scm-core/src/main/java/sonia/scm/ScmState.java @@ -85,7 +85,7 @@ public final class ScmState public ScmState(String version, User user, Collection groups, String token, Collection repositoryTypes, String defaultUserType, ScmClientConfig clientConfig, List assignedPermission, - List availablePermissions) + Collection availablePermissions) { this.version = version; this.user = user; @@ -119,7 +119,7 @@ public final class ScmState * @return available global permissions * @since 1.31 */ - public List getAvailablePermissions() + public Collection getAvailablePermissions() { return availablePermissions; } @@ -232,7 +232,7 @@ public final class ScmState * Avaliable global permission * @since 1.31 */ - private List availablePermissions; + private Collection availablePermissions; /** Field description */ private ScmClientConfig clientConfig; diff --git a/scm-core/src/main/java/sonia/scm/ScmStateFactory.java b/scm-core/src/main/java/sonia/scm/ScmStateFactory.java index 41502a6850..e839a0ddcc 100644 --- a/scm-core/src/main/java/sonia/scm/ScmStateFactory.java +++ b/scm-core/src/main/java/sonia/scm/ScmStateFactory.java @@ -134,7 +134,7 @@ public final class ScmStateFactory User user = collection.oneByType(User.class); GroupNames groups = collection.oneByType(GroupNames.class); - List ap = Collections.EMPTY_LIST; + Collection ap = Collections.EMPTY_LIST; if (subject.hasRole(Role.ADMIN)) { @@ -150,7 +150,7 @@ public final class ScmStateFactory private ScmState createState(User user, Collection groups, String token, List assignedPermissions, - List availablePermissions) + Collection availablePermissions) { User u = user.clone(); diff --git a/scm-core/src/main/java/sonia/scm/security/PermissionDescriptor.java b/scm-core/src/main/java/sonia/scm/security/PermissionDescriptor.java index 20d95958a1..a005583256 100644 --- a/scm-core/src/main/java/sonia/scm/security/PermissionDescriptor.java +++ b/scm-core/src/main/java/sonia/scm/security/PermissionDescriptor.java @@ -67,19 +67,8 @@ public class PermissionDescriptor implements Serializable */ public PermissionDescriptor() {} - /** - * Constructs ... - * - * - * @param displayName - * @param description - * @param value - */ - public PermissionDescriptor(String displayName, String description, - String value) + public PermissionDescriptor(String value) { - this.displayName = displayName; - this.description = description; this.value = value; } @@ -103,9 +92,7 @@ public class PermissionDescriptor implements Serializable final PermissionDescriptor other = (PermissionDescriptor) obj; - return Objects.equal(displayName, other.displayName) - && Objects.equal(description, other.description) - && Objects.equal(value, other.value); + return Objects.equal(value, other.value); } /** @@ -114,7 +101,7 @@ public class PermissionDescriptor implements Serializable @Override public int hashCode() { - return Objects.hashCode(displayName, description, value); + return value.hashCode(); } /** @@ -126,8 +113,6 @@ public class PermissionDescriptor implements Serializable //J- return MoreObjects.toStringHelper(this) - .add("displayName", displayName) - .add("description", description) .add("value", value) .toString(); @@ -136,28 +121,6 @@ public class PermissionDescriptor implements Serializable //~--- get methods ---------------------------------------------------------- - /** - * Returns the description of the permission. - * - * - * @return description - */ - public String getDescription() - { - return description; - } - - /** - * Returns the display name of the permission. - * - * - * @return display name - */ - public String getDisplayName() - { - return displayName; - } - /** * Returns the string representation of the permission. * @@ -171,13 +134,6 @@ public class PermissionDescriptor implements Serializable //~--- fields --------------------------------------------------------------- - /** description */ - private String description; - - /** display name */ - @XmlElement(name = "display-name") - private String displayName; - /** value */ private String value; } diff --git a/scm-core/src/main/java/sonia/scm/security/SecuritySystem.java b/scm-core/src/main/java/sonia/scm/security/SecuritySystem.java index f43afcb7f2..f99625a5a9 100644 --- a/scm-core/src/main/java/sonia/scm/security/SecuritySystem.java +++ b/scm-core/src/main/java/sonia/scm/security/SecuritySystem.java @@ -38,6 +38,7 @@ import com.google.common.base.Predicate; //~--- JDK imports ------------------------------------------------------------ +import java.util.Collection; import java.util.List; /** @@ -75,41 +76,15 @@ public interface SecuritySystem */ public void deletePermission(String id); - /** - * Modify stored permission. - * - * - * @param permission stored permisison - */ - public void modifyPermission(StoredAssignedPermission permission); - //~--- get methods ---------------------------------------------------------- - /** - * Return all stored permissions. - * - * - * @return stored permission - */ - public List getAllPermissions(); - /** * Return all available permissions. * * * @return available permissions */ - public List getAvailablePermissions(); - - /** - * Return the stored permission which is stored with the given id. - * - * - * @param id id of the stored permission - * - * @return stored permission - */ - public StoredAssignedPermission getPermission(String id); + public Collection getAvailablePermissions(); /** * Returns all stored permissions which are matched by the given @@ -120,6 +95,6 @@ public interface SecuritySystem * * @return filtered permissions */ - public List getPermissions( + public Collection getPermissions( Predicate predicate); } diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AbstractPermissionResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AbstractPermissionResource.java deleted file mode 100644 index 040eb6b2dc..0000000000 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AbstractPermissionResource.java +++ /dev/null @@ -1,298 +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.api.rest.resources; - -//~--- non-JDK imports -------------------------------------------------------- - -import com.google.common.base.Function; -import com.google.common.base.Predicate; -import com.google.common.collect.Lists; -import com.webcohesion.enunciate.metadata.rs.ResponseCode; -import com.webcohesion.enunciate.metadata.rs.ResponseHeader; -import com.webcohesion.enunciate.metadata.rs.StatusCodes; -import com.webcohesion.enunciate.metadata.rs.TypeHint; - -import sonia.scm.api.rest.Permission; -import sonia.scm.security.AssignedPermission; -import sonia.scm.security.SecuritySystem; -import sonia.scm.security.StoredAssignedPermission; - -//~--- JDK imports ------------------------------------------------------------ - -import java.net.URI; - -import java.util.List; - -import javax.ws.rs.Consumes; -import javax.ws.rs.DELETE; -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.WebApplicationException; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; -import javax.ws.rs.core.UriInfo; - -/** - * Abstract base class for global permission resources. - * - * @author Sebastian Sdorra - * @since 1.31 - */ -public abstract class AbstractPermissionResource -{ - - /** - * Constructs a new {@link AbstractPermissionResource}. - * - * - * @param securitySystem security system - * @param name name of the user or group - */ - protected AbstractPermissionResource(SecuritySystem securitySystem, - String name) - { - this.securitySystem = securitySystem; - this.name = name; - } - - //~--- methods -------------------------------------------------------------- - - /** - * Transforms a {@link Permission} to a {@link AssignedPermission}. - * - * - * @param permission permission object to transform - * - * @return transformed {@link AssignedPermission} - */ - protected abstract AssignedPermission transformPermission( - Permission permission); - - //~--- get methods ---------------------------------------------------------- - - /** - * Returns a {@link Predicate} to filter permissions. - * - * - * @return {@link Predicate} to filter permissions - */ - protected abstract Predicate getPredicate(); - - //~--- methods -------------------------------------------------------------- - - /** - * Adds a new permission to the user or group managed by the resource. - * - * @param uriInfo uri informations - * @param permission permission to add - * - * @return web response - */ - @POST - @StatusCodes({ - @ResponseCode(code = 201, condition = "creates", additionalHeaders = { - @ResponseHeader(name = "Location", description = "uri to new create permission") - }), - @ResponseCode(code = 500, condition = "internal server error") - }) - @TypeHint(TypeHint.NO_CONTENT.class) - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - public Response add(@Context UriInfo uriInfo, Permission permission) - { - AssignedPermission ap = transformPermission(permission); - StoredAssignedPermission sap = securitySystem.addPermission(ap); - URI uri = uriInfo.getAbsolutePathBuilder().path(sap.getId()).build(); - - return Response.created(uri).build(); - } - - /** - * Deletes a permission from the user or group managed by the resource. - * - * @param id id of the permission - * - * @return web response - */ - @DELETE - @Path("{id}") - @StatusCodes({ - @ResponseCode(code = 204, condition = "success"), - @ResponseCode(code = 400, condition = "bad request, permission id does not belong to the user or group"), - @ResponseCode(code = 404, condition = "not found, no permission with the specified id available"), - @ResponseCode(code = 500, condition = "internal server error") - }) - @TypeHint(TypeHint.NO_CONTENT.class) - public Response delete(@PathParam("id") String id) - { - StoredAssignedPermission sap = getPermission(id); - - securitySystem.deletePermission(sap); - - return Response.noContent().build(); - } - - /** - * Updates the specified permission on the user or group managed by the resource. - * - * @param id id of the permission - * @param permission updated permission - * - * @return web response - */ - @PUT - @Path("{id}") - @StatusCodes({ - @ResponseCode(code = 204, condition = "success"), - @ResponseCode(code = 400, condition = "bad request, permission id does not belong to the user or group"), - @ResponseCode(code = 404, condition = "not found, no permission with the specified id available"), - @ResponseCode(code = 500, condition = "internal server error") - }) - @TypeHint(TypeHint.NO_CONTENT.class) - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - public Response update(@PathParam("id") String id, Permission permission) - { - StoredAssignedPermission sap = getPermission(id); - - securitySystem.modifyPermission(new StoredAssignedPermission(sap.getId(), - transformPermission(permission))); - - return Response.noContent().build(); - } - - //~--- get methods ---------------------------------------------------------- - - /** - * Returns the {@link Permission} with the specified id. - * - * @param id id of the {@link Permission} - * - * @return {@link Permission} with the specified id - */ - @GET - @Path("{id}") - @StatusCodes({ - @ResponseCode(code = 204, condition = "success"), - @ResponseCode(code = 400, condition = "bad request, permission id does not belong to the user or group"), - @ResponseCode(code = 404, condition = "not found, no permission with the specified id available"), - @ResponseCode(code = 500, condition = "internal server error") - }) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - public Permission get(@PathParam("id") String id) - { - StoredAssignedPermission sap = getPermission(id); - - return new Permission(sap.getId(), sap.getPermission()); - } - - /** - * Returns all permissions of the user or group managed by the resource. - * - * @return all permissions of the user or group - */ - @GET - @StatusCodes({ - @ResponseCode(code = 204, condition = "success"), - @ResponseCode(code = 500, condition = "internal server error") - }) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - public List getAll() - { - return getPermissions(getPredicate()); - } - - /** - * Returns the {@link StoredAssignedPermission} with the given id. - * - * - * @param id id of the stored permission - * - * @return {@link StoredAssignedPermission} with the given id - */ - private StoredAssignedPermission getPermission(String id) - { - StoredAssignedPermission sap = securitySystem.getPermission(id); - - if (sap == null) - { - throw new WebApplicationException(Status.NOT_FOUND); - } - - if (!getPredicate().apply(sap)) - { - throw new WebApplicationException(Status.BAD_REQUEST); - } - - return sap; - } - - /** - * Returns all permissions which matches the given {@link Predicate}. - * - * - * @param predicate predicate for filtering - * - * @return all permissions which matches the given {@link Predicate} - */ - private List getPermissions( - Predicate predicate) - { - List permissions = - securitySystem.getPermissions(predicate); - - return Lists.transform(permissions, - new Function() - { - - @Override - public Permission apply(StoredAssignedPermission mgp) - { - return new Permission(mgp.getId(), mgp.getPermission()); - } - }); - } - - //~--- fields --------------------------------------------------------------- - - /** name of the user or the group */ - protected String name; - - /** security system */ - private SecuritySystem securitySystem; -} diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/GroupPermissionResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/GroupPermissionResource.java deleted file mode 100644 index b591d6a2a3..0000000000 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/GroupPermissionResource.java +++ /dev/null @@ -1,127 +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.api.rest.resources; - -//~--- non-JDK imports -------------------------------------------------------- - -import com.google.common.base.Predicate; - -import sonia.scm.api.rest.Permission; -import sonia.scm.security.AssignedPermission; -import sonia.scm.security.SecuritySystem; - -/** - * Resource to manage global group permission for a specified group. - * - * @author Sebastian Sdorra - * @since 1.31 - */ -public class GroupPermissionResource extends AbstractPermissionResource -{ - - /** - * Constructs a new group permissions resource - * - * - * @param securitySystem security system - * @param name name of the group - */ - public GroupPermissionResource(SecuritySystem securitySystem, String name) - { - super(securitySystem, name); - } - - //~--- methods -------------------------------------------------------------- - - /** - * {@inheritDoc} - */ - @Override - protected AssignedPermission transformPermission(Permission permission) - { - return new AssignedPermission(name, true, permission.getValue()); - } - - //~--- get methods ---------------------------------------------------------- - - /** - * {@inheritDoc} - */ - @Override - protected Predicate getPredicate() - { - return new GroupPredicate(name); - } - - //~--- inner classes -------------------------------------------------------- - - /** - * Group predicate to filter permissions. - */ - private static class GroupPredicate implements Predicate - { - - /** - * Constructs a new group predicate - * - * - * @param name name of the group - */ - public GroupPredicate(String name) - { - this.name = name; - } - - //~--- methods ------------------------------------------------------------ - - /** - * Returns true if the permission is a group permission and the name is - * equals. - * - * @param input permission - * - * @return true if the permission is a group permission and the name is - * equals - */ - @Override - public boolean apply(AssignedPermission input) - { - return input.isGroupPermission() && input.getName().equals(name); - } - - //~--- fields ------------------------------------------------------------- - - /** name of the group */ - private String name; - } -} diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/SecuritySystemResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/SecuritySystemResource.java deleted file mode 100644 index f9e95232db..0000000000 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/SecuritySystemResource.java +++ /dev/null @@ -1,106 +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.api.rest.resources; - -//~--- non-JDK imports -------------------------------------------------------- - -import com.google.inject.Inject; - -import org.apache.shiro.SecurityUtils; - -import sonia.scm.security.Role; -import sonia.scm.security.SecuritySystem; - -//~--- JDK imports ------------------------------------------------------------ - -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; - -/** - * Resource for managing system security permissions. - * - * @author Sebastian Sdorra - */ -@Path("security/permission") -public class SecuritySystemResource -{ - - /** - * Constructs ... - * - * - * @param system - */ - @Inject - public SecuritySystemResource(SecuritySystem system) - { - this.system = system; - - // only administrators can use this resource - SecurityUtils.getSubject().checkRole(Role.ADMIN); - } - - //~--- get methods ---------------------------------------------------------- - - /** - * Returns group permission sub resource. - * - * @param group name of group - * - * @return sub resource - */ - @Path("group/{group}") - public GroupPermissionResource getGroupSubResource(@PathParam("group") String group) - { - return new GroupPermissionResource(system, group); - } - - /** - * Returns user permission sub resource. - * - * - * @param user name of user - * - * @return sub resource - */ - @Path("user/{user}") - public UserPermissionResource getUserSubResource(@PathParam("user") String user) - { - return new UserPermissionResource(system, user); - } - - //~--- fields --------------------------------------------------------------- - - /** Field description */ - private final SecuritySystem system; -} diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/UserPermissionResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/UserPermissionResource.java deleted file mode 100644 index 5f82fb98eb..0000000000 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/UserPermissionResource.java +++ /dev/null @@ -1,127 +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.api.rest.resources; - -//~--- non-JDK imports -------------------------------------------------------- - -import com.google.common.base.Predicate; - -import sonia.scm.api.rest.Permission; -import sonia.scm.security.AssignedPermission; -import sonia.scm.security.SecuritySystem; - -/** - * Resource to manage global user permission for a specified user. - * - * @author Sebastian Sdorra - * @since 1.31 - */ -public class UserPermissionResource extends AbstractPermissionResource -{ - - /** - * Constructs a new user permission resource. - * - * - * @param securitySystem security system - * @param name name of the user - */ - public UserPermissionResource(SecuritySystem securitySystem, String name) - { - super(securitySystem, name); - } - - //~--- methods -------------------------------------------------------------- - - /** - * {@inheritDoc} - */ - @Override - protected AssignedPermission transformPermission(Permission permission) - { - return new AssignedPermission(name, permission.getValue()); - } - - //~--- get methods ---------------------------------------------------------- - - /** - * {@inheritDoc} - */ - @Override - protected Predicate getPredicate() - { - return new UserPredicate(name); - } - - //~--- inner classes -------------------------------------------------------- - - /** - * User predicate to filter permissions. - */ - private static class UserPredicate implements Predicate - { - - /** - * Constructs a new user predicate. - * - * - * @param name name of the user - */ - public UserPredicate(String name) - { - this.name = name; - } - - //~--- methods ------------------------------------------------------------ - - /** - * Returns true if the permission is a user permission and the name is - * equals. - * - * @param input permission - * - * @return true if the permission is a user permission and the name is - * equals - */ - @Override - public boolean apply(AssignedPermission input) - { - return !input.isGroupPermission() && input.getName().equals(name); - } - - //~--- fields ------------------------------------------------------------- - - /** name of the user */ - private String name; - } -} diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/GlobalPermissionPocResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/GlobalPermissionPocResource.java index 6c564a43bd..369fd376c7 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/GlobalPermissionPocResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/GlobalPermissionPocResource.java @@ -2,12 +2,15 @@ package sonia.scm.api.v2.resources; import lombok.extern.slf4j.Slf4j; import sonia.scm.security.AssignedPermission; +import sonia.scm.security.PermissionDescriptor; import sonia.scm.security.SecuritySystem; import javax.inject.Inject; import javax.ws.rs.Consumes; +import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; +import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; @@ -71,8 +74,6 @@ public class GlobalPermissionPocResource { // Core: scm-webapp/src/main/resources/META-INF/scm/permissions.xml // Plugins, e.g. scm-plugins/scm-git-plugin/src/main/resources/META-INF/scm/permissions.xml log.info("{} Available permissions: {}", securitySystem.getAvailablePermissions().size(), securitySystem.getAvailablePermissions()); - // Should contain all stored permissions. See assignExemplaryPermissions() for example. - log.info("{} All permissions: {}", securitySystem.getAllPermissions().size(), securitySystem.getAllPermissions()); assignExemplaryPermissions(); @@ -80,12 +81,20 @@ public class GlobalPermissionPocResource { return Response.noContent().build(); } + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("") + public Response getAll() { + String[] permissions = securitySystem.getAvailablePermissions().stream().map(PermissionDescriptor::getValue).toArray(String[]::new); + return Response.ok(new PerminssionListDto(permissions)).build(); + } + protected void assignExemplaryPermissions() { AssignedPermission groupPermission = new AssignedPermission("configurers", true,"configuration:*"); log.info("try to add new permission: {}", groupPermission); securitySystem.addPermission(groupPermission); - AssignedPermission userPermission = new AssignedPermission("arthur", "group:*"); + AssignedPermission userPermission = new AssignedPermission("rene", "group:*"); log.info("try to add new permission: {}", userPermission); securitySystem.addPermission(userPermission); } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PerminssionListDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PerminssionListDto.java new file mode 100644 index 0000000000..3752d089f7 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PerminssionListDto.java @@ -0,0 +1,15 @@ +package sonia.scm.api.v2.resources; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +public class PerminssionListDto { + + private String[] permissions; +} diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserResource.java index 0076d057ca..70381c3304 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserResource.java @@ -4,12 +4,14 @@ 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.authc.credential.PasswordService; +import sonia.scm.security.PermissionDescriptor; +import sonia.scm.security.SecuritySystem; +import sonia.scm.security.StoredAssignedPermission; import sonia.scm.user.User; import sonia.scm.user.UserManager; import sonia.scm.web.VndMediaType; import javax.inject.Inject; -import javax.inject.Named; import javax.validation.Valid; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; @@ -28,14 +30,16 @@ public class UserResource { private final IdResourceManagerAdapter adapter; private final UserManager userManager; private final PasswordService passwordService; + private final SecuritySystem securitySystem; @Inject - public UserResource(UserDtoToUserMapper dtoToUserMapper, UserToUserDtoMapper userToDtoMapper, UserManager manager, PasswordService passwordService) { + public UserResource(UserDtoToUserMapper dtoToUserMapper, UserToUserDtoMapper userToDtoMapper, UserManager manager, PasswordService passwordService, SecuritySystem securitySystem) { this.dtoToUserMapper = dtoToUserMapper; this.userToDtoMapper = userToDtoMapper; this.adapter = new IdResourceManagerAdapter<>(manager, User.class); this.userManager = manager; this.passwordService = passwordService; + this.securitySystem = securitySystem; } /** @@ -132,4 +136,25 @@ public class UserResource { userManager.overwritePassword(name, passwordService.encryptPassword(passwordOverwrite.getNewPassword())); return Response.noContent().build(); } + + /** + * Returns permissions for a user. + * + * @param id the id/name of the user + */ + @GET + @Path("permissions") + @Produces(VndMediaType.USER) + @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 user"), + @ResponseCode(code = 404, condition = "not found, no user with the specified id/name available"), + @ResponseCode(code = 500, condition = "internal server error") + }) + public Response getPermissions(@PathParam("id") String id) { + String[] permissions = securitySystem.getPermissions(p -> !p.isGroupPermission() && p.getName().equals(id)).stream().map(StoredAssignedPermission::getPermission).toArray(String[]::new); + return Response.ok(new PerminssionListDto(permissions)).build(); + } } diff --git a/scm-webapp/src/main/java/sonia/scm/security/DefaultAuthorizationCollector.java b/scm-webapp/src/main/java/sonia/scm/security/DefaultAuthorizationCollector.java index 8a79293642..0a347a1a03 100644 --- a/scm-webapp/src/main/java/sonia/scm/security/DefaultAuthorizationCollector.java +++ b/scm-webapp/src/main/java/sonia/scm/security/DefaultAuthorizationCollector.java @@ -175,7 +175,7 @@ public class DefaultAuthorizationCollector implements AuthorizationCollector private void collectGlobalPermissions(Builder builder, final User user, final GroupNames groups) { - List globalPermissions = + Collection globalPermissions = securitySystem.getPermissions((AssignedPermission input) -> isUserPermitted(user, groups, input)); for (StoredAssignedPermission gp : globalPermissions) diff --git a/scm-webapp/src/main/java/sonia/scm/security/DefaultSecuritySystem.java b/scm-webapp/src/main/java/sonia/scm/security/DefaultSecuritySystem.java index 780b3832bc..1869558345 100644 --- a/scm-webapp/src/main/java/sonia/scm/security/DefaultSecuritySystem.java +++ b/scm-webapp/src/main/java/sonia/scm/security/DefaultSecuritySystem.java @@ -39,8 +39,8 @@ import com.github.legman.Subscribe; import com.google.common.base.Preconditions; import com.google.common.base.Predicate; import com.google.common.base.Strings; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableList.Builder; +import com.google.common.collect.ImmutableSet.Builder; +import com.google.common.collect.ImmutableSet; import com.google.inject.Inject; import com.google.inject.Singleton; import org.apache.shiro.SecurityUtils; @@ -62,6 +62,7 @@ import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import java.io.IOException; import java.net.URL; +import java.util.Collection; import java.util.Collections; import java.util.Enumeration; import java.util.List; @@ -92,8 +93,6 @@ public class DefaultSecuritySystem implements SecuritySystem private static final Logger logger = LoggerFactory.getLogger(DefaultSecuritySystem.class); - private PluginLoader pluginLoader; - //~--- constructors --------------------------------------------------------- /** @@ -110,8 +109,7 @@ public class DefaultSecuritySystem implements SecuritySystem .withType(AssignedPermission.class) .withName(NAME) .build(); - this.pluginLoader = pluginLoader; - readAvailablePermissions(); + this.availablePermissions = readAvailablePermissions(pluginLoader); } //~--- methods -------------------------------------------------------------- @@ -228,31 +226,6 @@ public class DefaultSecuritySystem implements SecuritySystem } } - /** - * Method description - * - * - * @param permission - */ - @Override - public void modifyPermission(StoredAssignedPermission permission) - { - assertIsAdmin(); - validatePermission(permission); - - synchronized (store) - { - store.remove(permission.getId()); - store.put(permission.getId(), new AssignedPermission(permission)); - } - - //J- - ScmEventBus.getInstance().post( - new StoredAssignedPermissionEvent(HandlerEventType.CREATE, permission) - ); - //J+ - } - //~--- get methods ---------------------------------------------------------- /** @@ -262,49 +235,13 @@ public class DefaultSecuritySystem implements SecuritySystem * @return */ @Override - public List getAllPermissions() - { - return getPermissions(null); - } - - /** - * Method description - * - * - * @return - */ - @Override - public List getAvailablePermissions() + public Collection getAvailablePermissions() { assertIsAdmin(); return availablePermissions; } - /** - * Method description - * - * - * @param id - * - * @return - */ - @Override - public StoredAssignedPermission getPermission(String id) - { - assertIsAdmin(); - - StoredAssignedPermission sap = null; - AssignedPermission ap = store.get(id); - - if (ap != null) - { - sap = new StoredAssignedPermission(id, ap); - } - - return sap; - } - /** * Method description * @@ -314,10 +251,9 @@ public class DefaultSecuritySystem implements SecuritySystem * @return */ @Override - public List getPermissions( - Predicate predicate) + public Collection getPermissions(Predicate predicate) { - Builder permissions = ImmutableList.builder(); + Builder permissions = ImmutableSet.builder(); for (Entry e : store.getAll().entrySet()) { @@ -349,7 +285,7 @@ public class DefaultSecuritySystem implements SecuritySystem */ private void deletePermissions(Predicate predicate) { - List permissions = getPermissions(predicate); + Collection permissions = getPermissions(predicate); for (StoredAssignedPermission permission : permissions) { @@ -367,7 +303,7 @@ public class DefaultSecuritySystem implements SecuritySystem * @return */ @SuppressWarnings("unchecked") - private List parsePermissionDescriptor( + private static List parsePermissionDescriptor( JAXBContext context, URL descriptorUrl) { List descriptors = Collections.EMPTY_LIST; @@ -395,10 +331,11 @@ public class DefaultSecuritySystem implements SecuritySystem /** * Method description * + * @param pluginLoader */ - private void readAvailablePermissions() + private static ImmutableSet readAvailablePermissions(PluginLoader pluginLoader) { - Builder builder = ImmutableList.builder(); + ImmutableSet.Builder builder = ImmutableSet.builder(); try { @@ -428,7 +365,7 @@ public class DefaultSecuritySystem implements SecuritySystem "could not create jaxb context to read permission descriptors", ex); } - availablePermissions = builder.build(); + return builder.build(); } /** @@ -455,12 +392,6 @@ public class DefaultSecuritySystem implements SecuritySystem private static class PermissionDescriptors { - /** - * Constructs ... - * - */ - public PermissionDescriptors() {} - //~--- get methods -------------------------------------------------------- /** @@ -494,5 +425,5 @@ public class DefaultSecuritySystem implements SecuritySystem private final ConfigurationEntryStore store; /** Field description */ - private List availablePermissions; + private final ImmutableSet availablePermissions; } diff --git a/scm-webapp/src/main/resources/META-INF/scm/permissions.xml b/scm-webapp/src/main/resources/META-INF/scm/permissions.xml index 537ada0bce..8978b050ca 100644 --- a/scm-webapp/src/main/resources/META-INF/scm/permissions.xml +++ b/scm-webapp/src/main/resources/META-INF/scm/permissions.xml @@ -34,21 +34,15 @@ - All Repository (read) - Read access to all repositories - repository:*:READ + repository:read:* - All Repository (write) - Write access to all repositories repository:*:WRITE - All Repository (owner) - Owner access to all repositories repository:*:OWNER - + diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UserRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UserRootResourceTest.java index 284e7d1d7b..06376675df 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UserRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UserRootResourceTest.java @@ -17,6 +17,7 @@ import org.mockito.Mock; import sonia.scm.ContextEntry; import sonia.scm.NotFoundException; import sonia.scm.PageResult; +import sonia.scm.security.SecuritySystem; import sonia.scm.user.ChangePasswordNotAllowedException; import sonia.scm.user.User; import sonia.scm.user.UserManager; @@ -59,6 +60,8 @@ public class UserRootResourceTest { private PasswordService passwordService; @Mock private UserManager userManager; + @Mock + private SecuritySystem securitySystem; @InjectMocks private UserDtoToUserMapperImpl dtoToUserMapper; @InjectMocks @@ -80,7 +83,7 @@ public class UserRootResourceTest { UserCollectionToDtoMapper userCollectionToDtoMapper = new UserCollectionToDtoMapper(userToDtoMapper, resourceLinks); UserCollectionResource userCollectionResource = new UserCollectionResource(userManager, dtoToUserMapper, userCollectionToDtoMapper, resourceLinks, passwordService); - UserResource userResource = new UserResource(dtoToUserMapper, userToDtoMapper, userManager, passwordService); + UserResource userResource = new UserResource(dtoToUserMapper, userToDtoMapper, userManager, passwordService, securitySystem); UserRootResource userRootResource = new UserRootResource(Providers.of(userCollectionResource), Providers.of(userResource)); diff --git a/scm-webapp/src/test/java/sonia/scm/security/DefaultSecuritySystemTest.java b/scm-webapp/src/test/java/sonia/scm/security/DefaultSecuritySystemTest.java index efae4b8ee5..ed6bac7bea 100644 --- a/scm-webapp/src/test/java/sonia/scm/security/DefaultSecuritySystemTest.java +++ b/scm-webapp/src/test/java/sonia/scm/security/DefaultSecuritySystemTest.java @@ -32,9 +32,6 @@ package sonia.scm.security; -//~--- non-JDK imports -------------------------------------------------------- - -import com.google.common.base.Predicate; import org.apache.shiro.authz.UnauthorizedException; import org.apache.shiro.mgt.DefaultSecurityManager; import org.apache.shiro.realm.SimpleAccountRealm; @@ -48,14 +45,15 @@ import sonia.scm.store.JAXBConfigurationEntryStoreFactory; import sonia.scm.util.ClassLoaders; import sonia.scm.util.MockUtil; +import java.util.Collection; import java.util.List; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.hamcrest.Matchers.greaterThan; -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; - -//~--- JDK imports ------------------------------------------------------------ +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; /** * @@ -111,10 +109,10 @@ public class DefaultSecuritySystemTest extends AbstractTestBase { setAdminSubject(); - List list = securitySystem.getAvailablePermissions(); + Collection list = securitySystem.getAvailablePermissions(); assertNotNull(list); - assertThat(list.size(), greaterThan(0)); + assertThat(list).isNotEmpty(); } /** @@ -131,7 +129,7 @@ public class DefaultSecuritySystemTest extends AbstractTestBase securitySystem.deletePermission(sap); - assertNull(securitySystem.getPermission(sap.getId())); + assertThat(securitySystem.getPermissions(p -> p.getName().equals("trillian"))).isEmpty(); } /** @@ -150,10 +148,10 @@ public class DefaultSecuritySystemTest extends AbstractTestBase StoredAssignedPermission marvin = createPermission("marvin", false, "repository:*:READ"); - List all = securitySystem.getAllPermissions(); + List all = securitySystem.getPermissions(p -> true); assertEquals(3, all.size()); - assertThat(all, containsInAnyOrder(trillian, dent, marvin)); + assertThat(all).contains(trillian, dent, marvin); } /** @@ -168,10 +166,9 @@ public class DefaultSecuritySystemTest extends AbstractTestBase StoredAssignedPermission sap = createPermission("trillian", false, "repository:*:READ"); - StoredAssignedPermission other = securitySystem.getPermission(sap.getId()); + List other = securitySystem.getPermissions(p -> p.getName().equals("trillian")); - assertEquals(sap.getId(), other.getId()); - assertEquals(sap, other); + assertThat(other).containsExactly(sap); } /** @@ -191,41 +188,11 @@ public class DefaultSecuritySystemTest extends AbstractTestBase createPermission("hitchhiker", true, "repository:*:READ"); List filtered = - securitySystem.getPermissions(new Predicate() - { + securitySystem.getPermissions(p -> !p.isGroupPermission()); - @Override - public boolean apply(AssignedPermission input) - { - return !input.isGroupPermission(); - } - }); - - assertEquals(2, filtered.size()); - assertThat(filtered, containsInAnyOrder(trillian, dent)); - } - - /** - * Method description - * - */ - @Test - public void testModifyPermission() - { - setAdminSubject(); - - StoredAssignedPermission sap = createPermission("trillian", false, - "repository:*:READ"); - StoredAssignedPermission modified = - new StoredAssignedPermission(sap.getId(), - new AssignedPermission("trillian", "repository:*:WRITE")); - - securitySystem.modifyPermission(modified); - - sap = securitySystem.getPermission(modified.getId()); - - assertEquals(modified.getId(), sap.getId()); - assertEquals(modified, sap); + assertThat(filtered) + .hasSize(2) + .contains(trillian, dent); } /** @@ -268,24 +235,7 @@ public class DefaultSecuritySystemTest extends AbstractTestBase "repository:*:READ"); setUserSubject(); - securitySystem.getPermission(sap.getId()); - } - - /** - * Method description - * - */ - @Test(expected = UnauthorizedException.class) - public void testUnauthorizedModifyPermission() - { - setAdminSubject(); - - StoredAssignedPermission sap = createPermission("trillian", false, - "repository:*:READ"); - - setUserSubject(); - - securitySystem.modifyPermission(sap); + securitySystem.getPermissions(p -> true); } /**