mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
Added 'hasClearance' method to SecurityClearanceService to support EntryVoter and AfterInvocationProvider implementations
* relates to RM-2129 & RM-2130 * added 'getCurrentClassification" method to ClassificationService * added concept of system classification level "Unclassified" .. it no longer is required to be specified in the JSON bootstrap since this is a well known and alway required basic classification level * added concept of system security clearance level "No Clearance" .. automatically added and relates to unclassified classificaiton level * unit tests updated and added * started to move some of the logic out of unit test base class and into helper library called 'AlfMock'! git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@104229 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -18,11 +18,13 @@
|
||||
*/
|
||||
package org.alfresco.module.org_alfresco_module_rm.classification;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationServiceException.LevelIdNotFound;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
* Container for the configured {@link ClassificationLevel} objects.
|
||||
*
|
||||
@@ -30,6 +32,11 @@ import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationS
|
||||
*/
|
||||
public class ClassificationLevelManager
|
||||
{
|
||||
/** Unclassified classificaiton level */
|
||||
public static final String UNCLASSIFIED_ID = "Unclassified";
|
||||
private static final String UNCLASSIFIED_MSG = "rm.classification.unclassified";
|
||||
public static final ClassificationLevel UNCLASSIFIED = new ClassificationLevel(UNCLASSIFIED_ID, UNCLASSIFIED_MSG);
|
||||
|
||||
/** An immutable list of classification levels ordered from most to least secure. */
|
||||
private ImmutableList<ClassificationLevel> classificationLevels;
|
||||
|
||||
@@ -40,7 +47,9 @@ public class ClassificationLevelManager
|
||||
*/
|
||||
public ClassificationLevelManager(List<ClassificationLevel> classificationLevels)
|
||||
{
|
||||
this.classificationLevels = ImmutableList.copyOf(classificationLevels);
|
||||
List<ClassificationLevel> temp = new ArrayList<ClassificationLevel>(classificationLevels);
|
||||
temp.add(temp.size(), UNCLASSIFIED);
|
||||
this.classificationLevels = ImmutableList.copyOf(temp);
|
||||
}
|
||||
|
||||
/** @return the highest security classification level. */
|
||||
|
@@ -44,6 +44,14 @@ public interface ClassificationService
|
||||
* and therefore access to the most restricted documents).
|
||||
*/
|
||||
List<ClassificationLevel> getClassificationLevels();
|
||||
|
||||
/**
|
||||
* Returns the current classification level of a given node.
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
* @return {@link ClassificationLevel} classification level, unclassified if none
|
||||
*/
|
||||
ClassificationLevel getCurrentClassification(NodeRef nodeRef);
|
||||
|
||||
/**
|
||||
* Returns an immutable list of the defined classification reasons.
|
||||
@@ -63,15 +71,14 @@ public interface ClassificationService
|
||||
* @throws InvalidNodeRefException If the node could not be found.
|
||||
* @throws InvalidNode If the supplied node is not a content node.
|
||||
*/
|
||||
void classifyContent(String classificationLevelId, String classificationAuthority,
|
||||
Set<String> classificationReasonIds, NodeRef content) throws LevelIdNotFound, ReasonIdNotFound,
|
||||
InvalidNodeRefException, InvalidNode;
|
||||
void classifyContent(String classificationLevelId, String classificationAuthority, Set<String> classificationReasonIds, NodeRef content)
|
||||
throws LevelIdNotFound, ReasonIdNotFound, InvalidNodeRefException, InvalidNode;
|
||||
|
||||
/**
|
||||
* Gets the default {@link ClassificationLevel}, which will usually be the level with the lowest security clearance.
|
||||
* @return the default classification level, or {@code null} if no security levels are configured.
|
||||
* Gets the unclassified {@link ClassificationLevel}.
|
||||
* @return the unclassified classification level
|
||||
*/
|
||||
ClassificationLevel getDefaultClassificationLevel();
|
||||
ClassificationLevel getUnclassifiedClassificationLevel();
|
||||
|
||||
/**
|
||||
* Gets the classification level for the given classification level id
|
||||
|
@@ -166,6 +166,23 @@ public class ClassificationServiceImpl extends ServiceBaseImpl
|
||||
{
|
||||
return classificationServiceDao.getConfiguredLevels();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.classification.ClassificationService#getCurrentClassification(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
public ClassificationLevel getCurrentClassification(NodeRef nodeRef)
|
||||
{
|
||||
// by default everything is unclassified
|
||||
ClassificationLevel result = ClassificationLevelManager.UNCLASSIFIED;
|
||||
|
||||
if (nodeService.hasAspect(nodeRef, ASPECT_CLASSIFIED))
|
||||
{
|
||||
String classificationId = (String)nodeService.getProperty(nodeRef, PROP_CURRENT_CLASSIFICATION);
|
||||
result = levelManager.findLevelById(classificationId);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the list of classification reasons as persisted in the system.
|
||||
@@ -272,11 +289,10 @@ public class ClassificationServiceImpl extends ServiceBaseImpl
|
||||
// Add aspect
|
||||
nodeService.addAspect(content, ASPECT_CLASSIFIED, properties);
|
||||
}
|
||||
|
||||
@Override public ClassificationLevel getDefaultClassificationLevel()
|
||||
|
||||
@Override public ClassificationLevel getUnclassifiedClassificationLevel()
|
||||
{
|
||||
List<ClassificationLevel> classificationLevels = getClassificationLevels();
|
||||
return classificationLevels.isEmpty() ? null : classificationLevels.get(classificationLevels.size() - 1);
|
||||
return ClassificationLevelManager.UNCLASSIFIED;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -18,11 +18,13 @@
|
||||
*/
|
||||
package org.alfresco.module.org_alfresco_module_rm.classification;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationServiceException.LevelIdNotFound;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
* Container for the configured {@link ClearanceLevel} objects.
|
||||
*
|
||||
@@ -30,6 +32,9 @@ import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationS
|
||||
*/
|
||||
public class ClearanceLevelManager
|
||||
{
|
||||
private static String NO_CLEARANCE_MSG = "rm.classification.noClearance";
|
||||
public static final ClearanceLevel NO_CLEARANCE = new ClearanceLevel(ClassificationLevelManager.UNCLASSIFIED, NO_CLEARANCE_MSG);
|
||||
|
||||
/** An immutable list of clearance levels ordered from most to least secure. */
|
||||
private ImmutableList<ClearanceLevel> clearanceLevels;
|
||||
|
||||
@@ -40,7 +45,9 @@ public class ClearanceLevelManager
|
||||
*/
|
||||
public ClearanceLevelManager(List<ClearanceLevel> clearanceLevels)
|
||||
{
|
||||
this.clearanceLevels = ImmutableList.copyOf(clearanceLevels);
|
||||
List<ClearanceLevel> temp = new ArrayList<ClearanceLevel>(clearanceLevels);
|
||||
temp.add(temp.size(), NO_CLEARANCE);
|
||||
this.clearanceLevels = ImmutableList.copyOf(temp);
|
||||
}
|
||||
|
||||
/** @return An immutable list of clearance levels ordered from most to least secure. */
|
||||
|
@@ -19,6 +19,7 @@
|
||||
package org.alfresco.module.org_alfresco_module_rm.classification;
|
||||
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.security.NoSuchPersonException;
|
||||
|
||||
/**
|
||||
@@ -29,6 +30,18 @@ import org.alfresco.service.cmr.security.NoSuchPersonException;
|
||||
*/
|
||||
public interface SecurityClearanceService
|
||||
{
|
||||
/**
|
||||
* Indicates whether the currently authenticated user has clearance to see the
|
||||
* provided node.
|
||||
* <p>
|
||||
* Note that users, regardless of their clearance level, are always cleared to see a node that has no classification
|
||||
* applied.
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
* @return boolean true if cleared to see node, false otherwise
|
||||
*/
|
||||
boolean hasClearance(NodeRef nodeRef);
|
||||
|
||||
/**
|
||||
* Get the currently authenticated user's security clearance.
|
||||
*
|
||||
|
@@ -57,15 +57,12 @@ public class SecurityClearanceServiceImpl extends ServiceBaseImpl implements Sec
|
||||
{
|
||||
ArrayList<ClearanceLevel> clearanceLevels = new ArrayList<ClearanceLevel>();
|
||||
List<ClassificationLevel> classificationLevels = classificationService.getClassificationLevels();
|
||||
ClassificationLevel unclassified = classificationLevels.get(classificationLevels.size() - 1);
|
||||
for (ClassificationLevel classificationLevel : classificationLevels)
|
||||
{
|
||||
String displayLabelKey = classificationLevel.getDisplayLabelKey();
|
||||
if (classificationLevel.equals(unclassified))
|
||||
{
|
||||
displayLabelKey = "rm.classification.noClearance";
|
||||
}
|
||||
clearanceLevels.add(new ClearanceLevel(classificationLevel, displayLabelKey));
|
||||
if (!ClassificationLevelManager.UNCLASSIFIED.equals(classificationLevel))
|
||||
{
|
||||
clearanceLevels.add(new ClearanceLevel(classificationLevel, classificationLevel.getDisplayLabelKey()));
|
||||
}
|
||||
}
|
||||
this.clearanceManager = new ClearanceLevelManager(clearanceLevels);
|
||||
}
|
||||
@@ -73,6 +70,46 @@ public class SecurityClearanceServiceImpl extends ServiceBaseImpl implements Sec
|
||||
/** Get the clearance manager (for use in unit testing). */
|
||||
protected ClearanceLevelManager getClearanceManager() { return clearanceManager; }
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.classification.SecurityClearanceService#hasClearance(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
@Override
|
||||
public boolean hasClearance(NodeRef nodeRef)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
// get the nodes current classification
|
||||
ClassificationLevel currentClassification = classificationService.getCurrentClassification(nodeRef);
|
||||
if (ClassificationLevelManager.UNCLASSIFIED.equals(currentClassification))
|
||||
{
|
||||
// since the node is not classified user has clearance
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// get the users security clearance
|
||||
SecurityClearance securityClearance = getUserSecurityClearance();
|
||||
if (!ClearanceLevelManager.NO_CLEARANCE.equals(securityClearance.getClearanceLevel()))
|
||||
{
|
||||
// get the users highest classification clearance
|
||||
ClassificationLevel highestClassification = securityClearance.getClearanceLevel().getHighestClassificationLevel();
|
||||
|
||||
// if classification is less than or equal to highest classification then user has clearance
|
||||
List<ClassificationLevel> allClassificationLevels = classificationService.getClassificationLevels();
|
||||
int highestIndex = allClassificationLevels.indexOf(highestClassification);
|
||||
int currentIndex = allClassificationLevels.indexOf(currentClassification);
|
||||
|
||||
if (highestIndex <= currentIndex)
|
||||
{
|
||||
// user has clearance
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecurityClearance getUserSecurityClearance()
|
||||
{
|
||||
@@ -82,6 +119,12 @@ public class SecurityClearanceServiceImpl extends ServiceBaseImpl implements Sec
|
||||
return getUserSecurityClearance(currentUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the users security clearnace.
|
||||
*
|
||||
* @param userName user name
|
||||
* @return {@link SecurityClearance} provides information about the user and their clearance level
|
||||
*/
|
||||
private SecurityClearance getUserSecurityClearance(final String userName)
|
||||
{
|
||||
final NodeRef personNode = personService.getPerson(userName, false);
|
||||
@@ -91,12 +134,15 @@ public class SecurityClearanceServiceImpl extends ServiceBaseImpl implements Sec
|
||||
|
||||
if (nodeService.hasAspect(personNode, ASPECT_SECURITY_CLEARANCE))
|
||||
{
|
||||
final String clearanceLevel = (String)nodeService.getProperty(personNode, PROP_CLEARANCE_LEVEL);
|
||||
final String clearanceLevelValue = (String)nodeService.getProperty(personNode, PROP_CLEARANCE_LEVEL);
|
||||
|
||||
classificationLevel = clearanceLevel == null ? classificationService.getDefaultClassificationLevel() :
|
||||
classificationService.getClassificationLevelById(clearanceLevel);
|
||||
classificationLevel = clearanceLevelValue == null ? classificationService.getUnclassifiedClassificationLevel() :
|
||||
classificationService.getClassificationLevelById(clearanceLevelValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
classificationLevel = classificationService.getUnclassifiedClassificationLevel();
|
||||
}
|
||||
else { classificationLevel = classificationService.getDefaultClassificationLevel(); }
|
||||
|
||||
ClearanceLevel clearanceLevel = clearanceManager.findLevelByClassificationLevelId(classificationLevel.getId());
|
||||
return new SecurityClearance(personInfo, clearanceLevel);
|
||||
|
Reference in New Issue
Block a user