diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/generic-paged-results.lib.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/generic-paged-results.lib.ftl index bc1f7e2a4a..7cd367b232 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/repository/generic-paged-results.lib.ftl +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/generic-paged-results.lib.ftl @@ -48,3 +48,41 @@ Usage: + +<#-- + Renders paged results information to conforms to the RESTful APIs standards. + The passed in data object should contain following attributes: + count: The actual number of elements returned + hasMoreItems: True if more items on next page + totalItems: The total result count + skipCount: The number of elements to skip before retrieving the page + maxItems: The number of elements requested to be returned + +Usage: + <#import "generic-paged-results.lib.ftl" as gen/> + { + <@gen.standardRestfulPagedResults data=data ; item> + output of the individual item, for example by calling another macro: + <@yourLib.itemJSON item=item /> + + } +--> +<#macro standardRestfulPagedResults data> + "list" : { + "pagination" : { + "count" : ${data.count?c}, + "hasMoreItems" : ${data.hasMoreItems?c}, + "totalItems" : ${data.totalItems?c}, + "skipCount" :${data.skipCount?c}, + "maxItems" : ${data.maxItems?c} + }, + "entries" : [{ + <#list data.items as item> + "entry" : { + <#nested item> + } + }<#if item_has_next>, { + + ] + } + diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/site/site-admin-sites.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/site/site-admin-sites.get.desc.xml new file mode 100644 index 0000000000..515ab4c09c --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/site/site-admin-sites.get.desc.xml @@ -0,0 +1,8 @@ + + Get sites + Get a collection of the sites in the repository accessible to site administrators. The collection can be filtered by name. + /api/admin-sites?nf={namefilter?}&maxItems={maxItems?}&skipCount={skipCount?}&roles={roles?}& + argument + user + required + diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/site/site-admin-sites.get.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/site/site-admin-sites.get.json.ftl new file mode 100644 index 0000000000..fa1dba1b9b --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/site/site-admin-sites.get.json.ftl @@ -0,0 +1,31 @@ +<#import "../generic-paged-results.lib.ftl" as gen/> + +<#macro siteJSON item> +<#escape x as jsonUtils.encodeJSONString(x)> + "url" : "${url.serviceContext + "/api/sites/" + item.siteInfo.shortName}", + "sitePreset" : "${item.siteInfo.sitePreset}", + "shortName" : "${item.siteInfo.shortName}", + "title" : "${item.siteInfo.title}", + "description" : "${item.siteInfo.description}", + "createdDate" : "${xmldate(item.siteInfo.createdDate)}", + "lastModifiedDate" : "${xmldate(item.siteInfo.lastModifiedDate)}", + "visibility" : "${item.siteInfo.visibility}", + "siteManagers" : [{ + <#list item.members as manager> + "entry" : { + "userName" : "${manager.userName}", + "firstName" : "${manager.firstName}", + "lastName" : "${manager.lastName}" + } + }<#if manager_has_next>, { + + ] + + + +{ + <@gen.standardRestfulPagedResults data=data ; item> + <@siteJSON item=item /> + +} + diff --git a/config/alfresco/web-scripts-application-context.xml b/config/alfresco/web-scripts-application-context.xml index 4d688d7ef9..53fa81bfb0 100644 --- a/config/alfresco/web-scripts-application-context.xml +++ b/config/alfresco/web-scripts-application-context.xml @@ -786,6 +786,13 @@ + + + + + + + diff --git a/source/java/org/alfresco/repo/web/scripts/site/SiteAdminSitesGet.java b/source/java/org/alfresco/repo/web/scripts/site/SiteAdminSitesGet.java new file mode 100644 index 0000000000..88022fe9a6 --- /dev/null +++ b/source/java/org/alfresco/repo/web/scripts/site/SiteAdminSitesGet.java @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2005-2014 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.repo.web.scripts.site; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; + +import org.alfresco.model.ContentModel; +import org.alfresco.query.PagingResults; +import org.alfresco.repo.node.getchildren.FilterProp; +import org.alfresco.repo.node.getchildren.FilterPropString; +import org.alfresco.repo.node.getchildren.FilterPropString.FilterTypeString; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.site.SiteModel; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.security.PersonService; +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; +import org.alfresco.util.ScriptPagingDetails; +import org.springframework.extensions.webscripts.Cache; +import org.springframework.extensions.webscripts.DeclarativeWebScript; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * This class is the controller for the site-admin-sites.get web script. + * + * @author Jamal Kaabi-Mofrad + */ +public class SiteAdminSitesGet extends DeclarativeWebScript +{ + private static final String NAME_FILTER = "nf"; + private static final String MAX_ITEMS = "maxItems"; + private static final String SKIP_COUNT = "skipCount"; + private static final int DEFAULT_MAX_ITEMS_PER_PAGE = 50; + + private SiteService siteService; + private NodeService nodeService; + private PersonService personService; + + public void setSiteService(SiteService siteService) + { + this.siteService = siteService; + } + + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public void setPersonService(PersonService personService) + { + this.personService = personService; + } + + @Override + protected Map executeImpl(WebScriptRequest req, Status status, Cache cache) + { + // check the current user access rights + if (!siteService.isSiteAdmin(AuthenticationUtil.getFullyAuthenticatedUser())) + { + // Note: security, no message to indicate why + throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Resource no found."); + } + + // Create paging + final ScriptPagingDetails paging = new ScriptPagingDetails(getIntParameter(req, MAX_ITEMS, + DEFAULT_MAX_ITEMS_PER_PAGE), getIntParameter(req, SKIP_COUNT, 0)); + + // request a total count of found items + paging.setRequestTotalCountMax(Integer.MAX_VALUE); + + final List filterProp = getFilterProperties(req.getParameter(NAME_FILTER)); + + final List> sortProps = new ArrayList>(); + sortProps.add(new Pair(ContentModel.PROP_NAME, true)); + + PagingResults pagingResults = AuthenticationUtil.runAs( + new AuthenticationUtil.RunAsWork>() + { + public PagingResults doWork() throws Exception + { + return siteService.listSites(filterProp, sortProps, paging); + } + }, AuthenticationUtil.getAdminUserName()); + + List result = pagingResults.getPage(); + List sites = new ArrayList(result.size()); + for (SiteInfo info : result) + { + sites.add(SiteState.create(info, + siteService.listMembers(info.getShortName(), null, SiteModel.SITE_MANAGER, 0), nodeService, + personService)); + } + + Map sitesData = new HashMap(6); + + // Site data + sitesData.put("items", sites); + // Paging data + sitesData.put("count", result.size()); + sitesData.put("hasMoreItems", pagingResults.hasMoreItems()); + sitesData.put("totalItems", (pagingResults.getTotalResultCount() == null ? -1 : pagingResults.getTotalResultCount().getFirst())); + sitesData.put("skipCount", paging.getSkipCount()); + sitesData.put("maxItems", paging.getMaxItems()); + + // Create the model from the site and pagination data + Map model = new HashMap(1); + model.put("data", sitesData); + + return model; + } + + private int getIntParameter(WebScriptRequest req, String paramName, int defaultValue) + { + String paramString = req.getParameter(paramName); + + if (paramString != null) + { + try + { + int param = Integer.valueOf(paramString); + + if (param >= 0) + { + return param; + } + } + catch (NumberFormatException e) + { + throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, e.getMessage()); + } + } + + return defaultValue; + } + + private List getFilterProperties(String filter) + { + if (filter == null || filter.isEmpty() || filter.equals("*")) + { + return null; + } + List filterProps = new ArrayList(); + filterProps.add(new FilterPropString(ContentModel.PROP_NAME, filter, FilterTypeString.STARTSWITH_IGNORECASE)); + filterProps.add(new FilterPropString(ContentModel.PROP_TITLE, filter, FilterTypeString.STARTSWITH_IGNORECASE)); + return filterProps; + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/site/SiteState.java b/source/java/org/alfresco/repo/web/scripts/site/SiteState.java new file mode 100644 index 0000000000..59c817a04d --- /dev/null +++ b/source/java/org/alfresco/repo/web/scripts/site/SiteState.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2005-2014 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.repo.web.scripts.site; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.model.ContentModel; +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.site.SiteInfo; + +/** + * A simple POJO class for the state of a site. For easier passing to the FTL model. + * + * @author jkaabimofrad + */ +public class SiteState +{ + + private SiteInfo siteInfo; + private List members; + + private SiteState() + { + } + + public static SiteState create(SiteInfo siteInfo, Map members, NodeService nodeService, + PersonService personService) + { + SiteState result = new SiteState(); + result.members = new ArrayList(members.size()); + + result.siteInfo = siteInfo; + + Set siteMembers = members.keySet(); + for (String userName : siteMembers) + { + NodeRef person = personService.getPersonOrNull(userName); + if (person != null) + { + String firstName = (String) nodeService.getProperty(person, ContentModel.PROP_FIRSTNAME); + String lastName = (String) nodeService.getProperty(person, ContentModel.PROP_LASTNAME); + result.members.add(new MemberState(userName, firstName, lastName)); + } + } + + return result; + } + + public SiteInfo getSiteInfo() + { + return this.siteInfo; + } + + public List getMembers() + { + return this.members; + } + + public static class MemberState + { + private String userName; + private String firstName; + private String lastName; + + public MemberState(String userName, String firstName, String lastName) + { + this.userName = userName; + this.firstName = firstName; + this.lastName = lastName; + } + + public String getUserName() + { + return this.userName; + } + + public String getFirstName() + { + return this.firstName; + } + + public String getLastName() + { + return this.lastName; + } + + } +}