Browse Source

SONAR-12531 drop usage of UserIdentity#getLogin and UserIdentity#setLogin (#2139)

* remove login generation strategy
* add migration to remove gh login strategy + code review fixes
* support same login for new user and update login for SQ authority
tags/8.1.0.31237
Jacek 4 years ago
parent
commit
caf0309d6e
33 changed files with 297 additions and 383 deletions
  1. 0
    23
      server/sonar-auth-github/src/main/java/org/sonar/auth/github/GitHubSettings.java
  2. 5
    10
      server/sonar-auth-github/src/main/java/org/sonar/auth/github/UserIdentityFactoryImpl.java
  3. 0
    51
      server/sonar-auth-github/src/main/java/org/sonar/auth/github/UserIdentityGenerator.java
  4. 0
    3
      server/sonar-auth-github/src/test/java/org/sonar/auth/github/GitHubIdentityProviderTest.java
  5. 1
    1
      server/sonar-auth-github/src/test/java/org/sonar/auth/github/GitHubModuleTest.java
  6. 4
    18
      server/sonar-auth-github/src/test/java/org/sonar/auth/github/GitHubSettingsTest.java
  7. 4
    26
      server/sonar-auth-github/src/test/java/org/sonar/auth/github/IntegrationTest.java
  8. 2
    55
      server/sonar-auth-github/src/test/java/org/sonar/auth/github/UserIdentityFactoryImplTest.java
  9. 0
    1
      server/sonar-auth-gitlab/src/test/java/org/sonar/auth/gitlab/IntegrationTest.java
  10. 0
    1
      server/sonar-auth-saml/src/main/java/org/sonar/auth/saml/SamlIdentityProvider.java
  11. 2
    4
      server/sonar-auth-saml/src/test/java/org/sonar/auth/saml/SamlIdentityProviderTest.java
  12. 12
    5
      server/sonar-db-dao/src/testFixtures/java/org/sonar/db/user/UserDbTester.java
  13. 1
    0
      server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v80/DbVersion80.java
  14. 39
    0
      server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v80/RemoveGitHubLoginGenerationStrategyProperty.java
  15. 1
    1
      server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v80/DbVersion80Test.java
  16. 65
    0
      server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v80/RemoveGitHubLoginGenerationStrategyPropertyTest.java
  17. 11
    0
      server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v80/RemoveGitHubLoginGenerationStrategyPropertyTest/schema.sql
  18. 0
    1
      server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/CredentialsExternalAuthentication.java
  19. 0
    1
      server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/HttpHeadersAuthentication.java
  20. 8
    21
      server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/UserRegistrarImpl.java
  21. 1
    1
      server/sonar-webserver-auth/src/main/java/org/sonar/server/user/UserUpdater.java
  22. 0
    2
      server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/BaseContextFactoryTest.java
  23. 0
    3
      server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/CredentialsExternalAuthenticationTest.java
  24. 1
    1
      server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/HttpHeadersAuthenticationTest.java
  25. 0
    1
      server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/InitFilterTest.java
  26. 0
    2
      server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/OAuth2CallbackFilterTest.java
  27. 0
    2
      server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/OAuth2ContextFactoryTest.java
  28. 0
    1
      server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/TestUserRegistrar.java
  29. 9
    6
      server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/UserRegistrarImplOrgMembershipSyncTest.java
  30. 96
    87
      server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/UserRegistrarImplTest.java
  31. 26
    1
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/user/ws/UpdateLoginActionTest.java
  32. 9
    12
      sonar-plugin-api/src/main/java/org/sonar/api/server/authentication/UserIdentity.java
  33. 0
    42
      sonar-plugin-api/src/test/java/org/sonar/api/server/authentication/UserIdentityTest.java

+ 0
- 23
server/sonar-auth-github/src/main/java/org/sonar/auth/github/GitHubSettings.java View File

@@ -26,10 +26,8 @@ import javax.annotation.Nullable;
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 {
@@ -42,11 +40,6 @@ 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";
@@ -74,10 +67,6 @@ public class GitHubSettings {
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);
}
@@ -138,18 +127,6 @@ public class GitHubSettings {
.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.")

+ 5
- 10
server/sonar-auth-github/src/main/java/org/sonar/auth/github/UserIdentityFactoryImpl.java View File

@@ -24,23 +24,13 @@ import java.util.stream.Collectors;
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) {
@@ -51,4 +41,9 @@ public class UserIdentityFactoryImpl implements UserIdentityFactory {
return builder.build();
}

private static String generateName(GsonUser gson) {
String name = gson.getName();
return name == null || name.isEmpty() ? gson.getLogin() : name;
}

}

