diff --git a/config/alfresco/authority-services-context.xml b/config/alfresco/authority-services-context.xml
index b02685ca94..e71bcd83fa 100644
--- a/config/alfresco/authority-services-context.xml
+++ b/config/alfresco/authority-services-context.xml
@@ -100,7 +100,9 @@
groups
-
+
+
+
-
\ No newline at end of file
+
diff --git a/source/java/org/alfresco/repo/security/authority/script/ScriptAuthorityService.java b/source/java/org/alfresco/repo/security/authority/script/ScriptAuthorityService.java
index b239c8735e..40dae8e200 100644
--- a/source/java/org/alfresco/repo/security/authority/script/ScriptAuthorityService.java
+++ b/source/java/org/alfresco/repo/security/authority/script/ScriptAuthorityService.java
@@ -20,13 +20,23 @@ package org.alfresco.repo.security.authority.script;
import static org.alfresco.repo.security.authority.script.ScriptGroup.makeScriptGroups;
+import java.util.ArrayList;
import java.util.Collections;
+import java.util.List;
import java.util.Set;
+import org.alfresco.model.ContentModel;
import org.alfresco.repo.jscript.BaseScopableProcessorExtension;
import org.alfresco.repo.security.authority.UnknownAuthorityException;
+import org.alfresco.service.ServiceRegistry;
+import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.AuthorityType;
+import org.alfresco.service.cmr.security.NoSuchPersonException;
+import org.alfresco.service.cmr.security.PagingPersonResults;
+import org.alfresco.service.cmr.security.PersonService;
+import org.alfresco.service.namespace.QName;
+import org.alfresco.util.Pair;
import org.alfresco.util.ScriptPagingDetails;
/**
@@ -38,18 +48,24 @@ import org.alfresco.util.ScriptPagingDetails;
*/
public class ScriptAuthorityService extends BaseScopableProcessorExtension
{
- /** The service */
+ /** The group/authority service */
private AuthorityService authorityService;
+ /** The person service */
+ private PersonService personService;
+
+ private ServiceRegistry serviceRegistry;
- public void setAuthorityService(AuthorityService authorityService)
- {
- this.authorityService = authorityService;
- }
+ public void setServiceRegistry(ServiceRegistry serviceRegistry)
+ {
+ this.serviceRegistry = serviceRegistry;
+ this.authorityService = serviceRegistry.getAuthorityService();
+ this.personService = serviceRegistry.getPersonService();
+ }
- public AuthorityService getAuthorityService()
- {
- return authorityService;
- }
+ public AuthorityService getAuthorityService()
+ {
+ return authorityService;
+ }
/**
* Search the root groups, those without a parent group.
@@ -307,4 +323,82 @@ public class ScriptAuthorityService extends BaseScopableProcessorExtension
}
return makeScriptGroups(authorities, paging, sortBy, authorityService);
}
+
+ /**
+ * Get a user given their username
+ * @param username, the username of the user
+ * @return the user or null if they can't be found
+ */
+ public ScriptUser getUser(String username)
+ {
+ try
+ {
+ NodeRef person = personService.getPerson(username, false);
+ return new ScriptUser(username, person, serviceRegistry);
+ }
+ catch(NoSuchPersonException e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Search for users
+ * Includes paging parameters to limit size of results returned.
+ *
+ * @param nameFilter partial match of the name (username, first name, last name). If empty then matches everyone.
+ * @param paging Paging object with max number to return, and items to skip
+ * @param sortBy What to sort on (firstName, lastName or userName)
+ * @return the users matching the query
+ */
+ public ScriptUser[] searchUsers(String nameFilter, ScriptPagingDetails paging, String sortBy)
+ {
+ // Build the filter
+ List> filter = new ArrayList>();
+ filter.add(new Pair(ContentModel.PROP_FIRSTNAME, nameFilter));
+ filter.add(new Pair(ContentModel.PROP_LASTNAME, nameFilter));
+ filter.add(new Pair(ContentModel.PROP_USERNAME, nameFilter));
+
+ // Build the sorting. The user controls the primary sort, we supply
+ // additional ones automatically
+ List> sort = new ArrayList>();
+ if("lastName".equals(sortBy))
+ {
+ sort.add(new Pair(ContentModel.PROP_LASTNAME, true));
+ sort.add(new Pair(ContentModel.PROP_FIRSTNAME, true));
+ sort.add(new Pair(ContentModel.PROP_USERNAME, true));
+ }
+ else if("firstName".equals(sortBy))
+ {
+ sort.add(new Pair(ContentModel.PROP_FIRSTNAME, true));
+ sort.add(new Pair(ContentModel.PROP_LASTNAME, true));
+ sort.add(new Pair(ContentModel.PROP_USERNAME, true));
+ }
+ else
+ {
+ sort.add(new Pair(ContentModel.PROP_USERNAME, true));
+ sort.add(new Pair(ContentModel.PROP_FIRSTNAME, true));
+ sort.add(new Pair(ContentModel.PROP_LASTNAME, true));
+ }
+
+ // Do the search
+ PagingPersonResults results = personService.getPeople(filter, true, sort, paging);
+
+ // Record the size of the results
+ paging.setTotalItems(results);
+
+ // Now wrap up the users
+ List nodes = results.getPage();
+ ScriptUser[] users = new ScriptUser[nodes.size()];
+ for(int i=0; i.
+ */
+package org.alfresco.repo.security.authority.script;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.transaction.Status;
+import javax.transaction.UserTransaction;
+
+import junit.framework.TestCase;
+
+import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.domain.permissions.AclDAO;
+import org.alfresco.repo.security.authentication.AuthenticationComponent;
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.security.authentication.MutableAuthenticationDao;
+import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
+import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
+import org.alfresco.service.ServiceRegistry;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
+import org.alfresco.service.cmr.security.AuthorityService;
+import org.alfresco.service.cmr.security.AuthorityType;
+import org.alfresco.service.cmr.security.MutableAuthenticationService;
+import org.alfresco.service.cmr.security.PersonService;
+import org.alfresco.service.namespace.QName;
+import org.alfresco.service.transaction.TransactionService;
+import org.alfresco.util.ApplicationContextHelper;
+import org.alfresco.util.ScriptPagingDetails;
+import org.springframework.context.ApplicationContext;
+
+/**
+ * Tests for the Script wrapper for the Authority Service,
+ * ScriptAuthorityService
+ */
+public class ScriptAuthorityServiceTest extends TestCase
+{
+ private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
+
+ private static final String GROUP_A = "testGroupA";
+ private static final String GROUP_A_FULL = "GROUP_testGroupA";
+ private static final String GROUP_B = "testGroupB";
+ private static final String GROUP_B_FULL = "GROUP_testGroupB";
+ private static final String GROUP_C = "testGroupC";
+ private static final String GROUP_C_FULL = "GROUP_testGroupC";
+ private static final String USER_A = "testUserA";
+ private static final String USER_B = "testUserB";
+ private static final String USER_C = "testUserC";
+
+ private AuthenticationComponent authenticationComponentImpl;
+
+ private MutableAuthenticationService authenticationService;
+
+ private MutableAuthenticationDao authenticationDAO;
+
+ private AuthorityService authorityService;
+
+ private AuthorityService pubAuthorityService;
+
+ private PersonService personService;
+
+ private UserTransaction tx;
+
+ private AclDAO aclDaoComponent;
+
+ private NodeService nodeService;
+
+ private ScriptAuthorityService service;
+
+ public ScriptAuthorityServiceTest()
+ {
+ super();
+
+ }
+
+ public void setUp() throws Exception
+ {
+ if (AlfrescoTransactionSupport.getTransactionReadState() != TxnReadState.TXN_NONE)
+ {
+ throw new AlfrescoRuntimeException(
+ "A previous tests did not clean up transaction: " +
+ AlfrescoTransactionSupport.getTransactionId());
+ }
+
+ authenticationComponentImpl = (AuthenticationComponent) ctx.getBean("authenticationComponent");
+ authenticationService = (MutableAuthenticationService) ctx.getBean("authenticationService");
+ authorityService = (AuthorityService) ctx.getBean("authorityService");
+ pubAuthorityService = (AuthorityService) ctx.getBean("AuthorityService");
+ personService = (PersonService) ctx.getBean("personService");
+ authenticationDAO = (MutableAuthenticationDao) ctx.getBean("authenticationDao");
+ aclDaoComponent = (AclDAO) ctx.getBean("aclDAO");
+ nodeService = (NodeService) ctx.getBean("nodeService");
+ service = (ScriptAuthorityService) ctx.getBean("authorityServiceScript");
+
+ authenticationComponentImpl.setSystemUserAsCurrentUser();
+
+ // Clean up the users if they're already there
+ TransactionService transactionService = (TransactionService) ctx.getBean(ServiceRegistry.TRANSACTION_SERVICE.getLocalName());
+ tx = transactionService.getUserTransaction();
+ tx.begin();
+ for (String user : new String[] { USER_A, USER_B, USER_C })
+ {
+ if (personService.personExists(user))
+ {
+ NodeRef person = personService.getPerson(user);
+ NodeRef hf = DefaultTypeConverter.INSTANCE.convert(NodeRef.class, nodeService.getProperty(person, ContentModel.PROP_HOMEFOLDER));
+ if (hf != null)
+ {
+ nodeService.deleteNode(hf);
+ }
+ aclDaoComponent.deleteAccessControlEntries(user);
+ personService.deletePerson(user);
+ }
+ if (authenticationDAO.userExists(user))
+ {
+ authenticationDAO.deleteUser(user);
+ }
+ }
+
+ // And the group
+ if(authorityService.authorityExists(GROUP_A_FULL))
+ {
+ authorityService.deleteAuthority(GROUP_A_FULL);
+ }
+ if(authorityService.authorityExists(GROUP_B_FULL))
+ {
+ authorityService.deleteAuthority(GROUP_B_FULL);
+ }
+ if(authorityService.authorityExists(GROUP_C_FULL))
+ {
+ authorityService.deleteAuthority(GROUP_C_FULL);
+ }
+ tx.commit();
+
+ // Now re-create them
+ tx = transactionService.getUserTransaction();
+ tx.begin();
+
+ authorityService.createAuthority(AuthorityType.GROUP, GROUP_A);
+ authorityService.createAuthority(AuthorityType.GROUP, GROUP_B);
+ authorityService.createAuthority(AuthorityType.GROUP, GROUP_C);
+
+ for (String user : new String[] { USER_A, USER_B, USER_C })
+ {
+ if (!authenticationDAO.userExists(user))
+ {
+ authenticationService.createAuthentication(user, user.toCharArray());
+ }
+
+ Map props = new HashMap();
+ props.put(ContentModel.PROP_USERNAME, user);
+ props.put(ContentModel.PROP_FIRSTNAME, user);
+ props.put(ContentModel.PROP_LASTNAME, "Last_" + user);
+ personService.createPerson(props);
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception
+ {
+ if ((tx.getStatus() == Status.STATUS_ACTIVE) || (tx.getStatus() == Status.STATUS_MARKED_ROLLBACK))
+ {
+ tx.rollback();
+ }
+ AuthenticationUtil.clearCurrentSecurityContext();
+ super.tearDown();
+ }
+
+ public void testBasics()
+ {
+ // Should return the same count for the root groups
+ int count = pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size();
+ ScriptGroup[] groups = service.getAllRootGroups();
+ assertEquals(count, groups.length);
+
+ // And our test ones are in there
+ ScriptGroup groupA = null;
+ ScriptGroup groupB = null;
+ ScriptGroup groupC = null;
+ for(ScriptGroup group : groups)
+ {
+ if(group.getShortName().equals(GROUP_A)) groupA = group;
+ if(group.getShortName().equals(GROUP_B)) groupB = group;
+ if(group.getShortName().equals(GROUP_C)) groupC = group;
+ }
+ assertNotNull(GROUP_A + " not found in " + groups, groupA);
+ assertNotNull(GROUP_B + " not found in " + groups, groupB);
+ assertNotNull(GROUP_C + " not found in " + groups, groupC);
+
+ // Check group A in more detail
+ assertEquals(GROUP_A, groupA.getShortName());
+ assertEquals(GROUP_A, groupA.getDisplayName());
+ assertEquals(GROUP_A_FULL, groupA.getFullName());
+ }
+
+ public void testZones()
+ {
+ }
+
+ public void testFindGroups()
+ {
+
+ }
+
+ public void testGroupUsers()
+ {
+
+ }
+
+ public void testUsers()
+ {
+ // Getting by username
+ ScriptUser userA = service.getUser(USER_A);
+ ScriptUser userB = service.getUser(USER_B);
+ ScriptUser userC = service.getUser(USER_C);
+ ScriptUser userNA = service.getUser("DOESnotEXISTinTHEsystem");
+ assertNotNull(userA);
+ assertNotNull(userB);
+ assertNotNull(userC);
+ assertNull(userNA);
+
+ // Check the details on one user
+ assertEquals(USER_A, userA.getFullName());
+ assertEquals(USER_A, userA.getShortName());
+ assertEquals(USER_A, userA.getDisplayName());
+
+ NodeRef nodeA = personService.getPerson(USER_A, false);
+ assertNotNull(nodeA);
+
+ // Check the person
+ assertEquals(nodeA, userA.getPersonNodeRef());
+ assertEquals(nodeA, userA.getPerson().getNodeRef());
+ assertEquals(USER_A, userA.getPerson().getProperties().get("userName"));
+ assertEquals(USER_A, userA.getPerson().getProperties().get("firstName"));
+ }
+
+ public void testFindUsers()
+ {
+ // Try to find admin
+ ScriptUser[] users = service.searchUsers(
+ AuthenticationUtil.getAdminUserName(),
+ new ScriptPagingDetails(10, 0),
+ "userName"
+ );
+ assertTrue("Admin not found", users.length > 0);
+
+ // Try to find our test users
+ users = service.searchUsers(
+ USER_A.substring(0, USER_A.length()-1),
+ new ScriptPagingDetails(10, 0),
+ "userName"
+ );
+ assertEquals("Users count wrong " + users, 3, users.length);
+
+ // Check on the username sorting
+ assertEquals(USER_A, users[0].getPerson().getProperties().get("userName"));
+ assertEquals(USER_B, users[1].getPerson().getProperties().get("userName"));
+ assertEquals(USER_C, users[2].getPerson().getProperties().get("userName"));
+
+ // Tweak names and re-check
+ ScriptUser userA = users[0];
+ ScriptUser userB = users[1];
+ ScriptUser userC = users[2];
+ nodeService.setProperty(userB.getPersonNodeRef(), ContentModel.PROP_FIRSTNAME, "bbbbFIRST");
+ nodeService.setProperty(userC.getPersonNodeRef(), ContentModel.PROP_LASTNAME, "ccccLAST");
+
+ users = service.searchUsers(
+ USER_A.substring(0, USER_A.length()-1),
+ new ScriptPagingDetails(10, 0),
+ "userName"
+ );
+ assertEquals("Users count wrong " + users, 3, users.length);
+ assertEquals(USER_A, users[0].getPerson().getProperties().get("userName"));
+ assertEquals(USER_B, users[1].getPerson().getProperties().get("userName"));
+ assertEquals(USER_C, users[2].getPerson().getProperties().get("userName"));
+
+ // Check sorting on firstname
+ users = service.searchUsers(
+ USER_A.substring(0, USER_A.length()-1),
+ new ScriptPagingDetails(10, 0),
+ "firstName"
+ );
+ assertEquals("Users count wrong " + users, 3, users.length);
+ assertEquals(USER_B, users[0].getPerson().getProperties().get("userName"));
+ assertEquals(USER_A, users[1].getPerson().getProperties().get("userName"));
+ assertEquals(USER_C, users[2].getPerson().getProperties().get("userName"));
+
+ // And lastname
+ users = service.searchUsers(
+ USER_A.substring(0, USER_A.length()-1),
+ new ScriptPagingDetails(10, 0),
+ "lastName"
+ );
+ assertEquals("Users count wrong " + users, 3, users.length);
+ assertEquals(USER_C, users[0].getPerson().getProperties().get("userName"));
+ assertEquals(USER_A, users[1].getPerson().getProperties().get("userName"));
+ assertEquals(USER_B, users[2].getPerson().getProperties().get("userName"));
+ }
+}
diff --git a/source/java/org/alfresco/repo/security/authority/script/ScriptUser.java b/source/java/org/alfresco/repo/security/authority/script/ScriptUser.java
index 1522720239..c9142080b0 100644
--- a/source/java/org/alfresco/repo/security/authority/script/ScriptUser.java
+++ b/source/java/org/alfresco/repo/security/authority/script/ScriptUser.java
@@ -20,8 +20,10 @@ package org.alfresco.repo.security.authority.script;
import java.io.Serializable;
+import org.alfresco.repo.jscript.ScriptNode;
+import org.alfresco.service.ServiceRegistry;
+import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.AuthorityService;
-import org.alfresco.service.cmr.security.AuthorityType;
/**
* The Script user is a USER authority exposed to the scripting API
@@ -30,51 +32,104 @@ import org.alfresco.service.cmr.security.AuthorityType;
*/
public class ScriptUser implements Authority, Serializable
{
- private transient AuthorityService authorityService;
+ private static final long serialVersionUID = 7865300693011208293L;
+ private transient ServiceRegistry serviceRegistry;
+ private transient AuthorityService authorityService;
private ScriptAuthorityType authorityType = ScriptAuthorityType.USER;
+ private String userName;
private String shortName;
- private String fullName;
private String displayName;
+ private NodeRef personNodeRef;
- public ScriptUser(String fullName, AuthorityService authorityService)
+ public ScriptUser(String userName, NodeRef personNodeRef, ServiceRegistry serviceRegistry)
{
- this.authorityService = authorityService;
- this.fullName = fullName;
- shortName = authorityService.getShortName(fullName);
- displayName = authorityService.getAuthorityDisplayName(fullName);
- //isInternal = authorityService.
+ this.serviceRegistry = serviceRegistry;
+ this.authorityService = serviceRegistry.getAuthorityService();
+
+ this.personNodeRef = personNodeRef;
+ this.userName = userName;
+ shortName = authorityService.getShortName(userName);
+ displayName = authorityService.getAuthorityDisplayName(userName);
}
- public void setAuthorityType(ScriptAuthorityType authorityType) {
- this.authorityType = authorityType;
- }
+ /**
+ * @deprecated The ServiceRegistry is now needed
+ */
+ public ScriptUser(String userName, AuthorityService authorityService)
+ {
+ this.authorityService = authorityService;
+ this.userName = userName;
+ shortName = authorityService.getShortName(userName);
+ displayName = authorityService.getAuthorityDisplayName(userName);
+ }
+
+ public void setAuthorityType(ScriptAuthorityType authorityType)
+ {
+ this.authorityType = authorityType;
+ }
- public ScriptAuthorityType getAuthorityType() {
- return authorityType;
- }
+ public ScriptAuthorityType getAuthorityType()
+ {
+ return authorityType;
+ }
- public void setShortName(String shortName) {
- this.shortName = shortName;
- }
+ public void setShortName(String shortName)
+ {
+ this.shortName = shortName;
+ }
- public String getShortName() {
- return shortName;
- }
+ public String getShortName()
+ {
+ return shortName;
+ }
- public void setFullName(String fullName) {
- this.fullName = fullName;
- }
+ public void setFullName(String fullName)
+ {
+ this.userName = fullName;
+ }
- public String getFullName() {
- return fullName;
- }
+ public String getFullName()
+ {
+ return userName;
+ }
- public void setDisplayName(String displayName) {
- this.displayName = displayName;
- }
+ /**
+ * Return the User Name, also known as the
+ * Authority Full Name
+ */
+ public String getUserName()
+ {
+ return userName;
+ }
- public String getDisplayName() {
- return displayName;
- }
-
+ public void setDisplayName(String displayName)
+ {
+ this.displayName = displayName;
+ }
+
+ public String getDisplayName()
+ {
+ return displayName;
+ }
+
+ /**
+ * Return the NodeRef of the person
+ */
+ public NodeRef getPersonNodeRef()
+ {
+ if (personNodeRef == null)
+ {
+ // Lazy lookup for Authority based creation
+ personNodeRef = authorityService.getAuthorityNodeRef(userName);
+ }
+ return personNodeRef;
+ }
+
+ /**
+ * Return a ScriptNode wrapping the person
+ */
+ public ScriptNode getPerson()
+ {
+ return new ScriptNode(getPersonNodeRef(), serviceRegistry);
+ }
}
diff --git a/source/java/org/alfresco/util/ScriptPagingDetails.java b/source/java/org/alfresco/util/ScriptPagingDetails.java
index 5c0cd83e66..4f8a5498c7 100644
--- a/source/java/org/alfresco/util/ScriptPagingDetails.java
+++ b/source/java/org/alfresco/util/ScriptPagingDetails.java
@@ -82,30 +82,39 @@ public class ScriptPagingDetails extends PagingRequest
*/
public void setTotalItems(PagingResults results)
{
- Integer min = results.getTotalResultCount().getFirst();
- Integer max = results.getTotalResultCount().getSecond();
-
- // Get the total count and confidence
- if(min == null)
+ if(results.getTotalResultCount() == null)
{
+ // No count calculated
this.totalItems = -1;
this.confidence = ItemsSizeConfidence.UNKNOWN;
}
- else if(max == null)
- {
- this.totalItems = min;
- this.confidence = ItemsSizeConfidence.AT_LEAST;
- }
- else if(min == max)
- {
- this.totalItems = min;
- this.confidence = ItemsSizeConfidence.EXACT;
- }
else
{
- this.totalItems = min;
- this.totalItemsRangeMax = max;
- this.confidence = ItemsSizeConfidence.RANGE;
+ // Get the total count and confidence
+ Integer min = results.getTotalResultCount().getFirst();
+ Integer max = results.getTotalResultCount().getSecond();
+
+ if(min == null)
+ {
+ this.totalItems = -1;
+ this.confidence = ItemsSizeConfidence.UNKNOWN;
+ }
+ else if(max == null)
+ {
+ this.totalItems = min;
+ this.confidence = ItemsSizeConfidence.AT_LEAST;
+ }
+ else if(min == max)
+ {
+ this.totalItems = min;
+ this.confidence = ItemsSizeConfidence.EXACT;
+ }
+ else
+ {
+ this.totalItems = min;
+ this.totalItemsRangeMax = max;
+ this.confidence = ItemsSizeConfidence.RANGE;
+ }
}
// Finally record the query execution ID