Commits

Sebastian Sdorra  committed cfd48f7

added rest api for new security system

  • Participants
  • Parent commits c4a4b94
  • Branches issue-340

Comments (0)

Files changed (6)

File scm-webapp/src/main/java/sonia/scm/api/rest/Permission.java

+/**
+ * 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;
+}

File scm-webapp/src/main/java/sonia/scm/api/rest/resources/AbstractPermissionResource.java

+/**
+ * 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<AssignedPermission> 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<Permission> 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<Permission> getPermissions(
+    Predicate<AssignedPermission> predicate)
+  {
+    List<StoredAssignedPermission> permissions =
+      securitySystem.getPermissions(predicate);
+
+    return Lists.transform(permissions,
+      new Function<StoredAssignedPermission, Permission>()
+    {
+
+      @Override
+      public Permission apply(StoredAssignedPermission mgp)
+      {
+        return new Permission(mgp.getId(), mgp.getPermission());
+      }
+    });
+  }
+
+  //~--- fields ---------------------------------------------------------------
+
+  /** Field description */
+  protected String name;
+
+  /** Field description */
+  private SecuritySystem securitySystem;
+}

File scm-webapp/src/main/java/sonia/scm/api/rest/resources/GroupPermissionResource.java

+/**
+ * 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<AssignedPermission> 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<AssignedPermission>
+  {
+
+    /**
+     * 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;
+  }
+}

File scm-webapp/src/main/java/sonia/scm/api/rest/resources/SecurityConfigurationResource.java

-/**
- * 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 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;
-
-/**
- *
- * @author Sebastian Sdorra
- */
-@Path("security")
-@ExternallyManagedLifecycle
-public class SecurityConfigurationResource
-{
-
-  /**
-   * Constructs ...
-   *
-   *
-   * @param system
-   */
-  @Inject
-  public SecurityConfigurationResource(SecuritySystem system)
-  {
-    this.system = system;
-  }
-
-  //~--- get methods ----------------------------------------------------------
-
-  /**
-   * Method description
-   *
-   *
-   * @return
-   */
-  @GET
-  @TypeHint(SecurityConfiguration.class)
-  @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-  public Response getConfiguration()
-  {
-    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;
-  }
-
-  //~--- set methods ----------------------------------------------------------
-
-  /**
-   * Method description
-   *
-   *
-   * @param uriInfo
-   * @param newConfig
-   *
-   * @return
-   */
-  @POST
-  @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-  public Response setConfig(@Context UriInfo uriInfo,
-    SecurityConfiguration newConfig)
-  {
-
-    // TODO replace by checkRole
-    SecurityUtils.getSubject().checkRole(Role.ADMIN);
-
-    system.setConfiguration(newConfig);
-
-    return Response.created(uriInfo.getRequestUri()).build();
-  }
-
-  //~--- fields ---------------------------------------------------------------
-
-  /** Field description */
-  private SecuritySystem system;
-}

File scm-webapp/src/main/java/sonia/scm/api/rest/resources/SecuritySystemResource.java

+/**
+ * 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;
+
+/**
+ *
+ * @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 ----------------------------------------------------------
+
+  /**
+   * Method description
+   *
+   *
+   * @param group
+   *
+   * @return
+   */
+  @Path("group/{group}")
+  public GroupPermissionResource getGroupSubResource(
+    @PathParam("group") String group)
+  {
+    return new GroupPermissionResource(system, group);
+  }
+
+  /**
+   * Method description
+   *
+   *
+   * @param user
+   *
+   * @return
+   */
+  @Path("user/{user}")
+  public UserPermissionResource getUserSubResource(
+    @PathParam("user") String user)
+  {
+    return new UserPermissionResource(system, user);
+  }
+
+  //~--- fields ---------------------------------------------------------------
+
+  /** Field description */
+  private SecuritySystem system;
+}

File scm-webapp/src/main/java/sonia/scm/api/rest/resources/UserPermissionResource.java

+/**
+ * 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<AssignedPermission> 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<AssignedPermission>
+  {
+
+    /**
+     * 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;
+  }
+}