1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.module.groovy.setup;
35
36 import static info.magnolia.module.groovy.GroovyModule.*;
37 import static info.magnolia.test.hamcrest.NodeMatchers.*;
38 import static org.hamcrest.CoreMatchers.*;
39 import static org.junit.Assert.*;
40 import static org.mockito.Mockito.mock;
41
42 import info.magnolia.cms.security.MgnlGroupManager;
43 import info.magnolia.cms.security.MgnlRoleManager;
44 import info.magnolia.cms.security.MgnlUserManager;
45 import info.magnolia.cms.security.Permission;
46 import info.magnolia.cms.security.Realm;
47 import info.magnolia.cms.security.Role;
48 import info.magnolia.cms.security.SecuritySupport;
49 import info.magnolia.cms.security.SecuritySupportImpl;
50 import info.magnolia.context.MgnlContext;
51 import info.magnolia.jcr.predicate.NodeTypePredicate;
52 import info.magnolia.jcr.util.NodeTypeTemplateUtil;
53 import info.magnolia.jcr.util.NodeTypes;
54 import info.magnolia.jcr.util.NodeUtil;
55 import info.magnolia.jcr.util.PropertyUtil;
56 import info.magnolia.module.InstallContext;
57 import info.magnolia.module.ModuleManagementException;
58 import info.magnolia.module.ModuleVersionHandler;
59 import info.magnolia.module.ModuleVersionHandlerTestCase;
60 import info.magnolia.module.groovy.console.MgnlGroovyConsole;
61 import info.magnolia.module.model.Version;
62 import info.magnolia.repository.RepositoryConstants;
63 import info.magnolia.test.ComponentsTestUtil;
64 import info.magnolia.ui.form.field.definition.CodeFieldDefinition;
65
66 import java.io.Writer;
67 import java.util.Arrays;
68 import java.util.List;
69
70 import javax.jcr.Node;
71 import javax.jcr.NodeIterator;
72 import javax.jcr.RepositoryException;
73 import javax.jcr.Session;
74 import javax.jcr.nodetype.NodeType;
75 import javax.jcr.nodetype.NodeTypeManager;
76 import javax.jcr.nodetype.NodeTypeTemplate;
77
78 import org.junit.Before;
79 import org.junit.Test;
80
81 import com.vaadin.ui.UI;
82
83 import groovy.lang.Binding;
84
85
86 public class GroovyModuleVersionHandlerTest extends ModuleVersionHandlerTestCase {
87
88 private Node uiApp;
89 private Node uiConfig;
90 private Node groovyModule;
91 private MgnlRoleManager roleManager;
92
93 private Session scriptsSession;
94
95 @Override
96 protected String getModuleDescriptorPath() {
97 return "/META-INF/magnolia/groovy.xml";
98 }
99
100 @Override
101 protected ModuleVersionHandler newModuleVersionHandlerForTests() {
102 return new GroovyModuleVersionHandler();
103 }
104
105 @Override
106 protected List<String> getModuleDescriptorPathsForTests() {
107 return Arrays.asList("/META-INF/magnolia/core.xml");
108 }
109
110 @Override
111 protected String[] getExtraWorkspaces() {
112 return new String[]{SCRIPTS_REPOSITORY_NAME, "contacts"};
113 }
114
115 @Override
116 protected String getRepositoryConfigFileName() {
117 return "info/magnolia/module/groovy/setup/test-repositories.xml";
118 }
119
120 @Override
121 @Before
122 public void setUp() throws Exception {
123 super.setUp();
124
125 Session configSession = MgnlContext.getJCRSession(RepositoryConstants.CONFIG);
126 scriptsSession = MgnlContext.getJCRSession(SCRIPTS_REPOSITORY_NAME);
127
128 uiApp = NodeUtil.createPath(configSession.getRootNode(), "/modules/ui-admincentral/apps", NodeTypes.ContentNode.NAME);
129 groovyModule = NodeUtil.createPath(configSession.getRootNode(), "/modules/groovy", NodeTypes.ContentNode.NAME);
130 uiConfig = NodeUtil.createPath(configSession.getRootNode(), "/modules/ui-admincentral/config/appLauncherLayout/groups/dev/apps", NodeTypes.ContentNode.NAME);
131 uiApp.getSession().save();
132
133
134 final SecuritySupportImpl securitySupport = new SecuritySupportImpl();
135 securitySupport.addUserManager(Realm.REALM_ALL.getName(), new MgnlUserManager());
136 roleManager = new MgnlRoleManager();
137 securitySupport.setRoleManager(roleManager);
138 securitySupport.setGroupManager(new MgnlGroupManager());
139 ComponentsTestUtil.setInstance(SecuritySupport.class, securitySupport);
140
141 setupConfigProperty("/modules/groovy/apps/groovy/subApps/browser/workbench", "dropConstraintClass", "info.magnolia.contacts.app.main.tree.ContactDropConstraint");
142 }
143
144 @Test
145 public void updateFrom201WithExistingLegacyApp() throws ModuleManagementException, RepositoryException {
146
147 groovyModule.addNode("trees", NodeTypes.Folder.NAME);
148 groovyModule.addNode("dialogs", NodeTypes.Folder.NAME).addNode("scriptsEdit", NodeTypes.ContentNode.NAME);
149 groovyModule.addNode("controls", NodeTypes.Folder.NAME);
150
151 uiApp.addNode("groovyConsole", NodeTypes.ContentNode.NAME);
152 uiApp.addNode("groovyScripts", NodeTypes.ContentNode.NAME);
153
154 uiConfig.addNode("groovyConsole", NodeTypes.ContentNode.NAME);
155 uiConfig.addNode("groovyScript", NodeTypes.ContentNode.NAME);
156
157
158 executeUpdatesAsIfTheCurrentlyInstalledVersionWas(Version.parseVersion("2.0.1"));
159
160
161 assertFalse(groovyModule.hasNode("trees"));
162 assertFalse(groovyModule.hasNode("dialogs/scriptsEdit"));
163 assertFalse(groovyModule.hasNode("controls"));
164
165 assertFalse(uiApp.hasNode("groovyConsole"));
166 assertFalse(uiApp.hasNode("groovyScripts"));
167
168 assertFalse(uiConfig.hasNode("groovyConsole"));
169 assertFalse(uiConfig.hasNode("groovyScripts"));
170
171 assertTrue(uiConfig.hasNode("groovy"));
172 assertTrue(groovyModule.hasNode("fieldTypes"));
173 assertTrue(groovyModule.hasNode("dialogs/renameScript"));
174 }
175
176 @Test
177 public void updateFrom201WithNoExistingLegacyApp() throws ModuleManagementException, RepositoryException {
178
179
180
181 executeUpdatesAsIfTheCurrentlyInstalledVersionWas(Version.parseVersion("2.0.1"));
182
183
184 assertTrue(uiConfig.hasNode("groovy"));
185 assertTrue(groovyModule.hasNode("fieldTypes"));
186 assertTrue(groovyModule.hasNode("dialogs/renameScript"));
187 }
188
189 @Test
190 public void upgradeFrom21SetsAppPermissions() throws Exception {
191
192 final Session configSession = MgnlContext.getJCRSession(RepositoryConstants.CONFIG);
193
194
195 executeUpdatesAsIfTheCurrentlyInstalledVersionWas(Version.parseVersion("2.1"));
196
197
198 assertEquals("scripter", configSession.getProperty("/modules/groovy/apps/groovy/permissions/roles/scripter").getString());
199 }
200
201 @Test
202 public void updateFrom21ReordersGroovyInDevGroup() throws Exception {
203
204 Session session = MgnlContext.getJCRSession(RepositoryConstants.CONFIG);
205 Node devApps = NodeUtil.createPath(session.getRootNode(), "/modules/ui-admincentral/config/appLauncherLayout/groups/dev/apps", NodeTypes.ContentNode.NAME);
206 NodeUtil.createPath(devApps, "jcrQueryUtils", NodeTypes.ContentNode.NAME);
207 NodeUtil.createPath(devApps, "activation", NodeTypes.ContentNode.NAME);
208
209
210 executeUpdatesAsIfTheCurrentlyInstalledVersionWas(Version.parseVersion("2.1"));
211
212
213 NodeIterator it = devApps.getNodes();
214 assertTrue(devApps.hasNode("groovy"));
215 assertEquals("jcrQueryUtils", it.nextNode().getName());
216 assertEquals("groovy", it.nextNode().getName());
217 assertEquals("activation", it.nextNode().getName());
218 }
219
220 @Test
221 public void updateFrom22AddsDuplicateAction() throws Exception {
222
223
224
225 executeUpdatesAsIfTheCurrentlyInstalledVersionWas(Version.parseVersion("2.2"));
226
227
228 assertTrue(groovyModule.hasNode("apps/groovy/subApps/browser/actions/duplicateScript"));
229 assertTrue(groovyModule.hasNode("apps/groovy/subApps/browser/actionbar/sections/script/groups/editActions/items/duplicateScript"));
230 }
231
232 @Test
233 public void upgradeFrom10() throws Exception {
234
235 executeUpdatesAsIfTheCurrentlyInstalledVersionWas(Version.parseVersion("1.0"));
236
237
238 }
239
240 @Test
241 public void upgradeFrom222() throws Exception {
242
243 setupConfigProperty("/modules/groovy/apps/groovy/subApps/detail/editor/form/tabs/script/fields/text", "class", "info.magnolia.ui.form.field.definition.BasicTextCodeFieldDefinition");
244 Session userRoles = MgnlContext.getJCRSession(RepositoryConstants.USER_ROLES);
245 Role role = roleManager.createRole(SCRIPTER_ROLE_NAME);
246
247 roleManager.addPermission(role, RepositoryConstants.CONFIG, "/modules/adminInterface/config/menu/tools/groovyInteractiveShell", Permission.READ);
248 assertTrue(userRoles.propertyExists("/" + SCRIPTER_ROLE_NAME + "/acl_config/0/path"));
249 assertEquals("/modules/adminInterface/config/menu/tools/groovyInteractiveShell",
250 userRoles.getProperty("/" + SCRIPTER_ROLE_NAME + "/acl_config/0/path").getString());
251
252 roleManager.addPermission(role, RepositoryConstants.CONFIG, "/modules/adminInterface/config/menu/tools/scripts", Permission.READ);
253 assertTrue(userRoles.propertyExists("/" + SCRIPTER_ROLE_NAME + "/acl_config/0/path"));
254 assertEquals("/modules/adminInterface/config/menu/tools/scripts",
255 userRoles.getProperty("/" + SCRIPTER_ROLE_NAME + "/acl_config/00/path").getString());
256
257 roleManager.addPermission(role, RepositoryConstants.CONFIG, "/modules/adminInterface/config/menu/tools", Permission.READ);
258 assertTrue(userRoles.propertyExists("/" + SCRIPTER_ROLE_NAME + "/acl_config/01/path"));
259 assertEquals("/modules/adminInterface/config/menu/tools",
260 userRoles.getProperty("/" + SCRIPTER_ROLE_NAME + "/acl_config/01/path").getString());
261
262
263 InstallContext ctx = executeUpdatesAsIfTheCurrentlyInstalledVersionWas(Version.parseVersion("2.2.2"));
264
265
266 assertFalse(userRoles.nodeExists("/" + SCRIPTER_ROLE_NAME + "/acl_config/0"));
267 assertFalse(userRoles.nodeExists("/" + SCRIPTER_ROLE_NAME + "/acl_config/00"));
268 assertFalse(userRoles.nodeExists("/" + SCRIPTER_ROLE_NAME + "/acl_config/01"));
269 this.assertNoMessages(ctx);
270 }
271
272 @Test
273 public void upgradeFrom23() throws Exception {
274
275
276
277 InstallContext ctx = executeUpdatesAsIfTheCurrentlyInstalledVersionWas(Version.parseVersion("2.3"));
278
279
280 assertThat(ctx.getConfigJCRSession().getNode("/modules/groovy/apps/groovy/subApps/detail/editor/form/tabs/script/fields/text/"), hasNode("validators"));
281 assertThat(ctx.getConfigJCRSession().getNode("/modules/groovy/apps/groovy/subApps/browser/workbench"), hasProperty("dropConstraintClass", "info.magnolia.module.groovy.app.drop.GroovyDropConstraint"));
282 }
283
284 @Test
285 public void updateFrom232ReplaceBasicTextCodeFieldDefinition() throws Exception {
286
287 String textPath = "/modules/groovy/apps/groovy/subApps/detail/editor/form/tabs/script/fields/text";
288 setupConfigProperty(textPath, "class", "info.magnolia.ui.form.field.definition.BasicTextCodeFieldDefinition");
289
290
291 InstallContext ctx = executeUpdatesAsIfTheCurrentlyInstalledVersionWas(Version.parseVersion("2.3.2"));
292
293
294 assertThat(ctx.getConfigJCRSession().getNode(textPath), hasProperty("class", CodeFieldDefinition.class.getName()));
295 }
296
297 @Test
298 public void updateFrom252RemovesWorkspaceFromCreateAppScriptEditorSection() throws Exception {
299
300 String editorSectionOpeningLine = "editor {";
301 String setWorkspaceLine = "workspace(app_workspace)";
302 setupProperty(SCRIPTS_REPOSITORY_NAME, "/createAppScript", "text", editorSectionOpeningLine + "\n" + setWorkspaceLine, null);
303
304
305 executeUpdatesAsIfTheCurrentlyInstalledVersionWas(Version.parseVersion("2.5.2"));
306
307
308 assertThat(scriptsSession.getNode("/createAppScript"), hasProperty("text"));
309 String scriptProperty = scriptsSession.getNode("/createAppScript").getProperty("text").getString();
310
311 int indexOfEditorSectionOpeningLine = scriptProperty.indexOf(editorSectionOpeningLine);
312 assertThat(scriptProperty.indexOf(setWorkspaceLine, indexOfEditorSectionOpeningLine), is(-1));
313 }
314
315 @Test
316 public void updateFrom253ReplacesOldGroovyMailCommandSampleAndRemovesEmptyFolders() throws Exception {
317
318 setupNode(SCRIPTS_REPOSITORY_NAME, "/my/commands/GroovyMailCommand");
319 setupConfigNode("modules/mail");
320
321
322 executeUpdatesAsIfTheCurrentlyInstalledVersionWas(Version.parseVersion("2.5.3"));
323
324
325 assertThat(scriptsSession.nodeExists("/my"), is(false));
326 assertThat(scriptsSession.getRootNode(), hasNode("samples/commands/GroovyMailCommand"));
327 }
328
329 @Test
330 public void updateFrom253ReplacesOldGroovyMailCommandSampleAndKeepsNonEmptyFolders() throws Exception {
331
332 setupConfigNode("modules/mail");
333 setupNode(SCRIPTS_REPOSITORY_NAME, "/my/commands/GroovyMailCommand");
334 setupNode(SCRIPTS_REPOSITORY_NAME, "/my/commands/CustomCommand");
335
336 executeUpdatesAsIfTheCurrentlyInstalledVersionWas(Version.parseVersion("2.5.3"));
337
338
339 assertThat(scriptsSession.nodeExists("/my/commands/GroovyMailCommand"), is(false));
340 assertThat(scriptsSession.nodeExists("/my/commands/CustomCommand"), is(true));
341 assertThat(scriptsSession.getRootNode(), hasNode("samples/commands/GroovyMailCommand"));
342 }
343
344 @Test
345 public void updateFrom260FixesCreateAppScript() throws Exception {
346
347 setupNode(SCRIPTS_REPOSITORY_NAME, "/createAppScript");
348
349
350 executeUpdatesAsIfTheCurrentlyInstalledVersionWas(Version.parseVersion("2.6"));
351
352
353 assertThat(scriptsSession.getNode("/createAppScript").getProperty("text").getString(), containsString("/modules/publishing-core/config/receivers"));
354 assertThat(scriptsSession.getNode("/createAppScript").getProperty("text").getString(), not(containsString("/server/activation/subscribers")));
355 }
356
357 @Test
358 public void updateFrom261() throws Exception {
359
360 setupConfigNode("modules/mail");
361 setupConfigNode("modules/contacts");
362 setupConfigNode("modules/travel-demo");
363
364 setupNode(SCRIPTS_REPOSITORY_NAME, "/samples/commands/GroovyMailCommand");
365
366
367 executeUpdatesAsIfTheCurrentlyInstalledVersionWas(Version.parseVersion("2.6.1"));
368
369
370 assertThat(scriptsSession.getRootNode(), allOf(
371 hasNode("samples/commands/GroovyMailCommand"),
372 hasNode("deleteSomeContacts"),
373 hasNode("importContactsFromXml"),
374 hasNode("simplifiedDataHierarchyNavigation")
375 ));
376 }
377
378 @Test
379 public void cleanInstallBootstrapsSamples() throws Exception {
380
381 setupConfigNode("modules/contacts");
382 setupConfigNode("modules/ui-admincentral");
383 setupConfigNode("modules/mail");
384
385 setupConfigNode("modules/travel-demo");
386 setupNode(RepositoryConstants.WEBSITE, "travel/about");
387
388
389 executeUpdatesAsIfTheCurrentlyInstalledVersionWas(null);
390
391
392 assertThat(scriptsSession.getRootNode(), allOf(
393 hasNode("deleteSomeContacts"),
394 hasNode("importContactsFromXml"),
395 hasNode("simplifiedDataHierarchyNavigation"),
396 hasNode("createAppScript"),
397 hasNode("samples/commands/GroovyMailCommand")
398 ));
399
400 final NodeTypeManager nodeTypeManager = MgnlContext.getJCRSession("contacts").getWorkspace().getNodeTypeManager();
401 final NodeTypeTemplate type = NodeTypeTemplateUtil.createSimpleNodeType(nodeTypeManager, "mgnl:contact", Arrays.asList(NodeType.NT_HIERARCHY_NODE, NodeType.MIX_REFERENCEABLE, NodeTypes.Created.NAME, NodeTypes.Activatable.NAME, NodeTypes.LastModified.NAME, NodeTypes.Renderable.NAME));
402 nodeTypeManager.registerNodeType(type, true);
403
404 final MgnlGroovyConsole shell = new MgnlGroovyConsole(new Binding(), null, null);
405
406 for (Node script : NodeUtil.collectAllChildren(scriptsSession.getRootNode(), new NodeTypePredicate(NodeTypes.Content.NAME))) {
407 final String scriptText = PropertyUtil.getString(script, "text");
408
409 if (PropertyUtil.getBoolean(script, "script", false)) {
410 shell.runAsync(scriptText, mock(UI.class), new MgnlGroovyConsole.ScriptCallback() {
411 @Override
412 public void onSuccess(String result) {
413 }
414
415 @Override
416 public void onFailure(Throwable e) {
417 fail(String.format("Exception in script %s\n%s", script, e.getMessage()));
418 }
419
420 @Override
421 public void onProgress(Writer out) {
422 }
423
424 @Override
425 public boolean requiresNotificationMessageUponCompletion() {
426 return false;
427 }
428 });
429 } else {
430 shell.parse(scriptText);
431 }
432 }
433 }
434
435 }