CCM NG: Documentation for ccm-core:org.libreccm.security
git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@3762 8810af33-2d31-482b-a856-94f89814c4dfpull/2/head
parent
bf5ddceda7
commit
d043fbea56
|
|
@ -74,6 +74,8 @@ public class AuthorizationInterceptor {
|
|||
* @throws Exception If any exception occurs.
|
||||
*/
|
||||
@AroundInvoke
|
||||
// throws Exception necessary because InvocationContext#proceed has also throws Exception
|
||||
@SuppressWarnings("PMD.SignatureDeclareThrowsException")
|
||||
public Object intercept(final InvocationContext context) throws Exception {
|
||||
LOGGER.debug("Intercepting method invocation");
|
||||
|
||||
|
|
@ -123,6 +125,7 @@ public class AuthorizationInterceptor {
|
|||
* @param parameter The parameter to check.
|
||||
* @param annotations All annotations of the parameter.
|
||||
*/
|
||||
@SuppressWarnings("PMD.UseVarargs")
|
||||
private void checkParameterPermission(final Object parameter,
|
||||
final Annotation[] annotations) {
|
||||
if (parameter instanceof CcmObject
|
||||
|
|
@ -131,7 +134,7 @@ public class AuthorizationInterceptor {
|
|||
final CcmObject object = (CcmObject) parameter;
|
||||
|
||||
String requiredPrivilege = null;
|
||||
for (Annotation annotation : annotations) {
|
||||
for (final Annotation annotation : annotations) {
|
||||
if (annotation instanceof RequiresPrivilege) {
|
||||
requiredPrivilege = ((RequiresPrivilege) annotation).value();
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -39,16 +39,19 @@ import javax.enterprise.inject.spi.BeanManager;
|
|||
import javax.enterprise.inject.spi.CDI;
|
||||
|
||||
/**
|
||||
* Implementation of the Shiro's {@link AuthorizingRealm} to provide Shiro with
|
||||
* the users, groups, roles and permissions stored in CCM's database.
|
||||
* Implementation of Shiro's {@link AuthorizingRealm} to provide Shiro with the
|
||||
* users, groups, roles and permissions stored in CCM's database.
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
@SuppressWarnings({"PMD.CyclomaticComplexity",
|
||||
"PMD.ModifiedCyclomaticComplexity",
|
||||
"PMD.StdCyclomaticComplexity"})
|
||||
public class CcmShiroRealm extends AuthorizingRealm {
|
||||
|
||||
@Override
|
||||
protected AuthorizationInfo doGetAuthorizationInfo(
|
||||
final PrincipalCollection principals) {
|
||||
final PrincipalCollection principals) {
|
||||
|
||||
// Get the pricipal (object identifing the user).
|
||||
final Object principal = principals.getPrimaryPrincipal();
|
||||
|
|
@ -56,9 +59,9 @@ public class CcmShiroRealm extends AuthorizingRealm {
|
|||
// This realm expects the principal to be a string.
|
||||
if (!(principal instanceof String)) {
|
||||
throw new AuthenticationException(String.format(
|
||||
"Can' process principal of "
|
||||
+ "type \"%s\".",
|
||||
principal.getClass().getName()));
|
||||
"Can' process principal of "
|
||||
+ "type \"%s\".",
|
||||
principal.getClass().getName()));
|
||||
}
|
||||
// Convert the pricipal to a string.
|
||||
final String userIdentifier = (String) principal;
|
||||
|
|
@ -70,30 +73,31 @@ public class CcmShiroRealm extends AuthorizingRealm {
|
|||
final RoleRepository roleRepository;
|
||||
final BeanManager beanManager = CDI.current().getBeanManager();
|
||||
final Set<Bean<?>> beans = beanManager.
|
||||
getBeans(RoleRepository.class);
|
||||
getBeans(RoleRepository.class);
|
||||
final Iterator<Bean<?>> iterator = beans.iterator();
|
||||
if (iterator.hasNext()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Bean<RoleRepository> bean = (Bean<RoleRepository>) iterator.
|
||||
next();
|
||||
final Bean<RoleRepository> bean
|
||||
= (Bean<RoleRepository>) iterator.
|
||||
next();
|
||||
final CreationalContext<RoleRepository> ctx = beanManager.
|
||||
createCreationalContext(bean);
|
||||
createCreationalContext(bean);
|
||||
|
||||
roleRepository = (RoleRepository) beanManager.getReference(
|
||||
bean, RoleRepository.class, ctx);
|
||||
bean, RoleRepository.class, ctx);
|
||||
} else {
|
||||
throw new AuthenticationException(
|
||||
"Failed to retrieve RoleRepository");
|
||||
"Failed to retrieve RoleRepository");
|
||||
}
|
||||
|
||||
|
||||
final List<Role> roles = roleRepository.findAll();
|
||||
|
||||
|
||||
final SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
|
||||
for(final Role role : roles) {
|
||||
for (final Role role : roles) {
|
||||
info.addRole(role.getName());
|
||||
}
|
||||
info.addStringPermission("*");
|
||||
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
|
|
@ -110,7 +114,7 @@ public class CcmShiroRealm extends AuthorizingRealm {
|
|||
|
||||
// Add the permissions assigned to the role to the AuthorizatonInfo.
|
||||
for (final Permission permission : roleMembership.getRole()
|
||||
.getPermissions()) {
|
||||
.getPermissions()) {
|
||||
info.addStringPermission(permissionToString(permission));
|
||||
}
|
||||
}
|
||||
|
|
@ -119,13 +123,13 @@ public class CcmShiroRealm extends AuthorizingRealm {
|
|||
for (final GroupMembership membership : user.getGroupMemberships()) {
|
||||
// Get the roles assigned to the group
|
||||
for (final RoleMembership roleMembership : membership.getGroup()
|
||||
.getRoleMemberships()) {
|
||||
.getRoleMemberships()) {
|
||||
// Add the role to the AuthorizationInfo
|
||||
info.addRole(roleMembership.getRole().getName());
|
||||
// Add the permissions assigned to the role to the
|
||||
// AuthorizationInfo
|
||||
for (final Permission permission : roleMembership.getRole()
|
||||
.getPermissions()) {
|
||||
.getPermissions()) {
|
||||
info.addStringPermission(permissionToString(permission));
|
||||
}
|
||||
}
|
||||
|
|
@ -136,8 +140,8 @@ public class CcmShiroRealm extends AuthorizingRealm {
|
|||
|
||||
@Override
|
||||
protected AuthenticationInfo doGetAuthenticationInfo(
|
||||
final AuthenticationToken token)
|
||||
throws AuthenticationException {
|
||||
final AuthenticationToken token)
|
||||
throws AuthenticationException {
|
||||
|
||||
// Get the pricipal identifing the user
|
||||
final Object principal = token.getPrincipal();
|
||||
|
|
@ -145,9 +149,9 @@ public class CcmShiroRealm extends AuthorizingRealm {
|
|||
// This realm expects the pricipal to be a string
|
||||
if (!(principal instanceof String)) {
|
||||
throw new AuthenticationException(String.format(
|
||||
"Can' process authentication token with a principal of "
|
||||
+ "type \"%s\".",
|
||||
principal.getClass().getName()));
|
||||
"Can' process authentication token with a principal of "
|
||||
+ "type \"%s\".",
|
||||
principal.getClass().getName()));
|
||||
}
|
||||
|
||||
// Convert the pricipal to a string.
|
||||
|
|
@ -168,9 +172,11 @@ public class CcmShiroRealm extends AuthorizingRealm {
|
|||
* address of the user.
|
||||
*
|
||||
* @param userIdentifier The identifier of the user.
|
||||
*
|
||||
* @return The User identified by the provided {@code userIdentifier}.
|
||||
*
|
||||
* @throws AuthenticationException if no user for the provided identifier
|
||||
* could be retrieved.
|
||||
* could be retrieved.
|
||||
*/
|
||||
private User findUser(final String userIdentifier) {
|
||||
// For some reason we can't use the the CdiUtil class here, therefore
|
||||
|
|
@ -178,20 +184,20 @@ public class CcmShiroRealm extends AuthorizingRealm {
|
|||
final UserRepository userRepository;
|
||||
final BeanManager beanManager = CDI.current().getBeanManager();
|
||||
final Set<Bean<?>> beans = beanManager.getBeans(
|
||||
UserRepository.class);
|
||||
UserRepository.class);
|
||||
final Iterator<Bean<?>> iterator = beans.iterator();
|
||||
if (iterator.hasNext()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Bean<UserRepository> bean = (Bean<UserRepository>) iterator
|
||||
.next();
|
||||
.next();
|
||||
final CreationalContext<UserRepository> ctx = beanManager
|
||||
.createCreationalContext(bean);
|
||||
.createCreationalContext(bean);
|
||||
|
||||
userRepository = (UserRepository) beanManager.getReference(
|
||||
bean, UserRepository.class, ctx);
|
||||
bean, UserRepository.class, ctx);
|
||||
} else {
|
||||
throw new AuthenticationException(
|
||||
"Failed to retrieve UserRepository.");
|
||||
"Failed to retrieve UserRepository.");
|
||||
}
|
||||
|
||||
// Depending of the configuration of CCM use the appropriate method
|
||||
|
|
@ -207,9 +213,9 @@ public class CcmShiroRealm extends AuthorizingRealm {
|
|||
// If no matching user is found throw an AuthenticationException
|
||||
if (user == null) {
|
||||
throw new AuthenticationException(String.format(
|
||||
"No user identified by principal \"%s\" was found. Primary user "
|
||||
+ "identifier is \"%s\".",
|
||||
userIdentifier, config.getPrimaryUserIdentifier()));
|
||||
"No user identified by principal \"%s\" was found. Primary user "
|
||||
+ "identifier is \"%s\".",
|
||||
userIdentifier, config.getPrimaryUserIdentifier()));
|
||||
}
|
||||
|
||||
return user;
|
||||
|
|
@ -220,6 +226,7 @@ public class CcmShiroRealm extends AuthorizingRealm {
|
|||
* used by Shiro.
|
||||
*
|
||||
* @param permission The permission to convert.
|
||||
*
|
||||
* @return A Shiro permission string.
|
||||
*/
|
||||
private String permissionToString(final Permission permission) {
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ import javax.xml.bind.annotation.XmlElementWrapper;
|
|||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* A group is bascially a collection of users.
|
||||
* A group is basically a collection of users.
|
||||
*
|
||||
* Group extends the {@link Party} class. Therefore {@link Role}s can be
|
||||
* assigned to a group. When a {@link Role} is assigned to a group each member
|
||||
|
|
@ -113,6 +113,14 @@ public class Group extends Party implements Serializable {
|
|||
return obj instanceof Group;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("PMD.UselessOverridingMethod")
|
||||
public int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String toString(final String data) {
|
||||
return super.toString(String.format(", members = { %s }%s",
|
||||
|
|
|
|||
|
|
@ -21,7 +21,13 @@ package org.libreccm.security;
|
|||
import org.libreccm.core.CcmObject;
|
||||
|
||||
/**
|
||||
*
|
||||
* Subclasses of {@link CcmObject} can implement this interface to inherit
|
||||
* the permissions of their parent object. This annotation is processed by the
|
||||
* {@link PermissionChecker}.
|
||||
*
|
||||
* @see PermissionChecker#checkPermission(java.lang.String, org.libreccm.core.CcmObject)
|
||||
* @see PermissionChecker#isPermitted(java.lang.String, org.libreccm.core.CcmObject)
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
public interface InheritsPermissions {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ import javax.xml.bind.annotation.XmlElement;
|
|||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* A permission grants a privilege on an object or systemwide to {@link Role}.
|
||||
* A permission grants a privilege on an object or system wide to {@link Role}.
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -37,8 +37,11 @@ import javax.enterprise.context.RequestScoped;
|
|||
@RequestScoped
|
||||
public class PermissionManager {
|
||||
|
||||
@SuppressWarnings("PMD.LongVariable")
|
||||
private static final String QUERY_PARAM_OBJECT = "object";
|
||||
@SuppressWarnings("PMD.LongVariable")
|
||||
private static final String QUERY_PARAM_GRANTEE = "grantee";
|
||||
@SuppressWarnings("PMD.LongVariable")
|
||||
private static final String QUERY_PARAM_PRIVILEGE = "privilege";
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@ package org.libreccm.security;
|
|||
|
||||
import com.arsdigita.util.UncheckedWrapperException;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.libreccm.cdi.utils.CdiLookupException;
|
||||
import org.libreccm.cdi.utils.CdiUtil;
|
||||
import org.libreccm.core.CcmObject;
|
||||
|
|
@ -30,24 +28,59 @@ import java.util.Collection;
|
|||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* A decorator for collections which checks if the current user is permitted to
|
||||
* access the objects in the collection before returning them.
|
||||
*
|
||||
* This implementation of the {@link Collection} interface decorates a given
|
||||
* collection. The methods which manipulate the collection are simply calling
|
||||
* the methods of decorated collection. The methods which retrieve objects from
|
||||
* the collection are first calling the method of the decorated collection, and
|
||||
* check if the current subject is permitted to access the object. If the
|
||||
* current subject is permitted to access the object the object is returned.
|
||||
* Otherwise the object is replaced with a virtual object were the
|
||||
* {@link CcmObject#displayName} property is set to {@code Access Denied}.
|
||||
* Methods which return arrays or collections of objects from the decorated
|
||||
* collection check each object in the array or collection and replace the
|
||||
* objects which the current subject is not permitted to access with a
|
||||
* <em>Access denied</em> object.
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*
|
||||
* @param <E>
|
||||
* @param <E> Type of the objects in the collection. Must extend
|
||||
* {@link CcmObject}.
|
||||
*/
|
||||
@SuppressWarnings("PMD.TooManyMethods")
|
||||
public class SecuredCollection<E extends CcmObject> implements Collection<E> {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(
|
||||
SecuredCollection.class);
|
||||
|
||||
/**
|
||||
* The decorated collection.
|
||||
*/
|
||||
private final Collection<E> collection;
|
||||
|
||||
/**
|
||||
* The class of the objects in the collection. Required for creating the
|
||||
* virtual <em>Access denied</em> object
|
||||
*/
|
||||
private final Class<E> clazz;
|
||||
|
||||
/**
|
||||
* The privilege required for accessing the objects in the collection.
|
||||
*/
|
||||
private final String requiredPrivilege;
|
||||
|
||||
|
||||
/**
|
||||
* Helper class for creating the <em>Access denied</em> object.
|
||||
*/
|
||||
private final SecuredHelper<E> securedHelper;
|
||||
|
||||
/**
|
||||
* Create a new secured collection for the provided collection.
|
||||
*
|
||||
* @param collection The collection to secure.
|
||||
* @param clazz The class of the objects in the collection.
|
||||
* @param requiredPrivilege The privilege required to access the objects
|
||||
* in the collection.
|
||||
*/
|
||||
public SecuredCollection(final Collection<E> collection,
|
||||
final Class<E> clazz,
|
||||
final String requiredPrivilege) {
|
||||
|
|
@ -74,7 +107,8 @@ public class SecuredCollection<E extends CcmObject> implements Collection<E> {
|
|||
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
return new SecuredIterator<>(collection.iterator(), clazz, requiredPrivilege);
|
||||
return new SecuredIterator<>(collection.iterator(), clazz,
|
||||
requiredPrivilege);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -91,16 +125,17 @@ public class SecuredCollection<E extends CcmObject> implements Collection<E> {
|
|||
|
||||
final Object[] objects = collection.toArray();
|
||||
for (int i = 0; i < objects.length; i++) {
|
||||
if (!permissionChecker.isPermitted(requiredPrivilege, (E) objects[i])) {
|
||||
if (!permissionChecker
|
||||
.isPermitted(requiredPrivilege, (E) objects[i])) {
|
||||
objects[i] = securedHelper.generateAccessDeniedObject();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return objects;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({"unchecked", "PMD.UseVarargs"})
|
||||
public <T> T[] toArray(final T[] array) {
|
||||
final PermissionChecker permissionChecker;
|
||||
final CdiUtil cdiUtil = new CdiUtil();
|
||||
|
|
@ -110,10 +145,11 @@ public class SecuredCollection<E extends CcmObject> implements Collection<E> {
|
|||
} catch (CdiLookupException ex) {
|
||||
throw new UncheckedWrapperException(ex);
|
||||
}
|
||||
|
||||
|
||||
final T[] objects = collection.toArray(array);
|
||||
for(int i = 0; i < objects.length; i++) {
|
||||
if (!permissionChecker.isPermitted(requiredPrivilege, (CcmObject) objects[i])) {
|
||||
for (int i = 0; i < objects.length; i++) {
|
||||
if (!permissionChecker.isPermitted(requiredPrivilege,
|
||||
(CcmObject) objects[i])) {
|
||||
objects[i] = (T) securedHelper.generateAccessDeniedObject();
|
||||
}
|
||||
}
|
||||
|
|
@ -156,18 +192,4 @@ public class SecuredCollection<E extends CcmObject> implements Collection<E> {
|
|||
collection.clear();
|
||||
}
|
||||
|
||||
// private E generateAccessDeniedObject(final Class<E> clazz) {
|
||||
// final E placeholder;
|
||||
// try {
|
||||
// placeholder = clazz.newInstance();
|
||||
// placeholder.setDisplayName("Access denied");
|
||||
//
|
||||
// return placeholder;
|
||||
// } catch (InstantiationException | IllegalAccessException ex) {
|
||||
// LOGGER.error(
|
||||
// "Failed to create placeholder object. Returing null.", ex);
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,16 +23,39 @@ import org.libreccm.core.CcmObject;
|
|||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* A decorator for {@link Map.Entry} which checks if the current subject is
|
||||
* permitted to access the value before returning it. If the current subject
|
||||
* is not permitted to access the value it is replaced with an virtual
|
||||
* <em>Access Denied</em> which is an object of the same class as the value.
|
||||
*
|
||||
* This class is not intended for direct use and is therefore only accessible
|
||||
* from the {@code org.libreccm.security} package. The class is used by the
|
||||
* {@link SecuredMap}.
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
* @param <K>
|
||||
* @param <V>
|
||||
* @param <K> The type of the key of the entry.
|
||||
* @param <V> The type of the value of the entry.
|
||||
*/
|
||||
class SecuredEntry<K, V extends CcmObject> implements Map.Entry<K, V> {
|
||||
|
||||
/**
|
||||
* The decorated entry.
|
||||
*/
|
||||
private final Map.Entry<K, V> entry;
|
||||
/**
|
||||
* {@link SecuredHelper} for creating the virtual <em>Access denied</em>
|
||||
* object. Provided by the {@link SecuredMap} which creates the
|
||||
* {@code SecuredEntry}.
|
||||
*/
|
||||
private final SecuredHelper<V> securedHelper;
|
||||
|
||||
/**
|
||||
* Creates a new secured entry.
|
||||
*
|
||||
* @param entry The entry to secure.
|
||||
* @param securedHelper The {@link SecuredHelper} for creating the
|
||||
* virtual <em>Access denied</em> object.
|
||||
*/
|
||||
public SecuredEntry(final Map.Entry<K, V> entry,
|
||||
final SecuredHelper<V> securedHelper) {
|
||||
this.entry = entry;
|
||||
|
|
|
|||
|
|
@ -24,15 +24,31 @@ import java.util.Iterator;
|
|||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A decorator for an iterator of {@link Map.Entry} objects which returns
|
||||
* {@link SecuredEntry} objects. Used by the {@link SecuredMap}.
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
class SecuredEntryIterator<E extends Map.Entry<K, V>, K, V extends CcmObject>
|
||||
implements Iterator<E> {
|
||||
|
||||
/**
|
||||
* The decorated iterator.
|
||||
*/
|
||||
private final Iterator<E> iterator;
|
||||
/**
|
||||
* The {@link SecuredHelper} for creating the virtual <em>Access denied</em>
|
||||
* object. Provided by the {@link SecuredMap} creating the iterator.
|
||||
*/
|
||||
private final SecuredHelper<V> securedHelper;
|
||||
|
||||
/**
|
||||
* Creates a new secured iterator for entries.
|
||||
*
|
||||
* @param iterator The iterator to secure.
|
||||
* @param securedHelper The {@link SecuredHelper} for creating the virtual
|
||||
* <em>Access denied</em> object.
|
||||
*/
|
||||
public SecuredEntryIterator(final Iterator<E> iterator,
|
||||
final SecuredHelper<V> securedHelper) {
|
||||
this.iterator = iterator;
|
||||
|
|
|
|||
|
|
@ -30,126 +30,146 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A decorator for a set of {@link Map.Entry} objects which returns
|
||||
* {@link SecuredEntry} instances. Used by the {@link SecuredMap}.
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
class SecuredEntrySet<E extends Map.Entry<K, V>, K, V extends CcmObject>
|
||||
@SuppressWarnings("PMD.TooManyMethods")
|
||||
class SecuredEntrySet<E extends Map.Entry<K, V>, K, V extends CcmObject>
|
||||
implements Set<E> {
|
||||
|
||||
private final Set<E> set;
|
||||
private final String requiredPrivilege;
|
||||
private final SecuredHelper<V> securedHelper;
|
||||
|
||||
public SecuredEntrySet(final Set<E> set,
|
||||
final String requiredPrivilege,
|
||||
final SecuredHelper<V> securedHelper) {
|
||||
this.set = set;
|
||||
this.requiredPrivilege = requiredPrivilege;
|
||||
this.securedHelper = securedHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return set.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return set.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(final Object object) {
|
||||
return set.contains(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
return new SecuredEntryIterator<>(set.iterator(), securedHelper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object[] toArray() {
|
||||
final PermissionChecker permissionChecker;
|
||||
final CdiUtil cdiUtil = new CdiUtil();
|
||||
try {
|
||||
permissionChecker = cdiUtil.findBean(
|
||||
PermissionChecker.class);
|
||||
} catch (CdiLookupException ex) {
|
||||
throw new UncheckedWrapperException(ex);
|
||||
}
|
||||
|
||||
final Object[] entries = set.toArray();
|
||||
for (int i = 0; i < entries.length; i++) {
|
||||
final E entry = (E) entries[i];
|
||||
if (!permissionChecker.isPermitted(requiredPrivilege,
|
||||
entry.getValue())) {
|
||||
entries[i] = securedHelper.generateAccessDeniedObject();
|
||||
}
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T[] toArray(final T[] array) {
|
||||
final PermissionChecker permissionChecker;
|
||||
final CdiUtil cdiUtil = new CdiUtil();
|
||||
try {
|
||||
permissionChecker = cdiUtil.findBean(
|
||||
PermissionChecker.class);
|
||||
} catch (CdiLookupException ex) {
|
||||
throw new UncheckedWrapperException(ex);
|
||||
}
|
||||
|
||||
final E[] entries = (E[]) set.toArray(array);
|
||||
for (int i = 0; i < entries.length; i++) {
|
||||
if (!permissionChecker.isPermitted(requiredPrivilege,
|
||||
entries[i].getValue())) {
|
||||
entries[i] = (E) securedHelper.generateAccessDeniedObject();
|
||||
}
|
||||
}
|
||||
|
||||
return (T[]) entries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(final E element) {
|
||||
return set.add(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(final Object object) {
|
||||
return set.remove(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(final Collection<?> collection) {
|
||||
return set.containsAll(collection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(final Collection<? extends E> collection) {
|
||||
return set.addAll(collection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(final Collection<?> collection) {
|
||||
return set.retainAll(collection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(final Collection<?> collection) {
|
||||
return set.removeAll(collection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
set.clear();
|
||||
}
|
||||
/**
|
||||
* The decorated set.
|
||||
*/
|
||||
private final Set<E> set;
|
||||
/**
|
||||
* The privilege required to access the values of the entries in the set.
|
||||
*/
|
||||
private final String requiredPrivilege;
|
||||
/**
|
||||
* {@link SecuredHelper} for creating the virtual <em>Access denied</em>
|
||||
* object.
|
||||
*/
|
||||
private final SecuredHelper<V> securedHelper;
|
||||
|
||||
/**
|
||||
* Creates a new secured entry set.
|
||||
*
|
||||
* @param set The set of entries to secure.
|
||||
* @param requiredPrivilege The privilege required to access the values of
|
||||
* the entries.
|
||||
* @param securedHelper The {@link SecuredHelper} for creating the
|
||||
* virtual <em>Access denied</em> objects.
|
||||
*/
|
||||
public SecuredEntrySet(final Set<E> set,
|
||||
final String requiredPrivilege,
|
||||
final SecuredHelper<V> securedHelper) {
|
||||
this.set = set;
|
||||
this.requiredPrivilege = requiredPrivilege;
|
||||
this.securedHelper = securedHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return set.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return set.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(final Object object) {
|
||||
return set.contains(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
return new SecuredEntryIterator<>(set.iterator(), securedHelper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object[] toArray() {
|
||||
final PermissionChecker permissionChecker;
|
||||
final CdiUtil cdiUtil = new CdiUtil();
|
||||
try {
|
||||
permissionChecker = cdiUtil.findBean(
|
||||
PermissionChecker.class);
|
||||
} catch (CdiLookupException ex) {
|
||||
throw new UncheckedWrapperException(ex);
|
||||
}
|
||||
|
||||
final Object[] entries = set.toArray();
|
||||
for (int i = 0; i < entries.length; i++) {
|
||||
final E entry = (E) entries[i];
|
||||
if (!permissionChecker.isPermitted(requiredPrivilege,
|
||||
entry.getValue())) {
|
||||
entries[i] = securedHelper.generateAccessDeniedObject();
|
||||
}
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "PMD.UseVarargs"})
|
||||
public <T> T[] toArray(final T[] array) {
|
||||
final PermissionChecker permissionChecker;
|
||||
final CdiUtil cdiUtil = new CdiUtil();
|
||||
try {
|
||||
permissionChecker = cdiUtil.findBean(
|
||||
PermissionChecker.class);
|
||||
} catch (CdiLookupException ex) {
|
||||
throw new UncheckedWrapperException(ex);
|
||||
}
|
||||
|
||||
final E[] entries = (E[]) set.toArray(array);
|
||||
for (int i = 0; i < entries.length; i++) {
|
||||
if (!permissionChecker.isPermitted(requiredPrivilege,
|
||||
entries[i].getValue())) {
|
||||
entries[i] = (E) securedHelper.generateAccessDeniedObject();
|
||||
}
|
||||
}
|
||||
|
||||
return (T[]) entries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(final E element) {
|
||||
return set.add(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(final Object object) {
|
||||
return set.remove(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(final Collection<?> collection) {
|
||||
return set.containsAll(collection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(final Collection<? extends E> collection) {
|
||||
return set.addAll(collection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(final Collection<?> collection) {
|
||||
return set.retainAll(collection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(final Collection<?> collection) {
|
||||
return set.removeAll(collection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
set.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,13 @@ class SecuredHelper<E extends CcmObject> {
|
|||
private final static Logger LOGGER = LogManager.getLogger(
|
||||
SecuredHelper.class);
|
||||
|
||||
/**
|
||||
* Class of the objects in the collection.
|
||||
*/
|
||||
private final Class<E> clazz;
|
||||
/**
|
||||
* Privilege required to access the objects in the collection.
|
||||
*/
|
||||
private final String requiredPrivilege;
|
||||
|
||||
protected SecuredHelper(final Class<E> clazz,
|
||||
|
|
@ -51,8 +57,8 @@ class SecuredHelper<E extends CcmObject> {
|
|||
* @param object The object to check.
|
||||
* @return The provided {@code object} if the current subject has the
|
||||
* permission to access it with the provided {@code privilege}. Otherwise a
|
||||
* placeholder object is returned whichs {@link CcmObject#displayName}
|
||||
* property is set to {@code Access denied}.
|
||||
* placeholder object is returned. The {@link CcmObject#displayName}
|
||||
* property of these object is set to {@code Access denied}.
|
||||
*/
|
||||
protected E canAccess(final E object) {
|
||||
if (object == null) {
|
||||
|
|
@ -76,7 +82,7 @@ class SecuredHelper<E extends CcmObject> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Helper method for creating an "Access denied" placeholder object.
|
||||
* Helper method for creating an <em>Access denied</em> placeholder object.
|
||||
*
|
||||
* @return An object of the provided {@link #clazz} with it's
|
||||
* {@link CcmObject#displayName} property set to {@code Access denied}.
|
||||
|
|
|
|||
|
|
@ -18,12 +18,6 @@
|
|||
*/
|
||||
package org.libreccm.security;
|
||||
|
||||
import com.arsdigita.util.UncheckedWrapperException;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.libreccm.cdi.utils.CdiLookupException;
|
||||
import org.libreccm.cdi.utils.CdiUtil;
|
||||
import org.libreccm.core.CcmObject;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
|
|
|||
|
|
@ -24,19 +24,43 @@ import java.util.ListIterator;
|
|||
import org.libreccm.core.CcmObject;
|
||||
|
||||
/**
|
||||
* A decorator for {@link List}s of {@link CcmObject}s which checks if the
|
||||
* current subject is permitted to access the objects in the list before
|
||||
* returning them.
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
* @param <E>
|
||||
*
|
||||
* @param <E> The type of the objects in the list.
|
||||
*/
|
||||
public class SecuredList<E extends CcmObject>
|
||||
extends SecuredCollection<E>
|
||||
implements List<E> {
|
||||
extends SecuredCollection<E>
|
||||
implements List<E> {
|
||||
|
||||
/**
|
||||
* The decorated list.
|
||||
*/
|
||||
private final List<E> list;
|
||||
/**
|
||||
* The class of the objects in the list.
|
||||
*/
|
||||
private final Class<E> clazz;
|
||||
/**
|
||||
* The privilege required to access the objects in the list.
|
||||
*/
|
||||
private final String requiredPrivilege;
|
||||
/**
|
||||
* {@link SecuredHelper} used by the list.
|
||||
*/
|
||||
private final SecuredHelper<E> securedHelper;
|
||||
|
||||
/**
|
||||
* Creates a new secured list.
|
||||
*
|
||||
* @param list The {@link List} to secure.
|
||||
* @param clazz Class of the objects in the list.
|
||||
* @param requiredPrivilege The privilege required to access the objects in
|
||||
* the list.
|
||||
*/
|
||||
public SecuredList(final List<E> list,
|
||||
final Class<E> clazz,
|
||||
final String requiredPrivilege) {
|
||||
|
|
|
|||
|
|
@ -19,25 +19,38 @@
|
|||
package org.libreccm.security;
|
||||
|
||||
import java.util.ListIterator;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import org.libreccm.core.CcmObject;
|
||||
|
||||
/**
|
||||
* A decorator for {@link ListIterator} which checks if the current subject is
|
||||
* permitted to access an object from the list the iterator iterates over before
|
||||
* returning it.
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
* @param <E>
|
||||
*/
|
||||
public class SecuredListIterator<E extends CcmObject>
|
||||
extends SecuredIterator<E>
|
||||
implements ListIterator<E> {
|
||||
|
||||
private final static Logger LOGGER = LogManager.getLogger(
|
||||
SecuredListIterator.class);
|
||||
extends SecuredIterator<E>
|
||||
implements ListIterator<E> {
|
||||
|
||||
/**
|
||||
* The decorated {@link ListIterator}.
|
||||
*/
|
||||
private final ListIterator<E> iterator;
|
||||
/**
|
||||
* {@link SecuredHelper} used by this iterator.
|
||||
*/
|
||||
private final SecuredHelper<E> securedHelper;
|
||||
|
||||
/**
|
||||
* Creates a new secured list iterator.
|
||||
*
|
||||
* @param iterator The iterator to secure.
|
||||
* @param clazz The class of the objects in the list.
|
||||
* @param requiredPrivilege The privilege required to access the objects in
|
||||
* list.
|
||||
*/
|
||||
public SecuredListIterator(final ListIterator<E> iterator,
|
||||
final Class<E> clazz,
|
||||
final String requiredPrivilege) {
|
||||
|
|
|
|||
|
|
@ -18,30 +18,49 @@
|
|||
*/
|
||||
package org.libreccm.security;
|
||||
|
||||
import com.arsdigita.util.UncheckedWrapperException;
|
||||
|
||||
import org.libreccm.cdi.utils.CdiLookupException;
|
||||
import org.libreccm.cdi.utils.CdiUtil;
|
||||
import org.libreccm.core.CcmObject;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Decorator for {@link Map} which checks if the current subject is permitted to
|
||||
* access the values of the decorated map before returning them. The keys used
|
||||
* by the map are not checked.
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
* @param <K>
|
||||
* @param <V>
|
||||
*
|
||||
* @param <K> Type of the keys
|
||||
* @param <V> Type of the values.
|
||||
*/
|
||||
public class SecuredMap<K, V extends CcmObject> implements Map<K, V> {
|
||||
|
||||
/**
|
||||
* The decorated map.
|
||||
*/
|
||||
private final Map<K, V> map;
|
||||
/**
|
||||
* Class of the values in map.
|
||||
*/
|
||||
private final Class<V> clazz;
|
||||
/**
|
||||
* The privilege required to access the values of the map.
|
||||
*/
|
||||
private final String requiredPrivilege;
|
||||
/**
|
||||
* {@link SecuredHelper} used by the map.
|
||||
*/
|
||||
private final SecuredHelper<V> securedHelper;
|
||||
|
||||
/**
|
||||
* Creates a new secured map.
|
||||
*
|
||||
* @param map The map to secure.
|
||||
* @param clazz Class of the values in the map.
|
||||
* @param requiredPrivilege The privilege required to access the values of
|
||||
* the map.
|
||||
*/
|
||||
public SecuredMap(final Map<K, V> map,
|
||||
final Class<V> clazz,
|
||||
final String requiredPrivilege) {
|
||||
|
|
|
|||
|
|
@ -24,20 +24,44 @@ import java.util.NavigableMap;
|
|||
import java.util.NavigableSet;
|
||||
|
||||
/**
|
||||
*
|
||||
* A decorator for {@link NavigableMap} which checks if the current subject is
|
||||
* permitted to access the values of the decorated map before returning them.
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
* @param <K>
|
||||
* @param <V>
|
||||
*
|
||||
* @param <K> Type of the keys.
|
||||
* @param <V> Type of the values.
|
||||
*/
|
||||
@SuppressWarnings("PMD.TooManyMethods")
|
||||
public class SecuredNavigableMap<K, V extends CcmObject>
|
||||
extends SecuredSortedMap<K, V>
|
||||
implements NavigableMap<K, V> {
|
||||
|
||||
/**
|
||||
* The decorated navigable map.
|
||||
*/
|
||||
private final NavigableMap<K, V> navigableMap;
|
||||
/**
|
||||
* Class of the values.
|
||||
*/
|
||||
private final Class<V> clazz;
|
||||
/**
|
||||
* The privilege required to access the values of the decorated map.
|
||||
*/
|
||||
private final String requiredPrivilege;
|
||||
/**
|
||||
* {@link SecuredHelper} used by the decorator.
|
||||
*/
|
||||
private final SecuredHelper<V> securedHelper;
|
||||
|
||||
/**
|
||||
* Creates a new secured navigable map.
|
||||
*
|
||||
* @param navigableMap The navigable map to secure.
|
||||
* @param clazz The class of the values of the navigable map.
|
||||
* @param requiredPrivilege The privilege required to access the objects of
|
||||
* the navigable map.
|
||||
*/
|
||||
public SecuredNavigableMap(final NavigableMap<K, V> navigableMap,
|
||||
final Class<V> clazz,
|
||||
final String requiredPrivilege) {
|
||||
|
|
|
|||
|
|
@ -23,19 +23,44 @@ import java.util.NavigableSet;
|
|||
import org.libreccm.core.CcmObject;
|
||||
|
||||
/**
|
||||
* A decorated for {@link NavigableSet} which checks if the current subject is
|
||||
* permitted to access the objects from the decorated navigable set before
|
||||
* returning them.
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
* @param <E>
|
||||
*
|
||||
* @param <E> Type of the objects in the navigable set.
|
||||
*/
|
||||
@SuppressWarnings("PMD.TooManyMethods")
|
||||
public class SecuredNavigableSet<E extends CcmObject>
|
||||
extends SecuredSortedSet<E>
|
||||
implements NavigableSet<E> {
|
||||
extends SecuredSortedSet<E>
|
||||
implements NavigableSet<E> {
|
||||
|
||||
/**
|
||||
* The decorated navigable set.
|
||||
*/
|
||||
private final NavigableSet<E> set;
|
||||
/**
|
||||
* Class of the objects in the navigable set.
|
||||
*/
|
||||
private final Class<E> clazz;
|
||||
/**
|
||||
* The privilege required to access the objects of the navigable set.
|
||||
*/
|
||||
private final String requiredPrivilege;
|
||||
/**
|
||||
* {@link SecuredHelper} used by this decorator.
|
||||
*/
|
||||
private final SecuredHelper<E> securedHelper;
|
||||
|
||||
/**
|
||||
* Creates a new secured navigable set.
|
||||
*
|
||||
* @param set The set to secure.
|
||||
* @param clazz Class of the objects in the set.
|
||||
* @param requiredPrivilege The privilege required to access the objects in
|
||||
* the set.
|
||||
*/
|
||||
public SecuredNavigableSet(final NavigableSet<E> set,
|
||||
final Class<E> clazz,
|
||||
final String requiredPrivilege) {
|
||||
|
|
|
|||
|
|
@ -22,15 +22,26 @@ import java.util.Set;
|
|||
import org.libreccm.core.CcmObject;
|
||||
|
||||
/**
|
||||
* A decorator for {@link Set} which checks if the current subject is permitted
|
||||
* to access the objects from the decorated set before returning them.
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
* @param <E>
|
||||
*
|
||||
* @param <E> Type of the objects in the set.
|
||||
*/
|
||||
public class SecuredSet<E extends CcmObject>
|
||||
extends SecuredCollection<E>
|
||||
implements Set<E> {
|
||||
extends SecuredCollection<E>
|
||||
implements Set<E> {
|
||||
|
||||
public SecuredSet(final Set<E> set,
|
||||
/**
|
||||
* Creates a new secured set.
|
||||
*
|
||||
* @param set The {@link Set} to secure.
|
||||
* @param clazz Class of the objects in the set.
|
||||
* @param requiredPrivilege Privilege required to access the objects in the
|
||||
* set.
|
||||
*/
|
||||
public SecuredSet(final Set<E> set,
|
||||
final Class<E> clazz,
|
||||
final String requiredPrivilege) {
|
||||
super(set, clazz, requiredPrivilege);
|
||||
|
|
|
|||
|
|
@ -24,19 +24,40 @@ import java.util.Comparator;
|
|||
import java.util.SortedMap;
|
||||
|
||||
/**
|
||||
* A decorator for {@link SortedMap} which checks if the current subject is
|
||||
* permitted to access the values from the decorated sorted map before returning
|
||||
* them.
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
* @param <K>
|
||||
* @param <V>
|
||||
*
|
||||
* @param <K> Type of the keys.
|
||||
* @param <V> Type of the values.
|
||||
*/
|
||||
public class SecuredSortedMap<K, V extends CcmObject>
|
||||
extends SecuredMap<K, V>
|
||||
implements SortedMap<K, V> {
|
||||
|
||||
/**
|
||||
* The decorated sorted map.
|
||||
*/
|
||||
private final SortedMap<K, V> sortedMap;
|
||||
/**
|
||||
* Class of the values of the decorated sorted map.
|
||||
*/
|
||||
private final Class<V> clazz;
|
||||
/**
|
||||
* Privilege required to access the values of the decorated sorted map.
|
||||
*/
|
||||
private final String requiredPrivilege;
|
||||
|
||||
/**
|
||||
* Creates new secured sorted map.
|
||||
*
|
||||
* @param sortedMap The map to secure.
|
||||
* @param clazz Class of the values.
|
||||
* @param requiredPrivilege Privilege required to access the values of the
|
||||
* secured sorted map.
|
||||
*/
|
||||
public SecuredSortedMap(final SortedMap<K, V> sortedMap,
|
||||
final Class<V> clazz,
|
||||
final String requiredPrivilege) {
|
||||
|
|
|
|||
|
|
@ -19,24 +19,48 @@
|
|||
package org.libreccm.security;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
|
||||
import org.libreccm.core.CcmObject;
|
||||
|
||||
/**
|
||||
* Decorator for {@link SortedSet} which checks if the current subject is
|
||||
* permitted to access the objects from the decorated sorted set before
|
||||
* returning them.
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
* @param <E>
|
||||
*
|
||||
* @param <E> Type of the objects in the decorated sorted set.
|
||||
*/
|
||||
public class SecuredSortedSet<E extends CcmObject>
|
||||
extends SecuredSet<E>
|
||||
implements SortedSet<E> {
|
||||
extends SecuredSet<E>
|
||||
implements SortedSet<E> {
|
||||
|
||||
/**
|
||||
* The decorated sorted set.
|
||||
*/
|
||||
private final SortedSet<E> set;
|
||||
/**
|
||||
* The class of the objects in the decorated sorted set.
|
||||
*/
|
||||
private final Class<E> clazz;
|
||||
/**
|
||||
* The privilege required to access the objects in the decorated set.
|
||||
*/
|
||||
private final String requiredPrivilege;
|
||||
/**
|
||||
* {@link SecuredHelper} used by this decorator.
|
||||
*/
|
||||
private final SecuredHelper<E> securedHelper;
|
||||
|
||||
/**
|
||||
* Creates new secured sorted set.
|
||||
*
|
||||
* @param set The sorted set to secure.
|
||||
* @param clazz The class of the objects in the set.
|
||||
* @param requiredPrivilege The privilege required to access the objects in
|
||||
* the set.
|
||||
*/
|
||||
public SecuredSortedSet(final SortedSet<E> set,
|
||||
final Class<E> clazz,
|
||||
final String requiredPrivilege) {
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ import javax.xml.bind.annotation.XmlTransient;
|
|||
@XmlRootElement(name = "user", namespace = CORE_XML_NS)
|
||||
//Supressing a few warnings from PMD because they misleading here.
|
||||
//User is perfectly fine class name, and the complexity is not to high...
|
||||
@SuppressWarnings({"PMD.ShortClassName"})
|
||||
@SuppressWarnings({"PMD.ShortClassName", "PMD.LongVariable"})
|
||||
public class User extends Party implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 4035223413596611393L;
|
||||
|
|
@ -97,7 +97,6 @@ public class User extends Party implements Serializable {
|
|||
}))
|
||||
@NotNull
|
||||
@XmlElement(name = "primary-email-address", namespace = CORE_XML_NS)
|
||||
@SuppressWarnings("PMD.LongVariable")
|
||||
private EmailAddress primaryEmailAddress;
|
||||
|
||||
/**
|
||||
|
|
@ -136,7 +135,6 @@ public class User extends Party implements Serializable {
|
|||
*/
|
||||
@Column(name = "PASSWORD_RESET_REQUIRED")
|
||||
//Can't shorten the name without making the name cryptic.
|
||||
@SuppressWarnings("PMD.LongVariable")
|
||||
private boolean passwordResetRequired;
|
||||
|
||||
/**
|
||||
|
|
@ -216,7 +214,6 @@ public class User extends Party implements Serializable {
|
|||
return passwordResetRequired;
|
||||
}
|
||||
|
||||
@SuppressWarnings("PMD.LongVariable")
|
||||
protected void setPasswordResetRequired(final boolean passwordResetRequired) {
|
||||
this.passwordResetRequired = passwordResetRequired;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,27 +15,27 @@
|
|||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
*/
|
||||
/**
|
||||
* This package contains all classes dealing with authentication and
|
||||
* This package contains all classes dealing with authentication and
|
||||
* authorisation in LibreCCM.
|
||||
*
|
||||
*
|
||||
* Most of this classes are only relevant for the developers of the core part
|
||||
* of LibreCCM and and core administration UI. For developers of modules the
|
||||
* primary interface is the Apache Shiro Library. Module developers usually have
|
||||
* the use these classes only in the {@code CcmModule#install(InstallEvent)
|
||||
* method to create roles and privileges for their module. Therefore most
|
||||
* methods of these classes can only be invoked by the System user.
|
||||
*
|
||||
* the use these classes only in the <code>CcmModule#install(InstallEvent</code>
|
||||
* method to create roles and privileges for their module. Therefore most
|
||||
* methods of these classes can only be invoked by the System user.
|
||||
*
|
||||
* The check if the current user is logged in and/or has a certain permission
|
||||
* you have to obtain the current {@link Subject} from Shiro. In LibreCCM the
|
||||
* subject is provided using CDI. In classes eligible for injection you simply
|
||||
* inject the current subject. In other classes you can use the {@link CdiUtil}
|
||||
* class.
|
||||
*
|
||||
* Another option for method of CDI beans is to use the interceptors provided by
|
||||
* you have to obtain the current <code>Subject</code> from Shiro. In
|
||||
* LibreCCM the subject is provided using CDI. In classes eligible for injection
|
||||
* you simply inject the current subject. In other classes you can use the
|
||||
* <a href="../cdi/utils/CdiUtil.html">CdiUtil</a> class.
|
||||
*
|
||||
* Another option for method of CDI beans is to use the interceptors provided by
|
||||
* this package.
|
||||
*
|
||||
*
|
||||
* @see CcmModule
|
||||
*/
|
||||
package org.libreccm.security;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,97 @@
|
|||
--------------------------------------------
|
||||
Authentication and Authorisation in LibreCCM
|
||||
--------------------------------------------
|
||||
Jens Pelzetter
|
||||
--------------------------------------------
|
||||
2015-12-04
|
||||
--------------------------------------------
|
||||
|
||||
Authentication and Authorisation in LibreCCM
|
||||
|
||||
LibreCCM uses {{{http://shiro.apache.org}Apache Shiro}} as the foundation
|
||||
for its authentication and authorisation system. All classes related to
|
||||
authentication and authorisation are provided by the
|
||||
{{{ccm-core/apidocs/index.html?org/libreccm/security/package-summary.html}org.libreccm.security}}
|
||||
from the CCM Core module.
|
||||
|
||||
* Definitions
|
||||
|
||||
[User] A user is person (or a system) which accesses LibreCCM.
|
||||
|
||||
[Group] A collection of users. A user can be member of multiple groups.
|
||||
|
||||
[Role] A role is basically a collection of permissions and tasks (workflows)
|
||||
which can be assigned a user or group.
|
||||
|
||||
[Permission] Grants a certain privilege to a role. Permissions are either
|
||||
systemwide permissions or permissions granting a certain
|
||||
privilege on a certain CcmObject.
|
||||
|
||||
[Privilege] Describes an action.
|
||||
|
||||
* Managing permissions, roles, users and groups.
|
||||
|
||||
Permissions are granted and revoked using the
|
||||
{{{ccm-core/apidocs/index.html?org/libreccm/security/PermissionManager.html}PermissionManager}}
|
||||
class. This class is a CDI bean which can be injected or manually retrieved
|
||||
using the {{{ccm-core/apidocs/index.html?org/libreccm/cdi/utils/CdiUtil.html}CdiUtil}}
|
||||
utility.
|
||||
|
||||
Users, Groups and Roles are managed using the repository and manager classes
|
||||
provided by the {{{ccm-core/apidocs/index.html?org/libreccm/security/package-summary.html}org.libreccm.security}}
|
||||
package. Most module developers will not have to deal with these classes.
|
||||
Only if the module wants to create special roles it might be necessary
|
||||
for a module to use the {{{ccm-core/apidocs/index.html?org/libreccm/security/RoleManager.html}RoleManager}}
|
||||
or the {{{ccm-core/apidocs/index.html?org/libreccm/security/RoleRepository.html}RoleRepository}}.
|
||||
|
||||
* Validating permissions
|
||||
|
||||
Validating permissions can be done in various ways. For CDI enabled beans
|
||||
an Interceptor is provided for securing methods. Also a class for checking
|
||||
permissions is provided which can be injected using CDI or retrieved
|
||||
using {{{ccm-core/apidocs/index.html?org/libreccm/cdi/utils/CdiUtil.html}CdiUtil}}
|
||||
utility.
|
||||
|
||||
** Using the CDI interceptor
|
||||
|
||||
A method is secured by
|
||||
annotating the method with the <<<@AuthorizationRequired>>> annotation.
|
||||
Additional at least one of the annotations <<<@RequiresRole>>> and
|
||||
<<<@RequiresPrivilege>>> must be used.
|
||||
|
||||
The <<<@{{{ccm-core/apidocs/index.html?org/libreccm/security/RequiresRole.html}RequiresRole}}>>>
|
||||
annotation can only be used on method. If the current subject is not
|
||||
authenticated (not logged in) or does not have the role given by the
|
||||
annotation the interceptor will throw an <<<AuthorizationException>>>.
|
||||
|
||||
The <<<@{{{ccm-core/apidocs/index.html?org/libreccm/security/RequiresPrivilege.html}RequiresPrivilege}}>>>
|
||||
annotation can be used at the method or on a parameter of the type
|
||||
<<<CcmObject>>> of the secured method. If the annotation is put on a method
|
||||
the current subject must be authenticated and have a permission granting
|
||||
the user the given privilege.
|
||||
|
||||
If the annotation is used on a method parameter the current user must be
|
||||
authenticated and have a permission which grants the user the given
|
||||
privilege on the object with which the method is called.
|
||||
|
||||
If the current subject does have appropriate permissions an
|
||||
<<<AuthorizationException>>> is thrown.
|
||||
|
||||
Under the hood the interceptor uses the <<<PermissionChecker>>> class which
|
||||
is described in the next section.
|
||||
|
||||
** Using the <<<PermissionChecker>>>
|
||||
|
||||
An instance of the
|
||||
<<<@{{{ccm-core/apidocs/index.html?org/libreccm/security/PermissionChecker.html}PermisssionChecker}}>>>
|
||||
can be obtained by injection or by manual lookup. The <<<PermissionChecker>>>
|
||||
provides various methods for checking permissions. Details can be found in
|
||||
the JavaDoc.
|
||||
|
||||
** Secured collections
|
||||
|
||||
Methods in the repository classes often return collections. To make securing
|
||||
these collections easy the {{{ccm-core/apidocs/index.html?org/libreccm/security/package-summary.html}org.libreccm.security}}
|
||||
package provides decorators for the collections from the Java Standard API
|
||||
which check if the current subject is permitted to access an object before
|
||||
returning it. Details can be found in the JavaDoc of the decorators.
|
||||
|
|
@ -24,6 +24,8 @@
|
|||
href="module-system/anatomy.html"/>
|
||||
</item>
|
||||
<item name="How LibreCCM uses JPA" href="entities.html"/>
|
||||
<item name="Authentication and Authorization"
|
||||
href="auth.html"/>
|
||||
</menu>
|
||||
|
||||
<menu ref="modules"/>
|
||||
|
|
|
|||
Loading…
Reference in New Issue