mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
RM-2586 Refactor the classification loader to use the caveat config.
Remove the old classification level configuration files. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/DEV/caveatmarkdatatype@114358 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -61,8 +61,6 @@ rm.record.contributors.group.name=RECORD_CONTRIBUTORS
|
|||||||
#
|
#
|
||||||
# Classified records
|
# Classified records
|
||||||
#
|
#
|
||||||
# The location of the classification levels configuration file (relative to the classpath).
|
|
||||||
rm.classification.levelsFile=/alfresco/module/org_alfresco_module_rm/classification/rm-classification-levels.json
|
|
||||||
# The location of the classification reasons configuration file (relative to the classpath).
|
# The location of the classification reasons configuration file (relative to the classpath).
|
||||||
rm.classification.reasonsFile=/alfresco/module/org_alfresco_module_rm/classification/rm-classification-reasons.json
|
rm.classification.reasonsFile=/alfresco/module/org_alfresco_module_rm/classification/rm-classification-reasons.json
|
||||||
# The location of the exemption categories configuration file (relative to the classpath).
|
# The location of the exemption categories configuration file (relative to the classpath).
|
||||||
|
@@ -1,14 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"name" : "TS",
|
|
||||||
"displayLabel" : "rm.classification.topSecret"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name" : "S",
|
|
||||||
"displayLabel" : "rm.classification.secret"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name" : "C",
|
|
||||||
"displayLabel" : "rm.classification.confidential"
|
|
||||||
}
|
|
||||||
]
|
|
@@ -53,7 +53,6 @@
|
|||||||
<!-- Classification service DAO -->
|
<!-- Classification service DAO -->
|
||||||
|
|
||||||
<bean id="classificationServiceDAO" class="org.alfresco.module.org_alfresco_module_rm.classification.ClassificationServiceDAO">
|
<bean id="classificationServiceDAO" class="org.alfresco.module.org_alfresco_module_rm.classification.ClassificationServiceDAO">
|
||||||
<property name="levelConfigLocation" value="${rm.classification.levelsFile}" />
|
|
||||||
<property name="reasonConfigLocation" value="${rm.classification.reasonsFile}" />
|
<property name="reasonConfigLocation" value="${rm.classification.reasonsFile}" />
|
||||||
<property name="exemptionCategoryConfigLocation" value="${rm.classification.exemptionCategoriesFile}" />
|
<property name="exemptionCategoryConfigLocation" value="${rm.classification.exemptionCategoriesFile}" />
|
||||||
</bean>
|
</bean>
|
||||||
@@ -123,6 +122,7 @@
|
|||||||
<constructor-arg ref="TransactionService"/>
|
<constructor-arg ref="TransactionService"/>
|
||||||
<constructor-arg ref="attributeService"/>
|
<constructor-arg ref="attributeService"/>
|
||||||
<constructor-arg ref="classificationServiceDAO"/>
|
<constructor-arg ref="classificationServiceDAO"/>
|
||||||
|
<property name="caveatDAO" ref="caveatDAO" />
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean name="classifiedRenditionAssoc" parent="mr.baseReferralAssoc">
|
<bean name="classifiedRenditionAssoc" parent="mr.baseReferralAssoc">
|
||||||
|
@@ -270,12 +270,12 @@
|
|||||||
<!-- Import the Metadata Referral Services -->
|
<!-- Import the Metadata Referral Services -->
|
||||||
<import resource="classpath:alfresco/module/org_alfresco_module_rm/metadata-referral-context.xml"/>
|
<import resource="classpath:alfresco/module/org_alfresco_module_rm/metadata-referral-context.xml"/>
|
||||||
|
|
||||||
<!-- Import the Classified Content Services -->
|
|
||||||
<import resource="classpath:alfresco/module/org_alfresco_module_rm/classified-content-context.xml"/>
|
|
||||||
|
|
||||||
<!-- Import the Caveat Services -->
|
<!-- Import the Caveat Services -->
|
||||||
<import resource="classpath:alfresco/module/org_alfresco_module_rm/caveat-context.xml"/>
|
<import resource="classpath:alfresco/module/org_alfresco_module_rm/caveat-context.xml"/>
|
||||||
|
|
||||||
|
<!-- Import the Classified Content Services -->
|
||||||
|
<import resource="classpath:alfresco/module/org_alfresco_module_rm/classified-content-context.xml"/>
|
||||||
|
|
||||||
<!-- Import the Content Services -->
|
<!-- Import the Content Services -->
|
||||||
<import resource="classpath:alfresco/module/org_alfresco_module_rm/content-context.xml"/>
|
<import resource="classpath:alfresco/module/org_alfresco_module_rm/content-context.xml"/>
|
||||||
|
|
||||||
|
@@ -108,7 +108,14 @@ public class CaveatDAOFromJSONBootstrap extends AbstractLifecycleBean
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public ImmutableMap<String, CaveatGroup> doWork() throws Exception
|
public ImmutableMap<String, CaveatGroup> doWork() throws Exception
|
||||||
{
|
{
|
||||||
return (ImmutableMap<String, CaveatGroup>) attributeService.getAttribute(key);
|
// TODO: Although an ImmutableMap is stored, after restarting the server, a HashMap is returned.
|
||||||
|
// Investigate why this is, and whether we can avoid creating a new copy of the map here.
|
||||||
|
Map<String, CaveatGroup> persistedMap = (Map<String, CaveatGroup>) attributeService.getAttribute(key);
|
||||||
|
if (persistedMap == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return ImmutableMap.copyOf(persistedMap);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -23,6 +23,10 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableList.Builder;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.caveat.dao.CaveatDAOInterface;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.caveat.scheme.CaveatGroup;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.caveat.scheme.CaveatMark;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationException.MissingConfiguration;
|
import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationException.MissingConfiguration;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.classification.model.ClassifiedContentModel;
|
import org.alfresco.module.org_alfresco_module_rm.classification.model.ClassifiedContentModel;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.classification.validation.ClassificationLevelFieldsValidator;
|
import org.alfresco.module.org_alfresco_module_rm.classification.validation.ClassificationLevelFieldsValidator;
|
||||||
@@ -61,6 +65,8 @@ public class ClassificationServiceBootstrap extends AbstractLifecycleBean implem
|
|||||||
private ClearanceLevelManager clearanceLevelManager = new ClearanceLevelManager();
|
private ClearanceLevelManager clearanceLevelManager = new ClearanceLevelManager();
|
||||||
/** The exemption categories currently configured in this server. */
|
/** The exemption categories currently configured in this server. */
|
||||||
private ExemptionCategoryManager exemptionCategoryManager = new ExemptionCategoryManager();
|
private ExemptionCategoryManager exemptionCategoryManager = new ExemptionCategoryManager();
|
||||||
|
/** The caveat DAO, which is used to access the classification levels. */
|
||||||
|
private CaveatDAOInterface caveatDAO;
|
||||||
private ClassificationServiceDAO classificationServiceDAO;
|
private ClassificationServiceDAO classificationServiceDAO;
|
||||||
private ClassificationLevelFieldsValidator classificationLevelFieldsValidator = new ClassificationLevelFieldsValidator();
|
private ClassificationLevelFieldsValidator classificationLevelFieldsValidator = new ClassificationLevelFieldsValidator();
|
||||||
private ClassificationSchemeEntityValidator<ClassificationLevel> classificationLevelValidator = new ClassificationSchemeEntityValidator<>(classificationLevelFieldsValidator);
|
private ClassificationSchemeEntityValidator<ClassificationLevel> classificationLevelValidator = new ClassificationSchemeEntityValidator<>(classificationLevelFieldsValidator);
|
||||||
@@ -82,6 +88,8 @@ public class ClassificationServiceBootstrap extends AbstractLifecycleBean implem
|
|||||||
this.classificationServiceDAO = classificationServiceDAO;
|
this.classificationServiceDAO = classificationServiceDAO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Set the caveat DAO, which is used to access the classification levels. */
|
||||||
|
public void setCaveatDAO(CaveatDAOInterface caveatDAO) { this.caveatDAO = caveatDAO; }
|
||||||
/** Set the object from which configuration options will be read. */
|
/** Set the object from which configuration options will be read. */
|
||||||
public void setClassificationServiceDAO(ClassificationServiceDAO classificationServiceDAO) { this.classificationServiceDAO = classificationServiceDAO; }
|
public void setClassificationServiceDAO(ClassificationServiceDAO classificationServiceDAO) { this.classificationServiceDAO = classificationServiceDAO; }
|
||||||
public void setAttributeService(AttributeService attributeService) { this.attributeService = attributeService; }
|
public void setAttributeService(AttributeService attributeService) { this.attributeService = attributeService; }
|
||||||
@@ -110,8 +118,7 @@ public class ClassificationServiceBootstrap extends AbstractLifecycleBean implem
|
|||||||
{
|
{
|
||||||
public Void execute()
|
public Void execute()
|
||||||
{
|
{
|
||||||
List<ClassificationLevel> levels = getConfiguredSchemeEntities(
|
List<ClassificationLevel> levels = getConfiguredClassificationLevels(LEVELS_KEY, classificationLevelValidator);
|
||||||
ClassificationLevel.class, LEVELS_KEY, classificationLevelValidator);
|
|
||||||
classificationLevelManager.setClassificationLevels(levels);
|
classificationLevelManager.setClassificationLevels(levels);
|
||||||
|
|
||||||
List<ClassificationReason> reasons = getConfiguredSchemeEntities(
|
List<ClassificationReason> reasons = getConfiguredSchemeEntities(
|
||||||
@@ -160,6 +167,46 @@ public class ClassificationServiceBootstrap extends AbstractLifecycleBean implem
|
|||||||
else { return "non-empty"; }
|
else { return "non-empty"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the classification levels from the classification caveat group data.
|
||||||
|
*
|
||||||
|
* @param key The key used to persist the classification levels in the attribute service.
|
||||||
|
* @param validator The validator used to check the classification levels.
|
||||||
|
* @return A list of the configured classification levels.
|
||||||
|
*/
|
||||||
|
protected List<ClassificationLevel> getConfiguredClassificationLevels(Serializable[] key, ClassificationSchemeEntityValidator<ClassificationLevel> validator)
|
||||||
|
{
|
||||||
|
List<ClassificationLevel> persistedValues = getPersistedValues(key);
|
||||||
|
CaveatGroup classificationCaveatGroup = caveatDAO.getGroupById(CLASSIFICATION_LEVEL_CAVEAT);
|
||||||
|
Builder<ClassificationLevel> builder = ImmutableList.builder();
|
||||||
|
for (CaveatMark caveatMark : classificationCaveatGroup.getCaveatMarks())
|
||||||
|
{
|
||||||
|
builder.add(new ClassificationLevel(caveatMark));
|
||||||
|
}
|
||||||
|
List<ClassificationLevel> classpathValues = builder.build();
|
||||||
|
|
||||||
|
// Note! We cannot log the entities or even the size of these lists for security reasons.
|
||||||
|
LOGGER.debug("Persisted ClassificationLevel: {}", loggableStatusOf(persistedValues));
|
||||||
|
LOGGER.debug("Classpath ClassificationLevel: {}", loggableStatusOf(classpathValues));
|
||||||
|
|
||||||
|
validator.validate(classpathValues, ClassificationLevel.class.getSimpleName());
|
||||||
|
|
||||||
|
if (isEmpty(classpathValues))
|
||||||
|
{
|
||||||
|
throw new MissingConfiguration("ClassificationLevel configuration is missing.");
|
||||||
|
}
|
||||||
|
if (classpathValues.equals(persistedValues))
|
||||||
|
{
|
||||||
|
return persistedValues;
|
||||||
|
}
|
||||||
|
if (!isEmpty(persistedValues))
|
||||||
|
{
|
||||||
|
LOGGER.warn("ClassificationLevel configuration changed. This may result in unpredictable results if the classification scheme is already in use.");
|
||||||
|
}
|
||||||
|
attributeService.setAttribute((Serializable) classpathValues, key);
|
||||||
|
return classpathValues;
|
||||||
|
}
|
||||||
|
|
||||||
protected <T extends ClassificationSchemeEntity> List<T> getConfiguredSchemeEntities(Class<T> clazz, Serializable[] key, ClassificationSchemeEntityValidator<T> validator)
|
protected <T extends ClassificationSchemeEntity> List<T> getConfiguredSchemeEntities(Class<T> clazz, Serializable[] key, ClassificationSchemeEntityValidator<T> validator)
|
||||||
{
|
{
|
||||||
final List<T> persistedValues = getPersistedValues(key);
|
final List<T> persistedValues = getPersistedValues(key);
|
||||||
|
@@ -34,8 +34,8 @@ import org.json.JSONObject;
|
|||||||
import org.json.JSONTokener;
|
import org.json.JSONTokener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is responsible for providing the configured classification levels
|
* This class is responsible for providing the configured classification scheme entities, dealing with JSON schema as
|
||||||
* and classification reasons, dealing with JSON schema as part of that.
|
* part of that.
|
||||||
*
|
*
|
||||||
* @author Neil Mc Erlean
|
* @author Neil Mc Erlean
|
||||||
* @since 2.4.a
|
* @since 2.4.a
|
||||||
@@ -47,11 +47,6 @@ class ClassificationServiceDAO
|
|||||||
|
|
||||||
private ClassificationSchemeEntityFactory classificationSchemeEntityFactory = new ClassificationSchemeEntityFactory();
|
private ClassificationSchemeEntityFactory classificationSchemeEntityFactory = new ClassificationSchemeEntityFactory();
|
||||||
|
|
||||||
/** Set the location of the level configuration file relative to the classpath. */
|
|
||||||
public void setLevelConfigLocation(String levelConfigLocation)
|
|
||||||
{
|
|
||||||
configLocations.put(ClassificationLevel.class.getSimpleName(), levelConfigLocation);
|
|
||||||
}
|
|
||||||
/** Set the location of the reasons configuration file relative to the classpath. */
|
/** Set the location of the reasons configuration file relative to the classpath. */
|
||||||
public void setReasonConfigLocation(String reasonConfigLocation)
|
public void setReasonConfigLocation(String reasonConfigLocation)
|
||||||
{
|
{
|
||||||
|
@@ -36,6 +36,8 @@ public interface ClassifiedContentModel
|
|||||||
String CLF_URI = "http://www.alfresco.org/model/classifiedcontent/1.0";
|
String CLF_URI = "http://www.alfresco.org/model/classifiedcontent/1.0";
|
||||||
String CLF_PREFIX = "clf";
|
String CLF_PREFIX = "clf";
|
||||||
|
|
||||||
|
String CLASSIFICATION_LEVEL_CAVEAT = "classification";
|
||||||
|
|
||||||
Serializable[] LEVELS_KEY = new String[] { "org.alfresco", "module.org_alfresco_module_rm", "classification.levels" };
|
Serializable[] LEVELS_KEY = new String[] { "org.alfresco", "module.org_alfresco_module_rm", "classification.levels" };
|
||||||
Serializable[] REASONS_KEY = new String[] { "org.alfresco", "module.org_alfresco_module_rm", "classification.reasons" };
|
Serializable[] REASONS_KEY = new String[] { "org.alfresco", "module.org_alfresco_module_rm", "classification.reasons" };
|
||||||
Serializable[] EXEMPTION_CATEGORIES_KEY = new String[] { "org.alfresco", "module.org_alfresco_module_rm", "classification.exemptionCategories" };
|
Serializable[] EXEMPTION_CATEGORIES_KEY = new String[] { "org.alfresco", "module.org_alfresco_module_rm", "classification.exemptionCategories" };
|
||||||
|
@@ -179,29 +179,29 @@ public class ClassificationConstraintTest implements RMPermissionModel
|
|||||||
* Mid-level user further downgrading a downgraded record.
|
* Mid-level user further downgrading a downgraded record.
|
||||||
* <p>
|
* <p>
|
||||||
* <a href="https://issues.alfresco.com/jira/browse/RM-2502">RM-2502</a><pre>
|
* <a href="https://issues.alfresco.com/jira/browse/RM-2502">RM-2502</a><pre>
|
||||||
* Given I have "level2" clearance
|
* Given I have secret clearance
|
||||||
* And a record has an initial classification of "level1"
|
* And a record has an initial classification of top secret
|
||||||
* And the record has a current classification of "level2"
|
* And the record has a current classification of secret
|
||||||
* When I try to downgrade the record to "level3"
|
* When I try to downgrade the record to confidential
|
||||||
* Then I am successful.
|
* Then I am successful.
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testInitialClassificationConstraint()
|
public void testInitialClassificationConstraint()
|
||||||
{
|
{
|
||||||
// Given I set up some test data (admin at level 1, midLevelUser at level 2 and a new record).
|
// Given I set up some test data (admin at TS, midLevelUser at S and a new record).
|
||||||
final String midLevelUser = GUID.generate();
|
final String midLevelUser = GUID.generate();
|
||||||
final NodeRef record = AuthenticationUtil.runAsSystem(new RunAsWork<NodeRef>()
|
final NodeRef record = AuthenticationUtil.runAsSystem(new RunAsWork<NodeRef>()
|
||||||
{
|
{
|
||||||
public NodeRef doWork()
|
public NodeRef doWork()
|
||||||
{
|
{
|
||||||
// Ensure admin is level 1 cleared.
|
// Ensure admin is TS cleared.
|
||||||
securityClearanceService.setUserSecurityClearance(AuthenticationUtil.getAdminUserName(), "level1");
|
securityClearanceService.setUserSecurityClearance(AuthenticationUtil.getAdminUserName(), "TS");
|
||||||
// Create user with level 2 clearance.
|
// Create user with S clearance.
|
||||||
createPerson(midLevelUser, true);
|
createPerson(midLevelUser, true);
|
||||||
filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_RECORDS_MANAGER, midLevelUser);
|
filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_RECORDS_MANAGER, midLevelUser);
|
||||||
filePlanPermissionService.setPermission(rmContainer, midLevelUser, FILING);
|
filePlanPermissionService.setPermission(rmContainer, midLevelUser, FILING);
|
||||||
securityClearanceService.setUserSecurityClearance(midLevelUser, "level2");
|
securityClearanceService.setUserSecurityClearance(midLevelUser, "S");
|
||||||
// Create a record to be classified during the test.
|
// Create a record to be classified during the test.
|
||||||
return utils.createRecord(rmFolder, RECORD_NAME);
|
return utils.createRecord(rmFolder, RECORD_NAME);
|
||||||
}
|
}
|
||||||
@@ -212,42 +212,42 @@ public class ClassificationConstraintTest implements RMPermissionModel
|
|||||||
{
|
{
|
||||||
public Void doWork()
|
public Void doWork()
|
||||||
{
|
{
|
||||||
// Create a level 1 record and downgrade it to level 2.
|
// Create a TS record and downgrade it to S.
|
||||||
classifyAs(record, "level1");
|
classifyAs(record, "TS");
|
||||||
classifyAs(record, "level2");
|
classifyAs(record, "S");
|
||||||
|
|
||||||
assertTrue("Record should have been classified.",
|
assertTrue("Record should have been classified.",
|
||||||
nodeService.hasAspect(record, ClassifiedContentModel.ASPECT_CLASSIFIED));
|
nodeService.hasAspect(record, ClassifiedContentModel.ASPECT_CLASSIFIED));
|
||||||
assertEquals("Record have initial classification of 'level1'.", "level1",
|
assertEquals("Record have initial classification of 'TS'.", "TS",
|
||||||
nodeService.getProperty(record, ClassifiedContentModel.PROP_INITIAL_CLASSIFICATION));
|
nodeService.getProperty(record, ClassifiedContentModel.PROP_INITIAL_CLASSIFICATION));
|
||||||
assertEquals("Record should be 'level2' classified.", "level2",
|
assertEquals("Record should be 'S' classified.", "S",
|
||||||
nodeService.getProperty(record, ClassifiedContentModel.PROP_CURRENT_CLASSIFICATION));
|
nodeService.getProperty(record, ClassifiedContentModel.PROP_CURRENT_CLASSIFICATION));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}, AuthenticationUtil.getAdminUserName());
|
}, AuthenticationUtil.getAdminUserName());
|
||||||
|
|
||||||
// When the mid-level user downgrades the record to level 3.
|
// When the mid-level user downgrades the record to C.
|
||||||
AuthenticationUtil.runAs(new RunAsWork<Void>()
|
AuthenticationUtil.runAs(new RunAsWork<Void>()
|
||||||
{
|
{
|
||||||
public Void doWork()
|
public Void doWork()
|
||||||
{
|
{
|
||||||
// Check that the mid-clearance user can further downgrade the classification (even though the initial
|
// Check that the mid-clearance user can further downgrade the classification (even though the initial
|
||||||
// classification was above their clearance).
|
// classification was above their clearance).
|
||||||
classifyAs(record, "level3");
|
classifyAs(record, "C");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}, midLevelUser);
|
}, midLevelUser);
|
||||||
|
|
||||||
// Then the record is classified at level 3 (with initial classification level 1).
|
// Then the record is classified at C (with initial classification TS).
|
||||||
AuthenticationUtil.runAs(new RunAsWork<Void>()
|
AuthenticationUtil.runAs(new RunAsWork<Void>()
|
||||||
{
|
{
|
||||||
public Void doWork()
|
public Void doWork()
|
||||||
{
|
{
|
||||||
assertTrue("Record should still be classified.",
|
assertTrue("Record should still be classified.",
|
||||||
nodeService.hasAspect(record, ClassifiedContentModel.ASPECT_CLASSIFIED));
|
nodeService.hasAspect(record, ClassifiedContentModel.ASPECT_CLASSIFIED));
|
||||||
assertEquals("Record have initial classification of 'level1'.", "level1",
|
assertEquals("Record have initial classification of 'TS'.", "TS",
|
||||||
nodeService.getProperty(record, ClassifiedContentModel.PROP_INITIAL_CLASSIFICATION));
|
nodeService.getProperty(record, ClassifiedContentModel.PROP_INITIAL_CLASSIFICATION));
|
||||||
assertEquals("Record should be 'level3' classified.", "level3",
|
assertEquals("Record should be 'C' classified.", "C",
|
||||||
nodeService.getProperty(record, ClassifiedContentModel.PROP_CURRENT_CLASSIFICATION));
|
nodeService.getProperty(record, ClassifiedContentModel.PROP_CURRENT_CLASSIFICATION));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.module.org_alfresco_module_rm.test.integration.classification;
|
package org.alfresco.module.org_alfresco_module_rm.test.integration.classification;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationLevel;
|
import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationLevel;
|
||||||
@@ -33,28 +33,10 @@ import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
|
|||||||
*/
|
*/
|
||||||
public class ClassificationLevelsTest extends BaseRMTestCase
|
public class ClassificationLevelsTest extends BaseRMTestCase
|
||||||
{
|
{
|
||||||
private static final String CLASSIFICATION_LEVELS_FILE_PATH = "/alfresco/module/org_alfresco_module_rm/classification/rm-classification-levels.json";
|
|
||||||
private static final String LEVEL1_ID = "level1";
|
|
||||||
private static final String LEVEL1_DISPLAY_LABEL = "Level 1";
|
|
||||||
private static final String LEVEL2_ID = "level2";
|
|
||||||
private static final String LEVEL2_DISPLAY_LABEL_KEY = "rm.classification.level2";
|
|
||||||
private static final String LEVEL3_ID = "level3";
|
|
||||||
private static final String LEVEL3_DISPLAY_LABEL_KEY = "rm.classification.level3";
|
|
||||||
private static final String LEVEL4_ID = "level4";
|
|
||||||
private static final String LEVEL4_DISPLAY_LABEL = "Level 4";
|
|
||||||
|
|
||||||
public void testClassificationLevels() throws Exception
|
public void testClassificationLevels() throws Exception
|
||||||
{
|
{
|
||||||
doBehaviourDrivenTest(new BehaviourDrivenTest()
|
doBehaviourDrivenTest(new BehaviourDrivenTest()
|
||||||
{
|
{
|
||||||
public void given() throws Exception
|
|
||||||
{
|
|
||||||
try (final InputStream in = getClass().getResourceAsStream(CLASSIFICATION_LEVELS_FILE_PATH))
|
|
||||||
{
|
|
||||||
assertNotNull(in);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void when() throws Exception
|
public void when() throws Exception
|
||||||
{
|
{
|
||||||
// Server is up and running
|
// Server is up and running
|
||||||
@@ -63,25 +45,12 @@ public class ClassificationLevelsTest extends BaseRMTestCase
|
|||||||
public void then() throws Exception
|
public void then() throws Exception
|
||||||
{
|
{
|
||||||
List<ClassificationLevel> levels = classificationSchemeService.getClassificationLevels();
|
List<ClassificationLevel> levels = classificationSchemeService.getClassificationLevels();
|
||||||
assertNotNull(levels);
|
List<ClassificationLevel> expectedLevels = Arrays.asList(
|
||||||
assertEquals("Expected 5 levels to be configured (4 defined in the test plus Unclassified)", 5, levels.size());
|
new ClassificationLevel("TS", "rm.caveat.classification.mark.ts.label"),
|
||||||
|
new ClassificationLevel("S", "rm.caveat.classification.mark.s.label"),
|
||||||
ClassificationLevel level1 = levels.get(0);
|
new ClassificationLevel("C", "rm.caveat.classification.mark.c.label"),
|
||||||
ClassificationLevel level2 = levels.get(1);
|
ClassificationLevelManager.UNCLASSIFIED);
|
||||||
ClassificationLevel level3 = levels.get(2);
|
assertEquals(levels, expectedLevels);
|
||||||
ClassificationLevel level4 = levels.get(3);
|
|
||||||
|
|
||||||
assertEquals(level4.getDisplayLabel(), LEVEL4_DISPLAY_LABEL);
|
|
||||||
assertEquals(level3.getDisplayLabel(), LEVEL3_DISPLAY_LABEL_KEY);
|
|
||||||
assertEquals(level2.getDisplayLabel(), LEVEL2_DISPLAY_LABEL_KEY);
|
|
||||||
assertEquals(level1.getDisplayLabel(), LEVEL1_DISPLAY_LABEL);
|
|
||||||
|
|
||||||
assertEquals(level1.getId(), LEVEL1_ID);
|
|
||||||
assertEquals(level2.getId(), LEVEL2_ID);
|
|
||||||
assertEquals(level3.getId(), LEVEL3_ID);
|
|
||||||
assertEquals(level4.getId(), LEVEL4_ID);
|
|
||||||
|
|
||||||
assertEquals(ClassificationLevelManager.UNCLASSIFIED, levels.get(4));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -40,8 +40,8 @@ import org.alfresco.util.GUID;
|
|||||||
public class ClassifyTest extends BaseRMTestCase
|
public class ClassifyTest extends BaseRMTestCase
|
||||||
{
|
{
|
||||||
/** test data */
|
/** test data */
|
||||||
private static final String CLASSIFICATION_LEVEL = "level1";
|
private static final String CLASSIFICATION_LEVEL = "TS";
|
||||||
private static final String LOWER_CLASSIFICATION_LEVEL = "level2";
|
private static final String LOWER_CLASSIFICATION_LEVEL = "S";
|
||||||
private static final String CLASSIFICATION_REASON = "Test Reason 1";
|
private static final String CLASSIFICATION_REASON = "Test Reason 1";
|
||||||
private static final String CLASSIFICATION_AGENCY = "classification agency";
|
private static final String CLASSIFICATION_AGENCY = "classification agency";
|
||||||
private static final String CLASSIFIED_BY = "classified by text";
|
private static final String CLASSIFIED_BY = "classified by text";
|
||||||
@@ -122,8 +122,8 @@ public class ClassifyTest extends BaseRMTestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given I have "level1" clearance
|
* Given I have top secret clearance
|
||||||
* When I try to classify content with the level "level1"
|
* When I try to classify content as top secret
|
||||||
* Then the content is classified.
|
* Then the content is classified.
|
||||||
*/
|
*/
|
||||||
public void testClassifyContent()
|
public void testClassifyContent()
|
||||||
@@ -165,15 +165,15 @@ public class ClassifyTest extends BaseRMTestCase
|
|||||||
{
|
{
|
||||||
assertTrue("Record should have been classified.",
|
assertTrue("Record should have been classified.",
|
||||||
nodeService.hasAspect(record, ClassifiedContentModel.ASPECT_CLASSIFIED));
|
nodeService.hasAspect(record, ClassifiedContentModel.ASPECT_CLASSIFIED));
|
||||||
assertEquals("Record should be 'level1' classified.", CLASSIFICATION_LEVEL,
|
assertEquals("Record should be classified as top secret.", CLASSIFICATION_LEVEL,
|
||||||
nodeService.getProperty(record, ClassifiedContentModel.PROP_CURRENT_CLASSIFICATION));
|
nodeService.getProperty(record, ClassifiedContentModel.PROP_CURRENT_CLASSIFICATION));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given I have "level2" clearance
|
* Given I have secret clearance
|
||||||
* When I call the classify content API directly using the level "level1"
|
* When I call the classify content API directly using the level "top secret"
|
||||||
* Then I receive an error that the level could not be found.
|
* Then I receive an error that the level could not be found.
|
||||||
*/
|
*/
|
||||||
public void testClearanceNecessaryToClassifyContent()
|
public void testClearanceNecessaryToClassifyContent()
|
||||||
|
@@ -18,8 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.module.org_alfresco_module_rm.test.integration.classification;
|
package org.alfresco.module.org_alfresco_module_rm.test.integration.classification;
|
||||||
|
|
||||||
import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationLevel;
|
|
||||||
import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationException.LevelIdNotFound;
|
import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationException.LevelIdNotFound;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationLevel;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.classification.ClearanceLevel;
|
import org.alfresco.module.org_alfresco_module_rm.classification.ClearanceLevel;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.classification.SecurityClearance;
|
import org.alfresco.module.org_alfresco_module_rm.classification.SecurityClearance;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
|
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
|
||||||
@@ -50,21 +50,21 @@ public class SecurityClearanceTest extends BaseRMTestCase
|
|||||||
|
|
||||||
public void when() throws Exception
|
public void when() throws Exception
|
||||||
{
|
{
|
||||||
securityClearance = securityClearanceService.setUserSecurityClearance(userName, "level1");
|
securityClearance = securityClearanceService.setUserSecurityClearance(userName, "TS");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void then() throws Exception
|
public void then() throws Exception
|
||||||
{
|
{
|
||||||
ClearanceLevel clearanceLevel = securityClearance.getClearanceLevel();
|
ClearanceLevel clearanceLevel = securityClearance.getClearanceLevel();
|
||||||
ClassificationLevel highestClassificationLevel = clearanceLevel.getHighestClassificationLevel();
|
ClassificationLevel highestClassificationLevel = clearanceLevel.getHighestClassificationLevel();
|
||||||
assertEquals("level1", highestClassificationLevel.getId());
|
assertEquals("TS", highestClassificationLevel.getId());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given I am a user with level2 access
|
* Given I am a user with S access
|
||||||
* And I try to give another user level1 access
|
* And I try to give another user TS access
|
||||||
* Then an exception is thrown.
|
* Then an exception is thrown.
|
||||||
*/
|
*/
|
||||||
public void testCantGiveClearance() throws Exception
|
public void testCantGiveClearance() throws Exception
|
||||||
@@ -73,7 +73,7 @@ public class SecurityClearanceTest extends BaseRMTestCase
|
|||||||
{
|
{
|
||||||
public void given() throws Exception
|
public void given() throws Exception
|
||||||
{
|
{
|
||||||
securityClearanceService.setUserSecurityClearance(userName, "level2");
|
securityClearanceService.setUserSecurityClearance(userName, "S");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void when() throws Exception
|
public void when() throws Exception
|
||||||
@@ -83,7 +83,7 @@ public class SecurityClearanceTest extends BaseRMTestCase
|
|||||||
@Override
|
@Override
|
||||||
public Void run()
|
public Void run()
|
||||||
{
|
{
|
||||||
securityClearanceService.setUserSecurityClearance(rmUserName, "level1");
|
securityClearanceService.setUserSecurityClearance(rmUserName, "TS");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}, userName);
|
}, userName);
|
||||||
|
@@ -38,12 +38,12 @@ import org.alfresco.service.cmr.repository.NodeRef;
|
|||||||
public abstract class BrowseClassificationEnforcementTestBase extends BaseRMTestCase
|
public abstract class BrowseClassificationEnforcementTestBase extends BaseRMTestCase
|
||||||
{
|
{
|
||||||
protected String testUser;
|
protected String testUser;
|
||||||
protected static final String LEVEL1 = "level1";
|
protected static final String TOP_SECRET_ID = "TS";
|
||||||
protected static final String LEVEL2 = "level2";
|
protected static final String SECRET_ID = "S";
|
||||||
protected static final String REASON = "Test Reason 1";
|
protected static final String REASON = "Test Reason 1";
|
||||||
/** Classified properties for classification level 1. */
|
/** Classified properties for top secret. */
|
||||||
protected ClassificationAspectProperties propertiesDTO1;
|
protected ClassificationAspectProperties propertiesDTO1;
|
||||||
/** Classified properties for classification level 2. */
|
/** Classified properties for secret. */
|
||||||
protected ClassificationAspectProperties propertiesDTO2;
|
protected ClassificationAspectProperties propertiesDTO2;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -51,12 +51,12 @@ public abstract class BrowseClassificationEnforcementTestBase extends BaseRMTest
|
|||||||
{
|
{
|
||||||
super.setUp();
|
super.setUp();
|
||||||
propertiesDTO1 = new ClassificationAspectProperties();
|
propertiesDTO1 = new ClassificationAspectProperties();
|
||||||
propertiesDTO1.setClassificationLevelId(LEVEL1);
|
propertiesDTO1.setClassificationLevelId(TOP_SECRET_ID);
|
||||||
propertiesDTO1.setClassifiedBy(generate());
|
propertiesDTO1.setClassifiedBy(generate());
|
||||||
propertiesDTO1.setClassificationAgency(generate());
|
propertiesDTO1.setClassificationAgency(generate());
|
||||||
propertiesDTO1.setClassificationReasonIds(Collections.singleton(REASON));
|
propertiesDTO1.setClassificationReasonIds(Collections.singleton(REASON));
|
||||||
propertiesDTO2 = new ClassificationAspectProperties();
|
propertiesDTO2 = new ClassificationAspectProperties();
|
||||||
propertiesDTO2.setClassificationLevelId(LEVEL2);
|
propertiesDTO2.setClassificationLevelId(SECRET_ID);
|
||||||
propertiesDTO2.setClassifiedBy(generate());
|
propertiesDTO2.setClassifiedBy(generate());
|
||||||
propertiesDTO2.setClassificationAgency(generate());
|
propertiesDTO2.setClassificationAgency(generate());
|
||||||
propertiesDTO2.setClassificationReasonIds(Collections.singleton(REASON));
|
propertiesDTO2.setClassificationReasonIds(Collections.singleton(REASON));
|
||||||
|
@@ -40,7 +40,7 @@ import org.alfresco.service.namespace.QName;
|
|||||||
*/
|
*/
|
||||||
public class ClassificationEnforcementPreMethodInvocationTest extends BaseRMTestCase
|
public class ClassificationEnforcementPreMethodInvocationTest extends BaseRMTestCase
|
||||||
{
|
{
|
||||||
private static final String LEVEL1 = "level1";
|
private static final String TOP_SECRET_ID = "TS";
|
||||||
private static final String REASON = "Test Reason 1";
|
private static final String REASON = "Test Reason 1";
|
||||||
|
|
||||||
private ClassificationAspectProperties propertiesDTO;
|
private ClassificationAspectProperties propertiesDTO;
|
||||||
@@ -50,7 +50,7 @@ public class ClassificationEnforcementPreMethodInvocationTest extends BaseRMTest
|
|||||||
{
|
{
|
||||||
super.setUp();
|
super.setUp();
|
||||||
propertiesDTO = new ClassificationAspectProperties();
|
propertiesDTO = new ClassificationAspectProperties();
|
||||||
propertiesDTO.setClassificationLevelId(LEVEL1);
|
propertiesDTO.setClassificationLevelId(TOP_SECRET_ID);
|
||||||
propertiesDTO.setClassifiedBy(generate());
|
propertiesDTO.setClassifiedBy(generate());
|
||||||
propertiesDTO.setClassificationAgency(generate());
|
propertiesDTO.setClassificationAgency(generate());
|
||||||
propertiesDTO.setClassificationReasonIds(Collections.singleton(REASON));
|
propertiesDTO.setClassificationReasonIds(Collections.singleton(REASON));
|
||||||
|
@@ -164,7 +164,7 @@ public class DocumentBrowseClassificationEnforcementTest extends BrowseClassific
|
|||||||
testUser = generate();
|
testUser = generate();
|
||||||
createPerson(testUser);
|
createPerson(testUser);
|
||||||
siteService.setMembership(collabSiteId, testUser, SITE_MANAGER);
|
siteService.setMembership(collabSiteId, testUser, SITE_MANAGER);
|
||||||
securityClearanceService.setUserSecurityClearance(testUser, LEVEL2);
|
securityClearanceService.setUserSecurityClearance(testUser, SECRET_ID);
|
||||||
|
|
||||||
folder = fileFolderService.create(documentLibrary, generate(), TYPE_FOLDER).getNodeRef();
|
folder = fileFolderService.create(documentLibrary, generate(), TYPE_FOLDER).getNodeRef();
|
||||||
doc1 = fileFolderService.create(folder, generate(), TYPE_CONTENT).getNodeRef();
|
doc1 = fileFolderService.create(folder, generate(), TYPE_CONTENT).getNodeRef();
|
||||||
@@ -259,7 +259,7 @@ public class DocumentBrowseClassificationEnforcementTest extends BrowseClassific
|
|||||||
testUser = generate();
|
testUser = generate();
|
||||||
createPerson(testUser);
|
createPerson(testUser);
|
||||||
siteService.setMembership(collabSiteId, testUser, SITE_MANAGER);
|
siteService.setMembership(collabSiteId, testUser, SITE_MANAGER);
|
||||||
securityClearanceService.setUserSecurityClearance(testUser, LEVEL1);
|
securityClearanceService.setUserSecurityClearance(testUser, TOP_SECRET_ID);
|
||||||
|
|
||||||
folder = fileFolderService.create(documentLibrary, generate(), TYPE_FOLDER).getNodeRef();
|
folder = fileFolderService.create(documentLibrary, generate(), TYPE_FOLDER).getNodeRef();
|
||||||
doc1 = fileFolderService.create(folder, generate(), TYPE_CONTENT).getNodeRef();
|
doc1 = fileFolderService.create(folder, generate(), TYPE_CONTENT).getNodeRef();
|
||||||
|
@@ -166,7 +166,7 @@ public class DocumentSearchClassificationEnforcementTest extends SearchClassific
|
|||||||
testUser = generate();
|
testUser = generate();
|
||||||
createPerson(testUser);
|
createPerson(testUser);
|
||||||
siteService.setMembership(collabSiteId, testUser, SITE_MANAGER);
|
siteService.setMembership(collabSiteId, testUser, SITE_MANAGER);
|
||||||
securityClearanceService.setUserSecurityClearance(testUser, LEVEL2);
|
securityClearanceService.setUserSecurityClearance(testUser, SECRET_ID);
|
||||||
|
|
||||||
folder = fileFolderService.create(documentLibrary, generate(), TYPE_FOLDER).getNodeRef();
|
folder = fileFolderService.create(documentLibrary, generate(), TYPE_FOLDER).getNodeRef();
|
||||||
doc1 = fileFolderService.create(folder, searchQuery + generate(), TYPE_CONTENT).getNodeRef();
|
doc1 = fileFolderService.create(folder, searchQuery + generate(), TYPE_CONTENT).getNodeRef();
|
||||||
@@ -258,7 +258,7 @@ public class DocumentSearchClassificationEnforcementTest extends SearchClassific
|
|||||||
testUser = generate();
|
testUser = generate();
|
||||||
createPerson(testUser);
|
createPerson(testUser);
|
||||||
siteService.setMembership(collabSiteId, testUser, SITE_MANAGER);
|
siteService.setMembership(collabSiteId, testUser, SITE_MANAGER);
|
||||||
securityClearanceService.setUserSecurityClearance(testUser, LEVEL1);
|
securityClearanceService.setUserSecurityClearance(testUser, TOP_SECRET_ID);
|
||||||
|
|
||||||
folder = fileFolderService.create(documentLibrary, generate(), TYPE_FOLDER).getNodeRef();
|
folder = fileFolderService.create(documentLibrary, generate(), TYPE_FOLDER).getNodeRef();
|
||||||
doc1 = fileFolderService.create(folder, searchQuery + generate(), TYPE_CONTENT).getNodeRef();
|
doc1 = fileFolderService.create(folder, searchQuery + generate(), TYPE_CONTENT).getNodeRef();
|
||||||
|
@@ -160,7 +160,7 @@ public class RecordBrowseClassificationEnforcementTest extends BrowseClassificat
|
|||||||
testUser = generate();
|
testUser = generate();
|
||||||
createPerson(testUser);
|
createPerson(testUser);
|
||||||
filePlanRoleService.assignRoleToAuthority(filePlan, ROLE_ADMIN, testUser);
|
filePlanRoleService.assignRoleToAuthority(filePlan, ROLE_ADMIN, testUser);
|
||||||
securityClearanceService.setUserSecurityClearance(testUser, LEVEL2);
|
securityClearanceService.setUserSecurityClearance(testUser, SECRET_ID);
|
||||||
|
|
||||||
category = filePlanService.createRecordCategory(filePlan, generate());
|
category = filePlanService.createRecordCategory(filePlan, generate());
|
||||||
folder = recordFolderService.createRecordFolder(category, generate());
|
folder = recordFolderService.createRecordFolder(category, generate());
|
||||||
@@ -258,7 +258,7 @@ public class RecordBrowseClassificationEnforcementTest extends BrowseClassificat
|
|||||||
testUser = generate();
|
testUser = generate();
|
||||||
createPerson(testUser);
|
createPerson(testUser);
|
||||||
filePlanRoleService.assignRoleToAuthority(filePlan, ROLE_ADMIN, testUser);
|
filePlanRoleService.assignRoleToAuthority(filePlan, ROLE_ADMIN, testUser);
|
||||||
securityClearanceService.setUserSecurityClearance(testUser, LEVEL1);
|
securityClearanceService.setUserSecurityClearance(testUser, TOP_SECRET_ID);
|
||||||
|
|
||||||
category = filePlanService.createRecordCategory(filePlan, generate());
|
category = filePlanService.createRecordCategory(filePlan, generate());
|
||||||
folder = recordFolderService.createRecordFolder(category, generate());
|
folder = recordFolderService.createRecordFolder(category, generate());
|
||||||
|
@@ -256,7 +256,7 @@ public class RecordSearchClassificationEnforcementTest extends SearchClassificat
|
|||||||
testUser = generate();
|
testUser = generate();
|
||||||
createPerson(testUser);
|
createPerson(testUser);
|
||||||
filePlanRoleService.assignRoleToAuthority(filePlan, ROLE_ADMIN, testUser);
|
filePlanRoleService.assignRoleToAuthority(filePlan, ROLE_ADMIN, testUser);
|
||||||
securityClearanceService.setUserSecurityClearance(testUser, LEVEL1);
|
securityClearanceService.setUserSecurityClearance(testUser, TOP_SECRET_ID);
|
||||||
|
|
||||||
category = filePlanService.createRecordCategory(filePlan, generate());
|
category = filePlanService.createRecordCategory(filePlan, generate());
|
||||||
folder = recordFolderService.createRecordFolder(category, generate());
|
folder = recordFolderService.createRecordFolder(category, generate());
|
||||||
|
@@ -40,8 +40,8 @@ import org.alfresco.service.cmr.repository.NodeRef;
|
|||||||
*/
|
*/
|
||||||
public class RelationshipClassificationEnforcementTest extends BaseRMTestCase
|
public class RelationshipClassificationEnforcementTest extends BaseRMTestCase
|
||||||
{
|
{
|
||||||
private static final String LEVEL1 = "level1";
|
private static final String TOP_SECRET_ID = "TS";
|
||||||
private static final String LEVEL3 = "level3";
|
private static final String CONFIDENTIAL_ID = "C";
|
||||||
private static final String REASON = "Test Reason 1";
|
private static final String REASON = "Test Reason 1";
|
||||||
private ClassificationAspectProperties propertiesDTO;
|
private ClassificationAspectProperties propertiesDTO;
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ public class RelationshipClassificationEnforcementTest extends BaseRMTestCase
|
|||||||
{
|
{
|
||||||
super.setUp();
|
super.setUp();
|
||||||
propertiesDTO = new ClassificationAspectProperties();
|
propertiesDTO = new ClassificationAspectProperties();
|
||||||
propertiesDTO.setClassificationLevelId(LEVEL1);
|
propertiesDTO.setClassificationLevelId(TOP_SECRET_ID);
|
||||||
propertiesDTO.setClassifiedBy(generate());
|
propertiesDTO.setClassifiedBy(generate());
|
||||||
propertiesDTO.setClassificationAgency(generate());
|
propertiesDTO.setClassificationAgency(generate());
|
||||||
propertiesDTO.setClassificationReasonIds(Collections.singleton(REASON));
|
propertiesDTO.setClassificationReasonIds(Collections.singleton(REASON));
|
||||||
@@ -64,8 +64,8 @@ public class RelationshipClassificationEnforcementTest extends BaseRMTestCase
|
|||||||
* and a category, a folder and two records have been created
|
* and a category, a folder and two records have been created
|
||||||
*
|
*
|
||||||
* When the user has been granted filing permissions
|
* When the user has been granted filing permissions
|
||||||
* and the clearance level 3 for the test user has been set
|
* and confidential clearance for the test user has been set
|
||||||
* and one of the records has been classified as level 1
|
* and one of the records has been classified as top secret
|
||||||
* and a relationship between those two records has been created
|
* and a relationship between those two records has been created
|
||||||
*
|
*
|
||||||
* Then the admin user should see both records in the folder
|
* Then the admin user should see both records in the folder
|
||||||
@@ -106,7 +106,7 @@ public class RelationshipClassificationEnforcementTest extends BaseRMTestCase
|
|||||||
public void when() throws Exception
|
public void when() throws Exception
|
||||||
{
|
{
|
||||||
filePlanPermissionService.setPermission(category, myUser, FILING);
|
filePlanPermissionService.setPermission(category, myUser, FILING);
|
||||||
securityClearanceService.setUserSecurityClearance(myUser, LEVEL3);
|
securityClearanceService.setUserSecurityClearance(myUser, CONFIDENTIAL_ID);
|
||||||
contentClassificationService.classifyContent(propertiesDTO, record1);
|
contentClassificationService.classifyContent(propertiesDTO, record1);
|
||||||
relationshipService.addRelationship(CUSTOM_REF_RENDITION.getLocalName(), record1, record2);
|
relationshipService.addRelationship(CUSTOM_REF_RENDITION.getLocalName(), record1, record2);
|
||||||
}
|
}
|
||||||
|
@@ -81,7 +81,7 @@ public class SavedSearchClassificationEnforcementTest extends SearchClassificati
|
|||||||
testUser = generate();
|
testUser = generate();
|
||||||
createPerson(testUser);
|
createPerson(testUser);
|
||||||
filePlanRoleService.assignRoleToAuthority(filePlan, ROLE_ADMIN, testUser);
|
filePlanRoleService.assignRoleToAuthority(filePlan, ROLE_ADMIN, testUser);
|
||||||
securityClearanceService.setUserSecurityClearance(testUser, LEVEL2);
|
securityClearanceService.setUserSecurityClearance(testUser, SECRET_ID);
|
||||||
|
|
||||||
category = filePlanService.createRecordCategory(filePlan, generate());
|
category = filePlanService.createRecordCategory(filePlan, generate());
|
||||||
folder = recordFolderService.createRecordFolder(category, generate());
|
folder = recordFolderService.createRecordFolder(category, generate());
|
||||||
|
@@ -37,12 +37,12 @@ import org.alfresco.service.cmr.repository.NodeRef;
|
|||||||
public abstract class SearchClassificationEnforcementTestBase extends BaseRMTestCase
|
public abstract class SearchClassificationEnforcementTestBase extends BaseRMTestCase
|
||||||
{
|
{
|
||||||
protected String testUser;
|
protected String testUser;
|
||||||
protected static final String LEVEL1 = "level1";
|
protected static final String TOP_SECRET_ID = "TS";
|
||||||
protected static final String LEVEL2 = "level2";
|
protected static final String SECRET_ID = "S";
|
||||||
protected static final String REASON = "Test Reason 1";
|
protected static final String REASON = "Test Reason 1";
|
||||||
/** Classified properties for classification level 1. */
|
/** Classified properties for top secret. */
|
||||||
protected ClassificationAspectProperties propertiesDTO1;
|
protected ClassificationAspectProperties propertiesDTO1;
|
||||||
/** Classified properties for classification level 2. */
|
/** Classified properties for secret. */
|
||||||
protected ClassificationAspectProperties propertiesDTO2;
|
protected ClassificationAspectProperties propertiesDTO2;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -50,12 +50,12 @@ public abstract class SearchClassificationEnforcementTestBase extends BaseRMTest
|
|||||||
{
|
{
|
||||||
super.setUp();
|
super.setUp();
|
||||||
propertiesDTO1 = new ClassificationAspectProperties();
|
propertiesDTO1 = new ClassificationAspectProperties();
|
||||||
propertiesDTO1.setClassificationLevelId(LEVEL1);
|
propertiesDTO1.setClassificationLevelId(TOP_SECRET_ID);
|
||||||
propertiesDTO1.setClassifiedBy(generate());
|
propertiesDTO1.setClassifiedBy(generate());
|
||||||
propertiesDTO1.setClassificationAgency(generate());
|
propertiesDTO1.setClassificationAgency(generate());
|
||||||
propertiesDTO1.setClassificationReasonIds(Collections.singleton(REASON));
|
propertiesDTO1.setClassificationReasonIds(Collections.singleton(REASON));
|
||||||
propertiesDTO2 = new ClassificationAspectProperties();
|
propertiesDTO2 = new ClassificationAspectProperties();
|
||||||
propertiesDTO2.setClassificationLevelId(LEVEL2);
|
propertiesDTO2.setClassificationLevelId(SECRET_ID);
|
||||||
propertiesDTO2.setClassifiedBy(generate());
|
propertiesDTO2.setClassifiedBy(generate());
|
||||||
propertiesDTO2.setClassificationAgency(generate());
|
propertiesDTO2.setClassificationAgency(generate());
|
||||||
propertiesDTO2.setClassificationReasonIds(Collections.singleton(REASON));
|
propertiesDTO2.setClassificationReasonIds(Collections.singleton(REASON));
|
||||||
|
@@ -440,7 +440,7 @@ public class DestroyContentTest extends BaseRMTestCase
|
|||||||
|
|
||||||
// classify the content
|
// classify the content
|
||||||
ClassificationAspectProperties properties = new ClassificationAspectProperties();
|
ClassificationAspectProperties properties = new ClassificationAspectProperties();
|
||||||
properties.setClassificationLevelId("level1");
|
properties.setClassificationLevelId("TS");
|
||||||
properties.setClassifiedBy("me");
|
properties.setClassifiedBy("me");
|
||||||
properties.setClassificationReasonIds(Collections.singleton("Test Reason 1"));
|
properties.setClassificationReasonIds(Collections.singleton("Test Reason 1"));
|
||||||
contentClassificationService.classifyContent(properties, deleteableContent);
|
contentClassificationService.classifyContent(properties, deleteableContent);
|
||||||
@@ -505,7 +505,7 @@ public class DestroyContentTest extends BaseRMTestCase
|
|||||||
|
|
||||||
// classify the content
|
// classify the content
|
||||||
ClassificationAspectProperties properties = new ClassificationAspectProperties();
|
ClassificationAspectProperties properties = new ClassificationAspectProperties();
|
||||||
properties.setClassificationLevelId("level1");
|
properties.setClassificationLevelId("TS");
|
||||||
properties.setClassifiedBy("me");
|
properties.setClassifiedBy("me");
|
||||||
properties.setClassificationReasonIds(Collections.singleton("Test Reason 1"));
|
properties.setClassificationReasonIds(Collections.singleton("Test Reason 1"));
|
||||||
contentClassificationService.classifyContent(properties, deleteableContent);
|
contentClassificationService.classifyContent(properties, deleteableContent);
|
||||||
|
@@ -35,7 +35,7 @@ import org.alfresco.service.cmr.repository.NodeRef;
|
|||||||
*/
|
*/
|
||||||
public class RM2260Test extends BaseRMTestCase
|
public class RM2260Test extends BaseRMTestCase
|
||||||
{
|
{
|
||||||
private static final String LEVEL = "level1";
|
private static final String LEVEL = "TS";
|
||||||
private static final String REASON = "Test Reason 1";
|
private static final String REASON = "Test Reason 1";
|
||||||
private ClassificationAspectProperties propertiesDTO;
|
private ClassificationAspectProperties propertiesDTO;
|
||||||
|
|
||||||
|
@@ -39,15 +39,15 @@ import org.json.JSONObject;
|
|||||||
*/
|
*/
|
||||||
public class JSONConversionComponentTest extends BaseRMTestCase
|
public class JSONConversionComponentTest extends BaseRMTestCase
|
||||||
{
|
{
|
||||||
private static final String LEVEL1 = "level1";
|
private static final String TOP_SECRET_ID = "TS";
|
||||||
private static final String REASON1 = "Test Reason 1";
|
private static final String REASON1 = "Test Reason 1";
|
||||||
|
|
||||||
private JSONConversionComponent converter;
|
private JSONConversionComponent converter;
|
||||||
private ContentClassificationService contentClassificationService;
|
private ContentClassificationService contentClassificationService;
|
||||||
|
|
||||||
private NodeRef record;
|
private NodeRef record;
|
||||||
/** Classification properties for classification level 1. */
|
/** Classification properties for top secret classification. */
|
||||||
private ClassificationAspectProperties level1PropertiesDTO;
|
private ClassificationAspectProperties topSecretPropertiesDTO;
|
||||||
/** Classification properties for unclassified content. */
|
/** Classification properties for unclassified content. */
|
||||||
private ClassificationAspectProperties unclassifiedPropertiesDTO;
|
private ClassificationAspectProperties unclassifiedPropertiesDTO;
|
||||||
|
|
||||||
@@ -55,11 +55,11 @@ public class JSONConversionComponentTest extends BaseRMTestCase
|
|||||||
public void setUp() throws Exception
|
public void setUp() throws Exception
|
||||||
{
|
{
|
||||||
super.setUp();
|
super.setUp();
|
||||||
level1PropertiesDTO = new ClassificationAspectProperties();
|
topSecretPropertiesDTO = new ClassificationAspectProperties();
|
||||||
level1PropertiesDTO.setClassificationLevelId(LEVEL1);
|
topSecretPropertiesDTO.setClassificationLevelId(TOP_SECRET_ID);
|
||||||
level1PropertiesDTO.setClassifiedBy(generate());
|
topSecretPropertiesDTO.setClassifiedBy(generate());
|
||||||
level1PropertiesDTO.setClassificationAgency(generate());
|
topSecretPropertiesDTO.setClassificationAgency(generate());
|
||||||
level1PropertiesDTO.setClassificationReasonIds(Collections.singleton(REASON1));
|
topSecretPropertiesDTO.setClassificationReasonIds(Collections.singleton(REASON1));
|
||||||
unclassifiedPropertiesDTO = new ClassificationAspectProperties();
|
unclassifiedPropertiesDTO = new ClassificationAspectProperties();
|
||||||
unclassifiedPropertiesDTO.setClassificationLevelId(UNCLASSIFIED_ID);
|
unclassifiedPropertiesDTO.setClassificationLevelId(UNCLASSIFIED_ID);
|
||||||
unclassifiedPropertiesDTO.setClassifiedBy(generate());
|
unclassifiedPropertiesDTO.setClassifiedBy(generate());
|
||||||
@@ -113,7 +113,7 @@ public class JSONConversionComponentTest extends BaseRMTestCase
|
|||||||
@Override
|
@Override
|
||||||
public void when() throws Exception
|
public void when() throws Exception
|
||||||
{
|
{
|
||||||
contentClassificationService.classifyContent(level1PropertiesDTO, record);
|
contentClassificationService.classifyContent(topSecretPropertiesDTO, record);
|
||||||
jsonString = converter.toJSON(record, true);
|
jsonString = converter.toJSON(record, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +227,7 @@ public class JSONConversionComponentTest extends BaseRMTestCase
|
|||||||
@Override
|
@Override
|
||||||
public void when() throws Exception
|
public void when() throws Exception
|
||||||
{
|
{
|
||||||
contentClassificationService.classifyContent(level1PropertiesDTO, file);
|
contentClassificationService.classifyContent(topSecretPropertiesDTO, file);
|
||||||
jsonString = converter.toJSON(file, true);
|
jsonString = converter.toJSON(file, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -86,8 +86,8 @@ public class ClassificationRestApiTest extends BaseRMWebScriptTestCase
|
|||||||
|
|
||||||
/** Constants for classification request body parameters */
|
/** Constants for classification request body parameters */
|
||||||
private static final String ID = "id";
|
private static final String ID = "id";
|
||||||
private static final String CLASSIFICATION_LEVEL_ID1_VALUE = "level1";
|
private static final String TOP_SECRET_ID = "TS";
|
||||||
private static final String CLASSIFICATION_LEVEL_ID2_VALUE = "level2";
|
private static final String SECRET_ID = "S";
|
||||||
private static final String CLASSIFIED_BY1 = generate();
|
private static final String CLASSIFIED_BY1 = generate();
|
||||||
private static final String CLASSIFIED_BY2 = generate();
|
private static final String CLASSIFIED_BY2 = generate();
|
||||||
private static final String CLASSIFICATION_AGENCY1 = generate();
|
private static final String CLASSIFICATION_AGENCY1 = generate();
|
||||||
@@ -123,7 +123,7 @@ public class ClassificationRestApiTest extends BaseRMWebScriptTestCase
|
|||||||
|
|
||||||
// Classify content
|
// Classify content
|
||||||
JSONObject requestBody = new JSONObject();
|
JSONObject requestBody = new JSONObject();
|
||||||
requestBody.put(CLASSIFICATION_LEVEL_ID, CLASSIFICATION_LEVEL_ID1_VALUE);
|
requestBody.put(CLASSIFICATION_LEVEL_ID, TOP_SECRET_ID);
|
||||||
requestBody.put(CLASSIFIED_BY, CLASSIFIED_BY1);
|
requestBody.put(CLASSIFIED_BY, CLASSIFIED_BY1);
|
||||||
requestBody.put(CLASSIFICATION_AGENCY, CLASSIFICATION_AGENCY1);
|
requestBody.put(CLASSIFICATION_AGENCY, CLASSIFICATION_AGENCY1);
|
||||||
JSONArray classificationReasons = new JSONArray();
|
JSONArray classificationReasons = new JSONArray();
|
||||||
@@ -142,7 +142,7 @@ public class ClassificationRestApiTest extends BaseRMWebScriptTestCase
|
|||||||
|
|
||||||
assertNotNull(responseAsJson);
|
assertNotNull(responseAsJson);
|
||||||
assertTrue(responseAsJson.getBoolean(RESPONSE_SUCCESS));
|
assertTrue(responseAsJson.getBoolean(RESPONSE_SUCCESS));
|
||||||
assertEquals(CLASSIFICATION_LEVEL_ID1_VALUE, nodeService.getProperty(record, PROP_CURRENT_CLASSIFICATION));
|
assertEquals(TOP_SECRET_ID, nodeService.getProperty(record, PROP_CURRENT_CLASSIFICATION));
|
||||||
assertEquals(CLASSIFIED_BY1, nodeService.getProperty(record, PROP_CLASSIFIED_BY));
|
assertEquals(CLASSIFIED_BY1, nodeService.getProperty(record, PROP_CLASSIFIED_BY));
|
||||||
assertEquals(CLASSIFICATION_AGENCY1, nodeService.getProperty(record, PROP_CLASSIFICATION_AGENCY));
|
assertEquals(CLASSIFICATION_AGENCY1, nodeService.getProperty(record, PROP_CLASSIFICATION_AGENCY));
|
||||||
List<String> classificationReasonsList = (List<String>) nodeService.getProperty(record, PROP_CLASSIFICATION_REASONS);
|
List<String> classificationReasonsList = (List<String>) nodeService.getProperty(record, PROP_CLASSIFICATION_REASONS);
|
||||||
@@ -160,7 +160,7 @@ public class ClassificationRestApiTest extends BaseRMWebScriptTestCase
|
|||||||
|
|
||||||
// Edit classified content
|
// Edit classified content
|
||||||
requestBody = new JSONObject();
|
requestBody = new JSONObject();
|
||||||
requestBody.put(CLASSIFICATION_LEVEL_ID, CLASSIFICATION_LEVEL_ID2_VALUE);
|
requestBody.put(CLASSIFICATION_LEVEL_ID, SECRET_ID);
|
||||||
requestBody.put(CLASSIFIED_BY, CLASSIFIED_BY2);
|
requestBody.put(CLASSIFIED_BY, CLASSIFIED_BY2);
|
||||||
requestBody.put(CLASSIFICATION_AGENCY, CLASSIFICATION_AGENCY2);
|
requestBody.put(CLASSIFICATION_AGENCY, CLASSIFICATION_AGENCY2);
|
||||||
classificationReasons = new JSONArray();
|
classificationReasons = new JSONArray();
|
||||||
@@ -174,7 +174,7 @@ public class ClassificationRestApiTest extends BaseRMWebScriptTestCase
|
|||||||
|
|
||||||
assertNotNull(responseAsJson);
|
assertNotNull(responseAsJson);
|
||||||
assertTrue(responseAsJson.getBoolean(RESPONSE_SUCCESS));
|
assertTrue(responseAsJson.getBoolean(RESPONSE_SUCCESS));
|
||||||
assertEquals(CLASSIFICATION_LEVEL_ID2_VALUE, nodeService.getProperty(record, PROP_CURRENT_CLASSIFICATION));
|
assertEquals(SECRET_ID, nodeService.getProperty(record, PROP_CURRENT_CLASSIFICATION));
|
||||||
assertEquals(CLASSIFIED_BY2, nodeService.getProperty(record, PROP_CLASSIFIED_BY));
|
assertEquals(CLASSIFIED_BY2, nodeService.getProperty(record, PROP_CLASSIFIED_BY));
|
||||||
assertEquals(CLASSIFICATION_AGENCY2, nodeService.getProperty(record, PROP_CLASSIFICATION_AGENCY));
|
assertEquals(CLASSIFICATION_AGENCY2, nodeService.getProperty(record, PROP_CLASSIFICATION_AGENCY));
|
||||||
List<String> editedClassificationReasonsList = (List<String>) nodeService.getProperty(record, PROP_CLASSIFICATION_REASONS);
|
List<String> editedClassificationReasonsList = (List<String>) nodeService.getProperty(record, PROP_CLASSIFICATION_REASONS);
|
||||||
@@ -206,7 +206,7 @@ public class ClassificationRestApiTest extends BaseRMWebScriptTestCase
|
|||||||
|
|
||||||
// Classify content
|
// Classify content
|
||||||
JSONObject requestBody = new JSONObject();
|
JSONObject requestBody = new JSONObject();
|
||||||
requestBody.put(CLASSIFICATION_LEVEL_ID, CLASSIFICATION_LEVEL_ID1_VALUE);
|
requestBody.put(CLASSIFICATION_LEVEL_ID, TOP_SECRET_ID);
|
||||||
requestBody.put(CLASSIFIED_BY, CLASSIFIED_BY1);
|
requestBody.put(CLASSIFIED_BY, CLASSIFIED_BY1);
|
||||||
requestBody.put(CLASSIFICATION_AGENCY, CLASSIFICATION_AGENCY1);
|
requestBody.put(CLASSIFICATION_AGENCY, CLASSIFICATION_AGENCY1);
|
||||||
JSONArray classificationReasons = new JSONArray();
|
JSONArray classificationReasons = new JSONArray();
|
||||||
|
@@ -1,13 +0,0 @@
|
|||||||
[{
|
|
||||||
"name" : "level1",
|
|
||||||
"displayLabel" : "rm.classification.level1"
|
|
||||||
},{
|
|
||||||
"name" : "level2",
|
|
||||||
"displayLabel" : "rm.classification.level2"
|
|
||||||
},{
|
|
||||||
"name" : "level3",
|
|
||||||
"displayLabel" : "rm.classification.level3"
|
|
||||||
},{
|
|
||||||
"name" : "level4",
|
|
||||||
"displayLabel" : "rm.classification.level4"
|
|
||||||
}]
|
|
@@ -1,5 +1 @@
|
|||||||
test.company=Alfresco
|
test.company=Alfresco
|
||||||
|
|
||||||
#Classification levels
|
|
||||||
rm.classification.level1=Level 1
|
|
||||||
rm.classification.level4=Level 4
|
|
@@ -18,8 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.module.org_alfresco_module_rm.classification;
|
package org.alfresco.module.org_alfresco_module_rm.classification;
|
||||||
|
|
||||||
import static org.alfresco.module.org_alfresco_module_rm.classification.ClassificationSchemeServiceImplUnitTest.asLevelList;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
@@ -36,34 +34,6 @@ import org.junit.Test;
|
|||||||
*/
|
*/
|
||||||
public class ClassificationServiceDAOUnitTest
|
public class ClassificationServiceDAOUnitTest
|
||||||
{
|
{
|
||||||
private static final List<ClassificationLevel> DEFAULT_CLASSIFICATION_LEVELS = asLevelList("level1", "l1",
|
|
||||||
"level2", "l2",
|
|
||||||
"level3", "l3",
|
|
||||||
"level4", "l4");
|
|
||||||
|
|
||||||
@Test public void getConfiguredLevels_readingDefaultConfigurationShouldWork()
|
|
||||||
{
|
|
||||||
ClassificationServiceDAO c = new ClassificationServiceDAO();
|
|
||||||
c.setLevelConfigLocation("/alfresco/module/org_alfresco_module_rm/classification/rm-classification-levels.json");
|
|
||||||
List<ClassificationLevel> config = c.getConfiguredValues(ClassificationLevel.class);
|
|
||||||
assertEquals(DEFAULT_CLASSIFICATION_LEVELS, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void getConfiguredLevels_readingMissingConfigurationShouldProduceEmptyConfig() throws Exception
|
|
||||||
{
|
|
||||||
ClassificationServiceDAO c = new ClassificationServiceDAO();
|
|
||||||
c.setLevelConfigLocation("/no/such/resource");
|
|
||||||
assertTrue(c.getConfiguredValues(ClassificationLevel.class).isEmpty());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test (expected = MalformedConfiguration.class)
|
|
||||||
public void getConfiguredLevels_readingMalformedConfigurationShouldFail()
|
|
||||||
{
|
|
||||||
ClassificationServiceDAO c = new ClassificationServiceDAO();
|
|
||||||
c.setLevelConfigLocation("/alfresco/classification/rm-classification-levels-malformed.json");
|
|
||||||
c.getConfiguredValues(ClassificationLevel.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test public void getConfiguredReasons_readingDefaultConfigurationShouldWork()
|
@Test public void getConfiguredReasons_readingDefaultConfigurationShouldWork()
|
||||||
{
|
{
|
||||||
ClassificationServiceDAO c = new ClassificationServiceDAO();
|
ClassificationServiceDAO c = new ClassificationServiceDAO();
|
||||||
@@ -83,7 +53,7 @@ public class ClassificationServiceDAOUnitTest
|
|||||||
public void getConfiguredReasons_readingMalformedConfigurationShouldFail()
|
public void getConfiguredReasons_readingMalformedConfigurationShouldFail()
|
||||||
{
|
{
|
||||||
ClassificationServiceDAO c = new ClassificationServiceDAO();
|
ClassificationServiceDAO c = new ClassificationServiceDAO();
|
||||||
c.setReasonConfigLocation("/alfresco/classification/rm-classification-levels-malformed.json");
|
c.setReasonConfigLocation("/alfresco/classification/rm-classification-reasons-malformed.json");
|
||||||
c.getConfiguredValues(ClassificationReason.class);
|
c.getConfiguredValues(ClassificationReason.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"name" : "TopSecret",
|
|
||||||
"displayLabel" : "Top Secret"
|
|
||||||
}, { {
|
|
||||||
]
|
|
@@ -0,0 +1,6 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id" : "1.4(a)",
|
||||||
|
"displayLabel" : "rm.classification-reason.14a"
|
||||||
|
}, { {
|
||||||
|
]
|
Reference in New Issue
Block a user