From e2450d114ae66ddee6f61abfdf84d0205808f913 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Wed, 1 May 2013 14:11:45 +0200 Subject: [PATCH] added rest api for new security system --- .../java/sonia/scm/api/rest/Permission.java | 167 +++++++++++ .../resources/AbstractPermissionResource.java | 265 ++++++++++++++++++ .../resources/GroupPermissionResource.java | 135 +++++++++ ...ource.java => SecuritySystemResource.java} | 65 ++--- .../resources/UserPermissionResource.java | 135 +++++++++ 5 files changed, 720 insertions(+), 47 deletions(-) create mode 100644 scm-webapp/src/main/java/sonia/scm/api/rest/Permission.java create mode 100644 scm-webapp/src/main/java/sonia/scm/api/rest/resources/AbstractPermissionResource.java create mode 100644 scm-webapp/src/main/java/sonia/scm/api/rest/resources/GroupPermissionResource.java rename scm-webapp/src/main/java/sonia/scm/api/rest/resources/{SecurityConfigurationResource.java => SecuritySystemResource.java} (64%) create mode 100644 scm-webapp/src/main/java/sonia/scm/api/rest/resources/UserPermissionResource.java diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/Permission.java b/scm-webapp/src/main/java/sonia/scm/api/rest/Permission.java new file mode 100644 index 0000000000..bf6437e97c --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/Permission.java @@ -0,0 +1,167 @@ +/** + * 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; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.common.base.Objects; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.Serializable; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * + * @author Sebastian Sdorra + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class Permission implements Serializable +{ + + /** Field description */ + private static final long serialVersionUID = 4320217034601679261L; + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + */ + public Permission() {} + + /** + * Constructs ... + * + * + * @param id + * @param value + */ + public Permission(String id, String value) + { + this.id = id; + this.value = value; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param obj + * + * @return + */ + @Override + public boolean equals(Object obj) + { + if (obj == null) + { + return false; + } + + if (getClass() != obj.getClass()) + { + return false; + } + + final Permission other = (Permission) obj; + + return Objects.equal(id, other.id) && Objects.equal(value, other.value); + } + + /** + * Method description + * + * + * @return + */ + @Override + public int hashCode() + { + return Objects.hashCode(id, value); + } + + /** + * Method description + * + * + * @return + */ + @Override + public String toString() + { + //J- + return Objects.toStringHelper(this) + .add("id", id) + .add("value", value) + .toString(); + //J+ + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + public String getId() + { + return id; + } + + /** + * Method description + * + * + * @return + */ + public String getValue() + { + return value; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private String id; + + /** Field description */ + private String value; +} 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 new file mode 100644 index 0000000000..297145475c --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AbstractPermissionResource.java @@ -0,0 +1,265 @@ +/** + * 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 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; + +/** + * + * @author Sebastian Sdorra + * @since 1.31 + */ +public abstract class AbstractPermissionResource +{ + + /** + * Constructs ... + * + * + * @param securitySystem + * @param name + */ + protected AbstractPermissionResource(SecuritySystem securitySystem, + String name) + { + this.securitySystem = securitySystem; + this.name = name; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param permission + * + * @return + */ + protected abstract AssignedPermission transformPermission( + Permission permission); + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + protected abstract Predicate getPredicate(); + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param uriInfo + * @param permission + * + * @return + */ + @POST + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + 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(); + } + + /** + * Method description + * + * + * @param id + * + * @return + */ + @DELETE + @Path("{id}") + public Response delete(@PathParam("id") String id) + { + StoredAssignedPermission sap = getPermission(id); + + securitySystem.deletePermission(sap); + + return Response.noContent().build(); + } + + /** + * Method description + * + * + * @param id + * @param permission + * + * @return + */ + @PUT + @Path("{id}") + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + 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 ---------------------------------------------------------- + + /** + * Method description + * + * + * @param id + * + * @return + */ + @GET + @Path("{id}") + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public Permission get(@PathParam("id") String id) + { + StoredAssignedPermission sap = getPermission(id); + + return new Permission(sap.getId(), sap.getPermission()); + } + + /** + * Method description + * + * + * @return + */ + @GET + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public List getAll() + { + return getPermissions(getPredicate()); + } + + /** + * Method description + * + * + * @param id + * + * @return + */ + 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; + } + + /** + * Method description + * + * + * @param predicate + * + * @return + */ + 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 --------------------------------------------------------------- + + /** Field description */ + protected String name; + + /** Field description */ + 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 new file mode 100644 index 0000000000..6468397f4a --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/GroupPermissionResource.java @@ -0,0 +1,135 @@ +/** + * 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; + +/** + * + * @author Sebastian Sdorra + */ +public class GroupPermissionResource extends AbstractPermissionResource +{ + + /** + * Constructs ... + * + * + * @param securitySystem + * @param name + */ + public GroupPermissionResource(SecuritySystem securitySystem, String name) + { + super(securitySystem, name); + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param permission + * + * @return + */ + @Override + protected AssignedPermission transformPermission(Permission permission) + { + return new AssignedPermission(name, true, permission.getValue()); + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + @Override + protected Predicate getPredicate() + { + return new GroupPredicate(name); + } + + //~--- inner classes -------------------------------------------------------- + + /** + * Class description + * + * + * @version Enter version here..., 13/05/01 + * @author Enter your name here... + */ + private static class GroupPredicate implements Predicate + { + + /** + * Constructs ... + * + * + * @param name + */ + public GroupPredicate(String name) + { + this.name = name; + } + + //~--- methods ------------------------------------------------------------ + + /** + * Method description + * + * + * @param input + * + * @return + */ + @Override + public boolean apply(AssignedPermission input) + { + return input.isGroupPermission() && input.getName().equals(name); + } + + //~--- fields ------------------------------------------------------------- + + /** Field description */ + private String name; + } +} diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/SecurityConfigurationResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/SecuritySystemResource.java similarity index 64% rename from scm-webapp/src/main/java/sonia/scm/api/rest/resources/SecurityConfigurationResource.java rename to scm-webapp/src/main/java/sonia/scm/api/rest/resources/SecuritySystemResource.java index 332f1c1bf5..6f9e638b14 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/SecurityConfigurationResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/SecuritySystemResource.java @@ -37,32 +37,20 @@ import com.google.inject.Inject; import org.apache.shiro.SecurityUtils; -import org.codehaus.enunciate.jaxrs.TypeHint; -import org.codehaus.enunciate.modules.jersey.ExternallyManagedLifecycle; - import sonia.scm.security.Role; -import sonia.scm.security.SecurityConfiguration; import sonia.scm.security.SecuritySystem; //~--- JDK imports ------------------------------------------------------------ -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.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; +import javax.ws.rs.PathParam; /** * * @author Sebastian Sdorra */ -@Path("security") -@ExternallyManagedLifecycle -public class SecurityConfigurationResource +@Path("security/permission") +public class SecuritySystemResource { /** @@ -72,9 +60,12 @@ public class SecurityConfigurationResource * @param system */ @Inject - public SecurityConfigurationResource(SecuritySystem system) + public SecuritySystemResource(SecuritySystem system) { this.system = system; + + // only administrators can use this resource + SecurityUtils.getSubject().checkRole(Role.ADMIN); } //~--- get methods ---------------------------------------------------------- @@ -83,50 +74,30 @@ public class SecurityConfigurationResource * Method description * * + * @param group + * * @return */ - @GET - @TypeHint(SecurityConfiguration.class) - @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) - public Response getConfiguration() + @Path("group/{group}") + public GroupPermissionResource getGroupSubResource( + @PathParam("group") String group) { - Response response = null; - - if (SecurityUtils.getSubject().hasRole(Role.ADMIN)) - { - response = Response.ok(system.getConfiguration()).build(); - } - else - { - response = Response.status(Response.Status.FORBIDDEN).build(); - } - - return response; + return new GroupPermissionResource(system, group); } - //~--- set methods ---------------------------------------------------------- - /** * Method description * * - * @param uriInfo - * @param newConfig + * @param user * * @return */ - @POST - @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) - public Response setConfig(@Context UriInfo uriInfo, - SecurityConfiguration newConfig) + @Path("user/{user}") + public UserPermissionResource getUserSubResource( + @PathParam("user") String user) { - - // TODO replace by checkRole - SecurityUtils.getSubject().checkRole(Role.ADMIN); - - system.setConfiguration(newConfig); - - return Response.created(uriInfo.getRequestUri()).build(); + return new UserPermissionResource(system, user); } //~--- fields --------------------------------------------------------------- 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 new file mode 100644 index 0000000000..da1ae99512 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/UserPermissionResource.java @@ -0,0 +1,135 @@ +/** + * 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; + +/** + * + * @author Sebastian Sdorra + */ +public class UserPermissionResource extends AbstractPermissionResource +{ + + /** + * Constructs ... + * + * + * @param securitySystem + * @param name + */ + public UserPermissionResource(SecuritySystem securitySystem, String name) + { + super(securitySystem, name); + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param permission + * + * @return + */ + @Override + protected AssignedPermission transformPermission(Permission permission) + { + return new AssignedPermission(name, permission.getValue()); + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + @Override + protected Predicate getPredicate() + { + return new UserPredicate(name); + } + + //~--- inner classes -------------------------------------------------------- + + /** + * Class description + * + * + * @version Enter version here..., 13/05/01 + * @author Enter your name here... + */ + private static class UserPredicate implements Predicate + { + + /** + * Constructs ... + * + * + * @param name + */ + public UserPredicate(String name) + { + this.name = name; + } + + //~--- methods ------------------------------------------------------------ + + /** + * Method description + * + * + * @param input + * + * @return + */ + @Override + public boolean apply(AssignedPermission input) + { + return !input.isGroupPermission() && input.getName().equals(name); + } + + //~--- fields ------------------------------------------------------------- + + /** Field description */ + private String name; + } +}