diff --git a/config/alfresco/public-services-security-context.xml b/config/alfresco/public-services-security-context.xml index e4e50b005e..7524574253 100644 --- a/config/alfresco/public-services-security-context.xml +++ b/config/alfresco/public-services-security-context.xml @@ -1011,6 +1011,7 @@ org.alfresco.service.cmr.site.SiteService.listMembers=ACL_ALLOW org.alfresco.service.cmr.site.SiteService.listMembersInfo=ACL_ALLOW org.alfresco.service.cmr.site.SiteService.listMembersPaged=ACL_ALLOW + org.alfresco.service.cmr.site.SiteService.listSiteMemberships=ACL_ALLOW org.alfresco.service.cmr.site.SiteService.listSites=ACL_ALLOW,AFTER_ACL_NODE.sys:base.ReadProperties org.alfresco.service.cmr.site.SiteService.listSitesPaged=ACL_ALLOW,AFTER_ACL_NODE.sys:base.ReadProperties org.alfresco.service.cmr.site.SiteService.removeMembership=ACL_ALLOW diff --git a/source/java/org/alfresco/repo/site/SiteServiceImpl.java b/source/java/org/alfresco/repo/site/SiteServiceImpl.java index e7b6f7d262..68c051ad18 100644 --- a/source/java/org/alfresco/repo/site/SiteServiceImpl.java +++ b/source/java/org/alfresco/repo/site/SiteServiceImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2014 Alfresco Software Limited. + * Copyright (C) 2005-2015 Alfresco Software Limited. * * This file is part of Alfresco * @@ -1180,13 +1180,6 @@ public class SiteServiceImpl extends AbstractLifecycleBean implements SiteServic }; } - /** - * This method returns the {@link SiteInfo siteInfos} for sites to which the specified user has access. - * Note that if the user has access to more than 1000 sites, the list will be truncated to 1000 entries. - * - * @param userName the username - * @return a list of {@link SiteInfo site infos}. - */ public String resolveSite(String group) { // purge non Site related Groups and strip the group name down to the site "shortName" it relates too @@ -1206,48 +1199,20 @@ public class SiteServiceImpl extends AbstractLifecycleBean implements SiteServic return null; } + /** + * This method returns the {@link SiteInfo siteInfos} for sites to which the specified user has access. + * Note that if the user has access to more than 1000 sites, the list will be truncated to 1000 entries. + * + * @param userName the username + * @return a list of {@link SiteInfo site infos}. + */ private List listSitesImpl(final String userName, int size) { - final int maxResults = size > 0 ? size : 1000; - final Set siteNames = new TreeSet(); - - // MNT-13198 - use the bridge table - String actualUserName = personService.getUserIdentifier(userName); - if(actualUserName != null) + List siteMemberships = listSiteMemberships(userName, size); + List result = new ArrayList(siteMemberships.size()); + for (SiteMembership membership : siteMemberships) { - Set containingAuthorities = authorityService.getContainingAuthorities(AuthorityType.GROUP, actualUserName, false); - for(String authority : containingAuthorities) - { - if (siteNames.size() < maxResults) - { - String siteName = resolveSite(authority); - // MNT-10836 fix, after MNT-10109 we should also check site existence - // A simple exists check would be better than getting the site properties etc - profiling suggests x2 faster - if ((siteName != null) && hasSite(siteName)) - { - siteNames.add(siteName); - } - } - } - } - if (siteNames.isEmpty()) - { - return Collections.emptyList(); - } - List assocs = this.nodeService.getChildrenByName( - getSiteRoot(), - ContentModel.ASSOC_CONTAINS, - siteNames); - List result = new ArrayList(assocs.size()); - for (ChildAssociationRef assoc : assocs) - { - // Ignore any node that is not a "site" type - NodeRef site = assoc.getChildRef(); - QName siteClassName = this.directNodeService.getType(site); - if (this.dictionaryService.isSubClass(siteClassName, SiteModel.TYPE_SITE)) - { - result.add(createSiteInfo(site)); - } + result.add(membership.getSiteInfo()); } return result; } @@ -3049,6 +3014,82 @@ public class SiteServiceImpl extends AbstractLifecycleBean implements SiteServic return result; } + private String resolveRole(String group) + { + // purge non Site related Groups and strip the group name down to the role + if (group.startsWith(GROUP_SITE_PREFIX)) + { + int roleIndex = group.lastIndexOf('_'); + if (roleIndex + 1 <= GROUP_SITE_PREFIX_LENGTH) + { + // There is no role associated + return null; + } + else + { + return group.substring(roleIndex + 1); + } + } + return null; + } + + @Override + public List listSiteMemberships (String userName, int size) + { + final int maxResults = size > 0 ? size : 1000; + final Set siteNames = new TreeSet(); + Map roleSitePairs = new HashMap(); + // MNT-13198 - use the bridge table + String actualUserName = personService.getUserIdentifier(userName); + if(actualUserName != null) + { + Set containingAuthorities = authorityService.getContainingAuthorities(AuthorityType.GROUP, actualUserName, false); + for(String authority : containingAuthorities) + { + if (siteNames.size() < maxResults) + { + String siteName = resolveSite(authority); + // MNT-10836 fix, after MNT-10109 we should also check site existence + // A simple exists check would be better than getting the site properties etc - profiling suggests x2 faster + if ((siteName != null) && hasSite(siteName)) + { + String role = resolveRole(authority); + if (role != null) + { + siteNames.add(siteName); + roleSitePairs.put(siteName, role); + } + } + } + else + { + break; + } + } + } + if (siteNames.isEmpty()) + { + return Collections.emptyList(); + } + List assocs = this.nodeService.getChildrenByName( + getSiteRoot(), + ContentModel.ASSOC_CONTAINS, + siteNames); + List result = new ArrayList(assocs.size()); + for (ChildAssociationRef assoc : assocs) + { + // Ignore any node that is not a "site" type + NodeRef site = assoc.getChildRef(); + QName siteClassName = this.directNodeService.getType(site); + if (this.dictionaryService.isSubClass(siteClassName, SiteModel.TYPE_SITE)) + { + SiteInfo siteInfo = createSiteInfo(site); + result.add(new SiteMembership(siteInfo, userName, roleSitePairs.get(siteInfo.getShortName()))); + } + } + return result; + } + public PagingResults listSitesPaged(final String userName, List> sortProps, final PagingRequest pagingRequest) { SiteMembershipCannedQueryFactory sitesCannedQueryFactory = (SiteMembershipCannedQueryFactory)cannedQueryRegistry.getNamedObject("sitesCannedQueryFactory"); diff --git a/source/java/org/alfresco/service/cmr/site/SiteService.java b/source/java/org/alfresco/service/cmr/site/SiteService.java index c3437d151c..b834929a47 100644 --- a/source/java/org/alfresco/service/cmr/site/SiteService.java +++ b/source/java/org/alfresco/service/cmr/site/SiteService.java @@ -222,6 +222,16 @@ public interface SiteService @NotAuditable PagingResults listSites(List filterProps, List> sortProps, PagingRequest pagingRequest); + /** + * Lists all the memberships in sites that the specified user is in. + * + * @param userName + * @param size + * @return a list of SiteMembership objects + */ + @NotAuditable + List listSiteMemberships (String userName, int size); + /** * List all the sites that the specified user has a explicit membership to. * diff --git a/source/test-java/org/alfresco/repo/site/SiteServiceImplTest.java b/source/test-java/org/alfresco/repo/site/SiteServiceImplTest.java index 52be7b8b4c..ac66850b7a 100644 --- a/source/test-java/org/alfresco/repo/site/SiteServiceImplTest.java +++ b/source/test-java/org/alfresco/repo/site/SiteServiceImplTest.java @@ -1135,6 +1135,46 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest } } + public void testListSiteMemberships() + { + String siteName1 = "testMembership1"; + String siteName2 = "testMembership2"; + String siteName3 = "testMembership3"; + // Create a site as user one + this.siteService.createSite(TEST_SITE_PRESET, siteName1, TEST_TITLE, TEST_DESCRIPTION, SiteVisibility.PRIVATE); + + // Get the members of the site and check that user one is a manager + List members = this.siteService.listSiteMemberships(USER_ONE, 0); + assertNotNull(members); + assertEquals(1, members.size()); + assertEquals(USER_ONE, members.get(0).getPersonId()); + assertEquals(SiteModel.SITE_MANAGER, members.get(0).getRole()); + + // Create a site as user two and add user one + this.authenticationComponent.setCurrentUser(USER_TWO); + this.siteService.createSite(TEST_SITE_PRESET, siteName2, TEST_TITLE, TEST_DESCRIPTION, SiteVisibility.PRIVATE); + this.siteService.setMembership("testMembership2", USER_ONE, SiteModel.SITE_CONSUMER); + + // Create a site as user three and add user one + this.authenticationComponent.setCurrentUser(USER_THREE); + this.siteService.createSite(TEST_SITE_PRESET, siteName3, TEST_TITLE, TEST_DESCRIPTION, SiteVisibility.PRIVATE); + this.siteService.setMembership("testMembership3", USER_ONE, SiteModel.SITE_COLLABORATOR); + + this.authenticationComponent.setCurrentUser(USER_ONE); + members = this.siteService.listSiteMemberships(USER_ONE, 0); + assertNotNull(members); + assertEquals(3, members.size()); + assertEquals(USER_ONE, members.get(0).getPersonId()); + assertEquals(SiteModel.SITE_MANAGER, members.get(0).getRole()); + assertEquals(siteName1, members.get(0).getSiteInfo().getShortName()); + assertEquals(USER_ONE, members.get(1).getPersonId()); + assertEquals(SiteModel.SITE_CONSUMER, members.get(1).getRole()); + assertEquals(siteName2, members.get(1).getSiteInfo().getShortName()); + assertEquals(USER_ONE, members.get(2).getPersonId()); + assertEquals(SiteModel.SITE_COLLABORATOR, members.get(2).getRole()); + assertEquals(siteName3, members.get(2).getSiteInfo().getShortName()); + } + public void testJoinLeave() { // Create a site as user one