Browse code

FEATBL-807 Feat: handle calendar resource templates

Vincent Vignaud authored on 13/06/2019 07:53:42
Showing 19 changed files
... ...
@@ -91,4 +91,15 @@ public class VEventSeries {
91 91
 		return main != null ? main : occurrences.get(0);
92 92
 	}
93 93
 
94
+	public List<VEvent> flatten() {
95
+		final List<VEvent> evts = new ArrayList<>();
96
+		if (this.main != null) {
97
+			evts.add(this.main);
98
+		}
99
+		this.occurrences.forEach(occurrence -> {
100
+			evts.add(occurrence);
101
+		});
102
+		return evts;
103
+	}
104
+
94 105
 }
... ...
@@ -45,4 +45,5 @@ Import-Package: net.bluemind.addressbook.domainbook,
45 45
  net.bluemind.document.persistance.fs,
46 46
  net.bluemind.document.storage,
47 47
  net.bluemind.mailbox.persistance,
48
+ net.bluemind.resource.persistance,
48 49
  org.joda.time
... ...
@@ -115,7 +115,7 @@ public class IcsHook implements ICalendarHook {
115 115
 				sendEventInvitations(message);
116 116
 			} else {
117 117
 				DirEntry dirEntry = getMyDirEntry(message);
118
-				List<VEvent> flat = flatten(message.vevent);
118
+				List<VEvent> flat = message.vevent.flatten();
119 119
 				for (VEvent vEvent : flat) {
120 120
 					Optional<EventAttendeeTuple> attendee = getMatchingAttendeeForEvent(vEvent, dirEntry);
121 121
 					if (attendee.isPresent()) {
... ...
@@ -138,7 +138,7 @@ public class IcsHook implements ICalendarHook {
138 138
 		}
139 139
 
140 140
 		VEventSeries oldEventSeries = message.oldEvent;
141
-		List<VEvent> flatten = flatten(updatedEvent);
141
+		List<VEvent> flatten = updatedEvent.flatten();
142 142
 		try {
143 143
 			if (isMasterVersion(message.oldEvent, message.container)) {
144 144
 				onMasterVersionUpdated(message, updatedEvent, oldEventSeries, flatten);
... ...
@@ -223,6 +223,7 @@ public class IcsHook implements ICalendarHook {
223 223
 			deletedAttendees = deletedAttendees.stream().filter(a -> {
224 224
 				return !userDeletedFromSeries.contains(a);
225 225
 			}).collect(Collectors.toList());
226
+
226 227
 			if (!evt.exception()) {
227 228
 				userDeletedFromSeries.addAll(deletedAttendees);
228 229
 			}
... ...
@@ -348,7 +349,7 @@ public class IcsHook implements ICalendarHook {
348 349
 		List<Attendee> seriesAttendees = master != null ? master.attendees.stream().filter(a -> {
349 350
 			return attendsToSeries(message.vevent, a);
350 351
 		}).collect(Collectors.toList()) : Collections.emptyList();
351
-		List<VEvent> events = flatten(message.vevent);
352
+		List<VEvent> events = message.vevent.flatten();
352 353
 
353 354
 		for (VEvent evt : events) {
354 355
 			for (Attendee attendee : evt.attendees) {
... ...
@@ -447,7 +448,7 @@ public class IcsHook implements ICalendarHook {
447 448
 			return attendsToSeries(message.vevent, a);
448 449
 		}).collect(Collectors.toList()) : Collections.emptyList();
449 450
 
450
-		List<VEvent> events = flatten(message.vevent);
451
+		List<VEvent> events = message.vevent.flatten();
451 452
 
452 453
 		for (VEvent evt : events) {
453 454
 			for (Attendee attendee : evt.attendees) {
... ...
@@ -848,13 +849,13 @@ public class IcsHook implements ICalendarHook {
848 849
 	}
849 850
 
850 851
 	private VEventSeries getSeriesForAttendee(VEventSeries updatedEvent, Attendee attendee) {
851
-		return flatten(updatedEvent).stream() //
852
+		return updatedEvent.flatten().stream() //
852 853
 				.filter(evt -> userAttends(evt, attendee)) //
853 854
 				.reduce(new VEventSeries(), reduceSeries(), combineSeries());
854 855
 	}
855 856
 
856 857
 	private VEventSeries reduceToAttendee(VEventSeries updatedEvent, Attendee attendee) {
857
-		return flatten(updatedEvent).stream() //
858
+		return updatedEvent.flatten().stream() //
858 859
 				.map(evt -> {
859 860
 					evt.attendees = Arrays.asList(attendee);
860 861
 					return evt;
... ...
@@ -1021,7 +1022,7 @@ public class IcsHook implements ICalendarHook {
1021 1022
 
1022 1023
 	private boolean attendsToSeries(VEventSeries series, Attendee attendee) {
1023 1024
 		boolean attends = true;
1024
-		List<VEvent> flatten = flatten(series);
1025
+		List<VEvent> flatten = series.flatten();
1025 1026
 		for (VEvent vEvent : flatten) {
1026 1027
 			attends = attends && userAttends(vEvent, attendee);
1027 1028
 		}
... ...
@@ -1082,10 +1083,6 @@ public class IcsHook implements ICalendarHook {
1082 1083
 		return dirEntry.entryUid.equals(container.owner);
1083 1084
 	}
1084 1085
 
1085
-	/**
1086
-	 *
1087
-	 */
1088
-
1089 1086
 	private IServiceProvider provider() {
1090 1087
 		return ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM);
1091 1088
 	}
... ...
@@ -1100,17 +1097,6 @@ public class IcsHook implements ICalendarHook {
1100 1097
 		}
1101 1098
 	}
1102 1099
 
1103
-	private List<VEvent> flatten(VEventSeries vEvents) {
1104
-		List<VEvent> evts = new ArrayList<>();
1105
-		if (vEvents.main != null) {
1106
-			evts.add(vEvents.main);
1107
-		}
1108
-		vEvents.occurrences.forEach(occurrence -> {
1109
-			evts.add(occurrence);
1110
-		});
1111
-		return evts;
1112
-	}
1113
-
1114 1100
 	private static class MailData {
1115 1101
 		public final Organizer organizer;
1116 1102
 		public final String subject;
... ...
@@ -1189,4 +1175,5 @@ public class IcsHook implements ICalendarHook {
1189 1175
 		}
1190 1176
 
1191 1177
 	}
1178
+
1192 1179
 }
... ...
@@ -32,6 +32,19 @@ public class VEventMessage {
32 32
 	public Container container;
33 33
 	public String auditEventId;
34 34
 
35
+	public VEventMessage() {
36
+	}
37
+
38
+	public VEventMessage(final VEventSeries vevent, final String uid, boolean sendNotifications,
39
+			final SecurityContext securityContext, final String auditEventId, final Container container) {
40
+		this.itemUid = uid;
41
+		this.vevent = vevent;
42
+		this.securityContext = securityContext;
43
+		this.container = container;
44
+		this.sendNotifications = sendNotifications;
45
+		this.auditEventId = auditEventId;
46
+	}
47
+
35 48
 	public VEventMessage copy() {
36 49
 		VEventMessage copy = new VEventMessage();
37 50
 		copy.itemUid = this.itemUid;
... ...
@@ -33,5 +33,7 @@ Require-Bundle: org.junit,
33 33
  net.bluemind.calendar.api,
34 34
  net.bluemind.tag.hooks;bundle-version="4.1.0",
35 35
  net.bluemind.externaluser.service;bundle-version="4.1.0",
36
- net.bluemind.externaluser.api
36
+ net.bluemind.externaluser.api,
37
+ net.bluemind.backend.cyrus,
38
+ net.bluemind.resource.service;bundle-version="4.1.0"
37 39
 
... ...
@@ -3,4 +3,7 @@
3 3
  },
4 4
  { 
5 5
     "name":"bluemind/elasticsearch-tests" 
6
+ },
7
+ {
8
+    "name":"bluemind/imap-role"
6 9
 }]
7 10
new file mode 100644
... ...
@@ -0,0 +1,449 @@
1
+/* BEGIN LICENSE
2
+  * Copyright © Blue Mind SAS, 2012-2019
3
+  *
4
+  * This file is part of BlueMind. BlueMind is a messaging and collaborative
5
+  * solution.
6
+  *
7
+  * This program is free software; you can redistribute it and/or modify
8
+  * it under the terms of either the GNU Affero General Public License as
9
+  * published by the Free Software Foundation (version 3 of the License).
10
+  *
11
+  * This program is distributed in the hope that it will be useful,
12
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
+  *
15
+  * See LICENSE.txt
16
+  * END LICENSE
17
+  */
18
+package net.bluemind.calendar.service.internal;
19
+
20
+import static org.junit.Assert.assertNotNull;
21
+
22
+import java.sql.SQLException;
23
+import java.util.ArrayList;
24
+import java.util.Arrays;
25
+import java.util.Collections;
26
+import java.util.HashMap;
27
+import java.util.HashSet;
28
+import java.util.List;
29
+import java.util.Map;
30
+import java.util.UUID;
31
+
32
+import org.joda.time.DateTime;
33
+import org.joda.time.DateTimeZone;
34
+import org.junit.Assert;
35
+import org.junit.Before;
36
+import org.junit.Test;
37
+import org.vertx.java.core.AsyncResult;
38
+import org.vertx.java.core.Handler;
39
+
40
+import com.google.common.collect.Lists;
41
+import com.google.common.util.concurrent.SettableFuture;
42
+
43
+import net.bluemind.addressbook.api.VCard;
44
+import net.bluemind.addressbook.api.VCard.Identification.FormatedName;
45
+import net.bluemind.addressbook.api.VCard.Identification.Name;
46
+import net.bluemind.backend.cyrus.CyrusAdmins;
47
+import net.bluemind.backend.cyrus.CyrusService;
48
+import net.bluemind.calendar.api.ICalendarUids;
49
+import net.bluemind.calendar.api.VEvent;
50
+import net.bluemind.calendar.api.VEventSeries;
51
+import net.bluemind.calendar.hook.internal.VEventMessage;
52
+import net.bluemind.config.InstallationId;
53
+import net.bluemind.core.api.Email;
54
+import net.bluemind.core.api.date.BmDateTime;
55
+import net.bluemind.core.api.date.BmDateTime.Precision;
56
+import net.bluemind.core.api.date.BmDateTimeWrapper;
57
+import net.bluemind.core.api.fault.ServerFault;
58
+import net.bluemind.core.container.model.Container;
59
+import net.bluemind.core.container.model.ItemValue;
60
+import net.bluemind.core.container.persistance.ContainerStore;
61
+import net.bluemind.core.context.SecurityContext;
62
+import net.bluemind.core.jdbc.JdbcTestHelper;
63
+import net.bluemind.core.rest.ServerSideServiceProvider;
64
+import net.bluemind.core.sessions.Sessions;
65
+import net.bluemind.core.tests.BmTestContext;
66
+import net.bluemind.directory.api.BaseDirEntry;
67
+import net.bluemind.domain.api.Domain;
68
+import net.bluemind.icalendar.api.ICalendarElement.Attendee;
69
+import net.bluemind.icalendar.api.ICalendarElement.CUType;
70
+import net.bluemind.lib.vertx.VertxPlatform;
71
+import net.bluemind.mailbox.api.Mailbox.Routing;
72
+import net.bluemind.pool.impl.BmConfIni;
73
+import net.bluemind.resource.api.IResources;
74
+import net.bluemind.resource.api.ResourceDescriptor;
75
+import net.bluemind.resource.api.ResourceDescriptor.PropertyValue;
76
+import net.bluemind.resource.api.ResourceReservationMode;
77
+import net.bluemind.resource.api.type.IResourceTypes;
78
+import net.bluemind.resource.api.type.ResourceTypeDescriptor;
79
+import net.bluemind.resource.api.type.ResourceTypeDescriptor.Property;
80
+import net.bluemind.server.api.IServer;
81
+import net.bluemind.server.api.Server;
82
+import net.bluemind.tag.api.TagRef;
83
+import net.bluemind.tests.defaultdata.PopulateHelper;
84
+import net.bluemind.user.api.User;
85
+import net.bluemind.user.persistance.UserSubscriptionStore;
86
+import net.bluemind.user.service.internal.ContainerUserStoreService;
87
+
88
+public class VEventSeriesSanitizerTests {
89
+	private static final String USER_UID_AND_LOGIN = "u1";
90
+	private static final String TEMPLATE = "Hello! I am a template mate! ${Organizer} invites you to this wonderful event with the property ${MyCustomPropOne} and also ${MyCustomPropTwo} and the even better ${MyCustomPropThree} !!! How lucky you!\nThis entire ${line} should be removed since it contains ${unknown} variables.\nThis line should be kept.";
91
+	private static final String TRANSFORMED_TEMPLATE = ResourceTemplateHandler.separator()
92
+			+ "FR Hello! I am a template mate! John Doe invites you to this wonderful event with the property My Custom Prop One Value and also My Custom Prop Two Value and the even better My Custom Prop Three Value !!! How lucky you!\nThis line should be kept.";
93
+	private String domainUid;
94
+	private ItemValue<Server> dataLocation;
95
+	private ContainerStore containerHome;
96
+	private ContainerUserStoreService userStoreService;
97
+	private User user;
98
+	private ServerSideServiceProvider provider;
99
+
100
+	@SuppressWarnings("deprecation")
101
+	@Before
102
+	public void before() throws Exception {
103
+		JdbcTestHelper.getInstance().beforeTest();
104
+
105
+		final SettableFuture<Void> future = SettableFuture.<Void>create();
106
+		Handler<AsyncResult<Void>> done = new Handler<AsyncResult<Void>>() {
107
+
108
+			@Override
109
+			public void handle(AsyncResult<Void> event) {
110
+				future.set(null);
111
+			}
112
+		};
113
+		VertxPlatform.spawnVerticles(done);
114
+		future.get();
115
+
116
+		this.domainUid = "test.lan";
117
+
118
+		this.provider = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM);
119
+
120
+		Server imapServer = new Server();
121
+		imapServer.ip = new BmConfIni().get("imap-role");
122
+		imapServer.tags = Lists.newArrayList("mail/imap");
123
+
124
+		PopulateHelper.initGlobalVirt(imapServer);
125
+		this.dataLocation = this.provider.instance(IServer.class, InstallationId.getIdentifier())
126
+				.getComplete(imapServer.ip);
127
+
128
+		this.containerHome = new ContainerStore(JdbcTestHelper.getInstance().getDataSource(), SecurityContext.SYSTEM);
129
+		this.initDomain(dataLocation, imapServer);
130
+
131
+		this.createCyrusPartition(imapServer, this.domainUid);
132
+	}
133
+
134
+	private void createCyrusPartition(final Server imapServer, final String domainUid) {
135
+		final CyrusService cyrusService = new CyrusService(imapServer.ip);
136
+		cyrusService.createPartition(domainUid);
137
+		cyrusService.refreshPartitions(Arrays.asList(domainUid));
138
+		new CyrusAdmins(
139
+				ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IServer.class, "default"),
140
+				imapServer.ip).write();
141
+		cyrusService.reload();
142
+	}
143
+
144
+	/**
145
+	 * Test {@link ResourceDescriptionAdapterHook#onEventCreated(VEventMessage)} :
146
+	 * create an event with a resource having a template.
147
+	 */
148
+	@Test
149
+	public void onEventCreated() {
150
+		// build the event and call ResourceDescriptionAdapterHook.onEventCreated
151
+		final String description = "2 individuals attendees and 1 resource attendee having a template";
152
+		final VEventMessage vEventMessage = this.eventCreation(description, true);
153
+
154
+		// check the result - the processed template should have been added
155
+		Assert.assertNotNull(vEventMessage.vevent);
156
+		final List<VEvent> vEvents = vEventMessage.vevent.flatten();
157
+		Assert.assertNotNull(vEvents);
158
+		final String expectedResult = description + TRANSFORMED_TEMPLATE;
159
+		this.checkDescription(vEvents, expectedResult);
160
+	}
161
+
162
+	private VEventMessage eventCreation(final String description, final boolean withResource) {
163
+		// build event
164
+		final VEventMessage vEventMessage = this.buildEvent(description, withResource);
165
+
166
+		// call sanitizer
167
+		final Map<String, String> params = new HashMap<>(2);
168
+		params.put("owner", vEventMessage.container.owner);
169
+		params.put("domainUid", this.domainUid);
170
+		new VEventSeriesSanitizer(new BmTestContext(Sessions.get().getIfPresent(user.login)))
171
+				.create(vEventMessage.vevent, params);
172
+
173
+		return vEventMessage;
174
+	}
175
+
176
+	/**
177
+	 * Test {@link ResourceDescriptionAdapterHook#onEventUpdated(VEventMessage)} :
178
+	 * delete a resource having a template.
179
+	 */
180
+	@Test
181
+	public void onResourceDeleted() {
182
+		// first, create an event with a resource
183
+		final String oldDescription = "2 individuals attendees and 1 resource attendee having a template";
184
+		final VEventMessage oldEventMessage = this.eventCreation(oldDescription, true);
185
+
186
+		// build an event without a resource
187
+		final String description = "delete 1 resource attendee having an already transformed template in the description";
188
+		final VEventMessage vEventMessage = this.buildEvent(description + TRANSFORMED_TEMPLATE, false);
189
+		vEventMessage.oldEvent = oldEventMessage.vevent;
190
+
191
+		// execute the code
192
+		final Map<String, String> params = new HashMap<>(2);
193
+		params.put("owner", vEventMessage.container.owner);
194
+		params.put("domainUid", this.domainUid);
195
+		new VEventSeriesSanitizer(new BmTestContext(Sessions.get().getIfPresent(user.login)))
196
+				.update(vEventMessage.oldEvent, vEventMessage.vevent, params);
197
+
198
+		// check the result - the processed template should have been removed
199
+		Assert.assertNotNull(vEventMessage.vevent);
200
+		final List<VEvent> vEvents = vEventMessage.vevent.flatten();
201
+		Assert.assertNotNull(vEvents);
202
+		final String expectedResult = description;
203
+		this.checkDescription(vEvents, expectedResult);
204
+	}
205
+
206
+	/**
207
+	 * Test {@link ResourceDescriptionAdapterHook#onEventUpdated(VEventMessage)} :
208
+	 * add a resource having a template.
209
+	 */
210
+	@Test
211
+	public void onResourceAdded() {
212
+		// first, create an event without resource
213
+		final String oldDescription = "2 individuals attendees";
214
+		final VEventMessage oldEventMessage = this.eventCreation(oldDescription, false);
215
+
216
+		// build event with resource
217
+		final String description = "add 1 resource attendee having a template";
218
+		final VEventMessage vEventMessage = this.buildEvent(description, true);
219
+		vEventMessage.oldEvent = oldEventMessage.vevent;
220
+
221
+		// execute the code
222
+		final Map<String, String> params = new HashMap<>(2);
223
+		params.put("owner", vEventMessage.container.owner);
224
+		params.put("domainUid", this.domainUid);
225
+		new VEventSeriesSanitizer(new BmTestContext(Sessions.get().getIfPresent(user.login)))
226
+				.update(vEventMessage.oldEvent, vEventMessage.vevent, params);
227
+
228
+		// check the result - the processed template should have been added
229
+		Assert.assertNotNull(vEventMessage.vevent);
230
+		final List<VEvent> vEvents = vEventMessage.vevent.flatten();
231
+		Assert.assertNotNull(vEvents);
232
+		final String expectedResult = description + TRANSFORMED_TEMPLATE;
233
+		this.checkDescription(vEvents, expectedResult);
234
+	}
235
+
236
+	private void checkDescription(final List<VEvent> vEvents, final String expectedResult) {
237
+		vEvents.forEach(vEvent -> {
238
+			Assert.assertNotNull(vEvent.description);
239
+			Assert.assertEquals(expectedResult, vEvent.description);
240
+		});
241
+	}
242
+
243
+	private VEventMessage buildEvent(final String description, final boolean withResource) {
244
+		final String subject = "onResourceCreated";
245
+		final List<Attendee> attendees = new ArrayList<>(3);
246
+
247
+		final Attendee toto = new Attendee();
248
+		toto.commonName = "Toto Matic";
249
+		toto.cutype = CUType.Individual;
250
+		toto.mailto = "toto@" + this.domainUid;
251
+		attendees.add(toto);
252
+
253
+		final Attendee georges = new Attendee();
254
+		georges.commonName = "Georges Abitbol";
255
+		georges.cutype = CUType.Individual;
256
+		georges.mailto = "georges@" + this.domainUid;
257
+		attendees.add(georges);
258
+
259
+		if (withResource) {
260
+			final Attendee visio = this.buildAndPersistResource();
261
+			attendees.add(visio);
262
+		}
263
+
264
+		final VEventMessage vEventMessage = this.buildEvent(subject, description, attendees);
265
+
266
+		return vEventMessage;
267
+	}
268
+
269
+	@SuppressWarnings("serial")
270
+	private Attendee buildAndPersistResource() {
271
+		final Attendee visio = new Attendee();
272
+		visio.commonName = "Visio-conference";
273
+		visio.cutype = CUType.Resource;
274
+		final String resourceId = "visioId";
275
+		visio.mailto = resourceId + "@" + this.domainUid;
276
+		visio.dir = "path/to/my/resource/" + resourceId;
277
+		final String resourceTypeId = "visioTypeId";
278
+		final String template = TEMPLATE;
279
+		this.createResourceTypeWithTemplate(resourceTypeId, visio.commonName, new HashMap<String, String>() {
280
+			{
281
+				put("customProp1", "MyCustomPropOne");
282
+				put("customProp2", "MyCustomPropTwo");
283
+				put("customProp3", "MyCustomPropThree");
284
+			}
285
+		}, template);
286
+
287
+		this.createResource(resourceId, resourceTypeId, visio.commonName, new HashMap<String, String>() {
288
+			{
289
+				put("customProp1", "My Custom Prop One Value");
290
+				put("customProp2", "My Custom Prop Two Value");
291
+				put("customProp3", "My Custom Prop Three Value");
292
+			}
293
+		});
294
+		return visio;
295
+	}
296
+
297
+	private void initDomain(ItemValue<Server> dataLocation, Server... servers) throws Exception {
298
+		ItemValue<Domain> domain = PopulateHelper.createTestDomain(domainUid, servers);
299
+		Container userContainer = containerHome.get(domainUid);
300
+		this.userStoreService = new ContainerUserStoreService(new BmTestContext(SecurityContext.SYSTEM), userContainer,
301
+				domain);
302
+		Container mboxContainer = containerHome.get(domainUid);
303
+		assertNotNull(mboxContainer);
304
+		ItemValue<User> user1Item = createTestUser(dataLocation, USER_UID_AND_LOGIN);
305
+		this.user = user1Item.value;
306
+	}
307
+
308
+	@SuppressWarnings("deprecation")
309
+	private ItemValue<User> createTestUser(ItemValue<Server> dataLocation, String login)
310
+			throws ServerFault, SQLException {
311
+		ItemValue<User> user = defaultUser(dataLocation, login, login);
312
+		userStoreService.create(user.uid, login, user.value);
313
+		SecurityContext securityContext = new SecurityContext(login, login, new ArrayList<String>(),
314
+				new ArrayList<String>(), domainUid);
315
+		createTestContainer(securityContext, ICalendarUids.TYPE, user.value.login,
316
+				ICalendarUids.defaultUserCalendar(user.uid), user.uid);
317
+		Sessions.get().put(login, securityContext);
318
+		return user;
319
+	}
320
+
321
+	@SuppressWarnings("deprecation")
322
+	private void createTestContainer(SecurityContext context, String type, String login, String name, String owner)
323
+			throws SQLException {
324
+		ContainerStore containerHome = new ContainerStore(JdbcTestHelper.getInstance().getDataSource(), context);
325
+		Container container = Container.create(name, type, name, owner, this.domainUid, true);
326
+		container = containerHome.create(container);
327
+		Container dom = containerHome.get(domainUid);
328
+		UserSubscriptionStore userSubscriptionStore = new UserSubscriptionStore(SecurityContext.SYSTEM,
329
+				JdbcTestHelper.getInstance().getDataSource(), dom);
330
+		userSubscriptionStore.subscribe(context.getSubject(), container);
331
+	}
332
+
333
+	private ItemValue<User> defaultUser(ItemValue<Server> dataLocation, String uid, String login) {
334
+		User user = new User();
335
+		user.login = login;
336
+		Email em = new Email();
337
+		em.address = login + "@test.lan";
338
+		em.isDefault = true;
339
+		em.allAliases = false;
340
+		user.emails = Arrays.asList(em);
341
+		user.password = "password";
342
+		user.routing = Routing.internal;
343
+		user.dataLocation = dataLocation.uid;
344
+
345
+		VCard card = new VCard();
346
+		card.identification.name = Name.create("Doe", "John", null, null, null, null);
347
+		card.identification.formatedName = FormatedName.create(login);
348
+		user.contactInfos = card;
349
+		return ItemValue.create(uid, user);
350
+	}
351
+
352
+	@SuppressWarnings("deprecation")
353
+	private VEventMessage buildEvent(final String summary, final String description, final List<Attendee> attendees) {
354
+		final VEventMessage veventMessage = new VEventMessage();
355
+
356
+		final ItemValue<VEventSeries> event = defaultVEvent(summary, description);
357
+		event.value.main.attendees = attendees;
358
+
359
+		veventMessage.itemUid = event.uid;
360
+		veventMessage.vevent = event.value;
361
+		veventMessage.oldEvent = null;
362
+		veventMessage.securityContext = SecurityContext.SYSTEM;
363
+		veventMessage.sendNotifications = true;
364
+		try {
365
+			veventMessage.container = new ContainerStore(JdbcTestHelper.getInstance().getDataSource(),
366
+					SecurityContext.SYSTEM).get(ICalendarUids.defaultUserCalendar(user.login));
367
+			Assert.assertNotNull(veventMessage.container);
368
+			veventMessage.container.domainUid = this.domainUid;
369
+		} catch (SQLException e) {
370
+			e.printStackTrace();
371
+			Assert.fail(e.getMessage());
372
+		}
373
+
374
+		return veventMessage;
375
+	}
376
+
377
+	private ItemValue<VEventSeries> defaultVEvent(final String summary, final String description) {
378
+		final VEvent event = new VEvent();
379
+		final DateTimeZone tz = DateTimeZone.forID("Europe/Paris");
380
+
381
+		final long now = System.currentTimeMillis();
382
+		final long start = now + (1000 * 60 * 60);
383
+		DateTime temp = new DateTime(start, tz);
384
+		event.dtstart = BmDateTimeWrapper.create(temp, Precision.DateTime);
385
+		temp = new DateTime(start + (1000 * 60 * 60), tz);
386
+		event.dtend = BmDateTimeWrapper.create(temp, Precision.DateTime);
387
+		event.summary = summary;
388
+		event.location = "Toulouse";
389
+		event.description = description;
390
+		event.priority = 1;
391
+		event.organizer = new VEvent.Organizer("John Doe", this.user.defaultEmailAddress());
392
+		event.organizer.dir = "bm://" + this.domainUid + "/" + BaseDirEntry.Kind.USER.name() + "/" + this.user.login;
393
+		event.attendees = new ArrayList<>();
394
+		event.categories = new ArrayList<TagRef>(0);
395
+
396
+		event.rdate = new HashSet<BmDateTime>();
397
+		event.rdate.add(BmDateTimeWrapper.create(temp, Precision.Date));
398
+
399
+		final VEventSeries series = new VEventSeries();
400
+		series.main = event;
401
+
402
+		return ItemValue.create(UUID.randomUUID().toString(), series);
403
+	}
404
+
405
+	private void createResourceTypeWithTemplate(final String resourceTypeId, final String label,
406
+			final Map<String, String> propsLabels, String template) {
407
+		final ResourceTypeDescriptor resourceTypeDescriptor = new ResourceTypeDescriptor();
408
+		resourceTypeDescriptor.label = label;
409
+		if (propsLabels != null) {
410
+			resourceTypeDescriptor.properties = new ArrayList<>(propsLabels.size());
411
+			propsLabels.entrySet().forEach(entry -> {
412
+				final Property p = new Property();
413
+				p.id = entry.getKey();
414
+				p.label = "en::" + entry.getValue() + "\nfr::" + entry.getValue() + "Fr";
415
+				p.type = Property.Type.String;
416
+				resourceTypeDescriptor.properties.add(p);
417
+			});
418
+		}
419
+		resourceTypeDescriptor.templates.put("fr", "FR " + template);
420
+		resourceTypeDescriptor.templates.put("en", "EN " + template);
421
+
422
+		this.provider.instance(IResourceTypes.class, domainUid).create(resourceTypeId, resourceTypeDescriptor);
423
+
424
+	}
425
+
426
+	private void createResource(final String resourceId, final String resourceTypeId, final String label,
427
+			final Map<String, String> propsValues) {
428
+		final ResourceDescriptor resourceDescriptor = new ResourceDescriptor();
429
+		resourceDescriptor.typeIdentifier = resourceTypeId;
430
+		resourceDescriptor.label = label;
431
+		resourceDescriptor.description = "What a mighty description!";
432
+		resourceDescriptor.reservationMode = ResourceReservationMode.OWNER_MANAGED;
433
+		resourceDescriptor.dataLocation = this.dataLocation.uid;
434
+		resourceDescriptor.emails = Collections
435
+				.singletonList(Email.create(resourceId.toLowerCase() + "@test.lan", true));
436
+		if (propsValues != null) {
437
+			resourceDescriptor.properties = new ArrayList<>(propsValues.size());
438
+			propsValues.entrySet().forEach(entry -> {
439
+				final PropertyValue p = new PropertyValue();
440
+				p.propertyId = entry.getKey();
441
+				p.value = entry.getValue();
442
+				resourceDescriptor.properties.add(p);
443
+			});
444
+		}
445
+
446
+		this.provider.instance(IResources.class, domainUid).create(resourceId, resourceDescriptor);
447
+	}
448
+
449
+}
... ...
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals;
22 22
 import static org.junit.Assert.assertFalse;
23 23
 
24 24
 import java.util.ArrayList;
25
+import java.util.Arrays;
25 26
 import java.util.HashMap;
26 27
 import java.util.Map;
27 28
 
... ...
@@ -40,6 +41,8 @@ import com.google.common.collect.Lists;
40 41
 import com.google.common.util.concurrent.SettableFuture;
41 42
 
42 43
 import net.bluemind.calendar.api.ICalendarUids;
44
+import net.bluemind.backend.cyrus.CyrusAdmins;
45
+import net.bluemind.backend.cyrus.CyrusService;
43 46
 import net.bluemind.calendar.api.VEvent;
44 47
 import net.bluemind.calendar.api.VEventOccurrence;
45 48
 import net.bluemind.calendar.api.VEventSeries;
... ...
@@ -53,9 +56,12 @@ import net.bluemind.core.container.persistance.DataSourceRouter;
53 56
 import net.bluemind.core.context.SecurityContext;
54 57
 import net.bluemind.core.elasticsearch.ElasticsearchTestHelper;
55 58
 import net.bluemind.core.jdbc.JdbcTestHelper;
59
+import net.bluemind.core.rest.ServerSideServiceProvider;
56 60
 import net.bluemind.core.task.service.NullTaskMonitor;
57 61
 import net.bluemind.core.tests.BmTestContext;
58 62
 import net.bluemind.lib.vertx.VertxPlatform;
63
+import net.bluemind.pool.impl.BmConfIni;
64
+import net.bluemind.server.api.IServer;
59 65
 import net.bluemind.server.api.Server;
60 66
 import net.bluemind.tag.api.ITags;
61 67
 import net.bluemind.tag.api.Tag;
... ...
@@ -94,10 +100,18 @@ public class CalendarRepairSupportTests {
94 100
 		Server esServer = new Server();
95 101
 		esServer.ip = ElasticsearchTestHelper.getInstance().getHost();
96 102
 		esServer.tags = Lists.newArrayList("bm/es");
97
-		PopulateHelper.initGlobalVirt(esServer);
98 103
 
99
-		domainUid = "bm.lan";
100
-		PopulateHelper.createTestDomain(domainUid);
104
+		Server imapServer = new Server();
105
+		imapServer.ip = new BmConfIni().get("imap-role");
106
+		imapServer.tags = Lists.newArrayList("mail/imap");
107
+
108
+		PopulateHelper.initGlobalVirt(esServer, imapServer);
109
+
110
+		domainUid = "test.lan";
111
+		PopulateHelper.createTestDomain(domainUid, esServer, imapServer);
112
+
113
+		this.createCyrusPartition(imapServer, this.domainUid);
114
+
101 115
 		user1 = PopulateHelper.addUser("test1", domainUid);
102 116
 		user2 = PopulateHelper.addUser("test2", domainUid);
103 117
 
... ...
@@ -118,6 +132,16 @@ public class CalendarRepairSupportTests {
118 132
 		css.setSettings(settings);
119 133
 	}
120 134
 
135
+	private void createCyrusPartition(final Server imapServer, final String domainUid) {
136
+		final CyrusService cyrusService = new CyrusService(imapServer.ip);
137
+		cyrusService.createPartition(domainUid);
138
+		cyrusService.refreshPartitions(Arrays.asList(domainUid));
139
+		new CyrusAdmins(
140
+				ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IServer.class, "default"),
141
+				imapServer.ip).write();
142
+		cyrusService.reload();
143
+	}
144
+
121 145
 	@After
122 146
 	public void after() throws Exception {
123 147
 		JdbcTestHelper.getInstance().afterTest();
... ...
@@ -38,6 +38,8 @@ import com.google.common.util.concurrent.SettableFuture;
38 38
 import net.bluemind.addressbook.api.VCard;
39 39
 import net.bluemind.addressbook.api.VCard.Identification.Name;
40 40
 import net.bluemind.addressbook.domainbook.IDomainAddressBook;
41
+import net.bluemind.backend.cyrus.CyrusAdmins;
42
+import net.bluemind.backend.cyrus.CyrusService;
41 43
 import net.bluemind.calendar.api.CalendarLookupResponse;
42 44
 import net.bluemind.calendar.api.ICalendarAutocomplete;
43 45
 import net.bluemind.calendar.api.ICalendarUids;
... ...
@@ -54,15 +56,17 @@ import net.bluemind.core.context.SecurityContext;
54 56
 import net.bluemind.core.elasticsearch.ElasticsearchTestHelper;
55 57
 import net.bluemind.core.jdbc.JdbcTestHelper;
56 58
 import net.bluemind.core.rest.BmContext;
59
+import net.bluemind.core.rest.ServerSideServiceProvider;
57 60
 import net.bluemind.core.sessions.Sessions;
58 61
 import net.bluemind.core.tests.BmTestContext;
59
-import net.bluemind.externaluser.api.ExternalUser;
60 62
 import net.bluemind.group.api.Group;
61 63
 import net.bluemind.group.api.IGroup;
62 64
 import net.bluemind.group.api.Member;
63 65
 import net.bluemind.lib.vertx.VertxPlatform;
64 66
 import net.bluemind.mailbox.api.Mailbox.Routing;
67
+import net.bluemind.pool.impl.BmConfIni;
65 68
 import net.bluemind.role.api.BasicRoles;
69
+import net.bluemind.server.api.IServer;
66 70
 import net.bluemind.server.api.Server;
67 71
 import net.bluemind.tests.defaultdata.PopulateHelper;
68 72
 import net.bluemind.user.api.IUser;
... ...
@@ -70,11 +74,11 @@ import net.bluemind.user.api.User;
70 74
 import net.bluemind.user.persistance.UserSubscriptionStore;
71 75
 
72 76
 public class CalendarAutocompleteServiceTests {
77
+	private static final String DOMAIN = "test.lan";
73 78
 	private BmContext testContext;
74 79
 	protected SecurityContext defaultSecurityContext;
75 80
 	private ContainerStore containerStore;
76 81
 	private Server imapServer;
77
-	private AclStore aclStore;
78 82
 	private SecurityContext adminSecurityContext;
79 83
 
80 84
 	@Before
... ...
@@ -97,16 +101,23 @@ public class CalendarAutocompleteServiceTests {
97 101
 		esServer.ip = ElasticsearchTestHelper.getInstance().getHost();
98 102
 		esServer.tags = Lists.newArrayList("bm/es");
99 103
 
100
-		PopulateHelper.initGlobalVirt(esServer);
101
-		PopulateHelper.addDomain("bm.lan");
102
-		PopulateHelper.addUser("test", "bm.lan");
104
+		this.imapServer = new Server();
105
+		imapServer.ip = new BmConfIni().get("imap-role");
106
+		imapServer.tags = Lists.newArrayList("mail/imap");
107
+
108
+		PopulateHelper.initGlobalVirt(esServer, imapServer);
109
+		PopulateHelper.createTestDomain(DOMAIN, esServer, imapServer);
110
+
111
+		this.createCyrusPartition(imapServer, DOMAIN);
112
+
113
+		PopulateHelper.addUser("test", DOMAIN);
103 114
 		defaultSecurityContext = new SecurityContext("testUser", "test", Arrays.<String>asList(),
104
-				Arrays.<String>asList(), "bm.lan");
115
+				Arrays.<String>asList(), DOMAIN);
105 116
 
106 117
 		Sessions.get().put(defaultSecurityContext.getSessionId(), defaultSecurityContext);
107 118
 
108 119
 		adminSecurityContext = new SecurityContext("testAdmin", "testAdmin", Arrays.<String>asList(),
109
-				Arrays.<String>asList(BasicRoles.ROLE_ADMIN), "bm.lan");
120
+				Arrays.<String>asList(BasicRoles.ROLE_ADMIN), DOMAIN);
110 121
 
111 122
 		Sessions.get().put(adminSecurityContext.getSessionId(), adminSecurityContext);
112 123
 		testContext = new BmTestContext(SecurityContext.SYSTEM);
... ...
@@ -116,7 +127,7 @@ public class CalendarAutocompleteServiceTests {
116 127
 				defaultSecurityContext);
117 128
 
118 129
 		Container container = Container.create("addressbook_testUser", "addressbook", "Contacts",
119
-				defaultSecurityContext.getSubject(), "bm.lan", true);
130
+				defaultSecurityContext.getSubject(), DOMAIN, true);
120 131
 		container = containerStore.create(container);
121 132
 		assertNotNull(container);
122 133
 
... ...
@@ -125,16 +136,25 @@ public class CalendarAutocompleteServiceTests {
125 136
 				Arrays.asList(AccessControlEntry.create(defaultSecurityContext.getSubject(), Verb.All)));
126 137
 
127 138
 		UserSubscriptionStore userSubscriptionStore = new UserSubscriptionStore(SecurityContext.SYSTEM,
128
-				JdbcTestHelper.getInstance().getDataSource(), dirContainerStore.get("bm.lan"));
139
+				JdbcTestHelper.getInstance().getDataSource(), dirContainerStore.get(DOMAIN));
129 140
 
130 141
 		userSubscriptionStore.subscribe(defaultSecurityContext.getSubject(), container);
142
+	}
131 143
 
144
+	private void createCyrusPartition(final Server imapServer, final String domainUid) {
145
+		final CyrusService cyrusService = new CyrusService(imapServer.ip);
146
+		cyrusService.createPartition(domainUid);
147
+		cyrusService.refreshPartitions(Arrays.asList(domainUid));
148
+		new CyrusAdmins(
149
+				ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IServer.class, "default"),
150
+				imapServer.ip).write();
151
+		cyrusService.reload();
132 152
 	}
133 153
 
134 154
 	protected Container createTestContainer(String uid, String name, Verb verb, boolean isDefault) throws Exception {
135 155
 
136 156
 		Container container = Container.create(uid, ICalendarUids.TYPE, name, defaultSecurityContext.getSubject(),
137
-				"bm.lan", isDefault);
157
+				 DOMAIN, isDefault);
138 158
 		container = containerStore.create(container);
139 159
 		assertNotNull(container);
140 160
 
... ...
@@ -153,7 +173,7 @@ public class CalendarAutocompleteServiceTests {
153 173
 
154 174
 	protected void createTestUser(String uid, String firstname, String lastname, Verb verb)
155 175
 			throws SQLException, ServerFault {
156
-		IUser users = testContext.provider().instance(IUser.class, "bm.lan");
176
+		IUser users = testContext.provider().instance(IUser.class, DOMAIN);
157 177
 
158 178
 		String f = java.text.Normalizer.normalize(firstname, java.text.Normalizer.Form.NFD)
159 179
 				.replaceAll("\\p{InCombiningDiacriticalMarks}+", "");
... ...
@@ -174,8 +194,7 @@ public class CalendarAutocompleteServiceTests {
174 194
 	}
175 195
 
176 196
 	protected String createTestExternalUser(String name, String email) {
177
-		ExternalUser eu = new ExternalUser();
178
-		return PopulateHelper.addExternalUser("bm.lan", email, name);
197
+		return PopulateHelper.addExternalUser(DOMAIN, email, name);
179 198
 	}
180 199
 
181 200
 	protected void createTestGroup(String uid, String name, String... membersUid) throws SQLException, ServerFault {
... ...
@@ -189,11 +208,11 @@ public class CalendarAutocompleteServiceTests {
189 208
 
190 209
 	protected void createTestGroup(String uid, String name, boolean hidden, boolean hiddenMembers, Member... members)
191 210
 			throws SQLException, ServerFault {
192
-		IGroup groups = testContext.provider().instance(IGroup.class, "bm.lan");
211
+		IGroup groups = testContext.provider().instance(IGroup.class, DOMAIN);
193 212
 		Group g = new Group();
194 213
 		g.name = name;
195 214
 		// server imap uid
196
-		g.dataLocation = PopulateHelper.FAKE_CYRUS_IP;
215
+		g.dataLocation = this.imapServer.ip;
197 216
 		g.hidden = hidden;
198 217
 		g.hiddenMembers = hiddenMembers;
199 218
 		groups.create(uid, g);
... ...
@@ -205,7 +224,7 @@ public class CalendarAutocompleteServiceTests {
205 224
 		net.bluemind.user.api.User user = new User();
206 225
 		user.login = login;
207 226
 		Email em = new Email();
208
-		em.address = login + "@bm.lan";
227
+		em.address = login + "@" + DOMAIN;
209 228
 		em.isDefault = true;
210 229
 		em.allAliases = false;
211 230
 		user.emails = Arrays.asList(em);
... ...
@@ -329,7 +348,7 @@ public class CalendarAutocompleteServiceTests {
329 348
 
330 349
 		createTestGroup("g1", "David Gilmour all band", Member.user("u1"), Member.user("u2"), Member.user("u3"),
331 350
 				Member.group("g2"), Member.group("g3"), Member.group("g4"));
332
-		testContext.provider().instance(IDomainAddressBook.class, "bm.lan").sync();
351
+		testContext.provider().instance(IDomainAddressBook.class, DOMAIN).sync();
333 352
 
334 353
 		res = service.calendarLookup("david", Verb.Read);
335 354
 		assertEquals(3, res.size());
... ...
@@ -36,8 +36,13 @@ import org.vertx.java.core.Handler;
36 36
 import com.google.common.collect.Lists;
37 37
 import com.google.common.util.concurrent.SettableFuture;
38 38
 
39
+import net.bluemind.addressbook.api.VCard;
40
+import net.bluemind.addressbook.api.VCard.Identification.Name;
41
+import net.bluemind.backend.cyrus.CyrusAdmins;
42
+import net.bluemind.backend.cyrus.CyrusService;
39 43
 import net.bluemind.calendar.api.CalendarDescriptor;
40 44
 import net.bluemind.calendar.api.ICalendarsMgmt;
45
+import net.bluemind.core.api.Email;
41 46
 import net.bluemind.core.api.fault.ErrorCode;
42 47
 import net.bluemind.core.api.fault.ServerFault;
43 48
 import net.bluemind.core.container.persistance.ContainerStore;
... ...
@@ -51,8 +56,12 @@ import net.bluemind.core.tests.BmTestContext;
51 56
 import net.bluemind.directory.api.DirEntry;
52 57
 import net.bluemind.directory.api.IDirectory;
53 58
 import net.bluemind.lib.vertx.VertxPlatform;
59
+import net.bluemind.mailbox.api.Mailbox.Routing;
60
+import net.bluemind.pool.impl.BmConfIni;
61
+import net.bluemind.server.api.IServer;
54 62
 import net.bluemind.server.api.Server;
55 63
 import net.bluemind.tests.defaultdata.PopulateHelper;
64
+import net.bluemind.user.api.User;
56 65
 
57 66
 public class CalendarsMgmtTests {
58 67
 
... ...
@@ -72,14 +81,21 @@ public class CalendarsMgmtTests {
72 81
 		esServer.ip = ElasticsearchTestHelper.getInstance().getHost();
73 82
 		esServer.tags = Lists.newArrayList("bm/es");
74 83
 
75
-		PopulateHelper.initGlobalVirt(esServer);
84
+		Server imapServer = new Server();
85
+		imapServer.ip = new BmConfIni().get("imap-role");
86
+		imapServer.tags = Lists.newArrayList("mail/imap");
76 87
 
77
-		domainUid = "test" + System.currentTimeMillis() + ".lan";
88
+		PopulateHelper.initGlobalVirt(esServer, imapServer);
89
+
90
+		domainUid = "test.lan";
78 91
 
79 92
 		domainAdmin = BmTestContext.contextWithSession("testUser", "test", domainUid, SecurityContext.ROLE_ADMIN)
80 93
 				.getSecurityContext();
81 94
 
82
-		PopulateHelper.addDomain(domainUid);
95
+		PopulateHelper.createTestDomain(domainUid, esServer, imapServer);
96
+
97
+		this.createCyrusPartition(imapServer, domainUid);
98
+
83 99
 		PopulateHelper.domainAdmin(domainUid, domainAdmin.getSubject());
84 100
 		final SettableFuture<Void> future = SettableFuture.<Void>create();
85 101
 		Handler<AsyncResult<Void>> done = new Handler<AsyncResult<Void>>() {
... ...
@@ -103,6 +119,32 @@ public class CalendarsMgmtTests {
103 119
 		testContext = new BmTestContext(SecurityContext.SYSTEM);
104 120
 	}
105 121
 
122
+	private void createCyrusPartition(final Server imapServer, final String domainUid) {
123
+		final CyrusService cyrusService = new CyrusService(imapServer.ip);
124
+		cyrusService.createPartition(domainUid);
125
+		cyrusService.refreshPartitions(Arrays.asList(domainUid));
126
+		new CyrusAdmins(
127
+				ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IServer.class, "default"),
128
+				imapServer.ip).write();
129
+		cyrusService.reload();
130
+	}
131
+
132
+	private User defaultUser(String login) {
133
+		User user = new User();
134
+		user.login = login;
135
+		Email em = new Email();
136
+		em.address = login + "@" + this.domainUid;
137
+		em.isDefault = true;
138
+		em.allAliases = false;
139
+		user.emails = Arrays.asList(em);
140
+		user.password = "password";
141
+		user.routing = Routing.none;
142
+		VCard card = new VCard();
143
+		card.identification.name = Name.create(login, login, null, null, null, null);
144
+		user.contactInfos = card;
145
+		return user;
146
+	}
147
+
106 148
 	@Test
107 149
 	public void testCreate_Domain() throws ServerFault, SQLException {
108 150
 		String calUid = "testdomab" + System.currentTimeMillis();
... ...
@@ -33,10 +33,13 @@ import org.junit.Test;
33 33
 import org.vertx.java.core.AsyncResult;
34 34
 import org.vertx.java.core.Handler;
35 35
 
36
+import com.google.common.collect.Lists;
36 37
 import com.google.common.util.concurrent.SettableFuture;
37 38
 
38
-import net.bluemind.calendar.api.IFreebusyUids;
39
+import net.bluemind.backend.cyrus.CyrusAdmins;
40
+import net.bluemind.backend.cyrus.CyrusService;
39 41
 import net.bluemind.calendar.api.IFreebusyMgmt;
42
+import net.bluemind.calendar.api.IFreebusyUids;
40 43
 import net.bluemind.core.api.fault.ServerFault;
41 44
 import net.bluemind.core.container.model.Container;
42 45
 import net.bluemind.core.container.model.acl.AccessControlEntry;
... ...
@@ -48,11 +51,15 @@ import net.bluemind.core.jdbc.JdbcTestHelper;
48 51
 import net.bluemind.core.rest.ServerSideServiceProvider;
49 52
 import net.bluemind.core.sessions.Sessions;
50 53
 import net.bluemind.lib.vertx.VertxPlatform;
54
+import net.bluemind.pool.impl.BmConfIni;
55
+import net.bluemind.server.api.IServer;
56
+import net.bluemind.server.api.Server;
51 57
 import net.bluemind.tests.defaultdata.PopulateHelper;
52 58
 import net.bluemind.user.persistance.UserSubscriptionStore;
53 59
 
54 60
 public class FreebusyMgmtTests {
55 61
 
62
+	private static final String DOMAIN = "test.lan";
56 63
 	protected SecurityContext defaultSecurityContext;
57 64
 	protected SecurityContext anotherSecurityContext;
58 65
 	protected Container container;
... ...
@@ -60,7 +67,6 @@ public class FreebusyMgmtTests {
60 67
 	@Before
61 68
 	public void before() throws Exception {
62 69
 		JdbcTestHelper.getInstance().beforeTest();
63
-		
64 70
 
65 71
 		final SettableFuture<Void> future = SettableFuture.<Void>create();
66 72
 		Handler<AsyncResult<Void>> done = new Handler<AsyncResult<Void>>() {
... ...
@@ -73,11 +79,18 @@ public class FreebusyMgmtTests {
73 79
 		VertxPlatform.spawnVerticles(done);
74 80
 		future.get();
75 81
 
76
-		PopulateHelper.initGlobalVirt();
82
+		Server imapServer = new Server();
83
+		imapServer.ip = new BmConfIni().get("imap-role");
84
+		imapServer.tags = Lists.newArrayList("mail/imap");
85
+
86
+		PopulateHelper.initGlobalVirt(imapServer);
87
+
88
+		PopulateHelper.createTestDomain(DOMAIN, imapServer);
89
+
90
+		this.createCyrusPartition(imapServer, DOMAIN);
77 91
 
78
-		PopulateHelper.addDomain("bm.lan");
79 92
 		defaultSecurityContext = new SecurityContext("testUser", "test", Arrays.<String>asList(),
80
-				Arrays.<String>asList(), "bm.lan");
93
+				Arrays.<String>asList(), DOMAIN);
81 94
 
82 95
 		Sessions.get().put(defaultSecurityContext.getSessionId(), defaultSecurityContext);
83 96
 
... ...
@@ -87,7 +100,7 @@ public class FreebusyMgmtTests {
87 100
 		AclStore aclStore = new AclStore(JdbcTestHelper.getInstance().getDataSource());
88 101
 
89 102
 		container = Container.create(UUID.randomUUID().toString(), IFreebusyUids.TYPE, "fb container",
90
-				defaultSecurityContext.getSubject(), "bm.lan", true);
103
+				defaultSecurityContext.getSubject(), DOMAIN, true);
91 104
 		container = containerStore.create(container);
92 105
 		assertNotNull(container);
93 106
 
... ...
@@ -95,17 +108,27 @@ public class FreebusyMgmtTests {
95 108
 				Arrays.asList(AccessControlEntry.create(defaultSecurityContext.getSubject(), Verb.All)));
96 109
 
97 110
 		UserSubscriptionStore userSubscriptionStore = new UserSubscriptionStore(SecurityContext.SYSTEM,
98
-				JdbcTestHelper.getInstance().getDataSource(), containerStore.get("bm.lan"));
111
+				JdbcTestHelper.getInstance().getDataSource(), containerStore.get(DOMAIN));
99 112
 
100 113
 		userSubscriptionStore.subscribe(defaultSecurityContext.getSubject(), container);
101 114
 
102 115
 		anotherSecurityContext = new SecurityContext(UUID.randomUUID().toString(), "another", Arrays.<String>asList(),
103
-				Arrays.<String>asList(), "bm.lan");
116
+				Arrays.<String>asList(), "another.lan");
104 117
 
105 118
 		Sessions.get().put(anotherSecurityContext.getSessionId(), anotherSecurityContext);
106 119
 
107 120
 	}
108 121
 
122
+	private void createCyrusPartition(final Server imapServer, final String domainUid) {
123
+		final CyrusService cyrusService = new CyrusService(imapServer.ip);
124
+		cyrusService.createPartition(domainUid);
125
+		cyrusService.refreshPartitions(Arrays.asList(domainUid));
126
+		new CyrusAdmins(
127
+				ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IServer.class, "default"),
128
+				imapServer.ip).write();
129
+		cyrusService.reload();
130
+	}
131
+
109 132
 	@After
110 133
 	public void after() throws Exception {
111 134
 		JdbcTestHelper.getInstance().afterTest();
... ...
@@ -36,6 +36,8 @@ import com.google.common.util.concurrent.SettableFuture;
36 36
 
37 37
 import net.bluemind.addressbook.api.VCard;
38 38
 import net.bluemind.addressbook.api.VCard.Identification.Name;
39
+import net.bluemind.backend.cyrus.CyrusAdmins;
40
+import net.bluemind.backend.cyrus.CyrusService;
39 41
 import net.bluemind.calendar.api.VEvent;
40 42
 import net.bluemind.calendar.api.VEventSeries;
41 43
 import net.bluemind.calendar.service.internal.VEventSanitizer;
... ...
@@ -46,6 +48,7 @@ import net.bluemind.core.api.fault.ServerFault;
46 48
 import net.bluemind.core.context.SecurityContext;
47 49
 import net.bluemind.core.elasticsearch.ElasticsearchTestHelper;
48 50
 import net.bluemind.core.jdbc.JdbcTestHelper;
51
+import net.bluemind.core.rest.ServerSideServiceProvider;
49 52
 import net.bluemind.core.tests.BmTestContext;
50 53
 import net.bluemind.group.api.Group;
51 54
 import net.bluemind.group.api.IGroup;
... ...
@@ -55,6 +58,8 @@ import net.bluemind.icalendar.api.ICalendarElement.Organizer;
55 58
 import net.bluemind.icalendar.api.ICalendarElement.ParticipationStatus;
56 59
 import net.bluemind.lib.vertx.VertxPlatform;
57 60
 import net.bluemind.mailbox.api.Mailbox.Routing;
61
+import net.bluemind.pool.impl.BmConfIni;
62
+import net.bluemind.server.api.IServer;
58 63
 import net.bluemind.server.api.Server;
59 64
 import net.bluemind.tests.defaultdata.PopulateHelper;
60 65
 import net.bluemind.user.api.IUser;
... ...
@@ -63,11 +68,11 @@ import net.bluemind.user.api.User;
63 68
 public class VEventSanitizerTests {
64 69
 
65 70
 	private BmTestContext test1Context;
71
+	private String domainUid;
66 72
 
67 73
 	@Before
68 74
 	public void beforeBefore() throws Exception {
69 75
 		JdbcTestHelper.getInstance().beforeTest();
70
-		
71 76
 
72 77
 		final SettableFuture<Void> future = SettableFuture.<Void>create();
73 78
 		Handler<AsyncResult<Void>> done = new Handler<AsyncResult<Void>>() {
... ...
@@ -80,15 +85,21 @@ public class VEventSanitizerTests {
80 85
 		VertxPlatform.spawnVerticles(done);
81 86
 		future.get();
82 87
 
83
-		String domainUid = "bm.lan";
88
+		this.domainUid = "test.lan";
84 89
 
85 90
 		Server esServer = new Server();
86 91
 		esServer.ip = ElasticsearchTestHelper.getInstance().getHost();
87 92
 		esServer.tags = Lists.newArrayList("bm/es");
88 93
 
89
-		PopulateHelper.initGlobalVirt(esServer);
94
+		Server imapServer = new Server();
95
+		imapServer.ip = new BmConfIni().get("imap-role");
96
+		imapServer.tags = Lists.newArrayList("mail/imap");
90 97
 
91
-		PopulateHelper.createTestDomain(domainUid, esServer);
98
+		PopulateHelper.initGlobalVirt(esServer, imapServer);
99
+
100
+		PopulateHelper.createTestDomain(domainUid, esServer, imapServer);
101
+
102
+		this.createCyrusPartition(imapServer, this.domainUid);
92 103
 
93 104
 		BmTestContext systemContext = new BmTestContext(SecurityContext.SYSTEM);
94 105
 		IUser users = systemContext.provider().instance(IUser.class, domainUid);
... ...
@@ -96,13 +107,23 @@ public class VEventSanitizerTests {
96 107
 		users.create("test2", defaultUser("test2"));
97 108
 
98 109
 		test1Context = new BmTestContext(
99
-				new SecurityContext("test1", "test1", Arrays.<String>asList("g1"), Arrays.<String>asList(), "bm.lan"));
110
+				new SecurityContext("test1", "test1", Arrays.<String>asList("g1"), Arrays.<String>asList(), domainUid));
100 111
 
101 112
 		IGroup groups = systemContext.provider().instance(IGroup.class, domainUid);
102
-		groups.create("g1", defaultGroup("g1", PopulateHelper.FAKE_CYRUS_IP));
113
+		groups.create("g1", defaultGroup("g1", imapServer.ip));
103 114
 		groups.add("g1", Arrays.asList(Member.user("test1")));
104 115
 	}
105 116
 
117
+	private void createCyrusPartition(final Server imapServer, final String domainUid) {
118
+		final CyrusService cyrusService = new CyrusService(imapServer.ip);
119
+		cyrusService.createPartition(domainUid);
120
+		cyrusService.refreshPartitions(Arrays.asList(domainUid));
121
+		new CyrusAdmins(
122
+				ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IServer.class, "default"),
123
+				imapServer.ip).write();
124
+		cyrusService.reload();
125
+	}
126
+
106 127
 	private Group defaultGroup(String name, String cyrusIp) {
107 128
 		Group g = new Group();
108 129
 		g.dataLocation = cyrusIp;
... ...
@@ -114,7 +135,7 @@ public class VEventSanitizerTests {
114 135
 		User user = new User();
115 136
 		user.login = login;
116 137
 		Email em = new Email();
117
-		em.address = login + "@bm.lan";
138
+		em.address = login + "@" + this.domainUid;
118 139
 		em.isDefault = true;
119 140
 		em.allAliases = false;
120 141
 		user.emails = Arrays.asList(em);
... ...
@@ -129,7 +150,7 @@ public class VEventSanitizerTests {
129 150
 	@Test
130 151
 	public void testSanitizeSimple() throws ServerFault {
131 152
 
132
-		VEventSanitizer sanitizer = new VEventSanitizer(test1Context, "bm.lan");
153
+		VEventSanitizer sanitizer = new VEventSanitizer(test1Context, this.domainUid);
133 154
 
134 155
 		VEvent vevent = new VEvent();
135 156
 
... ...
@@ -149,7 +170,7 @@ public class VEventSanitizerTests {
149 170
 	@Test
150 171
 	public void testOrganizerWithoutEmailCannotCreateMeeting() throws ServerFault {
151 172
 
152
-		VEventSanitizer sanitizer = new VEventSanitizer(test1Context, "bm.lan");
173
+		VEventSanitizer sanitizer = new VEventSanitizer(test1Context, this.domainUid);
153 174
 
154 175
 		VEvent vevent = new VEvent();
155 176
 
... ...
@@ -171,7 +192,7 @@ public class VEventSanitizerTests {
171 192
 	@Test
172 193
 	public void testSanitizeOrganizer() throws ServerFault {
173 194
 
174
-		VEventSanitizer sanitizer = new VEventSanitizer(test1Context, "bm.lan");
195
+		VEventSanitizer sanitizer = new VEventSanitizer(test1Context, this.domainUid);
175 196
 
176 197
 		VEvent vevent = new VEvent();
177 198
 
... ...
@@ -182,13 +203,13 @@ public class VEventSanitizerTests {
182 203
 
183 204
 		vevent.organizer = new Organizer();
184 205
 		vevent.organizer.commonName = "check";
185
-		vevent.organizer.mailto = "test1@bm.lan";
206
+		vevent.organizer.mailto = "test1@" + this.domainUid;
186 207
 		vevent.attendees = Arrays.asList(simpleAttendee());
187 208
 		sanitizer.sanitize(vevent);
188 209
 
189
-		assertEquals("test1@bm.lan", vevent.organizer.mailto);
210
+		assertEquals("test1@" + this.domainUid, vevent.organizer.mailto);
190 211
 		assertEquals("test1 test1", vevent.organizer.commonName);
191
-		assertEquals("bm://bm.lan/users/test1", vevent.organizer.dir);
212
+		assertEquals("bm://" + this.domainUid + "/users/test1", vevent.organizer.dir);
192 213
 
193 214
 		vevent = new VEvent();
194 215
 
... ...
@@ -196,32 +217,32 @@ public class VEventSanitizerTests {
196 217
 		vevent.summary = "event " + System.currentTimeMillis();
197 218
 		vevent.organizer = new Organizer();
198 219
 		vevent.organizer.commonName = "check";
199
-		vevent.organizer.dir = "bm://bm.lan/users/test1";
220
+		vevent.organizer.dir = "bm://" + this.domainUid + "/users/test1";
200 221
 		vevent.attendees = Arrays.asList(simpleAttendee());
201 222
 		sanitizer.sanitize(vevent);
202 223
 
203 224
 		assertEquals("test1 test1", vevent.organizer.commonName);
204
-		assertEquals("test1@bm.lan", vevent.organizer.mailto);
225
+		assertEquals("test1@" + this.domainUid, vevent.organizer.mailto);
205 226
 		assertEquals(1, vevent.attendees.size());
206 227
 
207 228
 		// organizer not in system
208 229
 		vevent.organizer = new Organizer();
209 230
 		vevent.organizer.commonName = "check";
210
-		vevent.organizer.mailto = "fake@bm.lan";
231
+		vevent.organizer.mailto = "fake@" + this.domainUid;
211 232
 		sanitizer.sanitize(vevent);
212 233
 
213
-		assertEquals("fake@bm.lan", vevent.organizer.mailto);
234
+		assertEquals("fake@" + this.domainUid, vevent.organizer.mailto);
214 235
 		assertEquals("check", vevent.organizer.commonName);
215 236
 		assertNull(vevent.organizer.dir);
216 237
 
217 238
 		// organizer not in system
218 239
 		vevent.organizer = new Organizer();
219 240
 		vevent.organizer.commonName = "check";
220
-		vevent.organizer.mailto = "fake@bm.lan";
221
-		vevent.organizer.dir = "bm://bm.lan/users/fake";
241
+		vevent.organizer.mailto = "fake@" + this.domainUid;
242
+		vevent.organizer.dir = "bm://" + this.domainUid + "/users/fake";
222 243
 		sanitizer.sanitize(vevent);
223 244
 
224
-		assertEquals("fake@bm.lan", vevent.organizer.mailto);
245
+		assertEquals("fake@" + this.domainUid, vevent.organizer.mailto);
225 246
 		assertEquals("check", vevent.organizer.commonName);
226 247
 		assertNull(vevent.organizer.dir);
227 248
 
... ...
@@ -235,7 +256,7 @@ public class VEventSanitizerTests {
235 256
 
236 257
 		vevent.organizer = new Organizer();
237 258
 		vevent.organizer.commonName = "check";
238
-		vevent.organizer.mailto = "test1@bm.lan";
259
+		vevent.organizer.mailto = "test1@" + this.domainUid;
239 260
 		sanitizer.sanitize(vevent);
240 261
 		assertNull(vevent.organizer);
241 262
 	}
... ...
@@ -243,7 +264,7 @@ public class VEventSanitizerTests {
243 264
 	@Test
244 265
 	public void testSanitizeOrganizerInvalidMailto() throws ServerFault {
245 266
 
246
-		VEventSanitizer sanitizer = new VEventSanitizer(test1Context, "bm.lan");
267
+		VEventSanitizer sanitizer = new VEventSanitizer(test1Context, this.domainUid);
247 268
 
248 269
 		VEvent vevent = new VEvent();
249 270
 
... ...
@@ -264,7 +285,7 @@ public class VEventSanitizerTests {
264 285
 	private Attendee simpleAttendee() {
265 286
 		Attendee attendee = new VEvent.Attendee();
266 287
 		attendee.commonName = "check";
267
-		attendee.mailto = "test2@bm.lan";
288
+		attendee.mailto = "test2@" + this.domainUid;
268 289
 		attendee.partStatus = ParticipationStatus.NeedsAction;
269 290
 		return attendee;
270 291
 	}
... ...
@@ -272,7 +293,7 @@ public class VEventSanitizerTests {
272 293
 	@Test
273 294
 	public void testSanitizeAttendee() throws ServerFault {
274 295
 
275
-		VEventSanitizer sanitizer = new VEventSanitizer(test1Context, "bm.lan");
296
+		VEventSanitizer sanitizer = new VEventSanitizer(test1Context, this.domainUid);
276 297
 
277 298
 		VEvent vevent = new VEvent();
278 299
 
... ...
@@ -283,15 +304,15 @@ public class VEventSanitizerTests {
283 304
 
284 305
 		Attendee attendee = new VEvent.Attendee();
285 306
 		attendee.commonName = "check";
286
-		attendee.mailto = "test1@bm.lan";
307
+		attendee.mailto = "test1@" + this.domainUid;
287 308
 		vevent.attendees = Arrays.asList(attendee);
288 309
 		vevent.organizer = new Organizer("chef@bad-company.com");
289 310
 		sanitizer.sanitize(vevent);
290 311
 
291 312
 		assertEquals(1, vevent.attendees.size());
292
-		assertEquals("test1@bm.lan", vevent.attendees.get(0).mailto);
313
+		assertEquals("test1@" + this.domainUid, vevent.attendees.get(0).mailto);
293 314
 		assertEquals("test1 test1", vevent.attendees.get(0).commonName);
294
-		assertEquals("bm://bm.lan/users/test1", vevent.attendees.get(0).dir);
315
+		assertEquals("bm://" + this.domainUid + "/users/test1", vevent.attendees.get(0).dir);
295 316
 
296 317
 		vevent = new VEvent();
297 318
 
... ...
@@ -300,15 +321,15 @@ public class VEventSanitizerTests {
300 321
 		attendee = new VEvent.Attendee();
301 322
 		attendee.commonName = "check";
302 323
 		attendee.mailto = "fake@gmail.com";
303
-		attendee.dir = "bm://bm.lan/users/test1";
324
+		attendee.dir = "bm://" + this.domainUid + "/users/test1";
304 325
 		vevent.attendees = Arrays.asList(attendee);
305 326
 		vevent.organizer = new Organizer("chef@bad-company.com");
306 327
 		sanitizer.sanitize(vevent);
307 328
 
308 329
 		// BM-9907 returns user default email
309
-		assertEquals("test1@bm.lan", vevent.attendees.get(0).mailto);
330
+		assertEquals("test1@" + this.domainUid, vevent.attendees.get(0).mailto);
310 331
 		assertEquals("test1 test1", vevent.attendees.get(0).commonName);
311
-		assertEquals("bm://bm.lan/users/test1", vevent.attendees.get(0).dir);
332
+		assertEquals("bm://" + this.domainUid + "/users/test1", vevent.attendees.get(0).dir);
312 333
 
313 334
 		// attendee not in system
314 335
 		vevent = new VEvent();
... ...
@@ -317,14 +338,14 @@ public class VEventSanitizerTests {
317 338
 		vevent.summary = "event " + System.currentTimeMillis();
318 339
 		attendee = new VEvent.Attendee();
319 340
 		attendee.commonName = "check";
320
-		attendee.mailto = "fake@bm.lan";
341
+		attendee.mailto = "fake@" + this.domainUid;
321 342
 		attendee.dir = "fake://test";
322 343
 		vevent.attendees = Arrays.asList(attendee);
323 344
 		vevent.organizer = new Organizer("chef@bad-company.com");
324 345
 
325 346
 		sanitizer.sanitize(vevent);
326 347
 		// not modified
327
-		assertEquals("fake@bm.lan", vevent.attendees.get(0).mailto);
348
+		assertEquals("fake@" + this.domainUid, vevent.attendees.get(0).mailto);
328 349
 		assertEquals("check", vevent.attendees.get(0).commonName);
329 350
 		assertNull(vevent.attendees.get(0).dir);
330 351
 
... ...
@@ -335,13 +356,13 @@ public class VEventSanitizerTests {
335 356
 		vevent.summary = "event " + System.currentTimeMillis();
336 357
 		attendee = new VEvent.Attendee();
337 358
 		attendee.commonName = "check";
338
-		attendee.mailto = "fake@bm.lan";
339
-		attendee.dir = "bm://bm.lan/users/fake";
359
+		attendee.mailto = "fake@" + this.domainUid;
360
+		attendee.dir = "bm://" + this.domainUid + "/users/fake";
340 361
 		vevent.attendees = Arrays.asList(attendee);
341 362
 		vevent.organizer = new Organizer("chef@bad-company.com");
342 363
 		sanitizer.sanitize(vevent);
343 364
 
344
-		assertEquals("fake@bm.lan", vevent.attendees.get(0).mailto);
365
+		assertEquals("fake@" + this.domainUid, vevent.attendees.get(0).mailto);
345 366
 		assertEquals("check", vevent.attendees.get(0).commonName);
346 367
 		assertNull(vevent.attendees.get(0).dir);
347 368
 
... ...
@@ -362,7 +383,7 @@ public class VEventSanitizerTests {
362 383
 		vevent.attendees = Arrays.asList(attendee);
363 384
 		vevent.organizer = new Organizer("chef@bad-company.com");
364 385
 
365
-		new VEventSanitizer(test1Context, "bm.lan").sanitize(vevent);
386
+		new VEventSanitizer(test1Context, this.domainUid).sanitize(vevent);
366 387
 		assertEquals("fake_/email.com", attendee.commonName);
367 388
 		assertNull(attendee.mailto);
368 389
 	}
... ...
@@ -370,7 +391,7 @@ public class VEventSanitizerTests {
370 391
 	@Test
371 392
 	public void testSanitizeExDate() throws ServerFault {
372 393
 
373
-		VEventSanitizer sanitizer = new VEventSanitizer(test1Context, "bm.lan");
394
+		VEventSanitizer sanitizer = new VEventSanitizer(test1Context, this.domainUid);
374 395
 
375 396
 		VEvent vevent = new VEvent();
376 397
 
... ...
@@ -387,16 +408,16 @@ public class VEventSanitizerTests {
387 408
 
388 409
 	@Test
389 410
 	public void testSanitizeOrganizerIsTheOnlyAttendee() {
390
-		VEventSanitizer sanitizer = new VEventSanitizer(test1Context, "bm.lan");
411
+		VEventSanitizer sanitizer = new VEventSanitizer(test1Context, this.domainUid);
391 412
 
392 413
 		VEvent vevent = new VEvent();
393 414
 		vevent.dtstart = BmDateTimeWrapper.create(new DateTime(2015, 05, 01, 0, 0, 0), Precision.Date);
394 415
 		vevent.summary = "event " + System.currentTimeMillis();
395 416
 		Attendee attendee = new VEvent.Attendee();
396 417
 		attendee.commonName = "test1";
397
-		attendee.mailto = "test1@bm.lan";
418
+		attendee.mailto = "test1@" + this.domainUid;
398 419
 		vevent.attendees = Arrays.asList(attendee);
399
-		vevent.organizer = new Organizer("test1@bm.lan");
420
+		vevent.organizer = new Organizer("test1@" + this.domainUid);
400 421
 
401 422
 		VEventSeries series = VEventSeries.create(vevent);
402 423
 
... ...
@@ -48,7 +48,8 @@ Require-Bundle: net.bluemind.calendar.api;bundle-version="1.0.0",
48 48
  net.bluemind.user.persistance,
49 49
  net.bluemind.core.container.sharding,
50 50
  net.bluemind.config,
51
- net.bluemind.server.api
51
+ net.bluemind.server.api,
52
+ net.bluemind.resource.api;bundle-version="4.1.0" 
52 53
 Export-Package: net.bluemind.calendar.service,
53 54
  net.bluemind.calendar.service.internal
54 55
 Bundle-Activator: net.bluemind.calendar.service.CalendarActivator
... ...
@@ -156,5 +156,10 @@
156 156
             factory="net.bluemind.calendar.service.internal.repair.CalendarViewRepairSupport$Factory">
157 157
       </repairSupport>
158 158
    </extension>
159
-
159
+   <extension
160
+         point="net.bluemind.core.sanitizerfactory">
161
+      <sanitizerfactory
162
+            implementation="net.bluemind.calendar.service.internal.VEventSeriesSanitizer$Factory">
163
+      </sanitizerfactory>
164
+   </extension>
160 165
 </plugin>
... ...
@@ -43,7 +43,6 @@ public class CalendarEventProducer {
43 43
 		this.loginAtDomain = securityContext.getSubject();
44 44
 		this.eventBus = ev;
45 45
 		this.securityContext = securityContext;
46
-
47 46
 	}
48 47
 
49 48
 	public void changed() {
... ...
@@ -59,35 +58,22 @@ public class CalendarEventProducer {
59 58
 	}
60 59
 
61 60
 	public void veventCreated(VEventSeries event, String uid, boolean sendNotifications) {
62
-		VEventMessage msg = getVEventMessage(event, uid, sendNotifications);
61
+		VEventMessage msg = new VEventMessage(event, uid, sendNotifications, securityContext, auditor.eventId(),
62
+				container);
63 63
 		eventBus.publish(CalendarHookAddress.EVENT_CREATED, new LocalJsonObject<>(msg));
64 64
 	}
65 65
 
66 66
 	public void veventUpdated(VEventSeries old, VEventSeries vevent, String uid, boolean sendNotifications) {
67
-		VEventMessage msg = getVEventMessage(vevent, uid, sendNotifications);
67
+		VEventMessage msg = new VEventMessage(vevent, uid, sendNotifications, securityContext, auditor.eventId(),
68
+				container);
68 69
 		msg.oldEvent = old;
69 70
 		eventBus.publish(CalendarHookAddress.EVENT_UPDATED, new LocalJsonObject<>(msg));
70 71
 	}
71 72
 
72 73
 	public void veventDeleted(VEventSeries vevent, String uid, boolean sendNotifications) {
73