]> source.dussan.org Git - sonarqube.git/blob
51d31dc2baf4b6951d0acbba10b5617105fedb9e
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2016 SonarSource SA
4  * mailto:contact 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 static com.google.common.collect.Sets.newHashSet;
23 import static java.util.Collections.singletonList;
24 import static org.assertj.core.api.Assertions.assertThat;
25 import static org.mockito.Mockito.mock;
26
27 import java.util.Collections;
28 import java.util.HashSet;
29 import java.util.Set;
30 import javax.servlet.http.HttpServletRequest;
31 import javax.servlet.http.HttpServletResponse;
32 import org.junit.Before;
33 import org.junit.Rule;
34 import org.junit.Test;
35 import org.junit.rules.ExpectedException;
36 import org.sonar.api.config.Settings;
37 import org.sonar.api.server.authentication.UnauthorizedException;
38 import org.sonar.api.server.authentication.UserIdentity;
39 import org.sonar.api.utils.System2;
40 import org.sonar.db.DbClient;
41 import org.sonar.db.DbSession;
42 import org.sonar.db.DbTester;
43 import org.sonar.db.user.GroupDao;
44 import org.sonar.db.user.GroupDto;
45 import org.sonar.db.user.UserDao;
46 import org.sonar.db.user.UserDto;
47 import org.sonar.db.user.UserGroupDto;
48 import org.sonar.db.user.UserTesting;
49 import org.sonar.server.user.NewUserNotifier;
50 import org.sonar.server.user.UserUpdater;
51 import org.sonar.server.user.index.UserIndexer;
52
53 public class UserIdentityAuthenticatorTest {
54
55   static String USER_LOGIN = "github-johndoo";
56
57   static String DEFAULT_GROUP = "default";
58
59   static UserIdentity USER_IDENTITY = UserIdentity.builder()
60     .setProviderLogin("johndoo")
61     .setLogin(USER_LOGIN)
62     .setName("John")
63     .setEmail("john@email.com")
64     .build();
65
66   static TestIdentityProvider IDENTITY_PROVIDER = new TestIdentityProvider()
67     .setKey("github")
68     .setEnabled(true)
69     .setAllowsUsersToSignUp(true);
70
71   @Rule
72   public ExpectedException thrown = ExpectedException.none();
73
74   System2 system2 = mock(System2.class);
75
76   @Rule
77   public DbTester dbTester = DbTester.create(system2);
78
79   DbClient dbClient = dbTester.getDbClient();
80   DbSession dbSession = dbTester.getSession();
81   UserDao userDao = dbClient.userDao();
82   GroupDao groupDao = dbClient.groupDao();
83   Settings settings = new Settings();
84
85   HttpServletRequest request = mock(HttpServletRequest.class);
86   HttpServletResponse response = mock(HttpServletResponse.class);
87
88   UserUpdater userUpdater = new UserUpdater(
89     mock(NewUserNotifier.class),
90     settings,
91     dbClient,
92     mock(UserIndexer.class),
93     system2);
94
95   UserIdentityAuthenticator underTest = new UserIdentityAuthenticator(dbClient, userUpdater);
96
97   @Before
98   public void setUp() throws Exception {
99     settings.setProperty("sonar.defaultGroup", DEFAULT_GROUP);
100     addGroup(DEFAULT_GROUP);
101   }
102
103   @Test
104   public void authenticate_new_user() throws Exception {
105     underTest.authenticate(USER_IDENTITY, IDENTITY_PROVIDER);
106     dbSession.commit();
107
108     UserDto userDto = userDao.selectByLogin(dbSession, USER_LOGIN);
109     assertThat(userDto).isNotNull();
110     assertThat(userDto.isActive()).isTrue();
111     assertThat(userDto.getName()).isEqualTo("John");
112     assertThat(userDto.getEmail()).isEqualTo("john@email.com");
113     assertThat(userDto.getExternalIdentity()).isEqualTo("johndoo");
114     assertThat(userDto.getExternalIdentityProvider()).isEqualTo("github");
115
116     verifyUserGroups(USER_LOGIN, DEFAULT_GROUP);
117   }
118
119   @Test
120   public void authenticate_new_user_with_groups() throws Exception {
121     addGroup("group1");
122     addGroup("group2");
123
124     underTest.authenticate(UserIdentity.builder()
125       .setProviderLogin("johndoo")
126       .setLogin(USER_LOGIN)
127       .setName("John")
128       // group3 doesn't exist in db, it will be ignored
129       .setGroups(newHashSet("group1", "group2", "group3"))
130       .build(), IDENTITY_PROVIDER);
131     dbSession.commit();
132
133     UserDto userDto = userDao.selectByLogin(dbSession, USER_LOGIN);
134     assertThat(userDto).isNotNull();
135
136     verifyUserGroups(USER_LOGIN, "group1", "group2");
137   }
138
139   @Test
140   public void authenticate_existing_user() throws Exception {
141     userDao.insert(dbSession, new UserDto()
142       .setLogin(USER_LOGIN)
143       .setActive(true)
144       .setName("Old name")
145       .setEmail("Old email")
146       .setExternalIdentity("old identity")
147       .setExternalIdentityProvider("old provide"));
148     dbSession.commit();
149
150     underTest.authenticate(USER_IDENTITY, IDENTITY_PROVIDER);
151     dbSession.commit();
152
153     UserDto userDto = userDao.selectByLogin(dbSession, USER_LOGIN);
154     assertThat(userDto).isNotNull();
155     assertThat(userDto.isActive()).isTrue();
156     assertThat(userDto.getName()).isEqualTo("John");
157     assertThat(userDto.getEmail()).isEqualTo("john@email.com");
158     assertThat(userDto.getExternalIdentity()).isEqualTo("johndoo");
159     assertThat(userDto.getExternalIdentityProvider()).isEqualTo("github");
160   }
161
162   @Test
163   public void authenticate_existing_disabled_user() throws Exception {
164     userDao.insert(dbSession, new UserDto()
165       .setLogin(USER_LOGIN)
166       .setActive(false)
167       .setName("Old name")
168       .setEmail("Old email")
169       .setExternalIdentity("old identity")
170       .setExternalIdentityProvider("old provide"));
171     dbSession.commit();
172
173     underTest.authenticate(USER_IDENTITY, IDENTITY_PROVIDER);
174     dbSession.commit();
175
176     UserDto userDto = userDao.selectByLogin(dbSession, USER_LOGIN);
177     assertThat(userDto).isNotNull();
178     assertThat(userDto.isActive()).isTrue();
179     assertThat(userDto.getName()).isEqualTo("John");
180     assertThat(userDto.getEmail()).isEqualTo("john@email.com");
181     assertThat(userDto.getExternalIdentity()).isEqualTo("johndoo");
182     assertThat(userDto.getExternalIdentityProvider()).isEqualTo("github");
183   }
184
185   @Test
186   public void authenticate_existing_user_and_add_new_groups() throws Exception {
187     userDao.insert(dbSession, new UserDto()
188       .setLogin(USER_LOGIN)
189       .setActive(true)
190       .setName("John"));
191     addGroup("group1");
192     addGroup("group2");
193     dbSession.commit();
194
195     underTest.authenticate(UserIdentity.builder()
196       .setProviderLogin("johndoo")
197       .setLogin(USER_LOGIN)
198       .setName("John")
199       // group3 doesn't exist in db, it will be ignored
200       .setGroups(newHashSet("group1", "group2", "group3"))
201       .build(), IDENTITY_PROVIDER);
202     dbSession.commit();
203
204     Set<String> userGroups = new HashSet<>(dbClient.groupMembershipDao().selectGroupsByLogins(dbSession, singletonList(USER_LOGIN)).get(USER_LOGIN));
205     assertThat(userGroups).containsOnly("group1", "group2");
206   }
207
208   @Test
209   public void authenticate_existing_user_and_remove_groups() throws Exception {
210     UserDto user = new UserDto()
211       .setLogin(USER_LOGIN)
212       .setActive(true)
213       .setName("John");
214     userDao.insert(dbSession, user);
215
216     GroupDto group1 = addGroup("group1");
217     GroupDto group2 = addGroup("group2");
218     dbClient.userGroupDao().insert(dbSession, new UserGroupDto().setUserId(user.getId()).setGroupId(group1.getId()));
219     dbClient.userGroupDao().insert(dbSession, new UserGroupDto().setUserId(user.getId()).setGroupId(group2.getId()));
220     dbSession.commit();
221
222     Set<String> userGroups = new HashSet<>(dbClient.groupMembershipDao().selectGroupsByLogins(dbSession, singletonList(USER_LOGIN)).get(USER_LOGIN));
223     assertThat(userGroups).containsOnly("group1", "group2");
224
225     underTest.authenticate(UserIdentity.builder()
226       .setProviderLogin("johndoo")
227       .setLogin(USER_LOGIN)
228       .setName("John")
229       // Only group1 is returned by the id provider => group2 will be removed
230       .setGroups(newHashSet("group1"))
231       .build(), IDENTITY_PROVIDER);
232     dbSession.commit();
233
234     verifyUserGroups(USER_LOGIN, "group1");
235   }
236
237   @Test
238   public void authenticate_existing_user_and_remove_all_groups() throws Exception {
239     UserDto user = new UserDto()
240       .setLogin(USER_LOGIN)
241       .setActive(true)
242       .setName("John");
243     userDao.insert(dbSession, user);
244
245     GroupDto group1 = addGroup("group1");
246     GroupDto group2 = addGroup("group2");
247     dbClient.userGroupDao().insert(dbSession, new UserGroupDto().setUserId(user.getId()).setGroupId(group1.getId()));
248     dbClient.userGroupDao().insert(dbSession, new UserGroupDto().setUserId(user.getId()).setGroupId(group2.getId()));
249     dbSession.commit();
250
251     Set<String> userGroups = new HashSet<>(dbClient.groupMembershipDao().selectGroupsByLogins(dbSession, singletonList(USER_LOGIN)).get(USER_LOGIN));
252     assertThat(userGroups).containsOnly("group1", "group2");
253
254     underTest.authenticate(UserIdentity.builder()
255       .setProviderLogin("johndoo")
256       .setLogin(USER_LOGIN)
257       .setName("John")
258       // No group => group1 and group2 will be removed
259       .setGroups(Collections.<String>emptySet())
260       .build(), IDENTITY_PROVIDER);
261     dbSession.commit();
262
263     verifyNoUserGroups(USER_LOGIN);
264   }
265
266   @Test
267   public void fail_to_authenticate_new_user_when_allow_users_to_signup_is_false() throws Exception {
268     TestIdentityProvider identityProvider = new TestIdentityProvider()
269       .setKey("github")
270       .setName("Github")
271       .setEnabled(true)
272       .setAllowsUsersToSignUp(false);
273
274     thrown.expect(UnauthorizedException.class);
275     thrown.expectMessage("'github' users are not allowed to sign up");
276     underTest.authenticate(USER_IDENTITY, identityProvider);
277   }
278
279   @Test
280   public void fail_to_authenticate_new_user_when_email_already_exists() throws Exception {
281     UserDto userDto = UserTesting.newUserDto()
282       .setLogin("Existing user with same email")
283       .setActive(true)
284       .setEmail("john@email.com");
285     userDao.insert(dbSession, userDto);
286     dbSession.commit();
287
288     thrown.expect(UnauthorizedException.class);
289     thrown.expectMessage("You can't sign up because email 'john@email.com' is already used by an existing user. " +
290       "This means that you probably already registered with another account.");
291     underTest.authenticate(USER_IDENTITY, IDENTITY_PROVIDER);
292   }
293
294   private void verifyUserGroups(String userLogin, String... groups) {
295     Set<String> userGroups = new HashSet<>(dbClient.groupMembershipDao().selectGroupsByLogins(dbSession, singletonList(USER_LOGIN)).get(userLogin));
296     assertThat(userGroups).containsOnly(groups);
297   }
298
299   private void verifyNoUserGroups(String userLogin) {
300     Set<String> userGroups = new HashSet<>(dbClient.groupMembershipDao().selectGroupsByLogins(dbSession, singletonList(USER_LOGIN)).get(userLogin));
301     assertThat(userGroups).isEmpty();
302   }
303
304   private GroupDto addGroup(String name) {
305     GroupDto group = new GroupDto().setName(name);
306     groupDao.insert(dbSession, group);
307     dbSession.commit();
308     return group;
309   }
310 }