mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-06-30 18:15:39 +00:00
13077: Abstracted ContentStore MBean operations 13099: Merge V3.0 to V3.1 13096 Merged V2.2 to V3.0 13071: Fix ETWOTWO-1058: Hibernate exception while concurrently submitting from and updating same user sandbox. 13079: Fix ETWOTWO-1117: Misleading exceptions reported during AVM flatten and update 13102: [no comment] 13112: Merged V3.0 to V3.1 13111: Merged V2.2 to V3.0 13110: Fix 2.1 -> 2.2 upgrade on Postgres 13114: Build/test fix (Enterprise Remote API project does not yet have any Java files to generate Javadoc) 13117: DM Index Check - unit test improvements 13123: *RECORD ONLY* Removed svn:mergeinfo fluff 13124: Used newer, more efficient NodeService.addProperties method instead of many NodeService.setProperty calls 13125: Added M2Binding for 'child-association': propagateTimestamps' 13126: WCM unit tests - reduce build/test time to check (async) submits 13127: Minor test fix - to allow it to run locally (on Mac OS X) 13130: Support for 'maxRetries' of zero or less 13131: Merged V3.0 to V3.1 13025 *RECORD-ONLY*: Removed unnecessary svn:mergeinfo 13026: Merged V2.2 to V3.0 12964: Fixed ETWOTWO-968: Space rules are not run when saving from MS Word 12993 *RECORD-ONLY*: added openoffice bootstrap context to sample-extensions 13009 *RECORD-ONLY*: Avoid default OOo config from causing problems on zip/gz installs 13132: Updated svn:mergeinfo 13134: ETHREEOH-1202 - initial fix and unit tests ___________________________________________________________________ Modified: svn:mergeinfo Merged /alfresco/BRANCHES/V3.0:r13005,13025-13026,13030,13039,13042,13050,13053,13096,13098,13111 Merged /alfresco/BRANCHES/V2.2:r12964,12993,13009,13071,13079,13110 Merged /alfresco/BRANCHES/V3.1:r13077,13099,13102,13112,13114,13117,13123-13127,13130-13132,13134 git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@13564 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
1418 lines
57 KiB
Java
1418 lines
57 KiB
Java
/*
|
|
* Copyright (C) 2005-2008 Alfresco Software Limited.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
|
|
* This program 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 General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
* As a special exception to the terms and conditions of version 2.0 of
|
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
|
* FLOSS exception. You should have recieved a copy of the text describing
|
|
* the FLOSS exception, and it is also available here:
|
|
* http://www.alfresco.com/legal/licensing"
|
|
*/
|
|
package org.alfresco.wcm.webproject;
|
|
|
|
import java.io.Serializable;
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.LinkedList;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
import org.alfresco.error.AlfrescoRuntimeException;
|
|
import org.alfresco.mbeans.VirtServerRegistry;
|
|
import org.alfresco.model.ApplicationModel;
|
|
import org.alfresco.model.ContentModel;
|
|
import org.alfresco.model.WCMAppModel;
|
|
import org.alfresco.repo.avm.AVMNodeConverter;
|
|
import org.alfresco.repo.domain.PropertyValue;
|
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
|
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
|
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
|
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
|
import org.alfresco.repo.transaction.TransactionListenerAdapter;
|
|
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
|
|
import org.alfresco.service.cmr.avm.AVMService;
|
|
import org.alfresco.service.cmr.avm.locking.AVMLockingService;
|
|
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
|
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
|
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.search.ResultSet;
|
|
import org.alfresco.service.cmr.search.SearchService;
|
|
import org.alfresco.service.cmr.security.AccessStatus;
|
|
import org.alfresco.service.cmr.security.AuthorityService;
|
|
import org.alfresco.service.cmr.security.AuthorityType;
|
|
import org.alfresco.service.cmr.security.PermissionService;
|
|
import org.alfresco.service.cmr.security.PersonService;
|
|
import org.alfresco.service.namespace.NamespaceService;
|
|
import org.alfresco.service.namespace.QName;
|
|
import org.alfresco.service.namespace.RegexQNamePattern;
|
|
import org.alfresco.util.DNSNameMangler;
|
|
import org.alfresco.util.ParameterCheck;
|
|
import org.alfresco.wcm.sandbox.SandboxFactory;
|
|
import org.alfresco.wcm.sandbox.SandboxInfo;
|
|
import org.alfresco.wcm.sandbox.SandboxFactory.UserRoleWrapper;
|
|
import org.alfresco.wcm.util.WCMUtil;
|
|
import org.apache.commons.logging.Log;
|
|
import org.apache.commons.logging.LogFactory;
|
|
|
|
/**
|
|
* Web Project Service Implementation
|
|
*
|
|
* @author janv
|
|
*/
|
|
public class WebProjectServiceImpl extends WCMUtil implements WebProjectService
|
|
{
|
|
/** Logger */
|
|
private static Log logger = LogFactory.getLog(WebProjectServiceImpl.class);
|
|
|
|
/** The DM store where web projects are kept */
|
|
public static final StoreRef WEBPROJECT_STORE = new StoreRef("workspace://SpacesStore");
|
|
|
|
/** The web projects root node reference */
|
|
private NodeRef webProjectsRootNodeRef; // note: WCM is not currently MT-enabled (so this is OK)
|
|
|
|
/** Services */
|
|
private NodeService nodeService;
|
|
private SearchService searchService;
|
|
private AVMService avmService;
|
|
private AVMLockingService avmLockingService;
|
|
private AuthorityService authorityService;
|
|
private PermissionService permissionService;
|
|
private PersonService personService;
|
|
|
|
private SandboxFactory sandboxFactory;
|
|
private VirtServerRegistry virtServerRegistry;
|
|
|
|
public void setNodeService(NodeService nodeService)
|
|
{
|
|
this.nodeService = nodeService;
|
|
}
|
|
|
|
public void setSearchService(SearchService searchService)
|
|
{
|
|
this.searchService = searchService;
|
|
}
|
|
|
|
public void setAvmService(AVMService avmService)
|
|
{
|
|
this.avmService = avmService;
|
|
}
|
|
|
|
public void setAvmLockingService(AVMLockingService avmLockingService)
|
|
{
|
|
this.avmLockingService = avmLockingService;
|
|
}
|
|
|
|
public void setAuthorityService(AuthorityService authorityService)
|
|
{
|
|
this.authorityService = authorityService;
|
|
}
|
|
|
|
public void setPermissionService(PermissionService permissionService)
|
|
{
|
|
this.permissionService = permissionService;
|
|
}
|
|
|
|
public void setPersonService(PersonService personService)
|
|
{
|
|
this.personService = personService;
|
|
}
|
|
|
|
public void setSandboxFactory(SandboxFactory sandboxFactory)
|
|
{
|
|
this.sandboxFactory = sandboxFactory;
|
|
}
|
|
|
|
public void setVirtServerRegistry(VirtServerRegistry virtServerRegistry)
|
|
{
|
|
this.virtServerRegistry = virtServerRegistry;
|
|
}
|
|
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.WebProjectService#createWebProject(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
|
|
*/
|
|
public WebProjectInfo createWebProject(String dnsName, String name, String title, String description)
|
|
{
|
|
return createWebProject(dnsName, name, title, description, null, false, null);
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.WebProjectService#createWebProject(java.lang.String, java.lang.String, java.lang.String, java.lang.String, org.alfresco.service.cmr.repository.NodeRef)
|
|
*/
|
|
public WebProjectInfo createWebProject(String dnsName, String name, String title, String description, NodeRef sourceNodeRef)
|
|
{
|
|
return createWebProject(dnsName, name, title, description, null, false, sourceNodeRef);
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.WebProjectService#createWebProject(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, boolean, org.alfresco.service.cmr.repository.NodeRef)
|
|
*/
|
|
public WebProjectInfo createWebProject(String dnsName, String name, String title, String description, String defaultWebApp, boolean useAsTemplate, NodeRef sourceNodeRef)
|
|
{
|
|
// Generate web project store id (an AVM store name)
|
|
String wpStoreId = DNSNameMangler.MakeDNSName(dnsName);
|
|
|
|
if (wpStoreId.indexOf(WCMUtil.STORE_SEPARATOR) != -1)
|
|
{
|
|
throw new IllegalArgumentException("Unexpected store id '"+wpStoreId+"' - should not contain '"+WCMUtil.STORE_SEPARATOR+"'");
|
|
}
|
|
|
|
if (wpStoreId.indexOf(WCMUtil.AVM_STORE_SEPARATOR) != -1)
|
|
{
|
|
throw new IllegalArgumentException("Unexpected store id '"+wpStoreId+"' - should not contain '"+WCMUtil.AVM_STORE_SEPARATOR+"'");
|
|
}
|
|
|
|
// create the website space in the correct parent folder
|
|
Map<QName, Serializable> props = new HashMap<QName, Serializable>(1);
|
|
props.put(ContentModel.PROP_NAME, name);
|
|
|
|
ChildAssociationRef childAssocRef = nodeService.createNode(
|
|
getWebProjectsRoot(),
|
|
ContentModel.ASSOC_CONTAINS,
|
|
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName(name)),
|
|
WCMAppModel.TYPE_AVMWEBFOLDER,
|
|
props);
|
|
|
|
NodeRef wpNodeRef = childAssocRef.getChildRef();
|
|
|
|
|
|
// apply the uifacets aspect - icon, title and description props
|
|
Map<QName, Serializable> uiFacetsProps = new HashMap<QName, Serializable>(4);
|
|
uiFacetsProps.put(ApplicationModel.PROP_ICON, WCMUtil.SPACE_ICON_WEBSITE);
|
|
uiFacetsProps.put(ContentModel.PROP_TITLE, title);
|
|
uiFacetsProps.put(ContentModel.PROP_DESCRIPTION, description);
|
|
nodeService.addAspect(wpNodeRef, ApplicationModel.ASPECT_UIFACETS, uiFacetsProps);
|
|
|
|
// use as template source flag
|
|
nodeService.setProperty(wpNodeRef, WCMAppModel.PROP_ISSOURCE, useAsTemplate);
|
|
|
|
// set the default webapp name for the project
|
|
defaultWebApp = (defaultWebApp != null && defaultWebApp.length() != 0) ? defaultWebApp : WCMUtil.DIR_ROOT;
|
|
nodeService.setProperty(wpNodeRef, WCMAppModel.PROP_DEFAULTWEBAPP, defaultWebApp);
|
|
|
|
// set the property on the node to reference the root AVM store
|
|
nodeService.setProperty(wpNodeRef, WCMAppModel.PROP_AVMSTORE, wpStoreId);
|
|
|
|
// branch from source web project, if supplied
|
|
String branchStoreId = null;
|
|
if (sourceNodeRef != null)
|
|
{
|
|
branchStoreId = (String)nodeService.getProperty(sourceNodeRef, WCMAppModel.PROP_AVMSTORE);
|
|
}
|
|
|
|
// create the AVM staging store to represent the newly created location website
|
|
sandboxFactory.createStagingSandbox(wpStoreId, wpNodeRef, branchStoreId); // ignore return, fails if web project already exists
|
|
|
|
// create the default webapp folder under the hidden system folders
|
|
if (branchStoreId == null)
|
|
{
|
|
String stagingStore = WCMUtil.buildStagingStoreName(wpStoreId);
|
|
String stagingStoreRoot = WCMUtil.buildSandboxRootPath(stagingStore);
|
|
avmService.createDirectory(stagingStoreRoot, defaultWebApp);
|
|
avmService.addAspect(AVMNodeConverter.ExtendAVMPath(stagingStoreRoot, defaultWebApp), WCMAppModel.ASPECT_WEBAPP);
|
|
}
|
|
|
|
// now the sandbox is created set the permissions masks for the store
|
|
sandboxFactory.setStagingPermissionMasks(wpStoreId);
|
|
|
|
// set the property on the node to reference the root AVM store
|
|
nodeService.setProperty(wpNodeRef, WCMAppModel.PROP_AVMSTORE, wpStoreId);
|
|
|
|
// inform the locking service about this new instance
|
|
avmLockingService.addWebProject(wpStoreId);
|
|
|
|
// Snapshot the store with the empty webapp
|
|
avmService.createSnapshot(wpStoreId, null, null);
|
|
|
|
// break the permissions inheritance on the web project node so that only assigned users can access it
|
|
permissionService.setInheritParentPermissions(wpNodeRef, false);
|
|
|
|
// TODO: Currently auto-creates author sandbox for creator of web project (eg. an admin or a DM contributor to web projects root space)
|
|
// NOTE: JSF client does not yet allow explicit creation of author sandboxes
|
|
inviteWebUser(wpNodeRef, AuthenticationUtil.getRunAsUser(), WCMUtil.ROLE_CONTENT_MANAGER, true);
|
|
|
|
// Bind the post-commit transaction listener with data required for virtualization server notification
|
|
CreateWebProjectTransactionListener tl = new CreateWebProjectTransactionListener(wpStoreId);
|
|
AlfrescoTransactionSupport.bindListener(tl);
|
|
|
|
if (logger.isInfoEnabled())
|
|
{
|
|
logger.info("Created web project: " + wpNodeRef + " (store id: " + wpStoreId + ")");
|
|
}
|
|
|
|
// Return created web project info
|
|
WebProjectInfo wpInfo = new WebProjectInfoImpl(name, title, description, wpStoreId, defaultWebApp, useAsTemplate, wpNodeRef);
|
|
return wpInfo;
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#createWebApp(java.lang.String, java.lang.String, java.lang.String)
|
|
*/
|
|
public void createWebApp(String wpStoreId, String webAppName, String webAppDescription)
|
|
{
|
|
createWebApp(getWebProjectNodeFromStore(wpStoreId), webAppName, webAppDescription);
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#createWebApp(org.alfresco.service.cmr.repository.NodeRef, java.lang.String, java.lang.String)
|
|
*/
|
|
public void createWebApp(NodeRef wpNodeRef, final String webAppName, final String webAppDescription)
|
|
{
|
|
WebProjectInfo wpInfo = getWebProject(wpNodeRef);
|
|
|
|
if (isContentManager(wpNodeRef))
|
|
{
|
|
// get AVM store name of the staging sandbox
|
|
final String stagingStoreId = wpInfo.getStagingStoreName();
|
|
|
|
AuthenticationUtil.runAs(new RunAsWork<Object>()
|
|
{
|
|
public Object doWork() throws Exception
|
|
{
|
|
final String parent = WCMUtil.buildSandboxRootPath(stagingStoreId);
|
|
avmService.createDirectory(parent, webAppName);
|
|
|
|
String path = AVMNodeConverter.ExtendAVMPath(parent, webAppName);
|
|
avmService.addAspect(path, ApplicationModel.ASPECT_UIFACETS);
|
|
avmService.addAspect(path, WCMAppModel.ASPECT_WEBAPP);
|
|
|
|
if (webAppDescription != null && webAppDescription.length() != 0)
|
|
{
|
|
avmService.setNodeProperty(path,
|
|
ContentModel.PROP_DESCRIPTION,
|
|
new PropertyValue(DataTypeDefinition.TEXT,
|
|
webAppDescription));
|
|
}
|
|
|
|
// Snapshot the store with the empty webapp
|
|
avmService.createSnapshot(stagingStoreId, null, null);
|
|
|
|
return null;
|
|
}
|
|
}, AuthenticationUtil.getSystemUserName());
|
|
|
|
if (logger.isInfoEnabled())
|
|
{
|
|
logger.info("Created web app: "+webAppName+" (store id: "+wpInfo.getStoreId()+")");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new AccessDeniedException("Only content managers may create new webapp '"+webAppName+"' (store id: "+wpInfo.getStoreId()+")");
|
|
}
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#listWebApps(java.lang.String)
|
|
*/
|
|
public List<String> listWebApps(String wpStoreId)
|
|
{
|
|
return listWebApps(getWebProjectNodeFromStore(wpStoreId));
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#listWebApps(org.alfresco.service.cmr.repository.NodeRef)
|
|
*/
|
|
public List<String> listWebApps(NodeRef wpNodeRef)
|
|
{
|
|
WebProjectInfo wpInfo = getWebProject(wpNodeRef);
|
|
|
|
String path = WCMUtil.buildSandboxRootPath(wpInfo.getStagingStoreName());
|
|
Map<String, AVMNodeDescriptor> folders = avmService.getDirectoryListing(-1, path);
|
|
|
|
List<String> webAppNames = new ArrayList<String>(folders.size());
|
|
webAppNames.addAll(folders.keySet());
|
|
return webAppNames;
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#deleteWebApp(java.lang.String, java.lang.String)
|
|
*/
|
|
public void deleteWebApp(String wpStoreId, String webAppName)
|
|
{
|
|
deleteWebApp(getWebProjectNodeFromStore(wpStoreId), webAppName);
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#deleteWebApp(org.alfresco.service.cmr.repository.NodeRef, java.lang.String)
|
|
*/
|
|
public void deleteWebApp(NodeRef wpNodeRef, final String webAppName)
|
|
{
|
|
ParameterCheck.mandatoryString("webAppName", webAppName);
|
|
|
|
WebProjectInfo wpInfo = getWebProject(wpNodeRef);
|
|
|
|
if (webAppName.equals(wpInfo.getDefaultWebApp()))
|
|
{
|
|
throw new AlfrescoRuntimeException("Cannot delete default webapp '"+webAppName+"' (store id: "+wpInfo.getStoreId()+")");
|
|
}
|
|
else if (isContentManager(wpInfo.getNodeRef()))
|
|
{
|
|
// get AVM store name of the staging sandbox
|
|
final String wpStoreId = wpInfo.getStoreId();
|
|
|
|
AuthenticationUtil.runAs(new RunAsWork<Object>()
|
|
{
|
|
public Object doWork() throws Exception
|
|
{
|
|
final String parent = WCMUtil.buildSandboxRootPath(wpStoreId);
|
|
|
|
avmService.removeNode(parent, webAppName);
|
|
|
|
// Snapshot the store with the webapp removed
|
|
avmService.createSnapshot(wpStoreId, null, null);
|
|
|
|
return null;
|
|
}
|
|
}, AuthenticationUtil.getSystemUserName());
|
|
|
|
if (logger.isInfoEnabled())
|
|
{
|
|
logger.info("Deleted web app: "+webAppName+" (store id: "+wpStoreId+")");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new AccessDeniedException("Only content managers may delete webapp '"+webAppName+"' (web project: "+wpNodeRef+")");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the node reference that is the web projects root
|
|
*
|
|
* @return NodeRef node reference
|
|
*/
|
|
public NodeRef getWebProjectsRoot()
|
|
{
|
|
if (this.webProjectsRootNodeRef == null)
|
|
{
|
|
// Get the root 'web projects' folder
|
|
ResultSet resultSet = null;
|
|
try
|
|
{
|
|
resultSet = this.searchService.query(WEBPROJECT_STORE, SearchService.LANGUAGE_LUCENE, "PATH:\""+getWebProjectsPath()+"\"");
|
|
if (resultSet.length() == 0)
|
|
{
|
|
// No root web projects folder exists
|
|
throw new AlfrescoRuntimeException("No root 'Web Projects' folder exists (is WCM enabled ?)");
|
|
}
|
|
else if (resultSet.length() != 1)
|
|
{
|
|
// More than one root web projects folder exits
|
|
throw new AlfrescoRuntimeException("More than one root 'Web Projects' folder exists");
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
if (resultSet != null)
|
|
{
|
|
resultSet.close();
|
|
}
|
|
}
|
|
|
|
this.webProjectsRootNodeRef = resultSet.getNodeRef(0);
|
|
}
|
|
|
|
return this.webProjectsRootNodeRef;
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#listWebProjects()
|
|
*/
|
|
public List<WebProjectInfo> listWebProjects()
|
|
{
|
|
NodeRef wpRoot = getWebProjectsRoot();
|
|
|
|
Set<QName> nodeTypeQNames = new HashSet<QName>(1);
|
|
nodeTypeQNames.add(WCMAppModel.TYPE_AVMWEBFOLDER);
|
|
List<ChildAssociationRef> webProjects = nodeService.getChildAssocs(wpRoot, nodeTypeQNames);
|
|
|
|
List<WebProjectInfo> result = new ArrayList<WebProjectInfo>(webProjects.size());
|
|
for (ChildAssociationRef childAssocRefs : webProjects)
|
|
{
|
|
result.add(getWebProject(childAssocRefs.getChildRef()));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#listWebProjects(java.lang.String)
|
|
*/
|
|
public List<WebProjectInfo> listWebProjects(String userName)
|
|
{
|
|
List<WebProjectInfo> webProjects = listWebProjects();
|
|
List<WebProjectInfo> result = new ArrayList<WebProjectInfo>(webProjects.size());
|
|
for (WebProjectInfo webProject : webProjects)
|
|
{
|
|
if (isWebUser(webProject.getNodeRef(), userName) == true)
|
|
{
|
|
result.add(webProject);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#isWebProject(java.lang.String)
|
|
*/
|
|
public boolean isWebProject(String wpStoreId)
|
|
{
|
|
NodeRef wpNodeRef = getWebProjectNodeFromStore(wpStoreId);
|
|
if (wpNodeRef == null)
|
|
{
|
|
return false;
|
|
}
|
|
return isWebProject(wpNodeRef);
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#isWebProject(org.alfresco.service.cmr.repository.NodeRef)
|
|
*/
|
|
public boolean isWebProject(NodeRef wpNodeRef)
|
|
{
|
|
if (wpNodeRef == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
try
|
|
{
|
|
return (WCMAppModel.TYPE_AVMWEBFOLDER.equals(nodeService.getType(wpNodeRef)));
|
|
}
|
|
catch (InvalidNodeRefException e)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#getWebProject(java.lang.String)
|
|
*/
|
|
public WebProjectInfo getWebProject(String wpStoreId)
|
|
{
|
|
WebProjectInfo result = null;
|
|
|
|
// Get the web project node
|
|
NodeRef wpNodeRef = getWebProjectNodeFromStore(wpStoreId);
|
|
if (wpNodeRef != null)
|
|
{
|
|
// Create the web project info
|
|
result = getWebProject(wpNodeRef);
|
|
}
|
|
|
|
// Return the web project info
|
|
return result;
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#getWebProject(org.alfresco.service.cmr.repository.NodeRef)
|
|
*/
|
|
public WebProjectInfo getWebProject(NodeRef wpNodeRef)
|
|
{
|
|
if (! isWebProject(wpNodeRef))
|
|
{
|
|
throw new IllegalArgumentException(wpNodeRef + " is not a web project");
|
|
}
|
|
|
|
// Get the properties
|
|
Map<QName, Serializable> properties = this.nodeService.getProperties(wpNodeRef);
|
|
|
|
String name = (String)properties.get(ContentModel.PROP_NAME);
|
|
String title = (String)properties.get(ContentModel.PROP_TITLE);
|
|
String description = (String)properties.get(ContentModel.PROP_DESCRIPTION);
|
|
String wpStoreId = (String)properties.get(WCMAppModel.PROP_AVMSTORE);
|
|
String defaultWebApp = (String)properties.get(WCMAppModel.PROP_DEFAULTWEBAPP);
|
|
Boolean useAsTemplate = (Boolean)properties.get(WCMAppModel.PROP_ISSOURCE);
|
|
|
|
// Create and return the web project info
|
|
WebProjectInfo wpInfo = new WebProjectInfoImpl(name, title, description, wpStoreId, defaultWebApp, useAsTemplate, wpNodeRef);
|
|
return wpInfo;
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#updateWebProject(org.alfresco.wcm.webproject.WebProjectInfo)
|
|
*/
|
|
public void updateWebProject(WebProjectInfo wpInfo)
|
|
{
|
|
NodeRef wpNodeRef = getWebProjectNodeFromStore(wpInfo.getStoreId());
|
|
if (wpNodeRef == null)
|
|
{
|
|
throw new AlfrescoRuntimeException("Cannot update web project '" + wpInfo.getStoreId() + "' because it does not exist.");
|
|
}
|
|
|
|
// Note: the site preset and short name can not be updated
|
|
|
|
// Update the properties of the site - note: cannot change storeId or wpNodeRef
|
|
Map<QName, Serializable> properties = this.nodeService.getProperties(wpNodeRef);
|
|
|
|
properties.put(ContentModel.PROP_NAME, wpInfo.getName());
|
|
properties.put(ContentModel.PROP_TITLE, wpInfo.getTitle());
|
|
properties.put(ContentModel.PROP_DESCRIPTION, wpInfo.getDescription());
|
|
properties.put(WCMAppModel.PROP_DEFAULTWEBAPP, wpInfo.getDefaultWebApp());
|
|
properties.put(WCMAppModel.PROP_ISSOURCE, wpInfo.isTemplate());
|
|
|
|
this.nodeService.setProperties(wpNodeRef, properties);
|
|
|
|
if (logger.isDebugEnabled())
|
|
{
|
|
logger.debug("Updated web project: " + wpNodeRef + " (store id: " + wpInfo.getStoreId() + ")");
|
|
}
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#deleteWebProject(java.lang.String)
|
|
*/
|
|
public void deleteWebProject(String wpStoreId)
|
|
{
|
|
NodeRef wpNodeRef = getWebProjectNodeFromStore(wpStoreId);
|
|
if (wpNodeRef != null)
|
|
{
|
|
deleteWebProject(wpNodeRef);
|
|
}
|
|
else
|
|
{
|
|
// by definition, the current user is not a content manager since the web project does not exist (or is not visible)
|
|
throw new AccessDeniedException("Only content managers may delete a web project");
|
|
}
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#deleteWebProject(org.alfresco.service.cmr.repository.NodeRef)
|
|
*/
|
|
public void deleteWebProject(final NodeRef wpNodeRef)
|
|
{
|
|
if (! isContentManager(wpNodeRef))
|
|
{
|
|
// the current user is not a content manager since the web project does not exist (or is not visible)
|
|
throw new AccessDeniedException("Only content managers may delete web project");
|
|
}
|
|
|
|
// delete all attached website sandboxes in reverse order to the layering
|
|
final String wpStoreId = (String)nodeService.getProperty(wpNodeRef, WCMAppModel.PROP_AVMSTORE);
|
|
|
|
if (wpStoreId != null)
|
|
{
|
|
// Notifiy virtualization server about removing this website
|
|
//
|
|
// Implementation note:
|
|
//
|
|
// Because the removal of virtual webapps in the virtualization
|
|
// server is recursive, it only needs to be given the name of
|
|
// the main staging store.
|
|
//
|
|
// This notification must occur *prior* to purging content
|
|
// within the AVM because the virtualization server must list
|
|
// the avm_webapps dir in each store to discover which
|
|
// virtual webapps must be unloaded. The virtualization
|
|
// server traverses the sandbox's stores in most-to-least
|
|
// dependent order, so clients don't have to worry about
|
|
// accessing a preview layer whose main layer has been torn
|
|
// out from under it.
|
|
//
|
|
// It does not matter what webapp name we give here, so "/ROOT"
|
|
// is as sensible as anything else. It's all going away.
|
|
|
|
String sandbox = WCMUtil.buildStagingStoreName(wpStoreId);
|
|
String path = WCMUtil.buildStoreWebappPath(sandbox, "/ROOT");
|
|
|
|
WCMUtil.removeAllVServerWebapps(virtServerRegistry, path, true);
|
|
|
|
AuthenticationUtil.runAs(new RunAsWork<Object>()
|
|
{
|
|
public Object doWork() throws Exception
|
|
{
|
|
List<SandboxInfo> sbInfos = sandboxFactory.listAllSandboxes(wpStoreId);
|
|
|
|
for (SandboxInfo sbInfo : sbInfos)
|
|
{
|
|
// delete sandbox
|
|
sandboxFactory.deleteSandbox(sbInfo.getSandboxId());
|
|
}
|
|
|
|
// TODO delete workflow sandboxes !
|
|
|
|
// delete the web project node itself
|
|
nodeService.deleteNode(wpNodeRef);
|
|
|
|
return null;
|
|
}
|
|
}, AuthenticationUtil.getSystemUserName());
|
|
|
|
if (logger.isInfoEnabled())
|
|
{
|
|
logger.info("Deleted web project: " + wpNodeRef + " (store id: " + wpStoreId + ")");
|
|
}
|
|
}
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#isContentManager(java.lang.String)
|
|
*/
|
|
public boolean isContentManager(String storeName)
|
|
{
|
|
return isContentManager(storeName, AuthenticationUtil.getRunAsUser());
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.WebProjectService#isContentManager(java.lang.String, java.lang.String)
|
|
*/
|
|
public boolean isContentManager(String wpStoreId, String userName)
|
|
{
|
|
return isContentManager(getWebProjectNodeFromStore(wpStoreId), userName);
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#isContentManager(org.alfresco.service.cmr.repository.NodeRef)
|
|
*/
|
|
public boolean isContentManager(NodeRef wpNodeRef)
|
|
{
|
|
return isContentManager(wpNodeRef, AuthenticationUtil.getRunAsUser());
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#isContentManager(org.alfresco.service.cmr.repository.NodeRef, java.lang.String)
|
|
*/
|
|
public boolean isContentManager(NodeRef wpNodeRef, String userName)
|
|
{
|
|
String userRole = getWebUserRole(wpNodeRef, userName);
|
|
return WCMUtil.ROLE_CONTENT_MANAGER.equals(userRole);
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#isWebUser(java.lang.String)
|
|
*/
|
|
public boolean isWebUser(String wpStoreId)
|
|
{
|
|
return isWebUser(getWebProjectNodeFromStore(wpStoreId));
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#isWebUser(org.alfresco.service.cmr.repository.NodeRef)
|
|
*/
|
|
public boolean isWebUser(NodeRef wpNodeRef)
|
|
{
|
|
// note: admin is an implied web user (content manager) although will not appear in listWebUsers unless explicitly invited
|
|
return (permissionService.hasPermission(wpNodeRef, PermissionService.READ) == AccessStatus.ALLOWED);
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#isWebUser(java.lang.String, java.lang.String)
|
|
*/
|
|
public boolean isWebUser(String wpStoreId, String username)
|
|
{
|
|
return isWebUser(getWebProjectNodeFromStore(wpStoreId), username);
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#isWebUser(org.alfresco.service.cmr.repository.NodeRef, java.lang.String)
|
|
*/
|
|
public boolean isWebUser(final NodeRef wpNodeRef, String userName)
|
|
{
|
|
return AuthenticationUtil.runAs(new RunAsWork<Boolean>()
|
|
{
|
|
public Boolean doWork() throws Exception
|
|
{
|
|
return isWebUser(wpNodeRef);
|
|
}
|
|
}, userName);
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#getWebUserCount(org.alfresco.service.cmr.repository.NodeRef)
|
|
*/
|
|
public int getWebUserCount(NodeRef wpNodeRef)
|
|
{
|
|
return WCMUtil.listWebUsers(nodeService, wpNodeRef).size();
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#listWebUsers(java.lang.String)
|
|
*/
|
|
public Map<String, String> listWebUsers(String wpStoreId)
|
|
{
|
|
return listWebUsers(getWebProjectNodeFromStore(wpStoreId));
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#listWebUsers(org.alfresco.service.cmr.repository.NodeRef)
|
|
*/
|
|
public Map<String, String> listWebUsers(NodeRef wpNodeRef)
|
|
{
|
|
// special case: allow System - eg. to allow user to create their own sandbox on-demand (createAuthorSandbox)
|
|
if (isContentManager(wpNodeRef)
|
|
|| (AuthenticationUtil.getRunAsUser().equals(AuthenticationUtil.getSystemUserName())
|
|
|| (permissionService.hasPermission(wpNodeRef, PermissionService.ADD_CHILDREN) == AccessStatus.ALLOWED)))
|
|
{
|
|
return WCMUtil.listWebUsers(nodeService, wpNodeRef);
|
|
}
|
|
else
|
|
{
|
|
throw new AccessDeniedException("Only content managers may list users in a web project");
|
|
}
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#getWebUserRole(java.lang.String, java.lang.String)
|
|
*/
|
|
public String getWebUserRole(String wpStoreId, String userName)
|
|
{
|
|
return getWebUserRole(getWebProjectNodeFromStore(wpStoreId), userName);
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#getWebUserRole(org.alfresco.service.cmr.repository.NodeRef, java.lang.String)
|
|
*/
|
|
public String getWebUserRole(NodeRef wpNodeRef, String userName)
|
|
{
|
|
ParameterCheck.mandatoryString("userName", userName);
|
|
|
|
String userRole = null;
|
|
|
|
if (! isWebProject(wpNodeRef))
|
|
{
|
|
logger.warn(wpNodeRef + " is not a web project");
|
|
return null;
|
|
}
|
|
|
|
if (authorityService.isAdminAuthority(userName))
|
|
{
|
|
// fake the Content Manager role for an admin user
|
|
userRole = WCMUtil.ROLE_CONTENT_MANAGER;
|
|
}
|
|
else
|
|
{
|
|
userRole = getWebUserRoleImpl(wpNodeRef, userName);
|
|
}
|
|
|
|
return userRole;
|
|
}
|
|
|
|
private String getWebUserRoleImpl(NodeRef wpNodeRef, String userName)
|
|
{
|
|
NodeRef userRef = getWebUserRef(wpNodeRef, userName);
|
|
String userRole = null;
|
|
|
|
if (userRef != null)
|
|
{
|
|
userRole = (String)nodeService.getProperty(userRef, WCMAppModel.PROP_WEBUSERROLE);
|
|
}
|
|
|
|
return userRole;
|
|
}
|
|
|
|
private NodeRef getWebUserRef(NodeRef wpNodeRef, String userName)
|
|
{
|
|
StringBuilder query = new StringBuilder(128);
|
|
query.append("+PARENT:\"").append(wpNodeRef).append("\" ");
|
|
query.append("+TYPE:\"").append(WCMAppModel.TYPE_WEBUSER).append("\" ");
|
|
query.append("+@").append(NamespaceService.WCMAPP_MODEL_PREFIX).append("\\:username:\"");
|
|
query.append(userName);
|
|
query.append("\"");
|
|
|
|
ResultSet resultSet = null;
|
|
List<NodeRef> nodes = null;
|
|
try
|
|
{
|
|
resultSet = searchService.query(
|
|
WEBPROJECT_STORE,
|
|
SearchService.LANGUAGE_LUCENE,
|
|
query.toString());
|
|
nodes = resultSet.getNodeRefs();
|
|
}
|
|
finally
|
|
{
|
|
if (resultSet != null)
|
|
{
|
|
resultSet.close();
|
|
}
|
|
}
|
|
|
|
if (nodes.size() == 1)
|
|
{
|
|
return nodes.get(0);
|
|
}
|
|
else if (nodes.size() == 0)
|
|
{
|
|
if (logger.isTraceEnabled())
|
|
{
|
|
logger.trace("getWebUserRef: web user ("+userName+") not found in web project: "+wpNodeRef);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
logger.error("getWebUserRef: more than one web user ("+userName+") found in web project: "+wpNodeRef);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#findWebProjectNodeFromPath(java.lang.String)
|
|
*/
|
|
public NodeRef getWebProjectNodeFromPath(String absoluteAVMPath)
|
|
{
|
|
return getWebProjectNodeFromStore(WCMUtil.getWebProjectStoreIdFromPath(absoluteAVMPath));
|
|
}
|
|
|
|
/*(non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#getWebProjectNodeFromStore(java.lang.String)
|
|
*/
|
|
public NodeRef getWebProjectNodeFromStore(String wpStoreId)
|
|
{
|
|
ParameterCheck.mandatoryString("wpStoreId", wpStoreId);
|
|
|
|
return WCMUtil.getWebProjectNodeFromWebProjectStore(avmService, wpStoreId);
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#inviteWebUsersGroups(java.lang.String, java.util.Map)
|
|
*/
|
|
public void inviteWebUsersGroups(String wpStoreId, Map<String, String> userGroupRoles)
|
|
{
|
|
inviteWebUsersGroups(getWebProjectNodeFromStore(wpStoreId), userGroupRoles, false);
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#inviteWebUsersGroups(java.lang.String, java.util.Map, boolean)
|
|
*/
|
|
public void inviteWebUsersGroups(String wpStoreId, Map<String, String> userGroupRoles, boolean autoCreateAuthorSandbox)
|
|
{
|
|
inviteWebUsersGroups(getWebProjectNodeFromStore(wpStoreId), userGroupRoles, autoCreateAuthorSandbox);
|
|
}
|
|
|
|
public void inviteWebUsersGroups(NodeRef wpNodeRef, Map<String, String> userGroupRoles, boolean autoCreateAuthorSandbox)
|
|
{
|
|
if (! (isContentManager(wpNodeRef) ||
|
|
permissionService.hasPermission(wpNodeRef, PermissionService.ADD_CHILDREN) == AccessStatus.ALLOWED))
|
|
{
|
|
throw new AccessDeniedException("Only content managers may invite web users");
|
|
}
|
|
|
|
WebProjectInfo wpInfo = getWebProject(wpNodeRef);
|
|
String wpStoreId = wpInfo.getStoreId();
|
|
|
|
// build a list of managers who will have full permissions on ALL staging areas
|
|
List<String> managers = new ArrayList<String>(4);
|
|
Map<String, NodeRef> webSiteUsers = new HashMap<String, NodeRef>(8);
|
|
List<String> managersToRemove = new LinkedList<String>();
|
|
List<UserRoleWrapper> usersToUpdate = new LinkedList<UserRoleWrapper>();
|
|
|
|
// retrieve the list of managers from the existing users
|
|
for (Map.Entry<String, String> userRole : userGroupRoles.entrySet())
|
|
{
|
|
String authority = userRole.getKey();
|
|
String role = userRole.getValue();
|
|
|
|
for (String userAuth : findNestedUserAuthorities(authority))
|
|
{
|
|
if (WCMUtil.ROLE_CONTENT_MANAGER.equals(role))
|
|
{
|
|
managers.add(userAuth);
|
|
}
|
|
}
|
|
}
|
|
|
|
List<ChildAssociationRef> userInfoRefs = nodeService.getChildAssocs(wpNodeRef, WCMAppModel.ASSOC_WEBUSER, RegexQNamePattern.MATCH_ALL);
|
|
|
|
for (ChildAssociationRef ref : userInfoRefs)
|
|
{
|
|
NodeRef userInfoRef = ref.getChildRef();
|
|
String username = (String)nodeService.getProperty(userInfoRef, WCMAppModel.PROP_WEBUSERNAME);
|
|
String userrole = (String)nodeService.getProperty(userInfoRef, WCMAppModel.PROP_WEBUSERROLE);
|
|
|
|
if (WCMUtil.ROLE_CONTENT_MANAGER.equals(userrole) && managers.contains(username) == false)
|
|
{
|
|
managers.add(username);
|
|
}
|
|
|
|
// add each existing user to the map which will be rechecked for update changed user permissions
|
|
webSiteUsers.put(username, userInfoRef);
|
|
}
|
|
|
|
List<SandboxInfo> sandboxInfoList = new LinkedList<SandboxInfo>();
|
|
|
|
int invitedCount = 0;
|
|
boolean managersUpdateRequired = false;
|
|
|
|
for (Map.Entry<String, String> userRole : userGroupRoles.entrySet())
|
|
{
|
|
String authority = userRole.getKey();
|
|
String role = userRole.getValue();
|
|
|
|
for (String userAuth : findNestedUserAuthorities(authority))
|
|
{
|
|
if (webSiteUsers.keySet().contains(userAuth) == false)
|
|
{
|
|
if (autoCreateAuthorSandbox)
|
|
{
|
|
// create a sandbox for the user with permissions based on role
|
|
SandboxInfo sbInfo = sandboxFactory.createUserSandbox(wpStoreId, managers, userAuth, role);
|
|
sandboxInfoList.add(sbInfo);
|
|
}
|
|
|
|
sandboxFactory.addStagingAreaUser(wpStoreId, userAuth, role);
|
|
|
|
// create an app:webuser instance for each authority and assoc to the web project node
|
|
createWebUser(wpNodeRef, userAuth, role);
|
|
|
|
// if this new user is a manager, we'll need to update the manager permissions applied
|
|
// to each existing user sandbox - to ensure that new managers have access to them
|
|
managersUpdateRequired |= (WCMUtil.ROLE_CONTENT_MANAGER.equals(role));
|
|
|
|
invitedCount++;
|
|
}
|
|
else
|
|
{
|
|
// TODO - split out into separate 'change role'
|
|
// if user role have been changed then update required properties etc.
|
|
NodeRef userRef = webSiteUsers.get(userAuth);
|
|
String oldUserRole = (String)nodeService.getProperty(userRef, WCMAppModel.PROP_WEBUSERROLE);
|
|
|
|
if (!role.equals(oldUserRole))
|
|
{
|
|
// change in role
|
|
Map<QName, Serializable> props = nodeService.getProperties(userRef);
|
|
props.put(WCMAppModel.PROP_WEBUSERNAME, userAuth);
|
|
props.put(WCMAppModel.PROP_WEBUSERROLE, role);
|
|
nodeService.setProperties(userRef, props);
|
|
|
|
if (WCMUtil.ROLE_CONTENT_MANAGER.equals(role))
|
|
{
|
|
managersUpdateRequired = true;
|
|
}
|
|
else if (WCMUtil.ROLE_CONTENT_MANAGER.equals(oldUserRole))
|
|
{
|
|
managersToRemove.add(userAuth);
|
|
}
|
|
|
|
usersToUpdate.add(sandboxFactory.new UserRoleWrapper(userAuth, oldUserRole, role));
|
|
|
|
if (logger.isDebugEnabled())
|
|
{
|
|
logger.debug(userAuth +"'s role has been changed from '" + oldUserRole +
|
|
"' to '" + role + "'");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Bind the post-commit transaction listener with data required for virtualization server notification
|
|
CreateSandboxTransactionListener tl = new CreateSandboxTransactionListener(sandboxInfoList, listWebApps(wpNodeRef));
|
|
AlfrescoTransactionSupport.bindListener(tl);
|
|
|
|
if (managersUpdateRequired == true)
|
|
{
|
|
sandboxFactory.updateSandboxManagers(wpStoreId, managers);
|
|
}
|
|
|
|
// TODO - split out into separate 'change role'
|
|
// remove ex-managers from sandboxes
|
|
if (managersToRemove.size() != 0)
|
|
{
|
|
sandboxFactory.removeSandboxManagers(wpStoreId, managersToRemove);
|
|
}
|
|
|
|
// get permissions and roles for a web project folder type
|
|
Set<String> perms = permissionService.getSettablePermissions(WCMAppModel.TYPE_AVMWEBFOLDER);
|
|
|
|
// set permissions for each user
|
|
for (Map.Entry<String, String> userRole : userGroupRoles.entrySet())
|
|
{
|
|
String authority = userRole.getKey();
|
|
String role = userRole.getValue();
|
|
|
|
for (String permission : perms)
|
|
{
|
|
if (role.equals(permission))
|
|
{
|
|
permissionService.setPermission(wpNodeRef,
|
|
authority,
|
|
permission,
|
|
true);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// TODO - split out into separate 'change role'
|
|
// update user's roles
|
|
if (usersToUpdate.size() != 0)
|
|
{
|
|
sandboxFactory.updateSandboxRoles(wpStoreId, usersToUpdate, perms);
|
|
}
|
|
|
|
if (logger.isInfoEnabled())
|
|
{
|
|
logger.info("Invited "+invitedCount+" web users (store id: "+wpStoreId+")");
|
|
}
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#inviteWebUser(java.lang.String, java.lang.String, java.lang.String)
|
|
*/
|
|
public void inviteWebUser(String wpStoreId, String userAuth, String role)
|
|
{
|
|
inviteWebUser(getWebProjectNodeFromStore(wpStoreId), userAuth, role, false);
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#inviteWebUser(java.lang.String, java.lang.String, java.lang.String, boolean)
|
|
*/
|
|
public void inviteWebUser(String wpStoreId, String userAuth, String role, boolean autoCreateAuthorSandbox)
|
|
{
|
|
inviteWebUser(getWebProjectNodeFromStore(wpStoreId), userAuth, role, autoCreateAuthorSandbox);
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#inviteWebUser(org.alfresco.service.cmr.repository.NodeRef, java.lang.String, java.lang.String, boolean)
|
|
*/
|
|
public void inviteWebUser(NodeRef wpNodeRef, String userAuth, String role, boolean autoCreateAuthorSandbox)
|
|
{
|
|
if (! (isContentManager(wpNodeRef) ||
|
|
permissionService.hasPermission(wpNodeRef, PermissionService.ADD_CHILDREN) == AccessStatus.ALLOWED))
|
|
{
|
|
throw new AccessDeniedException("Only content managers may invite web user");
|
|
}
|
|
|
|
WebProjectInfo wpInfo = getWebProject(wpNodeRef);
|
|
final String wpStoreId = wpInfo.getStoreId();
|
|
|
|
// build a list of managers who will have full permissions on ALL staging areas
|
|
List<String> managers = new ArrayList<String>(4);
|
|
|
|
// retrieve the list of managers from the existing users
|
|
Map<String, String> existingUserRoles = listWebUsers(wpNodeRef);
|
|
for (Map.Entry<String, String> userRole : existingUserRoles.entrySet())
|
|
{
|
|
String username = userRole.getKey();
|
|
String userrole = userRole.getValue();
|
|
|
|
if (WCMUtil.ROLE_CONTENT_MANAGER.equals(userrole) && managers.contains(username) == false)
|
|
{
|
|
managers.add(username);
|
|
}
|
|
}
|
|
|
|
// get permissions and roles for a web project folder type
|
|
Set<String> perms = permissionService.getSettablePermissions(WCMAppModel.TYPE_AVMWEBFOLDER);
|
|
|
|
NodeRef userRef = getWebUserRef(wpNodeRef, userAuth);
|
|
if (userRef != null)
|
|
{
|
|
// TODO - split out into separate 'change role'
|
|
// if user role has been changed then update required properties etc.
|
|
String oldUserRole = (String)nodeService.getProperty(userRef, WCMAppModel.PROP_WEBUSERROLE);
|
|
if (!role.equals(oldUserRole))
|
|
{
|
|
// change in role
|
|
Map<QName, Serializable> props = nodeService.getProperties(userRef);
|
|
props.put(WCMAppModel.PROP_WEBUSERNAME, userAuth);
|
|
props.put(WCMAppModel.PROP_WEBUSERROLE, role);
|
|
nodeService.setProperties(userRef, props);
|
|
|
|
if (WCMUtil.ROLE_CONTENT_MANAGER.equals(role))
|
|
{
|
|
managers.add(userAuth);
|
|
sandboxFactory.updateSandboxManagers(wpStoreId, managers);
|
|
}
|
|
else if (WCMUtil.ROLE_CONTENT_MANAGER.equals(oldUserRole))
|
|
{
|
|
List<String> managersToRemove = new LinkedList<String>();
|
|
managersToRemove.add(userAuth);
|
|
|
|
sandboxFactory.removeSandboxManagers(wpStoreId, managersToRemove);
|
|
}
|
|
|
|
List<UserRoleWrapper> usersToUpdate = new LinkedList<UserRoleWrapper>();
|
|
usersToUpdate.add(sandboxFactory.new UserRoleWrapper(userAuth, oldUserRole, role));
|
|
|
|
sandboxFactory.updateSandboxRoles(wpStoreId, usersToUpdate, perms);
|
|
|
|
if (logger.isInfoEnabled())
|
|
{
|
|
logger.info("Web user "+userAuth +"'s role has been changed from '" + oldUserRole + "' to '" + role + "' (store id: "+wpStoreId+")");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (autoCreateAuthorSandbox)
|
|
{
|
|
// create a sandbox for the user with permissions based on role
|
|
SandboxInfo sbInfo = sandboxFactory.createUserSandbox(wpStoreId, managers, userAuth, role);
|
|
|
|
List<SandboxInfo> sandboxInfoList = new LinkedList<SandboxInfo>();
|
|
sandboxInfoList.add(sbInfo);
|
|
|
|
// Bind the post-commit transaction listener with data required for virtualization server notification
|
|
CreateSandboxTransactionListener tl = new CreateSandboxTransactionListener(sandboxInfoList, listWebApps(wpNodeRef));
|
|
AlfrescoTransactionSupport.bindListener(tl);
|
|
}
|
|
|
|
// if this new user is a manager, we'll need to update the manager permissions applied
|
|
// to each existing user sandbox - to ensure that new user has access to them
|
|
if (WCMUtil.ROLE_CONTENT_MANAGER.equals(role))
|
|
{
|
|
managers.add(userAuth);
|
|
sandboxFactory.updateSandboxManagers(wpStoreId, managers);
|
|
}
|
|
|
|
sandboxFactory.addStagingAreaUser(wpStoreId, userAuth, role);
|
|
|
|
// create an app:webuser instance for the user and assoc to the web project node
|
|
createWebUser(wpNodeRef, userAuth, role);
|
|
|
|
// set permissions for the user
|
|
for (String permission : perms)
|
|
{
|
|
if (role.equals(permission))
|
|
{
|
|
permissionService.setPermission(wpNodeRef,
|
|
userAuth,
|
|
permission,
|
|
true);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (logger.isInfoEnabled())
|
|
{
|
|
logger.info("Invited web user: "+userAuth+" (store id: "+wpStoreId+")");
|
|
}
|
|
}
|
|
}
|
|
|
|
private void createWebUser(NodeRef wpNodeRef, String userName, String userRole)
|
|
{
|
|
// create an app:webuser instance for the user and assoc to the web project node
|
|
Map<QName, Serializable> props = new HashMap<QName, Serializable>(2, 1.0f);
|
|
props.put(WCMAppModel.PROP_WEBUSERNAME, userName);
|
|
props.put(WCMAppModel.PROP_WEBUSERROLE, userRole);
|
|
nodeService.createNode(wpNodeRef,
|
|
WCMAppModel.ASSOC_WEBUSER,
|
|
WCMAppModel.ASSOC_WEBUSER,
|
|
WCMAppModel.TYPE_WEBUSER,
|
|
props);
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#uninviteWebUser(java.lang.String, java.lang.String)
|
|
*/
|
|
public void uninviteWebUser(String wpStoreId, String userAuth)
|
|
{
|
|
uninviteWebUser(getWebProjectNodeFromStore(wpStoreId), userAuth, false);
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#uninviteWebUser(java.lang.String, java.lang.String, boolean)
|
|
*/
|
|
public void uninviteWebUser(String wpStoreId, String userAuth, boolean autoDeleteAuthorSandbox)
|
|
{
|
|
uninviteWebUser(getWebProjectNodeFromStore(wpStoreId), userAuth, autoDeleteAuthorSandbox);
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.alfresco.wcm.webproject.WebProjectService#uninviteWebUser(org.alfresco.service.cmr.repository.NodeRef, java.lang.String, boolean)
|
|
*/
|
|
public void uninviteWebUser(NodeRef wpNodeRef, String userAuth, boolean autoDeleteAuthorSandbox)
|
|
{
|
|
if (! isContentManager(wpNodeRef))
|
|
{
|
|
throw new AccessDeniedException("Only content managers may uninvite web user '"+userAuth+"' from web project: "+wpNodeRef);
|
|
}
|
|
|
|
ParameterCheck.mandatory("wpNodeRef", wpNodeRef);
|
|
ParameterCheck.mandatoryString("userAuth", userAuth);
|
|
|
|
WebProjectInfo wpInfo = getWebProject(wpNodeRef);
|
|
String wpStoreId = wpInfo.getStoreId();
|
|
String userMainStore = WCMUtil.buildUserMainStoreName(wpStoreId, userAuth);
|
|
|
|
if (autoDeleteAuthorSandbox)
|
|
{
|
|
sandboxFactory.deleteSandbox(userMainStore);
|
|
}
|
|
|
|
// remove the store reference from the website folder meta-data (see also WCMUtil.listWebUsers)
|
|
List<ChildAssociationRef> userInfoRefs = nodeService.getChildAssocs(wpNodeRef, WCMAppModel.ASSOC_WEBUSER, RegexQNamePattern.MATCH_ALL);
|
|
|
|
// retrieve the list of managers from the existing users
|
|
List<String> managers = new ArrayList<String>(4);
|
|
for (ChildAssociationRef ref : userInfoRefs)
|
|
{
|
|
NodeRef userInfoRef = ref.getChildRef();
|
|
String username = (String)nodeService.getProperty(userInfoRef, WCMAppModel.PROP_WEBUSERNAME);
|
|
String userrole = (String)nodeService.getProperty(userInfoRef, WCMAppModel.PROP_WEBUSERROLE);
|
|
|
|
if (WCMUtil.ROLE_CONTENT_MANAGER.equals(userrole) && managers.contains(username) == false)
|
|
{
|
|
managers.add(username);
|
|
}
|
|
}
|
|
|
|
for (ChildAssociationRef ref : userInfoRefs)
|
|
{
|
|
NodeRef userInfoRef = ref.getChildRef();
|
|
String user = (String)nodeService.getProperty(userInfoRef, WCMAppModel.PROP_WEBUSERNAME);
|
|
|
|
if (userAuth.equals(user))
|
|
{
|
|
// remove the association to this web project user meta-data
|
|
nodeService.removeChild(wpNodeRef, ref.getChildRef());
|
|
|
|
// remove permission for the user (also fixes ETWOONE-338)
|
|
permissionService.clearPermission(wpNodeRef, userAuth);
|
|
|
|
if (logger.isInfoEnabled())
|
|
{
|
|
logger.info("Uninvited web user: "+userAuth+" (store id: "+wpStoreId+")");
|
|
}
|
|
|
|
break; // for loop
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Find all nested user authorities contained with an authority
|
|
*
|
|
* @param authority The authority to search, USER authorities are returned immediately, GROUP authorites
|
|
* are recursively scanned for contained USER authorities.
|
|
*
|
|
* @return a Set of USER authorities
|
|
*/
|
|
private Set<String> findNestedUserAuthorities(String authority)
|
|
{
|
|
Set<String> users;
|
|
|
|
AuthorityType authType = AuthorityType.getAuthorityType(authority);
|
|
if (authType.equals(AuthorityType.USER))
|
|
{
|
|
users = new HashSet<String>(1, 1.0f);
|
|
if (personService.personExists(authority) == true)
|
|
{
|
|
users.add(authority);
|
|
}
|
|
}
|
|
else if (authType.equals(AuthorityType.GROUP))
|
|
{
|
|
// walk each member of the group
|
|
users = authorityService.getContainedAuthorities(AuthorityType.USER, authority, false);
|
|
for (String userAuth : users)
|
|
{
|
|
if (personService.personExists(userAuth) == false)
|
|
{
|
|
users.remove(authType);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
users = Collections.<String>emptySet();
|
|
}
|
|
|
|
return users;
|
|
}
|
|
|
|
private String getWebProjectsPath()
|
|
{
|
|
return "/"+SPACES_COMPANY_HOME_CHILDNAME+"/"+SPACES_WCM_CHILDNAME;
|
|
}
|
|
|
|
private static final String SPACES_COMPANY_HOME_CHILDNAME = "app:company_home"; // should match repository property: spaces.company_home.childname
|
|
private static final String SPACES_WCM_CHILDNAME = "app:wcm"; // should match repository property: spaces.wcm.childname
|
|
|
|
|
|
/**
|
|
* Transaction listener - invoked after commit
|
|
*/
|
|
private class CreateWebProjectTransactionListener extends TransactionListenerAdapter
|
|
{
|
|
private String wpStoreId;
|
|
|
|
public CreateWebProjectTransactionListener(String wpStoreId)
|
|
{
|
|
this.wpStoreId = wpStoreId;
|
|
}
|
|
|
|
/**
|
|
* @see org.alfresco.repo.transaction.TransactionListenerAdapter#afterCommit()
|
|
*/
|
|
@Override
|
|
public void afterCommit()
|
|
{
|
|
// post-commit
|
|
if (wpStoreId != null)
|
|
{
|
|
// update the virtualisation server with the default ROOT webapp path
|
|
// performed after the main txn has committed successfully
|
|
String newStoreName = WCMUtil.buildStagingStoreName(wpStoreId);
|
|
|
|
String path = WCMUtil.buildStoreWebappPath(newStoreName, WCMUtil.DIR_ROOT);
|
|
|
|
WCMUtil.updateVServerWebapp(virtServerRegistry, path, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create Sandbox Transaction listener - invoked after commit
|
|
*/
|
|
private class CreateSandboxTransactionListener extends TransactionListenerAdapter
|
|
{
|
|
private List<SandboxInfo> sandboxInfoList;
|
|
private List<String> webAppNames;
|
|
|
|
public CreateSandboxTransactionListener(List<SandboxInfo> sandboxInfoList, List<String> webAppNames)
|
|
{
|
|
this.sandboxInfoList = sandboxInfoList;
|
|
this.webAppNames = webAppNames;
|
|
}
|
|
|
|
/**
|
|
* @see org.alfresco.repo.transaction.TransactionListenerAdapter#afterCommit()
|
|
*/
|
|
@Override
|
|
public void afterCommit()
|
|
{
|
|
// Handle notification to the virtualization server
|
|
// (this needs to occur after the sandboxes are created in the main txn)
|
|
|
|
// reload virtualisation server for webapp(s) in this web project
|
|
for (SandboxInfo sandboxInfo : this.sandboxInfoList)
|
|
{
|
|
String newlyInvitedStoreName = WCMUtil.buildStagingStoreName(sandboxInfo.getMainStoreName());
|
|
|
|
for (String webAppName : webAppNames)
|
|
{
|
|
String path = WCMUtil.buildStoreWebappPath(newlyInvitedStoreName, webAppName);
|
|
WCMUtil.updateVServerWebapp(virtServerRegistry, path, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|