/* * 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.rest.api.impl; import java.io.Serializable; import java.text.Collator; import java.util.AbstractList; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeSet; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; import org.alfresco.query.PageDetails; import org.alfresco.query.PagingRequest; import org.alfresco.query.PagingResults; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authority.UnknownAuthorityException; import org.alfresco.repo.site.SiteMembership; import org.alfresco.repo.site.SiteModel; import org.alfresco.rest.api.Nodes; import org.alfresco.rest.api.People; import org.alfresco.rest.api.Sites; import org.alfresco.rest.api.model.FavouriteSite; import org.alfresco.rest.api.model.MemberOfSite; import org.alfresco.rest.api.model.Site; import org.alfresco.rest.api.model.SiteContainer; import org.alfresco.rest.api.model.SiteImpl; import org.alfresco.rest.api.model.SiteMember; import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException; import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; import org.alfresco.rest.framework.core.exceptions.NotFoundException; import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException; import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException; import org.alfresco.rest.framework.jacksonextensions.BeanPropertiesFilter; import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; import org.alfresco.rest.framework.resource.parameters.Paging; import org.alfresco.rest.framework.resource.parameters.Parameters; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.favourites.FavouritesService; import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.preference.PreferenceService; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.site.SiteInfo; import org.alfresco.service.cmr.site.SiteService; import org.alfresco.service.namespace.QName; import org.alfresco.util.Pair; /** * Centralises access to site services and maps between representations. * * @author steveglover * @since publicapi1.0 */ public class SitesImpl implements Sites { private static final String FAVOURITE_SITES_PREFIX = "org.alfresco.share.sites.favourites."; private static final int FAVOURITE_SITES_PREFIX_LENGTH = FAVOURITE_SITES_PREFIX.length(); protected Nodes nodes; protected People people; protected NodeService nodeService; protected DictionaryService dictionaryService; protected SiteService siteService; protected FavouritesService favouritesService; protected PreferenceService preferenceService; public void setPreferenceService(PreferenceService preferenceService) { this.preferenceService = preferenceService; } public void setDictionaryService(DictionaryService dictionaryService) { this.dictionaryService = dictionaryService; } public void setNodes(Nodes nodes) { this.nodes = nodes; } public void setFavouritesService(FavouritesService favouritesService) { this.favouritesService = favouritesService; } public void setPeople(People people) { this.people = people; } public void setNodeService(NodeService nodeService) { this.nodeService = nodeService; } public void setSiteService(SiteService siteService) { this.siteService = siteService; } public SiteInfo validateSite(NodeRef guid) { SiteInfo siteInfo = null; if(guid == null) { throw new InvalidArgumentException("guid is null"); } nodes.validateNode(guid); QName type = nodeService.getType(guid); boolean isSiteNodeRef = dictionaryService.isSubClass(type, SiteModel.TYPE_SITE); if(isSiteNodeRef) { siteInfo = siteService.getSite(guid); if(siteInfo == null) { // not a site throw new InvalidArgumentException(guid.getId() + " is not a site"); } } else { // site does not exist throw new EntityNotFoundException(guid.getId()); } return siteInfo; } public SiteInfo validateSite(String siteId) { if(siteId == null) { throw new InvalidArgumentException("siteId is null"); } SiteInfo siteInfo = siteService.getSite(siteId); return siteInfo; } public CollectionWithPagingInfo getSiteMembers(String siteId, Parameters parameters) { SiteInfo siteInfo = validateSite(siteId); if(siteInfo == null) { // site does not exist throw new EntityNotFoundException(siteId); } // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) siteId = siteInfo.getShortName(); Paging paging = parameters.getPaging(); PagingRequest pagingRequest = Util.getPagingRequest(paging); final List> sort = new ArrayList>(); sort.add(new Pair(SiteService.SortFields.LastName, Boolean.TRUE)); sort.add(new Pair(SiteService.SortFields.FirstName, Boolean.TRUE)); sort.add(new Pair(SiteService.SortFields.Role, Boolean.TRUE)); sort.add(new Pair(SiteService.SortFields.Username, Boolean.TRUE)); PagingResults pagedResults = siteService.listMembersPaged(siteId, true, sort, pagingRequest); List siteMembers = pagedResults.getPage(); List ret = new ArrayList(siteMembers.size()); for(SiteMembership siteMembership : siteMembers) { SiteMember siteMember = new SiteMember(siteMembership.getPersonId(), siteMembership.getRole()); ret.add(siteMember); } return CollectionWithPagingInfo.asPaged(paging, ret, pagedResults.hasMoreItems(), null); } public String getSiteRole(String siteId) { String personId = AuthenticationUtil.getFullyAuthenticatedUser(); return getSiteRole(siteId, personId); } public String getSiteRole(String siteId, String personId) { return siteService.getMembersRole(siteId, personId); } public Site getSite(String siteId) { return getSite(siteId, true); } public Site getSite(String siteId, boolean includeRole) { SiteInfo siteInfo = validateSite(siteId); if(siteInfo == null) { // site does not exist throw new EntityNotFoundException(siteId); } // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) siteId = siteInfo.getShortName(); String role = null; if(includeRole) { role = getSiteRole(siteId); } return new SiteImpl(siteInfo, role); } /** * people//sites/ * * @param siteId * @param personId * @return */ public MemberOfSite getMemberOfSite(String personId, String siteId) { MemberOfSite siteMember = null; personId = people.validatePerson(personId); SiteInfo siteInfo = validateSite(siteId); if(siteInfo == null) { // site does not exist throw new RelationshipResourceNotFoundException(personId, siteId); } // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) siteId = siteInfo.getShortName(); String roleStr = siteService.getMembersRole(siteInfo.getShortName(), personId); if(roleStr != null) { SiteImpl site = new SiteImpl(siteInfo, roleStr); siteMember = new MemberOfSite(site.getId(), siteInfo.getNodeRef(), roleStr); } else { throw new RelationshipResourceNotFoundException(personId, siteId); } return siteMember; } public SiteMember getSiteMember(String personId, String siteId) { SiteMember siteMember = null; personId = people.validatePerson(personId); SiteInfo siteInfo = validateSite(siteId); if(siteInfo == null) { // site does not exist throw new RelationshipResourceNotFoundException(personId, siteId); } siteId = siteInfo.getShortName(); String role = siteService.getMembersRole(siteId, personId); if(role != null) { siteMember = new SiteMember(personId, role); } else { throw new RelationshipResourceNotFoundException(personId, siteId); } return siteMember; } public SiteMember addSiteMember(String siteId, SiteMember siteMember) { String personId = people.validatePerson(siteMember.getPersonId()); SiteInfo siteInfo = validateSite(siteId); if(siteInfo == null) { // site does not exist throw new EntityNotFoundException(siteId); } // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) siteId = siteInfo.getShortName(); String role = siteMember.getRole(); if(role == null) { throw new InvalidArgumentException("Must provide a role"); } if(siteService.isMember(siteId, personId)) { throw new ConstraintViolatedException(personId + " is already a member of site " + siteId); } if(!siteService.canAddMember(siteId, personId, role)) { throw new PermissionDeniedException(); } try { siteService.setMembership(siteId, personId, role); } catch (UnknownAuthorityException e) { throw new InvalidArgumentException("Unknown role '" + role + "'"); } return siteMember; } public void removeSiteMember(String personId, String siteId) { personId = people.validatePerson(personId); SiteInfo siteInfo = validateSite(siteId); if(siteInfo == null) { // site does not exist throw new RelationshipResourceNotFoundException(personId, siteId); } // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) siteId = siteInfo.getShortName(); boolean isMember = siteService.isMember(siteId, personId); if(!isMember) { throw new InvalidArgumentException(); } String role = siteService.getMembersRole(siteId, personId); if(role != null) { if(role.equals(SiteModel.SITE_MANAGER)) { int numAuthorities = siteService.countAuthoritiesWithRole(siteId, SiteModel.SITE_MANAGER); if(numAuthorities <= 1) { throw new InvalidArgumentException("Can't remove last manager of site " + siteId); } siteService.removeMembership(siteId, personId); } else { siteService.removeMembership(siteId, personId); } } else { throw new AlfrescoRuntimeException("Unable to determine role of site member"); } } public SiteMember updateSiteMember(String siteId, SiteMember siteMember) { String siteMemberId = siteMember.getPersonId(); if(siteMemberId == null) { throw new InvalidArgumentException("Member id is null"); } siteMemberId = people.validatePerson(siteMemberId); SiteInfo siteInfo = validateSite(siteId); if(siteInfo == null) { // site does not exist throw new EntityNotFoundException(siteId); } siteId = siteInfo.getShortName(); String siteRole = siteMember.getRole(); if(siteRole == null) { throw new InvalidArgumentException("Must provide a role"); } /* MNT-10551 : fix */ if (!siteService.isMember(siteId, siteMember.getPersonId())) { throw new InvalidArgumentException("User is not a member of the site"); } try { siteService.setMembership(siteId, siteMember.getPersonId(), siteRole); } catch (UnknownAuthorityException e) { throw new InvalidArgumentException("Unknown role '" + siteRole + "'"); } return siteMember; } public CollectionWithPagingInfo getSites(String personId, Parameters parameters) { Paging paging = parameters.getPaging(); personId = people.validatePerson(personId); PagingRequest pagingRequest = Util.getPagingRequest(paging); final List> sort = new ArrayList>(); sort.add(new Pair(SiteService.SortFields.SiteTitle, Boolean.TRUE)); sort.add(new Pair(SiteService.SortFields.Role, Boolean.TRUE)); PagingResults results = siteService.listSitesPaged(personId, sort, pagingRequest); List siteMembers = results.getPage(); List ret = new ArrayList(siteMembers.size()); for(SiteMembership siteMember : siteMembers) { SiteInfo siteInfo = siteMember.getSiteInfo(); MemberOfSite memberOfSite = new MemberOfSite(siteInfo.getShortName(), siteInfo.getNodeRef(), siteMember.getRole()); ret.add(memberOfSite); } return CollectionWithPagingInfo.asPaged(paging, ret, results.hasMoreItems(), null); } public SiteContainer getSiteContainer(String siteId, String containerId) { // check site and container node validity SiteInfo siteInfo = validateSite(siteId); if(siteInfo == null) { // site does not exist throw new RelationshipResourceNotFoundException(siteId, containerId); } // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) siteId = siteInfo.getShortName(); NodeRef containerNodeRef = siteService.getContainer(siteId, containerId); if(containerNodeRef == null) { throw new RelationshipResourceNotFoundException(siteId, containerId); } // check that the containerId is actually a container for the specified site SiteInfo testSiteInfo = siteService.getSite(containerNodeRef); if(testSiteInfo == null) { throw new RelationshipResourceNotFoundException(siteId, containerId); } else { if(!testSiteInfo.getShortName().equals(siteId)) { throw new RelationshipResourceNotFoundException(siteId, containerId); } } String folderId = (String)nodeService.getProperty(containerNodeRef, SiteModel.PROP_COMPONENT_ID); SiteContainer siteContainer = new SiteContainer(folderId, containerNodeRef); return siteContainer; } public PagingResults getSiteContainers(String siteId, Paging paging) { SiteInfo siteInfo = validateSite(siteId); if(siteInfo == null) { // site does not exist throw new EntityNotFoundException(siteId); } final PagingResults pagingResults = siteService.listContainers(siteInfo.getShortName(), Util.getPagingRequest(paging)); List containerFileInfos = pagingResults.getPage(); final List siteContainers = new ArrayList(containerFileInfos.size()); for(FileInfo containerFileInfo : containerFileInfos) { NodeRef nodeRef = containerFileInfo.getNodeRef(); String containerId = (String)nodeService.getProperty(nodeRef, SiteModel.PROP_COMPONENT_ID); SiteContainer siteContainer = new SiteContainer(containerId, nodeRef); siteContainers.add(siteContainer); } return new PagingResults() { @Override public List getPage() { return siteContainers; } @Override public boolean hasMoreItems() { return pagingResults.hasMoreItems(); } @Override public Pair getTotalResultCount() { return pagingResults.getTotalResultCount(); } @Override public String getQueryExecutionId() { return null; } }; } public CollectionWithPagingInfo getSites(final Parameters parameters) { final BeanPropertiesFilter filter = parameters.getFilter(); Paging paging = parameters.getPaging(); PagingRequest pagingRequest = Util.getPagingRequest(paging); // pagingRequest.setRequestTotalCountMax(requestTotalCountMax) List> sortProps = new ArrayList>(); sortProps.add(new Pair(ContentModel.PROP_NAME, Boolean.TRUE)); final PagingResults pagingResult = siteService.listSites(null, sortProps, pagingRequest); final List sites = pagingResult.getPage(); int totalItems = pagingResult.getTotalResultCount().getFirst(); final String personId = AuthenticationUtil.getFullyAuthenticatedUser(); List page = new AbstractList() { @Override public SiteImpl get(int index) { SiteInfo siteInfo = sites.get(index); String role = null; if(filter.isAllowed(Site.ROLE)) { role = siteService.getMembersRole(siteInfo.getShortName(), personId); } return new SiteImpl(siteInfo, role); } @Override public int size() { return sites.size(); } }; return CollectionWithPagingInfo.asPaged(paging, page, pagingResult.hasMoreItems(), totalItems); } public FavouriteSite getFavouriteSite(String personId, String siteId) { personId = people.validatePerson(personId); SiteInfo siteInfo = validateSite(siteId); if(siteInfo == null) { // site does not exist throw new RelationshipResourceNotFoundException(personId, siteId); } // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) siteId = siteInfo.getShortName(); NodeRef nodeRef = siteInfo.getNodeRef(); if(favouritesService.isFavourite(personId, nodeRef)) { String role = getSiteRole(siteId, personId); return new FavouriteSite(siteInfo, role); } else { throw new RelationshipResourceNotFoundException(personId, siteId); } } public void addFavouriteSite(String personId, FavouriteSite favouriteSite) { personId = people.validatePerson(personId); String siteId = favouriteSite.getId(); SiteInfo siteInfo = validateSite(siteId); if(siteInfo == null) { // site does not exist throw new EntityNotFoundException(siteId); } // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) siteId = siteInfo.getShortName(); StringBuilder prefKey = new StringBuilder(FAVOURITE_SITES_PREFIX); prefKey.append(siteId); String value = (String)preferenceService.getPreference(personId, prefKey.toString()); boolean isFavouriteSite = (value == null ? false : value.equalsIgnoreCase("true")); if(isFavouriteSite) { throw new ConstraintViolatedException("Site " + siteId + " is already a favourite site"); } prefKey = new StringBuilder(FAVOURITE_SITES_PREFIX); prefKey.append(siteId); Map preferences = new HashMap(1); preferences.put(prefKey.toString(), Boolean.TRUE); preferenceService.setPreferences(personId, preferences); } public void removeFavouriteSite(String personId, String siteId) { personId = people.validatePerson(personId); SiteInfo siteInfo = validateSite(siteId); if(siteInfo == null) { // site does not exist throw new RelationshipResourceNotFoundException(personId, siteId); } siteId = siteInfo.getShortName(); StringBuilder prefKey = new StringBuilder(FAVOURITE_SITES_PREFIX); prefKey.append(siteId); String value = (String)preferenceService.getPreference(personId, prefKey.toString()); boolean isFavouriteSite = (value == null ? false : value.equalsIgnoreCase("true")); if(!isFavouriteSite) { throw new NotFoundException("Site " + siteId + " is not a favourite site"); } preferenceService.clearPreferences(personId, prefKey.toString()); } private PagingResults getFavouriteSites(String userName, PagingRequest pagingRequest) { final Collator collator = Collator.getInstance(); final Set sortedFavouriteSites = new TreeSet(new Comparator() { @Override public int compare(SiteInfo o1, SiteInfo o2) { return collator.compare(o1.getTitle(), o2.getTitle()); } }); Map prefs = preferenceService.getPreferences(userName, FAVOURITE_SITES_PREFIX); for(Entry entry : prefs.entrySet()) { boolean isFavourite = false; Serializable s = entry.getValue(); if(s instanceof Boolean) { isFavourite = (Boolean)s; } if(isFavourite) { String siteShortName = entry.getKey().substring(FAVOURITE_SITES_PREFIX_LENGTH).replace(".favourited", ""); SiteInfo siteInfo = siteService.getSite(siteShortName); if(siteInfo != null) { sortedFavouriteSites.add(siteInfo); } } } int totalSize = sortedFavouriteSites.size(); final PageDetails pageDetails = PageDetails.getPageDetails(pagingRequest, totalSize); final List page = new ArrayList(pageDetails.getPageSize()); Iterator it = sortedFavouriteSites.iterator(); for(int counter = 0; counter < pageDetails.getEnd() && it.hasNext(); counter++) { SiteInfo favouriteSite = it.next(); if(counter < pageDetails.getSkipCount()) { continue; } if(counter > pageDetails.getEnd() - 1) { break; } page.add(favouriteSite); } return new PagingResults() { @Override public List getPage() { return page; } @Override public boolean hasMoreItems() { return pageDetails.hasMoreItems(); } @Override public Pair getTotalResultCount() { Integer total = Integer.valueOf(sortedFavouriteSites.size()); return new Pair(total, total); } @Override public String getQueryExecutionId() { return null; } }; } public CollectionWithPagingInfo getFavouriteSites(String personId, Parameters parameters) { personId = people.validatePerson(personId); Paging paging = parameters.getPaging(); BeanPropertiesFilter filter = parameters.getFilter(); PagingResults favouriteSites = getFavouriteSites(personId, Util.getPagingRequest(paging)); List favourites = new ArrayList(favouriteSites.getPage().size()); for(SiteInfo favouriteSite : favouriteSites.getPage()) { String role = null; if(filter.isAllowed(Site.ROLE)) { role = getSiteRole(favouriteSite.getShortName(), personId); } FavouriteSite favourite = new FavouriteSite(favouriteSite, role); favourites.add(favourite); } return CollectionWithPagingInfo.asPaged(paging, favourites, favouriteSites.hasMoreItems(), favouriteSites.getTotalResultCount().getFirst()); } }