Merged V3.2 to HEAD

19614: ALF-1890: Merged V2.2 to V3.2
      17709: Merged DEV_TEMPORARY to V2.2
         17700: ETWOTWO-1393: concurrent writes to webdav lead to data loss (0kb resulting file)
      19613: Merged DEV/BELARUS/V2.2-2010_02_03 to V2.2
         19157: ALF-1890: concurrent writes to webdav lead to data loss (0kb resulting file)
   19562: Merged DEV/BELARUS/V3.2-2010_02_24 to V3.2
      19244: ALF-1816: Email templates can no longer be selected when creating a rule for the action 'Send email to specified users' following an upgrade
         - New patch has been created to create invite email templates and notify email templates folders if those are absent. Also it moves 
default notify and invite templates into appropriate folders. 
   19561: Merged DEV/BELARUS/V3.2-2010_02_24 to V3.2 (With improvements)
      19294: ALF-929: email to invite external users does not allow external users to login (no credentails)
         - Always create a password for created users if the authentication chain allows account creation


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@19615 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Dave Ward
2010-03-27 12:02:24 +00:00
parent 06e8a0aa74
commit f239f24550
7 changed files with 335 additions and 12 deletions

View File

@@ -27,6 +27,12 @@ spaces.templates.content.description=Presentation templates
spaces.templates.email.name=Email Templates
spaces.templates.email.description=Email templates
spaces.invite_templates.email.name=Email Invite Templates
spaces.invite_templates.email.description=Email Invite templates
spaces.notify_templates.email.name=Email Notify Templates
spaces.notify_templates.email.description=Email Notify templates
spaces.templates.rss.name=RSS Templates
spaces.templates.rss.description=RSS templates

View File

@@ -9,4 +9,5 @@ invitation.invite.already_member "The user , {0} is already a member of {1} and
invitation.cancel.not_site_manager "Current user, {0}, cannot cancel invitation: {1} because they are not a Site Manager for site: {2}
invitation.invite.not_site_manager "Current user, {0}, is not a Site Manager for site: {1}
invitation.invite.unable_generate_id "Unable to generate a user name for invitee, which doesn't already belong to someone else firstName:{0} lastName:{1} email:{2}"
invitation.invite.already_finished "Invitation, {0} has already been accepted, cancelled or rejected"
invitation.invite.already_finished "Invitation, {0} has already been accepted, cancelled or rejected"
invitation.invite.authentication_chain "Authentication chain does not allow creation of new accounts"

View File

@@ -74,6 +74,12 @@ patch.emailTemplatesFolder.description=Ensures the existence of the 'Email Templ
patch.emailTemplatesFolder.result.exists=The email templates folder already exists: {0}
patch.emailTemplatesFolder.result.created=The email templates folder was successfully created: {0}
patch.emailInviteAndNotifyTemplatesFolder.description=Ensures the existence of the 'Email Invite Templates' and 'Email Notify Templates' folders.
patch.emailNotifyTemplatesFolder.result.exists=The Email Notify Templates folder already exists: {0}
patch.emailNotifyTemplatesFolder.result.created=The Email Notify Templates folder was successfully created: {0}
patch.emailInviteTemplatesFolder.result.exists=The Email Invite Templates folder already exists: {0}
patch.emailInviteTemplatesFolder.result.created=The Email Invite Templates folder was successfully created: {0}
patch.emailTemplatesContent.description=Loads the email templates into the Email Templates folder.
patch.emailTemplatesContent.result=Imported the Email Templates into the default folder.

View File

@@ -320,6 +320,20 @@
</list>
</property>
</bean>
<bean id="patch.emailInviteAndNotifyTemplatesFolder" class="org.alfresco.repo.admin.patch.impl.EmailTemplatesInviteAndNotifyFoldersPatch" parent="basePatch" >
<property name="id"><value>patch.emailInviteAndNotifyTemplatesFolder</value></property>
<property name="description"><value>patch.emailInviteAndNotif yTemplatesFolder.description</value></property>
<property name="fixesFromSchema"><value>0</value></property>
<property name="fixesToSchema"><value>4006</value></property>
<property name="targetSchema"><value>4007</value></property>
<!-- helper beans for execution -->
<property name="importerBootstrap">
<ref bean="spacesBootstrap" />
</property>
<property name="messageSource">
<ref bean="bootstrapSpacesMessageSource" />
</property>
</bean>
<!-- Note: targetSchema 11 is allocated for patching in an enterprise trial license -->
<!-- A patch bean is not provided as this is handled by the license component internally (enterprise only) -->

View File

@@ -19,4 +19,4 @@ version.build=@build-number@
# Schema number
version.schema=4006
version.schema=4007

View File

