mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-10 15:35:49 +01:00
merge with branch issue-340
This commit is contained in:
@@ -35,12 +35,14 @@ package sonia.scm;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.security.PermissionDescriptor;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.web.security.WebSecurityContext;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
@@ -122,6 +124,29 @@ public class ScmState
|
||||
public ScmState(SCMContextProvider provider, User user,
|
||||
Collection<String> groups, Collection<Type> repositoryTypes,
|
||||
String defaultUserType, ScmClientConfig clientConfig)
|
||||
{
|
||||
this(provider, user, groups, repositoryTypes, defaultUserType,
|
||||
clientConfig, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs {@link ScmState} object.
|
||||
*
|
||||
*
|
||||
* @param provider context provider
|
||||
* @param user current user
|
||||
* @param groups groups of the current user
|
||||
* @param repositoryTypes available repository types
|
||||
* @param defaultUserType default user type
|
||||
* @param clientConfig client configuration
|
||||
* @param availablePermissions list of available permissions
|
||||
*
|
||||
* @since 1.31
|
||||
*/
|
||||
public ScmState(SCMContextProvider provider, User user,
|
||||
Collection<String> groups, Collection<Type> repositoryTypes,
|
||||
String defaultUserType, ScmClientConfig clientConfig,
|
||||
List<PermissionDescriptor> availablePermissions)
|
||||
{
|
||||
this.version = provider.getVersion();
|
||||
this.user = user;
|
||||
@@ -129,10 +154,23 @@ public class ScmState
|
||||
this.repositoryTypes = repositoryTypes;
|
||||
this.clientConfig = clientConfig;
|
||||
this.defaultUserType = defaultUserType;
|
||||
this.availablePermissions = availablePermissions;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns a list of available global permissions.
|
||||
*
|
||||
*
|
||||
* @return available global permissions
|
||||
* @since 1.31
|
||||
*/
|
||||
public List<PermissionDescriptor> getAvailablePermissions()
|
||||
{
|
||||
return availablePermissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns configuration for SCM-Manager clients.
|
||||
*
|
||||
@@ -215,6 +253,18 @@ public class ScmState
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Sets a list of available global permissions.
|
||||
*
|
||||
*
|
||||
* @param permissions list of available global permisisons
|
||||
* @since 1.31
|
||||
*/
|
||||
public void setAvailablePermissions(List<PermissionDescriptor> permissions)
|
||||
{
|
||||
this.availablePermissions = permissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the client configuration
|
||||
*
|
||||
@@ -299,6 +349,12 @@ public class ScmState
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Avaliable global permission
|
||||
* @since 1.31
|
||||
*/
|
||||
private List<PermissionDescriptor> availablePermissions;
|
||||
|
||||
/** Field description */
|
||||
private ScmClientConfig clientConfig;
|
||||
|
||||
|
||||
@@ -37,6 +37,8 @@ package sonia.scm.repository;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
import sonia.scm.security.PermissionObject;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.Serializable;
|
||||
@@ -52,7 +54,7 @@ import javax.xml.bind.annotation.XmlRootElement;
|
||||
*/
|
||||
@XmlRootElement(name = "permissions")
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class Permission implements Serializable
|
||||
public class Permission implements PermissionObject, Serializable
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
@@ -135,7 +137,7 @@ public class Permission implements Serializable
|
||||
final Permission other = (Permission) obj;
|
||||
|
||||
return Objects.equal(name, other.name) && Objects.equal(type, other.type)
|
||||
&& Objects.equal(groupPermission, groupPermission);
|
||||
&& Objects.equal(groupPermission, groupPermission);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,6 +178,7 @@ public class Permission implements Serializable
|
||||
*
|
||||
* @return name of the user or group
|
||||
*/
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
@@ -198,6 +201,7 @@ public class Permission implements Serializable
|
||||
*
|
||||
* @return true if the permision is a group permission
|
||||
*/
|
||||
@Override
|
||||
public boolean isGroupPermission()
|
||||
{
|
||||
return groupPermission;
|
||||
|
||||
@@ -44,16 +44,12 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.group.GroupNames;
|
||||
import sonia.scm.security.RepositoryPermission;
|
||||
import sonia.scm.security.Role;
|
||||
import sonia.scm.security.ScmSecurityException;
|
||||
import sonia.scm.util.AssertUtil;
|
||||
import sonia.scm.web.security.WebSecurityContext;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
@@ -179,7 +175,7 @@ public final class PermissionUtil
|
||||
public static boolean hasPermission(ScmConfiguration configuration,
|
||||
Repository repository, PermissionType pt)
|
||||
{
|
||||
boolean result = false;
|
||||
boolean result;
|
||||
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
|
||||
@@ -196,16 +192,7 @@ public final class PermissionUtil
|
||||
}
|
||||
else
|
||||
{
|
||||
List<Permission> permissions = repository.getPermissions();
|
||||
|
||||
if (permissions != null)
|
||||
{
|
||||
GroupNames groupNames =
|
||||
subject.getPrincipals().oneByType(GroupNames.class);
|
||||
|
||||
result = hasPermission(permissions, username, groupNames, pt);
|
||||
|
||||
}
|
||||
result = subject.isPermitted(new RepositoryPermission(repository, pt));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -270,37 +257,4 @@ public final class PermissionUtil
|
||||
|
||||
return permitted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param permissions
|
||||
* @param username
|
||||
* @param groups
|
||||
* @param pt
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private static boolean hasPermission(List<Permission> permissions,
|
||||
String username, GroupNames groups, PermissionType pt)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
for (Permission p : permissions)
|
||||
{
|
||||
String name = p.getName();
|
||||
|
||||
if (((name != null) && (p.getType().getValue() >= pt.getValue()))
|
||||
&& (name.equals(username)
|
||||
|| (p.isGroupPermission() && groups.contains(p.getName()))))
|
||||
{
|
||||
result = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
/**
|
||||
* 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.security;
|
||||
|
||||
//~--- 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.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* Permission object which is assigned to a specific user or group.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
* @since 1.31
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlRootElement(name = "assigned-permission")
|
||||
public class AssignedPermission implements PermissionObject, Serializable
|
||||
{
|
||||
|
||||
/** serial version uid */
|
||||
private static final long serialVersionUID = -7411338422110323879L;
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructor is only visible for JAXB.
|
||||
*
|
||||
*/
|
||||
public AssignedPermission() {}
|
||||
|
||||
/**
|
||||
* Constructs a new AssignedPermission.
|
||||
*
|
||||
*
|
||||
* @param permission assigned permission
|
||||
*/
|
||||
public AssignedPermission(AssignedPermission permission)
|
||||
{
|
||||
this.name = permission.name;
|
||||
this.groupPermission = permission.groupPermission;
|
||||
this.permission = permission.permission;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new AssingnedPermmission.
|
||||
*
|
||||
*
|
||||
* @param name name of the user
|
||||
* @param permission permission string
|
||||
*/
|
||||
public AssignedPermission(String name, String permission)
|
||||
{
|
||||
this.name = name;
|
||||
this.permission = permission;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new AssingnedPermmission.
|
||||
*
|
||||
*
|
||||
* @param name name of the user or group
|
||||
* @param groupPermission true if the permission should be assigned to a group
|
||||
* @param permission permission string
|
||||
*/
|
||||
public AssignedPermission(String name, boolean groupPermission,
|
||||
String permission)
|
||||
{
|
||||
this.name = name;
|
||||
this.groupPermission = groupPermission;
|
||||
this.permission = permission;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getClass() != obj.getClass())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
final AssignedPermission other = (AssignedPermission) obj;
|
||||
|
||||
return Objects.equal(name, other.name)
|
||||
&& Objects.equal(groupPermission, other.groupPermission)
|
||||
&& Objects.equal(permission, other.permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hashCode(name, groupPermission, permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
//J-
|
||||
return Objects.toStringHelper(this)
|
||||
.add("name", name)
|
||||
.add("groupPermisison", groupPermission)
|
||||
.add("permission", permission)
|
||||
.toString();
|
||||
//J+
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the name of the user or group which the permission is assigned.
|
||||
*
|
||||
*
|
||||
* @return name of user or group
|
||||
*/
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string representation of the permission.
|
||||
*
|
||||
*
|
||||
* @return string representation of the permission
|
||||
*/
|
||||
public String getPermission()
|
||||
{
|
||||
return permission;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the permission is assigned to a group.
|
||||
*
|
||||
*
|
||||
* @return true if the permission is assigned to a group
|
||||
*/
|
||||
@Override
|
||||
public boolean isGroupPermission()
|
||||
{
|
||||
return groupPermission;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** group permission indicator */
|
||||
@XmlElement(name = "group-permission")
|
||||
private boolean groupPermission;
|
||||
|
||||
/** name of the user or group */
|
||||
private String name;
|
||||
|
||||
/** string representation of the permission */
|
||||
private String permission;
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
/**
|
||||
* 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.security;
|
||||
|
||||
//~--- 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.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* Descriptor for available permission objects.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
* @since 1.31
|
||||
*/
|
||||
@XmlRootElement(name = "permission")
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class PermissionDescriptor implements Serializable
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
private static final long serialVersionUID = -9141065458354047154L;
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructor is only visible for JAXB.
|
||||
*
|
||||
*/
|
||||
public PermissionDescriptor() {}
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param displayName
|
||||
* @param description
|
||||
* @param value
|
||||
*/
|
||||
public PermissionDescriptor(String displayName, String description,
|
||||
String value)
|
||||
{
|
||||
this.displayName = displayName;
|
||||
this.description = description;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getClass() != obj.getClass())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
final PermissionDescriptor other = (PermissionDescriptor) obj;
|
||||
|
||||
return Objects.equal(displayName, other.displayName)
|
||||
&& Objects.equal(description, other.description)
|
||||
&& Objects.equal(value, other.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hashCode(displayName, description, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
|
||||
//J-
|
||||
return Objects.toStringHelper(this)
|
||||
.add("displayName", displayName)
|
||||
.add("description", description)
|
||||
.add("value", value)
|
||||
.toString();
|
||||
|
||||
//J+
|
||||
}
|
||||
|
||||
//~--- 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.
|
||||
*
|
||||
*
|
||||
* @return string representation
|
||||
*/
|
||||
public String getValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** description */
|
||||
private String description;
|
||||
|
||||
/** display name */
|
||||
@XmlElement(name = "display-name")
|
||||
private String displayName;
|
||||
|
||||
/** value */
|
||||
private String value;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* 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.security;
|
||||
|
||||
/**
|
||||
* Interface for permission objects.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
* @since 1.31
|
||||
*/
|
||||
public interface PermissionObject
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns the name of the user or group which the permission is assigned.
|
||||
*
|
||||
*
|
||||
* @return name of user or group
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
* Returns the id of the stored permission object.
|
||||
*
|
||||
*
|
||||
* @return id of permission
|
||||
*/
|
||||
public boolean isGroupPermission();
|
||||
}
|
||||
124
scm-core/src/main/java/sonia/scm/security/SecuritySystem.java
Normal file
124
scm-core/src/main/java/sonia/scm/security/SecuritySystem.java
Normal file
@@ -0,0 +1,124 @@
|
||||
/**
|
||||
* 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.security;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The SecuritySystem manages global permissions.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
* @since 1.31
|
||||
*/
|
||||
public interface SecuritySystem
|
||||
{
|
||||
|
||||
/**
|
||||
* Store a new permission.
|
||||
*
|
||||
*
|
||||
* @param permission permission to be stored
|
||||
*
|
||||
* @return stored permission
|
||||
*/
|
||||
public StoredAssignedPermission addPermission(AssignedPermission permission);
|
||||
|
||||
/**
|
||||
* Delete stored permission.
|
||||
*
|
||||
*
|
||||
* @param permission permission to be deleted
|
||||
*/
|
||||
public void deletePermission(StoredAssignedPermission permission);
|
||||
|
||||
/**
|
||||
* Delete stored permission.
|
||||
*
|
||||
*
|
||||
* @param id id of the permission
|
||||
*/
|
||||
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<StoredAssignedPermission> getAllPermissions();
|
||||
|
||||
/**
|
||||
* Return all available permissions.
|
||||
*
|
||||
*
|
||||
* @return available permissions
|
||||
*/
|
||||
public List<PermissionDescriptor> 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);
|
||||
|
||||
/**
|
||||
* Returns all stored permissions which are matched by the given
|
||||
* {@link Predicate}.
|
||||
*
|
||||
*
|
||||
* @param predicate predicate to filter
|
||||
*
|
||||
* @return filtered permissions
|
||||
*/
|
||||
public List<StoredAssignedPermission> getPermissions(
|
||||
Predicate<AssignedPermission> predicate);
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* 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.security;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* Permission object which is stored and assigned to a specific user or group.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
* @since 1.31
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlRootElement(name = "assigned-permission")
|
||||
public class StoredAssignedPermission extends AssignedPermission
|
||||
{
|
||||
|
||||
/** serial version uid */
|
||||
private static final long serialVersionUID = -4593919877023168090L;
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructor is only visible for JAXB.
|
||||
*
|
||||
*/
|
||||
public StoredAssignedPermission() {}
|
||||
|
||||
/**
|
||||
* Constructs a new StoredAssignedPermission.
|
||||
*
|
||||
*
|
||||
* @param id id of the permission object
|
||||
* @param permission assigned permission object
|
||||
*/
|
||||
public StoredAssignedPermission(String id, AssignedPermission permission)
|
||||
{
|
||||
super(permission);
|
||||
this.id = id;
|
||||
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the id of the stored permission object.
|
||||
*
|
||||
*
|
||||
* @return id of permission
|
||||
*/
|
||||
public String getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** id */
|
||||
private String id;
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* 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.security;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
import sonia.scm.HandlerEvent;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Event which is fired after a {@link StoredAssignedPermission} was added,
|
||||
* removed or changed.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
* @since 1.31
|
||||
*/
|
||||
public final class StoredAssignedPermissionEvent implements Serializable
|
||||
{
|
||||
|
||||
/** serial version uid */
|
||||
private static final long serialVersionUID = 706824497813169009L;
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs a new StoredAssignedPermissionEvent.
|
||||
*
|
||||
*
|
||||
* @param type type of the event
|
||||
* @param permission permission object which has changed
|
||||
*/
|
||||
public StoredAssignedPermissionEvent(HandlerEvent type,
|
||||
StoredAssignedPermission permission)
|
||||
{
|
||||
this.type = type;
|
||||
this.permission = permission;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getClass() != obj.getClass())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
final StoredAssignedPermissionEvent other =
|
||||
(StoredAssignedPermissionEvent) obj;
|
||||
|
||||
return Objects.equal(type, other.type)
|
||||
&& Objects.equal(permission, other.permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hashCode(type, permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
//J-
|
||||
return Objects.toStringHelper(this)
|
||||
.add("type", type)
|
||||
.add("permission", permission)
|
||||
.toString();
|
||||
//J+
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Return the type of the event.
|
||||
*
|
||||
*
|
||||
* @return type of event
|
||||
*/
|
||||
public HandlerEvent getEventType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the changed permission object.
|
||||
*
|
||||
*
|
||||
* @return changed permission
|
||||
*/
|
||||
public StoredAssignedPermission getPermission()
|
||||
{
|
||||
return permission;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** changed permission */
|
||||
private StoredAssignedPermission permission;
|
||||
|
||||
/** type of the event */
|
||||
private HandlerEvent type;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* 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.store;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* A ConfigurationEntryStore can be used to store multiple entries of structured
|
||||
* configuration data. <b>Note:<b> the default implementation use JAXB to
|
||||
* marshall the items.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*
|
||||
* @param <V> store value type
|
||||
* @since 1.31
|
||||
*/
|
||||
public interface ConfigurationEntryStore<V> extends DataStore<V>
|
||||
{
|
||||
|
||||
/**
|
||||
* Return all values matching the given {@link Predicate}.
|
||||
*
|
||||
*
|
||||
* @param predicate predicate to match values
|
||||
*
|
||||
* @return filtered collection of values
|
||||
*/
|
||||
public Collection<V> getMatchingValues(Predicate<V> predicate);
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* 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.store;
|
||||
|
||||
/**
|
||||
* The ConfigurationEntryStoreFactory can be used to create new or get existing
|
||||
* {@link ConfigurationEntryStore}s. <b>Note:</b> the default implementation
|
||||
* uses the same location as the {@link StoreFactory}, so be sure that the
|
||||
* store names are unique for all {@link ConfigurationEntryStore}s and
|
||||
* {@link Store}s.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
* @since 1.31
|
||||
*
|
||||
* @apiviz.landmark
|
||||
* @apiviz.uses sonia.scm.store.ConfigurationEntryStore
|
||||
*/
|
||||
public interface ConfigurationEntryStoreFactory
|
||||
{
|
||||
|
||||
/**
|
||||
* Get an existing {@link ConfigurationEntryStore} or create a new one.
|
||||
*
|
||||
*
|
||||
* @param type type of the store objects
|
||||
* @param name name of the store
|
||||
* @param <T> type of the store objects
|
||||
*
|
||||
* @return {@link ConfigurationEntryStore} with given name and type
|
||||
*/
|
||||
public <T> ConfigurationEntryStore<T> getStore(Class<T> type, String name);
|
||||
}
|
||||
@@ -0,0 +1,407 @@
|
||||
/**
|
||||
* 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.store;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Collections2;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.security.KeyGenerator;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Marshaller;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLOutputFactory;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import javax.xml.stream.XMLStreamWriter;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*
|
||||
* @param <V>
|
||||
*/
|
||||
public class JAXBConfigurationEntryStore<V>
|
||||
implements ConfigurationEntryStore<V>
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
private static final Object LOCK = new Object();
|
||||
|
||||
/** Field description */
|
||||
private static final String TAG_CONFIGURATION = "configuration";
|
||||
|
||||
/** Field description */
|
||||
private static final String TAG_ENTRY = "entry";
|
||||
|
||||
/** Field description */
|
||||
private static final String TAG_KEY = "key";
|
||||
|
||||
/** Field description */
|
||||
private static final String TAG_VALUE = "value";
|
||||
|
||||
/**
|
||||
* the logger for JAXBConfigurationEntryStore
|
||||
*/
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(JAXBConfigurationEntryStore.class);
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param keyGenerator
|
||||
* @param file
|
||||
* @param type
|
||||
*/
|
||||
JAXBConfigurationEntryStore(KeyGenerator keyGenerator, File file,
|
||||
Class<V> type)
|
||||
{
|
||||
this.keyGenerator = keyGenerator;
|
||||
this.file = file;
|
||||
this.type = type;
|
||||
|
||||
try
|
||||
{
|
||||
this.context = JAXBContext.newInstance(type);
|
||||
|
||||
if (file.exists())
|
||||
{
|
||||
load();
|
||||
}
|
||||
}
|
||||
catch (JAXBException ex)
|
||||
{
|
||||
throw new StoreException("could not create jaxb context", ex);
|
||||
}
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public void clear()
|
||||
{
|
||||
logger.debug("clear configuration store");
|
||||
|
||||
synchronized (LOCK)
|
||||
{
|
||||
entries.clear();
|
||||
store();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param item
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String put(V item)
|
||||
{
|
||||
String id = keyGenerator.createKey();
|
||||
|
||||
put(id, item);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param id
|
||||
* @param item
|
||||
*/
|
||||
@Override
|
||||
public void put(String id, V item)
|
||||
{
|
||||
logger.debug("put item {} to configuration store", id);
|
||||
|
||||
synchronized (LOCK)
|
||||
{
|
||||
entries.put(id, item);
|
||||
store();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
@Override
|
||||
public void remove(String id)
|
||||
{
|
||||
logger.debug("remove item {} from configuration store", id);
|
||||
|
||||
synchronized (LOCK)
|
||||
{
|
||||
entries.remove(id);
|
||||
store();
|
||||
}
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public V get(String id)
|
||||
{
|
||||
logger.trace("get item {} from configuration store", id);
|
||||
|
||||
return entries.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Map<String, V> getAll()
|
||||
{
|
||||
logger.trace("get all items from configuration store");
|
||||
|
||||
return Collections.unmodifiableMap(entries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param predicate
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Collection<V> getMatchingValues(Predicate<V> predicate)
|
||||
{
|
||||
return Collections2.filter(entries.values(), predicate);
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param writer
|
||||
*/
|
||||
private void close(XMLStreamWriter writer)
|
||||
{
|
||||
if (writer != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
writer.close();
|
||||
}
|
||||
catch (XMLStreamException ex)
|
||||
{
|
||||
logger.error("could not close writer", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param reader
|
||||
*/
|
||||
private void close(XMLStreamReader reader)
|
||||
{
|
||||
if (reader != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
reader.close();
|
||||
}
|
||||
catch (XMLStreamException ex)
|
||||
{
|
||||
logger.error("could not close reader", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private void load()
|
||||
{
|
||||
logger.debug("load configuration from {}", file);
|
||||
|
||||
XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
|
||||
|
||||
XMLStreamReader reader = null;
|
||||
|
||||
try
|
||||
{
|
||||
Unmarshaller u = context.createUnmarshaller();
|
||||
|
||||
reader = xmlInputFactory.createXMLStreamReader(new StreamSource(file));
|
||||
reader.nextTag();
|
||||
reader.nextTag();
|
||||
|
||||
while (reader.isStartElement() && reader.getLocalName().equals(TAG_ENTRY))
|
||||
{
|
||||
|
||||
// read key
|
||||
reader.nextTag();
|
||||
|
||||
String key = reader.getElementText();
|
||||
|
||||
// read entry
|
||||
reader.nextTag();
|
||||
|
||||
V v = (V) u.unmarshal(reader, type).getValue();
|
||||
|
||||
entries.put(key, v);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new StoreException("could not load configuration", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
close(reader);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
private void store()
|
||||
{
|
||||
logger.debug("store configuration to {}", file);
|
||||
|
||||
XMLStreamWriter writer = null;
|
||||
|
||||
try
|
||||
{
|
||||
writer = XMLOutputFactory.newFactory().createXMLStreamWriter(
|
||||
new FileOutputStream(file));
|
||||
writer.writeStartDocument();
|
||||
writer.writeStartElement(TAG_CONFIGURATION);
|
||||
|
||||
Marshaller m = context.createMarshaller();
|
||||
|
||||
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
|
||||
m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
|
||||
|
||||
for (Entry<String, V> e : entries.entrySet())
|
||||
{
|
||||
writer.writeStartElement(TAG_ENTRY);
|
||||
writer.writeStartElement(TAG_KEY);
|
||||
writer.writeCharacters(e.getKey());
|
||||
writer.writeEndElement();
|
||||
|
||||
JAXBElement<V> je = new JAXBElement<V>(QName.valueOf(TAG_VALUE), type,
|
||||
e.getValue());
|
||||
|
||||
m.marshal(je, writer);
|
||||
}
|
||||
|
||||
writer.writeEndElement();
|
||||
writer.writeEndDocument();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new StoreException("could not store configuration", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
close(writer);
|
||||
}
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private JAXBContext context;
|
||||
|
||||
/** Field description */
|
||||
private Map<String, V> entries = Maps.newHashMap();
|
||||
|
||||
/** Field description */
|
||||
private File file;
|
||||
|
||||
/** Field description */
|
||||
private KeyGenerator keyGenerator;
|
||||
|
||||
/** Field description */
|
||||
private Class<V> type;
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
* 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.store;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.SCMContextProvider;
|
||||
import sonia.scm.security.KeyGenerator;
|
||||
import sonia.scm.util.IOUtil;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@Singleton
|
||||
public class JAXBConfigurationEntryStoreFactory
|
||||
implements ConfigurationEntryStoreFactory
|
||||
{
|
||||
|
||||
/**
|
||||
* the logger for JAXBConfigurationEntryStoreFactory
|
||||
*/
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(JAXBConfigurationEntryStoreFactory.class);
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param keyGenerator
|
||||
* @param context
|
||||
*/
|
||||
@Inject
|
||||
public JAXBConfigurationEntryStoreFactory(KeyGenerator keyGenerator,
|
||||
SCMContextProvider context)
|
||||
{
|
||||
this.keyGenerator = keyGenerator;
|
||||
directory = new File(context.getBaseDirectory(),
|
||||
StoreConstants.CONFIGDIRECTORY_NAME);
|
||||
IOUtil.mkdirs(directory);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param type
|
||||
* @param name
|
||||
* @param <T>
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public <T> ConfigurationEntryStore<T> getStore(Class<T> type, String name)
|
||||
{
|
||||
logger.debug("create new configuration store for type {} with name {}",
|
||||
type, name);
|
||||
|
||||
return new JAXBConfigurationEntryStore<T>(keyGenerator,
|
||||
new File(directory, name.concat(StoreConstants.FILE_EXTENSION)), type);
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private File directory;
|
||||
|
||||
/** Field description */
|
||||
private KeyGenerator keyGenerator;
|
||||
}
|
||||
@@ -61,9 +61,6 @@ import javax.xml.bind.Marshaller;
|
||||
public class JAXBDataStore<T> extends FileBasedStore<T> implements DataStore<T>
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
private static final String SUFFIX = ".xml";
|
||||
|
||||
/**
|
||||
* the logger for JAXBDataStore
|
||||
*/
|
||||
@@ -82,7 +79,7 @@ public class JAXBDataStore<T> extends FileBasedStore<T> implements DataStore<T>
|
||||
*/
|
||||
public JAXBDataStore(KeyGenerator keyGenerator, Class<T> type, File directory)
|
||||
{
|
||||
super(directory, SUFFIX);
|
||||
super(directory, StoreConstants.FILE_EXTENSION);
|
||||
this.keyGenerator = keyGenerator;
|
||||
|
||||
try
|
||||
|
||||
@@ -56,12 +56,6 @@ import java.io.IOException;
|
||||
public class JAXBStoreFactory implements ListenableStoreFactory
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String CONFIGDIRECTORY_NAME = "config";
|
||||
|
||||
/** Field description */
|
||||
public static final String FILE_EXTENSION = ".xml";
|
||||
|
||||
/** the logger for JAXBStoreFactory */
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(JAXBStoreFactory.class);
|
||||
@@ -91,7 +85,7 @@ public class JAXBStoreFactory implements ListenableStoreFactory
|
||||
public void init(SCMContextProvider context)
|
||||
{
|
||||
configDirectory = new File(context.getBaseDirectory(),
|
||||
CONFIGDIRECTORY_NAME);
|
||||
StoreConstants.CONFIGDIRECTORY_NAME);
|
||||
IOUtil.mkdirs(configDirectory);
|
||||
}
|
||||
|
||||
@@ -115,7 +109,8 @@ public class JAXBStoreFactory implements ListenableStoreFactory
|
||||
throw new IllegalStateException("store factory is not initialized");
|
||||
}
|
||||
|
||||
File configFile = new File(configDirectory, name.concat(FILE_EXTENSION));
|
||||
File configFile = new File(configDirectory,
|
||||
name.concat(StoreConstants.FILE_EXTENSION));
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* 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.store;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public interface StoreConstants
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String CONFIGDIRECTORY_NAME = "config";
|
||||
|
||||
/** Field description */
|
||||
public static final String FILE_EXTENSION = ".xml";
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* 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.store;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.security.UUIDKeyGenerator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class JAXBConfigurationEntryStoreTest extends ConfigurationEntryStoreTestBase
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected ConfigurationEntryStoreFactory createConfigurationStoreFactory()
|
||||
{
|
||||
return new JAXBConfigurationEntryStoreFactory(new UUIDKeyGenerator(),
|
||||
contextProvider);
|
||||
}
|
||||
}
|
||||
@@ -151,6 +151,7 @@ public class AbstractTestBase
|
||||
try
|
||||
{
|
||||
preTearDown();
|
||||
clearSubject();
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -179,7 +180,7 @@ public class AbstractTestBase
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Clears Shiro's thread state, ensuring the thread remains clean for
|
||||
* Clears Shiro's thread state, ensuring the thread remains clean for
|
||||
* future test execution.
|
||||
*/
|
||||
protected void clearSubject()
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* 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.store;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public abstract class ConfigurationEntryStoreTestBase extends KeyValueStoreTestBase
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected abstract ConfigurationEntryStoreFactory createConfigurationStoreFactory();
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected ConfigurationEntryStore<StoreObject> getDataStore()
|
||||
{
|
||||
return createConfigurationStoreFactory().getStore(StoreObject.class,
|
||||
"test");
|
||||
}
|
||||
}
|
||||
@@ -30,26 +30,14 @@
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.store;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import sonia.scm.AbstractTestBase;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public abstract class DataStoreTestBase extends AbstractTestBase
|
||||
public abstract class DataStoreTestBase extends KeyValueStoreTestBase
|
||||
{
|
||||
|
||||
/**
|
||||
@@ -60,155 +48,6 @@ public abstract class DataStoreTestBase extends AbstractTestBase
|
||||
*/
|
||||
protected abstract DataStoreFactory createDataStoreFactory();
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Before
|
||||
public void before()
|
||||
{
|
||||
store = getDataStore();
|
||||
store.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testClear()
|
||||
{
|
||||
testPutWithId();
|
||||
|
||||
store.clear();
|
||||
assertNull(store.get("1"));
|
||||
assertNull(store.get("2"));
|
||||
|
||||
assertTrue(store.getAll().isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testGet()
|
||||
{
|
||||
StoreObject other = store.get("1");
|
||||
|
||||
assertNull(other);
|
||||
|
||||
StoreObject obj = new StoreObject("test-1");
|
||||
|
||||
store.put("1", obj);
|
||||
other = store.get("1");
|
||||
assertNotNull(other);
|
||||
assertEquals(obj, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testGetAll()
|
||||
{
|
||||
StoreObject obj1 = new StoreObject("test-1");
|
||||
|
||||
store.put("1", obj1);
|
||||
|
||||
StoreObject obj2 = new StoreObject("test-2");
|
||||
|
||||
store.put("2", obj2);
|
||||
|
||||
Map<String, StoreObject> map = store.getAll();
|
||||
|
||||
assertNotNull(map);
|
||||
|
||||
assertFalse(map.isEmpty());
|
||||
assertEquals(2, map.size());
|
||||
|
||||
assertEquals(obj1, map.get("1"));
|
||||
assertEquals(obj2, map.get("2"));
|
||||
|
||||
assertNull(map.get("3"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testGetAllFromEmpty()
|
||||
{
|
||||
Map<String, StoreObject> map = store.getAll();
|
||||
|
||||
assertNotNull(map);
|
||||
assertTrue(map.isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testGetFromEmpty()
|
||||
{
|
||||
StoreObject obj = store.get("test");
|
||||
|
||||
assertNull(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testPutWithId()
|
||||
{
|
||||
StoreObject obj1 = new StoreObject("test-1");
|
||||
|
||||
store.put("1", obj1);
|
||||
|
||||
StoreObject obj2 = new StoreObject("test-2");
|
||||
|
||||
store.put("2", obj2);
|
||||
|
||||
assertEquals(obj1, store.get("1"));
|
||||
assertEquals(obj2, store.get("2"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testPutWithoutId()
|
||||
{
|
||||
StoreObject obj = new StoreObject("test-1");
|
||||
String id = store.put(obj);
|
||||
|
||||
assertNotNull(id);
|
||||
|
||||
assertEquals(obj, store.get(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testRemove()
|
||||
{
|
||||
testPutWithId();
|
||||
|
||||
store.remove("1");
|
||||
assertNull(store.get("1"));
|
||||
assertNotNull(store.get("2"));
|
||||
store.remove("2");
|
||||
assertNull(store.get("2"));
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -217,13 +56,9 @@ public abstract class DataStoreTestBase extends AbstractTestBase
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private DataStore<StoreObject> getDataStore()
|
||||
@Override
|
||||
protected DataStore<StoreObject> getDataStore()
|
||||
{
|
||||
return createDataStoreFactory().getStore(StoreObject.class, "test");
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private DataStore<StoreObject> store;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
/**
|
||||
* 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.store;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import sonia.scm.AbstractTestBase;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public abstract class KeyValueStoreTestBase extends AbstractTestBase
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected abstract DataStore<StoreObject> getDataStore();
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Before
|
||||
public void before()
|
||||
{
|
||||
store = getDataStore();
|
||||
store.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testClear()
|
||||
{
|
||||
testPutWithId();
|
||||
|
||||
store.clear();
|
||||
assertNull(store.get("1"));
|
||||
assertNull(store.get("2"));
|
||||
|
||||
assertTrue(store.getAll().isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testGet()
|
||||
{
|
||||
StoreObject other = store.get("1");
|
||||
|
||||
assertNull(other);
|
||||
|
||||
StoreObject obj = new StoreObject("test-1");
|
||||
|
||||
store.put("1", obj);
|
||||
other = store.get("1");
|
||||
assertNotNull(other);
|
||||
assertEquals(obj, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testGetAll()
|
||||
{
|
||||
StoreObject obj1 = new StoreObject("test-1");
|
||||
|
||||
store.put("1", obj1);
|
||||
|
||||
StoreObject obj2 = new StoreObject("test-2");
|
||||
|
||||
store.put("2", obj2);
|
||||
|
||||
Map<String, StoreObject> map = store.getAll();
|
||||
|
||||
assertNotNull(map);
|
||||
|
||||
assertFalse(map.isEmpty());
|
||||
assertEquals(2, map.size());
|
||||
|
||||
assertEquals(obj1, map.get("1"));
|
||||
assertEquals(obj2, map.get("2"));
|
||||
|
||||
assertNull(map.get("3"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testGetAllFromEmpty()
|
||||
{
|
||||
Map<String, StoreObject> map = store.getAll();
|
||||
|
||||
assertNotNull(map);
|
||||
assertTrue(map.isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testGetFromEmpty()
|
||||
{
|
||||
StoreObject obj = store.get("test");
|
||||
|
||||
assertNull(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testPutWithId()
|
||||
{
|
||||
StoreObject obj1 = new StoreObject("test-1");
|
||||
|
||||
store.put("1", obj1);
|
||||
|
||||
StoreObject obj2 = new StoreObject("test-2");
|
||||
|
||||
store.put("2", obj2);
|
||||
|
||||
assertEquals(obj1, store.get("1"));
|
||||
assertEquals(obj2, store.get("2"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testPutWithoutId()
|
||||
{
|
||||
StoreObject obj = new StoreObject("test-1");
|
||||
String id = store.put(obj);
|
||||
|
||||
assertNotNull(id);
|
||||
|
||||
assertEquals(obj, store.get(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testRemove()
|
||||
{
|
||||
testPutWithId();
|
||||
|
||||
store.remove("1");
|
||||
assertNull(store.get("1"));
|
||||
assertNotNull(store.get("2"));
|
||||
store.remove("2");
|
||||
assertNull(store.get("2"));
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private DataStore<StoreObject> store;
|
||||
}
|
||||
@@ -41,6 +41,7 @@ import org.apache.shiro.authz.Permission;
|
||||
import org.apache.shiro.subject.PrincipalCollection;
|
||||
import org.apache.shiro.subject.SimplePrincipalCollection;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.apache.shiro.subject.Subject.Builder;
|
||||
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
@@ -138,6 +139,20 @@ public final class MockUtil
|
||||
* @return
|
||||
*/
|
||||
public static Subject createUserSubject()
|
||||
{
|
||||
return createUserSubject(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param securityManager
|
||||
* @return
|
||||
*/
|
||||
public static Subject createUserSubject(
|
||||
org.apache.shiro.mgt.SecurityManager securityManager)
|
||||
{
|
||||
SimplePrincipalCollection collection = new SimplePrincipalCollection();
|
||||
User user = UserTestData.createTrillian();
|
||||
@@ -145,8 +160,18 @@ public final class MockUtil
|
||||
collection.add(user.getName(), "junit");
|
||||
collection.add(user, "junit");
|
||||
|
||||
return new Subject.Builder().principals(collection).authenticated(
|
||||
true).buildSubject();
|
||||
Builder builder;
|
||||
|
||||
if (securityManager != null)
|
||||
{
|
||||
builder = new Subject.Builder(securityManager);
|
||||
}
|
||||
else
|
||||
{
|
||||
builder = new Subject.Builder();
|
||||
}
|
||||
|
||||
return builder.principals(collection).authenticated(true).buildSubject();
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
@@ -47,7 +47,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.api.rest.UriExtensionsConfig;
|
||||
import sonia.scm.cache.CacheManager;
|
||||
import sonia.scm.cache.EhCacheManager;
|
||||
import sonia.scm.cache.GuavaCacheManager;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.event.ScmEventBus;
|
||||
import sonia.scm.filter.AdminSecurityFilter;
|
||||
@@ -86,13 +86,17 @@ import sonia.scm.resources.ScriptResourceServlet;
|
||||
import sonia.scm.security.CipherHandler;
|
||||
import sonia.scm.security.CipherUtil;
|
||||
import sonia.scm.security.DefaultKeyGenerator;
|
||||
import sonia.scm.security.DefaultSecuritySystem;
|
||||
import sonia.scm.security.EncryptionHandler;
|
||||
import sonia.scm.security.KeyGenerator;
|
||||
import sonia.scm.security.MessageDigestEncryptionHandler;
|
||||
import sonia.scm.security.SecurityContext;
|
||||
import sonia.scm.security.SecuritySystem;
|
||||
import sonia.scm.store.BlobStoreFactory;
|
||||
import sonia.scm.store.ConfigurationEntryStoreFactory;
|
||||
import sonia.scm.store.DataStoreFactory;
|
||||
import sonia.scm.store.FileBlobStoreFactory;
|
||||
import sonia.scm.store.JAXBConfigurationEntryStoreFactory;
|
||||
import sonia.scm.store.JAXBDataStoreFactory;
|
||||
import sonia.scm.store.JAXBStoreFactory;
|
||||
import sonia.scm.store.ListenableStoreFactory;
|
||||
@@ -142,7 +146,6 @@ import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import sonia.scm.cache.GuavaCacheManager;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -252,6 +255,8 @@ public class ScmServletModule extends ServletModule
|
||||
// bind core
|
||||
bind(StoreFactory.class, JAXBStoreFactory.class);
|
||||
bind(ListenableStoreFactory.class, JAXBStoreFactory.class);
|
||||
bind(ConfigurationEntryStoreFactory.class,
|
||||
JAXBConfigurationEntryStoreFactory.class);
|
||||
bind(DataStoreFactory.class, JAXBDataStoreFactory.class);
|
||||
bind(BlobStoreFactory.class, FileBlobStoreFactory.class);
|
||||
bind(ScmConfiguration.class).toInstance(config);
|
||||
@@ -271,6 +276,7 @@ public class ScmServletModule extends ServletModule
|
||||
bind(AuthenticationManager.class, ChainAuthenticatonManager.class);
|
||||
bind(SecurityContext.class).to(BasicSecurityContext.class);
|
||||
bind(WebSecurityContext.class).to(BasicSecurityContext.class);
|
||||
bind(SecuritySystem.class).to(DefaultSecuritySystem.class);
|
||||
bind(AdministrationContext.class, DefaultAdministrationContext.class);
|
||||
|
||||
// bind cache
|
||||
|
||||
167
scm-webapp/src/main/java/sonia/scm/api/rest/Permission.java
Normal file
167
scm-webapp/src/main/java/sonia/scm/api/rest/Permission.java
Normal file
@@ -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;
|
||||
}
|
||||
@@ -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<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;
|
||||
}
|
||||
@@ -56,6 +56,9 @@ import sonia.scm.ScmState;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.group.GroupNames;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.security.PermissionDescriptor;
|
||||
import sonia.scm.security.Role;
|
||||
import sonia.scm.security.SecuritySystem;
|
||||
import sonia.scm.security.Tokens;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
@@ -64,6 +67,7 @@ import sonia.scm.user.UserManager;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -105,16 +109,18 @@ public class AuthenticationResource
|
||||
* @param repositoryManger
|
||||
* @param userManager
|
||||
* @param securityContextProvider
|
||||
* @param securitySystem
|
||||
*/
|
||||
@Inject
|
||||
public AuthenticationResource(SCMContextProvider contextProvider,
|
||||
ScmConfiguration configuration, RepositoryManager repositoryManger,
|
||||
UserManager userManager)
|
||||
UserManager userManager, SecuritySystem securitySystem)
|
||||
{
|
||||
this.contextProvider = contextProvider;
|
||||
this.configuration = configuration;
|
||||
this.repositoryManger = repositoryManger;
|
||||
this.userManager = userManager;
|
||||
this.securitySystem = securitySystem;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
@@ -295,7 +301,8 @@ public class AuthenticationResource
|
||||
*/
|
||||
private ScmState createAnonymousState()
|
||||
{
|
||||
return createState(SCMContext.ANONYMOUS, Collections.EMPTY_LIST);
|
||||
return createState(SCMContext.ANONYMOUS, Collections.EMPTY_LIST,
|
||||
Collections.EMPTY_LIST);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,7 +321,14 @@ public class AuthenticationResource
|
||||
User user = collection.oneByType(User.class);
|
||||
GroupNames groups = collection.oneByType(GroupNames.class);
|
||||
|
||||
return createState(user, groups.getCollection());
|
||||
List<PermissionDescriptor> ap = Collections.EMPTY_LIST;
|
||||
|
||||
if (subject.hasRole(Role.ADMIN))
|
||||
{
|
||||
ap = securitySystem.getAvailablePermissions();
|
||||
}
|
||||
|
||||
return createState(user, groups.getCollection(), ap);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -323,14 +337,16 @@ public class AuthenticationResource
|
||||
*
|
||||
* @param user
|
||||
* @param groups
|
||||
* @param availablePermissions
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private ScmState createState(User user, Collection<String> groups)
|
||||
private ScmState createState(User user, Collection<String> groups,
|
||||
List<PermissionDescriptor> availablePermissions)
|
||||
{
|
||||
return new ScmState(contextProvider, user, groups,
|
||||
repositoryManger.getConfiguredTypes(), userManager.getDefaultType(),
|
||||
new ScmClientConfig(configuration));
|
||||
new ScmClientConfig(configuration), availablePermissions);
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
@@ -344,6 +360,9 @@ public class AuthenticationResource
|
||||
/** Field description */
|
||||
private RepositoryManager repositoryManger;
|
||||
|
||||
/** Field description */
|
||||
private SecuritySystem securitySystem;
|
||||
|
||||
/** Field description */
|
||||
private UserManager userManager;
|
||||
}
|
||||
|
||||
@@ -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<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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
@@ -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<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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,501 @@
|
||||
/**
|
||||
* 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.security;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableList.Builder;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.HandlerEvent;
|
||||
import sonia.scm.event.ScmEventBus;
|
||||
import sonia.scm.event.Subscriber;
|
||||
import sonia.scm.group.GroupEvent;
|
||||
import sonia.scm.store.ConfigurationEntryStore;
|
||||
import sonia.scm.store.ConfigurationEntryStoreFactory;
|
||||
import sonia.scm.user.UserEvent;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* TODO add events
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
* @since 1.31
|
||||
*/
|
||||
@Singleton
|
||||
@Subscriber(async = true)
|
||||
public class DefaultSecuritySystem implements SecuritySystem
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
private static final String NAME = "security";
|
||||
|
||||
/** Field description */
|
||||
private static final String PERMISSION_DESCRIPTOR =
|
||||
"META-INF/scm/permissions.xml";
|
||||
|
||||
/**
|
||||
* the logger for DefaultSecuritySystem
|
||||
*/
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(DefaultSecuritySystem.class);
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param storeFactory
|
||||
*/
|
||||
@Inject
|
||||
public DefaultSecuritySystem(ConfigurationEntryStoreFactory storeFactory)
|
||||
{
|
||||
store = storeFactory.getStore(AssignedPermission.class, NAME);
|
||||
readAvailablePermissions();
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param permission
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public StoredAssignedPermission addPermission(AssignedPermission permission)
|
||||
{
|
||||
assertIsAdmin();
|
||||
|
||||
String id = store.put(permission);
|
||||
|
||||
StoredAssignedPermission sap = new StoredAssignedPermission(id, permission);
|
||||
|
||||
//J-
|
||||
ScmEventBus.getInstance().post(
|
||||
new StoredAssignedPermissionEvent(HandlerEvent.CREATE, sap)
|
||||
);
|
||||
//J+
|
||||
|
||||
return sap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param permission
|
||||
*/
|
||||
@Override
|
||||
public void deletePermission(StoredAssignedPermission permission)
|
||||
{
|
||||
assertIsAdmin();
|
||||
store.remove(permission.getId());
|
||||
//J-
|
||||
ScmEventBus.getInstance().post(
|
||||
new StoredAssignedPermissionEvent(HandlerEvent.CREATE, permission)
|
||||
);
|
||||
//J+
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
@Override
|
||||
public void deletePermission(String id)
|
||||
{
|
||||
assertIsAdmin();
|
||||
|
||||
AssignedPermission ap = store.get(id);
|
||||
|
||||
if (ap != null)
|
||||
{
|
||||
deletePermission(new StoredAssignedPermission(id, ap));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
@Subscribe
|
||||
public void handleEvent(final UserEvent event)
|
||||
{
|
||||
if (event.getEventType() == HandlerEvent.DELETE)
|
||||
{
|
||||
deletePermissions(new Predicate<AssignedPermission>()
|
||||
{
|
||||
|
||||
@Override
|
||||
public boolean apply(AssignedPermission p)
|
||||
{
|
||||
return !p.isGroupPermission()
|
||||
&& event.getItem().getName().equals(p.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
@Subscribe
|
||||
public void handleEvent(final GroupEvent event)
|
||||
{
|
||||
if (event.getEventType() == HandlerEvent.DELETE)
|
||||
{
|
||||
deletePermissions(new Predicate<AssignedPermission>()
|
||||
{
|
||||
|
||||
@Override
|
||||
public boolean apply(AssignedPermission p)
|
||||
{
|
||||
return p.isGroupPermission()
|
||||
&& event.getItem().getName().equals(p.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param permission
|
||||
*/
|
||||
@Override
|
||||
public void modifyPermission(StoredAssignedPermission permission)
|
||||
{
|
||||
assertIsAdmin();
|
||||
|
||||
synchronized (store)
|
||||
{
|
||||
store.remove(permission.getId());
|
||||
store.put(permission.getId(), new AssignedPermission(permission));
|
||||
}
|
||||
|
||||
//J-
|
||||
ScmEventBus.getInstance().post(
|
||||
new StoredAssignedPermissionEvent(HandlerEvent.CREATE, permission)
|
||||
);
|
||||
//J+
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<StoredAssignedPermission> getAllPermissions()
|
||||
{
|
||||
return getPermissions(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<PermissionDescriptor> 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
|
||||
*
|
||||
*
|
||||
* @param predicate
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<StoredAssignedPermission> getPermissions(
|
||||
Predicate<AssignedPermission> predicate)
|
||||
{
|
||||
Builder<StoredAssignedPermission> permissions = ImmutableList.builder();
|
||||
|
||||
for (Entry<String, AssignedPermission> e : store.getAll().entrySet())
|
||||
{
|
||||
if ((predicate == null) || predicate.apply(e.getValue()))
|
||||
{
|
||||
permissions.add(new StoredAssignedPermission(e.getKey(), e.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
return permissions.build();
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
private void assertIsAdmin()
|
||||
{
|
||||
SecurityUtils.getSubject().checkRole(Role.ADMIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param predicate
|
||||
*/
|
||||
private void deletePermissions(Predicate<AssignedPermission> predicate)
|
||||
{
|
||||
List<StoredAssignedPermission> permissions = getPermissions(predicate);
|
||||
|
||||
for (StoredAssignedPermission permission : permissions)
|
||||
{
|
||||
deletePermission(permission);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param context
|
||||
* @param descriptorUrl
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private List<PermissionDescriptor> parsePermissionDescriptor(
|
||||
JAXBContext context, URL descriptorUrl)
|
||||
{
|
||||
List<PermissionDescriptor> descriptors = Collections.EMPTY_LIST;
|
||||
|
||||
try
|
||||
{
|
||||
PermissionDescriptors descriptorWrapper =
|
||||
(PermissionDescriptors) context.createUnmarshaller().unmarshal(
|
||||
descriptorUrl);
|
||||
|
||||
descriptors = descriptorWrapper.getPermissions();
|
||||
|
||||
logger.debug("found {} permissions at {}", descriptors.size(),
|
||||
descriptorUrl);
|
||||
logger.trace("permissions from {}: {}", descriptorUrl, descriptors);
|
||||
}
|
||||
catch (JAXBException ex)
|
||||
{
|
||||
logger.error("could not parse permission descriptor", ex);
|
||||
}
|
||||
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
private void readAvailablePermissions()
|
||||
{
|
||||
Builder<PermissionDescriptor> builder = ImmutableList.builder();
|
||||
|
||||
try
|
||||
{
|
||||
JAXBContext context =
|
||||
JAXBContext.newInstance(PermissionDescriptors.class);
|
||||
|
||||
Enumeration<URL> descirptorEnum =
|
||||
getClassLoader().getResources(PERMISSION_DESCRIPTOR);
|
||||
|
||||
while (descirptorEnum.hasMoreElements())
|
||||
{
|
||||
URL descriptorUrl = descirptorEnum.nextElement();
|
||||
|
||||
logger.debug("read permission descriptor from {}", descriptorUrl);
|
||||
|
||||
builder.addAll(parsePermissionDescriptor(context, descriptorUrl));
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.error("could not read permission descriptors", ex);
|
||||
}
|
||||
catch (JAXBException ex)
|
||||
{
|
||||
logger.error(
|
||||
"could not create jaxb context to read permission descriptors", ex);
|
||||
}
|
||||
|
||||
availablePermissions = builder.build();
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private ClassLoader getClassLoader()
|
||||
{
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
|
||||
if (classLoader == null)
|
||||
{
|
||||
logger.warn("could not find context classloader, use default");
|
||||
|
||||
classLoader = DefaultSecuritySystem.class.getClassLoader();
|
||||
}
|
||||
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
//~--- inner classes --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Class description
|
||||
*
|
||||
*
|
||||
* @version Enter version here..., 13/04/30
|
||||
* @author Enter your name here...
|
||||
*/
|
||||
@XmlRootElement(name = "permissions")
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
private static class PermissionDescriptors
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*/
|
||||
public PermissionDescriptors() {}
|
||||
|
||||
//~--- get methods --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<PermissionDescriptor> getPermissions()
|
||||
{
|
||||
if (permissions == null)
|
||||
{
|
||||
permissions = Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
return permissions;
|
||||
}
|
||||
|
||||
//~--- fields -------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
@XmlElement(name = "permission")
|
||||
private List<PermissionDescriptor> permissions;
|
||||
}
|
||||
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private final ConfigurationEntryStore<AssignedPermission> store;
|
||||
|
||||
/** Field description */
|
||||
private List<PermissionDescriptor> availablePermissions;
|
||||
}
|
||||
@@ -36,6 +36,7 @@ package sonia.scm.security;
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
@@ -128,6 +129,7 @@ public class ScmRealm extends AuthorizingRealm
|
||||
*
|
||||
*
|
||||
* @param configuration
|
||||
* @param securitySystem
|
||||
* @param cacheManager
|
||||
* @param userManager
|
||||
* @param groupManager
|
||||
@@ -139,7 +141,8 @@ public class ScmRealm extends AuthorizingRealm
|
||||
* @param responseProvider
|
||||
*/
|
||||
@Inject
|
||||
public ScmRealm(ScmConfiguration configuration, CacheManager cacheManager,
|
||||
public ScmRealm(ScmConfiguration configuration,
|
||||
SecuritySystem securitySystem, CacheManager cacheManager,
|
||||
UserManager userManager, GroupManager groupManager,
|
||||
RepositoryDAO repositoryDAO, UserDAO userDAO,
|
||||
AuthenticationManager authenticator, RepositoryManager manager,
|
||||
@@ -147,6 +150,7 @@ public class ScmRealm extends AuthorizingRealm
|
||||
Provider<HttpServletResponse> responseProvider)
|
||||
{
|
||||
this.configuration = configuration;
|
||||
this.securitySystem = securitySystem;
|
||||
this.userManager = userManager;
|
||||
this.groupManager = groupManager;
|
||||
this.repositoryDAO = repositoryDAO;
|
||||
@@ -194,6 +198,27 @@ public class ScmRealm extends AuthorizingRealm
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
@Subscribe
|
||||
public void onEvent(StoredAssignedPermissionEvent event)
|
||||
{
|
||||
if (event.getEventType().isPost())
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("clear cache, because permission {} has changed",
|
||||
event.getPermission().getId());
|
||||
}
|
||||
|
||||
cache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -474,6 +499,51 @@ public class ScmRealm extends AuthorizingRealm
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param user
|
||||
* @param groups
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private List<String> collectGlobalPermissions(final User user,
|
||||
final GroupNames groups)
|
||||
{
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
logger.trace("collect global permissions for user {}", user.getName());
|
||||
}
|
||||
|
||||
List<String> permissions = Lists.newArrayList();
|
||||
|
||||
List<StoredAssignedPermission> globalPermissions =
|
||||
securitySystem.getPermissions(new Predicate<AssignedPermission>()
|
||||
{
|
||||
|
||||
@Override
|
||||
public boolean apply(AssignedPermission input)
|
||||
{
|
||||
return isUserPermission(user, groups, input);
|
||||
}
|
||||
});
|
||||
|
||||
for (StoredAssignedPermission gp : globalPermissions)
|
||||
{
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
logger.trace("add permission {} for user {}", gp.getPermission(),
|
||||
user.getName());
|
||||
}
|
||||
|
||||
permissions.add(gp.getPermission());
|
||||
|
||||
}
|
||||
|
||||
return permissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -585,7 +655,8 @@ public class ScmRealm extends AuthorizingRealm
|
||||
GroupNames groups)
|
||||
{
|
||||
Set<String> roles = Sets.newHashSet();
|
||||
List<org.apache.shiro.authz.Permission> permissions = null;
|
||||
List<org.apache.shiro.authz.Permission> permissions;
|
||||
List<String> globalPermissions = null;
|
||||
|
||||
roles.add(Role.USER);
|
||||
|
||||
@@ -604,12 +675,18 @@ public class ScmRealm extends AuthorizingRealm
|
||||
else
|
||||
{
|
||||
permissions = collectRepositoryPermissions(user, groups);
|
||||
globalPermissions = collectGlobalPermissions(user, groups);
|
||||
}
|
||||
|
||||
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);
|
||||
|
||||
info.addObjectPermissions(permissions);
|
||||
|
||||
if (globalPermissions != null)
|
||||
{
|
||||
info.addStringPermissions(globalPermissions);
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
@@ -737,7 +814,7 @@ public class ScmRealm extends AuthorizingRealm
|
||||
* @return
|
||||
*/
|
||||
private boolean isUserPermission(User user, GroupNames groups,
|
||||
Permission perm)
|
||||
PermissionObject perm)
|
||||
{
|
||||
//J-
|
||||
return (perm.isGroupPermission() && groups.contains(perm.getName()))
|
||||
@@ -768,6 +845,9 @@ public class ScmRealm extends AuthorizingRealm
|
||||
/** Field description */
|
||||
private Provider<HttpServletResponse> responseProvider;
|
||||
|
||||
/** Field description */
|
||||
private SecuritySystem securitySystem;
|
||||
|
||||
/** Field description */
|
||||
private UserDAO userDAO;
|
||||
|
||||
|
||||
54
scm-webapp/src/main/resources/META-INF/scm/permissions.xml
Normal file
54
scm-webapp/src/main/resources/META-INF/scm/permissions.xml
Normal file
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--*
|
||||
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
|
||||
|
||||
-->
|
||||
|
||||
|
||||
<permissions>
|
||||
|
||||
<permission>
|
||||
<display-name>All Repository (read)</display-name>
|
||||
<description>Read access to all repositories</description>
|
||||
<value>repository:*:READ</value>
|
||||
</permission>
|
||||
|
||||
<permission>
|
||||
<display-name>All Repository (write)</display-name>
|
||||
<description>Write access to all repositories</description>
|
||||
<value>repository:*:WRITE</value>
|
||||
</permission>
|
||||
|
||||
<permission>
|
||||
<display-name>All Repository (owner)</display-name>
|
||||
<description>Owner access to all repositories</description>
|
||||
<value>repository:*:OWNER</value>
|
||||
</permission>
|
||||
|
||||
</permissions>
|
||||
@@ -143,6 +143,10 @@
|
||||
<script type="text/javascript" src="resources/js/group/sonia.group.memberformpanel.js"></script>
|
||||
<script type="text/javascript" src="resources/js/group/sonia.group.panel.js"></script>
|
||||
|
||||
<!-- sonia.security -->
|
||||
<script type="text/javascript" src="resources/js/security/sonia.security.js"></script>
|
||||
<script type="text/javascript" src="resources/js/security/sonia.security.permissionspanel.js"></script>
|
||||
|
||||
<!-- sonia.config -->
|
||||
<script type="text/javascript" src="resources/js/config/sonia.config.js"></script>
|
||||
<script type="text/javascript" src="resources/js/config/sonia.config.configpanel.js"></script>
|
||||
|
||||
@@ -47,7 +47,7 @@ Sonia.group.FormPanel = Ext.extend(Sonia.rest.FormPanel,{
|
||||
|
||||
initComponent: function(){
|
||||
this.addEvents('preCreate', 'created', 'preUpdate', 'updated', 'updateFailed', 'creationFailed');
|
||||
Sonia.repository.FormPanel.superclass.initComponent.apply(this, arguments);
|
||||
Sonia.group.FormPanel.superclass.initComponent.apply(this, arguments);
|
||||
},
|
||||
|
||||
update: function(group){
|
||||
|
||||
@@ -105,7 +105,7 @@ Sonia.group.Grid = Ext.extend(Sonia.rest.Grid, {
|
||||
|
||||
renderMembers: function(members){
|
||||
var out = '';
|
||||
if ( members != null ){
|
||||
if ( members !== null ){
|
||||
var s = members.length;
|
||||
for ( var i=0; i<s; i++ ){
|
||||
out += members[i];
|
||||
@@ -151,6 +151,9 @@ Sonia.group.Grid = Ext.extend(Sonia.rest.Grid, {
|
||||
scope: this
|
||||
}
|
||||
}
|
||||
},{
|
||||
xtype: 'permissionsPanel',
|
||||
baseUrl: 'security/permission/group/' + group.name
|
||||
}]);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ Sonia.group.setEditPanel = function(panels){
|
||||
});
|
||||
editPanel.setActiveTab(0);
|
||||
editPanel.doLayout();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* panels
|
||||
@@ -51,4 +51,4 @@ Sonia.group.DefaultPanel = {
|
||||
bodyCssClass: 'x-panel-mc',
|
||||
padding: 5,
|
||||
html: 'Add or select a Group'
|
||||
}
|
||||
};
|
||||
|
||||
@@ -69,9 +69,9 @@ Sonia.group.MemberFormPanel = Ext.extend(Sonia.group.FormPanel, {
|
||||
singleSelect: true
|
||||
});
|
||||
|
||||
if ( this.item != null ){
|
||||
if ( this.item !== null ){
|
||||
var data = [];
|
||||
if ( this.item.members != null ){
|
||||
if ( this.item.members !== null ){
|
||||
for ( var i=0; i<this.item.members.length; i++ ){
|
||||
var a = [];
|
||||
a.push( this.item.members[i] );
|
||||
|
||||
@@ -50,27 +50,26 @@ Sonia.group.Panel = Ext.extend(Sonia.rest.Panel, {
|
||||
{xtype: 'tbbutton', text: this.reloadText, icon: this.reloadIcon, scope: this, handler: this.reload}
|
||||
],
|
||||
items: [{
|
||||
id: 'groupGrid',
|
||||
xtype: 'groupGrid',
|
||||
region: 'center',
|
||||
parentPanel: this
|
||||
}, {
|
||||
id: 'groupEditPanel',
|
||||
xtype: 'tabpanel',
|
||||
activeTab: 0,
|
||||
height: 250,
|
||||
split: true,
|
||||
border: true,
|
||||
region: 'south',
|
||||
items: [{
|
||||
bodyCssClass: 'x-panel-mc',
|
||||
title: this.titleText,
|
||||
padding: 5,
|
||||
html: this.emptyText
|
||||
}]
|
||||
}
|
||||
]
|
||||
}
|
||||
id: 'groupGrid',
|
||||
xtype: 'groupGrid',
|
||||
region: 'center',
|
||||
parentPanel: this
|
||||
}, {
|
||||
id: 'groupEditPanel',
|
||||
xtype: 'tabpanel',
|
||||
activeTab: 0,
|
||||
height: 250,
|
||||
split: true,
|
||||
border: true,
|
||||
region: 'south',
|
||||
items: [{
|
||||
bodyCssClass: 'x-panel-mc',
|
||||
title: this.titleText,
|
||||
padding: 5,
|
||||
html: this.emptyText
|
||||
}]
|
||||
}]
|
||||
};
|
||||
|
||||
Ext.apply(this, Ext.apply(this.initialConfig, config));
|
||||
Sonia.group.Panel.superclass.initComponent.apply(this, arguments);
|
||||
@@ -104,7 +103,7 @@ Sonia.group.Panel = Ext.extend(Sonia.rest.Panel, {
|
||||
buttons: Ext.MessageBox.OKCANCEL,
|
||||
icon: Ext.MessageBox.QUESTION,
|
||||
fn: function(result){
|
||||
if ( result == 'ok' ){
|
||||
if ( result === 'ok' ){
|
||||
|
||||
if ( debug ){
|
||||
console.debug( 'remove group ' + item.name );
|
||||
|
||||
@@ -38,7 +38,7 @@ Sonia.group.PropertiesFormPanel = Ext.extend(Sonia.group.FormPanel, {
|
||||
fieldLabel: this.nameText,
|
||||
name: 'name',
|
||||
allowBlank: false,
|
||||
readOnly: this.item != null,
|
||||
readOnly: this.item !== null,
|
||||
helpText: this.nameHelpText,
|
||||
vtype: 'name'
|
||||
},{
|
||||
@@ -47,7 +47,7 @@ Sonia.group.PropertiesFormPanel = Ext.extend(Sonia.group.FormPanel, {
|
||||
xtype: 'textarea',
|
||||
helpText: this.descriptionHelpText
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
Ext.apply(this, Ext.apply(this.initialConfig, config));
|
||||
Sonia.group.PropertiesFormPanel.superclass.initComponent.apply(this, arguments);
|
||||
|
||||
@@ -56,12 +56,12 @@ Sonia.rest.FormPanel = Ext.extend(Ext.FormPanel,{
|
||||
{text: this.okText, formBind: true, scope: this, handler: this.submit},
|
||||
{text: this.cancelText, scope: this, handler: this.cancel}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
Ext.apply(this, Ext.apply(this.initialConfig, config));
|
||||
Sonia.rest.FormPanel.superclass.initComponent.apply(this, arguments);
|
||||
|
||||
if ( this.item != null ){
|
||||
if ( this.item !== null ){
|
||||
this.loadData(this.item);
|
||||
}
|
||||
},
|
||||
@@ -77,7 +77,7 @@ Sonia.rest.FormPanel = Ext.extend(Ext.FormPanel,{
|
||||
console.debug( 'form submitted' );
|
||||
}
|
||||
var item = this.getForm().getFieldValues();
|
||||
if ( this.item != null ){
|
||||
if ( this.item !== null ){
|
||||
this.update(item);
|
||||
} else {
|
||||
this.create(item);
|
||||
|
||||
@@ -39,6 +39,7 @@ Sonia.rest.Panel = Ext.extend(Ext.Panel, {
|
||||
addIcon: 'resources/images/add.png',
|
||||
removeIcon: 'resources/images/delete.png',
|
||||
reloadIcon: 'resources/images/reload.png',
|
||||
helpIcon: 'resources/images/help.png',
|
||||
|
||||
initComponent: function(){
|
||||
|
||||
@@ -48,7 +49,7 @@ Sonia.rest.Panel = Ext.extend(Ext.Panel, {
|
||||
enableTabScroll: true,
|
||||
region:'center',
|
||||
autoScroll: true
|
||||
}
|
||||
};
|
||||
|
||||
Ext.apply(this, Ext.apply(this.initialConfig, config));
|
||||
Sonia.rest.Panel.superclass.initComponent.apply(this, arguments);
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
// register namespace
|
||||
Ext.ns('Sonia.security');
|
||||
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
Sonia.security.PermissionsPanel = Ext.extend(Ext.Panel, {
|
||||
|
||||
addText: 'Add',
|
||||
removeText: 'Remove',
|
||||
reloadText: 'Reload',
|
||||
|
||||
// icons
|
||||
addIcon: 'resources/images/add.png',
|
||||
removeIcon: 'resources/images/delete.png',
|
||||
reloadIcon: 'resources/images/reload.png',
|
||||
helpIcon: 'resources/images/help.png',
|
||||
|
||||
|
||||
//TODO i18n
|
||||
titleText: 'Permissions',
|
||||
|
||||
permissionStore: null,
|
||||
baseUrl: null,
|
||||
|
||||
initComponent: function(){
|
||||
|
||||
this.permissionStore = new Sonia.rest.JsonStore({
|
||||
proxy: new Ext.data.HttpProxy({
|
||||
api: {
|
||||
read: restUrl + this.baseUrl + '.json'
|
||||
},
|
||||
disableCaching: false
|
||||
}),
|
||||
idProperty: 'id',
|
||||
fields: [ 'id', 'value'],
|
||||
listeners: {
|
||||
update: {
|
||||
fn: this.modifyOrAddPermission,
|
||||
scope: this
|
||||
},
|
||||
remove: {
|
||||
fn: this.removePermission,
|
||||
scope: this
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var availablePermissionStore = new Ext.data.JsonStore({
|
||||
fields: ['display-name', 'description', 'value'],
|
||||
sortInfo: {
|
||||
field: 'display-name'
|
||||
}
|
||||
});
|
||||
availablePermissionStore.loadData(state.availablePermissions);
|
||||
|
||||
var permissionColModel = new Ext.grid.ColumnModel({
|
||||
columns: [{
|
||||
id: 'value',
|
||||
header: 'Permission',
|
||||
dataIndex: 'value',
|
||||
renderer: this.renderPermission,
|
||||
editor: new Ext.form.ComboBox({
|
||||
store: availablePermissionStore,
|
||||
displayField: 'display-name',
|
||||
valueField: 'value',
|
||||
typeAhead: false,
|
||||
editable: false,
|
||||
triggerAction: 'all',
|
||||
mode: 'local',
|
||||
width: 250
|
||||
})
|
||||
}]
|
||||
});
|
||||
|
||||
var selectionModel = new Ext.grid.RowSelectionModel({
|
||||
singleSelect: true
|
||||
});
|
||||
|
||||
var config = {
|
||||
title: this.titleText,
|
||||
bodyCssClass: 'x-panel-mc',
|
||||
padding: 5,
|
||||
items: [{
|
||||
id: 'permissionGrid',
|
||||
xtype: 'editorgrid',
|
||||
clicksToEdit: 1,
|
||||
frame: true,
|
||||
width: '100%',
|
||||
autoHeight: true,
|
||||
autoScroll: false,
|
||||
colModel: permissionColModel,
|
||||
sm: selectionModel,
|
||||
store: this.permissionStore,
|
||||
viewConfig: {
|
||||
forceFit: true,
|
||||
markDirty: false
|
||||
},
|
||||
tbar: [{
|
||||
text: this.addText,
|
||||
scope: this,
|
||||
icon: this.addIcon,
|
||||
handler : function(){
|
||||
var Permission = this.permissionStore.recordType;
|
||||
var grid = Ext.getCmp('permissionGrid');
|
||||
grid.stopEditing();
|
||||
this.permissionStore.insert(0, new Permission());
|
||||
grid.startEditing(0, 0);
|
||||
}
|
||||
},{
|
||||
text: this.removeText,
|
||||
scope: this,
|
||||
icon: this.removeIcon,
|
||||
handler: function(){
|
||||
var grid = Ext.getCmp('permissionGrid');
|
||||
var selected = grid.getSelectionModel().getSelected();
|
||||
if ( selected ){
|
||||
this.permissionStore.remove(selected);
|
||||
}
|
||||
}
|
||||
},'->',{
|
||||
id: 'permissionGridHelp',
|
||||
xtype: 'box',
|
||||
autoEl: {
|
||||
tag: 'img',
|
||||
src: this.helpIcon
|
||||
}
|
||||
}]
|
||||
}]
|
||||
};
|
||||
|
||||
Ext.apply(this, Ext.apply(this.initialConfig, config));
|
||||
Sonia.security.PermissionsPanel.superclass.initComponent.apply(this, arguments);
|
||||
},
|
||||
|
||||
getIdFromResponse: function(response){
|
||||
var id = null;
|
||||
var location = response.getResponseHeader('Location');
|
||||
if (location){
|
||||
var parts = location.split('/');
|
||||
id = parts[parts.length - 1];
|
||||
}
|
||||
return id;
|
||||
},
|
||||
|
||||
modifyOrAddPermission: function(store, record){
|
||||
var id = record.get('id');
|
||||
if ( id ){
|
||||
this.modifyPermission(id, record);
|
||||
} else {
|
||||
this.addPermission(record);
|
||||
}
|
||||
},
|
||||
|
||||
addPermission: function(record){
|
||||
Ext.Ajax.request({
|
||||
url: restUrl + this.baseUrl + '.json',
|
||||
method: 'POST',
|
||||
jsonData: record.data,
|
||||
scope: this,
|
||||
success: function(response){
|
||||
var id = this.getIdFromResponse(response);
|
||||
record.data.id = id;
|
||||
},
|
||||
failure: function(result){
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
modifyPermission: function(id, record){
|
||||
Ext.Ajax.request({
|
||||
url: restUrl + this.baseUrl + '/' + id + '.json',
|
||||
method: 'PUT',
|
||||
jsonData: record.data,
|
||||
scope: this,
|
||||
success: function(){
|
||||
},
|
||||
failure: function(result){
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removePermission: function(store, record){
|
||||
Ext.Ajax.request({
|
||||
url: restUrl + this.baseUrl + '/' + record.get('id') + '.json',
|
||||
method: 'DELETE',
|
||||
scope: this,
|
||||
success: function(){
|
||||
|
||||
},
|
||||
failure: function(result){
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
renderPermission: function(value){
|
||||
var ap = state.availablePermissions;
|
||||
for (var i=0; i<ap.length; i++){
|
||||
if ( value === ap[i].value ){
|
||||
value = ap[i]['display-name'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// register xtype
|
||||
Ext.reg('permissionsPanel', Sonia.security.PermissionsPanel);
|
||||
@@ -50,7 +50,7 @@ Sonia.scm.Main = Ext.extend(Ext.util.Observable, {
|
||||
tabUsersText: 'Users',
|
||||
navGroupsText: 'Groups',
|
||||
tabGroupsText: 'Groups',
|
||||
|
||||
|
||||
sectionLoginText: 'Login',
|
||||
navLoginText: 'Login',
|
||||
|
||||
@@ -236,8 +236,7 @@ Sonia.scm.Main = Ext.extend(Ext.util.Observable, {
|
||||
label: this.navUsersText,
|
||||
fn: this.addUsersTabPanel,
|
||||
scope: this
|
||||
});
|
||||
securitySection.links.push({
|
||||
},{
|
||||
label: this.navGroupsText,
|
||||
fn: this.addGroupsTabPanel,
|
||||
scope: this
|
||||
|
||||
@@ -57,7 +57,7 @@ Sonia.user.FormPanel = Ext.extend(Sonia.rest.FormPanel,{
|
||||
fieldLabel: this.nameText,
|
||||
name: 'name',
|
||||
allowBlank: false,
|
||||
readOnly: this.item != null,
|
||||
readOnly: this.item !== null,
|
||||
helpText: this.usernameHelpText,
|
||||
vtype: 'username'
|
||||
},{
|
||||
@@ -75,7 +75,7 @@ Sonia.user.FormPanel = Ext.extend(Sonia.rest.FormPanel,{
|
||||
helpText: this.mailHelpText
|
||||
}];
|
||||
|
||||
if ( this.item == null || this.item.type == state.defaultUserType ){
|
||||
if ( this.item === null || this.item.type === state.defaultUserType ){
|
||||
items.push({
|
||||
fieldLabel: this.passwordText,
|
||||
id: 'pwd',
|
||||
@@ -109,13 +109,13 @@ Sonia.user.FormPanel = Ext.extend(Sonia.rest.FormPanel,{
|
||||
helpText: this.activeHelpText,
|
||||
checked: true
|
||||
});
|
||||
|
||||
|
||||
Ext.apply(this, Ext.apply(this.initialConfig, {items: items}));
|
||||
Sonia.user.FormPanel.superclass.initComponent.apply(this, arguments);
|
||||
},
|
||||
|
||||
isReadOnly: function(){
|
||||
return this.item != null && this.item.type != state.defaultUserType;
|
||||
return this.item !== null && this.item.type !== state.defaultUserType;
|
||||
},
|
||||
|
||||
fixRequest: function(user){
|
||||
|
||||
@@ -128,13 +128,16 @@ Sonia.user.Grid = Ext.extend(Sonia.rest.Grid, {
|
||||
scope: this
|
||||
}
|
||||
});
|
||||
if ( item.type == state.defaultUserType ){
|
||||
if ( item.type === state.defaultUserType ){
|
||||
panel.getForm().setValues([
|
||||
{id: 'password', value: dummyPassword},
|
||||
{id: 'password-confirm', value: dummyPassword}
|
||||
]);
|
||||
}
|
||||
Sonia.user.setEditPanel(panel);
|
||||
Sonia.user.setEditPanel([panel,{
|
||||
xtype: 'permissionsPanel',
|
||||
baseUrl: 'security/permission/user/' + item.name
|
||||
}]);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -34,12 +34,15 @@ Ext.ns('Sonia.user');
|
||||
|
||||
// functions
|
||||
|
||||
Sonia.user.setEditPanel = function(panel){
|
||||
Sonia.user.setEditPanel = function(panels){
|
||||
var editPanel = Ext.getCmp('userEditPanel');
|
||||
editPanel.removeAll();
|
||||
editPanel.add(panel);
|
||||
Ext.each(panels, function(panel){
|
||||
editPanel.add(panel);
|
||||
});
|
||||
editPanel.setActiveTab(0);
|
||||
editPanel.doLayout();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Panels
|
||||
@@ -49,6 +52,7 @@ Sonia.user.DefaultPanel = {
|
||||
title: 'User Form',
|
||||
padding: 5,
|
||||
xtype: 'panel',
|
||||
bodyCssClass: 'x-panel-mc',
|
||||
html: 'Add or select an User'
|
||||
};
|
||||
|
||||
|
||||
@@ -43,9 +43,7 @@ Sonia.user.Panel = Ext.extend(Sonia.rest.Panel, {
|
||||
userGrid: null,
|
||||
|
||||
initComponent: function(){
|
||||
|
||||
var config = {
|
||||
bodyCssClass: 'x-panel-mc',
|
||||
tbar: [
|
||||
{xtype: 'tbbutton', text: this.addText, icon: this.addIcon, scope: this, handler: this.showAddPanel},
|
||||
{xtype: 'tbbutton', text: this.removeText, icon: this.removeIcon, scope: this, handler: this.removeUser},
|
||||
@@ -61,20 +59,20 @@ Sonia.user.Panel = Ext.extend(Sonia.rest.Panel, {
|
||||
xtype: 'userGrid',
|
||||
region: 'center',
|
||||
parentPanel: this
|
||||
},{
|
||||
}, {
|
||||
id: 'userEditPanel',
|
||||
layout: 'fit',
|
||||
items: [{
|
||||
region: 'south',
|
||||
title: 'User Form',
|
||||
xtype: 'panel',
|
||||
padding: 5,
|
||||
html: this.emptyText
|
||||
}],
|
||||
xtype: 'tabpanel',
|
||||
activeTab: 0,
|
||||
height: 250,
|
||||
split: true,
|
||||
border: false,
|
||||
region: 'south'
|
||||
border: true,
|
||||
region: 'south',
|
||||
items: [{
|
||||
bodyCssClass: 'x-panel-mc',
|
||||
title: 'User Form',
|
||||
padding: 5,
|
||||
html: this.emptyText
|
||||
}]
|
||||
}]
|
||||
};
|
||||
|
||||
@@ -103,10 +101,8 @@ Sonia.user.Panel = Ext.extend(Sonia.rest.Panel, {
|
||||
},
|
||||
|
||||
showAddPanel: function(){
|
||||
var editPanel = Ext.getCmp('userEditPanel');
|
||||
editPanel.removeAll();
|
||||
var panel = new Sonia.user.FormPanel({
|
||||
region: 'south',
|
||||
Sonia.user.setEditPanel({
|
||||
xtype: 'userForm',
|
||||
title: this.titleText,
|
||||
padding: 5,
|
||||
onUpdate: {
|
||||
@@ -118,8 +114,6 @@ Sonia.user.Panel = Ext.extend(Sonia.rest.Panel, {
|
||||
scope: this
|
||||
}
|
||||
});
|
||||
editPanel.add(panel);
|
||||
editPanel.doLayout();
|
||||
},
|
||||
|
||||
resetPanel: function(){
|
||||
@@ -140,7 +134,7 @@ Sonia.user.Panel = Ext.extend(Sonia.rest.Panel, {
|
||||
buttons: Ext.MessageBox.OKCANCEL,
|
||||
icon: Ext.MessageBox.QUESTION,
|
||||
fn: function(result){
|
||||
if ( result == 'ok' ){
|
||||
if ( result === 'ok' ){
|
||||
|
||||
if ( debug ){
|
||||
console.debug( 'remove user ' + item.name );
|
||||
|
||||
@@ -0,0 +1,333 @@
|
||||
/**
|
||||
* 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.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;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import sonia.scm.AbstractTestBase;
|
||||
import sonia.scm.store.JAXBConfigurationEntryStoreFactory;
|
||||
import sonia.scm.util.MockUtil;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class DefaultSecuritySystemTest extends AbstractTestBase
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Before
|
||||
public void createSecuritySystem()
|
||||
{
|
||||
JAXBConfigurationEntryStoreFactory factory =
|
||||
new JAXBConfigurationEntryStoreFactory(new UUIDKeyGenerator(),
|
||||
contextProvider);
|
||||
|
||||
securitySystem = new DefaultSecuritySystem(factory);
|
||||
|
||||
// ScmEventBus.getInstance().register(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testAddPermission()
|
||||
{
|
||||
setAdminSubject();
|
||||
|
||||
StoredAssignedPermission sap = createPermission("trillian", false,
|
||||
"repository:*:READ");
|
||||
|
||||
assertEquals("trillian", sap.getName());
|
||||
assertEquals("repository:*:READ", sap.getPermission());
|
||||
assertEquals(false, sap.isGroupPermission());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testAvailablePermissions()
|
||||
{
|
||||
setAdminSubject();
|
||||
|
||||
List<PermissionDescriptor> list = securitySystem.getAvailablePermissions();
|
||||
|
||||
assertNotNull(list);
|
||||
assertThat(list.size(), greaterThan(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testDeletePermission()
|
||||
{
|
||||
setAdminSubject();
|
||||
|
||||
StoredAssignedPermission sap = createPermission("trillian", false,
|
||||
"repository:*:READ");
|
||||
|
||||
securitySystem.deletePermission(sap);
|
||||
|
||||
assertNull(securitySystem.getPermission(sap.getId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testGetAllPermissions()
|
||||
{
|
||||
setAdminSubject();
|
||||
|
||||
StoredAssignedPermission trillian = createPermission("trillian", false,
|
||||
"repository:*:READ");
|
||||
StoredAssignedPermission dent = createPermission("dent", false,
|
||||
"repository:*:READ");
|
||||
StoredAssignedPermission marvin = createPermission("marvin", false,
|
||||
"repository:*:READ");
|
||||
|
||||
List<StoredAssignedPermission> all = securitySystem.getAllPermissions();
|
||||
|
||||
assertEquals(3, all.size());
|
||||
assertThat(all, containsInAnyOrder(trillian, dent, marvin));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testGetPermission()
|
||||
{
|
||||
setAdminSubject();
|
||||
|
||||
StoredAssignedPermission sap = createPermission("trillian", false,
|
||||
"repository:*:READ");
|
||||
|
||||
StoredAssignedPermission other = securitySystem.getPermission(sap.getId());
|
||||
|
||||
assertEquals(sap.getId(), other.getId());
|
||||
assertEquals(sap, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testGetPermissionsWithPredicate()
|
||||
{
|
||||
setAdminSubject();
|
||||
|
||||
StoredAssignedPermission trillian = createPermission("trillian", false,
|
||||
"repository:*:READ");
|
||||
StoredAssignedPermission dent = createPermission("dent", false,
|
||||
"repository:*:READ");
|
||||
|
||||
createPermission("hitchhiker", true, "repository:*:READ");
|
||||
|
||||
List<StoredAssignedPermission> filtered =
|
||||
securitySystem.getPermissions(new Predicate<AssignedPermission>()
|
||||
{
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test(expected = UnauthorizedException.class)
|
||||
public void testUnauthorizedAddPermission()
|
||||
{
|
||||
setUserSubject();
|
||||
createPermission("trillian", false, "repository:*:READ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test(expected = UnauthorizedException.class)
|
||||
public void testUnauthorizedDeletePermission()
|
||||
{
|
||||
setAdminSubject();
|
||||
|
||||
StoredAssignedPermission sap = createPermission("trillian", false,
|
||||
"repository:*:READ");
|
||||
|
||||
setUserSubject();
|
||||
securitySystem.deletePermission(sap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test(expected = UnauthorizedException.class)
|
||||
public void testUnauthorizedGetPermission()
|
||||
{
|
||||
setAdminSubject();
|
||||
|
||||
StoredAssignedPermission sap = createPermission("trillian", false,
|
||||
"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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param name
|
||||
* @param groupPermission
|
||||
* @param value
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private StoredAssignedPermission createPermission(String name,
|
||||
boolean groupPermission, String value)
|
||||
{
|
||||
AssignedPermission ap = new AssignedPermission(name, groupPermission,
|
||||
value);
|
||||
StoredAssignedPermission sap = securitySystem.addPermission(ap);
|
||||
|
||||
assertNotNull(sap);
|
||||
assertNotNull(sap.getId());
|
||||
|
||||
return sap;
|
||||
}
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
private void setAdminSubject()
|
||||
{
|
||||
setSubject(MockUtil.createAdminSubject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
private void setUserSubject()
|
||||
{
|
||||
org.apache.shiro.mgt.SecurityManager sm =
|
||||
new DefaultSecurityManager(new SimpleAccountRealm());
|
||||
|
||||
setSubject(MockUtil.createUserSubject(sm));
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private DefaultSecuritySystem securitySystem;
|
||||
}
|
||||
@@ -35,6 +35,7 @@ package sonia.scm.security;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.inject.Provider;
|
||||
@@ -50,6 +51,8 @@ import org.apache.shiro.subject.PrincipalCollection;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import sonia.scm.cache.MapCacheManager;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.group.Group;
|
||||
@@ -76,6 +79,7 @@ import static org.mockito.Mockito.*;
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
@@ -464,9 +468,16 @@ public class ScmRealmTest
|
||||
AuthenticationResult.NOT_FOUND
|
||||
);
|
||||
|
||||
SecuritySystem securitySystem = mock(SecuritySystem.class);
|
||||
when(
|
||||
securitySystem.getPermissions(Mockito.<Predicate>any())
|
||||
).thenReturn(
|
||||
Collections.EMPTY_LIST
|
||||
);
|
||||
|
||||
return new ScmRealm(
|
||||
new ScmConfiguration(),
|
||||
securitySystem,
|
||||
new MapCacheManager(),
|
||||
userManager,
|
||||
groupManager,
|
||||
|
||||
Reference in New Issue
Block a user