private void setExternalIdentity(DbSession dbSession, UserDto dto, @Nullable ExternalIdentity externalIdentity) { if (externalIdentity == null) { dto.setExternalLogin(dto.getLogin()); dto.setExternalIdentityProvider(SQ_AUTHORITY); dto.setExternalId(dto.getLogin()); dto.setLocal(true); } else { dto.setExternalLogin(externalIdentity.getLogin()); dto.setExternalIdentityProvider(externalIdentity.getProvider()); dto.setExternalId(externalIdentity.getId()); dto.setLocal(false); dto.setSalt(null); dto.setCryptedPassword(null); } UserDto existingUser = dbClient.userDao().selectByExternalIdAndIdentityProvider(dbSession, dto.getExternalId(), dto.getExternalIdentityProvider()); checkArgument(existingUser == null || Objects.equals(dto.getUuid(), existingUser.getUuid()), "A user with provider id '%s' and identity provider '%s' already exists", dto.getExternalId(), dto.getExternalIdentityProvider()); }
private boolean updateLogin(DbSession dbSession, UpdateUser updateUser, UserDto userDto, List<String> messages) { String newLogin = updateUser.login(); if (!updateUser.isLoginChanged() || !validateLoginFormat(newLogin, messages) || Objects.equals(userDto.getLogin(), newLogin)) { return false; } checkLoginUniqueness(dbSession, newLogin); dbClient.propertiesDao().selectByKeyAndMatchingValue(dbSession, DEFAULT_ISSUE_ASSIGNEE, userDto.getLogin()) .forEach(p -> dbClient.propertiesDao().saveProperty(p.setValue(newLogin))); userDto.setLogin(newLogin); if (userDto.isLocal()) { userDto.setExternalLogin(newLogin); userDto.setExternalId(newLogin); } return true; }
public static UserDto newLocalUser(String login, String name, @Nullable String email) { return newUserDto() .setLocal(true) .setName(name) .setEmail(email) .setLogin(login) .setExternalId(login) .setExternalLogin(login) .setExternalIdentityProvider("sonarqube"); }
public static UserDto newExternalUser(String login, String name, @Nullable String email) { return newUserDto() .setLocal(false) .setName(name) .setEmail(email) .setLogin(login) .setExternalId(randomAlphanumeric(40)) .setExternalLogin(randomAlphanumeric(40)) .setExternalIdentityProvider(randomAlphanumeric(40)); }
@Test public void update_only_external_identity_provider() { UserDto user = db.users().insertUser(newExternalUser(DEFAULT_LOGIN, "Marius", "marius@email.com") .setExternalId("ABCD") .setExternalLogin("john") .setExternalIdentityProvider("github")); createDefaultGroup(); underTest.updateAndCommit(session, user, new UpdateUser().setExternalIdentity(new ExternalIdentity("bitbucket", "john", "ABCD")), u -> { }); assertThat(dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN)) .extracting(UserDto::getExternalLogin, UserDto::getExternalIdentityProvider) .containsOnly("john", "bitbucket"); }
@Test public void reactivate_user_with_local_provider() { UserDto user = db.users().insertDisabledUser(u -> u.setLocal(false) .setExternalId("ABCD") .setExternalLogin("john") .setExternalIdentityProvider("github")); createDefaultGroup(); underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder() .setLogin(user.getLogin()) .setName(user.getName()) .build(), u -> { }); session.commit(); UserDto dto = dbClient.userDao().selectByUuid(session, user.getUuid()); assertThat(dto.isLocal()).isTrue(); assertThat(dto.getExternalId()).isEqualTo(user.getLogin()); assertThat(dto.getExternalLogin()).isEqualTo(user.getLogin()); assertThat(dto.getExternalIdentityProvider()).isEqualTo("sonarqube"); }
@Test public void update_only_external_login() { UserDto user = db.users().insertUser(newExternalUser(DEFAULT_LOGIN, "Marius", "marius@email.com") .setExternalId("ABCD") .setExternalLogin("john") .setExternalIdentityProvider("github")); createDefaultGroup(); underTest.updateAndCommit(session, user, new UpdateUser().setExternalIdentity(new ExternalIdentity("github", "john.smith", "ABCD")), u -> { }); assertThat(dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN)) .extracting(UserDto::getExternalLogin, UserDto::getExternalIdentityProvider) .containsOnly("john.smith", "github"); }
@Test public void reactivate_user_using_same_external_info_but_was_local() { UserDto user = db.users().insertDisabledUser(u -> u.setLocal(true) .setExternalId("ABCD") .setExternalLogin("john") .setExternalIdentityProvider("github")); createDefaultGroup(); underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder() .setLogin(user.getLogin()) .setName(user.getName()) .setExternalIdentity(new ExternalIdentity("github", "john", "ABCD")) .build(), u -> { }); session.commit(); UserDto dto = dbClient.userDao().selectByUuid(session, user.getUuid()); assertThat(dto.isLocal()).isFalse(); assertThat(dto.getExternalId()).isEqualTo("ABCD"); assertThat(dto.getExternalLogin()).isEqualTo("john"); assertThat(dto.getExternalIdentityProvider()).isEqualTo("github"); }
@Test public void update_only_external_id() { UserDto user = db.users().insertUser(newExternalUser(DEFAULT_LOGIN, "Marius", "marius@email.com") .setExternalId("1234") .setExternalLogin("john.smith") .setExternalIdentityProvider("github")); createDefaultGroup(); underTest.updateAndCommit(session, user, new UpdateUser().setExternalIdentity(new ExternalIdentity("github", "john.smith", "ABCD")), u -> { }); assertThat(dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN)) .extracting(UserDto::getExternalId) .containsOnly("ABCD"); }
@Override public UserDto register(UserRegistration registration) { this.authenticatorParameters = registration; 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()); }
@Test public void fail_to_update_user_when_external_id_and_external_provider_already_exists() { createDefaultGroup(); UserDto user = db.users().insertUser(u -> u.setActive(false)); UserDto existingUser = db.users().insertUser(u -> u.setExternalId("existing_external_id").setExternalIdentityProvider("existing_external_provider")); expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("A user with provider id 'existing_external_id' and identity provider 'existing_external_provider' already exists"); underTest.updateAndCommit(session, user, new UpdateUser() .setExternalIdentity(new ExternalIdentity(existingUser.getExternalIdentityProvider(), existingUser.getExternalLogin(), existingUser.getExternalId())), u -> { }); }
@Test public void fail_to_create_user_when_external_id_and_external_provider_already_exists() { createDefaultGroup(); UserDto existingUser = db.users().insertUser(u -> u.setExternalId("existing_external_id").setExternalIdentityProvider("existing_external_provider")); expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("A user with provider id 'existing_external_id' and identity provider 'existing_external_provider' already exists"); underTest.createAndCommit(db.getSession(), NewUser.builder() .setLogin("new_login") .setName("User") .setExternalIdentity(new ExternalIdentity(existingUser.getExternalIdentityProvider(), existingUser.getExternalLogin(), existingUser.getExternalId())) .build(), u -> { }); }
@Test public void authenticate_and_update_existing_user_matching_login() { 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() .setUserIdentity(USER_IDENTITY) .setProvider(IDENTITY_PROVIDER) .setSource(Source.local(BASIC)) .setExistingEmailStrategy(ExistingEmailStrategy.FORBID) .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW) .build()); assertThat(db.users().selectUserByLogin(USER_LOGIN).get()) .extracting(UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider, UserDto::isActive) .contains("John", "john@email.com", "ABCD", "johndoo", "github", true); }
@Test public void fail_to_reactivate_user_when_external_id_and_external_provider_already_exists() { createDefaultGroup(); UserDto user = db.users().insertUser(u -> u.setActive(false)); UserDto existingUser = db.users().insertUser(u -> u.setExternalId("existing_external_id").setExternalIdentityProvider("existing_external_provider")); expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("A user with provider id 'existing_external_id' and identity provider 'existing_external_provider' already exists"); underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder() .setLogin(user.getLogin()) .setName("Marius2") .setExternalIdentity(new ExternalIdentity(existingUser.getExternalIdentityProvider(), existingUser.getExternalLogin(), existingUser.getExternalId())) .build(), u -> { }); }
@Test public void fail_to_authenticate_existing_user_when_personal_org_does_not_exist() { organizationFlags.setEnabled(true); db.users().insertUser(u -> u .setLogin("Old login") .setExternalId(USER_IDENTITY.getProviderId()) .setExternalLogin("old identity") .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()) .setOrganizationUuid("unknown")); expectedException.expect(IllegalStateException.class); expectedException.expectMessage("Cannot find personal organization uuid 'unknown' for user 'Old login'"); underTest.register(UserRegistration.builder() .setUserIdentity(USER_IDENTITY) .setProvider(IDENTITY_PROVIDER) .setSource(Source.local(BASIC)) .setExistingEmailStrategy(ExistingEmailStrategy.FORBID) .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW) .build()); }
@Test public void authenticate_existing_user_with_login_update_and_strategy_is_ALLOW() { UserDto user = db.users().insertUser(u -> u .setLogin("Old login") .setExternalId(USER_IDENTITY.getProviderId()) .setExternalLogin("old identity") .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey())); underTest.register(UserRegistration.builder() .setUserIdentity(USER_IDENTITY) .setProvider(IDENTITY_PROVIDER) .setSource(Source.local(BASIC)) .setExistingEmailStrategy(ExistingEmailStrategy.FORBID) .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW) .build()); assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid())) .extracting(UserDto::getLogin, UserDto::getExternalLogin) .contains(USER_LOGIN, USER_IDENTITY.getProviderLogin()); }
@Test public void authenticate_and_update_existing_user_matching_external_login() { UserDto user = db.users().insertUser(u -> u .setLogin("Old login") .setName("Old name") .setEmail(USER_IDENTITY.getEmail()) .setExternalId("Old id") .setExternalLogin(USER_IDENTITY.getProviderLogin()) .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey())); underTest.register(UserRegistration.builder() .setUserIdentity(USER_IDENTITY) .setProvider(IDENTITY_PROVIDER) .setSource(Source.local(BASIC)) .setExistingEmailStrategy(ExistingEmailStrategy.FORBID) .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW) .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) .contains(USER_LOGIN, "John", "john@email.com", "ABCD", "johndoo", "github", true); }
@Test public void authenticate_existing_user_with_login_update_and_personal_org_does_not_exits_and_strategy_is_WARN() { organizationFlags.setEnabled(true); UserDto user = db.users().insertUser(u -> u .setLogin("Old login") .setExternalId(USER_IDENTITY.getProviderId()) .setExternalLogin("old identity") .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()) .setOrganizationUuid(null)); underTest.register(UserRegistration.builder() .setUserIdentity(USER_IDENTITY) .setProvider(IDENTITY_PROVIDER) .setSource(Source.local(BASIC)) .setExistingEmailStrategy(ExistingEmailStrategy.FORBID) .setUpdateLoginStrategy(UpdateLoginStrategy.WARN) .build()); assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid())) .extracting(UserDto::getLogin, UserDto::getExternalLogin) .contains(USER_LOGIN, USER_IDENTITY.getProviderLogin()); }
@Test public void throw_UpdateLoginRedirectionException_when_authenticating_with_login_update_and_personal_org_exists_and_strategy_is_WARN() { organizationFlags.setEnabled(true); OrganizationDto organization = db.organizations().insert(o -> o.setKey("Old login")); db.users().insertUser(u -> u .setLogin("Old login") .setExternalId(USER_IDENTITY.getProviderId()) .setExternalLogin("old identity") .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()) .setOrganizationUuid(organization.getUuid())); expectedException.expect(UpdateLoginRedirectionException.class); underTest.register(UserRegistration.builder() .setUserIdentity(USER_IDENTITY) .setProvider(IDENTITY_PROVIDER) .setSource(Source.local(BASIC)) .setExistingEmailStrategy(ExistingEmailStrategy.FORBID) .setUpdateLoginStrategy(UpdateLoginStrategy.WARN) .build()); }
public static UserDto newUserDto() { return new UserDto() .setId(nextInt()) .setUuid(randomAlphanumeric(40)) .setActive(true) .setLocal(nextBoolean()) .setLogin(randomAlphanumeric(30)) .setName(randomAlphanumeric(30)) .setEmail(randomAlphanumeric(30)) .setOnboarded(nextBoolean()) .setScmAccounts(singletonList(randomAlphanumeric(40))) .setExternalId(randomAlphanumeric(40)) .setExternalLogin(randomAlphanumeric(40)) .setExternalIdentityProvider(randomAlphanumeric(40)) .setSalt(randomAlphanumeric(40)) .setCryptedPassword(randomAlphanumeric(40)) .setCreatedAt(nextLong()) .setUpdatedAt(nextLong()); }