@@ -0,0 +1,294 @@
/*
* Copyright (C) 2005-2010 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 <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.admin.patch.impl;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.model.ApplicationModel;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.admin.patch.AbstractPatch;
import org.alfresco.repo.importer.ImporterBootstrap;
import org.alfresco.service.cmr.admin.PatchException;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.namespace.QName;
import org.springframework.context.MessageSource;
/**
* Ensures that the <b>invite email templates</b> and <b>notify email templates</b> folders are present.
* <p>
* This uses the bootstrap importer to get the paths to look for. If not present,
* the required structures are created.
* <p>
*
* @author valerysh
*
*/
public class EmailTemplatesInviteAndNotifyFoldersPatch extends AbstractPatch {
public static final String PROPERTY_COMPANY_HOME_CHILDNAME = "spaces.company_home.childname";
public static final String PROPERTY_DICTIONARY_CHILDNAME = "spaces.dictionary.childname";
public static final String PROPERTY_EMAIL_TEMPLATES_FOLDER_CHILDNAME = "spaces.templates.email.childname";
public static final String PROPERTY_EMAIL_NOTIFY_TEMPLATES_FOLDER_CHILDNAME = "spaces.templates.email.notify.childname";
public static final String PROPERTY_EMAIL_INVITE_TEMPLATES_FOLDER_CHILDNAME = "spaces.templates.email.invite1.childname";
private static final String PROPERTY_EMAIL_NOTIFY_TEMPLATES_FOLDER_NAME = "spaces.notify_templates.email.name";
private static final String PROPERTY_EMAIL_NOTIFY_TEMPLATES_FOLDER_DESCRIPTION = "spaces.notify_templates.email.description";
private static final String PROPERTY_EMAIL_INVITE_TEMPLATES_FOLDER_NAME = "spaces.invite_templates.email.name";
private static final String PROPERTY_EMAIL_INVITE_TEMPLATES_FOLDER_DESCRIPTION = "spaces.invite_templates.email.description";
private static final String NOTIFY_TEMPLATE_NAME = "notify_user_email.ftl";
private static final String INVITE_TEMPLATE_NAME = "invite_user_email.ftl";
private static final String MSG_EMAIL_INVITE_TEMPLATES_FOLDER_EXISTS = "patch.emailInviteTemplatesFolder.result.exists";
private static final String MSG_EMAIL_INVITE_TEMPLATES_FOLDER_CREATED = "patch.emailInviteTemplatesFolder.result.created";
private static final String MSG_EMAIL_NOTIFY_TEMPLATES_FOLDER_EXISTS = "patch.emailNotifyTemplatesFolder.result.exists";
private static final String MSG_EMAIL_NOTIFY_TEMPLATES_FOLDER_CREATED = "patch.emailNotifyTemplatesFolder.result.created";
private static final String PROPERTY_ICON = "space-icon-default";
private ImporterBootstrap importerBootstrap;
private MessageSource messageSource;
protected NodeRef emailNotifyTemplatesFolderNodeRef;
protected NodeRef emailInviteTemplatesFolderNodeRef;
protected Properties configuration;
protected NodeRef emailTemplatesFolderNodeRef;
private String emaiemailTemplatesFolderXPath;
public void setImporterBootstrap(ImporterBootstrap importerBootstrap)
{
this.importerBootstrap = importerBootstrap;
}
public void setMessageSource(MessageSource messageSource)
{
this.messageSource = messageSource;
}
/**
* Ensure that required common properties have been set
*/
protected void checkCommonProperties() throws Exception
{
checkPropertyNotNull(importerBootstrap, "importerBootstrap");
checkPropertyNotNull(messageSource, "messageSource");
}
/**
* Extracts pertinent references and properties that are common to execution
* of this and derived patches.
*/
protected void setUp() throws Exception
{
// get the node store that we must work against
StoreRef storeRef = importerBootstrap.getStoreRef();
if (storeRef == null)
{
throw new PatchException("Bootstrap store has not been set");
}
NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef);
this.configuration = importerBootstrap.getConfiguration();
// get the association names that form the path
String companyHomeChildName = configuration.getProperty(PROPERTY_COMPANY_HOME_CHILDNAME);
if (companyHomeChildName == null || companyHomeChildName.length() == 0)
{
throw new PatchException("Bootstrap property '" + PROPERTY_COMPANY_HOME_CHILDNAME + "' is not present");
}
String dictionaryChildName = configuration.getProperty(PROPERTY_DICTIONARY_CHILDNAME);
if (dictionaryChildName == null || dictionaryChildName.length() == 0)
{
throw new PatchException("Bootstrap property '" + PROPERTY_DICTIONARY_CHILDNAME + "' is not present");
}
String emailTemplatesChildName = configuration.getProperty(PROPERTY_EMAIL_TEMPLATES_FOLDER_CHILDNAME);
if (emailTemplatesChildName == null || emailTemplatesChildName.length() == 0)
{
throw new PatchException("Bootstrap property '" + PROPERTY_EMAIL_TEMPLATES_FOLDER_CHILDNAME + "' is not present");
}
String emailNotifyTemplatesChildName = configuration.getProperty(PROPERTY_EMAIL_NOTIFY_TEMPLATES_FOLDER_CHILDNAME);
if (emailNotifyTemplatesChildName == null || emailNotifyTemplatesChildName.length() == 0)
{
throw new PatchException("Bootstrap property '" + PROPERTY_EMAIL_NOTIFY_TEMPLATES_FOLDER_CHILDNAME + "' is not present");
}
String emailInviteTemplatesChildName = configuration.getProperty(PROPERTY_EMAIL_INVITE_TEMPLATES_FOLDER_CHILDNAME);
if (emailInviteTemplatesChildName == null || emailInviteTemplatesChildName.length() == 0)
{
throw new PatchException("Bootstrap property '" + PROPERTY_EMAIL_INVITE_TEMPLATES_FOLDER_CHILDNAME + "' is not present");
}
StringBuilder sb = new StringBuilder();
sb.append("/").append(companyHomeChildName)
.append("/").append(dictionaryChildName)
.append("/").append(emailTemplatesChildName);
emaiemailTemplatesFolderXPath = sb.toString();
// get the email templates node
List<NodeRef> nodeRefs = searchService.selectNodes(storeRootNodeRef, emaiemailTemplatesFolderXPath, null, namespaceService, false);
if (nodeRefs.size() == 0)
{
throw new PatchException("XPath didn't return any results: \n" +
" root: " + storeRootNodeRef + "\n" +
" xpath: " + emaiemailTemplatesFolderXPath);
}
else if (nodeRefs.size() > 1)
{
throw new PatchException("XPath returned too many results: \n" +
" root: " + storeRootNodeRef + "\n" +
" xpath: " + emaiemailTemplatesFolderXPath + "\n" +
" results: " + nodeRefs);
}
this.emailTemplatesFolderNodeRef = nodeRefs.get(0);
emailNotifyTemplatesFolderNodeRef = searchFolder(emailNotifyTemplatesChildName);
emailInviteTemplatesFolderNodeRef = searchFolder(emailInviteTemplatesChildName);
}
@Override
protected String applyInternal() throws Exception
{
// common properties must be set before we can continue
checkCommonProperties();
if (messageSource == null)
{
throw new PatchException("'messageSource' property has not been set");
}
setUp();
// create the folder if needed - output a message to describe the result
StringBuffer msg = new StringBuffer();
if (emailNotifyTemplatesFolderNodeRef == null)
{
emailNotifyTemplatesFolderNodeRef = createFolderAndMoveTemplate(PROPERTY_EMAIL_NOTIFY_TEMPLATES_FOLDER_CHILDNAME,
PROPERTY_EMAIL_NOTIFY_TEMPLATES_FOLDER_NAME,
PROPERTY_EMAIL_NOTIFY_TEMPLATES_FOLDER_DESCRIPTION,
NOTIFY_TEMPLATE_NAME);
msg.append(I18NUtil.getMessage(MSG_EMAIL_NOTIFY_TEMPLATES_FOLDER_CREATED, emailNotifyTemplatesFolderNodeRef));
}
else
{
msg.append(I18NUtil.getMessage(MSG_EMAIL_NOTIFY_TEMPLATES_FOLDER_EXISTS, emailNotifyTemplatesFolderNodeRef));
}
msg.append("; ");
if (emailInviteTemplatesFolderNodeRef == null)
{
emailInviteTemplatesFolderNodeRef = createFolderAndMoveTemplate(PROPERTY_EMAIL_INVITE_TEMPLATES_FOLDER_CHILDNAME,
PROPERTY_EMAIL_INVITE_TEMPLATES_FOLDER_NAME,
PROPERTY_EMAIL_INVITE_TEMPLATES_FOLDER_DESCRIPTION,
INVITE_TEMPLATE_NAME);
msg.append(I18NUtil.getMessage(MSG_EMAIL_INVITE_TEMPLATES_FOLDER_CREATED, emailNotifyTemplatesFolderNodeRef));
}
else
{
msg.append(I18NUtil.getMessage(MSG_EMAIL_INVITE_TEMPLATES_FOLDER_EXISTS, emailNotifyTemplatesFolderNodeRef));
}
return msg.toString();
}
private NodeRef searchFolder(String xpath)
{
List<NodeRef> nodeRefs = searchService.selectNodes(emailTemplatesFolderNodeRef, xpath, null, namespaceService, false);
if (nodeRefs.size() > 1)
{
throw new PatchException("XPath returned too many results: \n" +
" email templates node: " + emailTemplatesFolderNodeRef + "\n" +
" xpath: " + xpath + "\n" +
" results: " + nodeRefs);
}
else if (nodeRefs.size() == 0)
{
// the node does not exist
return null;
}
else
{
return nodeRefs.get(0);
}
}
private NodeRef createFolderAndMoveTemplate(String folderChildName, String folderName, String folderDescription, String templateName)
{
// get required properties
String emailTemplatesChildName = configuration.getProperty(folderChildName);
if (emailTemplatesChildName == null)
{
throw new PatchException("Bootstrap property '" + folderChildName + "' is not present");
}
String emailTemplatesName = messageSource.getMessage(
folderName,
null,
I18NUtil.getLocale());
if (emailTemplatesName == null || emailTemplatesName.length() == 0)
{
throw new PatchException("Bootstrap property '" + folderName + "' is not present");
}
String emailTemplatesDescription = messageSource.getMessage(
folderDescription,
null,
I18NUtil.getLocale());
if (emailTemplatesDescription == null || emailTemplatesDescription.length() == 0)
{
throw new PatchException("Bootstrap property '" + folderDescription + "' is not present");
}
Map<QName, Serializable> properties = new HashMap<QName, Serializable>(7);
properties.put(ContentModel.PROP_NAME, emailTemplatesName);
properties.put(ContentModel.PROP_TITLE, emailTemplatesName);
properties.put(ContentModel.PROP_DESCRIPTION, emailTemplatesDescription);
properties.put(ApplicationModel.PROP_ICON, PROPERTY_ICON);
// create the node
ChildAssociationRef childAssocRef = nodeService.createNode(
emailTemplatesFolderNodeRef,
ContentModel.ASSOC_CONTAINS,
QName.resolveToQName(namespaceService, emailTemplatesChildName),
ContentModel.TYPE_FOLDER,
properties);
NodeRef createdFolderNodeRef = childAssocRef.getChildRef();
// add the required aspects
nodeService.addAspect(createdFolderNodeRef, ApplicationModel.ASPECT_UIFACETS, null);
//move template
String xpath = emaiemailTemplatesFolderXPath + "/cm:" + templateName;
List<NodeRef> templateNodeRef = searchService.selectNodes(emailTemplatesFolderNodeRef, xpath, null, namespaceService, false);
if (templateNodeRef != null)
{
nodeService.moveNode(templateNodeRef.get(0), createdFolderNodeRef, ContentModel.ASSOC_CHILDREN,
nodeService.getPrimaryParent(templateNodeRef.get(0)).getQName());
}
return createdFolderNodeRef;
}
}

