]> source.dussan.org Git - sonarqube.git/blob
4673a5fce22a93087854821d598ee667c681cb3a
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2019 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 3 of the License, or (at your option) any later version.
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.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20 package org.sonar.server.authentication;
21
22 import java.util.Optional;
23 import java.util.stream.Collectors;
24 import org.junit.Rule;
25 import org.junit.Test;
26 import org.junit.rules.ExpectedException;
27 import org.sonar.api.config.internal.MapSettings;
28 import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
29 import org.sonar.api.server.authentication.UserIdentity;
30 import org.sonar.api.utils.System2;
31 import org.sonar.core.util.stream.MoreCollectors;
32 import org.sonar.db.DbTester;
33 import org.sonar.db.organization.OrganizationDto;
34 import org.sonar.db.user.GroupDto;
35 import org.sonar.db.user.UserDto;
36 import org.sonar.server.authentication.UserRegistration.ExistingEmailStrategy;
37 import org.sonar.server.authentication.event.AuthenticationEvent;
38 import org.sonar.server.authentication.event.AuthenticationEvent.Source;
39 import org.sonar.server.authentication.exception.EmailAlreadyExistsRedirectionException;
40 import org.sonar.server.es.EsTester;
41 import org.sonar.server.organization.DefaultOrganizationProvider;
42 import org.sonar.server.organization.MemberUpdater;
43 import org.sonar.server.organization.OrganizationUpdater;
44 import org.sonar.server.organization.TestDefaultOrganizationProvider;
45 import org.sonar.server.organization.TestOrganizationFlags;
46 import org.sonar.server.user.NewUserNotifier;
47 import org.sonar.server.user.UserUpdater;
48 import org.sonar.server.user.index.UserIndexer;
49 import org.sonar.server.usergroups.DefaultGroupFinder;
50
51 import static com.google.common.collect.Sets.newHashSet;
52 import static java.util.Arrays.stream;
53 import static org.assertj.core.api.Assertions.assertThat;
54 import static org.mockito.Mockito.mock;
55 import static org.sonar.db.user.UserTesting.newUserDto;
56 import static org.sonar.process.ProcessProperties.Property.ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS;
57 import static org.sonar.server.authentication.UserRegistration.ExistingEmailStrategy.FORBID;
58 import static org.sonar.server.authentication.event.AuthenticationEvent.Method.BASIC;
59 import static org.sonar.server.authentication.event.AuthenticationExceptionMatcher.authenticationException;
60
61 public class UserRegistrarImplTest {
62
63   private System2 system2 = new AlwaysIncreasingSystem2();
64
65   private static String USER_LOGIN = "github-johndoo";
66
67   private static UserIdentity USER_IDENTITY = UserIdentity.builder()
68     .setProviderId("ABCD")
69     .setProviderLogin("johndoo")
70     .setLogin(USER_LOGIN)
71     .setName("John")
72     .setEmail("john@email.com")
73     .build();
74
75   private static TestIdentityProvider IDENTITY_PROVIDER = new TestIdentityProvider()
76     .setKey("github")
77     .setName("name of github")
78     .setEnabled(true)
79     .setAllowsUsersToSignUp(true);
80
81   private MapSettings settings = new MapSettings();
82
83   @Rule
84   public ExpectedException expectedException = ExpectedException.none();
85   @Rule
86   public DbTester db = DbTester.create(new AlwaysIncreasingSystem2());
87   @Rule
88   public EsTester es = EsTester.create();
89   private UserIndexer userIndexer = new UserIndexer(db.getDbClient(), es.client());
90   private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
91   private OrganizationUpdater organizationUpdater = mock(OrganizationUpdater.class);
92   private TestOrganizationFlags organizationFlags = TestOrganizationFlags.standalone();
93   private CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient());
94   private UserUpdater userUpdater = new UserUpdater(
95     system2,
96     mock(NewUserNotifier.class),
97     db.getDbClient(),
98     userIndexer,
99     organizationFlags,
100     defaultOrganizationProvider,
101     new DefaultGroupFinder(db.getDbClient()),
102     settings.asConfig(),
103     localAuthentication);
104
105   private DefaultGroupFinder defaultGroupFinder = new DefaultGroupFinder(db.getDbClient());
106
107   private UserRegistrarImpl underTest = new UserRegistrarImpl(db.getDbClient(), userUpdater, defaultOrganizationProvider, organizationFlags,
108     defaultGroupFinder, new MemberUpdater(db.getDbClient(), defaultGroupFinder, userIndexer));
109
110   @Test
111   public void authenticate_new_user() {
112     organizationFlags.setEnabled(true);
113
114     underTest.register(UserRegistration.builder()
115       .setUserIdentity(USER_IDENTITY)
116       .setProvider(IDENTITY_PROVIDER)
117       .setSource(Source.realm(BASIC, IDENTITY_PROVIDER.getName()))
118       .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
119       .build());
120
121     UserDto user = db.users().selectUserByLogin(USER_LOGIN).get();
122     assertThat(user).isNotNull();
123     assertThat(user.isActive()).isTrue();
124     assertThat(user.getName()).isEqualTo("John");
125     assertThat(user.getEmail()).isEqualTo("john@email.com");
126     assertThat(user.getExternalLogin()).isEqualTo("johndoo");
127     assertThat(user.getExternalIdentityProvider()).isEqualTo("github");
128     assertThat(user.getExternalId()).isEqualTo("ABCD");
129     assertThat(user.isRoot()).isFalse();
130     checkGroupMembership(user);
131   }
132
133   @Test
134   public void authenticate_new_user_generate_login_when_no_login_provided() {
135     organizationFlags.setEnabled(true);
136
137     underTest.register(UserRegistration.builder()
138       .setUserIdentity(UserIdentity.builder()
139         .setProviderId("ABCD")
140         .setProviderLogin("johndoo")
141         .setName("John Doe")
142         .setEmail("john@email.com")
143         .build())
144       .setProvider(IDENTITY_PROVIDER)
145       .setSource(Source.realm(BASIC, IDENTITY_PROVIDER.getName()))
146       .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
147       .build());
148
149     UserDto user = db.getDbClient().userDao().selectByEmail(db.getSession(), "john@email.com").get(0);
150     assertThat(user).isNotNull();
151     assertThat(user.isActive()).isTrue();
152     assertThat(user.getLogin()).isNotEqualTo("John Doe").startsWith("john-doe");
153     assertThat(user.getEmail()).isEqualTo("john@email.com");
154     assertThat(user.getExternalLogin()).isEqualTo("johndoo");
155     assertThat(user.getExternalIdentityProvider()).isEqualTo("github");
156     assertThat(user.getExternalId()).isEqualTo("ABCD");
157   }
158
159   @Test
160   public void authenticate_new_user_with_groups() {
161     organizationFlags.setEnabled(true);
162     GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
163     GroupDto group2 = db.users().insertGroup(db.getDefaultOrganization(), "group2");
164
165     authenticate(USER_LOGIN, "group1", "group2", "group3");
166
167     Optional<UserDto> user = db.users().selectUserByLogin(USER_LOGIN);
168     checkGroupMembership(user.get(), group1, group2);
169   }
170
171   @Test
172   public void authenticate_new_user_and_force_default_group_when_organizations_are_disabled() {
173     organizationFlags.setEnabled(false);
174     UserDto user = db.users().insertUser();
175     GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
176     GroupDto defaultGroup = insertDefaultGroup();
177     db.users().insertMember(group1, user);
178     db.users().insertMember(defaultGroup, user);
179
180     authenticate(user.getLogin(), "group1");
181
182     checkGroupMembership(user, group1, defaultGroup);
183   }
184
185   @Test
186   public void does_not_force_default_group_when_authenticating_new_user_if_organizations_are_enabled() {
187     organizationFlags.setEnabled(true);
188     UserDto user = db.users().insertUser();
189     GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
190     GroupDto defaultGroup = insertDefaultGroup();
191     db.users().insertMember(group1, user);
192     db.users().insertMember(defaultGroup, user);
193
194     authenticate(user.getLogin(), "group1");
195
196     checkGroupMembership(user, group1);
197   }
198
199   @Test
200   public void authenticate_new_user_sets_onboarded_flag_to_false_when_onboarding_setting_is_set_to_true() {
201     organizationFlags.setEnabled(true);
202     settings.setProperty(ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS.getKey(), true);
203
204     underTest.register(UserRegistration.builder()
205       .setUserIdentity(USER_IDENTITY)
206       .setProvider(IDENTITY_PROVIDER)
207       .setSource(Source.local(BASIC))
208       .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
209       .build());
210
211     assertThat(db.users().selectUserByLogin(USER_LOGIN).get().isOnboarded()).isFalse();
212   }
213
214   @Test
215   public void authenticate_new_user_sets_onboarded_flag_to_true_when_onboarding_setting_is_set_to_false() {
216     organizationFlags.setEnabled(true);
217     settings.setProperty(ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS.getKey(), false);
218
219     underTest.register(UserRegistration.builder()
220       .setUserIdentity(USER_IDENTITY)
221       .setProvider(IDENTITY_PROVIDER)
222       .setSource(Source.local(BASIC))
223       .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
224       .build());
225
226     assertThat(db.users().selectUserByLogin(USER_LOGIN).get().isOnboarded()).isTrue();
227   }
228
229   @Test
230   public void external_id_is_set_to_provider_login_when_null() {
231     organizationFlags.setEnabled(true);
232     UserIdentity newUser = UserIdentity.builder()
233       .setProviderId(null)
234       .setLogin("john")
235       .setProviderLogin("johndoo")
236       .setName("JOhn")
237       .build();
238
239     underTest.register(UserRegistration.builder()
240       .setUserIdentity(newUser)
241       .setProvider(IDENTITY_PROVIDER)
242       .setSource(Source.local(BASIC))
243       .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
244       .build());
245
246     assertThat(db.users().selectUserByLogin(newUser.getLogin()).get())
247       .extracting(UserDto::getLogin, UserDto::getExternalId, UserDto::getExternalLogin)
248       .contains("john", "johndoo", "johndoo");
249   }
250
251   @Test
252   public void authenticate_new_user_update_existing_user_email_when_strategy_is_ALLOW() {
253     organizationFlags.setEnabled(true);
254     UserDto existingUser = db.users().insertUser(u -> u.setEmail("john@email.com"));
255     UserIdentity newUser = UserIdentity.builder()
256       .setProviderLogin("johndoo")
257       .setLogin("new_login")
258       .setName(existingUser.getName())
259       .setEmail(existingUser.getEmail())
260       .build();
261
262     underTest.register(UserRegistration.builder()
263       .setUserIdentity(newUser)
264       .setProvider(IDENTITY_PROVIDER)
265       .setSource(Source.local(BASIC))
266       .setExistingEmailStrategy(ExistingEmailStrategy.ALLOW)
267       .build());
268
269     UserDto newUserReloaded = db.users().selectUserByLogin(newUser.getLogin()).get();
270     assertThat(newUserReloaded.getEmail()).isEqualTo(existingUser.getEmail());
271     UserDto existingUserReloaded = db.users().selectUserByLogin(existingUser.getLogin()).get();
272     assertThat(existingUserReloaded.getEmail()).isNull();
273   }
274
275   @Test
276   public void throw_EmailAlreadyExistException_when_authenticating_new_user_when_email_already_exists_and_strategy_is_WARN() {
277     organizationFlags.setEnabled(true);
278     UserDto existingUser = db.users().insertUser(u -> u.setEmail("john@email.com"));
279     UserIdentity newUser = UserIdentity.builder()
280       .setProviderLogin("johndoo")
281       .setLogin("new_login")
282       .setName(existingUser.getName())
283       .setEmail(existingUser.getEmail())
284       .build();
285
286     expectedException.expect(EmailAlreadyExistsRedirectionException.class);
287
288     underTest.register(UserRegistration.builder()
289       .setUserIdentity(newUser)
290       .setProvider(IDENTITY_PROVIDER)
291       .setSource(Source.local(BASIC))
292       .setExistingEmailStrategy(ExistingEmailStrategy.WARN)
293       .build());
294   }
295
296   @Test
297   public void throw_AuthenticationException_when_authenticating_new_user_when_email_already_exists_and_strategy_is_FORBID() {
298     db.users().insertUser(u -> u.setEmail("john@email.com"));
299     Source source = Source.realm(AuthenticationEvent.Method.FORM, IDENTITY_PROVIDER.getName());
300
301     expectedException.expect(authenticationException().from(source)
302       .withLogin(USER_IDENTITY.getProviderLogin())
303       .andPublicMessage("You can't sign up because email 'john@email.com' is already used by an existing user. " +
304         "This means that you probably already registered with another account."));
305     expectedException.expectMessage("Email 'john@email.com' is already used");
306
307     underTest.register(UserRegistration.builder()
308       .setUserIdentity(USER_IDENTITY)
309       .setProvider(IDENTITY_PROVIDER)
310       .setSource(source)
311       .setExistingEmailStrategy(FORBID)
312       .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
313       .build());
314   }
315
316   @Test
317   public void throw_AuthenticationException_when_authenticating_new_user_and_email_already_exists_multiple_times() {
318     db.users().insertUser(u -> u.setEmail("john@email.com"));
319     db.users().insertUser(u -> u.setEmail("john@email.com"));
320     Source source = Source.realm(AuthenticationEvent.Method.FORM, IDENTITY_PROVIDER.getName());
321
322     expectedException.expect(authenticationException().from(source)
323       .withLogin(USER_IDENTITY.getProviderLogin())
324       .andPublicMessage("You can't sign up because email 'john@email.com' is already used by an existing user. " +
325         "This means that you probably already registered with another account."));
326     expectedException.expectMessage("Email 'john@email.com' is already used");
327
328     underTest.register(UserRegistration.builder()
329       .setUserIdentity(USER_IDENTITY)
330       .setProvider(IDENTITY_PROVIDER)
331       .setSource(source)
332       .setExistingEmailStrategy(FORBID)
333       .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
334       .build());
335   }
336
337   @Test
338   public void fail_to_authenticate_new_user_when_allow_users_to_signup_is_false() {
339     TestIdentityProvider identityProvider = new TestIdentityProvider()
340       .setKey("github")
341       .setName("Github")
342       .setEnabled(true)
343       .setAllowsUsersToSignUp(false);
344     Source source = Source.realm(AuthenticationEvent.Method.FORM, identityProvider.getName());
345
346     expectedException.expect(authenticationException().from(source).withLogin(USER_IDENTITY.getProviderLogin()).andPublicMessage("'github' users are not allowed to sign up"));
347     expectedException.expectMessage("User signup disabled for provider 'github'");
348
349     underTest.register(UserRegistration.builder()
350       .setUserIdentity(USER_IDENTITY)
351       .setProvider(identityProvider)
352       .setSource(source)
353       .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
354       .build());
355   }
356
357   @Test
358   public void authenticate_and_update_existing_user_matching_login() {
359     db.users().insertUser(u -> u
360       .setLogin(USER_LOGIN)
361       .setName("Old name")
362       .setEmail("Old email")
363       .setExternalId("old id")
364       .setExternalLogin("old identity")
365       .setExternalIdentityProvider("old provide"));
366
367     underTest.register(UserRegistration.builder()
368       .setUserIdentity(USER_IDENTITY)
369       .setProvider(IDENTITY_PROVIDER)
370       .setSource(Source.local(BASIC))
371       .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
372       .build());
373
374     assertThat(db.users().selectUserByLogin(USER_LOGIN).get())
375       .extracting(UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider, UserDto::isActive)
376       .contains("John", "john@email.com", "ABCD", "johndoo", "github", true);
377   }
378
379   @Test
380   public void authenticate_and_update_existing_user_matching_external_id() {
381     UserDto user = db.users().insertUser(u -> u
382       .setLogin("Old login")
383       .setName("Old name")
384       .setEmail("Old email")
385       .setExternalId(USER_IDENTITY.getProviderId())
386       .setExternalLogin("old identity")
387       .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
388
389     underTest.register(UserRegistration.builder()
390       .setUserIdentity(USER_IDENTITY)
391       .setProvider(IDENTITY_PROVIDER)
392       .setSource(Source.local(BASIC))
393       .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
394       .build());
395
396     assertThat(db.users().selectUserByLogin("Old login")).isNotPresent();
397     assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
398       .extracting(UserDto::getLogin, UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider,
399         UserDto::isActive)
400       .contains(USER_LOGIN, "John", "john@email.com", "ABCD", "johndoo", "github", true);
401   }
402
403   @Test
404   public void authenticate_and_update_existing_user_matching_external_login() {
405     UserDto user = db.users().insertUser(u -> u
406       .setLogin("Old login")
407       .setName("Old name")
408       .setEmail(USER_IDENTITY.getEmail())
409       .setExternalId("Old id")
410       .setExternalLogin(USER_IDENTITY.getProviderLogin())
411       .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
412
413     underTest.register(UserRegistration.builder()
414       .setUserIdentity(USER_IDENTITY)
415       .setProvider(IDENTITY_PROVIDER)
416       .setSource(Source.local(BASIC))
417       .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
418       .build());
419
420     assertThat(db.users().selectUserByLogin("Old login")).isNotPresent();
421     assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
422       .extracting(UserDto::getLogin, UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider,
423         UserDto::isActive)
424       .contains(USER_LOGIN, "John", "john@email.com", "ABCD", "johndoo", "github", true);
425   }
426
427   @Test
428   public void authenticate_existing_user_and_update_only_login() {
429     UserDto user = db.users().insertUser(u -> u
430       .setLogin("old login")
431       .setName(USER_IDENTITY.getName())
432       .setEmail(USER_IDENTITY.getEmail())
433       .setExternalId(USER_IDENTITY.getProviderId())
434       .setExternalLogin("old identity")
435       .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
436
437     underTest.register(UserRegistration.builder()
438       .setUserIdentity(USER_IDENTITY)
439       .setProvider(IDENTITY_PROVIDER)
440       .setSource(Source.local(BASIC))
441       .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
442       .build());
443
444     assertThat(db.users().selectUserByLogin("Old login")).isNotPresent();
445     assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
446       .extracting(UserDto::getLogin, UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider,
447         UserDto::isActive)
448       .containsExactlyInAnyOrder(USER_LOGIN, USER_IDENTITY.getName(), USER_IDENTITY.getEmail(), USER_IDENTITY.getProviderId(), USER_IDENTITY.getProviderLogin(),
449         IDENTITY_PROVIDER.getKey(),
450         true);
451   }
452
453   @Test
454   public void authenticate_existing_user_and_update_only_identity_provider_key() {
455     UserDto user = db.users().insertUser(u -> u
456       .setLogin(USER_LOGIN)
457       .setName(USER_IDENTITY.getName())
458       .setEmail(USER_IDENTITY.getEmail())
459       .setExternalId(USER_IDENTITY.getProviderId())
460       .setExternalLogin(USER_IDENTITY.getProviderLogin())
461       .setExternalIdentityProvider("old identity provider"));
462
463     underTest.register(UserRegistration.builder()
464       .setUserIdentity(USER_IDENTITY)
465       .setProvider(IDENTITY_PROVIDER)
466       .setSource(Source.local(BASIC))
467       .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
468       .build());
469
470     assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
471       .extracting(UserDto::getLogin, UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider,
472         UserDto::isActive)
473       .containsExactlyInAnyOrder(USER_LOGIN, USER_IDENTITY.getName(), USER_IDENTITY.getEmail(), USER_IDENTITY.getProviderId(), USER_IDENTITY.getProviderLogin(),
474         IDENTITY_PROVIDER.getKey(),
475         true);
476   }
477
478   @Test
479   public void authenticate_existing_user_matching_login_when_external_id_is_null() {
480     UserDto user = db.users().insertUser(u -> u
481       .setLogin(USER_LOGIN)
482       .setName("Old name")
483       .setEmail("Old email")
484       .setExternalId("Old id")
485       .setExternalLogin("old identity")
486       .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
487
488     underTest.register(UserRegistration.builder()
489       .setUserIdentity(UserIdentity.builder()
490         .setProviderId(null)
491         .setProviderLogin("johndoo")
492         .setLogin(USER_LOGIN)
493         .setName("John")
494         .setEmail("john@email.com")
495         .build())
496       .setProvider(IDENTITY_PROVIDER)
497       .setSource(Source.local(BASIC))
498       .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
499       .build());
500
501     assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
502       .extracting(UserDto::getLogin, UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider,
503         UserDto::isActive)
504       .contains(user.getLogin(), "John", "john@email.com", "johndoo", "johndoo", "github", true);
505   }
506
507   @Test
508   public void authenticate_existing_user_when_login_is_not_provided() {
509     UserDto user = db.users().insertUser(u -> u.setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
510
511     underTest.register(UserRegistration.builder()
512       .setUserIdentity(UserIdentity.builder()
513         .setProviderId(user.getExternalId())
514         .setProviderLogin(user.getExternalLogin())
515         // No login provided
516         .setName(user.getName())
517         .setEmail(user.getEmail())
518         .build())
519       .setProvider(IDENTITY_PROVIDER)
520       .setSource(Source.local(BASIC))
521       .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
522       .build());
523
524     // No new user is created
525     assertThat(db.countRowsOfTable(db.getSession(), "users")).isEqualTo(1);
526     assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
527       .extracting(UserDto::getLogin, UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider,
528         UserDto::isActive)
529       .contains(user.getLogin(), user.getName(), user.getEmail(), user.getExternalId(), user.getExternalLogin(), user.getExternalIdentityProvider(), true);
530   }
531
532   @Test
533   public void authenticate_existing_user_with_login_update_and_strategy_is_ALLOW() {
534     UserDto user = db.users().insertUser(u -> u
535       .setLogin("Old login")
536       .setExternalId(USER_IDENTITY.getProviderId())
537       .setExternalLogin("old identity")
538       .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
539
540     underTest.register(UserRegistration.builder()
541       .setUserIdentity(USER_IDENTITY)
542       .setProvider(IDENTITY_PROVIDER)
543       .setSource(Source.local(BASIC))
544       .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
545       .build());
546
547     assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
548       .extracting(UserDto::getLogin, UserDto::getExternalLogin)
549       .contains(USER_LOGIN, USER_IDENTITY.getProviderLogin());
550   }
551
552   @Test
553   public void authenticate_existing_disabled_user() {
554     organizationFlags.setEnabled(true);
555     db.users().insertUser(u -> u
556       .setLogin(USER_LOGIN)
557       .setActive(false)
558       .setName("Old name")
559       .setEmail("Old email")
560       .setExternalId("old id")
561       .setExternalLogin("old identity")
562       .setExternalIdentityProvider("old provide"));
563
564     underTest.register(UserRegistration.builder()
565       .setUserIdentity(USER_IDENTITY)
566       .setProvider(IDENTITY_PROVIDER)
567       .setSource(Source.local(BASIC))
568       .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
569       .build());
570
571     UserDto userDto = db.users().selectUserByLogin(USER_LOGIN).get();
572     assertThat(userDto.isActive()).isTrue();
573     assertThat(userDto.getName()).isEqualTo("John");
574     assertThat(userDto.getEmail()).isEqualTo("john@email.com");
575     assertThat(userDto.getExternalId()).isEqualTo("ABCD");
576     assertThat(userDto.getExternalLogin()).isEqualTo("johndoo");
577     assertThat(userDto.getExternalIdentityProvider()).isEqualTo("github");
578     assertThat(userDto.isRoot()).isFalse();
579   }
580
581   @Test
582   public void authenticate_existing_user_when_email_already_exists_and_strategy_is_ALLOW() {
583     organizationFlags.setEnabled(true);
584     UserDto existingUser = db.users().insertUser(u -> u.setEmail("john@email.com"));
585     UserDto currentUser = db.users().insertUser(u -> u.setEmail(null));
586     UserIdentity userIdentity = UserIdentity.builder()
587       .setLogin(currentUser.getLogin())
588       .setProviderLogin("johndoo")
589       .setName("John")
590       .setEmail("john@email.com")
591       .build();
592
593     underTest.register(UserRegistration.builder()
594       .setUserIdentity(userIdentity)
595       .setProvider(IDENTITY_PROVIDER)
596       .setSource(Source.local(BASIC))
597       .setExistingEmailStrategy(ExistingEmailStrategy.ALLOW)
598       .build());
599
600     UserDto currentUserReloaded = db.users().selectUserByLogin(currentUser.getLogin()).get();
601     assertThat(currentUserReloaded.getEmail()).isEqualTo("john@email.com");
602     UserDto existingUserReloaded = db.users().selectUserByLogin(existingUser.getLogin()).get();
603     assertThat(existingUserReloaded.getEmail()).isNull();
604   }
605
606   @Test
607   public void throw_EmailAlreadyExistException_when_authenticating_existing_user_when_email_already_exists_and_strategy_is_WARN() {
608     organizationFlags.setEnabled(true);
609     UserDto existingUser = db.users().insertUser(u -> u.setEmail("john@email.com"));
610     UserDto currentUser = db.users().insertUser(u -> u.setEmail(null));
611     UserIdentity userIdentity = UserIdentity.builder()
612       .setLogin(currentUser.getLogin())
613       .setProviderLogin("johndoo")
614       .setName("John")
615       .setEmail("john@email.com")
616       .build();
617
618     expectedException.expect(EmailAlreadyExistsRedirectionException.class);
619
620     underTest.register(UserRegistration.builder()
621       .setUserIdentity(userIdentity)
622       .setProvider(IDENTITY_PROVIDER)
623       .setSource(Source.local(BASIC))
624       .setExistingEmailStrategy(ExistingEmailStrategy.WARN)
625       .build());
626   }
627
628   @Test
629   public void throw_AuthenticationException_when_authenticating_existing_user_when_email_already_exists_and_strategy_is_FORBID() {
630     organizationFlags.setEnabled(true);
631     UserDto existingUser = db.users().insertUser(u -> u.setEmail("john@email.com"));
632     UserDto currentUser = db.users().insertUser(u -> u.setEmail(null));
633     UserIdentity userIdentity = UserIdentity.builder()
634       .setLogin(currentUser.getLogin())
635       .setProviderLogin("johndoo")
636       .setName("John")
637       .setEmail("john@email.com")
638       .build();
639
640     expectedException.expect(authenticationException().from(Source.realm(AuthenticationEvent.Method.FORM, IDENTITY_PROVIDER.getName()))
641       .withLogin(userIdentity.getProviderLogin())
642       .andPublicMessage("You can't sign up because email 'john@email.com' is already used by an existing user. " +
643         "This means that you probably already registered with another account."));
644     expectedException.expectMessage("Email 'john@email.com' is already used");
645
646     underTest.register(UserRegistration.builder()
647       .setUserIdentity(userIdentity)
648       .setProvider(IDENTITY_PROVIDER)
649       .setSource(Source.realm(AuthenticationEvent.Method.FORM, IDENTITY_PROVIDER.getName()))
650       .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
651       .build());
652   }
653
654   @Test
655   public void does_not_fail_to_authenticate_user_when_email_has_not_changed_and_strategy_is_FORBID() {
656     organizationFlags.setEnabled(true);
657     UserDto currentUser = db.users().insertUser(u -> u.setEmail("john@email.com")
658       .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
659     UserIdentity userIdentity = UserIdentity.builder()
660       .setLogin(currentUser.getLogin())
661       .setProviderId(currentUser.getExternalId())
662       .setProviderLogin(currentUser.getExternalLogin())
663       .setName("John")
664       .setEmail("john@email.com")
665       .build();
666
667     underTest.register(UserRegistration.builder()
668       .setUserIdentity(userIdentity)
669       .setProvider(IDENTITY_PROVIDER)
670       .setSource(Source.local(BASIC))
671       .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
672       .build());
673
674     UserDto currentUserReloaded = db.users().selectUserByLogin(currentUser.getLogin()).get();
675     assertThat(currentUserReloaded.getEmail()).isEqualTo("john@email.com");
676   }
677
678   @Test
679   public void authenticate_existing_user_and_add_new_groups() {
680     organizationFlags.setEnabled(true);
681     UserDto user = db.users().insertUser(newUserDto()
682       .setLogin(USER_LOGIN)
683       .setActive(true)
684       .setName("John"));
685     GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
686     GroupDto group2 = db.users().insertGroup(db.getDefaultOrganization(), "group2");
687
688     authenticate(USER_LOGIN, "group1", "group2", "group3");
689
690     checkGroupMembership(user, group1, group2);
691   }
692
693   @Test
694   public void authenticate_existing_user_and_remove_groups() {
695     organizationFlags.setEnabled(true);
696     UserDto user = db.users().insertUser(newUserDto()
697       .setLogin(USER_LOGIN)
698       .setActive(true)
699       .setName("John"));
700     GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
701     GroupDto group2 = db.users().insertGroup(db.getDefaultOrganization(), "group2");
702     db.users().insertMember(group1, user);
703     db.users().insertMember(group2, user);
704
705     authenticate(USER_LOGIN, "group1");
706
707     checkGroupMembership(user, group1);
708   }
709
710   @Test
711   public void authenticate_existing_user_and_remove_all_groups_expect_default_when_organizations_are_disabled() {
712     organizationFlags.setEnabled(false);
713     UserDto user = db.users().insertUser();
714     GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
715     GroupDto group2 = db.users().insertGroup(db.getDefaultOrganization(), "group2");
716     GroupDto defaultGroup = insertDefaultGroup();
717     db.users().insertMember(group1, user);
718     db.users().insertMember(group2, user);
719     db.users().insertMember(defaultGroup, user);
720
721     authenticate(user.getLogin());
722
723     checkGroupMembership(user, defaultGroup);
724   }
725
726   @Test
727   public void does_not_force_default_group_when_authenticating_existing_user_when_organizations_are_enabled() {
728     organizationFlags.setEnabled(true);
729     UserDto user = db.users().insertUser();
730     GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
731     GroupDto defaultGroup = insertDefaultGroup();
732     db.users().insertMember(group1, user);
733     db.users().insertMember(defaultGroup, user);
734
735     authenticate(user.getLogin(), "group1");
736
737     checkGroupMembership(user, group1);
738   }
739
740   @Test
741   public void ignore_groups_on_non_default_organizations() {
742     organizationFlags.setEnabled(true);
743     OrganizationDto org = db.organizations().insert();
744     UserDto user = db.users().insertUser(newUserDto()
745       .setLogin(USER_LOGIN)
746       .setActive(true)
747       .setName("John"));
748     String groupName = "a-group";
749     GroupDto groupInDefaultOrg = db.users().insertGroup(db.getDefaultOrganization(), groupName);
750     GroupDto groupInOrg = db.users().insertGroup(org, groupName);
751
752     // adding a group with the same name than in non-default organization
753     underTest.register(UserRegistration.builder()
754       .setUserIdentity(UserIdentity.builder()
755         .setProviderLogin("johndoo")
756         .setLogin(user.getLogin())
757         .setName(user.getName())
758         .setGroups(newHashSet(groupName))
759         .build())
760       .setProvider(IDENTITY_PROVIDER)
761       .setSource(Source.local(BASIC))
762       .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
763       .build());
764
765     checkGroupMembership(user, groupInDefaultOrg);
766   }
767
768   private void authenticate(String login, String... groups) {
769     underTest.register(UserRegistration.builder()
770       .setUserIdentity(UserIdentity.builder()
771         .setProviderLogin("johndoo")
772         .setLogin(login)
773         .setName("John")
774         // No group
775         .setGroups(stream(groups).collect(MoreCollectors.toSet()))
776         .build())
777       .setProvider(IDENTITY_PROVIDER)
778       .setSource(Source.local(BASIC))
779       .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
780       .build());
781   }
782
783   private void checkGroupMembership(UserDto user, GroupDto... expectedGroups) {
784     assertThat(db.users().selectGroupIdsOfUser(user)).containsOnly(stream(expectedGroups).map(GroupDto::getId).collect(Collectors.toList()).toArray(new Integer[] {}));
785   }
786
787   private GroupDto insertDefaultGroup() {
788     return db.users().insertDefaultGroup(db.getDefaultOrganization(), "sonar-users");
789   }
790
791 }