+ 0
- 51
server/sonar-auth-github/src/main/java/org/sonar/auth/github/UserIdentityGenerator.java View File

@@ -1,51 +0,0 @@
/*
* 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);
}
}

+ 0
- 3
server/sonar-auth-github/src/test/java/org/sonar/auth/github/GitHubIdentityProviderTest.java View File

@@ -29,7 +29,6 @@ import static org.assertj.core.api.Assertions.assertThat;
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 {

@@ -55,7 +54,6 @@ 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();

@@ -176,7 +174,6 @@ public class GitHubIdentityProviderTest {
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);

+ 1
- 1
server/sonar-auth-github/src/test/java/org/sonar/auth/github/GitHubModuleTest.java View File

@@ -31,7 +31,7 @@ public class GitHubModuleTest {
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);
}

}

+ 4
- 18
server/sonar-auth-github/src/test/java/org/sonar/auth/github/GitHubSettingsTest.java View File

@@ -24,8 +24,6 @@ import org.sonar.api.config.PropertyDefinitions;
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 {

@@ -37,7 +35,6 @@ 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();
@@ -51,7 +48,6 @@ public class GitHubSettingsTest {
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();
}
@@ -61,7 +57,6 @@ public class GitHubSettingsTest {
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();
}
@@ -78,12 +73,6 @@ public class GitHubSettingsTest {
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");
@@ -132,31 +121,28 @@ public class GitHubSettingsTest {
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);
}
}

+ 4
- 26
server/sonar-auth-github/src/test/java/org/sonar/auth/github/IntegrationTest.java View File

@@ -54,7 +54,7 @@ public class IntegrationTest {
// 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);

@@ -111,7 +111,7 @@ public class IntegrationTest {

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();
@@ -156,7 +156,7 @@ public class IntegrationTest {

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();
@@ -176,7 +176,7 @@ public class IntegrationTest {

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();
@@ -294,7 +294,6 @@ public class IntegrationTest {
@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
@@ -314,27 +313,6 @@ public class IntegrationTest {
}
}

@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());

+ 2
- 55
server/sonar-auth-github/src/test/java/org/sonar/auth/github/UserIdentityFactoryImplTest.java View File

@@ -19,8 +19,6 @@
*/
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;
@@ -36,56 +34,15 @@ public class UserIdentityFactoryImplTest {
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();
}
@@ -107,14 +64,4 @@ public class UserIdentityFactoryImplTest {

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);
}
}

+ 0
- 1
server/sonar-auth-gitlab/src/test/java/org/sonar/auth/gitlab/IntegrationTest.java View File

