3 * Copyright (C) 2009-2021 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.db.DbClient;
26 import org.sonar.db.DbSession;
27 import org.sonar.db.DbTester;
28 import org.sonar.db.user.UserDto;
29 import org.sonar.server.authentication.CredentialsLocalAuthentication;
30 import org.sonar.server.authentication.IdentityProviderRepositoryRule;
31 import org.sonar.server.authentication.TestIdentityProvider;
32 import org.sonar.server.es.EsTester;
33 import org.sonar.server.exceptions.ForbiddenException;
34 import org.sonar.server.exceptions.NotFoundException;
35 import org.sonar.server.exceptions.UnauthorizedException;
36 import org.sonar.server.tester.UserSessionRule;
37 import org.sonar.server.user.NewUserNotifier;
38 import org.sonar.server.user.UserUpdater;
39 import org.sonar.server.user.index.UserIndexer;
40 import org.sonar.server.usergroups.DefaultGroupFinder;
41 import org.sonar.server.ws.TestRequest;
42 import org.sonar.server.ws.WsActionTester;
44 import static com.google.common.collect.Lists.newArrayList;
45 import static org.assertj.core.api.Assertions.assertThat;
46 import static org.assertj.core.api.Assertions.assertThatThrownBy;
47 import static org.mockito.Mockito.mock;
48 import static org.sonar.db.user.UserTesting.newUserDto;
50 public class UpdateIdentityProviderActionTest {
51 private final static String SQ_AUTHORITY = "sonarqube";
54 public IdentityProviderRepositoryRule identityProviderRepository = new IdentityProviderRepositoryRule()
55 .addIdentityProvider(new TestIdentityProvider().setName("Gitlab").setKey("gitlab").setEnabled(true))
56 .addIdentityProvider(new TestIdentityProvider().setName("Github").setKey("github").setEnabled(true));
59 public DbTester db = DbTester.create();
61 public EsTester es = EsTester.create();
63 public UserSessionRule userSession = UserSessionRule.standalone().logIn().setSystemAdministrator();
65 private final MapSettings settings = new MapSettings().setProperty("sonar.internal.pbkdf2.iterations", "1");
66 private final DbClient dbClient = db.getDbClient();
67 private final DbSession dbSession = db.getSession();
68 private final UserIndexer userIndexer = new UserIndexer(dbClient, es.client());
69 private final CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(dbClient, settings.asConfig());
71 private final WsActionTester underTest = new WsActionTester(new UpdateIdentityProviderAction(dbClient, identityProviderRepository,
72 new UserUpdater(mock(NewUserNotifier.class), dbClient, userIndexer, new DefaultGroupFinder(db.getDbClient()), settings.asConfig(), localAuthentication),
76 public void change_identity_provider_of_a_local_user_all_params() {
77 String userLogin = "login-1";
78 String newExternalLogin = "login@github.com";
79 String newExternalIdentityProvider = "github";
80 createUser(true, userLogin, userLogin, SQ_AUTHORITY);
81 TestRequest request = underTest.newRequest()
82 .setParam("login", userLogin)
83 .setParam("newExternalProvider", newExternalIdentityProvider)
84 .setParam("newExternalIdentity", newExternalLogin);
87 assertThat(dbClient.userDao().selectByExternalLoginAndIdentityProvider(dbSession, newExternalLogin, newExternalIdentityProvider))
89 .extracting(UserDto::isLocal, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider)
90 .contains(false, newExternalLogin, newExternalIdentityProvider);
94 public void change_identity_provider_of_a_local_user_mandatory_params_only_provider_login_stays_same() {
95 String userLogin = "login-1";
96 String newExternalIdentityProvider = "github";
97 createUser(true, userLogin, userLogin, SQ_AUTHORITY);
98 TestRequest request = underTest.newRequest()
99 .setParam("login", userLogin)
100 .setParam("newExternalProvider", newExternalIdentityProvider);
103 assertThat(dbClient.userDao().selectByExternalLoginAndIdentityProvider(dbSession, userLogin, newExternalIdentityProvider))
105 .extracting(UserDto::isLocal, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider)
106 .contains(false, userLogin, newExternalIdentityProvider);
110 public void change_identity_provider_of_a_external_user_to_new_one() {
111 String userLogin = "login-1";
112 String oldExternalIdentityProvider = "gitlab";
113 String oldExternalIdentity = "john@gitlab.com";
114 createUser(false, userLogin, oldExternalIdentity, oldExternalIdentityProvider);
116 String newExternalIdentityProvider = "github";
117 String newExternalIdentity = "john@github.com";
118 TestRequest request = underTest.newRequest()
119 .setParam("login", userLogin)
120 .setParam("newExternalProvider", newExternalIdentityProvider)
121 .setParam("newExternalIdentity", newExternalIdentity);
124 assertThat(dbClient.userDao().selectByExternalLoginAndIdentityProvider(dbSession, newExternalIdentity, newExternalIdentityProvider))
126 .extracting(UserDto::isLocal, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider)
127 .contains(false, newExternalIdentity, newExternalIdentityProvider);
131 public void fail_if_user_not_exist() {
132 TestRequest request = underTest.newRequest()
133 .setParam("login", "not-existing")
134 .setParam("newExternalProvider", "gitlab");
136 assertThatThrownBy(request::execute)
137 .isInstanceOf(NotFoundException.class)
138 .hasMessage("User 'not-existing' doesn't exist");
142 public void fail_if_identity_provider_not_exist() {
143 createUser(true, "login-1", "login-1", SQ_AUTHORITY);
144 TestRequest request = underTest.newRequest()
145 .setParam("login", "login-1")
146 .setParam("newExternalProvider", "not-existing");
148 assertThatThrownBy(request::execute)
149 .isInstanceOf(IllegalArgumentException.class)
150 .hasMessage("Value of parameter 'newExternalProvider' (not-existing) must be one of: [github, gitlab, sonarqube]");
154 public void fail_if_anonymous() {
155 userSession.anonymous();
156 TestRequest request = underTest.newRequest()
157 .setParam("login", "not-existing")
158 .setParam("newExternalProvider", "something");
160 assertThatThrownBy(request::execute)
161 .isInstanceOf(UnauthorizedException.class);
165 public void fail_if_not_admin() {
166 userSession.logIn("some-user");
167 TestRequest request = underTest.newRequest()
168 .setParam("login", "not-existing")
169 .setParam("newExternalProvider", "something");
171 assertThatThrownBy(request::execute)
172 .isInstanceOf(ForbiddenException.class);
175 private void createUser(boolean local, String login, String externalLogin, String externalIdentityProvider) {
176 UserDto userDto = newUserDto()
177 .setEmail("john@email.com")
180 .setScmAccounts(newArrayList("jn"))
183 .setExternalLogin(externalLogin)
184 .setExternalIdentityProvider(externalIdentityProvider);
185 dbClient.userDao().insert(dbSession, userDto);
186 userIndexer.commitAndIndex(dbSession, userDto);