View File

@@ -1098,6 +1098,7 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
// get the inviter user name (the name of user web script is executed
// under)
String inviterUserName = this.authenticationService.getCurrentUserName();
boolean created = false;
checkManagerRole(inviterUserName, resourceType, siteShortName);
@@ -1164,10 +1165,16 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
if (inviteeUserName == null)
{
// This shouldn't normally happen. Due to the fix for ETHREEOH-3268, the link to invite external users
// should be disabled when the authentication chain does not allow it.
if (!authenticationService.isAuthenticationCreationAllowed())
{
throw new InvitationException("invitation.invite.authentication_chain");
}
// else there are no existing people who have the given invitee
// email address so create new person
inviteeUserName = createInviteePerson(inviteeFirstName, inviteeLastName, inviteeEmail);
created = true;
if (logger.isDebugEnabled())
{
logger.debug("not explictly passed username - created new person, inviteeUserName="
@@ -1211,19 +1218,14 @@ public class InvitationServiceImpl implements InvitationService, NodeServicePoli
// user name, then local reference to invitee password will be "null"
//
final String initeeUserNameFinal = inviteeUserName;
String inviteePassword = AuthenticationUtil.runAs(new RunAsWork<String>()
String inviteePassword = created ? AuthenticationUtil.runAs(new RunAsWork<String>()
{
public String doWork()
{
if (!InvitationServiceImpl.this.authenticationService.authenticationExists(initeeUserNameFinal))
{
if (logger.isDebugEnabled())
logger.debug("Invitee user account does not exist, creating disabled account.");
return createInviteeDisabledAccount(initeeUserNameFinal);
}
return null;
return createInviteeDisabledAccount(initeeUserNameFinal);
}
}, AuthenticationUtil.getSystemUserName());
}, AuthenticationUtil.getSystemUserName()) : null;
// create a ticket for the invite - this is used
String inviteTicket = GUID.generate();