Browse code

BM-14699 Fix: prevent external user creation in some cases and fix IDirectory.byEmail impl

kladier authored on 26/04/2019 16:21:18
Showing 13 changed files
... ...
@@ -53,10 +53,14 @@ public class Email {
53 53
 		return result;
54 54
 	}
55 55
 
56
-	public String leftPart() {
56
+	public String localPart() {
57 57
 		return address.split("@")[0];
58 58
 	}
59 59
 
60
+	public String domainPart() {
61
+		return address.split("@")[1];
62
+	}
63
+
60 64
 	@Override
61 65
 	public boolean equals(Object obj) {
62 66
 		if (this == obj)
... ...
@@ -107,7 +107,7 @@ public class DirBaseValue {
107 107
 	public String defaultEmailAddress(String domainName) {
108 108
 		Email defaultEmail = defaultEmail();
109 109
 		if (defaultEmail != null) {
110
-			return defaultEmail.allAliases ? defaultEmail.leftPart() + "@" + domainName : defaultEmail.address;
110
+			return defaultEmail.allAliases ? defaultEmail.localPart() + "@" + domainName : defaultEmail.address;
111 111
 		} else {
112 112
 			return null;
113 113
 		}
... ...
@@ -186,7 +186,7 @@ public class DirEntryStoreTests {
186 186
 
187 187
 	@Test
188 188
 	public void testSearchFilter() throws Exception {
189
-		creates(DirEntry.create(null, "test1", DirEntry.Kind.DOMAIN, "test1", "domain", null, true, false, false),
189
+		creates(true, DirEntry.create(null, "test1", DirEntry.Kind.DOMAIN, "test1", "domain", null, true, false, false),
190 190
 				DirEntry.create(null, "test2", DirEntry.Kind.USER, "jojo", "jojo", "jojo@test.com", false, false, false)
191 191
 						.withEmails("1jojo@test.com", "test2@test.com", "jojo@test.com"),
192 192
 				DirEntry.create(null, "test3", DirEntry.Kind.USER, "test3", "zozo", "test3@test.com", true, false, true)
... ...
@@ -375,7 +375,7 @@ public class DirEntryStoreTests {
375 375
 		Item itemOu2 = itemStore.create(Item.create("test1OuChild", null));
376 376
 		ouStore.create(itemOu2, ouRootChild);
377 377
 
378
-		creates(DirEntry.create(null, "test1", DirEntry.Kind.DOMAIN, "test1", "domain", null, true, false, false),
378
+		creates(true, DirEntry.create(null, "test1", DirEntry.Kind.DOMAIN, "test1", "domain", null, true, false, false),
379 379
 				DirEntry.create(itemOu2.uid, "test2", DirEntry.Kind.USER, "jojo", "jojo", "jojo@test.com", false, false,
380 380
 						false).withEmails("1jojo@test.com", "test2@test.com", "jojo@test.com"),
381 381
 				DirEntry.create(itemOuRoot2.uid, "test22", DirEntry.Kind.USER, "jojo2", "jojo2", "jojo2@test.com",
... ...
@@ -443,7 +443,7 @@ public class DirEntryStoreTests {
443 443
 
444 444
 	@Test
445 445
 	public void testSystemFilter() throws SQLException {
446
-		List<Item> items = creates(
446
+		List<Item> items = creates(true,
447 447
 				DirEntry.create(null, "test2", DirEntry.Kind.USER, "jojo", "jojo", "jojo@test.com", false, false, false)
448 448
 						.withEmails("1jojo@test.com", "test2@test.com", "jojo@test.com"),
449 449
 				DirEntry.create(null, "test3", DirEntry.Kind.USER, "zozo", "zozo", "test3@test.com", false, false, true)
... ...
@@ -470,7 +470,8 @@ public class DirEntryStoreTests {
470 470
 
471 471
 	@Test
472 472
 	public void testSearchByPath() throws Exception {
473
-		creates(DirEntry.create(null, "bm.lan", DirEntry.Kind.DOMAIN, "bm.lan", "domain", null, true, true, false), //
473
+		creates(true,
474
+				DirEntry.create(null, "bm.lan", DirEntry.Kind.DOMAIN, "bm.lan", "domain", null, true, true, false), //
474 475
 				DirEntry.create(null, "bm.lan/users/jojo", DirEntry.Kind.USER, "jojo", "jojo", "jojo@test.com", false,
475 476
 						false, false), //
476 477
 				DirEntry.create(null, "bm.lan/users/zozo", DirEntry.Kind.USER, "zozo", "zozo", "zozo@test.com", true,
... ...
@@ -482,14 +483,14 @@ public class DirEntryStoreTests {
482 483
 		assertEquals("bm.lan/users/zozo", res.get(1));
483 484
 	}
484 485
 
485
-	private List<Item> creates(DirEntry... dirEntries) throws SQLException {
486
+	private List<Item> creates(boolean withMailbox, DirEntry... dirEntries) throws SQLException {
486 487
 
487 488
 		return Arrays.asList(dirEntries).stream().map(entry -> {
488 489
 			try {
489 490
 				itemStore.create(Item.create(entry.path, null));
490 491
 				Item item = itemStore.get(entry.path);
491 492
 				dirEntryStore.create(item, entry);
492
-				if (entry.emails != null) {
493
+				if (entry.emails != null && withMailbox) {
493 494
 					Mailbox mbox = new Mailbox();
494 495
 					mbox.dataLocation = "test";
495 496
 					mbox.emails = entry.emails;
... ...
@@ -520,19 +521,28 @@ public class DirEntryStoreTests {
520 521
 
521 522
 	@Test
522 523
 	public void testGetByEmail() throws Exception {
523
-		creates(DirEntry.create(null, "test1", DirEntry.Kind.DOMAIN, "test1", "domain", null, true, false, false)
524
-				.withEmails(Arrays.asList(Email.create("zob@test.com", true, true))),
524
+		creates(true,
525
+				DirEntry.create(null, "test1", DirEntry.Kind.DOMAIN, "test1", "domain", null, true, false, false)
526
+						.withEmails(Arrays.asList(Email.create("zob@test.com", true, true))),
525 527
 				DirEntry.create(null, "test2", DirEntry.Kind.USER, "jojo", "jojo", "jojo@test.com", false, false, false)
526 528
 						.withEmails("1jojo@test.com", "test2@test.com", "jojo@test.com"),
527 529
 				DirEntry.create(null, "test3", DirEntry.Kind.USER, "test3", "zozo", "test3@test.com", true, false, true)
528 530
 						.withEmails("1test3@test.com", "2test3@test.com", "test3@test.com"));
529 531
 
530
-		assertNotNull(dirEntryStore.byEmail("1test3@test.com"));
531
-		assertNotNull(dirEntryStore.byEmail("zob@test.com"));
532
-		// test allAliases
533
-		assertNotNull(dirEntryStore.byEmail("zob@zob.com"));
532
+		assertNotNull(dirEntryStore.byEmail("1test3@test.com", false));
533
+		assertNotNull(dirEntryStore.byEmail("zob@test.com", false));
534
+		assertNull(dirEntryStore.byEmail("not@test.com", false));
534 535
 
535
-		assertNull(dirEntryStore.byEmail("not@test.com"));
536
+		// test allAliases: by passing isDomainAlias parameter at true, zob.com will be
537
+		// considered as an alias
538
+		assertNotNull(dirEntryStore.byEmail("zob@zob.com", true));
539
+		assertNull(dirEntryStore.byEmail("zob@zob.com", false));
540
+
541
+		// test when dir_entry created has no entry on table t_mailbox_email (as
542
+		// external user for example)
543
+		creates(false, DirEntry.create(null, "extuser", DirEntry.Kind.EXTERNALUSER, "extuser", "extuser",
544
+				"ext@user.com", true, false, false));
545
+		assertNotNull(dirEntryStore.byEmail("ext@user.com", false));
536 546
 	}
537 547
 
538 548
 	@Test
... ...
@@ -576,7 +586,7 @@ public class DirEntryStoreTests {
576 586
 
577 587
 	@Test
578 588
 	public void testSearch_NullOrder() throws SQLException {
579
-		List<Item> items = creates(
589
+		List<Item> items = creates(true,
580 590
 				DirEntry.create(null, "test1", DirEntry.Kind.DOMAIN, "test1", "domain", null, true, false, false),
581 591
 				DirEntry.create(null, "test2", DirEntry.Kind.USER, "jojo", "jojo", "jojo@test.com", false, false, false)
582 592
 						.withEmails("1jojo@test.com", "test2@test.com", "jojo@test.com"),
... ...
@@ -161,15 +161,20 @@ public class DirEntryStore extends AbstractItemValueStore<DirEntry> {
161 161
 		return unique(query, StringCreator.FIRST, Collections.emptyList(), new Object[] { container.id, entryUid });
162 162
 	}
163 163
 
164
-	public String byEmail(String email) throws SQLException {
165
-		String query = "select item.uid from t_container_item item, t_directory_entry dir, t_mailbox_email e"
166
-				+ " WHERE item.id = dir.item_id AND " //
167
-				+ " item.id = e.item_id AND item.container_id = ? AND "
168
-				+ "( ( e.left_address = ? AND e.right_address = ? ) or ( e.all_aliases = true and e.left_address = ?) ) ";
164
+	public String byEmail(String email, boolean isDomainAlias) throws SQLException {
165
+		String query = "SELECT item.uid FROM t_container_item item" //
166
+				+ " JOIN t_directory_entry dir ON item.id = dir.item_id" //
167
+				+ " LEFT JOIN t_mailbox_email e ON dir.item_id = e.item_id" //
168
+				+ " WHERE item.container_id = ? AND (" //
169
+				+ " (dir.email = ?) OR (" //
170
+				+ "   (e.left_address = ? AND " //
171
+				+ "    (e.right_address = ? OR (e.all_aliases AND ?))" //
172
+				+ "   )" //
173
+				+ " )) LIMIT 1";
169 174
 
170 175
 		String[] splittedEmail = email.split("@");
171 176
 		return unique(query, StringCreator.FIRST, Collections.emptyList(),
172
-				new Object[] { container.id, splittedEmail[0], splittedEmail[1], splittedEmail[0] });
177
+				new Object[] { container.id, email, splittedEmail[0], splittedEmail[1], isDomainAlias });
173 178
 	}
174 179
 
175 180
 	public ListResult<Item> search(DirEntryQuery q) throws SQLException {
... ...
@@ -186,9 +186,9 @@ public class DirEntryStoreService extends BaseDirStoreService<DirEntry> {
186 186
 		super.deleteAll();
187 187
 	}
188 188
 
189
-	public ItemValue<DirEntry> getByEmail(String email) {
189
+	public ItemValue<DirEntry> getByEmail(String email, boolean isDomainEmail) {
190 190
 		return doOrFail(() -> {
191
-			String res = entryStore.byEmail(email);
191
+			String res = entryStore.byEmail(email, isDomainEmail);
192 192
 			if (res != null) {
193 193
 				return get(res, null);
194 194
 			} else {
... ...
@@ -292,12 +292,8 @@ public class Directory {
292 292
 
293 293
 		email = email.toLowerCase();
294 294
 		String domainPart = email.split("@")[1];
295
-
296
-		if (!domain.value.aliases.contains(domainPart) && !domainPart.equals(domain.value.name)) {
297
-			return null;
298
-		}
299
-
300
-		return itemStore.getByEmail(email);
295
+		boolean isDomainEmail = domain.value.aliases.contains(domainPart) || domainPart.equals(domain.value.name);
296
+		return itemStore.getByEmail(email, isDomainEmail);
301 297
 	}
302 298
 
303 299
 	private void checkReadAccess() {
... ...
@@ -37,6 +37,7 @@ import org.vertx.java.core.AsyncResult;
37 37
 import org.vertx.java.core.Handler;
38 38
 
39 39
 import com.google.common.collect.Lists;
40
+import com.google.common.collect.Sets;
40 41
 
41 42
 import net.bluemind.core.api.fault.ErrorCode;
42 43
 import net.bluemind.core.api.fault.ServerFault;
... ...
@@ -59,9 +60,11 @@ import net.bluemind.domain.service.internal.DomainStoreService;
59 60
 import net.bluemind.domain.service.tests.FakeDomainHook;
60 61
 import net.bluemind.group.api.IGroup;
61 62
 import net.bluemind.lib.vertx.VertxPlatform;
63
+import net.bluemind.mailbox.api.Mailbox.Routing;
62 64
 import net.bluemind.role.api.BasicRoles;
63 65
 import net.bluemind.server.api.Server;
64 66
 import net.bluemind.tests.defaultdata.PopulateHelper;
67
+import net.bluemind.user.api.User;
65 68
 
66 69
 public class DomainsServiceTests {
67 70
 
... ...
@@ -72,7 +75,7 @@ public class DomainsServiceTests {
72 75
 	@Before
73 76
 	public void before() throws Exception {
74 77
 		JdbcTestHelper.getInstance().beforeTest();
75
-		
78
+
76 79
 		JdbcActivator.getInstance().setDataSource(JdbcTestHelper.getInstance().getDataSource());
77 80
 		ElasticsearchTestHelper.getInstance().beforeTest();
78 81
 
... ...
@@ -310,6 +313,35 @@ public class DomainsServiceTests {
310 313
 	}
311 314
 
312 315
 	@Test
316
+	// FIXME: BM-14722
317
+	public void testCanSetAliasesWhenConflict() throws Exception {
318
+		String domainAlias = "newalias.tld";
319
+
320
+		// create domain
321
+		String domainUid = "test" + System.currentTimeMillis() + ".lan";
322
+		PopulateHelper.createTestDomain(domainUid);
323
+
324
+		// create an external user which use domain alias not yet created
325
+		String leftPart = "whatever";
326
+		PopulateHelper.addExternalUser(domainUid, leftPart + "@" + domainAlias, "externaluser");
327
+
328
+		// create a user with all_alias
329
+		User user = PopulateHelper.getUser(leftPart, domainUid, Routing.none);
330
+		user.emails.forEach(email -> email.allAliases = true);
331
+		PopulateHelper.addUser(domainUid, user);
332
+
333
+		// try to add alias to domain
334
+		getService().setAliases(domainUid, Sets.newHashSet(domainAlias));
335
+
336
+//		try {
337
+//			
338
+//			fail("should fail because an external user using this alias exists");
339
+//		} catch (ServerFault e) {
340
+//			assertEquals(ErrorCode.INVALID_PARAMETER, e.getCode());
341
+//		}
342
+	}
343
+
344
+	@Test
313 345
 	public void testCustomProperties() throws ServerFault {
314 346
 		IDomains domains = getService();
315 347
 		Domain d = new Domain();
... ...
@@ -49,23 +49,21 @@ public class DomainValidator {
49 49
 		}
50 50
 
51 51
 		checkAliasesFormat(domain.aliases);
52
-		checkAliasUnicity(store, domain.name, domain.aliases);
52
+		checkAliasUniquity(store, domain.name, domain.aliases);
53 53
 	}
54 54
 
55
-	private void checkAliasUnicity(DomainStoreService store, String name, Set<String> aliases)
56
-			throws ServerFault {
55
+	private void checkAliasUniquity(DomainStoreService store, String name, Set<String> aliases) throws ServerFault {
57 56
 		Set<String> checkset = new HashSet<>(aliases);
58 57
 		checkset.add(name);
59
-		// Map<String, String> presentAliases =
60 58
 
61 59
 		Map<String, ItemValue<Domain>> presentAliases = checkset.stream() //
62 60
 				.map(alias -> {
63 61
 					ItemValue<Domain> domain = domainIsPresent(store, name, alias);
64 62
 					if (domain != null && !domain.uid.equals(name)) {
65
-						return (Map<String, ItemValue<Domain>>) ImmutableMap.<String, ItemValue<Domain>> builder()
63
+						return (Map<String, ItemValue<Domain>>) ImmutableMap.<String, ItemValue<Domain>>builder()
66 64
 								.put(alias, domain).build();
67 65
 					} else {
68
-						return (Map<String, ItemValue<Domain>>) ImmutableMap.<String, ItemValue<Domain>> of();
66
+						return (Map<String, ItemValue<Domain>>) ImmutableMap.<String, ItemValue<Domain>>of();
69 67
 					}
70 68
 				}).reduce(new HashMap<>(), (u, t) -> {
71 69
 					u.putAll(t);
... ...
@@ -20,4 +20,5 @@ Require-Bundle: org.junit,
20 20
  net.bluemind.role.api,
21 21
  slf4j.api,
22 22
  net.bluemind.group.api,
23
- net.bluemind.group.persistance
23
+ net.bluemind.group.persistance,
24
+ net.bluemind.user.api
... ...
@@ -34,6 +34,8 @@ import org.junit.After;
34 34
 import org.junit.Before;
35 35
 import org.junit.Test;
36 36
 
37
+import com.google.common.collect.Sets;
38
+
37 39
 import net.bluemind.addressbook.api.VCard;
38 40
 import net.bluemind.addressbook.domainbook.verticle.DomainBookVerticle;
39 41
 import net.bluemind.core.api.Email;
... ...
@@ -48,15 +50,19 @@ import net.bluemind.core.jdbc.JdbcTestHelper;
48 50
 import net.bluemind.core.rest.ServerSideServiceProvider;
49 51
 import net.bluemind.core.tests.BmTestContext;
50 52
 import net.bluemind.domain.api.Domain;
53
+import net.bluemind.domain.api.IDomains;
51 54
 import net.bluemind.externaluser.api.ExternalUser;
52 55
 import net.bluemind.externaluser.api.IExternalUser;
53 56
 import net.bluemind.externaluser.service.internal.ExternalUserContainerStoreService;
54 57
 import net.bluemind.group.api.Group;
55 58
 import net.bluemind.group.api.IGroup;
56 59
 import net.bluemind.group.api.Member;
60
+import net.bluemind.mailbox.api.Mailbox.Routing;
57 61
 import net.bluemind.role.api.BasicRoles;
58 62
 import net.bluemind.role.api.IRoles;
59 63
 import net.bluemind.tests.defaultdata.PopulateHelper;
64
+import net.bluemind.user.api.IUser;
65
+import net.bluemind.user.api.User;
60 66
 
61 67
 public class ExternalUserServiceTests {
62 68
 
... ...
@@ -66,6 +72,7 @@ public class ExternalUserServiceTests {
66 72
 	private ItemValue<Domain> domain;
67 73
 	private Container domainContainer;
68 74
 	private SecurityContext securityContext;
75
+	private SecurityContext adminSecurityContext;
69 76
 
70 77
 	@Before
71 78
 	public void before() throws Exception {
... ...
@@ -85,6 +92,9 @@ public class ExternalUserServiceTests {
85 92
 
86 93
 		securityContext = BmTestContext.contextWithSession("external-user-manager", "test", domainUid,
87 94
 				BasicRoles.ROLE_MANAGE_EXTERNAL_USER, BasicRoles.ROLE_MANAGE_GROUP).getSecurityContext();
95
+		adminSecurityContext = BmTestContext.contextWithSession("external-user-manager", "test", domainUid,
96
+				BasicRoles.ROLE_MANAGE_EXTERNAL_USER, BasicRoles.ROLE_MANAGE_GROUP, BasicRoles.ROLE_ADMIN)
97
+				.getSecurityContext();
88 98
 
89 99
 		Container container = containerStore.get(domainUid);
90 100
 		assertNotNull(container);
... ...
@@ -112,10 +122,13 @@ public class ExternalUserServiceTests {
112 122
 	}
113 123
 
114 124
 	private ExternalUser createDefaultExternalUser() {
125
+		return this.createDefaultExternalUser("user@external.com");
126
+	}
127
+
128
+	private ExternalUser createDefaultExternalUser(String address) {
115 129
 		ExternalUser externalUser = new ExternalUser();
116 130
 		String firstName = "MyFirstName";
117 131
 		String name = "MyName";
118
-		String mailAddress = "user@external.com";
119 132
 
120 133
 		externalUser.hidden = true;
121 134
 		externalUser.dataLocation = PopulateHelper.FAKE_CYRUS_IP;
... ...
@@ -125,9 +138,9 @@ public class ExternalUserServiceTests {
125 138
 		externalUser.contactInfos.identification.name.familyNames = name;
126 139
 		externalUser.contactInfos.identification.name.additionalNames = firstName;
127 140
 		externalUser.contactInfos.communications.emails = new ArrayList<>();
128
-		externalUser.contactInfos.communications.emails.add(VCard.Communications.Email.create(mailAddress));
141
+		externalUser.contactInfos.communications.emails.add(VCard.Communications.Email.create(address));
129 142
 		externalUser.emails = new ArrayList<>();
130
-		externalUser.emails.add(Email.create(mailAddress, true));
143
+		externalUser.emails.add(Email.create(address, true));
131 144
 
132 145
 		return externalUser;
133 146
 	}
... ...
@@ -204,6 +217,51 @@ public class ExternalUserServiceTests {
204 217
 	}
205 218
 
206 219
 	@Test
220
+	public void testCantCreateExternalUserWhoseRightPartIsDomainAliasAlreadyUsedByAnUser() {
221
+		// adding an alias
222
+		String newAlias = "newalias.tld";
223
+		ServerSideServiceProvider.getProvider(adminSecurityContext).instance(IDomains.class).setAliases(domainUid,
224
+				Sets.newHashSet(newAlias));
225
+
226
+		// creating an user with mailbox in all_alias
227
+		String userItemUid = UUID.randomUUID().toString();
228
+		String leftPart = "whatever";
229
+		User user = PopulateHelper.getUser(leftPart, domainUid, Routing.none);
230
+		user.emails.forEach(email -> email.allAliases = true);
231
+		ServerSideServiceProvider.getProvider(adminSecurityContext).instance(IUser.class, domainUid).create(userItemUid,
232
+				user);
233
+
234
+		// try to create an external user which uses the same left part as the user and
235
+		// the new alias as right part
236
+		String extUserItemUid = UUID.randomUUID().toString();
237
+		ExternalUser externalUser = createDefaultExternalUser(leftPart + "@" + newAlias);
238
+
239
+		try {
240
+			getExternalUserService().create(extUserItemUid, externalUser);
241
+			fail("can't create an external user whose right part is a domain alias already used by an user.");
242
+		} catch (ServerFault sf) {
243
+			assertEquals(ErrorCode.ALREADY_EXISTS, sf.getCode());
244
+		}
245
+	}
246
+
247
+	@Test
248
+	public void testCantCreateExternalUserWithSameEmailThanExistingExternalUser() {
249
+		String itemUid = UUID.randomUUID().toString();
250
+		ExternalUser eu = createDefaultExternalUser();
251
+		getExternalUserService().create(itemUid, eu);
252
+
253
+		String itemUid2 = UUID.randomUUID().toString();
254
+		ExternalUser eu2 = createDefaultExternalUser();
255
+
256
+		try {
257
+			getExternalUserService().create(itemUid2, eu2);
258
+			fail("can't create an external user with same email than an existing external user.");
259
+		} catch (ServerFault sf) {
260
+			assertEquals(ErrorCode.ALREADY_EXISTS, sf.getCode());
261
+		}
262
+	}
263
+
264
+	@Test
207 265
 	public void testUpdateExternalUser() {
208 266
 		String itemUid = UUID.randomUUID().toString();
209 267
 		ExternalUser eu = createDefaultExternalUser();
... ...
@@ -87,7 +87,7 @@ public class ExternalUserService implements IInCoreExternalUser {
87 87
 
88 88
 		sanitizer.create(externalUser);
89 89
 		sanitizer.create(new DirDomainValue<>(domainUid, uid, externalUser));
90
-		validator.validate(externalUser);
90
+		validator.validate(externalUser, domainUid, bmContext);
91 91
 
92 92
 		storeService.createWithExtId(uid, extId, externalUser);
93 93
 		eventProducer.changed(uid, storeService.getVersion());
... ...
@@ -102,7 +102,7 @@ public class ExternalUserService implements IInCoreExternalUser {
102 102
 
103 103
 		sanitizer.update(previous, eu);
104 104
 		sanitizer.update(new DirDomainValue<>(domainUid, uid, previous), new DirDomainValue<>(domainUid, uid, eu));
105
-		validator.validate(eu);
105
+		validator.validate(eu, domainUid, bmContext);
106 106
 
107 107
 		storeService.update(uid, eu);
108 108
 		eventProducer.changed(uid, storeService.getVersion());
... ...
@@ -21,11 +21,13 @@ import net.bluemind.core.api.ParametersValidator;
21 21
 import net.bluemind.core.api.fault.ErrorCode;
22 22
 import net.bluemind.core.api.fault.ServerFault;
23 23
 import net.bluemind.core.email.EmailHelper;
24
+import net.bluemind.core.rest.BmContext;
25
+import net.bluemind.directory.api.IDirectory;
24 26
 import net.bluemind.externaluser.api.ExternalUser;
25 27
 
26 28
 public class ExternalUserValidator {
27 29
 
28
-	public void validate(ExternalUser eu) throws ServerFault {
30
+	public void validate(ExternalUser eu, String domainUid, BmContext bmContext) throws ServerFault {
29 31
 		ParametersValidator.notNull(eu);
30 32
 		ParametersValidator.notNullAndNotEmpty(eu.defaultEmailAddress());
31 33
 		ParametersValidator.notNullAndNotEmpty(eu.contactInfos.defaultMail());
... ...
@@ -36,5 +38,11 @@ public class ExternalUserValidator {
36 38
 		EmailHelper.validate(eu.emails);
37 39
 		ParametersValidator.notNullAndNotEmpty(eu.contactInfos.identification.formatedName.value);
38 40
 		ParametersValidator.notNullAndNotEmpty(eu.dataLocation);
41
+
42
+		if (bmContext.provider().instance(IDirectory.class, domainUid).getByEmail(eu.defaultEmailAddress()) != null) {
43
+			throw new ServerFault(
44
+					"Can't create external user: An entry with the same email address already exists in this domain",
45
+					ErrorCode.ALREADY_EXISTS);
46
+		}
39 47
 	}
40 48
 }
... ...
@@ -389,14 +389,15 @@ public class PopulateHelper {
389 389
 		IExternalUser externalUserService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM)
390 390
 				.instance(IExternalUser.class, domain);
391 391
 		String uid = "extUserUID_" + System.nanoTime();
392
-		ExternalUser eu = new ExternalUser();
393
-		eu.contactInfos = new VCard();
394
-		eu.contactInfos.identification.name = VCard.Identification.Name.create(name, null, null, null, null, null);
395
-		eu.contactInfos.communications.emails = new ArrayList<>();
396
-		eu.contactInfos.communications.emails.add(VCard.Communications.Email.create(email));
397
-		eu.emails = new ArrayList<>();
398
-		eu.emails.add(Email.create(email, true));
399
-		externalUserService.create(uid, eu);
392
+		ExternalUser externalUser = new ExternalUser();
393
+		externalUser.dataLocation = PopulateHelper.FAKE_CYRUS_IP;
394
+		externalUser.contactInfos = new VCard();
395
+		externalUser.contactInfos.identification.name = VCard.Identification.Name.create(name, null, null, null, null, null);
396
+		externalUser.contactInfos.communications.emails = new ArrayList<>();
397
+		externalUser.contactInfos.communications.emails.add(VCard.Communications.Email.create(email));
398
+		externalUser.emails = new ArrayList<>();
399
+		externalUser.emails.add(Email.create(email, true));
400
+		externalUserService.create(uid, externalUser);
400 401
 		return uid;
401 402
 	}
402 403