diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/classified-content-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/classified-content-context.xml
index d83ff155e3..1dcf24b9eb 100644
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/classified-content-context.xml
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/classified-content-context.xml
@@ -96,4 +96,51 @@
+
+
+
+
+
+
+
+
+
+
+ org.alfresco.module.org_alfresco_module_rm.classification.SecurityClearanceService
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${server.transaction.mode.default}
+
+
+
+
+
+
+
+
+ org.alfresco.module.org_alfresco_module_rm.classification.SecurityClearanceService.getUserSecurityClearance=ACL_ALLOW
+ org.alfresco.module.org_alfresco_module_rm.classification.SecurityClearanceService.getUsersSecurityClearance=ACL_ALLOW
+ org.alfresco.module.org_alfresco_module_rm.classification.SecurityClearanceService.*=ACL_DENY
+
+
+
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/model/classifiedContentModel.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/model/classifiedContentModel.xml
index b771569c64..372fb3e659 100644
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/model/classifiedContentModel.xml
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/model/classifiedContentModel.xml
@@ -26,7 +26,8 @@
-
+
@@ -66,11 +67,31 @@
Classification Reasons
- Holds the id's of classification reasons
+ Holds the ids of classification reasons
d:text
true
+
+
+
+
+
+ Security Clearance
+ The security clearance for this user
+ d:text
+ true
+ true
+ false
+ NoClearance
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ClassificationService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ClassificationService.java
index 553b165906..b2beb8b45f 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ClassificationService.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ClassificationService.java
@@ -67,6 +67,11 @@ public interface ClassificationService
Set classificationReasonIds, NodeRef content) throws LevelIdNotFound, ReasonIdNotFound,
InvalidNodeRefException, InvalidNode;
+ /**
+ * Gets the default {@link ClassificationLevel}, which will usually be the level with the lowest security clearance.
+ */
+ ClassificationLevel getDefaultClassificationLevel();
+
/**
* Gets the classification level for the given classification level id
*
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ClassificationServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ClassificationServiceImpl.java
index 075b298142..8deca04cb5 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ClassificationServiceImpl.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ClassificationServiceImpl.java
@@ -267,6 +267,12 @@ public class ClassificationServiceImpl extends ServiceBaseImpl
nodeService.addAspect(content, ASPECT_CLASSIFIED, properties);
}
+ @Override public ClassificationLevel getDefaultClassificationLevel()
+ {
+ List classificationLevels = getClassificationLevels();
+ return classificationLevels.isEmpty() ? null : classificationLevels.get(classificationLevels.size() - 1);
+ }
+
/**
* @see org.alfresco.module.org_alfresco_module_rm.classification.ClassificationService#getClassificationLevelById(java.lang.String)
*/
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/SecurityClearanceService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/SecurityClearanceService.java
new file mode 100644
index 0000000000..0eb97b581d
--- /dev/null
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/SecurityClearanceService.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2005-2015 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+package org.alfresco.module.org_alfresco_module_rm.classification;
+
+import org.alfresco.query.PagingRequest;
+import org.alfresco.query.PagingResults;
+import org.alfresco.service.cmr.security.NoSuchPersonException;
+import org.alfresco.service.cmr.security.PersonService.PersonInfo;
+import org.alfresco.util.Pair;
+
+/**
+ * This service offers access to users' security clearance levels.
+ *
+ * @author Neil Mc Erlean
+ * @since 3.0
+ */
+public interface SecurityClearanceService
+{
+ /**
+ * Get the currently authenticated user's security clearance.
+ *
+ * @return a {@link PersonInfo}, {@link ClassificationLevel} pair for the currently authenticated user.
+ * @throws NoSuchPersonException if the current user's person node cannot be found.
+ */
+ Pair getUserSecurityClearance();
+
+ /**
+ * Get users' security clearances.
+ *
+ * @param userNameFragment A username fragment which will be used to apply a 'starts with' query.
+ * @param sortAscending if @code true} returns data sorted in ascending order by username.
+ * @param req paging request definition.
+ * @return {@link PersonInfo}, {@link ClassificationLevel} pairs for the specified page of users.
+ */
+ PagingResults> getUsersSecurityClearance(String userNameFragment,
+ boolean sortAscending,
+ PagingRequest req);
+}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/SecurityClearanceServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/SecurityClearanceServiceImpl.java
new file mode 100644
index 0000000000..9a240dfbbe
--- /dev/null
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/SecurityClearanceServiceImpl.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2005-2015 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+package org.alfresco.module.org_alfresco_module_rm.classification;
+
+import static java.util.Arrays.asList;
+import static org.alfresco.model.ContentModel.PROP_FIRSTNAME;
+import static org.alfresco.model.ContentModel.PROP_LASTNAME;
+import static org.alfresco.model.ContentModel.PROP_USERNAME;
+import static org.alfresco.module.org_alfresco_module_rm.classification.model.ClassifiedContentModel.ASPECT_SECURITY_CLEARANCE;
+import static org.alfresco.module.org_alfresco_module_rm.classification.model.ClassifiedContentModel.PROP_CLEARANCE_LEVEL;
+
+import org.alfresco.module.org_alfresco_module_rm.util.AuthenticationUtil;
+import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl;
+import org.alfresco.query.PagingRequest;
+import org.alfresco.query.PagingResults;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.security.PersonService;
+import org.alfresco.service.cmr.security.PersonService.PersonInfo;
+import org.alfresco.service.namespace.QName;
+import org.alfresco.util.Pair;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * @author Neil Mc Erlean
+ * @since 3.0
+ */
+public class SecurityClearanceServiceImpl extends ServiceBaseImpl implements SecurityClearanceService
+{
+ private ClassificationService classificationService;
+ private PersonService personService;
+
+ public void setClassificationService(ClassificationService service) { this.classificationService = service; }
+ public void setPersonService (PersonService service) { this.personService = service; }
+
+ public Pair getUserSecurityClearance()
+ {
+ final String currentUser = authenticationUtil.getFullyAuthenticatedUser();
+ Objects.requireNonNull(currentUser, "Fully authenticated user is null, which is not allowed.");
+
+ return getUserSecurityClearance(currentUser);
+ }
+
+ private Pair getUserSecurityClearance(final String userName)
+ {
+ final NodeRef personNode = personService.getPerson(userName, false);
+ final PersonInfo personInfo = personService.getPerson(personNode);
+
+ final ClassificationLevel classificationLevel;
+
+ if (nodeService.hasAspect(personNode, ASPECT_SECURITY_CLEARANCE))
+ {
+ final String clearanceLevel = (String)nodeService.getProperty(personNode, PROP_CLEARANCE_LEVEL);
+ // TODO Should we fall back to a default here or give an error?
+ classificationLevel = clearanceLevel == null ? classificationService.getDefaultClassificationLevel() :
+ classificationService.getClassificationLevelById(clearanceLevel);
+ }
+ else { classificationLevel = classificationService.getDefaultClassificationLevel(); }
+
+ return new Pair<>(personInfo, classificationLevel);
+ }
+
+ public PagingResults> getUsersSecurityClearance(String userNameFragment,
+ boolean sortAscending,
+ PagingRequest req)
+ {
+ final List filterProps = asList(PROP_USERNAME, PROP_FIRSTNAME, PROP_LASTNAME);
+ final List> sortProps = asList(new Pair<>(PROP_USERNAME, sortAscending));
+
+ final PagingResults p = personService.getPeople(userNameFragment, filterProps, sortProps, req);
+
+ return new PagingResults>()
+ {
+ @Override public List> getPage()
+ {
+ List> pcPage= new ArrayList<>(p.getPage().size());
+ for (PersonInfo pi : p.getPage())
+ {
+ pcPage.add(getUserSecurityClearance(pi.getUserName()));
+ }
+ return pcPage;
+ }
+
+ @Override public boolean hasMoreItems() { return p.hasMoreItems(); }
+ @Override public Pair getTotalResultCount() { return p.getTotalResultCount(); }
+ @Override public String getQueryExecutionId() { return p.getQueryExecutionId(); }
+ };
+ }
+}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/model/ClassifiedContentModel.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/model/ClassifiedContentModel.java
index a334fbea33..d463657c96 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/model/ClassifiedContentModel.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/model/ClassifiedContentModel.java
@@ -40,4 +40,8 @@ public interface ClassifiedContentModel
QName PROP_CURRENT_CLASSIFICATION = QName.createQName(CLF_URI, "currentClassification");
QName PROP_CLASSIFICATION_AUTHORITY = QName.createQName(CLF_URI, "classificationAuthority");
QName PROP_CLASSIFICATION_REASONS = QName.createQName(CLF_URI, "classificationReasons");
+
+ /** Security Clearance aspect. */
+ QName ASPECT_SECURITY_CLEARANCE = QName.createQName(CLF_URI, "securityClearance");
+ QName PROP_CLEARANCE_LEVEL = QName.createQName(CLF_URI, "clearanceLevel");
}
\ No newline at end of file
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/package-info.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/package-info.java
index 9bc85dffe2..1def2a1185 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/package-info.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/package-info.java
@@ -19,7 +19,14 @@
/**
* This package contains the various types required for the 'Classified Records' feature.
+ * Nodes within Alfresco can be given a {@link org.alfresco.module.org_alfresco_module_rm.classification.ClassificationLevel}
+ * which then restricts access to them to users having the appropriate clearance.
+ *
+ * The {@link org.alfresco.module.org_alfresco_module_rm.classification.ClassificationService} is responsible
+ * for the management of those levels and it is the
+ * {@link org.alfresco.module.org_alfresco_module_rm.classification.SecurityClearanceService} which deals
+ * wth users and their clearances.
*
* @since 3.0
*/
-package org.alfresco.module.org_alfresco_module_rm.classification;
\ No newline at end of file
+package org.alfresco.module.org_alfresco_module_rm.classification;