View Javadoc

1   /**
2    * This file Copyright (c) 2003-2010 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.module.workflow.setup;
35  
36  import info.magnolia.cms.beans.config.ContentRepository;
37  import info.magnolia.cms.core.Content;
38  import info.magnolia.cms.security.Permission;
39  import info.magnolia.module.DefaultModuleVersionHandler;
40  import info.magnolia.module.InstallContext;
41  import info.magnolia.module.admininterface.setup.AddMainMenuItemTask;
42  import info.magnolia.module.admininterface.setup.AddSubMenuItemTask;
43  import info.magnolia.module.admininterface.trees.WebsiteTreeConfiguration;
44  import info.magnolia.module.delta.AddPermissionTask;
45  import info.magnolia.module.delta.AddRoleToGroupTask;
46  import info.magnolia.module.delta.AddUserToGroupTask;
47  import info.magnolia.module.delta.ArrayDelegateTask;
48  import info.magnolia.module.delta.BackupTask;
49  import info.magnolia.module.delta.BootstrapResourcesTask;
50  import info.magnolia.module.delta.BootstrapSingleModuleResource;
51  import info.magnolia.module.delta.BootstrapSingleResource;
52  import info.magnolia.module.delta.CheckAndModifyPropertyValueTask;
53  import info.magnolia.module.delta.ConditionalDelegateTask;
54  import info.magnolia.module.delta.Delta;
55  import info.magnolia.module.delta.DeltaBuilder;
56  import info.magnolia.module.delta.IsModuleInstalledOrRegistered;
57  import info.magnolia.module.delta.ModuleDependencyBootstrapTask;
58  import info.magnolia.module.delta.NodeExistsDelegateTask;
59  import info.magnolia.module.delta.PropertyValueDelegateTask;
60  import info.magnolia.module.delta.RemovePermissionTask;
61  import info.magnolia.module.delta.Task;
62  import info.magnolia.module.delta.TaskExecutionException;
63  import info.magnolia.module.delta.WarnTask;
64  import info.magnolia.module.workflow.setup.for3_5.AddNewDefaultConfig;
65  import info.magnolia.module.workflow.setup.for3_5.CheckAndUpdateDefaultWorkflowDefinition;
66  import info.magnolia.module.workflow.setup.for3_5.RemoveMetadataFromExpressionsWorkspace;
67  import info.magnolia.module.workflow.setup.for3_5.SetDefaultWorkflowForActivationFlowCommands;
68  import info.magnolia.module.workflow.trees.WorkflowWebsiteTreeConfiguration;
69  
70  import java.util.ArrayList;
71  import java.util.List;
72  
73  import javax.jcr.ImportUUIDBehavior;
74  import javax.jcr.RepositoryException;
75  
76  /**
77   *
78   * @author gjoseph
79   * @version $Revision: $ ($Author: $)
80   */
81  public class WorkflowModuleVersionHandler extends DefaultModuleVersionHandler {
82      
83      private static final String BACKUP_PATH = "/server/install/backup";
84      private final Task inboxMenu = new AddMainMenuItemTask("inbox", "menu.inbox", "info.magnolia.module.workflow.messages",
85              "MgnlAdminCentral.showContent('/.magnolia/pages/inbox.html', false, false)", "/.resources/icons/24/mail.gif",
86              "security");
87      private final Task flowsPageMenu = new AddSubMenuItemTask("config", "workflows", "menu.config.workflows",
88              "MgnlAdminCentral.showContent('/.magnolia/pages/flows.html');", "/.resources/icons/16/dot.gif");
89  
90      private final Task bootstrapSecurityConfig = new BootstrapResourcesTask("New ACL configuration", "Bootstraps the new configuration for the ACL dialogs") {
91          protected String[] getResourcesToBootstrap(final InstallContext installContext) {
92              return new String[]{
93                      "/mgnl-bootstrap/workflow/config.modules.adminInterface.config.securityConfiguration.repositories.Expressions.xml",
94                      "/mgnl-bootstrap/workflow/config.modules.adminInterface.config.securityConfiguration.repositories.Store.xml"
95              };
96          }
97      };
98  
99      private Task changeWebsiteTreeConfigurationTask = new CheckAndModifyPropertyValueTask("Website tree configuration", "Modifies the website tree configuration so that a message window pops up for activation.",
100         ContentRepository.CONFIG,
101         "/modules/adminInterface/trees/website",
102         "configurationClass",
103         WebsiteTreeConfiguration.class.getName(),
104         WorkflowWebsiteTreeConfiguration.class.getName());
105 
106     private Task changeDMSTreeConfigurationTask = new IsModuleInstalledOrRegistered(
107         "DMS tree configuration", "Modifies the dms tree configuration so that a comment window pops up for activation.",
108         "dms",
109         new CheckAndModifyPropertyValueTask("DMS tree configuration", "Modifies the dms tree configuration so that a comment window pops up for activation.",
110             ContentRepository.CONFIG,
111             "/modules/dms/trees/dms",
112             "configurationClass",
113             // can't add a dependency to the dms so must use the class names
114             "info.magnolia.module.dms.DMSAdminTreeConfig",
115             "info.magnolia.module.dms.WorkflowDMSAdminTreeConfig"
116     ));
117 
118 
119     public WorkflowModuleVersionHandler() {
120         final Delta delta35 = DeltaBuilder.update("3.5", "")
121                 .addTask(inboxMenu)
122                 .addTask(flowsPageMenu)
123                 .addTask(new BootstrapSingleResource("Bootstrap", "Bootstraps the Workflow Utils page.", "/mgnl-bootstrap/workflow/config.modules.workflow.pages.flows.xml"))
124                 .addTask(new BootstrapSingleResource("Bootstrap", "Bootstraps the Inbox Subpages.", "/mgnl-bootstrap/workflow/config.modules.workflow.pages.inboxSubPages.xml"))
125                 // TODO refactor the following ArrayDelegateTask into a single one: BackupAndBootstrap("resource.xml", "/backup/location", "Message", MessageType.WARNING), will be fixed with MAGNOLIA-1945
126                 .addTask(new ArrayDelegateTask("Backup and Bootstrap", "Makes a backup of the current 'EditWorkItem' dialog and re-installs it.", new Task[] {
127                         new BackupTask(ContentRepository.CONFIG, "/modules/workflow/dialogs/editWorkItem", true),
128                         new BootstrapSingleResource("Bootstrap", "Bootstraps the Inbox Subpages.", "/mgnl-bootstrap/workflow/config.modules.workflow.dialogs.editWorkItem.xml", ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW),
129                         new WarnTask("Note: ", "Note that the 'EditWorkItem' dialog was re-installed. Magnolia put a backup of original dialog into '" + BACKUP_PATH + "/editWorkItem'. Please review the changes manually.")
130                     }))
131                 .addTask(new BootstrapSingleResource("Bootstrap", "Bootstraps the 'EditActivationWorkItem' dialog", "/mgnl-bootstrap/workflow/config.modules.workflow.dialogs.editActivationWorkItem.xml"))
132                 .addTask(new AddNewDefaultConfig())
133                 .addTask(new CheckAndUpdateDefaultWorkflowDefinition())
134                 .addTask(new RemoveMetadataFromExpressionsWorkspace())
135                 .addTask(new SetDefaultWorkflowForActivationFlowCommands())
136                 .addTask(bootstrapSecurityConfig)
137                 // TODO we might want to backup the following configurations before overwriting them, as well.
138                 .addTask(new BootstrapSingleResource("Bootstrap", "Bootstraps the 'editors' group.", "/mgnl-bootstrap/workflow/usergroups.editors.xml", ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING))
139                 .addTask(new BootstrapSingleResource("Bootstrap", "Bootstraps the 'publishers' group.", "/mgnl-bootstrap/workflow/usergroups.publishers.xml", ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING))
140                 .addTask(new BootstrapSingleResource("Bootstrap", "Bootstraps the 'workflow-base' role.", "/mgnl-bootstrap/workflow/userroles.workflow-base.xml"));
141         register(delta35);
142 
143         register(DeltaBuilder.update("3.6", "")
144                 .addTask(changeWebsiteTreeConfigurationTask)
145                 .addTask(changeDMSTreeConfigurationTask)
146                 .addTask(new BootstrapSingleResource("Comment on activation dialog", "Registers the dialog for activation comments.", "/mgnl-bootstrap/workflow/config.modules.workflow.dialogs.startActivationWorkflow.xml"))
147                 .addTask(new IsModuleInstalledOrRegistered("Sample users and groups", "Adds sample users to sample editors and publishers group, if the sample module is installed or registered.",
148                         "samples", new ArrayDelegateTask("",
149                         new AddUserToGroupTask("Sample user", "eve", "editors"),
150                         new AddUserToGroupTask("Sample user", "patrick", "publishers"))
151                 )));
152 
153         register(DeltaBuilder.update("3.6.4", "")
154                 .addTask(new ArrayDelegateTask("Update tree configuration",
155                         new BootstrapSingleResource("Update tree configuration", "Adds Store workspace tree configuration.", "/mgnl-bootstrap/workflow/config.modules.adminInterface.trees.Store.xml"),
156                         new BootstrapSingleResource("Update tree configuration", "Adds Expressions workspace tree configuration.", "/mgnl-bootstrap/workflow/config.modules.adminInterface.trees.Expressions.xml")))
157                 );
158         register(DeltaBuilder.update("4.0", "")
159                 .addTask(new AddUserToGroupTask("Superuser", "superuser", "publishers"))
160                 );
161         register(DeltaBuilder.update("4.2", "")
162                 // while this is checked and changed by DMS in 1.4 (bundled w/ Mgnl 4.1), there was a brief period of time (between 4.1 to 4.2) when workflow might have had overridden it.
163                 // if the property exists with a wrong value, fix it otherwise let it be as someone might have just removed the versioning or it uses custom or correct command
164                 .addTask(new IsModuleInstalledOrRegistered("Versioning", "Update of DMS specific versioning command.", "dms",
165                         new PropertyValueDelegateTask("", "", ContentRepository.CONFIG, "/modules/dms/commands/dms/activate/version", "class", "info.magnolia.module.admininterface.commands.VersionCommand", false,
166                                 new CheckAndModifyPropertyValueTask("", "", ContentRepository.CONFIG, "/modules/dms/commands/dms/activate/version", "class", "info.magnolia.module.admininterface.commands.VersionCommand", "info.magnolia.module.dms.commands.DocumentVersionCommand"))))
167                 .addTask(new IsModuleInstalledOrRegistered("Activation update","Enable workflow use for activation of data entries.", "data",
168                         new ConditionalDelegateTask("", "", new ArrayDelegateTask("","", new BackupTask(ContentRepository.CONFIG, "/modules/data/commands/data/activate"), new BootstrapSingleResource("","", "/info/magnolia/module/workflow/setup/data/config.modules.data.commands.data.activate.xml"))) {
169                             @Override
170                             protected boolean condition(InstallContext installContext) throws TaskExecutionException {
171                                 // the installation of the activation command is backported also to 1.2 branch, so it is possible that this particular activation command have been already bootstrapped. Do not backup & re-bootstrap it in this case again
172                                 try {
173                                     Content activation = installContext.getHierarchyManager(ContentRepository.CONFIG).getContentByUUID("a71a96a9-0c2b-4358-90f0-0be55e79361c");
174                                     return activation == null;
175                                 } catch (RepositoryException e) {
176                                     // doesn't exist, install
177                                     return true;
178                                 }
179                             }
180                 }))
181         );
182 
183         register(DeltaBuilder.update("4.2.3", "")
184             // MAGNOLIA-2971
185             .addTask(new AddPermissionTask("Update base role", "Adds permission to read the workflow definitions.", "workflow-base", "config", "/modules/workflow/config/flows", Permission.READ, true))
186         );
187         
188         register(DeltaBuilder.update("4.3", "")
189             // TODO use node builder instead of overwritting the dialogs completely
190             .addTask(new BootstrapSingleModuleResource("Publication date","Add new controls to the activation dialog.", "config.modules.workflow.dialogs.startActivationWorkflow.xml"))
191             .addTask(new BootstrapSingleModuleResource("Publication date","Add new controls to the workitem dialog", "config.modules.workflow.dialogs.editActivationWorkItem.xml"))
192             .addTask(new RemovePermissionTask("Update workflow-base role", "Updates the workflow-base role, removing unnecessary permission to self.", "workflow-base", "userroles", "/workflow-base", Permission.READ)));
193 
194         register(DeltaBuilder.update("4.3.3", "")
195             .addTask(new NodeExistsDelegateTask("StartActivationWorkflowDialog", "Checs if startActivationWorkflow node exists", ContentRepository.CONFIG, "/modules/workflow/dialogs/startActivationWorkflow", new CheckAndModifyPropertyValueTask("StartActivationWorkflowDialog", "Increases the height to 450px to prevent visual artefacts on FF on Linux", ContentRepository.CONFIG, "/modules/workflow/dialogs/startActivationWorkflow", "height", "400", "450")))
196         );
197     }
198 
199     protected List<Task> getExtraInstallTasks(InstallContext ctx) {
200         final List<Task> tasks = new ArrayList<Task>();
201         tasks.add(new ModuleDependencyBootstrapTask("dms"));
202         tasks.add(new ModuleDependencyBootstrapTask("data"));
203         tasks.add(inboxMenu);
204         tasks.add(flowsPageMenu);
205         tasks.add(new InstallWorkflowDefinitionTask("Setup default activation workflow definition", "Adds the default activation workflow definition under the /modules/workflow/config/flows/activation config node.",
206                 "activation", "info/magnolia/module/workflow/default-activation-workflow.xml"));
207         tasks.add(changeWebsiteTreeConfigurationTask);
208         tasks.add(changeDMSTreeConfigurationTask);
209 
210         // TODO: MAGNOLIA-2979, move that to the samples
211         if (ctx.isModuleRegistered("samples")) {
212             tasks.add(new AddUserToGroupTask("Sample user", "eve", "editors"));
213             tasks.add(new AddUserToGroupTask("Sample user", "patrick", "publishers"));
214             tasks.add(new AddRoleToGroupTask("Update editors group with samples role", "editors","editors"));
215         }
216 
217         tasks.add(new AddUserToGroupTask("Superuser", "superuser", "publishers"));
218         
219         // MAGNOLIA-2603 and MAGNOLIA-2971
220         // the worflow base role grants only read permission. Now that the superuser is added to the publisher group he gets this restrictive permission assigned
221         // to allow the superuser editing the workflow definition we have to add that permission explicitly to the superuser role
222         tasks.add(new AddPermissionTask("Update Superuser Role", "Add all those permissions explicitly which could be overwritten by assigning the workflow base role.", "superuser", "config", "/modules/workflow/config/flows", Permission.ALL, true));
223 
224         return tasks;
225     }
226 
227 }