3 * Copyright (C) 2009-2023 SonarSource SA
4 * mailto:info AT sonarsource DOT com
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.
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.
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.
20 package org.sonar.server.user.ws;
22 import org.junit.Rule;
23 import org.junit.Test;
24 import org.sonar.api.config.internal.MapSettings;
25 import org.sonar.auth.ldap.LdapSettingsManager;
26 import org.sonar.db.DbClient;
27 import org.sonar.db.DbSession;
28 import org.sonar.db.DbTester;
29 import org.sonar.db.user.UserDto;
30 import org.sonar.server.authentication.CredentialsLocalAuthentication;
31 import org.sonar.server.authentication.IdentityProviderRepositoryRule;
32 import org.sonar.server.authentication.TestIdentityProvider;
33 import org.sonar.server.es.EsTester;
34 import org.sonar.server.exceptions.ForbiddenException;
35 import org.sonar.server.exceptions.NotFoundException;
36 import org.sonar.server.exceptions.UnauthorizedException;
37 import org.sonar.server.tester.UserSessionRule;
38 import org.sonar.server.user.NewUserNotifier;
39 import org.sonar.server.user.UserUpdater;
40 import org.sonar.server.user.index.UserIndexer;
41 import org.sonar.server.usergroups.DefaultGroupFinder;
42 import org.sonar.server.ws.TestRequest;
43 import org.sonar.server.ws.WsActionTester;
45 import static com.google.common.collect.Lists.newArrayList;
46 import static org.assertj.core.api.Assertions.assertThat;
47 import static org.assertj.core.api.Assertions.assertThatThrownBy;
48 import static org.mockito.Mockito.mock;
49 import static org.sonar.db.user.UserTesting.newUserDto;
51 public class UpdateIdentityProviderActionIT {
52 private final static String SQ_AUTHORITY = "sonarqube";
55 public IdentityProviderRepositoryRule identityProviderRepository = new IdentityProviderRepositoryRule()
56 .addIdentityProvider(new TestIdentityProvider().setName("Gitlab").setKey("gitlab").setEnabled(true))
57 .addIdentityProvider(new TestIdentityProvider().setName("Github").setKey("github").setEnabled(true));
60 public DbTester db = DbTester.create();
62 public EsTester es = EsTester.create();
64 public UserSessionRule userSession = UserSessionRule.standalone().logIn().setSystemAdministrator();
66 private final MapSettings settings = new MapSettings().setProperty("sonar.internal.pbkdf2.iterations", "1");
67 private final DbClient dbClient = db.getDbClient();
68 private final DbSession dbSession = db.getSession();
69 private final UserIndexer userIndexer = new UserIndexer(dbClient, es.client());
70 private final CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(dbClient, settings.asConfig());
72 private final LdapSettingsManager ldapSettingsManager = mock(LdapSettingsManager.class);
74 private final WsActionTester underTest = new WsActionTester(new UpdateIdentityProviderAction(dbClient, identityProviderRepository,
75 new UserUpdater(mock(NewUserNotifier.class), dbClient, userIndexer, new DefaultGroupFinder(db.getDbClient()), settings.asConfig(), null, localAuthentication),
79 public void change_identity_provider_of_a_local_user_all_params() {
80 String userLogin = "login-1";
81 String newExternalLogin = "login@github.com";
82 String newExternalIdentityProvider = "github";
83 createUser(true, userLogin, userLogin, SQ_AUTHORITY);
84 TestRequest request = underTest.newRequest()
85 .setParam("login", userLogin)
86 .setParam("newExternalProvider", newExternalIdentityProvider)
87 .setParam("newExternalIdentity", newExternalLogin);
90 assertThat(dbClient.userDao().selectByExternalLoginAndIdentityProvider(dbSession, newExternalLogin, newExternalIdentityProvider))
92 .extracting(UserDto::isLocal, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider)
93 .contains(false, newExternalLogin, newExternalIdentityProvider);
97 public void change_identity_provider_of_a_local_user_mandatory_params_only_provider_login_stays_same() {
98 String userLogin = "login-1";
99 String newExternalIdentityProvider = "github";
100 createUser(true, userLogin, userLogin, SQ_AUTHORITY);
101 TestRequest request = underTest.newRequest()
102 .setParam("login", userLogin)
103 .setParam("newExternalProvider", newExternalIdentityProvider);
106 assertThat(dbClient.userDao().selectByExternalLoginAndIdentityProvider(dbSession, userLogin, newExternalIdentityProvider))
108 .extracting(UserDto::isLocal, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider)
109 .contains(false, userLogin, newExternalIdentityProvider);
113 public void change_identity_provider_of_a_external_user_to_new_one() {
114 String userLogin = "login-1";
115 String oldExternalIdentityProvider = "gitlab";
116 String oldExternalIdentity = "john@gitlab.com";
117 createUser(false, userLogin, oldExternalIdentity, oldExternalIdentityProvider);
119 String newExternalIdentityProvider = "github";
120 String newExternalIdentity = "john@github.com";
121 TestRequest request = underTest.newRequest()
122 .setParam("login", userLogin)
123 .setParam("newExternalProvider", newExternalIdentityProvider)
124 .setParam("newExternalIdentity", newExternalIdentity);
127 assertThat(dbClient.userDao().selectByExternalLoginAndIdentityProvider(dbSession, newExternalIdentity, newExternalIdentityProvider))
129 .extracting(UserDto::isLocal, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider)
130 .contains(false, newExternalIdentity, newExternalIdentityProvider);
134 public void change_identity_provider_of_a_local_user_to_ldap_default_using_sonarqube_as_parameter() {
135 String userLogin = "login-1";
136 String newExternalIdentityProvider = "LDAP_default";
137 createUser(true, userLogin, userLogin, SQ_AUTHORITY);
138 TestRequest request = underTest.newRequest()
139 .setParam("login", userLogin)
140 .setParam("newExternalProvider", "sonarqube");
143 assertThat(dbClient.userDao().selectByExternalLoginAndIdentityProvider(dbSession, userLogin, newExternalIdentityProvider))
145 .extracting(UserDto::isLocal, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider)
146 .contains(false, userLogin, newExternalIdentityProvider);
150 public void change_identity_provider_of_a_local_user_to_ldap_default_using_ldap_as_parameter() {
151 String userLogin = "login-1";
152 String newExternalIdentityProvider = "LDAP_default";
153 createUser(true, userLogin, userLogin, SQ_AUTHORITY);
154 TestRequest request = underTest.newRequest()
155 .setParam("login", userLogin)
156 .setParam("newExternalProvider", "LDAP");
159 assertThat(dbClient.userDao().selectByExternalLoginAndIdentityProvider(dbSession, userLogin, newExternalIdentityProvider))
161 .extracting(UserDto::isLocal, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider)
162 .contains(false, userLogin, newExternalIdentityProvider);
166 public void change_identity_provider_of_a_local_user_to_ldap_default_using_ldap_server_key_as_parameter() {
167 String userLogin = "login-1";
168 String newExternalIdentityProvider = "LDAP_server42";
169 createUser(true, userLogin, userLogin, SQ_AUTHORITY);
170 TestRequest request = underTest.newRequest()
171 .setParam("login", userLogin)
172 .setParam("newExternalProvider", newExternalIdentityProvider);
175 assertThat(dbClient.userDao().selectByExternalLoginAndIdentityProvider(dbSession, userLogin, newExternalIdentityProvider))
177 .extracting(UserDto::isLocal, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider)
178 .contains(false, userLogin, newExternalIdentityProvider);
182 public void fail_if_user_not_exist() {
183 TestRequest request = underTest.newRequest()
184 .setParam("login", "not-existing")
185 .setParam("newExternalProvider", "gitlab");
187 assertThatThrownBy(request::execute)
188 .isInstanceOf(NotFoundException.class)
189 .hasMessage("User 'not-existing' doesn't exist");
193 public void fail_if_identity_provider_not_exist() {
194 createUser(true, "login-1", "login-1", SQ_AUTHORITY);
195 TestRequest request = underTest.newRequest()
196 .setParam("login", "login-1")
197 .setParam("newExternalProvider", "not-existing");
199 assertThatThrownBy(request::execute)
200 .isInstanceOf(IllegalArgumentException.class)
201 .hasMessage("Value of parameter 'newExternalProvider' (not-existing) must be one of: [github, gitlab] or [LDAP, LDAP_{serverKey}]");
205 public void fail_if_anonymous() {
206 userSession.anonymous();
207 TestRequest request = underTest.newRequest()
208 .setParam("login", "not-existing")
209 .setParam("newExternalProvider", "something");
211 assertThatThrownBy(request::execute)
212 .isInstanceOf(UnauthorizedException.class);
216 public void fail_if_not_admin() {
217 userSession.logIn("some-user");
218 TestRequest request = underTest.newRequest()
219 .setParam("login", "not-existing")
220 .setParam("newExternalProvider", "something");
222 assertThatThrownBy(request::execute)
223 .isInstanceOf(ForbiddenException.class);
226 private void createUser(boolean local, String login, String externalLogin, String externalIdentityProvider) {
227 UserDto userDto = newUserDto()
228 .setEmail("john@email.com")
231 .setScmAccounts(newArrayList("jn"))
234 .setExternalLogin(externalLogin)
235 .setExternalIdentityProvider(externalIdentityProvider);
236 dbClient.userDao().insert(dbSession, userDto);
237 userIndexer.commitAndIndex(dbSession, userDto);