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:
Roy Wetherall
2015-05-15 03:21:08 +00:00
parent 9ccf39c394
commit 826a7d2403
20 changed files with 508 additions and 67 deletions

View File

@@ -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. */

View File

@@ -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

View File

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

View File

@@ -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. */

View File

@@ -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.
*

View File

@@ -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);