import org.sonar.api.config.Configuration;
import org.sonar.api.config.PropertyDefinition;
-import static java.lang.String.format;
import static java.lang.String.valueOf;
import static org.sonar.api.PropertyType.BOOLEAN;
-import static org.sonar.api.PropertyType.SINGLE_SELECT_LIST;
import static org.sonar.api.PropertyType.STRING;
public class GitHubSettings {
private static final String API_URL = "sonar.auth.github.apiUrl";
private static final String WEB_URL = "sonar.auth.github.webUrl";
- static final String LOGIN_STRATEGY = "sonar.auth.github.loginStrategy";
- static final String LOGIN_STRATEGY_UNIQUE = "Unique";
- static final String LOGIN_STRATEGY_PROVIDER_ID = "Same as GitHub login";
- static final String LOGIN_STRATEGY_DEFAULT_VALUE = LOGIN_STRATEGY_UNIQUE;
-
private static final String ORGANIZATIONS = "sonar.auth.github.organizations";
private static final String CATEGORY = "security";
return configuration.getBoolean(ALLOW_USERS_TO_SIGN_UP).orElse(false);
}
- String loginStrategy() {
- return configuration.get(LOGIN_STRATEGY).orElse("");
- }
-
boolean syncGroups() {
return configuration.getBoolean(GROUPS_SYNC).orElse(false);
}
.defaultValue(valueOf(true))
.index(4)
.build(),
- PropertyDefinition.builder(LOGIN_STRATEGY)
- .name("Login generation strategy")
- .description(format("When the login strategy is set to '%s', the user's login will be auto-generated the first time so that it is unique. " +
- "When the login strategy is set to '%s', the user's login will be the GitHub login.",
- LOGIN_STRATEGY_UNIQUE, LOGIN_STRATEGY_PROVIDER_ID))
- .category(CATEGORY)
- .subCategory(SUBCATEGORY)
- .type(SINGLE_SELECT_LIST)
- .defaultValue(LOGIN_STRATEGY_DEFAULT_VALUE)
- .options(LOGIN_STRATEGY_UNIQUE, LOGIN_STRATEGY_PROVIDER_ID)
- .index(5)
- .build(),
PropertyDefinition.builder(GROUPS_SYNC)
.name("Synchronize teams as groups")
.description("For each team he belongs to, the user will be associated to a group named 'Organisation/Team' (if it exists) in SonarQube.")
import javax.annotation.Nullable;
import org.sonar.api.server.authentication.UserIdentity;
-import static org.sonar.auth.github.UserIdentityGenerator.generateLogin;
-import static org.sonar.auth.github.UserIdentityGenerator.generateName;
-
public class UserIdentityFactoryImpl implements UserIdentityFactory {
- private final GitHubSettings settings;
-
- public UserIdentityFactoryImpl(GitHubSettings settings) {
- this.settings = settings;
- }
-
@Override
public UserIdentity create(GsonUser user, @Nullable String email, @Nullable List<GsonTeam> teams) {
UserIdentity.Builder builder = UserIdentity.builder()
.setProviderId(user.getId())
.setProviderLogin(user.getLogin())
- .setLogin(generateLogin(user, settings.loginStrategy()))
.setName(generateName(user))
.setEmail(email);
if (teams != null) {
return builder.build();
}
+ private static String generateName(GsonUser gson) {
+ String name = gson.getName();
+ return name == null || name.isEmpty() ? gson.getLogin() : name;
+ }
+
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.auth.github;
-
-import static java.lang.String.format;
-import static org.sonar.auth.github.GitHubSettings.LOGIN_STRATEGY_PROVIDER_ID;
-import static org.sonar.auth.github.GitHubSettings.LOGIN_STRATEGY_UNIQUE;
-
-class UserIdentityGenerator {
-
- private UserIdentityGenerator() {
- // Only static method
- }
-
- static String generateLogin(GsonUser gsonUser, String loginStrategy) {
- switch (loginStrategy) {
- case LOGIN_STRATEGY_PROVIDER_ID:
- return gsonUser.getLogin();
- case LOGIN_STRATEGY_UNIQUE:
- return generateUniqueLogin(gsonUser);
- default:
- throw new IllegalStateException(format("Login strategy not supported : %s", loginStrategy));
- }
- }
-
- static String generateName(GsonUser gson) {
- String name = gson.getName();
- return name == null || name.isEmpty() ? gson.getLogin() : name;
- }
-
- private static String generateUniqueLogin(GsonUser gsonUser) {
- return format("%s@%s", gsonUser.getLogin(), GitHubIdentityProvider.KEY);
- }
-}
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import static org.sonar.auth.github.GitHubSettings.LOGIN_STRATEGY_DEFAULT_VALUE;
public class GitHubIdentityProviderTest {
public void is_enabled() {
settings.setProperty("sonar.auth.github.clientId.secured", "id");
settings.setProperty("sonar.auth.github.clientSecret.secured", "secret");
- settings.setProperty("sonar.auth.github.loginStrategy", LOGIN_STRATEGY_DEFAULT_VALUE);
settings.setProperty("sonar.auth.github.enabled", true);
assertThat(underTest.isEnabled()).isTrue();
if (enabled) {
settings.setProperty("sonar.auth.github.clientId.secured", "id");
settings.setProperty("sonar.auth.github.clientSecret.secured", "secret");
- settings.setProperty("sonar.auth.github.loginStrategy", LOGIN_STRATEGY_DEFAULT_VALUE);
settings.setProperty("sonar.auth.github.enabled", true);
} else {
settings.setProperty("sonar.auth.github.enabled", false);
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new GitHubModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 14);
+ assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 13);
}
}
import org.sonar.api.config.internal.MapSettings;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.auth.github.GitHubSettings.LOGIN_STRATEGY_DEFAULT_VALUE;
-import static org.sonar.auth.github.GitHubSettings.LOGIN_STRATEGY_PROVIDER_ID;
public class GitHubSettingsTest {
public void is_enabled() {
settings.setProperty("sonar.auth.github.clientId.secured", "id");
settings.setProperty("sonar.auth.github.clientSecret.secured", "secret");
- settings.setProperty("sonar.auth.github.loginStrategy", LOGIN_STRATEGY_DEFAULT_VALUE);
settings.setProperty("sonar.auth.github.enabled", true);
assertThat(underTest.isEnabled()).isTrue();
settings.setProperty("sonar.auth.github.enabled", true);
settings.setProperty("sonar.auth.github.clientId.secured", (String) null);
settings.setProperty("sonar.auth.github.clientSecret.secured", "secret");
- settings.setProperty("sonar.auth.github.loginStrategy", LOGIN_STRATEGY_DEFAULT_VALUE);
assertThat(underTest.isEnabled()).isFalse();
}
settings.setProperty("sonar.auth.github.enabled", true);
settings.setProperty("sonar.auth.github.clientId.secured", "id");
settings.setProperty("sonar.auth.github.clientSecret.secured", (String) null);
- settings.setProperty("sonar.auth.github.loginStrategy", LOGIN_STRATEGY_DEFAULT_VALUE);
assertThat(underTest.isEnabled()).isFalse();
}
assertThat(underTest.clientSecret()).isEqualTo("secret");
}
- @Test
- public void return_login_strategy() {
- settings.setProperty("sonar.auth.github.loginStrategy", LOGIN_STRATEGY_PROVIDER_ID);
- assertThat(underTest.loginStrategy()).isEqualTo(LOGIN_STRATEGY_PROVIDER_ID);
- }
-
@Test
public void allow_users_to_sign_up() {
settings.setProperty("sonar.auth.github.allowUsersToSignUp", "true");
public void return_organizations_single() {
String setting = "example";
settings.setProperty("sonar.auth.github.organizations", setting);
- String[] expected = new String[] {"example"};
String[] actual = underTest.organizations();
- assertThat(actual).isEqualTo(expected);
+ assertThat(actual).containsOnly(setting);
}
@Test
public void return_organizations_multiple() {
String setting = "example0,example1";
settings.setProperty("sonar.auth.github.organizations", setting);
- String[] expected = new String[] {"example0", "example1"};
String[] actual = underTest.organizations();
- assertThat(actual).isEqualTo(expected);
+ assertThat(actual).containsOnly("example0", "example1");
}
@Test
public void return_organizations_empty_list() {
String[] setting = null;
settings.setProperty("sonar.auth.github.organizations", setting);
- String[] expected = new String[] {};
String[] actual = underTest.organizations();
- assertThat(actual).isEqualTo(expected);
+ assertThat(actual).hasSize(0);
}
@Test
public void definitions() {
- assertThat(GitHubSettings.definitions()).hasSize(9);
+ assertThat(GitHubSettings.definitions()).hasSize(8);
}
}
// load settings with default values
private MapSettings settings = new MapSettings(new PropertyDefinitions(GitHubSettings.definitions()));
private GitHubSettings gitHubSettings = new GitHubSettings(settings.asConfig());
- private UserIdentityFactoryImpl userIdentityFactory = new UserIdentityFactoryImpl(gitHubSettings);
+ private UserIdentityFactoryImpl userIdentityFactory = new UserIdentityFactoryImpl();
private ScribeGitHubApi scribeApi = new ScribeGitHubApi(gitHubSettings);
private GitHubRestClient gitHubRestClient = new GitHubRestClient(gitHubSettings);
assertThat(callbackContext.csrfStateVerified.get()).isTrue();
assertThat(callbackContext.userIdentity.getProviderId()).isEqualTo("ABCD");
- assertThat(callbackContext.userIdentity.getLogin()).isEqualTo("octocat@github");
+ assertThat(callbackContext.userIdentity.getProviderLogin()).isEqualTo("octocat");
assertThat(callbackContext.userIdentity.getName()).isEqualTo("monalisa octocat");
assertThat(callbackContext.userIdentity.getEmail()).isEqualTo("octocat@github.com");
assertThat(callbackContext.redirectedToRequestedPage.get()).isTrue();
assertThat(callbackContext.csrfStateVerified.get()).isTrue();
assertThat(callbackContext.userIdentity.getProviderId()).isEqualTo("ABCD");
- assertThat(callbackContext.userIdentity.getLogin()).isEqualTo("octocat@github");
+ assertThat(callbackContext.userIdentity.getProviderLogin()).isEqualTo("octocat");
assertThat(callbackContext.userIdentity.getName()).isEqualTo("monalisa octocat");
assertThat(callbackContext.userIdentity.getEmail()).isEqualTo("octocat@github.com");
assertThat(callbackContext.redirectedToRequestedPage.get()).isTrue();
assertThat(callbackContext.csrfStateVerified.get()).isTrue();
assertThat(callbackContext.userIdentity.getProviderId()).isEqualTo("ABCD");
- assertThat(callbackContext.userIdentity.getLogin()).isEqualTo("octocat@github");
+ assertThat(callbackContext.userIdentity.getProviderLogin()).isEqualTo("octocat");
assertThat(callbackContext.userIdentity.getName()).isEqualTo("monalisa octocat");
assertThat(callbackContext.userIdentity.getEmail()).isNull();
assertThat(callbackContext.redirectedToRequestedPage.get()).isTrue();
@Test
public void callback_on_successful_authentication_with_organizations_without_membership() {
settings.setProperty("sonar.auth.github.organizations", "first_org,second_org");
- settings.setProperty("sonar.auth.github.loginStrategy", GitHubSettings.LOGIN_STRATEGY_PROVIDER_ID);
github.enqueue(newSuccessfulAccessTokenResponse());
// response of api.github.com/user
}
}
- @Test
- public void callback_on_successful_authentication_with_organizations_without_membership_with_unique_login_strategy() {
- settings.setProperty("sonar.auth.github.organizations", "example");
- settings.setProperty("sonar.auth.github.loginStrategy", GitHubSettings.LOGIN_STRATEGY_UNIQUE);
-
- github.enqueue(newSuccessfulAccessTokenResponse());
- // response of api.github.com/user
- github.enqueue(new MockResponse().setBody("{\"id\":\"ABCD\", \"login\":\"octocat\", \"name\":\"monalisa octocat\",\"email\":\"octocat@github.com\"}"));
- // response of api.github.com/orgs/example0/members/user
- github.enqueue(new MockResponse().setResponseCode(404).setBody("{}"));
-
- HttpServletRequest request = newRequest("the-verifier-code");
- DumbCallbackContext callbackContext = new DumbCallbackContext(request);
- try {
- underTest.callback(callbackContext);
- fail("exception expected");
- } catch (UnauthorizedException e) {
- assertThat(e.getMessage()).isEqualTo("'octocat' must be a member of at least one organization: 'example'");
- }
- }
-
@Test
public void callback_throws_ISE_if_error_when_requesting_user_profile() {
github.enqueue(newSuccessfulAccessTokenResponse());
*/
package org.sonar.auth.github;
-import java.util.Arrays;
-import java.util.List;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
public ExpectedException expectedException = ExpectedException.none();
private MapSettings settings = new MapSettings(new PropertyDefinitions(GitHubSettings.definitions()));
- private UserIdentityFactoryImpl underTest = new UserIdentityFactoryImpl(new GitHubSettings(settings.asConfig()));
-
- /**
- * Keep the same login as at GitHub
- */
- @Test
- public void create_for_provider_strategy() {
- GsonUser gson = new GsonUser("ABCD", "octocat", "monalisa octocat", "octocat@github.com");
- settings.setProperty(GitHubSettings.LOGIN_STRATEGY, GitHubSettings.LOGIN_STRATEGY_PROVIDER_ID);
-
- UserIdentity identity = underTest.create(gson, gson.getEmail(), null);
-
- assertThat(identity.getProviderId()).isEqualTo("ABCD");
- assertThat(identity.getLogin()).isEqualTo("octocat");
- assertThat(identity.getName()).isEqualTo("monalisa octocat");
- assertThat(identity.getEmail()).isEqualTo("octocat@github.com");
- }
+ private UserIdentityFactoryImpl underTest = new UserIdentityFactoryImpl();
@Test
public void no_email() {
GsonUser gson = new GsonUser("ABCD", "octocat", "monalisa octocat", null);
- settings.setProperty(GitHubSettings.LOGIN_STRATEGY, GitHubSettings.LOGIN_STRATEGY_PROVIDER_ID);
-
- UserIdentity identity = underTest.create(gson, null, null);
-
- assertThat(identity.getLogin()).isEqualTo("octocat");
- assertThat(identity.getName()).isEqualTo("monalisa octocat");
- assertThat(identity.getEmail()).isNull();
- }
-
- @Test
- public void create_for_provider_strategy_with_teams() {
- GsonUser gson = new GsonUser("ABCD", "octocat", "monalisa octocat", "octocat@github.com");
- List<GsonTeam> teams = Arrays.asList(
- new GsonTeam("developers", new GsonTeam.GsonOrganization("SonarSource")));
- settings.setProperty(GitHubSettings.LOGIN_STRATEGY, GitHubSettings.LOGIN_STRATEGY_PROVIDER_ID);
-
- UserIdentity identity = underTest.create(gson, null, teams);
-
- assertThat(identity.getGroups()).containsOnly("SonarSource/developers");
- }
-
- @Test
- public void create_for_unique_login_strategy() {
- GsonUser gson = new GsonUser("ABCD", "octocat", "monalisa octocat", "octocat@github.com");
- settings.setProperty(GitHubSettings.LOGIN_STRATEGY, GitHubSettings.LOGIN_STRATEGY_UNIQUE);
UserIdentity identity = underTest.create(gson, null, null);
- assertThat(identity.getLogin()).isEqualTo("octocat@github");
+ assertThat(identity.getProviderLogin()).isEqualTo("octocat");
assertThat(identity.getName()).isEqualTo("monalisa octocat");
assertThat(identity.getEmail()).isNull();
}
assertThat(identity.getName()).isEqualTo("octocat");
}
-
- @Test
- public void throw_ISE_if_strategy_is_not_supported() {
- settings.setProperty(GitHubSettings.LOGIN_STRATEGY, "xxx");
-
- expectedException.expect(IllegalStateException.class);
- expectedException.expectMessage("Login strategy not supported : xxx");
-
- underTest.create(new GsonUser("ABCD", "octocat", "octocat", "octocat@github.com"), null, null);
- }
}
ArgumentCaptor<UserIdentity> argument = ArgumentCaptor.forClass(UserIdentity.class);
verify(callbackContext).authenticate(argument.capture());
assertThat(argument.getValue()).isNotNull();
- assertThat(argument.getValue().getLogin()).isNull();
assertThat(argument.getValue().getProviderId()).isEqualTo("123");
assertThat(argument.getValue().getProviderLogin()).isEqualTo("toto");
assertThat(argument.getValue().getName()).isEqualTo("Toto Toto");
LOGGER.trace("Attributes received : {}", auth.getAttributes());
String login = getNonNullFirstAttribute(auth, samlSettings.getUserLogin());
UserIdentity.Builder userIdentityBuilder = UserIdentity.builder()
- .setLogin(login)
.setProviderLogin(login)
.setName(getNonNullFirstAttribute(auth, samlSettings.getUserName()));
samlSettings.getUserEmail().ifPresent(
underTest.callback(callbackContext);
assertThat(callbackContext.redirectedToRequestedPage.get()).isTrue();
- assertThat(callbackContext.userIdentity.getLogin()).isEqualTo("johndoe");
+ assertThat(callbackContext.userIdentity.getProviderLogin()).isEqualTo("johndoe");
assertThat(callbackContext.verifyState.get()).isTrue();
}
underTest.callback(callbackContext);
- assertThat(callbackContext.userIdentity.getLogin()).isEqualTo("johndoe");
assertThat(callbackContext.userIdentity.getName()).isEqualTo("John Doe");
assertThat(callbackContext.userIdentity.getEmail()).isEqualTo("johndoe@email.com");
assertThat(callbackContext.userIdentity.getProviderLogin()).isEqualTo("johndoe");
underTest.callback(callbackContext);
- assertThat(callbackContext.userIdentity.getLogin()).isEqualTo("johndoe");
assertThat(callbackContext.userIdentity.getName()).isEqualTo("John Doe");
assertThat(callbackContext.userIdentity.getEmail()).isNull();
assertThat(callbackContext.userIdentity.getProviderLogin()).isEqualTo("johndoe");
underTest.callback(callbackContext);
- assertThat(callbackContext.userIdentity.getLogin()).isEqualTo("johndoe");
+ assertThat(callbackContext.userIdentity.getProviderLogin()).isEqualTo("johndoe");
assertThat(callbackContext.userIdentity.getGroups()).isEmpty();
}
import static java.lang.String.format;
import static java.util.Arrays.stream;
import static org.sonar.db.permission.OrganizationPermission.ADMINISTER;
-import static org.sonar.db.user.GroupTesting.newGroupDto;
-import static org.sonar.db.user.UserTesting.newDisabledUser;
-import static org.sonar.db.user.UserTesting.newUserDto;
-import static org.sonar.db.user.UserTesting.newUserSettingDto;
-import static org.sonar.db.user.UserTokenTesting.newUserToken;
public class UserDbTester {
private static final Set<String> PUBLIC_PERMISSIONS = ImmutableSet.of(UserRole.USER, UserRole.CODEVIEWER); // FIXME to check with Simon
return Optional.ofNullable(dbClient.userDao().selectByLogin(db.getSession(), login));
}
+ public Optional<UserDto> selectUserByEmail(String email) {
+ List<UserDto> users = dbClient.userDao().selectByEmail(db.getSession(), email);
+ if (users.size() > 1) {
+ return Optional.empty();
+ }
+ return Optional.of(users.get(0));
+ }
+
+ public Optional<UserDto> selectUserByExternalLoginAndIdentityProvider(String login, String identityProvider) {
+ return Optional.ofNullable(dbClient.userDao().selectByExternalLoginAndIdentityProvider(db.getSession(), login, identityProvider));
+ }
+
// USER SETTINGS
@SafeVarargs
.add(3006, "Create NEW_CODE_PERIOD table", CreateNewCodePeriodTable.class)
.add(3007, "Populate NEW_CODE_PERIOD table", PopulateNewCodePeriodTable.class)
.add(3008, "Remove leak period properties", RemoveLeakPeriodProperties.class)
+ .add(3009, "Remove GitHub login generation strategy property", RemoveGitHubLoginGenerationStrategyProperty.class)
;
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.platform.db.migration.version.v80;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.step.DataChange;
+
+public class RemoveGitHubLoginGenerationStrategyProperty extends DataChange {
+ private static final String GH_LOGIN_STRATEGY_PROP_KEY = "sonar.auth.github.loginStrategy";
+
+ public RemoveGitHubLoginGenerationStrategyProperty(Database db) {
+ super(db);
+ }
+
+ @Override
+ protected void execute(Context context) throws SQLException {
+ context.prepareUpsert("delete from properties where prop_key='" + GH_LOGIN_STRATEGY_PROP_KEY + "'")
+ .execute()
+ .commit();
+ }
+}
@Test
public void verify_migration_count() {
- verifyMigrationCount(underTest, 9);
+ verifyMigrationCount(underTest, 10);
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.platform.db.migration.version.v80;
+
+import java.sql.SQLException;
+import java.time.Instant;
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.db.CoreDbTester;
+
+public class RemoveGitHubLoginGenerationStrategyPropertyTest {
+ private static final String PROPERTIES_TABLE_NAME = "properties";
+
+ @Rule
+ public CoreDbTester dbTester = CoreDbTester.createForSchema(RemoveGitHubLoginGenerationStrategyPropertyTest.class, "schema.sql");
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private RemoveGitHubLoginGenerationStrategyProperty underTest = new RemoveGitHubLoginGenerationStrategyProperty(dbTester.database());
+
+ @Test
+ public void remove_github_login_strategy_property() throws SQLException {
+ insertGitHubLoginStrategy();
+
+ int propertiesCount = dbTester.countRowsOfTable(PROPERTIES_TABLE_NAME);
+ Assert.assertEquals(1, propertiesCount);
+
+ underTest.execute();
+
+ //should delete properties
+ propertiesCount = dbTester.countRowsOfTable(PROPERTIES_TABLE_NAME);
+ Assert.assertEquals(0, propertiesCount);
+
+ //should not fail if executed twice
+ underTest.execute();
+ }
+
+ private void insertGitHubLoginStrategy() {
+ dbTester.executeInsert(PROPERTIES_TABLE_NAME,
+ "prop_key", "sonar.auth.github.loginStrategy",
+ "is_empty", false,
+ "text_value", "Unique",
+ "created_at", Instant.now().toEpochMilli());
+ }
+}
--- /dev/null
+CREATE TABLE "PROPERTIES" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "PROP_KEY" VARCHAR(512) NOT NULL,
+ "RESOURCE_ID" INTEGER,
+ "USER_ID" INTEGER,
+ "IS_EMPTY" BOOLEAN NOT NULL,
+ "TEXT_VALUE" VARCHAR(4000),
+ "CLOB_VALUE" CLOB,
+ "CREATED_AT" BIGINT
+);
+CREATE INDEX "PROPERTIES_KEY" ON "PROPERTIES" ("PROP_KEY");
private UserDto synchronize(String userLogin, UserDetails details, HttpServletRequest request, AuthenticationEvent.Method method) {
String name = details.getName();
UserIdentity.Builder userIdentityBuilder = UserIdentity.builder()
- .setLogin(userLogin)
.setName(isEmpty(name) ? userLogin : name)
.setEmail(trimToNull(details.getEmail()))
.setProviderLogin(userLogin);
String name = getHeaderValue(headerValuesByNames, SONAR_WEB_SSO_NAME_HEADER.getKey());
String email = getHeaderValue(headerValuesByNames, SONAR_WEB_SSO_EMAIL_HEADER.getKey());
UserIdentity.Builder userIdentityBuilder = UserIdentity.builder()
- .setLogin(login)
.setName(name == null ? login : name)
.setEmail(email)
.setProviderLogin(login);
public class UserRegistrarImpl implements UserRegistrar {
private static final Logger LOGGER = Loggers.get(UserRegistrarImpl.class);
+ private static final String SQ_AUTHORITY = "sonarqube";
private final DbClient dbClient;
private final UserUpdater userUpdater;
return user;
}
// Then, try with the external login, for instance when external ID has changed
- user = dbClient.userDao().selectByExternalLoginAndIdentityProvider(dbSession, userIdentity.getProviderLogin(), provider.getKey());
- if (user != null) {
- return user;
- }
- // Last, try with login, for instance when external ID and external login has been updated
- String login = userIdentity.getLogin();
- if (login == null) {
- return null;
- }
- return dbClient.userDao().selectByLogin(dbSession, login);
+ return dbClient.userDao().selectByExternalLoginAndIdentityProvider(dbSession, userIdentity.getProviderLogin(), provider.getKey());
}
private UserDto registerNewUser(DbSession dbSession, @Nullable UserDto disabledUser, UserRegistration authenticatorParameters) {
authenticatorParameters.getProvider().getKey(),
authenticatorParameters.getUserIdentity().getProviderLogin(),
authenticatorParameters.getUserIdentity().getProviderId()));
- String login = authenticatorParameters.getUserIdentity().getLogin();
- if (login != null) {
- update.setLogin(login);
- }
Optional<UserDto> otherUserToIndex = detectEmailUpdate(dbSession, authenticatorParameters);
userUpdater.updateAndCommit(dbSession, userDto, update, beforeCommit(dbSession, false, authenticatorParameters), toArray(otherUserToIndex));
return userDto;
}
private static boolean isSameUser(UserDto existingUser, UserRegistration authenticatorParameters) {
- // Check if same login
- return Objects.equals(existingUser.getLogin(), authenticatorParameters.getUserIdentity().getLogin()) ||
// Check if same identity provider and same provider id or provider login
- (Objects.equals(existingUser.getExternalIdentityProvider(), authenticatorParameters.getProvider().getKey()) &&
- (Objects.equals(existingUser.getExternalId(), getProviderIdOrProviderLogin(authenticatorParameters.getUserIdentity()))
- || Objects.equals(existingUser.getExternalLogin(), authenticatorParameters.getUserIdentity().getProviderLogin())));
+ return (Objects.equals(existingUser.getExternalIdentityProvider(), authenticatorParameters.getProvider().getKey()) &&
+ (Objects.equals(existingUser.getExternalId(), getProviderIdOrProviderLogin(authenticatorParameters.getUserIdentity()))
+ || Objects.equals(existingUser.getExternalLogin(), authenticatorParameters.getUserIdentity().getProviderLogin())));
}
private void syncGroups(DbSession dbSession, UserIdentity userIdentity, UserDto userDto) {
.setPublicMessage(format("'%s' users are not allowed to sign up", identityProviderKey))
.build();
}
+ String providerLogin = authenticatorParameters.getUserIdentity().getProviderLogin();
return NewUser.builder()
- .setLogin(authenticatorParameters.getUserIdentity().getLogin())
+ .setLogin(SQ_AUTHORITY.equals(identityProviderKey) ? providerLogin : null)
.setEmail(authenticatorParameters.getUserIdentity().getEmail())
.setName(authenticatorParameters.getUserIdentity().getName())
.setExternalIdentity(
new ExternalIdentity(
identityProviderKey,
- authenticatorParameters.getUserIdentity().getProviderLogin(),
+ providerLogin,
authenticatorParameters.getUserIdentity().getProviderId()))
.build();
}
dbClient.propertiesDao().selectByKeyAndMatchingValue(dbSession, DEFAULT_ISSUE_ASSIGNEE, userDto.getLogin())
.forEach(p -> dbClient.propertiesDao().saveProperty(p.setValue(newLogin)));
userDto.setLogin(newLogin);
- if (userDto.isLocal()) {
+ if (userDto.isLocal() || SQ_AUTHORITY.equals(userDto.getExternalIdentityProvider())) {
userDto.setExternalLogin(newLogin);
userDto.setExternalId(newLogin);
}
private static final UserIdentity USER_IDENTITY = UserIdentity.builder()
.setProviderId("ABCD")
.setProviderLogin("johndoo")
- .setLogin("id:johndoo")
.setName("John")
.setEmail("john@email.com")
.build();
assertThat(userIdentityAuthenticator.isAuthenticated()).isTrue();
verify(threadLocalUserSession).set(any(UserSession.class));
verify(jwtHttpHandler).generateToken(userArgumentCaptor.capture(), eq(request), eq(response));
- assertThat(userArgumentCaptor.getValue().getLogin()).isEqualTo(USER_IDENTITY.getLogin());
assertThat(userArgumentCaptor.getValue().getExternalId()).isEqualTo(USER_IDENTITY.getProviderId());
assertThat(userArgumentCaptor.getValue().getExternalLogin()).isEqualTo(USER_IDENTITY.getProviderLogin());
assertThat(userArgumentCaptor.getValue().getExternalIdentityProvider()).isEqualTo("github");
assertThat(userIdentityAuthenticator.isAuthenticated()).isTrue();
assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getExistingEmailStrategy()).isEqualTo(FORBID);
- assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getUserIdentity().getLogin()).isEqualTo(LOGIN);
assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getUserIdentity().getProviderLogin()).isEqualTo(LOGIN);
assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getUserIdentity().getProviderId()).isNull();
assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getUserIdentity().getName()).isEqualTo("name");
executeAuthenticate("LOGIN");
assertThat(userIdentityAuthenticator.isAuthenticated()).isTrue();
- assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getUserIdentity().getLogin()).isEqualTo("login");
assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getUserIdentity().getProviderLogin()).isEqualTo("login");
verify(authenticationEvent).loginSuccess(request, "login", Source.realm(BASIC, REALM_NAME));
}
executeAuthenticate("LoGiN");
assertThat(userIdentityAuthenticator.isAuthenticated()).isTrue();
- assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getUserIdentity().getLogin()).isEqualTo("LoGiN");
assertThat(userIdentityAuthenticator.getAuthenticatorParameters().getUserIdentity().getProviderLogin()).isEqualTo("LoGiN");
verify(authenticationEvent).loginSuccess(request, "LoGiN", Source.realm(BASIC, REALM_NAME));
}
public void update_user_when_authenticating_exiting_user() {
startWithSso();
setNotUserInToken();
- insertUser(newUserDto().setLogin(DEFAULT_LOGIN).setName("old name").setEmail("old email"), group1);
+ insertUser(newUserDto().setLogin(DEFAULT_LOGIN).setExternalLogin(DEFAULT_LOGIN).setExternalIdentityProvider("sonarqube").setName("old name").setEmail("old email"), group1);
// Name, email and groups are different
HttpServletRequest request = createRequest(DEFAULT_LOGIN, DEFAULT_NAME, DEFAULT_EMAIL, GROUP2);
public void init(Context context) {
throw new EmailAlreadyExistsRedirectionException(existingUser.getEmail(), existingUser, UserIdentity.builder()
.setProviderLogin("john.github")
- .setLogin("john.github")
.setName(existingUser.getName())
.setEmail(existingUser.getEmail())
.build(), this);
public void callback(CallbackContext context) {
throw new EmailAlreadyExistsRedirectionException(existingUser.getEmail(), existingUser, UserIdentity.builder()
.setProviderLogin("john.github")
- .setLogin("john.github")
.setName(existingUser.getName())
.setEmail(existingUser.getEmail())
.build(), this);
public void callback(CallbackContext context) {
super.callback(context);
context.authenticate(UserIdentity.builder()
- .setLogin(login)
.setProviderLogin(login)
.setEmail(login + "@toto.com")
.setName("name of " + login)
private static final UserIdentity USER_IDENTITY = UserIdentity.builder()
.setProviderId("ABCD")
.setProviderLogin("johndoo")
- .setLogin("id:johndoo")
.setName("John")
.setEmail("john@email.com")
.build();
verify(threadLocalUserSession).set(any(UserSession.class));
ArgumentCaptor<UserDto> userArgumentCaptor = ArgumentCaptor.forClass(UserDto.class);
verify(jwtHttpHandler).generateToken(userArgumentCaptor.capture(), eq(request), eq(response));
- assertThat(userArgumentCaptor.getValue().getLogin()).isEqualTo(USER_IDENTITY.getLogin());
assertThat(userArgumentCaptor.getValue().getExternalId()).isEqualTo(USER_IDENTITY.getProviderId());
assertThat(userArgumentCaptor.getValue().getExternalLogin()).isEqualTo(USER_IDENTITY.getProviderLogin());
assertThat(userArgumentCaptor.getValue().getExternalIdentityProvider()).isEqualTo(PROVIDER_KEY);
String providerId = registration.getUserIdentity().getProviderId();
return UserTesting.newUserDto()
.setLocal(false)
- .setLogin(registration.getUserIdentity().getLogin())
.setExternalLogin(registration.getUserIdentity().getProviderLogin())
.setExternalId(providerId == null ? registration.getUserIdentity().getProviderLogin() : providerId)
.setExternalIdentityProvider(registration.getProvider().getKey());
private static UserIdentity USER_IDENTITY = UserIdentity.builder()
.setProviderId("ABCD")
.setProviderLogin("johndoo")
- .setLogin(USER_LOGIN)
.setName("John")
.setEmail("john@email.com")
.build();
.setOrganizationAlmIds(ImmutableSet.of(gitHubInstall.getOrganizationAlmId()))
.build());
- UserDto user = db.users().selectUserByLogin(USER_LOGIN).get();
+ UserDto user = db.users().selectUserByExternalLoginAndIdentityProvider(USER_IDENTITY.getProviderLogin(), GITHUB_PROVIDER.getKey()).get();
db.organizations().assertUserIsMemberOfOrganization(organization, user);
}
.setOrganizationAlmIds(null)
.build());
- UserDto user = db.users().selectUserByLogin(USER_LOGIN).get();
+ UserDto user = db.users().selectUserByExternalLoginAndIdentityProvider(USER_IDENTITY.getProviderLogin(), GITHUB_PROVIDER.getKey()).get();
db.organizations().assertUserIsNotMemberOfOrganization(organization, user);
}
.setOrganizationAlmIds(ImmutableSet.of(gitHubInstall.getOrganizationAlmId()))
.build());
- UserDto user = db.users().selectUserByLogin(USER_LOGIN).get();
+ UserDto user = db.users().selectUserByExternalLoginAndIdentityProvider(USER_IDENTITY.getProviderLogin(), BITBUCKET_PROVIDER.getKey()).get();
db.organizations().assertUserIsNotMemberOfOrganization(organization, user);
}
.setOrganizationAlmIds(ImmutableSet.of(almAppInstall.getOrganizationAlmId()))
.build());
- UserDto user = db.users().selectUserByLogin(USER_LOGIN).get();
+ UserDto user = db.users().selectUserByExternalLoginAndIdentityProvider(USER_IDENTITY.getProviderLogin(), identityProvider.getKey()).get();
db.organizations().assertUserIsNotMemberOfOrganization(organization, user);
}
db.users().insertDefaultGroup(organization, "Members");
AlmAppInstallDto gitHubInstall = db.alm().insertAlmAppInstall(a -> a.setAlm(GITHUB));
db.alm().insertOrganizationAlmBinding(organization, gitHubInstall, true);
- UserDto user = db.users().insertDisabledUser(u -> u.setLogin(USER_LOGIN));
+ UserDto user = db.users().insertDisabledUser(u -> u
+ .setLogin(USER_LOGIN)
+ .setExternalId(USER_IDENTITY.getProviderId())
+ .setExternalIdentityProvider(GITHUB_PROVIDER.getKey())
+ );
underTest.register(UserRegistration.builder()
.setUserIdentity(USER_IDENTITY)
private System2 system2 = new AlwaysIncreasingSystem2();
- private static String USER_LOGIN = "github-johndoo";
+ private static String USER_LOGIN = "johndoo";
private static UserIdentity USER_IDENTITY = UserIdentity.builder()
.setProviderId("ABCD")
.setProviderLogin("johndoo")
- .setLogin(USER_LOGIN)
.setName("John")
.setEmail("john@email.com")
.build();
public void authenticate_new_user() {
organizationFlags.setEnabled(true);
- underTest.register(UserRegistration.builder()
+ UserDto createdUser = underTest.register(UserRegistration.builder()
.setUserIdentity(USER_IDENTITY)
.setProvider(IDENTITY_PROVIDER)
.setSource(Source.realm(BASIC, IDENTITY_PROVIDER.getName()))
.setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
.build());
- UserDto user = db.users().selectUserByLogin(USER_LOGIN).get();
+ UserDto user = db.users().selectUserByLogin(createdUser.getLogin()).get();
assertThat(user).isNotNull();
assertThat(user.isActive()).isTrue();
assertThat(user.getName()).isEqualTo("John");
checkGroupMembership(user);
}
+ @Test
+ public void authenticate_new_user_with_sq_identity() {
+ organizationFlags.setEnabled(false);
+ GroupDto defaultGroup = insertDefaultGroup();
+
+ TestIdentityProvider sqIdentityProvider = new TestIdentityProvider()
+ .setKey("sonarqube")
+ .setName("sonarqube identity name")
+ .setEnabled(true)
+ .setAllowsUsersToSignUp(true);
+
+ UserDto createdUser = underTest.register(UserRegistration.builder()
+ .setUserIdentity(USER_IDENTITY)
+ .setProvider(sqIdentityProvider)
+ .setSource(Source.realm(BASIC, sqIdentityProvider.getName()))
+ .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
+ .build());
+
+ UserDto user = db.users().selectUserByLogin(createdUser.getLogin()).get();
+ assertThat(user).isNotNull();
+ assertThat(user.isActive()).isTrue();
+ assertThat(user.getLogin()).isEqualTo("johndoo");
+ assertThat(user.getName()).isEqualTo("John");
+ assertThat(user.getEmail()).isEqualTo("john@email.com");
+ assertThat(user.getExternalLogin()).isEqualTo("johndoo");
+ assertThat(user.getExternalIdentityProvider()).isEqualTo("sonarqube");
+ assertThat(user.getExternalId()).isEqualTo("ABCD");
+ assertThat(user.isLocal()).isFalse();
+ assertThat(user.isRoot()).isFalse();
+ checkGroupMembership(user, defaultGroup);
+ }
+
@Test
public void authenticate_new_user_generate_login_when_no_login_provided() {
organizationFlags.setEnabled(true);
GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
GroupDto group2 = db.users().insertGroup(db.getDefaultOrganization(), "group2");
- authenticate(USER_LOGIN, "group1", "group2", "group3");
+ UserDto loggedInUser = authenticate(USER_LOGIN, "group1", "group2", "group3");
- Optional<UserDto> user = db.users().selectUserByLogin(USER_LOGIN);
+ Optional<UserDto> user = db.users().selectUserByLogin(loggedInUser.getLogin());
checkGroupMembership(user.get(), group1, group2);
}
@Test
public void does_not_force_default_group_when_authenticating_new_user_if_organizations_are_enabled() {
organizationFlags.setEnabled(true);
- UserDto user = db.users().insertUser();
+ UserDto user = db.users().insertUser(newUserDto()
+ .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey())
+ .setExternalLogin(USER_IDENTITY.getProviderLogin())
+ );
GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
GroupDto defaultGroup = insertDefaultGroup();
db.users().insertMember(group1, user);
db.users().insertMember(defaultGroup, user);
- authenticate(user.getLogin(), "group1");
+ authenticate(user.getExternalLogin(), "group1");
checkGroupMembership(user, group1);
}
organizationFlags.setEnabled(true);
settings.setProperty(ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS.getKey(), true);
- underTest.register(UserRegistration.builder()
+ UserDto user = underTest.register(UserRegistration.builder()
.setUserIdentity(USER_IDENTITY)
.setProvider(IDENTITY_PROVIDER)
.setSource(Source.local(BASIC))
.setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
.build());
- assertThat(db.users().selectUserByLogin(USER_LOGIN).get().isOnboarded()).isFalse();
+ assertThat(db.users().selectUserByLogin(user.getLogin()).get().isOnboarded()).isFalse();
}
@Test
organizationFlags.setEnabled(true);
settings.setProperty(ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS.getKey(), false);
- underTest.register(UserRegistration.builder()
+ UserDto user = underTest.register(UserRegistration.builder()
.setUserIdentity(USER_IDENTITY)
.setProvider(IDENTITY_PROVIDER)
.setSource(Source.local(BASIC))
.setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
.build());
- assertThat(db.users().selectUserByLogin(USER_LOGIN).get().isOnboarded()).isTrue();
+ assertThat(db.users().selectUserByLogin(user.getLogin()).get().isOnboarded()).isTrue();
}
@Test
organizationFlags.setEnabled(true);
UserIdentity newUser = UserIdentity.builder()
.setProviderId(null)
- .setLogin("john")
.setProviderLogin("johndoo")
.setName("JOhn")
.build();
- underTest.register(UserRegistration.builder()
+ UserDto user = underTest.register(UserRegistration.builder()
.setUserIdentity(newUser)
.setProvider(IDENTITY_PROVIDER)
.setSource(Source.local(BASIC))
.setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
.build());
- assertThat(db.users().selectUserByLogin(newUser.getLogin()).get())
+ assertThat(db.users().selectUserByLogin(user.getLogin()).get())
.extracting(UserDto::getLogin, UserDto::getExternalId, UserDto::getExternalLogin)
- .contains("john", "johndoo", "johndoo");
+ .contains(user.getLogin(), "johndoo", "johndoo");
}
@Test
UserDto existingUser = db.users().insertUser(u -> u.setEmail("john@email.com"));
UserIdentity newUser = UserIdentity.builder()
.setProviderLogin("johndoo")
- .setLogin("new_login")
.setName(existingUser.getName())
.setEmail(existingUser.getEmail())
.build();
- underTest.register(UserRegistration.builder()
+ UserDto user = underTest.register(UserRegistration.builder()
.setUserIdentity(newUser)
.setProvider(IDENTITY_PROVIDER)
.setSource(Source.local(BASIC))
.setExistingEmailStrategy(ExistingEmailStrategy.ALLOW)
.build());
- UserDto newUserReloaded = db.users().selectUserByLogin(newUser.getLogin()).get();
+ UserDto newUserReloaded = db.users().selectUserByLogin(user.getLogin()).get();
assertThat(newUserReloaded.getEmail()).isEqualTo(existingUser.getEmail());
UserDto existingUserReloaded = db.users().selectUserByLogin(existingUser.getLogin()).get();
assertThat(existingUserReloaded.getEmail()).isNull();
UserDto existingUser = db.users().insertUser(u -> u.setEmail("john@email.com"));
UserIdentity newUser = UserIdentity.builder()
.setProviderLogin("johndoo")
- .setLogin("new_login")
.setName(existingUser.getName())
.setEmail(existingUser.getEmail())
.build();
@Test
public void authenticate_and_update_existing_user_matching_login() {
+ insertDefaultGroup();
db.users().insertUser(u -> u
- .setLogin(USER_LOGIN)
.setName("Old name")
.setEmail("Old email")
.setExternalId("old id")
.setExternalLogin("old identity")
.setExternalIdentityProvider("old provide"));
- underTest.register(UserRegistration.builder()
+ UserDto user = underTest.register(UserRegistration.builder()
.setUserIdentity(USER_IDENTITY)
.setProvider(IDENTITY_PROVIDER)
.setSource(Source.local(BASIC))
.setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
.build());
- assertThat(db.users().selectUserByLogin(USER_LOGIN).get())
+ assertThat(db.users().selectUserByLogin(user.getLogin()).get())
.extracting(UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider, UserDto::isActive)
.contains("John", "john@email.com", "ABCD", "johndoo", "github", true);
}
.setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
.build());
- assertThat(db.users().selectUserByLogin("Old login")).isNotPresent();
assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
.extracting(UserDto::getLogin, UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider,
UserDto::isActive)
.setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
.build());
- assertThat(db.users().selectUserByLogin("Old login")).isNotPresent();
assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
- .extracting(UserDto::getLogin, UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider,
+ .extracting(UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider,
UserDto::isActive)
- .contains(USER_LOGIN, "John", "john@email.com", "ABCD", "johndoo", "github", true);
+ .contains("John", "john@email.com", "ABCD", "johndoo", "github", true);
}
@Test
- public void authenticate_existing_user_and_update_only_login() {
+ public void authenticate_existing_user_and_login_should_not_be_updated() {
UserDto user = db.users().insertUser(u -> u
.setLogin("old login")
.setName(USER_IDENTITY.getName())
.setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
.build());
- assertThat(db.users().selectUserByLogin("Old login")).isNotPresent();
- assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
- .extracting(UserDto::getLogin, UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider,
- UserDto::isActive)
- .containsExactlyInAnyOrder(USER_LOGIN, USER_IDENTITY.getName(), USER_IDENTITY.getEmail(), USER_IDENTITY.getProviderId(), USER_IDENTITY.getProviderLogin(),
- IDENTITY_PROVIDER.getKey(),
- true);
- }
-
- @Test
- public void authenticate_existing_user_and_update_only_identity_provider_key() {
- UserDto user = db.users().insertUser(u -> u
- .setLogin(USER_LOGIN)
- .setName(USER_IDENTITY.getName())
- .setEmail(USER_IDENTITY.getEmail())
- .setExternalId(USER_IDENTITY.getProviderId())
- .setExternalLogin(USER_IDENTITY.getProviderLogin())
- .setExternalIdentityProvider("old identity provider"));
-
- underTest.register(UserRegistration.builder()
- .setUserIdentity(USER_IDENTITY)
- .setProvider(IDENTITY_PROVIDER)
- .setSource(Source.local(BASIC))
- .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
- .build());
-
+ //no new user should be created
+ assertThat(db.countRowsOfTable(db.getSession(), "users")).isEqualTo(1);
assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
.extracting(UserDto::getLogin, UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider,
UserDto::isActive)
- .containsExactlyInAnyOrder(USER_LOGIN, USER_IDENTITY.getName(), USER_IDENTITY.getEmail(), USER_IDENTITY.getProviderId(), USER_IDENTITY.getProviderLogin(),
+ .containsExactlyInAnyOrder("old login", USER_IDENTITY.getName(), USER_IDENTITY.getEmail(), USER_IDENTITY.getProviderId(), USER_IDENTITY.getProviderLogin(),
IDENTITY_PROVIDER.getKey(),
true);
}
@Test
- public void authenticate_existing_user_matching_login_when_external_id_is_null() {
+ public void authenticate_existing_user_matching_external_login_when_external_id_is_null() {
UserDto user = db.users().insertUser(u -> u
- .setLogin(USER_LOGIN)
.setName("Old name")
.setEmail("Old email")
.setExternalId("Old id")
- .setExternalLogin("old identity")
+ .setExternalLogin("johndoo")
.setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
underTest.register(UserRegistration.builder()
.setUserIdentity(UserIdentity.builder()
.setProviderId(null)
.setProviderLogin("johndoo")
- .setLogin(USER_LOGIN)
.setName("John")
.setEmail("john@email.com")
.build())
assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
.extracting(UserDto::getLogin, UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider,
UserDto::isActive)
- .contains(user.getLogin(), user.getName(), user.getEmail(), user.getExternalId(), user.getExternalLogin(), user.getExternalIdentityProvider(), true);
+ .contains(user.getExternalLogin(), user.getName(), user.getEmail(), user.getExternalId(), user.getExternalLogin(), user.getExternalIdentityProvider(), true);
}
@Test
.setActive(false)
.setName("Old name")
.setEmail("Old email")
- .setExternalId("old id")
- .setExternalLogin("old identity")
- .setExternalIdentityProvider("old provide"));
+ .setExternalId("Old id")
+ .setExternalLogin(USER_IDENTITY.getProviderLogin())
+ .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
underTest.register(UserRegistration.builder()
.setUserIdentity(USER_IDENTITY)
public void authenticate_existing_user_when_email_already_exists_and_strategy_is_ALLOW() {
organizationFlags.setEnabled(true);
UserDto existingUser = db.users().insertUser(u -> u.setEmail("john@email.com"));
- UserDto currentUser = db.users().insertUser(u -> u.setEmail(null));
+ UserDto currentUser = db.users().insertUser(u -> u.setExternalLogin("johndoo").setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()).setEmail(null));
+
UserIdentity userIdentity = UserIdentity.builder()
- .setLogin(currentUser.getLogin())
- .setProviderLogin("johndoo")
+ .setProviderLogin(currentUser.getExternalLogin())
.setName("John")
.setEmail("john@email.com")
.build();
- underTest.register(UserRegistration.builder()
+ currentUser = underTest.register(UserRegistration.builder()
.setUserIdentity(userIdentity)
.setProvider(IDENTITY_PROVIDER)
.setSource(Source.local(BASIC))
.setExistingEmailStrategy(ExistingEmailStrategy.ALLOW)
.build());
- UserDto currentUserReloaded = db.users().selectUserByLogin(currentUser.getLogin()).get();
- assertThat(currentUserReloaded.getEmail()).isEqualTo("john@email.com");
UserDto existingUserReloaded = db.users().selectUserByLogin(existingUser.getLogin()).get();
assertThat(existingUserReloaded.getEmail()).isNull();
+
+ UserDto currentUserReloaded = db.users().selectUserByLogin(currentUser.getLogin()).get();
+ assertThat(currentUserReloaded.getEmail()).isEqualTo("john@email.com");
+
}
@Test
UserDto existingUser = db.users().insertUser(u -> u.setEmail("john@email.com"));
UserDto currentUser = db.users().insertUser(u -> u.setEmail(null));
UserIdentity userIdentity = UserIdentity.builder()
- .setLogin(currentUser.getLogin())
.setProviderLogin("johndoo")
.setName("John")
.setEmail("john@email.com")
UserDto existingUser = db.users().insertUser(u -> u.setEmail("john@email.com"));
UserDto currentUser = db.users().insertUser(u -> u.setEmail(null));
UserIdentity userIdentity = UserIdentity.builder()
- .setLogin(currentUser.getLogin())
.setProviderLogin("johndoo")
.setName("John")
.setEmail("john@email.com")
UserDto currentUser = db.users().insertUser(u -> u.setEmail("john@email.com")
.setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
UserIdentity userIdentity = UserIdentity.builder()
- .setLogin(currentUser.getLogin())
.setProviderId(currentUser.getExternalId())
.setProviderLogin(currentUser.getExternalLogin())
.setName("John")
public void authenticate_existing_user_and_add_new_groups() {
organizationFlags.setEnabled(true);
UserDto user = db.users().insertUser(newUserDto()
- .setLogin(USER_LOGIN)
+ .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey())
+ .setExternalLogin(USER_IDENTITY.getProviderLogin())
.setActive(true)
.setName("John"));
GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
GroupDto group2 = db.users().insertGroup(db.getDefaultOrganization(), "group2");
- authenticate(USER_LOGIN, "group1", "group2", "group3");
+ authenticate(USER_IDENTITY.getProviderLogin(), "group1", "group2", "group3");
checkGroupMembership(user, group1, group2);
}
public void authenticate_existing_user_and_remove_groups() {
organizationFlags.setEnabled(true);
UserDto user = db.users().insertUser(newUserDto()
- .setLogin(USER_LOGIN)
+ .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey())
+ .setExternalLogin(USER_IDENTITY.getProviderLogin())
.setActive(true)
.setName("John"));
GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
db.users().insertMember(group1, user);
db.users().insertMember(group2, user);
- authenticate(USER_LOGIN, "group1");
+ authenticate(USER_IDENTITY.getProviderLogin(), "group1");
checkGroupMembership(user, group1);
}
@Test
public void authenticate_existing_user_and_remove_all_groups_expect_default_when_organizations_are_disabled() {
organizationFlags.setEnabled(false);
- UserDto user = db.users().insertUser();
+ UserDto user = db.users().insertUser(newUserDto()
+ .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey())
+ .setExternalLogin(USER_IDENTITY.getProviderLogin())
+ );
GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
GroupDto group2 = db.users().insertGroup(db.getDefaultOrganization(), "group2");
GroupDto defaultGroup = insertDefaultGroup();
db.users().insertMember(group2, user);
db.users().insertMember(defaultGroup, user);
- authenticate(user.getLogin());
+ authenticate(user.getExternalLogin());
checkGroupMembership(user, defaultGroup);
}
@Test
public void does_not_force_default_group_when_authenticating_existing_user_when_organizations_are_enabled() {
organizationFlags.setEnabled(true);
- UserDto user = db.users().insertUser();
+ UserDto user = db.users().insertUser(newUserDto()
+ .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey())
+ .setExternalLogin(USER_IDENTITY.getProviderLogin())
+ );
GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
GroupDto defaultGroup = insertDefaultGroup();
db.users().insertMember(group1, user);
db.users().insertMember(defaultGroup, user);
- authenticate(user.getLogin(), "group1");
+ authenticate(user.getExternalLogin(), "group1");
checkGroupMembership(user, group1);
}
organizationFlags.setEnabled(true);
OrganizationDto org = db.organizations().insert();
UserDto user = db.users().insertUser(newUserDto()
- .setLogin(USER_LOGIN)
+ .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey())
+ .setExternalLogin(USER_IDENTITY.getProviderLogin())
.setActive(true)
.setName("John"));
String groupName = "a-group";
underTest.register(UserRegistration.builder()
.setUserIdentity(UserIdentity.builder()
.setProviderLogin("johndoo")
- .setLogin(user.getLogin())
.setName(user.getName())
.setGroups(newHashSet(groupName))
.build())
checkGroupMembership(user, groupInDefaultOrg);
}
- private void authenticate(String login, String... groups) {
- underTest.register(UserRegistration.builder()
+ private UserDto authenticate(String providerLogin, String... groups) {
+ return underTest.register(UserRegistration.builder()
.setUserIdentity(UserIdentity.builder()
- .setProviderLogin("johndoo")
- .setLogin(login)
+ .setProviderLogin(providerLogin)
.setName("John")
// No group
.setGroups(stream(groups).collect(MoreCollectors.toSet()))
}
private void checkGroupMembership(UserDto user, GroupDto... expectedGroups) {
- assertThat(db.users().selectGroupIdsOfUser(user)).containsOnly(stream(expectedGroups).map(GroupDto::getId).collect(Collectors.toList()).toArray(new Integer[] {}));
+ assertThat(db.users().selectGroupIdsOfUser(user)).containsOnly(stream(expectedGroups).map(GroupDto::getId).collect(Collectors.toList()).toArray(new Integer[]{}));
}
private GroupDto insertDefaultGroup() {
organizationUpdater));
@Test
- public void update_login_from_sonarqube_account() {
+ public void update_login_from_sonarqube_account_when_user_is_local() {
userSession.logIn().setSystemAdministrator();
UserDto user = db.users().insertUser(u -> u
.setLogin("old_login")
assertThat(userReloaded.getSalt()).isNotNull().isEqualTo(user.getSalt());
}
+ @Test
+ public void update_login_from_sonarqube_account_when_user_is_not_local() {
+ userSession.logIn().setSystemAdministrator();
+ UserDto user = db.users().insertUser(u -> u
+ .setLogin("old_login")
+ .setLocal(false)
+ .setExternalIdentityProvider("sonarqube")
+ .setExternalLogin("old_login")
+ .setExternalId("old_login"));
+
+ ws.newRequest()
+ .setParam("login", user.getLogin())
+ .setParam("newLogin", "new_login")
+ .execute();
+
+ assertThat(db.getDbClient().userDao().selectByLogin(db.getSession(), "old_login")).isNull();
+ UserDto userReloaded = db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid());
+ assertThat(userReloaded.getLogin()).isEqualTo("new_login");
+ assertThat(userReloaded.getExternalLogin()).isEqualTo("new_login");
+ assertThat(userReloaded.getExternalId()).isEqualTo("new_login");
+ assertThat(userReloaded.isLocal()).isFalse();
+ assertThat(userReloaded.getCryptedPassword()).isNotNull().isEqualTo(user.getCryptedPassword());
+ assertThat(userReloaded.getSalt()).isNotNull().isEqualTo(user.getSalt());
+ }
+
@Test
public void update_login_from_external_account() {
userSession.logIn().setSystemAdministrator();
import org.sonar.api.user.UserGroupValidation;
import static java.util.Objects.requireNonNull;
-import static org.apache.commons.lang.StringUtils.isBlank;
import static org.apache.commons.lang.StringUtils.isNotBlank;
import static org.sonar.api.utils.Preconditions.checkArgument;
@Nullable
private final String id;
private final String providerLogin;
- @Nullable
- private final String login;
private final String name;
@Nullable
private final String email;
private UserIdentity(Builder builder) {
this.id = builder.id;
this.providerLogin = builder.providerLogin;
- this.login = builder.login;
this.name = builder.name;
this.email = builder.email;
this.groupsProvided = builder.groupsProvided;
*
* Since 7.4, a unique login will be generated if result is null and the user referenced by {@link #getProviderId()}
* or {@link #getProviderLogin()} does not already exist.
+ *
+ * @deprecated since 8.0, should not be used as it is internal managed field
+ *
+ * @return null
*/
@CheckForNull
+ @Deprecated
public String getLogin() {
- return login;
+ return null;
}
/**
public static class Builder {
private String id;
private String providerLogin;
- private String login;
private String name;
private String email;
private boolean groupsProvided = false;
/**
* @see UserIdentity#getLogin()
+ *
+ * @deprecated since 8.0, has no effect as it is internal managed field
*/
+ @Deprecated
public Builder setLogin(@Nullable String login) {
- this.login = login;
return this;
}
public UserIdentity build() {
validateId(id);
validateProviderLogin(providerLogin);
- validateLogin(login);
validateName(name);
validateEmail(email);
return new UserIdentity(this);
checkArgument(providerLogin.length() <= 255, "Provider login size is incorrect (maximum 255 characters)");
}
- private static void validateLogin(@Nullable String login) {
- checkArgument(isBlank(login) || (login.length() <= 255 && login.length() >= 2), "User login size is incorrect (Between 2 and 255 characters)");
- }
-
private static void validateName(String name) {
checkArgument(isNotBlank(name), "User name must not be blank");
checkArgument(name.length() <= 200, "User name size is too big (200 characters max)");
UserIdentity underTest = UserIdentity.builder()
.setProviderId("4321")
.setProviderLogin("john")
- .setLogin("1234")
.setName("John")
.setEmail("john@email.com")
.build();
assertThat(underTest.getProviderId()).isEqualTo("4321");
assertThat(underTest.getProviderLogin()).isEqualTo("john");
- assertThat(underTest.getLogin()).isEqualTo("1234");
assertThat(underTest.getName()).isEqualTo("John");
assertThat(underTest.getEmail()).isEqualTo("john@email.com");
assertThat(underTest.shouldSyncGroups()).isFalse();
assertThat(underTest.getProviderLogin()).isEqualTo("john");
assertThat(underTest.getName()).isEqualTo("John");
assertThat(underTest.getProviderId()).isNull();
- assertThat(underTest.getLogin()).isNull();
assertThat(underTest.getEmail()).isNull();
assertThat(underTest.shouldSyncGroups()).isFalse();
assertThat(underTest.getGroups()).isEmpty();
UserIdentity.builder()
.setProviderId(Strings.repeat("1", 256))
.setProviderLogin("john")
- .setLogin("1234")
.setName("John")
.build();
}
- @Test
- public void fail_when_login_is_too_long() {
- thrown.expect(IllegalArgumentException.class);
- thrown.expectMessage("User login size is incorrect (Between 2 and 255 characters)");
- UserIdentity.builder()
- .setProviderLogin("john")
- .setLogin(Strings.repeat("1", 256))
- .setName("John")
- .setEmail("john@email.com")
- .build();
- }
-
- @Test
- public void fail_when_login_is_too_small() {
- thrown.expect(IllegalArgumentException.class);
- thrown.expectMessage("User login size is incorrect (Between 2 and 255 characters)");
- UserIdentity.builder()
- .setProviderLogin("john")
- .setLogin("j")
- .setName("John")
- .setEmail("john@email.com")
- .build();
- }
-
@Test
public void fail_when_provider_login_is_null() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Provider login must not be blank");
UserIdentity.builder()
- .setLogin("1234")
.setName("John")
.setEmail("john@email.com")
.build();
thrown.expectMessage("Provider login must not be blank");
UserIdentity.builder()
.setProviderLogin("")
- .setLogin("1234")
.setName("John")
.setEmail("john@email.com")
.build();
thrown.expectMessage("Provider login size is incorrect (maximum 255 characters)");
UserIdentity.builder()
.setProviderLogin(Strings.repeat("1", 256))
- .setLogin("1234")
.setName("John")
.setEmail("john@email.com")
.build();
thrown.expectMessage("User name must not be blank");
UserIdentity.builder()
.setProviderLogin("john")
- .setLogin("1234")
.setEmail("john@email.com")
.build();
}
thrown.expectMessage("User name must not be blank");
UserIdentity.builder()
.setProviderLogin("john")
- .setLogin("1234")
.setName("")
.setEmail("john@email.com")
.build();
thrown.expectMessage("User name size is too big (200 characters max)");
UserIdentity.builder()
.setProviderLogin("john")
- .setLogin("1234")
.setName(Strings.repeat("1", 201))
.setEmail("john@email.com")
.build();
thrown.expectMessage("User email size is too big (100 characters max)");
UserIdentity.builder()
.setProviderLogin("john")
- .setLogin("1234")
.setName("John")
.setEmail(Strings.repeat("1", 101))
.build();
public void create_user_with_groups() {
UserIdentity underTest = UserIdentity.builder()
.setProviderLogin("john")
- .setLogin("1234")
.setName("John")
.setEmail("john@email.com")
.setGroups(newHashSet("admin", "user"))
UserIdentity.builder()
.setProviderLogin("john")
- .setLogin("1234")
.setName("John")
.setEmail("john@email.com")
.setGroups(null);
UserIdentity.builder()
.setProviderLogin("john")
- .setLogin("1234")
.setName("John")
.setEmail("john@email.com")
.setGroups(newHashSet(""));
UserIdentity.builder()
.setProviderLogin("john")
- .setLogin("1234")
.setName("John")
.setEmail("john@email.com")
.setGroups(newHashSet(" "));
UserIdentity.builder()
.setProviderLogin("john")
- .setLogin("1234")
.setName("John")
.setEmail("john@email.com")
.setGroups(newHashSet((String)null));
UserIdentity.builder()
.setProviderLogin("john")
- .setLogin("1234")
.setName("John")
.setEmail("john@email.com")
.setGroups(newHashSet("Anyone"));
UserIdentity.builder()
.setProviderLogin("john")
- .setLogin("1234")
.setName("John")
.setEmail("john@email.com")
.setGroups(newHashSet(Strings.repeat("group", 300)));