Browse code

BM-14963 Chore: LDAP export tests no more a plugin fragment

Anthony Prades authored on 20/06/2019 15:45:44
Showing 42 changed files
... ...
@@ -4,14 +4,19 @@ Bundle-Name: net.bluemind.system.ldap.export.tests
4 4
 Bundle-SymbolicName: net.bluemind.system.ldap.export.tests
5 5
 Bundle-Version: 4.1.0.qualifier
6 6
 Bundle-Vendor: bluemind.net
7
-Fragment-Host: net.bluemind.system.ldap.export
8 7
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
9 8
 Require-Bundle: net.bluemind.pool,
10 9
  org.junit,
11
- net.bluemind.node.client;bundle-version="4.1.0",
10
+ net.bluemind.node.client,
12 11
  net.bluemind.core.jdbc.testshelper,
13 12
  net.bluemind.tests.defaultdata,
14 13
  net.bluemind.core.tests.testshelper,
15 14
  net.bluemind.core.container.persistance,
16 15
  net.bluemind.role.api,
17
- net.bluemind.externaluser.service;bundle-version="4.1.0"
16
+ net.bluemind.externaluser.service,
17
+ net.bluemind.system.ldap.export,
18
+ net.bluemind.lib.ldap,
19
+ net.bluemind.group.api,
20
+ net.bluemind.config,
21
+ net.bluemind.node.api,
22
+ net.bluemind.server.hook
... ...
@@ -1,4 +1,5 @@
1 1
 source.. = src/
2 2
 output.. = bin/
3 3
 bin.includes = META-INF/,\
