View Javadoc
1   /**
2    * This file Copyright (c) 2003-2014 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.setup;
35  
36  import static info.magnolia.nodebuilder.Ops.*;
37  
38  import info.magnolia.cms.core.MgnlNodeType;
39  import info.magnolia.cms.filters.FilterManager;
40  import info.magnolia.module.AbstractModuleVersionHandler;
41  import info.magnolia.module.InstallContext;
42  import info.magnolia.module.delta.AddURIPermissionTask;
43  import info.magnolia.module.delta.ArrayDelegateTask;
44  import info.magnolia.module.delta.BootstrapConditionally;
45  import info.magnolia.module.delta.BootstrapSingleModuleResource;
46  import info.magnolia.module.delta.BootstrapSingleResource;
47  import info.magnolia.module.delta.CheckAndModifyPropertyValueTask;
48  import info.magnolia.module.delta.CheckOrCreatePropertyTask;
49  import info.magnolia.module.delta.ChildrenExistsDelegateTask;
50  import info.magnolia.module.delta.Condition;
51  import info.magnolia.module.delta.CreateNodeTask;
52  import info.magnolia.module.delta.DeltaBuilder;
53  import info.magnolia.module.delta.FindAndChangeTemplateIdTask;
54  import info.magnolia.module.delta.MoveAndRenamePropertyTask;
55  import info.magnolia.module.delta.NodeExistsDelegateTask;
56  import info.magnolia.module.delta.OrderFilterBeforeTask;
57  import info.magnolia.module.delta.OrderNodeBeforeTask;
58  import info.magnolia.module.delta.PartialBootstrapTask;
59  import info.magnolia.module.delta.PropertyExistsDelegateTask;
60  import info.magnolia.module.delta.PropertyValueDelegateTask;
61  import info.magnolia.module.delta.RemoveDuplicatePermissionTask;
62  import info.magnolia.module.delta.RemoveNodeTask;
63  import info.magnolia.module.delta.RemovePermissionTask;
64  import info.magnolia.module.delta.RenameNodesTask;
65  import info.magnolia.module.delta.Task;
66  import info.magnolia.module.delta.TextFileConditionsUtil;
67  import info.magnolia.module.delta.WarnTask;
68  import info.magnolia.module.delta.WebXmlConditionsUtil;
69  import info.magnolia.module.delta.WorkspaceXmlConditionsUtil;
70  import info.magnolia.nodebuilder.task.ErrorHandling;
71  import info.magnolia.nodebuilder.task.NodeBuilderTask;
72  import info.magnolia.repository.RepositoryConstants;
73  import info.magnolia.setup.for4_5.IsNotAProblematicEnvironmentCondition;
74  import info.magnolia.setup.for4_5.RenameACLNodesTask;
75  import info.magnolia.setup.for4_5.RenameOldServletMappingsNodesTask;
76  import info.magnolia.setup.for4_5.UpdateSecurityFilterClientCallbacksConfiguration;
77  import info.magnolia.setup.for4_5.UpdateUserManagers;
78  import info.magnolia.setup.initial.GenericTasks;
79  
80  import java.util.ArrayList;
81  import java.util.List;
82  
83  import javax.jcr.ImportUUIDBehavior;
84  
85  /**
86   * Special VersionHandler for the core module. As it does not extend {@link info.magnolia.module.DefaultModuleVersionHandler} it has a special getBasicInstallTasks(InstallContext) that
87   * e.g. will not automatically bootstrap xml-files placed in mgnl-bootstrap/core.
88   *
89   * @version $Id$
90   */
91  public class CoreModuleVersionHandler extends AbstractModuleVersionHandler {
92      public static final String BOOTSTRAP_AUTHOR_INSTANCE_PROPERTY = "magnolia.bootstrap.authorInstance";
93  
94      // TODO : why is this a BootstrapConditionally and not a BootstrapSingleResource ?
95      private final BootstrapConditionally auditTrailManagerTask = new BootstrapConditionally("New auditory log configuration", "Install new configuration for auditory log manager.", "/mgnl-bootstrap/core/config.server.auditLogging.xml");
96      private final BootstrapSingleResource bootstrapFreemarker = new BootstrapSingleResource("Freemarker configuration", "Freemarker template loaders can now be configured in Magnolia. Adds default configuration", "/mgnl-bootstrap/core/config.server.rendering.freemarker.xml");
97      private final CreateNodeTask addFreemarkerSharedVariables = new CreateNodeTask("Freemarker configuration", "Adds sharedVariables node to the Freemarker configuration",
98              RepositoryConstants.CONFIG, "/server/rendering/freemarker", "sharedVariables", MgnlNodeType.NT_CONTENTNODE);
99      private final BootstrapSingleResource bootstrapWebContainerResources = new BootstrapSingleResource("Web container resources configuration", "Global configuration which resources are not meant to be handled by Magnolia. For instance JSP files.", "/mgnl-bootstrap/core/config.server.webContainerResources.xml");
100     private final BootstrapSingleModuleResource bootstrapChannelManagement = new BootstrapSingleModuleResource("ChannelManagement configuration", "", "config.server.rendering.channelManagement.xml");
101 
102     private final BootstrapSingleModuleResource bootstrapChannelFilter = new BootstrapSingleModuleResource("ChannelFilter configuration", "", "config.server.filters.channel.xml");
103     private final Task placeChannelBeforeLogout = new OrderFilterBeforeTask("channel", new String[] { "logout" });
104     private final Task updateSecurityBaseRole = updateSecurityBaseRole();
105 
106     private Task updateSecurityBaseRole() {
107         ArrayDelegateTask permissionsTask = new ArrayDelegateTask("Update security-base role", "Disallow access to view configuration/tools pages");
108         permissionsTask.addTask(new RemovePermissionTask("", "", "security-base", "uri", "/.magnolia/pages/installedModulesList.html", AddURIPermissionTask.DENY));
109         permissionsTask.addTask(new RemovePermissionTask("", "", "security-base", "uri", "/.magnolia/pages/jcrUtils.html", AddURIPermissionTask.DENY));
110         permissionsTask.addTask(new RemovePermissionTask("", "", "security-base", "uri", "/.magnolia/pages/configuration.html", AddURIPermissionTask.DENY));
111         permissionsTask.addTask(new RemovePermissionTask("", "", "security-base", "uri", "/.magnolia/pages/logViewer.html", AddURIPermissionTask.DENY));
112         permissionsTask.addTask(new RemovePermissionTask("", "", "security-base", "uri", "/.magnolia/pages/sendMail.html", AddURIPermissionTask.DENY));
113         permissionsTask.addTask(new AddURIPermissionTask("", "", "security-base", "/.magnolia/pages/installedModulesList*", AddURIPermissionTask.DENY));
114         permissionsTask.addTask(new AddURIPermissionTask("", "", "security-base", "/.magnolia/pages/jcrUtils*", AddURIPermissionTask.DENY));
115         permissionsTask.addTask(new AddURIPermissionTask("", "", "security-base", "/.magnolia/pages/configuration*", AddURIPermissionTask.DENY));
116         permissionsTask.addTask(new AddURIPermissionTask("", "", "security-base", "/.magnolia/pages/logViewer*", AddURIPermissionTask.DENY));
117         permissionsTask.addTask(new AddURIPermissionTask("", "", "security-base", "/.magnolia/pages/sendMail*", AddURIPermissionTask.DENY));
118 
119         permissionsTask.addTask(new AddURIPermissionTask("", "", "security-base", "/.magnolia/pages/users*", AddURIPermissionTask.DENY));
120         permissionsTask.addTask(new AddURIPermissionTask("", "", "security-base", "/.magnolia/pages/import*", AddURIPermissionTask.DENY));
121         permissionsTask.addTask(new AddURIPermissionTask("", "", "security-base", "/.magnolia/pages/export*", AddURIPermissionTask.DENY));
122         permissionsTask.addTask(new AddURIPermissionTask("", "", "security-base", "/.magnolia/pages/permission*", AddURIPermissionTask.DENY));
123         permissionsTask.addTask(new AddURIPermissionTask("", "", "security-base", "/.magnolia/pages/developmentUtils*", AddURIPermissionTask.DENY));
124         permissionsTask.addTask(new AddURIPermissionTask("", "", "security-base", "/.magnolia/pages/activationTools*", AddURIPermissionTask.DENY));
125         permissionsTask.addTask(new AddURIPermissionTask("", "", "security-base", "/.magnolia/pages/migrationReport*", AddURIPermissionTask.DENY));
126         permissionsTask.addTask(new AddURIPermissionTask("", "", "security-base", "/.magnolia/pages/backup*", AddURIPermissionTask.DENY));
127         permissionsTask.addTask(new AddURIPermissionTask("", "", "security-base", "/.magnolia/pages/activationMonitor*", AddURIPermissionTask.DENY));
128         permissionsTask.addTask(new AddURIPermissionTask("", "", "security-base", "/.magnolia/pages/installedModulesList*", AddURIPermissionTask.DENY));
129         permissionsTask.addTask(new AddURIPermissionTask("", "", "security-base", "/.magnolia/pages/allModulesList*", AddURIPermissionTask.DENY));
130         permissionsTask.addTask(new AddURIPermissionTask("", "", "security-base", "/.magnolia/pages/cacheTools*", AddURIPermissionTask.DENY));
131         permissionsTask.addTask(new AddURIPermissionTask("", "", "security-base", "/.magnolia/pages/flows*", AddURIPermissionTask.DENY));
132         return permissionsTask;
133     }
134 
135     public CoreModuleVersionHandler() {
136         super();
137 
138         register(DeltaBuilder.checkPrecondition("4.4.6", "4.5"));
139 
140         register(DeltaBuilder.update("4.5", "")
141                 .addCondition(new SystemTmpDirCondition())
142                 .addConditions(get45ConfigFileConditions())
143                 .addTask(new RenameACLNodesTask())
144                 .addTask(new ArrayDelegateTask("New security filter", "Adds the securityCallback filter.",
145                         new NodeBuilderTask("New security filter", "Adds the securityCallback filter.", ErrorHandling.strict, RepositoryConstants.CONFIG, FilterManager.SERVER_FILTERS,
146                                 addNode("securityCallback", MgnlNodeType.NT_CONTENT).then(
147                                         addProperty("class", "info.magnolia.cms.security.SecurityCallbackFilter"),
148                                         addNode("bypasses", MgnlNodeType.NT_CONTENTNODE)
149                                         )
150                         ),
151                         new OrderNodeBeforeTask("", "Puts the securityCallback just before the uriSecurity filter.", RepositoryConstants.CONFIG, FilterManager.SERVER_FILTERS + "/securityCallback", "uriSecurity")
152                         ))
153 
154                 .addTask(new UpdateSecurityFilterClientCallbacksConfiguration("uriSecurity", "securityCallback"))
155                 .addTask(new UpdateUserManagers())
156                 .addTask(new HashUsersPasswords())
157                 .addTask(bootstrapChannelManagement)
158                 .addTask(bootstrapChannelFilter)
159                 .addTask(placeChannelBeforeLogout)
160                 .addTask(new RemoveDuplicatePermissionTask("Remove duplicate permission", "Remove duplicate permission in workspace Expression for role superuser", "superuser", "acl_Expressions"))
161                 .addTask(new RemoveDuplicatePermissionTask("Remove duplicate permission", "Remove duplicate permission in workspace Store for role superuser", "superuser", "acl_Store"))
162                 .addTask(new RemoveDuplicatePermissionTask("Remove duplicate permission", "Remove duplicate permission in workspace forum for role superuser", "superuser", "acl_forum"))
163                 .addTask(new CheckOrCreatePropertyTask("Update system userManager ", "Add the realName property.", RepositoryConstants.CONFIG, "/server/security/userManagers/system", "realName", "system"))
164                 .addTask(new CheckOrCreatePropertyTask("Update system userManager ", "Add the realName property.", RepositoryConstants.CONFIG, "/server/security/userManagers/admin", "realName", "admin"))
165                 .addTask(new RenameNodesTask("Update servlet mapping names", "Update '--resources--' servlet mapping names to use '.'.", RepositoryConstants.CONFIG, "/server/filters/servlets", "--resources--", "-.resources--", MgnlNodeType.NT_CONTENTNODE))
166 
167                 .addTask(new ChildrenExistsDelegateTask("name", "description", RepositoryConstants.CONFIG, "/server/filters/securityCallback/bypasses", MgnlNodeType.NT_CONTENTNODE, null, new RemoveNodeTask("Update securityCallback", "Remove empty bypasses node from securityCallback.", RepositoryConstants.CONFIG, "/server/filters/securityCallback/bypasses")))
168                 .addTask(new PropertyValueDelegateTask("Remove urlPattern", "Remove urlPattern from 'magnolia' clientCallback if previously set to '*'", RepositoryConstants.CONFIG, "/server/filters/securityCallback/clientCallbacks/magnolia/urlPattern", "patternString", "*", true, new RemoveNodeTask("Update form clientCallback", "Remove 'urlPattern' from new 'magnolia' clientCallback", RepositoryConstants.CONFIG, "/server/filters/securityCallback/clientCallbacks/magnolia/urlPattern")))
169                 .addTask(new RenameNodesTask("Rename clientCallback", "Rename 'magnolia' clientCallback to 'form'.", RepositoryConstants.CONFIG, "/server/filters/securityCallback/clientCallbacks", "magnolia", "form", MgnlNodeType.NT_CONTENTNODE))
170                 .addTask(new NodeExistsDelegateTask("Server node", "Update uriSecurity if needed.", RepositoryConstants.CONFIG, "/server/filters/securityCallback/public",
171                         new OrderNodeBeforeTask("Order clientCallbacks", "Order 'form' clientCallback before 'public'.", RepositoryConstants.CONFIG, "/server/filters/securityCallback/clientCallbacks/form", "public"), null))
172                 .addTask(new RemoveNodeTask("Update contentSecurity", "Remove clientCallback from cms/contentSecurity as they're now under 'securityCallback'.", RepositoryConstants.CONFIG, "/server/filters/cms/contentSecurity/clientCallback"))
173                 .addTask(new OrderNodeBeforeTask("Order i18n", "Put i18n subnodes in proper order.", RepositoryConstants.CONFIG, "/server/i18n/content", "system")));
174 
175         register(DeltaBuilder.update("4.5.2", "")
176                 .addTask(new PropertyExistsDelegateTask("Fix property name", "", RepositoryConstants.CONFIG, "/server/security/userManagers/system", "realName", new MoveAndRenamePropertyTask("Fix propertyName", "/server/security/userManagers/system", "realName", "/server/security/userManagers/system", "realmName")))
177                 .addTask(new PropertyExistsDelegateTask("Fix property name", "", RepositoryConstants.CONFIG, "/server/security/userManagers/admin", "realName", new MoveAndRenamePropertyTask("Fix propertyName", "/server/security/userManagers/admin", "realName", "/server/security/userManagers/admin", "realmName"))));
178         register(DeltaBuilder.update("4.5.8", "")
179                 .addTask(new FindAndChangeTemplateIdTask("Change template id mgnlDelete", "Change template id mgnlDeleted to adminInterface:mgnlDeleted for all content marked as deleted in website repository", "website", "mgnlDeleted", "adminInterface:mgnlDeleted")));
180         register(DeltaBuilder.update("4.5.9", "")
181                 .addTask(new NodeExistsDelegateTask("AuditLogging configurations", "Add auditLogging configurations for delete action", "config", "/server/auditLogging/logConfigurations/delete", null, new PartialBootstrapTask("", "", "/mgnl-bootstrap/core/config.server.auditLogging.xml", "/auditLogging/logConfigurations/delete", ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW)))
182                 .addTask(new CheckAndModifyPropertyValueTask("AuditLogging configurations", "Change auditLogging class", "config", "/server/auditLogging", "class", "info.magnolia.logging.AuditLoggingManager", "info.magnolia.audit.AuditLoggingManager"))
183                 .addTask(updateSecurityBaseRole));
184         register((DeltaBuilder.update("4.5.10", ""))
185                 .addTask(new CheckAndModifyPropertyValueTask("MIMEMapping", "Change xsl extension mime-type from text/xml to application/xml", RepositoryConstants.CONFIG, "/server/MIMEMapping/xsl", "mime-type", "text/xml", "application/xml"))
186                 .addTask(new CheckAndModifyPropertyValueTask("MIMEMapping", "Change xml extension mime-type from text/xml to application/xml", RepositoryConstants.CONFIG, "/server/MIMEMapping/xml", "mime-type", "text/xml", "application/xml")));
187         register((DeltaBuilder.update("4.5.11", ""))
188                 .addTask(new PartialBootstrapTask("JSON", "Add JSON mime-type", "/mgnl-bootstrap/core/config.server.MIMEMapping.xml", "/MIMEMapping/json")));
189         register((DeltaBuilder.update("4.5.14", ""))
190                 .addTask(new PartialBootstrapTask("Anonymous user", "Change anonymous user permission. He can't have write access to himself.", "/mgnl-bootstrap/core/users.system.anonymous.xml", "/anonymous/acl_users")));
191         register((DeltaBuilder.update("4.5.16", ""))
192                 .addTask(new RenameOldServletMappingsNodesTask()));
193         register((DeltaBuilder.update("4.5.21", ""))
194                 .addTask(new PartialBootstrapTask("Add csrfSecurity Filter", "", "/mgnl-bootstrap/core/config.server.filters.xml", "/filters/csrfSecurity", ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW))
195                 .addTask(new NodeExistsDelegateTask("Order csrfSecurity Filter", "Put csrfSecurity before uriSecurity Filter.", RepositoryConstants.CONFIG, "/server/filters/uriSecurity",
196                         new OrderNodeBeforeTask("Order csrfSecurity Filter", "Put csrfSecurity before uriSecurity Filter.", RepositoryConstants.CONFIG, "/server/filters/csrfSecurity", "uriSecurity"),
197                         new WarnTask("CSRF Security Filter is inactive.", "CSRF Security Filter inactive. The installed csrfFilter would normally be ordered before the uriSecurity filter, but could not be moved there as a uriFilter node does not exist in the /server/filters node. The installed csrfFilter must be movded up the filters list manually.")
198                         ))
199                 .addTask(new PartialBootstrapTask("Add 'security' AuditLogging logConfiguration.", "", "/mgnl-bootstrap/core/config.server.auditLogging.xml", "/auditLogging/logConfigurations/security", ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW))
200                 );
201         register((DeltaBuilder.update("4.5.23", ""))
202                 .addTask(new RemovePermissionTask("Edit security-base role", "Remove messages page deny rule", "security-base", "uri", "/.magnolia/pages/messages*", AddURIPermissionTask.DENY)));
203     }
204 
205     @Override
206     protected List<Task> getBasicInstallTasks(InstallContext ctx) {
207         final List<Task> tasks = new ArrayList<Task>();
208         tasks.addAll(GenericTasks.genericTasksForNewInstallation());
209         tasks.add(auditTrailManagerTask);
210         tasks.add(bootstrapFreemarker);
211         tasks.add(addFreemarkerSharedVariables);
212         tasks.add(bootstrapWebContainerResources);
213         tasks.add(new BootstrapConditionally("Security", "Bootstraps security-base role.", "/mgnl-bootstrap/core/userroles.security-base.xml"));
214         // always hash passwords. Task will not re-hash so it is safe to run this op at any time, multiple times.
215         tasks.add(new HashUsersPasswords());
216         tasks.add(bootstrapChannelManagement);
217         tasks.add(bootstrapChannelFilter);
218         tasks.add(placeChannelBeforeLogout);
219 
220         return tasks;
221     }
222 
223     @Override
224     protected List<Condition> getInstallConditions() {
225         final ArrayList<Condition> conditions = new ArrayList<Condition>();
226 
227         conditions.add(new IsNotAProblematicEnvironmentCondition());
228 
229         final WebXmlConditionsUtil u = new WebXmlConditionsUtil(conditions);
230         u.servletIsNowWrapped("ActivationHandler");
231         u.servletIsNowWrapped("AdminTreeServlet");
232         u.servletIsNowWrapped("classpathspool");
233         u.servletIsNowWrapped("DialogServlet");
234         u.servletIsNowWrapped("PageServlet");
235         u.servletIsNowWrapped("log4j");
236         u.servletIsNowWrapped("FCKEditorSimpleUploadServlet");
237         u.servletIsDeprecated("uuidRequestDispatcher");
238         u.filterIsDeprecated("info.magnolia.cms.filters.MagnoliaManagedFilter", "info.magnolia.cms.filters.MgnlMainFilter");
239         u.filterMustBeRegisteredWithCorrectDispatchers("info.magnolia.cms.filters.MgnlMainFilter");
240         u.listenerIsDeprecated("info.magnolia.cms.servlets.PropertyInitializer", "info.magnolia.cms.servlets.MgnlServletContextListener");
241         u.listenerIsDeprecated("info.magnolia.cms.beans.config.ShutdownManager", "info.magnolia.cms.servlets.MgnlServletContextListener");
242         final WorkspaceXmlConditionsUtil u2 = new WorkspaceXmlConditionsUtil(conditions);
243         u2.textFilterClassesAreNotSet();
244 
245         conditions.add(new SystemTmpDirCondition());
246 
247         return conditions;
248     }
249 
250     private List<Condition> get45ConfigFileConditions() {
251         List<Condition> conditions = new ArrayList<Condition>();
252 
253         final TextFileConditionsUtil u = new TextFileConditionsUtil(conditions);
254         u.addFalseConditionIfExpressionIsContained(System.getProperty("java.security.auth.login.config"), "^Jackrabbit.*");
255 
256         final WorkspaceXmlConditionsUtil u2 = new WorkspaceXmlConditionsUtil(conditions);
257         u2.textFilterClassesAreNotSet();
258         u2.paramAnalyzerIsNotSet();
259         u2.accessControlProviderIsSet();
260 
261         return conditions;
262     }
263 
264 }