@@ -94,7 +94,6 @@ public class IntegrationTest {
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");

+ 0
- 1
server/sonar-auth-saml/src/main/java/org/sonar/auth/saml/SamlIdentityProvider.java View File

@@ -111,7 +111,6 @@ public class SamlIdentityProvider implements OAuth2IdentityProvider {
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(

+ 2
- 4
server/sonar-auth-saml/src/test/java/org/sonar/auth/saml/SamlIdentityProviderTest.java View File

@@ -111,7 +111,7 @@ public class SamlIdentityProviderTest {
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();
}

@@ -122,7 +122,6 @@ public class SamlIdentityProviderTest {

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");
@@ -136,7 +135,6 @@ public class SamlIdentityProviderTest {

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");
@@ -151,7 +149,7 @@ public class SamlIdentityProviderTest {

underTest.callback(callbackContext);

assertThat(callbackContext.userIdentity.getLogin()).isEqualTo("johndoe");
assertThat(callbackContext.userIdentity.getProviderLogin()).isEqualTo("johndoe");
assertThat(callbackContext.userIdentity.getGroups()).isEmpty();
}


+ 12
- 5
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/user/UserDbTester.java View File

@@ -41,11 +41,6 @@ import static com.google.common.base.Preconditions.checkArgument;
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
@@ -117,6 +112,18 @@ public class UserDbTester {
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

+ 1
- 0
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v80/DbVersion80.java View File

@@ -35,6 +35,7 @@ public class DbVersion80 implements DbVersion {
.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)
;
}
}

+ 39
- 0
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v80/RemoveGitHubLoginGenerationStrategyProperty.java View File

@@ -0,0 +1,39 @@
/*
* 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();
}
}

+ 1
- 1
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v80/DbVersion80Test.java View File

@@ -35,7 +35,7 @@ public class DbVersion80Test {

@Test
public void verify_migration_count() {
verifyMigrationCount(underTest, 9);
verifyMigrationCount(underTest, 10);
}

}

+ 65
- 0
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v80/RemoveGitHubLoginGenerationStrategyPropertyTest.java View File

@@ -0,0 +1,65 @@
/*
* 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());
}
}

+ 11
- 0
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v80/RemoveGitHubLoginGenerationStrategyPropertyTest/schema.sql View File

@@ -0,0 +1,11 @@
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");

+ 0
- 1
server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/CredentialsExternalAuthentication.java View File

@@ -133,7 +133,6 @@ public class CredentialsExternalAuthentication implements Startable {
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);

+ 0
- 1
server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/HttpHeadersAuthentication.java View File

@@ -157,7 +157,6 @@ public class HttpHeadersAuthentication implements Startable {
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);

+ 8
- 21
server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/UserRegistrarImpl.java View File

@@ -62,6 +62,7 @@ import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
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;
@@ -102,16 +103,7 @@ public class UserRegistrarImpl implements UserRegistrar {
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) {
@@ -131,10 +123,6 @@ public class UserRegistrarImpl implements UserRegistrar {
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;
@@ -180,12 +168,10 @@ public class UserRegistrarImpl implements UserRegistrar {
}

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) {
@@ -257,14 +243,15 @@ public class UserRegistrarImpl implements UserRegistrar {
.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();
}

+ 1
- 1
server/sonar-webserver-auth/src/main/java/org/sonar/server/user/UserUpdater.java View File

@@ -229,7 +229,7 @@ public class UserUpdater {
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);
}

+ 0
- 2
server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/BaseContextFactoryTest.java View File

@@ -47,7 +47,6 @@ public class BaseContextFactoryTest {
private static final UserIdentity USER_IDENTITY = UserIdentity.builder()
.setProviderId("ABCD")
.setProviderLogin("johndoo")
.setLogin("id:johndoo")
.setName("John")
.setEmail("john@email.com")
.build();
@@ -92,7 +91,6 @@ public class BaseContextFactoryTest {
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");

+ 0
- 3
server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/CredentialsExternalAuthenticationTest.java View File

@@ -92,7 +92,6 @@ public class CredentialsExternalAuthenticationTest {

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");
@@ -169,7 +168,6 @@ public class CredentialsExternalAuthenticationTest {
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));
}
@@ -182,7 +180,6 @@ public class CredentialsExternalAuthenticationTest {
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));
}

+ 1
- 1
server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/HttpHeadersAuthenticationTest.java View File

@@ -152,7 +152,7 @@ public class HttpHeadersAuthenticationTest {
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);


+ 0
- 1
server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/InitFilterTest.java View File

@@ -328,7 +328,6 @@ public class InitFilterTest {
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);

+ 0
- 2
server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/OAuth2CallbackFilterTest.java View File

@@ -289,7 +289,6 @@ public class OAuth2CallbackFilterTest {
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);
@@ -324,7 +323,6 @@ public class OAuth2CallbackFilterTest {
public void callback(CallbackContext context) {
super.callback(context);
context.authenticate(UserIdentity.builder()
.setLogin(login)
.setProviderLogin(login)
.setEmail(login + "@toto.com")
.setName("name of " + login)

+ 0
- 2
server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/OAuth2ContextFactoryTest.java View File

@@ -55,7 +55,6 @@ public class OAuth2ContextFactoryTest {
private static final UserIdentity USER_IDENTITY = UserIdentity.builder()
.setProviderId("ABCD")
.setProviderLogin("johndoo")
.setLogin("id:johndoo")
.setName("John")
.setEmail("john@email.com")
.build();
@@ -135,7 +134,6 @@ public class OAuth2ContextFactoryTest {
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);

+ 0
- 1
server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/TestUserRegistrar.java View File

@@ -32,7 +32,6 @@ public class TestUserRegistrar implements UserRegistrar {
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());

+ 9
- 6
server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/UserRegistrarImplOrgMembershipSyncTest.java View File

@@ -63,7 +63,6 @@ public class UserRegistrarImplOrgMembershipSyncTest {
private static UserIdentity USER_IDENTITY = UserIdentity.builder()
.setProviderId("ABCD")
.setProviderLogin("johndoo")
.setLogin(USER_LOGIN)
.setName("John")
.setEmail("john@email.com")
.build();
@@ -127,7 +126,7 @@ public class UserRegistrarImplOrgMembershipSyncTest {
.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);
}

@@ -147,7 +146,7 @@ public class UserRegistrarImplOrgMembershipSyncTest {
.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);
}

@@ -167,7 +166,7 @@ public class UserRegistrarImplOrgMembershipSyncTest {
.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);
}

@@ -192,7 +191,7 @@ public class UserRegistrarImplOrgMembershipSyncTest {
.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);
}

@@ -226,7 +225,11 @@ public class UserRegistrarImplOrgMembershipSyncTest {
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)

+ 96
- 87
server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/UserRegistrarImplTest.java View File

@@ -62,12 +62,11 @@ public class UserRegistrarImplTest {

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();
@@ -111,14 +110,14 @@ public class UserRegistrarImplTest {
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");
@@ -130,6 +129,38 @@ public class UserRegistrarImplTest {
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);
@@ -162,9 +193,9 @@ public class UserRegistrarImplTest {
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);
}

@@ -185,13 +216,16 @@ public class UserRegistrarImplTest {
@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);
}
@@ -201,14 +235,14 @@ public class UserRegistrarImplTest {
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
@@ -216,14 +250,14 @@ public class UserRegistrarImplTest {
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
@@ -231,21 +265,20 @@ public class UserRegistrarImplTest {
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
@@ -254,19 +287,18 @@ public class UserRegistrarImplTest {
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();
@@ -278,7 +310,6 @@ public class UserRegistrarImplTest {
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();
@@ -356,22 +387,22 @@ public class UserRegistrarImplTest {

@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);
}
@@ -393,7 +424,6 @@ public class UserRegistrarImplTest {
.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)
@@ -417,15 +447,14 @@ public class UserRegistrarImplTest {
.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())
@@ -441,55 +470,29 @@ public class UserRegistrarImplTest {
.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())
@@ -526,7 +529,7 @@ public class UserRegistrarImplTest {
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
@@ -557,9 +560,9 @@ public class UserRegistrarImplTest {
.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)
@@ -582,25 +585,27 @@ public class UserRegistrarImplTest {
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
@@ -609,7 +614,6 @@ public class UserRegistrarImplTest {
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")
@@ -631,7 +635,6 @@ public class UserRegistrarImplTest {
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")
@@ -657,7 +660,6 @@ public class UserRegistrarImplTest {
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")
@@ -679,13 +681,14 @@ public class UserRegistrarImplTest {
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);
}
@@ -694,7 +697,8 @@ public class UserRegistrarImplTest {
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");
@@ -702,7 +706,7 @@ public class UserRegistrarImplTest {
db.users().insertMember(group1, user);
db.users().insertMember(group2, user);

authenticate(USER_LOGIN, "group1");
authenticate(USER_IDENTITY.getProviderLogin(), "group1");

checkGroupMembership(user, group1);
}
@@ -710,7 +714,10 @@ public class UserRegistrarImplTest {
@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();
@@ -718,7 +725,7 @@ public class UserRegistrarImplTest {
db.users().insertMember(group2, user);
db.users().insertMember(defaultGroup, user);

authenticate(user.getLogin());
authenticate(user.getExternalLogin());

checkGroupMembership(user, defaultGroup);
}
@@ -726,13 +733,16 @@ public class UserRegistrarImplTest {
@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);
}
@@ -742,7 +752,8 @@ public class UserRegistrarImplTest {
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";
@@ -753,7 +764,6 @@ public class UserRegistrarImplTest {
underTest.register(UserRegistration.builder()
.setUserIdentity(UserIdentity.builder()
.setProviderLogin("johndoo")
.setLogin(user.getLogin())
.setName(user.getName())
.setGroups(newHashSet(groupName))
.build())
@@ -765,11 +775,10 @@ public class UserRegistrarImplTest {
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()))
@@ -781,7 +790,7 @@ public class UserRegistrarImplTest {
}

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() {

+ 26
- 1
server/sonar-webserver-webapi/src/test/java/org/sonar/server/user/ws/UpdateLoginActionTest.java View File

@@ -68,7 +68,7 @@ public class UpdateLoginActionTest {
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")
@@ -92,6 +92,31 @@ public class UpdateLoginActionTest {
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();

+ 9
- 12
sonar-plugin-api/src/main/java/org/sonar/api/server/authentication/UserIdentity.java View File

@@ -27,7 +27,6 @@ import javax.annotation.concurrent.Immutable;
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;

@@ -42,8 +41,6 @@ public final class UserIdentity {
@Nullable
private final String id;
private final String providerLogin;
@Nullable
private final String login;
private final String name;
@Nullable
private final String email;
@@ -53,7 +50,6 @@ public final class UserIdentity {
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;
@@ -86,10 +82,15 @@ public final class UserIdentity {
*
* 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;
}

/**
@@ -134,7 +135,6 @@ public final class UserIdentity {
public static class Builder {
private String id;
private String providerLogin;
private String login;
private String name;
private String email;
private boolean groupsProvided = false;
@@ -162,9 +162,11 @@ public final class UserIdentity {

/**
* @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;
}

@@ -210,7 +212,6 @@ public final class UserIdentity {
public UserIdentity build() {
validateId(id);
validateProviderLogin(providerLogin);
validateLogin(login);
validateName(name);
validateEmail(email);
return new UserIdentity(this);
@@ -225,10 +226,6 @@ public final class UserIdentity {
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)");

+ 0
- 42
sonar-plugin-api/src/test/java/org/sonar/api/server/authentication/UserIdentityTest.java View File

@@ -37,14 +37,12 @@ public class UserIdentityTest {
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();
@@ -61,7 +59,6 @@ public class UserIdentityTest {
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();
@@ -74,41 +71,15 @@ public class UserIdentityTest {
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();
@@ -120,7 +91,6 @@ public class UserIdentityTest {
thrown.expectMessage("Provider login must not be blank");
UserIdentity.builder()
.setProviderLogin("")
.setLogin("1234")
.setName("John")
.setEmail("john@email.com")
.build();
@@ -132,7 +102,6 @@ public class UserIdentityTest {
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();
@@ -144,7 +113,6 @@ public class UserIdentityTest {
thrown.expectMessage("User name must not be blank");
UserIdentity.builder()
.setProviderLogin("john")
.setLogin("1234")
.setEmail("john@email.com")
.build();
}
@@ -155,7 +123,6 @@ public class UserIdentityTest {
thrown.expectMessage("User name must not be blank");
UserIdentity.builder()
.setProviderLogin("john")
.setLogin("1234")
.setName("")
.setEmail("john@email.com")
.build();
@@ -167,7 +134,6 @@ public class UserIdentityTest {
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();
@@ -179,7 +145,6 @@ public class UserIdentityTest {
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();
@@ -189,7 +154,6 @@ public class UserIdentityTest {
public void create_user_with_groups() {
UserIdentity underTest = UserIdentity.builder()
.setProviderLogin("john")
.setLogin("1234")
.setName("John")
.setEmail("john@email.com")
.setGroups(newHashSet("admin", "user"))
@@ -206,7 +170,6 @@ public class UserIdentityTest {

UserIdentity.builder()
.setProviderLogin("john")
.setLogin("1234")
.setName("John")
.setEmail("john@email.com")
.setGroups(null);
@@ -219,7 +182,6 @@ public class UserIdentityTest {

UserIdentity.builder()
.setProviderLogin("john")
.setLogin("1234")
.setName("John")
.setEmail("john@email.com")
.setGroups(newHashSet(""));
@@ -232,7 +194,6 @@ public class UserIdentityTest {

UserIdentity.builder()
.setProviderLogin("john")
.setLogin("1234")
.setName("John")
.setEmail("john@email.com")
.setGroups(newHashSet(" "));
@@ -245,7 +206,6 @@ public class UserIdentityTest {

UserIdentity.builder()
.setProviderLogin("john")
.setLogin("1234")
.setName("John")
.setEmail("john@email.com")
.setGroups(newHashSet((String)null));
@@ -258,7 +218,6 @@ public class UserIdentityTest {

UserIdentity.builder()
.setProviderLogin("john")
.setLogin("1234")
.setName("John")
.setEmail("john@email.com")
.setGroups(newHashSet("Anyone"));
@@ -271,7 +230,6 @@ public class UserIdentityTest {

UserIdentity.builder()
.setProviderLogin("john")
.setLogin("1234")
.setName("John")
.setEmail("john@email.com")
.setGroups(newHashSet(Strings.repeat("group", 300)));

Loading…
Cancel
Save