4
-               .
4
+               .,\
5
+               plugin.xml
5 6
new file mode 100644
... ...
@@ -0,0 +1,1187 @@
1
+/* BEGIN LICENSE
2
+  * Copyright © Blue Mind SAS, 2012-2017
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.system.ldap.export;
19
+
20
+import static org.junit.Assert.assertEquals;
21
+import static org.junit.Assert.assertFalse;
22
+import static org.junit.Assert.assertNotEquals;
23
+import static org.junit.Assert.assertNotNull;
24
+import static org.junit.Assert.assertNull;
25
+import static org.junit.Assert.assertTrue;
26
+import static org.junit.Assert.fail;
27
+
28
+import java.sql.SQLException;
29
+import java.util.ArrayList;
30
+import java.util.Arrays;
31
+import java.util.List;
32
+import java.util.UUID;
33
+
34
+import org.apache.directory.api.ldap.model.cursor.CursorException;
35
+import org.apache.directory.api.ldap.model.entry.Attribute;
36
+import org.apache.directory.api.ldap.model.entry.Entry;
37
+import org.apache.directory.api.ldap.model.exception.LdapException;
38
+import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
39
+import org.apache.directory.ldap.client.api.LdapConnection;
40
+import org.junit.Before;
41
+import org.junit.Test;
42
+import org.vertx.java.core.AsyncResult;
43
+import org.vertx.java.core.Handler;
44
+
45
+import com.google.common.util.concurrent.SettableFuture;
46
+
47
+import net.bluemind.config.InstallationId;
48
+import net.bluemind.config.Token;
49
+import net.bluemind.core.api.fault.ErrorCode;
50
+import net.bluemind.core.api.fault.ServerFault;
51
+import net.bluemind.core.container.model.ContainerChangeset;
52
+import net.bluemind.core.container.model.ItemValue;
53
+import net.bluemind.core.context.SecurityContext;
54
+import net.bluemind.core.jdbc.JdbcTestHelper;
55
+import net.bluemind.core.rest.ServerSideServiceProvider;
56
+import net.bluemind.core.task.api.ITask;
57
+import net.bluemind.core.task.api.TaskRef;
58
+import net.bluemind.core.task.api.TaskStatus.State;
59
+import net.bluemind.core.tests.BmTestContext;
60
+import net.bluemind.core.utils.UIDGenerator;
61
+import net.bluemind.directory.api.DirEntry;
62
+import net.bluemind.directory.api.IDirectory;
63
+import net.bluemind.domain.api.Domain;
64
+import net.bluemind.group.api.Group;
65
+import net.bluemind.group.api.IGroup;
66
+import net.bluemind.group.api.Member;
67
+import net.bluemind.lib.vertx.VertxPlatform;
68
+import net.bluemind.mailbox.api.Mailbox;
69
+import net.bluemind.node.api.INodeClient;
70
+import net.bluemind.node.api.NCUtils;
71
+import net.bluemind.node.api.NodeActivator;
72
+import net.bluemind.pool.impl.BmConfIni;
73
+import net.bluemind.server.api.IServer;
74
+import net.bluemind.server.api.Server;
75
+import net.bluemind.system.ldap.export.LdapExportService;
76
+import net.bluemind.system.ldap.export.LdapHelper;
77
+import net.bluemind.system.ldap.export.objects.DomainDirectoryGroup;
78
+import net.bluemind.system.ldap.export.objects.DomainDirectoryUser;
79
+import net.bluemind.system.ldap.export.verticle.LdapExportVerticle;
80
+import net.bluemind.tests.defaultdata.PopulateHelper;
81
+import net.bluemind.user.api.IUser;
82
+import net.bluemind.user.api.User;
83
+
84
+public class LdapExportServiceTests {
85
+	private static final String LDAPTAG = "directory/bm-master";
86
+
87
+	private ItemValue<Domain> domain;
88
+	private ItemValue<Server> ldapRoleServer;
89
+
90
+	@Before
91
+	public void before() throws Exception {
92
+		LdapExportVerticle.suspended = true;
93
+
94
+		JdbcTestHelper.getInstance().beforeTest();
95
+
96
+		PopulateHelper.initGlobalVirt();
97
+
98
+		String domainUid = "test" + System.currentTimeMillis() + ".lan";
99
+
100
+		SecurityContext domainAdmin = BmTestContext
101
+				.contextWithSession("testUser", "test", domainUid, SecurityContext.ROLE_ADMIN).getSecurityContext();
102
+
103
+		domain = PopulateHelper.createTestDomain(domainUid);
104
+		PopulateHelper.domainAdmin(domainUid, domainAdmin.getSubject());
105
+
106
+		final SettableFuture<Void> future = SettableFuture.<Void>create();
107
+		Handler<AsyncResult<Void>> done = new Handler<AsyncResult<Void>>() {
108
+
109
+			@Override
110
+			public void handle(AsyncResult<Void> event) {
111
+				future.set(null);
112
+			}
113
+		};
114
+		VertxPlatform.spawnVerticles(done);
115
+		future.get();
116
+
117
+		initAndAssignLdapExportServer();
118
+	}
119
+
120
+	@Test
121
+	public void testExportService_builder() throws Exception {
122
+		try {
123
+			LdapExportService.build(null);
124
+			fail("Test must thrown an exception");
125
+		} catch (ServerFault sf) {
126
+			assertEquals(ErrorCode.INVALID_PARAMETER, sf.getCode());
127
+		}
128
+
129
+		try {
130
+			LdapExportService.build("");
131
+			fail("Test must thrown an exception");
132
+		} catch (ServerFault sf) {
133
+			assertEquals(ErrorCode.INVALID_PARAMETER, sf.getCode());
134
+		}
135
+
136
+		try {
137
+			LdapExportService.build("invalidUid");
138
+			fail("Test must thrown an exception");
139
+		} catch (ServerFault sf) {
140
+			assertEquals(ErrorCode.UNKNOWN, sf.getCode());
141
+		}
142
+
143
+		assertNotNull(LdapExportService.build(domain.uid));
144
+
145
+		String noLdapExportDomainUid = "test" + System.currentTimeMillis() + ".lan";
146
+		PopulateHelper.createTestDomain(noLdapExportDomainUid);
147
+		assertNull(LdapExportService.build(noLdapExportDomainUid));
148
+	}
149
+
150
+	@Test
151
+	public void testExport_syncAll() throws Exception {
152
+		checkBmVersion();
153
+
154
+		String userUid = PopulateHelper.addUser(UUID.randomUUID().toString(), domain.value.name);
155
+		String groupUid = addGroup();
156
+
157
+		LdapExportService les = LdapExportService.build(domain.uid);
158
+		les.sync();
159
+
160
+		Results results = checkSync();
161
+
162
+		assertNotEquals(0, results.userExported.size());
163
+		assertTrue(results.userExported.contains(userUid));
164
+
165
+		assertNotEquals(0, results.userNotExported.size());
166
+
167
+		assertNotEquals(0, results.groupExported.size());
168
+		assertTrue(results.groupExported.contains(groupUid));
169
+
170
+		assertNotEquals(0, results.groupNotExported.size());
171
+	}
172
+
173
+	@Test
174
+	public void testExportUser_hiddenNotExported() throws Exception {
175
+		checkBmVersion();
176
+
177
+		User user = PopulateHelper.getUser("test-" + System.nanoTime(), domain.value.name, Mailbox.Routing.none);
178
+		user.hidden = true;
179
+		PopulateHelper.addUser(domain.value.name, user);
180
+
181
+		LdapExportService les = LdapExportService.build(domain.uid);
182
+		les.sync();
183
+
184
+		checkBmVersion();
185
+
186
+		LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);
187
+		Entry ldapEntry = ldapCon.lookup("uid=" + user.login + ",ou=users,dc=" + domain.value.name + ",dc=local");
188
+		assertNull(ldapEntry);
189
+	}
190
+
191
+	@Test
192
+	public void testExportGroup_hiddenNotExported() throws Exception {
193
+		checkBmVersion();
194
+
195
+		Group group = getGroup();
196
+		group.hidden = true;
197
+		addGroup(group);
198
+
199
+		LdapExportService les = LdapExportService.build(domain.uid);
200
+		les.sync();
201
+
202
+		checkBmVersion();
203
+
204
+		LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);
205
+		Entry ldapEntry = ldapCon.lookup("cn=" + group.name + ",ou=groups,dc=" + domain.value.name + ",dc=local");
206
+		assertNull(ldapEntry);
207
+	}
208
+
209
+	@Test
210
+	public void testExportGroup_removeFromLdapIfDeleted() throws Exception {
211
+		String groupUid = addGroup();
212
+
213
+		LdapExportService.build(domain.uid).sync();
214
+
215
+		IGroup groupService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IGroup.class,
216
+				domain.value.name);
217
+		ItemValue<Group> group = groupService.getComplete(groupUid);
218
+
219
+		LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);
220
+		Entry ldapGroup = ldapCon.lookup("cn=" + group.value.name + ",ou=groups,dc=" + domain.value.name + ",dc=local");
221
+		assertNotNull(ldapGroup);
222
+
223
+		TaskRef tr = groupService.delete(group.uid);
224
+		waitFor(tr);
225
+
226
+		LdapExportService.build(domain.uid).sync();
227
+
228
+		ldapGroup = ldapCon.lookup("cn=" + group.value.name + ",ou=groups,dc=" + domain.value.name + ",dc=local");
229
+		assertNull(ldapGroup);
230
+	}
231
+
232
+	@Test
233
+	public void testExportUser_systemNotExported() throws Exception {
234
+		checkBmVersion();
235
+
236
+		User user = PopulateHelper.getUser("test-" + System.nanoTime(), domain.value.name, Mailbox.Routing.none);
237
+		user.system = true;
238
+		PopulateHelper.addUser(domain.value.name, user);
239
+
240
+		LdapExportService les = LdapExportService.build(domain.uid);
241
+		les.sync();
242
+
243
+		checkBmVersion();
244
+
245
+		LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);
246
+		Entry ldapEntry = ldapCon.lookup("uid=" + user.login + ",ou=users,dc=" + domain.value.name + ",dc=local");
247
+		assertNull(ldapEntry);
248
+	}
249
+
250
+	@Test
251
+	public void testExport_syncAllWithNoDomainRoot() throws Exception {
252
+		LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);
253
+		LdapHelper.deleteTree(ldapCon, "dc=" + domain.value.name + ",dc=local");
254
+
255
+		LdapExportService les = LdapExportService.build(domain.uid);
256
+		les.sync();
257
+
258
+		checkSync();
259
+	}
260
+
261
+	@Test
262
+	public void testExportUser_createIfAbsentOnUpdate() throws Exception {
263
+		String userUid = PopulateHelper.addUser("test" + System.nanoTime(), domain.value.name, Mailbox.Routing.none);
264
+
265
+		IUser userService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IUser.class,
266
+				domain.value.name);
267
+		ItemValue<User> user = userService.getComplete(userUid);
268
+
269
+		LdapExportService les = LdapExportService.build(domain.uid);
270
+		les.sync();
271
+
272
+		LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);
273
+		LdapHelper.deleteTree(ldapCon, "uid=" + user.value.login + ",ou=users,dc=" + domain.value.name + ",dc=local");
274
+
275
+		Entry ldapUser = ldapCon.lookup("uid=" + user.value.login + ",ou=users,dc=" + domain.value.name + ",dc=local");
276
+		assertNull(ldapUser);
277
+
278
+		userService.update(user.uid, user.value);
279
+
280
+		les = LdapExportService.build(domain.uid);
281
+		les.sync();
282
+
283
+		ldapUser = ldapCon.lookup("uid=" + user.value.login + ",ou=users,dc=" + domain.value.name + ",dc=local");
284
+		assertNotNull(ldapUser);
285
+	}
286
+
287
+	@Test
288
+	public void testExportGroup_createIfAbsentOnUpdate() throws Exception {
289
+		String groupUid = addGroup();
290
+
291
+		IGroup groupService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IGroup.class,
292
+				domain.value.name);
293
+		ItemValue<Group> group = groupService.getComplete(groupUid);
294
+
295
+		LdapExportService.build(domain.uid).sync();
296
+
297
+		LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);
298
+		LdapHelper.deleteTree(ldapCon, "cn=" + group.value.name + ",ou=groups,dc=" + domain.value.name + ",dc=local");
299
+
300
+		Entry ldapGroup = ldapCon.lookup("cn=" + group.value.name + ",ou=groups,dc=" + domain.value.name + ",dc=local");
301
+		assertNull(ldapGroup);
302
+
303
+		groupService.update(group.uid, group.value);
304
+
305
+		LdapExportService.build(domain.uid).sync();
306
+
307
+		ldapGroup = ldapCon.lookup("cn=" + group.value.name + ",ou=groups,dc=" + domain.value.name + ",dc=local");
308
+		assertNotNull(ldapGroup);
309
+	}
310
+
311
+	@Test
312
+	public void testExportUser_resetLdapEntryIfMoreThanOneEntryFound() throws Exception {
313
+		String userUid = PopulateHelper.addUser("test" + System.nanoTime(), domain.value.name, Mailbox.Routing.none);
314
+
315
+		IUser userService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IUser.class,
316
+				domain.value.name);
317
+		ItemValue<User> user = userService.getComplete(userUid);
318
+
319
+		LdapExportService.build(domain.uid).sync();
320
+
321
+		try (LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);) {
322
+			Entry ldapUser = ldapCon
323
+					.lookup("uid=" + user.value.login + ",ou=users,dc=" + domain.value.name + ",dc=local");
324
+			ldapUser.removeAttributes("uid");
325
+			String newLogin = user.value.login + "-2";
326
+			ldapUser.add("uid", newLogin);
327
+			ldapUser.setDn("uid=" + newLogin + ",ou=users,dc=" + domain.value.name + ",dc=local");
328
+			ldapCon.add(ldapUser);
329
+		}
330
+
331
+		userService.update(user.uid, user.value);
332
+
333
+		LdapExportService.build(domain.uid).sync();
334
+
335
+		LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);
336
+
337
+		List<Entry> entries = LdapHelper.getLdapEntryFromUid(ldapCon, domain, userUid);
338
+		assertEquals(1, entries.size());
339
+		assertEquals("uid=" + user.value.login + ",ou=users,dc=" + domain.value.name + ",dc=local",
340
+				entries.get(0).getDn().getName());
341
+		assertEquals(userUid, entries.get(0).get("bmUid").getString());
342
+	}
343
+
344
+	@Test
345
+	public void testExportGroup_resetLdapEntryIfMoreThanOneEntryFound() throws Exception {
346
+		String groupUid = addGroup();
347
+
348
+		IGroup groupService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IGroup.class,
349
+				domain.value.name);
350
+		ItemValue<Group> group = groupService.getComplete(groupUid);
351
+
352
+		LdapExportService.build(domain.uid).sync();
353
+
354
+		try (LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);) {
355
+			Entry ldapGroup = ldapCon
356
+					.lookup("cn=" + group.value.name + ",ou=groups,dc=" + domain.value.name + ",dc=local");
357
+			ldapGroup.removeAttributes("uid");
358
+			String newName = group.value.name + "-2";
359
+			ldapGroup.add("cn", newName);
360
+			ldapGroup.setDn("cn=" + newName + ",ou=groups,dc=" + domain.value.name + ",dc=local");
361
+			ldapCon.add(ldapGroup);
362
+		}
363
+
364
+		groupService.update(group.uid, group.value);
365
+
366
+		LdapExportService.build(domain.uid).sync();
367
+
368
+		LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);
369
+
370
+		List<Entry> entries = LdapHelper.getLdapEntryFromUid(ldapCon, domain, groupUid);
371
+		assertEquals(1, entries.size());
372
+		assertEquals("cn=" + group.value.name + ",ou=groups,dc=" + domain.value.name + ",dc=local",
373
+				entries.get(0).getDn().getName());
374
+		assertEquals(groupUid, entries.get(0).get("bmUid").getString());
375
+	}
376
+
377
+	@Test
378
+	public void testExportUser_removeFromLdapIfUpdatedToHidden() throws Exception {
379
+		String userUid = PopulateHelper.addUser("test" + System.nanoTime(), domain.value.name, Mailbox.Routing.none);
380
+
381
+		LdapExportService les = LdapExportService.build(domain.uid);
382
+		les.sync();
383
+
384
+		IUser userService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IUser.class,
385
+				domain.value.name);
386
+		ItemValue<User> user = userService.getComplete(userUid);
387
+
388
+		LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);
389
+		Entry ldapUser = ldapCon.lookup("uid=" + user.value.login + ",ou=users,dc=" + domain.value.name + ",dc=local");
390
+		assertNotNull(ldapUser);
391
+
392
+		user.value.hidden = true;
393
+		userService.update(user.uid, user.value);
394
+
395
+		les.sync();
396
+
397
+		ldapUser = ldapCon.lookup("uid=" + user.value.login + ",ou=users,dc=" + domain.value.name + ",dc=local");
398
+		assertNull(ldapUser);
399
+	}
400
+
401
+	@Test
402
+	public void testExportGroup_removeFromLdapIfUpdatedToHidden() throws Exception {
403
+		String groupUid = addGroup();
404
+
405
+		LdapExportService.build(domain.uid).sync();
406
+
407
+		IGroup groupService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IGroup.class,
408
+				domain.value.name);
409
+		ItemValue<Group> group = groupService.getComplete(groupUid);
410
+
411
+		LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);
412
+		Entry ldapGroup = ldapCon.lookup("cn=" + group.value.name + ",ou=groups,dc=" + domain.value.name + ",dc=local");
413
+		assertNotNull(ldapGroup);
414
+
415
+		group.value.hidden = true;
416
+		groupService.update(group.uid, group.value);
417
+
418
+		LdapExportService.build(domain.uid).sync();
419
+
420
+		ldapGroup = ldapCon.lookup("cn=" + group.value.name + ",ou=groups,dc=" + domain.value.name + ",dc=local");
421
+		assertNull(ldapGroup);
422
+	}
423
+
424
+	@Test
425
+	public void testExportUser_removeFromLdapIfUpdatedToSystem() throws Exception {
426
+		String userUid = PopulateHelper.addUser("test" + System.nanoTime(), domain.value.name, Mailbox.Routing.none);
427
+
428
+		LdapExportService les = LdapExportService.build(domain.uid);
429
+		les.sync();
430
+
431
+		IUser userService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IUser.class,
432
+				domain.value.name);
433
+		ItemValue<User> user = userService.getComplete(userUid);
434
+
435
+		LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);
436
+		Entry ldapUser = ldapCon.lookup("uid=" + user.value.login + ",ou=users,dc=" + domain.value.name + ",dc=local");
437
+		assertNotNull(ldapUser);
438
+
439
+		user.value.system = true;
440
+		userService.update(user.uid, user.value);
441
+
442
+		les.sync();
443
+
444
+		ldapUser = ldapCon.lookup("uid=" + user.value.login + ",ou=users,dc=" + domain.value.name + ",dc=local");
445
+		assertNull(ldapUser);
446
+	}
447
+
448
+	@Test
449
+	public void testExportUser_removeFromLdapIfDeleted() throws Exception {
450
+		String userUid = PopulateHelper.addUser("test" + System.nanoTime(), domain.value.name, Mailbox.Routing.none);
451
+
452
+		LdapExportService les = LdapExportService.build(domain.uid);
453
+		les.sync();
454
+
455
+		IUser userService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IUser.class,
456
+				domain.value.name);
457
+		ItemValue<User> user = userService.getComplete(userUid);
458
+
459
+		LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);
460
+		Entry ldapUser = ldapCon.lookup("uid=" + user.value.login + ",ou=users,dc=" + domain.value.name + ",dc=local");
461
+		assertNotNull(ldapUser);
462
+
463
+		TaskRef tr = userService.delete(user.uid);
464
+		waitFor(tr);
465
+
466
+		les.sync();
467
+
468
+		ldapUser = ldapCon.lookup("uid=" + user.value.login + ",ou=users,dc=" + domain.value.name + ",dc=local");
469
+		assertNull(ldapUser);
470
+	}
471
+
472
+	@Test
473
+	public void testExportUser_updated() throws Exception {
474
+		String userUid = PopulateHelper.addUser("test" + System.nanoTime(), domain.value.name, Mailbox.Routing.none);
475
+
476
+		IUser userService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IUser.class,
477
+				domain.value.name);
478
+		ItemValue<User> user = userService.getComplete(userUid);
479
+		user.value.contactInfos.explanatory.note = "description";
480
+		userService.update(user.uid, user.value);
481
+
482
+		LdapExportService les = LdapExportService.build(domain.uid);
483
+		les.sync();
484
+
485
+		user.value.contactInfos.explanatory.note = "updated description";
486
+		userService.update(user.uid, user.value);
487
+
488
+		les.sync();
489
+
490
+		LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);
491
+		Entry ldapUser = ldapCon.lookup("uid=" + user.value.login + ",ou=users,dc=" + domain.value.name + ",dc=local");
492
+		assertNotNull(ldapUser);
493
+		assertEquals(userUid, ldapUser.get("bmUid").getString());
494
+		assertEquals("updated description", ldapUser.get("description").getString());
495
+	}
496
+
497
+	@Test
498
+	public void testExportGroup_updated() throws Exception {
499
+		String groupUid = addGroup();
500
+
501
+		IGroup groupService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IGroup.class,
502
+				domain.value.name);
503
+		ItemValue<Group> group = groupService.getComplete(groupUid);
504
+		group.value.description = "description";
505
+		groupService.update(group.uid, group.value);
506
+
507
+		LdapExportService.build(domain.uid).sync();
508
+
509
+		group.value.description = "updated description";
510
+		groupService.update(group.uid, group.value);
511
+
512
+		LdapExportService.build(domain.uid).sync();
513
+
514
+		LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);
515
+		Entry ldapGroup = ldapCon.lookup("cn=" + group.value.name + ",ou=groups,dc=" + domain.value.name + ",dc=local");
516
+		assertNotNull(ldapGroup);
517
+		assertEquals(groupUid, ldapGroup.get("bmUid").getString());
518
+		assertEquals("updated description", ldapGroup.get("description").getString());
519
+	}
520
+
521
+	@Test
522
+	public void testExportUser_renamed() throws Exception {
523
+		String userUid = PopulateHelper.addUser("test" + System.nanoTime(), domain.value.name, Mailbox.Routing.none);
524
+
525
+		IUser userService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IUser.class,
526
+				domain.value.name);
527
+		ItemValue<User> user = userService.getComplete(userUid);
528
+
529
+		LdapExportService.build(domain.uid).sync();
530
+
531
+		String oldLogin = user.value.login;
532
+		user.value.login = "newlogin";
533
+		userService.update(user.uid, user.value);
534
+
535
+		LdapExportService.build(domain.uid).sync();
536
+
537
+		LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);
538
+		Entry ldapUser = ldapCon.lookup("uid=newlogin,ou=users,dc=" + domain.value.name + ",dc=local");
539
+		assertNotNull(ldapUser);
540
+		assertEquals(userUid, ldapUser.get("bmUid").getString());
541
+
542
+		ldapUser = ldapCon.lookup("uid=" + oldLogin + ",ou=users,dc=" + domain.value.name + ",dc=local");
543
+		assertNull(ldapUser);
544
+	}
545
+
546
+	@Test
547
+	public void testExportGroup_renamed() throws Exception {
548
+		String groupUid = addGroup();
549
+
550
+		IGroup groupService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IGroup.class,
551
+				domain.value.name);
552
+		ItemValue<Group> group = groupService.getComplete(groupUid);
553
+
554
+		LdapExportService.build(domain.uid).sync();
555
+
556
+		String oldName = group.value.name;
557
+		group.value.name = "newlogin";
558
+		groupService.update(group.uid, group.value);
559
+
560
+		LdapExportService.build(domain.uid).sync();
561
+
562
+		LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);
563
+		Entry ldapUser = ldapCon.lookup("cn=newlogin,ou=groups,dc=" + domain.value.name + ",dc=local");
564
+		assertNotNull(ldapUser);
565
+		assertEquals(groupUid, ldapUser.get("bmUid").getString());
566
+
567
+		ldapUser = ldapCon.lookup("cn=" + oldName + ",ou=groups,dc=" + domain.value.name + ",dc=local");
568
+		assertNull(ldapUser);
569
+	}
570
+
571
+	@Test
572
+	public void testExportGroupMember_membersOnCreate() throws Exception {
573
+		String userLogin = "test" + System.nanoTime();
574
+		String userUid = PopulateHelper.addUser(userLogin, domain.value.name, Mailbox.Routing.none);
575
+		String groupUid = addGroup();
576
+
577
+		IGroup groupService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IGroup.class,
578
+				domain.value.name);
579
+		groupService.add(groupUid, Arrays.asList(Member.user(userUid)));
580
+
581
+		LdapExportService.build(domain.uid).sync();
582
+
583
+		checkUserIsMemberOfGroup(groupUid, userUid, userLogin);
584
+	}
585
+
586
+	@Test
587
+	public void testExportGroupMember_addMember() throws Exception {
588
+		String userLogin = "test" + System.nanoTime();
589
+		String userUid = PopulateHelper.addUser(userLogin, domain.value.name, Mailbox.Routing.none);
590
+		String groupUid = addGroup();
591
+
592
+		LdapExportService.build(domain.uid).sync();
593
+
594
+		try (LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer)) {
595
+			List<Entry> ldapGroup = LdapHelper.getLdapEntryFromUid(ldapCon, domain, groupUid);
596
+			assertEquals(1, ldapGroup.size());
597
+
598
+			Attribute memberAttribute = ldapGroup.get(0).get("member");
599
+			assertNull(memberAttribute);
600
+
601
+			Attribute memberUidAttribute = ldapGroup.get(0).get("memberUid");
602
+			assertNull(memberUidAttribute);
603
+		}
604
+
605
+		IGroup groupService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IGroup.class,
606
+				domain.value.name);
607
+		groupService.add(groupUid, Arrays.asList(Member.user(userUid)));
608
+
609
+		LdapExportService.build(domain.uid).sync();
610
+
611
+		checkUserIsMemberOfGroup(groupUid, userUid, userLogin);
612
+	}
613
+
614
+	@Test
615
+	public void testExportGroupMember_removeMember() throws Exception {
616
+		String userLogin = "test" + System.nanoTime();
617
+		String userUid = PopulateHelper.addUser(userLogin, domain.value.name, Mailbox.Routing.none);
618
+		String groupUid = addGroup();
619
+
620
+		IGroup groupService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IGroup.class,
621
+				domain.value.name);
622
+		groupService.add(groupUid, Arrays.asList(Member.user(userUid)));
623
+
624
+		LdapExportService.build(domain.uid).sync();
625
+
626
+		checkUserIsMemberOfGroup(groupUid, userUid, userLogin);
627
+
628
+		groupService.remove(groupUid, Arrays.asList(Member.user(userUid)));
629
+
630
+		LdapExportService.build(domain.uid).sync();
631
+
632
+		LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);
633
+		List<Entry> ldapGroup = LdapHelper.getLdapEntryFromUid(ldapCon, domain, groupUid);
634
+		assertEquals(1, ldapGroup.size());
635
+
636
+		Attribute memberAttribute = ldapGroup.get(0).get("member");
637
+		assertNull(memberAttribute);
638
+
639
+		Attribute memberUidAttribute = ldapGroup.get(0).get("memberUid");
640
+		assertNull(memberUidAttribute);
641
+	}
642
+
643
+	@Test
644
+	public void testExportGroupMember_createGroupHierarchy() throws Exception {
645
+		String user1Login = "test" + System.nanoTime();
646
+		String user1Uid = PopulateHelper.addUser(user1Login, domain.value.name, Mailbox.Routing.none);
647
+		String user2Login = "test" + System.nanoTime();
648
+		String user2Uid = PopulateHelper.addUser(user2Login, domain.value.name, Mailbox.Routing.none);
649
+		String group1Uid = addGroup();
650
+		String group2Uid = addGroup();
651
+
652
+		IGroup groupService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IGroup.class,
653
+				domain.value.name);
654
+		groupService.add(group1Uid, Arrays.asList(Member.user(user1Uid)));
655
+		groupService.add(group2Uid, Arrays.asList(Member.user(user2Uid)));
656
+		groupService.add(group1Uid, Arrays.asList(Member.group(group2Uid)));
657
+
658
+		LdapExportService.build(domain.uid).sync();
659
+
660
+		checkGroupHierarchyMembers(group1Uid, user1Uid, user1Login, group2Uid, user2Login, user2Uid);
661
+	}
662
+
663
+	@Test
664
+	public void testExportGroupMember_removeUserFromGroupChild() throws Exception {
665
+		Group group1 = getGroup();
666
+		String group1Uid = addGroup(group1);
667
+		Group group2 = getGroup();
668
+		String group2Uid = addGroup(group2);
669
+		Group group3 = getGroup();
670
+		String group3Uid = addGroup(group3);
671
+		String user1Uid = PopulateHelper.addUser("test" + System.nanoTime(), domain.value.name, Mailbox.Routing.none);
672
+		User user2 = PopulateHelper.getUser("test" + System.nanoTime(), domain.value.name, Mailbox.Routing.none);
673
+		String user2Uid = PopulateHelper.addUser(domain.value.name, user2);
674
+
675
+		IGroup groupService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IGroup.class,
676
+				domain.value.name);
677
+		groupService.add(group1Uid, Arrays.asList(Member.user(user1Uid)));
678
+		groupService.add(group2Uid, Arrays.asList(Member.user(user2Uid)));
679
+		groupService.add(group1Uid, Arrays.asList(Member.group(group2Uid)));
680
+		groupService.add(group3Uid, Arrays.asList(Member.user(user2Uid)));
681
+
682
+		LdapExportService.build(domain.uid).sync();
683
+
684
+		groupService.remove(group2Uid, Arrays.asList(Member.user(user2Uid)));
685
+
686
+		LdapExportService.build(domain.uid).sync();
687
+
688
+		checkUserIsMemberOfGroup(group3Uid, user2Uid, user2.login);
689
+
690
+		LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);
691
+		String user2Dn = new DomainDirectoryUser(domain, ItemValue.create(user2Uid, user2), null).getDn();
692
+
693
+		Entry entry = ldapCon.lookup(new DomainDirectoryGroup(domain, ItemValue.create(group1Uid, group1)).getDn());
694
+		Attribute attrs = entry.get("member");
695
+		assertFalse(attrs.contains(user2Dn));
696
+		attrs = entry.get("memberUid");
697
+		assertFalse(attrs.contains(user2.login));
698
+
699
+		entry = ldapCon.lookup(new DomainDirectoryGroup(domain, ItemValue.create(group2Uid, group2)).getDn());
700
+		assertNull(entry.get("member"));
701
+		assertNull(entry.get("memberUid"));
702
+	}
703
+
704
+	@Test
705
+	public void testExportGroupMember_addUserToGroupChild() throws Exception {
706
+		Group group1 = getGroup();
707
+		String group1Uid = addGroup(group1);
708
+		Group group2 = getGroup();
709
+		String group2Uid = addGroup(group2);
710
+		User user1 = PopulateHelper.getUser("test" + System.nanoTime(), domain.value.name, Mailbox.Routing.none);
711
+		String user1Uid = PopulateHelper.addUser(domain.value.name, user1);
712
+		User user2 = PopulateHelper.getUser("test" + System.nanoTime(), domain.value.name, Mailbox.Routing.none);
713
+		String user2Uid = PopulateHelper.addUser(domain.value.name, user2);
714
+
715
+		IGroup groupService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IGroup.class,
716
+				domain.value.name);
717
+		groupService.add(group1Uid, Arrays.asList(Member.user(user1Uid)));
718
+		groupService.add(group1Uid, Arrays.asList(Member.group(group2Uid)));
719
+
720
+		LdapExportService.build(domain.uid).sync();
721
+
722
+		groupService.add(group2Uid, Arrays.asList(Member.user(user2Uid)));
723
+
724
+		LdapExportService.build(domain.uid).sync();
725
+
726
+		checkGroupHierarchyMembers(group1Uid, user1Uid, user1.login, group2Uid, user2.login, user2Uid);
727
+	}
728
+
729
+	@Test
730
+	public void testExportGroupWithExternalUserNotTaken() throws Exception {
731
+		// create a user
732
+		String user1Login = "test" + System.nanoTime();
733
+		String user1Uid = PopulateHelper.addUser(user1Login, domain.value.name, Mailbox.Routing.none);
734
+
735
+		// create a group
736
+		String groupUid = addGroup();
737
+
738
+		// create an external user
739
+		String externalUser1Uid = PopulateHelper.addExternalUser(domain.value.name, "external@user.com", "displayName");
740
+
741
+		// add all members to group
742
+		IGroup groupService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IGroup.class,
743
+				domain.value.name);
744
+		groupService.add(groupUid, Arrays.asList(Member.user(user1Uid), Member.externalUser(externalUser1Uid)));
745
+
746
+		LdapExportService.build(domain.uid).sync();
747
+
748
+		checkUidIsNotMemberOfGroup(groupUid, externalUser1Uid);
749
+		checkUserIsMemberOfGroup(groupUid, user1Uid, user1Login);
750
+	}
751
+
752
+	@Test
753
+	public void testExportGroupMember_addGroupMember() throws Exception {
754
+		String user1Login = "test" + System.nanoTime();
755
+		String user1Uid = PopulateHelper.addUser(user1Login, domain.value.name, Mailbox.Routing.none);
756
+		String user2Login = "test" + System.nanoTime();
757
+		String user2Uid = PopulateHelper.addUser(user2Login, domain.value.name, Mailbox.Routing.none);
758
+		String group1Uid = addGroup();
759
+		String group2Uid = addGroup();
760
+
761
+		IGroup groupService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IGroup.class,
762
+				domain.value.name);
763
+		groupService.add(group1Uid, Arrays.asList(Member.user(user1Uid)));
764
+		groupService.add(group2Uid, Arrays.asList(Member.user(user2Uid)));
765
+
766
+		LdapExportService.build(domain.uid).sync();
767
+
768
+		checkUserIsMemberOfGroup(group1Uid, user1Uid, user1Login);
769
+		checkUserIsMemberOfGroup(group2Uid, user2Uid, user2Login);
770
+
771
+		groupService.add(group1Uid, Arrays.asList(Member.group(group2Uid)));
772
+
773
+		LdapExportService.build(domain.uid).sync();
774
+
775
+		checkGroupHierarchyMembers(group1Uid, user1Uid, user1Login, group2Uid, user2Login, user2Uid);
776
+	}
777
+
778
+	@Test
779
+	public void testExportGroupMember_removeGroupMember() throws Exception {
780
+		String user1Login = "test" + System.nanoTime();
781
+		String user1Uid = PopulateHelper.addUser(user1Login, domain.value.name, Mailbox.Routing.none);
782
+		String user2Login = "test" + System.nanoTime();
783
+		String user2Uid = PopulateHelper.addUser(user2Login, domain.value.name, Mailbox.Routing.none);
784
+		String group1Uid = addGroup();
785
+		String group2Uid = addGroup();
786
+
787
+		IGroup groupService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IGroup.class,
788
+				domain.value.name);
789
+		groupService.add(group1Uid, Arrays.asList(Member.user(user1Uid)));
790
+		groupService.add(group2Uid, Arrays.asList(Member.user(user2Uid)));
791
+		groupService.add(group1Uid, Arrays.asList(Member.group(group2Uid)));
792
+
793
+		LdapExportService.build(domain.uid).sync();
794
+
795
+		checkGroupHierarchyMembers(group1Uid, user1Uid, user1Login, group2Uid, user2Login, user2Uid);
796
+
797
+		groupService.remove(group1Uid, Arrays.asList(Member.group(group2Uid)));
798
+
799
+		LdapExportService.build(domain.uid).sync();
800
+
801
+		checkUserIsMemberOfGroup(group1Uid, user1Uid, user1Login);
802
+		checkUserIsMemberOfGroup(group2Uid, user2Uid, user2Login);
803
+	}
804
+
805
+	@Test
806
+	public void testExportGroupMember_renameGroupMember() throws Exception {
807
+		String group1Uid = addGroup();
808
+		Group group2 = getGroup();
809
+		String group2Uid = addGroup(group2);
810
+		String user1Login = "test" + System.nanoTime();
811
+		String user1Uid = PopulateHelper.addUser(user1Login, domain.value.name, Mailbox.Routing.none);
812
+		String user2Login = "test" + System.nanoTime();
813
+		String user2Uid = PopulateHelper.addUser(user2Login, domain.value.name, Mailbox.Routing.none);
814
+
815
+		IGroup groupService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IGroup.class,
816
+				domain.value.name);
817
+		groupService.add(group1Uid, Arrays.asList(Member.user(user1Uid)));
818
+		groupService.add(group2Uid, Arrays.asList(Member.user(user2Uid)));
819
+		groupService.add(group1Uid, Arrays.asList(Member.group(group2Uid)));
820
+
821
+		LdapExportService.build(domain.uid).sync();
822
+
823
+		checkGroupHierarchyMembers(group1Uid, user1Uid, user1Login, group2Uid, user2Login, user2Uid);
824
+
825
+		group2.name = group2.name + "-new";
826
+		groupService.update(group2Uid, group2);
827
+
828
+		LdapExportService.build(domain.uid).sync();
829
+
830
+		checkGroupHierarchyMembers(group1Uid, user1Uid, user1Login, group2Uid, user2Login, user2Uid);
831
+	}
832
+
833
+	@Test
834
+	public void testExportGroupMember_renameUserMember() throws Exception {
835
+		String group1Uid = addGroup();
836
+		Group group2 = getGroup();
837
+		String group2Uid = addGroup(group2);
838
+		String user1Login = "test" + System.nanoTime();
839
+		String user1Uid = PopulateHelper.addUser(user1Login, domain.value.name, Mailbox.Routing.none);
840
+		User user2 = PopulateHelper.getUser("test" + System.nanoTime(), domain.value.name, Mailbox.Routing.none);
841
+		String user2Uid = PopulateHelper.addUser(domain.value.name, user2);
842
+
843
+		IGroup groupService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IGroup.class,
844
+				domain.value.name);
845
+		groupService.add(group1Uid, Arrays.asList(Member.user(user1Uid)));
846
+		groupService.add(group2Uid, Arrays.asList(Member.user(user2Uid)));
847
+		groupService.add(group1Uid, Arrays.asList(Member.group(group2Uid)));
848
+
849
+		LdapExportService.build(domain.uid).sync();
850
+
851
+		checkGroupHierarchyMembers(group1Uid, user1Uid, user1Login, group2Uid, user2.login, user2Uid);
852
+
853
+		user2.login = user2.login + "-new";
854
+		ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IUser.class, domain.value.name)
855
+				.update(user2Uid, user2);
856
+
857
+		LdapExportService.build(domain.uid).sync();
858
+
859
+		checkGroupHierarchyMembers(group1Uid, user1Uid, user1Login, group2Uid, user2.login, user2Uid);
860
+	}
861
+
862
+	@Test
863
+	public void testExportGroupMember_deleteUserMemberFromChild() throws Exception {
864
+		Group group1 = getGroup();
865
+		String group1Uid = addGroup(group1);
866
+		Group group2 = getGroup();
867
+		String group2Uid = addGroup(group2);
868
+		String user1Login = "test" + System.nanoTime();
869
+		String user1Uid = PopulateHelper.addUser(user1Login, domain.value.name, Mailbox.Routing.none);
870
+		User user2 = PopulateHelper.getUser("test" + System.nanoTime(), domain.value.name, Mailbox.Routing.none);
871
+		String user2Uid = PopulateHelper.addUser(domain.value.name, user2);
872
+
873
+		IGroup groupService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IGroup.class,
874
+				domain.value.name);
875
+		groupService.add(group1Uid, Arrays.asList(Member.user(user1Uid)));
876
+		groupService.add(group2Uid, Arrays.asList(Member.user(user2Uid)));
877
+		groupService.add(group1Uid, Arrays.asList(Member.group(group2Uid)));
878
+
879
+		LdapExportService.build(domain.uid).sync();
880
+
881
+		checkGroupHierarchyMembers(group1Uid, user1Uid, user1Login, group2Uid, user2.login, user2Uid);
882
+
883
+		TaskRef tr = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM)
884
+				.instance(IUser.class, domain.value.name).delete(user2Uid);
885
+		waitFor(tr);
886
+
887
+		LdapExportService.build(domain.uid).sync();
888
+
889
+		LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);
890
+		String user2Dn = new DomainDirectoryUser(domain, ItemValue.create(user2Uid, user2), null).getDn();
891
+
892
+		Entry entry = ldapCon.lookup(new DomainDirectoryGroup(domain, ItemValue.create(group1Uid, group1)).getDn());
893
+		Attribute attrs = entry.get("member");
894
+		assertFalse(attrs.contains(user2Dn));
895
+		attrs = entry.get("memberUid");
896
+		assertFalse(attrs.contains(user2.login));
897
+
898
+		entry = ldapCon.lookup(new DomainDirectoryGroup(domain, ItemValue.create(group2Uid, group2)).getDn());
899
+		assertNull(entry.get("member"));
900
+		assertNull(entry.get("memberUid"));
901
+	}
902
+
903
+	@Test
904
+	public void testExportGroupMember_deleteGroupMemberFromChild() throws Exception {
905
+		Group group1 = getGroup();
906
+		String group1Uid = addGroup(group1);
907
+		Group group2 = getGroup();
908
+		String group2Uid = addGroup(group2);
909
+		String user1Login = "test" + System.nanoTime();
910
+		String user1Uid = PopulateHelper.addUser(user1Login, domain.value.name, Mailbox.Routing.none);
911
+		User user2 = PopulateHelper.getUser("test" + System.nanoTime(), domain.value.name, Mailbox.Routing.none);
912
+		String user2Uid = PopulateHelper.addUser(domain.value.name, user2);
913
+
914
+		IGroup groupService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IGroup.class,
915
+				domain.value.name);
916
+		groupService.add(group1Uid, Arrays.asList(Member.user(user1Uid)));
917
+		groupService.add(group2Uid, Arrays.asList(Member.user(user2Uid)));
918
+		groupService.add(group1Uid, Arrays.asList(Member.group(group2Uid)));
919
+
920
+		LdapExportService.build(domain.uid).sync();
921
+
922
+		checkGroupHierarchyMembers(group1Uid, user1Uid, user1Login, group2Uid, user2.login, user2Uid);
923
+
924
+		TaskRef tr = groupService.delete(group2Uid);
925
+		waitFor(tr);
926
+
927
+		LdapExportService.build(domain.uid).sync();
928
+
929
+		LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);
930
+		String user2Dn = new DomainDirectoryUser(domain, ItemValue.create(user2Uid, user2), null).getDn();
931
+		String group2Dn = new DomainDirectoryGroup(domain, ItemValue.create(group2Uid, group2)).getDn();
932
+
933
+		Entry entry = ldapCon.lookup(group2Dn);
934
+		assertNull(entry);
935
+
936
+		entry = ldapCon.lookup(new DomainDirectoryGroup(domain, ItemValue.create(group1Uid, group1)).getDn());
937
+		Attribute attrs = entry.get("member");
938
+		assertFalse(attrs.contains(user2Dn));
939
+		assertFalse(attrs.contains(group2Dn));
940
+		attrs = entry.get("memberUid");
941
+		assertFalse(attrs.contains(user2.login));
942
+	}
943
+
944
+	/**
945
+	 * Check:
946
+	 * <ul>
947
+	 * <li>user (<i>groupUserUid</i>, <i>groupUserLogin</i>) member of group
948
+	 * (<i>groupUid</i>)</li>
949
+	 * <li>user (<i>childGroupUserLogin</i>, <i>childGroupUserUid</i>) member of
950
+	 * group (<i>childGroupUid</i>)</li>
951
+	 * <li>group (<i>childGroupUid</i>) member of group (<i>groupUid</i>)</li>
952
+	 * </ul>
953
+	 * 
954
+	 * @param groupUid
955
+	 * @param groupUserUid
956
+	 * @param groupUserLogin
957
+	 * @param childGroupUid
958
+	 * @param childGroupUserLogin
959
+	 * @param childGroupUserUid
960
+	 * @throws LdapException
961
+	 * @throws CursorException
962
+	 * @throws LdapInvalidAttributeValueException
963
+	 */
964
+	private void checkGroupHierarchyMembers(String groupUid, String groupUserUid, String groupUserLogin,
965
+			String childGroupUid, String childGroupUserLogin, String childGroupUserUid)
966
+			throws LdapException, CursorException, LdapInvalidAttributeValueException {
967
+		checkUserIsMemberOfGroup(childGroupUid, childGroupUserUid, childGroupUserLogin);
968
+
969
+		LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);
970
+
971
+		List<Entry> ldapUser1 = LdapHelper.getLdapEntryFromUid(ldapCon, domain, groupUserUid, "memberOf");
972
+		assertEquals(1, ldapUser1.size());
973
+
974
+		List<Entry> ldapGroup1 = LdapHelper.getLdapEntryFromUid(ldapCon, domain, groupUid, "member", "memberuid",
975
+				"memberOf");
976
+		assertEquals(1, ldapGroup1.size());
977
+
978
+		List<Entry> ldapGroup2 = LdapHelper.getLdapEntryFromUid(ldapCon, domain, childGroupUid, "member", "memberuid",
979
+				"memberOf");
980
+		assertEquals(1, ldapGroup2.size());
981
+
982
+		// Check group1 member and memberUid attributes
983
+		Attribute memberAttribute = ldapGroup1.get(0).get("member");
984
+		assertNotNull(memberAttribute);
985
+		assertEquals(2, memberAttribute.size());
986
+		assertTrue(memberAttribute.contains(ldapUser1.get(0).getDn().getName()));
987
+		assertTrue(memberAttribute.contains(ldapGroup2.get(0).getDn().getName()));
988
+
989
+		Attribute memberUidAttribute = ldapGroup1.get(0).get("memberUid");
990
+		assertNotNull(memberUidAttribute);
991
+		assertEquals(2, memberUidAttribute.size());
992
+		assertTrue(memberUidAttribute.contains(groupUserLogin));
993
+		assertTrue(memberUidAttribute.contains(childGroupUserLogin));
994
+
995
+		// Check user1 memberOf attributes
996
+		Attribute memberOfAttribute = ldapUser1.get(0).get("memberof");
997
+		assertNotNull(memberOfAttribute);
998
+		assertEquals(1, memberOfAttribute.size());
999
+		assertEquals(ldapGroup1.get(0).getDn().getName(), memberOfAttribute.getString());
1000
+
1001
+		// Check group2 memberOf attributes
1002
+		memberOfAttribute = ldapGroup2.get(0).get("memberof");
1003
+		assertNotNull(memberOfAttribute);
1004
+		assertEquals(1, memberOfAttribute.size());
1005
+		assertEquals(ldapGroup1.get(0).getDn().getName(), memberOfAttribute.getString());
1006
+	}
1007
+
1008
+	/**
1009
+	 * Check user (<i>userUid</i>, <i>userLogin</i>) is member of group
1010
+	 * (<i>groupUid</i>).
1011
+	 * 
1012
+	 * @param groupUid
1013
+	 * @param userUid
1014
+	 * @param userLogin
1015
+	 * 
1016
+	 * @throws LdapException
1017
+	 * @throws CursorException
1018
+	 * @throws LdapInvalidAttributeValueException
1019
+	 */
1020
+	private void checkUserIsMemberOfGroup(String groupUid, String userUid, String userLogin)
1021
+			throws LdapException, CursorException, LdapInvalidAttributeValueException {
1022
+		LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);
1023
+
1024
+		List<Entry> ldapUser = LdapHelper.getLdapEntryFromUid(ldapCon, domain, userUid, "memberOf");
1025
+		assertEquals(1, ldapUser.size());
1026
+
1027
+		List<Entry> ldapGroup = LdapHelper.getLdapEntryFromUid(ldapCon, domain, groupUid);
1028
+		assertEquals(1, ldapGroup.size());
1029
+
1030
+		Attribute memberAttribute = ldapGroup.get(0).get("member");
1031
+		assertNotNull(memberAttribute);
1032
+		assertEquals(1, memberAttribute.size());
1033
+		assertEquals(ldapUser.get(0).getDn().getName(), memberAttribute.getString());
1034
+
1035
+		Attribute memberUidAttribute = ldapGroup.get(0).get("memberUid");
1036
+		assertNotNull(memberUidAttribute);
1037
+		assertEquals(1, memberUidAttribute.size());
1038
+		assertEquals(userLogin, memberUidAttribute.getString());
1039
+
1040
+		Attribute memberOfAttribute = ldapUser.get(0).get("memberof");
1041
+		assertNotNull(memberOfAttribute);
1042
+		assertEquals(1, memberOfAttribute.size());
1043
+		assertEquals(ldapGroup.get(0).getDn().getName(), memberOfAttribute.getString());
1044
+	}
1045
+
1046
+	private void checkUidIsNotMemberOfGroup(String groupUid, String memberUid) throws LdapException, CursorException {
1047
+		assertEquals(0,
1048
+				LdapHelper
1049
+						.getLdapEntryFromUid(LdapHelper.connectDirectory(ldapRoleServer), domain, memberUid, "memberOf")
1050
+						.size());
1051
+	}
1052
+
1053
+	private void initAndAssignLdapExportServer() throws ServerFault, SQLException, InterruptedException {
1054
+		IServer serverService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IServer.class,
1055
+				InstallationId.getIdentifier());
1056
+
1057
+		String ldapRoleServerUid = UUID.randomUUID().toString();
1058
+		Server ldapRoleServer = new Server();
1059
+		ldapRoleServer.name = "LDAP export server";
1060
+		ldapRoleServer.ip = new BmConfIni().get("bluemind/ldap");
1061
+		waitFor(serverService.create(ldapRoleServerUid, ldapRoleServer));
1062
+
1063
+		this.ldapRoleServer = serverService.getComplete(ldapRoleServerUid);
1064
+
1065
+		INodeClient nodeClient = NodeActivator.get(ldapRoleServer.ip);
1066
+		updateUserPassword(nodeClient, "admin0@global.virt", Token.admin0());
1067
+
1068
+		waitFor(serverService.setTags(ldapRoleServerUid, Arrays.asList(LDAPTAG)));
1069
+
1070
+		serverService.assign(ldapRoleServerUid, domain.uid, LDAPTAG);
1071
+		// Wait for domain assign ending
1072
+		Thread.sleep(1000);
1073
+	}
1074
+
1075
+	private void waitFor(TaskRef taskRef) {
1076
+		ITask task = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(ITask.class, taskRef.id);
1077
+		while (!task.status().state.ended) {
1078
+			try {
1079
+				Thread.sleep(100);
1080
+			} catch (InterruptedException e) {
1081
+				e.printStackTrace();
1082
+			}
1083
+		}
1084
+		assertEquals(State.Success, task.status().state);
1085
+	}
1086
+
1087
+	private void updateUserPassword(INodeClient nodeClient, String login, String passwd) {
1088
+		NCUtils.exec(nodeClient, "/usr/local/sbin/updateUserPassword.sh " + login + " " + passwd);
1089
+	}
1090
+
1091
+	private class Results {
1092
+		List<String> userNotExported = new ArrayList<>();
1093
+		List<String> userExported = new ArrayList<>();
1094
+		List<String> groupNotExported = new ArrayList<>();
1095
+		List<String> groupExported = new ArrayList<>();
1096
+	}
1097
+
1098
+	private String addGroup() {
1099
+		Group group = getGroup();
1100
+		return addGroup(group);
1101
+	}
1102
+
1103
+	private String addGroup(Group group) {
1104
+		IGroup groupService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IGroup.class,
1105
+				domain.value.name);
1106
+		String uid = UIDGenerator.uid();
1107
+		groupService.create(uid, group);
1108
+		return uid;
1109
+	}
1110
+
1111
+	private Group getGroup() {
1112
+		Group group = new Group();
1113
+		group.name = UUID.randomUUID().toString();
1114
+
1115
+		return group;
1116
+	}
1117
+
1118
+	private Results checkSync() throws LdapException {
1119
+		IDirectory directoryService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM)
1120
+				.instance(IDirectory.class, domain.uid);
1121
+		ContainerChangeset<String> changeSet = directoryService.changeset(0l);
1122
+		assertNotEquals(0, changeSet.version);
1123
+		checkBmVersion(changeSet.version);
1124
+
1125
+		Results results = new Results();
1126
+		LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);
1127
+		for (String uid : changeSet.created) {
1128
+			DirEntry dirEntry = directoryService.findByEntryUid(uid);
1129
+			assertNotNull(dirEntry);
1130
+
1131
+			switch (dirEntry.kind) {
1132
+			case USER:
1133
+				checkUser(ldapCon, dirEntry, results);
1134
+				break;
1135
+			case GROUP:
1136
+				checkGroup(ldapCon, dirEntry, results);
1137
+				break;
1138
+			default:
1139
+				break;
1140
+			}
1141
+		}
1142
+		return results;
1143
+	}
1144
+
1145
+	private void checkGroup(LdapConnection ldapCon, DirEntry dirEntry, Results results) throws LdapException {
1146
+		IGroup groupService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IGroup.class,
1147
+				domain.uid);
1148
+		ItemValue<Group> group = groupService.getComplete(dirEntry.entryUid);
1149
+
1150
+		Entry ldapEntry = ldapCon.lookup("cn=" + group.value.name + ",ou=groups,dc=" + domain.value.name + ",dc=local");
1151
+
1152
+		if (dirEntry.hidden || dirEntry.system) {
1153
+			assertNull(ldapEntry);
1154
+			results.groupNotExported.add(dirEntry.entryUid);
1155
+		} else {
1156
+			assertNotNull(ldapEntry);
1157
+			results.groupExported.add(dirEntry.entryUid);
1158
+		}
1159
+	}
1160
+
1161
+	private void checkUser(LdapConnection ldapCon, DirEntry dirEntry, Results results) throws LdapException {
1162
+		IUser userService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IUser.class,
1163
+				domain.uid);
1164
+		ItemValue<User> user = userService.getComplete(dirEntry.entryUid);
1165
+
1166
+		Entry ldapEntry = ldapCon.lookup("uid=" + user.value.login + ",ou=users,dc=" + domain.value.name + ",dc=local");
1167
+
1168
+		if (dirEntry.hidden || dirEntry.system) {
1169
+			assertNull(ldapEntry);
1170
+			results.userNotExported.add(dirEntry.entryUid);
1171
+		} else {
1172
+			assertNotNull(ldapEntry);
1173
+			results.userExported.add(dirEntry.entryUid);
1174
+		}
1175
+	}
1176
+
1177
+	private void checkBmVersion() throws ServerFault, LdapException {
1178
+		checkBmVersion(ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM)
1179
+				.instance(IDirectory.class, domain.uid).changeset(0l).version);
1180
+	}
1181
+
1182
+	private void checkBmVersion(long i) throws LdapException {
1183
+		LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer);
1184
+		Entry entry = ldapCon.lookup("dc=" + domain.value.name + ",dc=local", "bmVersion");
1185
+		assertEquals(i, Long.parseLong(entry.get("bmVersion").getString()));
1186
+	}
1187
+}
0 1188
new file mode 100644
... ...
@@ -0,0 +1,131 @@
1
+/* BEGIN LICENSE
2
+  * Copyright © Blue Mind SAS, 2012-2017
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.system.ldap.export.conf;
19
+
20
+import static org.junit.Assert.assertEquals;
21
+import static org.junit.Assert.assertNotNull;
22
+import static org.junit.Assert.assertTrue;
23
+
24
+import java.io.IOException;
25
+import java.util.Collections;
26
+import java.util.UUID;
27
+
28
+import org.apache.directory.api.ldap.codec.api.ConfigurableBinaryAttributeDetector;
29
+import org.apache.directory.api.ldap.codec.api.DefaultConfigurableBinaryAttributeDetector;
30
+import org.apache.directory.api.ldap.model.entry.DefaultEntry;
31
+import org.apache.directory.api.ldap.model.exception.LdapException;
32
+import org.apache.directory.api.ldap.model.message.BindRequest;
33
+import org.apache.directory.api.ldap.model.message.BindRequestImpl;
34
+import org.apache.directory.api.ldap.model.message.BindResponse;
35
+import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
36
+import org.apache.directory.ldap.client.api.LdapConnection;
37
+import org.apache.directory.ldap.client.api.LdapConnectionConfig;
38
+import org.apache.directory.ldap.client.api.NoVerificationTrustManager;
39
+import org.junit.Before;
40
+import org.junit.Test;
41
+
42
+import net.bluemind.config.Token;
43
+import net.bluemind.core.api.fault.ServerFault;
44
+import net.bluemind.core.container.model.Item;
45
+import net.bluemind.core.container.model.ItemValue;
46
+import net.bluemind.lib.ldap.LdapConProxy;
47
+import net.bluemind.node.api.INodeClient;
48
+import net.bluemind.node.api.NCUtils;
49
+import net.bluemind.node.api.NodeActivator;
50
+import net.bluemind.pool.impl.BmConfIni;
51
+import net.bluemind.server.api.Server;
52
+import net.bluemind.system.ldap.export.LdapHelper;
53
+import net.bluemind.system.ldap.export.conf.DebSlapdConfig;
54
+
55
+public class DebSlapdConfigTests {
56
+	private String ldapRoleServerIp = new BmConfIni().get("bluemind/ldap");
57
+	private ItemValue<Server> ldapRoleServer;
58
+
59
+	@Before
60
+	public void before() throws Exception {
61
+		getLdapRoleServer();
62
+		updateUserPassword("admin0@global.virt", Token.admin0());
63
+	}
64
+
65
+	@Test
66
+	public void testSlapdConfig_initHost() throws ServerFault, IOException {
67
+		new DebSlapdConfig(ldapRoleServer).init();
68
+
69
+		try (LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer)) {
70
+			assertNotNull(ldapCon);
71
+			assertTrue(ldapCon.isConnected());
72
+			assertTrue(ldapCon.isAuthenticated());
73
+		}
74
+	}
75
+
76
+	@Test
77
+	public void testSlapdConfig_checkSaslAuth() throws ServerFault, IOException, LdapException {
78
+		updateUserPassword("test@domain.tld", "testpassword");
79
+
80
+		new DebSlapdConfig(ldapRoleServer).init();
81
+
82
+		try (LdapConnection ldapCon = LdapHelper.connectDirectory(ldapRoleServer)) {
83
+			ldapCon.add(new DefaultEntry("dc=local", "objectClass: organization", "objectClass: dcObject",
84
+					"o: BlueMind", "description: BlueMind LDAP directory"));
85
+
86
+			ldapCon.add(new DefaultEntry("uid=test,dc=local", "objectclass: inetOrgPerson", "sn: test", "cn: test",
87
+					"userPassword: {SASL}test@domain.tld"));
88
+		}
89
+
90
+		LdapConnectionConfig config = new LdapConnectionConfig();
91
+		config.setLdapHost(ldapRoleServer.value.address());
92
+		config.setLdapPort(389);
93
+		config.setUseTls(true);
94
+		config.setUseSsl(false);
95
+		config.setTrustManagers(new NoVerificationTrustManager());
96
+
97
+		config.setTimeout(10000);
98
+
99
+		ConfigurableBinaryAttributeDetector detector = new DefaultConfigurableBinaryAttributeDetector();
100
+		config.setBinaryAttributeDetector(detector);
101
+
102
+		try (LdapConnection ldapCon = new LdapConProxy(config)) {
103
+			assertNotNull(ldapCon);
104
+
105
+			BindRequest bindRequest = new BindRequestImpl();
106
+			bindRequest.setSimple(true);
107
+			bindRequest.setName("uid=test,dc=local");
108
+			bindRequest.setCredentials("testpassword");
109
+
110
+			BindResponse response = ldapCon.bind(bindRequest);
111
+			assertEquals(ResultCodeEnum.SUCCESS, response.getLdapResult().getResultCode());
112
+			assertTrue(ldapCon.isConnected());
113
+			assertTrue(ldapCon.isAuthenticated());
114
+		}
115
+	}
116
+
117
+	private void updateUserPassword(String login, String passwd) {
118
+		INodeClient nodeClient = NodeActivator.get(ldapRoleServerIp);
119
+		NCUtils.exec(nodeClient, "/usr/local/sbin/updateUserPassword.sh " + login + " " + passwd);
120
+	}
121
+
122
+	private void getLdapRoleServer() {
123
+		String uid = UUID.randomUUID().toString();
124
+
125
+		Server lrs = new Server();
126
+		lrs.ip = ldapRoleServerIp;
127
+		lrs.tags = Collections.emptyList();
128
+
129
+		ldapRoleServer = ItemValue.create(Item.create(uid, null), lrs);
130
+	}
131
+}
... ...
@@ -64,7 +64,7 @@ import net.bluemind.node.api.NCUtils;
64 64
 import net.bluemind.node.api.NodeActivator;
65 65
 import net.bluemind.pool.impl.BmConfIni;
66 66
 import net.bluemind.server.api.Server;
67
-import net.bluemind.system.ldap.export.internal.LdapHelper;
67
+import net.bluemind.system.ldap.export.LdapHelper;
68 68
 import net.bluemind.tests.defaultdata.PopulateHelper;
69 69
 
70 70
 public class LdapServerHookTests {
71 71
deleted file mode 100644
... ...
@@ -1,1185 +0,0 @@
1
-/* BEGIN LICENSE
2
-  * Copyright © Blue Mind SAS, 2012-2017
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