diff --git a/source/java/org/alfresco/rest/api/Sites.java b/source/java/org/alfresco/rest/api/Sites.java index 7ab3169635..8093187d2f 100644 --- a/source/java/org/alfresco/rest/api/Sites.java +++ b/source/java/org/alfresco/rest/api/Sites.java @@ -1,14 +1,14 @@ /* - * #%L - * Alfresco Remote API - * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited - * %% - * This file is part of the Alfresco software. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * + * #%L + * Alfresco Remote API + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * * 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 @@ -44,7 +44,7 @@ public interface Sites CollectionWithPagingInfo getSiteMembers(String siteShortName, Parameters parameters); Site getSite(String siteId); void deleteSite(String siteId, Parameters parameters); - Site createSite(Site site, Parameters parameters); + Site createSite(Site site, Parameters parameters); /** * people//sites/ @@ -71,6 +71,10 @@ public interface Sites String getSiteRole(String siteId, String personId); String PARAM_PERMANENT = "permanent"; - String PARAM_SKIP_ADDTOFAVORITES = "skipAddToFavorites"; - String PARAM_SKIP_SURF_CONFIGURATION = "skipConfiguration"; + String PARAM_SKIP_ADDTOFAVORITES = "skipAddToFavorites"; + String PARAM_SKIP_SURF_CONFIGURATION = "skipConfiguration"; + + String PARAM_SITE_ID = "id"; + String PARAM_SITE_TITLE = "title"; + String PARAM_SITE_DESCRIPTION = "description"; } diff --git a/source/java/org/alfresco/rest/api/impl/SitesImpl.java b/source/java/org/alfresco/rest/api/impl/SitesImpl.java index fbb5fda381..744e39c5bf 100644 --- a/source/java/org/alfresco/rest/api/impl/SitesImpl.java +++ b/source/java/org/alfresco/rest/api/impl/SitesImpl.java @@ -1,14 +1,14 @@ /* - * #%L - * Alfresco Remote API - * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited - * %% - * This file is part of the Alfresco software. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * + * #%L + * Alfresco Remote API + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * * 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 @@ -47,12 +47,12 @@ 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.security.permissions.AccessDeniedException; +import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.repo.site.SiteMembership; import org.alfresco.repo.site.SiteMembershipComparator; import org.alfresco.repo.site.SiteModel; -import org.alfresco.repo.site.SiteServiceException; -import org.alfresco.repo.site.SiteServiceImpl; +import org.alfresco.repo.site.SiteServiceException; +import org.alfresco.repo.site.SiteServiceImpl; import org.alfresco.rest.api.Nodes; import org.alfresco.rest.api.People; import org.alfresco.rest.api.Sites; @@ -78,9 +78,8 @@ 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.repository.StoreRef; -import org.alfresco.service.cmr.security.AccessStatus; -import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.site.SiteInfo; import org.alfresco.service.cmr.site.SiteService; import org.alfresco.service.cmr.site.SiteVisibility; @@ -91,7 +90,6 @@ import org.alfresco.service.cmr.view.ImporterProgress; import org.alfresco.service.cmr.view.ImporterService; import org.alfresco.service.cmr.view.Location; import org.alfresco.service.namespace.QName; -import org.alfresco.util.ISO9075; import org.alfresco.util.Pair; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -105,18 +103,29 @@ import org.apache.commons.logging.LogFactory; */ public class SitesImpl implements Sites { - private static final Log logger = LogFactory.getLog(SitesImpl.class); - + private static final Log logger = LogFactory.getLog(SitesImpl.class); + private static final String FAVOURITE_SITES_PREFIX = "org.alfresco.share.sites.favourites."; private static final int FAVOURITE_SITES_PREFIX_LENGTH = FAVOURITE_SITES_PREFIX.length(); - // based on Share create site - private static final int SITE_MAXLEN_ID = 72; - private static final int SITE_MAXLEN_TITLE = 256; - private static final int SITE_MAXLEN_DESCRIPTION = 512; - - private static final String SITE_ID_VALID_CHARS_PARTIAL_REGEX = "A-Za-z0-9\\-"; - + // based on Share create site + private static final int SITE_MAXLEN_ID = 72; + private static final int SITE_MAXLEN_TITLE = 256; + private static final int SITE_MAXLEN_DESCRIPTION = 512; + + private static final String SITE_ID_VALID_CHARS_PARTIAL_REGEX = "A-Za-z0-9\\-"; + + private final static Map SORT_PARAMS_TO_QNAMES; + static + { + Map aMap = new HashMap<>(3); + aMap.put(PARAM_SITE_TITLE, ContentModel.PROP_TITLE); + aMap.put(PARAM_SITE_ID, ContentModel.PROP_NAME); + aMap.put(PARAM_SITE_DESCRIPTION, ContentModel.PROP_DESCRIPTION); + SORT_PARAMS_TO_QNAMES = Collections.unmodifiableMap(aMap); + } + + protected Nodes nodes; protected People people; protected NodeService nodeService; @@ -126,8 +135,8 @@ public class SitesImpl implements Sites protected PreferenceService preferenceService; protected ImporterService importerService; protected SiteSurfConfig siteSurfConfig; - protected PermissionService permissionService; - protected SiteServiceImpl siteServiceImpl; + protected PermissionService permissionService; + protected SiteServiceImpl siteServiceImpl; public void setPreferenceService(PreferenceService preferenceService) { @@ -174,17 +183,17 @@ public class SitesImpl implements Sites this.siteSurfConfig = siteSurfConfig; } - public void setPermissionService(PermissionService permissionService) - { - this.permissionService = permissionService; - } - - public void setSiteServiceImpl(SiteServiceImpl siteServiceImpl) - { - this.siteServiceImpl = siteServiceImpl; - } - - + public void setPermissionService(PermissionService permissionService) + { + this.permissionService = permissionService; + } + + public void setSiteServiceImpl(SiteServiceImpl siteServiceImpl) + { + this.siteServiceImpl = siteServiceImpl; + } + + public SiteInfo validateSite(NodeRef guid) { SiteInfo siteInfo = null; @@ -281,13 +290,13 @@ public class SitesImpl implements Sites // site does not exist throw new EntityNotFoundException(siteId); } - return getSite(siteInfo, includeRole); - } - - private Site getSite(SiteInfo siteInfo, boolean includeRole) - { + return getSite(siteInfo, includeRole); + } + + private Site getSite(SiteInfo siteInfo, boolean includeRole) + { // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) - String siteId = siteInfo.getShortName(); + String siteId = siteInfo.getShortName(); String role = null; if(includeRole) { @@ -639,7 +648,7 @@ public class SitesImpl implements Sites } }; } - + public CollectionWithPagingInfo getSites(final Parameters parameters) { final BeanPropertiesFilter filter = parameters.getFilter(); @@ -647,8 +656,27 @@ public class SitesImpl implements Sites 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)); + List sortCols = parameters.getSorting(); + if ((sortCols != null) && (sortCols.size() > 0)) + { + for (SortColumn sortCol : sortCols) + { + QName sortPropQName = SORT_PARAMS_TO_QNAMES.get(sortCol.column); + if (sortPropQName == null) + { + throw new InvalidArgumentException("Invalid sort field: "+sortCol.column); + } + sortProps.add(new Pair<>(sortPropQName, (sortCol.asc ? Boolean.TRUE : Boolean.FALSE))); + } + } + else + { + // default sort order + 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(); @@ -874,24 +902,24 @@ public class SitesImpl implements Sites } siteId = siteInfo.getShortName(); - NodeRef siteNodeRef = siteInfo.getNodeRef(); - - // belt-and-braces - double-check before purge/delete (rather than rollback) - if (permissionService.hasPermission(siteNodeRef, PermissionService.DELETE) != AccessStatus.ALLOWED) - { - throw new AccessDeniedException("Cannot delete site: "+siteId); - } - + NodeRef siteNodeRef = siteInfo.getNodeRef(); + + // belt-and-braces - double-check before purge/delete (rather than rollback) + if (permissionService.hasPermission(siteNodeRef, PermissionService.DELETE) != AccessStatus.ALLOWED) + { + throw new AccessDeniedException("Cannot delete site: "+siteId); + } + // default false (if not provided) boolean permanentDelete = Boolean.valueOf(parameters.getParameter(PARAM_PERMANENT)); if (permanentDelete == true) { // Set as temporary to delete node instead of archiving. - nodeService.addAspect(siteNodeRef, ContentModel.ASPECT_TEMPORARY, null); - - // bypassing trashcan means that purge behaviour will not fire, so explicitly force cleanup here - siteServiceImpl.beforePurgeNode(siteNodeRef); + nodeService.addAspect(siteNodeRef, ContentModel.ASPECT_TEMPORARY, null); + + // bypassing trashcan means that purge behaviour will not fire, so explicitly force cleanup here + siteServiceImpl.beforePurgeNode(siteNodeRef); } siteService.deleteSite(siteId); @@ -899,56 +927,56 @@ public class SitesImpl implements Sites /** - * Create default/fixed preset (Share) site - with DocLib container/component + * Create default/fixed preset (Share) site - with DocLib container/component * * @param site * @return */ - public Site createSite(Site site, Parameters parameters) + public Site createSite(Site site, Parameters parameters) { - // note: if site id is null then will be generated from the site title + // note: if site id is null then will be generated from the site title site = validateSite(site); - SiteInfo siteInfo = null; - try - { - siteInfo = siteService.createSite("sitePreset", site.getId(), site.getTitle(), site.getDescription(), site.getVisibility()); - } - catch (SiteServiceException sse) - { - if (sse.getMsgId().equals("site_service.unable_to_create")) - { - throw new ConstraintViolatedException(sse.getMessage()); - } - else - { - throw sse; - } - } - - String siteId = siteInfo.getShortName(); - NodeRef siteNodeRef = siteInfo.getNodeRef(); - - // default false (if not provided) - boolean skipShareSurfConfig = Boolean.valueOf(parameters.getParameter(PARAM_SKIP_SURF_CONFIGURATION)); - if (skipShareSurfConfig == false) - { - // import default/fixed preset Share surf config - importSite(siteId, siteNodeRef); - } + SiteInfo siteInfo = null; + try + { + siteInfo = siteService.createSite("sitePreset", site.getId(), site.getTitle(), site.getDescription(), site.getVisibility()); + } + catch (SiteServiceException sse) + { + if (sse.getMsgId().equals("site_service.unable_to_create")) + { + throw new ConstraintViolatedException(sse.getMessage()); + } + else + { + throw sse; + } + } + + String siteId = siteInfo.getShortName(); + NodeRef siteNodeRef = siteInfo.getNodeRef(); + + // default false (if not provided) + boolean skipShareSurfConfig = Boolean.valueOf(parameters.getParameter(PARAM_SKIP_SURF_CONFIGURATION)); + if (skipShareSurfConfig == false) + { + // import default/fixed preset Share surf config + importSite(siteId, siteNodeRef); + } // pre-create doclib siteService.createContainer(siteId, SiteService.DOCUMENT_LIBRARY, ContentModel.TYPE_FOLDER, null); - // default false (if not provided) - boolean skipAddToFavorites = Boolean.valueOf(parameters.getParameter(PARAM_SKIP_ADDTOFAVORITES)); - if (skipAddToFavorites == false) - { - String personId = AuthenticationUtil.getFullyAuthenticatedUser(); - favouritesService.addFavourite(personId, siteNodeRef); // ignore result - } - - return getSite(siteInfo, true); + // default false (if not provided) + boolean skipAddToFavorites = Boolean.valueOf(parameters.getParameter(PARAM_SKIP_ADDTOFAVORITES)); + if (skipAddToFavorites == false) + { + String personId = AuthenticationUtil.getFullyAuthenticatedUser(); + favouritesService.addFavourite(personId, siteNodeRef); // ignore result + } + + return getSite(siteInfo, true); } private Site validateSite(Site site) @@ -973,17 +1001,17 @@ public class SitesImpl implements Sites String siteId = site.getId(); if (siteId == null) { - // generate a site id from title (similar to Share create site dialog) - siteId = siteTitle. - trim(). // trim leading & trailing whitespace - replaceAll("[^"+SITE_ID_VALID_CHARS_PARTIAL_REGEX+" ]",""). // remove special characters (except spaces) - replaceAll(" +", " "). // collapse multiple spaces to single space - replace(" ","-"). // replaces spaces with dashs - toLowerCase(); // lowercase :-) + // generate a site id from title (similar to Share create site dialog) + siteId = siteTitle. + trim(). // trim leading & trailing whitespace + replaceAll("[^"+SITE_ID_VALID_CHARS_PARTIAL_REGEX+" ]",""). // remove special characters (except spaces) + replaceAll(" +", " "). // collapse multiple spaces to single space + replace(" ","-"). // replaces spaces with dashs + toLowerCase(); // lowercase :-) } else { - if (! siteId.matches("^["+SITE_ID_VALID_CHARS_PARTIAL_REGEX+"]+")) + if (! siteId.matches("^["+SITE_ID_VALID_CHARS_PARTIAL_REGEX+"]+")) { throw new InvalidArgumentException("Invalid site id - should consist of alphanumeric/dash characters"); } @@ -997,13 +1025,13 @@ public class SitesImpl implements Sites site.setId(siteId); String siteDescription = site.getDescription(); - - if (siteDescription == null) - { - // workaround: to avoid Share error (eg. in My Sites dashlet / freemarker template) - site.setDescription(""); - } - + + if (siteDescription == null) + { + // workaround: to avoid Share error (eg. in My Sites dashlet / freemarker template) + site.setDescription(""); + } + if ((siteDescription != null) && (siteDescription.length() > SITE_MAXLEN_DESCRIPTION)) { throw new InvalidArgumentException("Site description exceeds max length of "+SITE_MAXLEN_DESCRIPTION+" characters"); @@ -1012,10 +1040,10 @@ public class SitesImpl implements Sites return site; } - private void importSite(final String siteId, final NodeRef siteNodeRef) + private void importSite(final String siteId, final NodeRef siteNodeRef) { ImportPackageHandler acpHandler = new SiteImportPackageHandler(siteSurfConfig, siteId); - Location location = new Location(siteNodeRef); + Location location = new Location(siteNodeRef); ImporterBinding binding = new ImporterBinding() { @Override