-INSERT INTO USERS(ID, UUID, LOGIN, NAME, EMAIL, EXTERNAL_IDENTITY, EXTERNAL_IDENTITY_PROVIDER, USER_LOCAL, CRYPTED_PASSWORD, SALT, HASH_METHOD, IS_ROOT, ONBOARDED, CREATED_AT, UPDATED_AT) VALUES (1, 'UuidnciQUUs7Zd3KPvFD', 'admin', 'Administrator', '', 'admin', 'sonarqube', true, '$2a$12$uCkkXmhW5ThVK8mpBvnXOOJRLd64LJeHTeCkSuB3lfaR2N0AYBaSi', null, 'BCRYPT', false, false, '1418215735482', '1418215735482');
+INSERT INTO USERS(ID, UUID, LOGIN, NAME, EMAIL, EXTERNAL_ID, EXTERNAL_LOGIN, EXTERNAL_IDENTITY_PROVIDER, USER_LOCAL, CRYPTED_PASSWORD, SALT, HASH_METHOD, IS_ROOT, ONBOARDED, CREATED_AT, UPDATED_AT) VALUES (1, 'UuidnciQUUs7Zd3KPvFD', 'admin', 'Administrator', '', 'admin', 'admin', 'sonarqube', true, '$2a$12$uCkkXmhW5ThVK8mpBvnXOOJRLd64LJeHTeCkSuB3lfaR2N0AYBaSi', null, 'BCRYPT', false, false, '1418215735482', '1418215735482');
ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2;
INSERT INTO GROUPS(ID, ORGANIZATION_UUID, NAME, DESCRIPTION, CREATED_AT, UPDATED_AT) VALUES (1, 'AVdqnciQUUs7Zd3KPvFD', 'sonar-administrators', 'System administrators', '2011-09-26 22:27:51.0', '2011-09-26 22:27:51.0');
CREATE TABLE "USERS" (
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
- "UUID" VARCHAR(40),
- "LOGIN" VARCHAR(255),
+ "UUID" VARCHAR(40) NOT NULL,
+ "LOGIN" VARCHAR(255) NOT NULL,
"NAME" VARCHAR(200),
"EMAIL" VARCHAR(100),
"CRYPTED_PASSWORD" VARCHAR(100),
"HASH_METHOD" VARCHAR(10),
"ACTIVE" BOOLEAN DEFAULT TRUE,
"SCM_ACCOUNTS" VARCHAR(4000),
- "EXTERNAL_IDENTITY" VARCHAR(255),
- "EXTERNAL_IDENTITY_PROVIDER" VARCHAR(100),
+ "EXTERNAL_ID" VARCHAR(255) NOT NULL,
+ "EXTERNAL_LOGIN" VARCHAR(255) NOT NULL,
+ "EXTERNAL_IDENTITY_PROVIDER" VARCHAR(100) NOT NULL,
"IS_ROOT" BOOLEAN NOT NULL,
"USER_LOCAL" BOOLEAN,
"ONBOARDED" BOOLEAN NOT NULL,
"HOMEPAGE_TYPE" VARCHAR(40),
"HOMEPAGE_PARAMETER" VARCHAR(40)
);
+CREATE UNIQUE INDEX "USERS_UUID" ON "USERS" ("UUID");
CREATE UNIQUE INDEX "USERS_LOGIN" ON "USERS" ("LOGIN");
+CREATE UNIQUE INDEX "UNIQ_EXTERNAL_ID" ON "USERS" ("EXTERNAL_IDENTITY_PROVIDER", "EXTERNAL_ID");
CREATE INDEX "USERS_UPDATED_AT" ON "USERS" ("UPDATED_AT");
return Optional.ofNullable(mapper(dbSession).select(organizationUuid, userId));
}
- public List<String> selectLoginsByOrganizationUuid(DbSession dbSession, String organizationUuid) {
- return mapper(dbSession).selectLogins(organizationUuid);
+ public List<String> selectUserUuidsByOrganizationUuid(DbSession dbSession, String organizationUuid) {
+ return mapper(dbSession).selectUserUuids(organizationUuid);
}
public List<Integer> selectUserIdsByOrganizationUuid(DbSession dbSession, String organizationUuid) {
}
/**
- *
- * @param loginOrganizationConsumer {@link BiConsumer}<String,String> (login, organization uuid)
+ * @param userUuidOrganizationConsumer {@link BiConsumer}<String,String> (uuid, organization uuid)
*/
- public void selectForUserIndexing(DbSession dbSession, Collection<String> logins, BiConsumer<String, String> loginOrganizationConsumer) {
- executeLargeInputsWithoutOutput(logins, list -> mapper(dbSession).selectForIndexing(list)
- .forEach(row -> loginOrganizationConsumer.accept(row.get("login"), row.get("organizationUuid"))));
+ public void selectForUserIndexing(DbSession dbSession, Collection<String> uuids, BiConsumer<String, String> userUuidOrganizationConsumer) {
+ executeLargeInputsWithoutOutput(uuids, list -> mapper(dbSession).selectForIndexing(list)
+ .forEach(row -> userUuidOrganizationConsumer.accept(row.get("uuid"), row.get("organizationUuid"))));
}
/**
*
- * @param loginOrganizationConsumer {@link BiConsumer}<String,String> (login, organization uuid)
+ * @param userUuidOrganizationConsumer {@link BiConsumer}<String,String> (uuid, organization uuid)
*/
- public void selectAllForUserIndexing(DbSession dbSession, BiConsumer<String, String> loginOrganizationConsumer) {
+ public void selectAllForUserIndexing(DbSession dbSession, BiConsumer<String, String> userUuidOrganizationConsumer) {
mapper(dbSession).selectAllForIndexing()
- .forEach(row -> loginOrganizationConsumer.accept(row.get("login"), row.get("organizationUuid")));
+ .forEach(row -> userUuidOrganizationConsumer.accept(row.get("uuid"), row.get("organizationUuid")));
}
}
Set<String> selectOrganizationUuidsByUser(@Param("userId") int userId);
- List<String> selectLogins(String organizationUuid);
+ List<String> selectUserUuids(String organizationUuid);
List<Integer> selectUserIds(String organizationUuid);
- List<Map<String, String>> selectForIndexing(@Param("logins") List<String> logins);
+ List<Map<String, String>> selectForIndexing(@Param("uuids") List<String> uuids);
List<Map<String, String>> selectAllForIndexing();
return executeLargeInputs(componentIds, getMapper(session)::selectByComponentIds);
}
+ public List<PropertyDto> selectByKeyAndMatchingValue(DbSession session, String key, String value) {
+ return getMapper(session).selectByKeyAndMatchingValue(key, value);
+ }
+
/**
* Saves the specified property and its value.
* <p>
List<PropertyDto> selectByQuery(@Param("query") PropertyQuery query);
+ List<PropertyDto> selectByKeyAndMatchingValue(@Param("key") String key, @Param("value") String value);
+
List<PropertyDto> selectDescendantModuleProperties(@Param("moduleUuid") String moduleUuid, @Param(value = "scope") String scope,
@Param(value = "excludeDisabled") boolean excludeDisabled);
return mapper(session).selectUser(userId);
}
+ @CheckForNull
+ public UserDto selectByUuid(DbSession session, String uuid) {
+ return mapper(session).selectByUuid(uuid);
+ }
+
/**
* Select users by ids, including disabled users. An empty list is returned
* if list of ids is empty, without any db round trips.
return executeLargeInputs(logins, mapper(session)::selectByLogins);
}
+ /**
+ * Select users by uuids, including disabled users. An empty list is returned
+ * if list of uuids is empty, without any db round trips.
+ */
+ public List<UserDto> selectByUuids(DbSession session, Collection<String> uuids) {
+ return executeLargeInputs(uuids, mapper(session)::selectByUuids);
+ }
+
/**
* Gets a list users by their logins. The result does NOT contain {@code null} values for users not found, so
* the size of result may be less than the number of keys.
return mapper(dbSession).selectByEmail(email.toLowerCase(Locale.ENGLISH));
}
- public void scrollByLogins(DbSession dbSession, Collection<String> logins, Consumer<UserDto> consumer) {
+ @CheckForNull
+ public UserDto selectByExternalIdAndIdentityProvider(DbSession dbSession, String externalId, String externalIdentityProvider) {
+ return mapper(dbSession).selectByExternalIdAndIdentityProvider(externalId, externalIdentityProvider);
+ }
+
+ public void scrollByUuids(DbSession dbSession, Collection<String> uuids, Consumer<UserDto> consumer) {
UserMapper mapper = mapper(dbSession);
- executeLargeInputsWithoutOutput(logins,
- pageOfLogins -> mapper
- .selectByLogins(pageOfLogins)
+ executeLargeInputsWithoutOutput(uuids,
+ pageOfUuids -> mapper
+ .selectByUuids(pageOfUuids)
.forEach(consumer));
}
private String email;
private boolean active = true;
private String scmAccounts;
- private String externalIdentity;
+ private String externalId;
+ private String externalLogin;
private String externalIdentityProvider;
// Hashed password that may be null in case of external authentication
private String cryptedPassword;
}
}
- public String getExternalIdentity() {
- return externalIdentity;
+ public String getExternalId() {
+ return externalId;
}
- public UserDto setExternalIdentity(String authorithy) {
- this.externalIdentity = authorithy;
+ public UserDto setExternalId(String externalId) {
+ this.externalId = externalId;
+ return this;
+ }
+
+ public String getExternalLogin() {
+ return externalLogin;
+ }
+
+ public UserDto setExternalLogin(String externalLogin) {
+ this.externalLogin = externalLogin;
return this;
}
public interface UserMapper {
+ @CheckForNull
+ UserDto selectByUuid(String uuid);
+
@CheckForNull
UserDto selectByLogin(String login);
List<UserDto> selectByLogins(List<String> logins);
+ List<UserDto> selectByUuids(List<String> uuids);
+
List<UserDto> selectByIds(@Param("ids") List<Integer> ids);
@CheckForNull
UserDto selectByEmail(String email);
+ @CheckForNull
+ UserDto selectByExternalIdAndIdentityProvider(@Param("externalId") String externalId, @Param("externalIdentityProvider") String externalExternalIdentityProvider);
+
void scrollAll(ResultHandler<UserDto> handler);
/**
and om.user_id = #{userId, jdbcType=INTEGER}
</select>
- <select id="selectLogins" resultType="string">
- select u.login
+ <select id="selectUserUuids" resultType="string">
+ select u.uuid
from organization_members om
inner join users u on om.user_id = u.id
where om.organization_uuid=#{organizationUuid,jdbcType=VARCHAR}
</select>
<select id="selectForIndexing" resultType="hashmap">
- select u.login as "login", om.organization_uuid as "organizationUuid"
+ select u.uuid as "uuid", om.organization_uuid as "organizationUuid"
from organization_members om
inner join users u on om.user_id=u.id
- where u.login in
- <foreach collection="logins" open="(" close=")" item="login" separator=",">
- #{login, jdbcType=VARCHAR}
+ where u.uuid in
+ <foreach collection="uuids" open="(" close=")" item="uuid" separator=",">
+ #{uuid, jdbcType=VARCHAR}
</foreach>
</select>
<select id="selectAllForIndexing" resultType="hashmap">
- select u.login as "login", om.organization_uuid as "organizationUuid"
+ select u.uuid as "uuid", om.organization_uuid as "organizationUuid"
from organization_members om
inner join users u on om.user_id=u.id
</select>
and ps.organization_uuid=#{organizationUuid,jdbcType=VARCHAR}
</select>
+ <select id="selectByKeyAndMatchingValue" parameterType="map" resultType="ScrapProperty">
+ select
+ <include refid="columnsToScrapPropertyDto"/>
+ from properties p
+ <where>
+ p.prop_key = #{key,jdbcType=VARCHAR}
+ and p.text_value like #{value,jdbcType=VARCHAR}
+ </where>
+ </select>
+
<insert id="insertAsEmpty" parameterType="Map" useGeneratedKeys="false">
insert into properties
(
u.salt as "salt",
u.crypted_password as "cryptedPassword",
u.hash_method as "hashMethod",
- u.external_identity as "externalIdentity",
+ u.external_id as "externalId",
+ u.external_login as "externalLogin",
u.external_identity_provider as "externalIdentityProvider",
u.user_local as "local",
u.is_root as "root",
u.homepage_parameter as "homepageParameter"
</sql>
+ <select id="selectByUuid" parameterType="String" resultType="User">
+ SELECT
+ <include refid="userColumns"/>
+ FROM users u
+ WHERE u.uuid=#{uuid}
+ </select>
+
<select id="selectByLogin" parameterType="String" resultType="User">
SELECT
<include refid="userColumns"/>
</foreach>
</select>
+ <select id="selectByUuids" parameterType="string" resultType="User">
+ SELECT
+ <include refid="userColumns"/>
+ FROM users u
+ WHERE u.uuid in
+ <foreach collection="list" open="(" close=")" item="uuid" separator=",">
+ #{uuid}
+ </foreach>
+ </select>
+
<select id="scrollAll" resultType="User" fetchSize="${_scrollFetchSize}" resultSetType="FORWARD_ONLY">
select
<include refid="userColumns"/>
AND u.active=${_true}
</select>
+ <select id="selectByExternalIdAndIdentityProvider" parameterType="map" resultType="User">
+ SELECT
+ <include refid="userColumns"/>
+ FROM users u
+ WHERE u.external_id=#{externalId} AND u.external_identity_provider=#{externalIdentityProvider}
+ </select>
+
<select id="countRootUsersButLogin" parameterType="String" resultType="long">
select
count(1)
active = ${_false},
email = null,
scm_accounts = null,
- external_identity = null,
- external_identity_provider = null,
salt = null,
crypted_password = null,
updated_at = #{now, jdbcType=BIGINT}
email,
active,
scm_accounts,
- external_identity,
+ external_id,
+ external_login,
external_identity_provider,
user_local,
salt,
#{user.email,jdbcType=VARCHAR},
#{user.active,jdbcType=BOOLEAN},
#{user.scmAccounts,jdbcType=VARCHAR},
- #{user.externalIdentity,jdbcType=VARCHAR},
+ #{user.externalId,jdbcType=VARCHAR},
+ #{user.externalLogin,jdbcType=VARCHAR},
#{user.externalIdentityProvider,jdbcType=VARCHAR},
#{user.local,jdbcType=BOOLEAN},
#{user.salt,jdbcType=VARCHAR},
<update id="update" parameterType="map">
update users set
+ login = #{user.login, jdbcType=VARCHAR},
name = #{user.name, jdbcType=VARCHAR},
email = #{user.email, jdbcType=VARCHAR},
active = #{user.active, jdbcType=BOOLEAN},
scm_accounts = #{user.scmAccounts, jdbcType=VARCHAR},
- external_identity = #{user.externalIdentity, jdbcType=VARCHAR},
+ external_id = #{user.externalId, jdbcType=VARCHAR},
+ external_login = #{user.externalLogin, jdbcType=VARCHAR},
external_identity_provider = #{user.externalIdentityProvider, jdbcType=VARCHAR},
user_local = #{user.local, jdbcType=BOOLEAN},
onboarded = #{user.onboarded, jdbcType=BOOLEAN},
homepage_type = #{user.homepageType, jdbcType=VARCHAR},
homepage_parameter = #{user.homepageParameter, jdbcType=VARCHAR}
where
- login = #{user.login, jdbcType=VARCHAR}
+ uuid = #{user.uuid, jdbcType=VARCHAR}
</update>
</mapper>
*/
package org.sonar.db.organization;
+import java.util.Arrays;
import java.util.function.Consumer;
import javax.annotation.Nullable;
import org.sonar.db.DbSession;
dbSession.commit();
}
- public void addMember(OrganizationDto organization, UserDto user) {
- checkArgument(user.getId() != null, "User must be saved in database");
- dbTester.getDbClient().organizationMemberDao().insert(dbTester.getSession(), new OrganizationMemberDto().setOrganizationUuid(organization.getUuid()).setUserId(user.getId()));
+ public void addMember(OrganizationDto organization, UserDto... users) {
+ Arrays.stream(users).forEach(u -> dbTester.getDbClient().organizationMemberDao().insert(dbTester.getSession(), new OrganizationMemberDto().setOrganizationUuid(organization.getUuid()).setUserId(u.getId())));
dbTester.commit();
}
package org.sonar.db.organization;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.sonar.db.DbTester;
import org.sonar.db.user.UserDto;
+import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.entry;
import static org.assertj.core.api.Assertions.tuple;
}
@Test
- public void select_logins() {
+ public void select_user_uuids_by_organization_uuid() {
OrganizationDto organization = db.organizations().insert();
OrganizationDto anotherOrganization = db.organizations().insert();
UserDto user = db.users().insertUser();
db.organizations().addMember(organization, anotherUser);
db.organizations().addMember(anotherOrganization, userInAnotherOrganization);
- List<String> result = underTest.selectLoginsByOrganizationUuid(dbSession, organization.getUuid());
+ List<String> result = underTest.selectUserUuidsByOrganizationUuid(dbSession, organization.getUuid());
- assertThat(result).containsOnly(user.getLogin(), anotherUser.getLogin());
+ assertThat(result).containsOnly(user.getUuid(), anotherUser.getUuid());
}
@Test
public void select_for_indexing() {
OrganizationDto org1 = db.organizations().insert(o -> o.setUuid("ORG_1"));
OrganizationDto org2 = db.organizations().insert(o -> o.setUuid("ORG_2"));
- UserDto user1 = db.users().insertUser("L_1");
- UserDto user2 = db.users().insertUser("L_2");
+ UserDto user1 = db.users().insertUser();
+ UserDto user2 = db.users().insertUser();
db.organizations().addMember(org1, user1);
db.organizations().addMember(org1, user2);
db.organizations().addMember(org2, user1);
List<Tuple> result = new ArrayList<>();
- underTest.selectForUserIndexing(dbSession, Arrays.asList("L_1", "L_2"), (login, org) -> result.add(tuple(login, org)));
+ underTest.selectForUserIndexing(dbSession, asList(user1.getUuid(), user2.getUuid()), (login, org) -> result.add(tuple(login, org)));
- assertThat(result).containsOnly(tuple("L_1", "ORG_1"), tuple("L_1", "ORG_2"), tuple("L_2", "ORG_1"));
+ assertThat(result).containsOnly(tuple(user1.getUuid(), "ORG_1"), tuple(user1.getUuid(), "ORG_2"), tuple(user2.getUuid(), "ORG_1"));
}
@Test
public void select_all_for_indexing() {
OrganizationDto org1 = db.organizations().insert(o -> o.setUuid("ORG_1"));
OrganizationDto org2 = db.organizations().insert(o -> o.setUuid("ORG_2"));
- UserDto user1 = db.users().insertUser("L_1");
- UserDto user2 = db.users().insertUser("L_2");
+ UserDto user1 = db.users().insertUser();
+ UserDto user2 = db.users().insertUser();
db.organizations().addMember(org1, user1);
db.organizations().addMember(org1, user2);
db.organizations().addMember(org2, user1);
underTest.selectAllForUserIndexing(dbSession, (login, org) -> result.add(tuple(login, org)));
- assertThat(result).containsOnly(tuple("L_1", "ORG_1"), tuple("L_1", "ORG_2"), tuple("L_2", "ORG_1"));
+ assertThat(result).containsOnly(tuple(user1.getUuid(), "ORG_1"), tuple(user1.getUuid(), "ORG_2"), tuple(user2.getUuid(), "ORG_1"));
}
@Test
package org.sonar.db.permission.template;
import java.util.Collections;
-import java.util.List;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.utils.System2;
-import org.sonar.api.web.UserRole;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
-import org.sonar.db.permission.PermissionQuery;
+import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.user.UserDto;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
+import static org.sonar.api.web.UserRole.ADMIN;
+import static org.sonar.api.web.UserRole.CODEVIEWER;
+import static org.sonar.api.web.UserRole.USER;
import static org.sonar.db.permission.PermissionQuery.builder;
public class UserWithPermissionTemplateDaoTest {
- private static final Long TEMPLATE_ID = 50L;
-
@Rule
- public DbTester dbTester = DbTester.create(System2.INSTANCE);
+ public DbTester db = DbTester.create(System2.INSTANCE);
- private DbSession dbSession = dbTester.getSession();
+ private DbSession dbSession = db.getSession();
- private PermissionTemplateDao underTest = dbTester.getDbClient().permissionTemplateDao();
+ private PermissionTemplateDao underTest = db.getDbClient().permissionTemplateDao();
@Test
public void select_logins() {
- dbTester.prepareDbUnit(getClass(), "users_with_permissions.xml");
-
- assertThat(underTest.selectUserLoginsByQueryAndTemplate(dbSession, newQuery().build(), TEMPLATE_ID)).containsOnly("user1", "user2", "user3");
- assertThat(underTest.selectUserLoginsByQueryAndTemplate(dbSession, newQuery().withAtLeastOnePermission().setPermission("user").build(),
- TEMPLATE_ID)).containsOnly("user1", "user2");
+ OrganizationDto organization = db.organizations().insert();
+ UserDto user1 = db.users().insertUser();
+ UserDto user2 = db.users().insertUser();
+ UserDto user3 = db.users().insertUser();
+ db.organizations().addMember(organization, user1, user2, user3);
+ PermissionTemplateDto permissionTemplate = db.permissionTemplates().insertTemplate();
+ db.permissionTemplates().addUserToTemplate(permissionTemplate, user1, USER);
+ db.permissionTemplates().addUserToTemplate(permissionTemplate, user1, ADMIN);
+ db.permissionTemplates().addUserToTemplate(permissionTemplate, user1, CODEVIEWER);
+ db.permissionTemplates().addUserToTemplate(permissionTemplate, user2, USER);
+ PermissionTemplateDto anotherPermissionTemplate = db.permissionTemplates().insertTemplate();
+ db.permissionTemplates().addUserToTemplate(anotherPermissionTemplate, user1, USER);
+
+ assertThat(underTest.selectUserLoginsByQueryAndTemplate(dbSession,
+ builder().setOrganizationUuid(organization.getUuid()).build(),
+ permissionTemplate.getId()))
+ .containsExactlyInAnyOrder(user1.getLogin(), user2.getLogin(), user3.getLogin());
+ assertThat(underTest.selectUserLoginsByQueryAndTemplate(dbSession,
+ builder().setOrganizationUuid(organization.getUuid()).withAtLeastOnePermission().setPermission(USER).build(),
+ permissionTemplate.getId()))
+ .containsExactlyInAnyOrder(user1.getLogin(), user2.getLogin());
}
@Test
public void return_no_logins_on_unknown_template_key() {
- dbTester.prepareDbUnit(getClass(), "users_with_permissions.xml");
-
- assertThat(underTest.selectUserLoginsByQueryAndTemplate(dbSession, newQuery().setPermission("user").withAtLeastOnePermission().build(), 999L)).isEmpty();
+ OrganizationDto organization = db.organizations().insert();
+ UserDto user = db.users().insertUser();
+ db.organizations().addMember(organization, user);
+ PermissionTemplateDto permissionTemplate = db.permissionTemplates().insertTemplate();
+ db.permissionTemplates().addUserToTemplate(permissionTemplate, user, USER);
+
+ assertThat(underTest.selectUserLoginsByQueryAndTemplate(dbSession,
+ builder().setOrganizationUuid(organization.getUuid()).setPermission(USER).withAtLeastOnePermission().build(), 999L))
+ .isEmpty();
}
@Test
public void select_only_logins_with_permission() {
- dbTester.prepareDbUnit(getClass(), "users_with_permissions.xml");
-
- assertThat(underTest.selectUserLoginsByQueryAndTemplate(
- dbSession,
- newQuery().setPermission("user").withAtLeastOnePermission().build(),
- TEMPLATE_ID)).containsOnly("user1", "user2");
+ OrganizationDto organization = db.organizations().insert();
+ UserDto user1 = db.users().insertUser();
+ UserDto user2 = db.users().insertUser();
+ UserDto user3 = db.users().insertUser();
+ db.organizations().addMember(organization, user1, user2, user3);
+ PermissionTemplateDto permissionTemplate = db.permissionTemplates().insertTemplate();
+ db.permissionTemplates().addUserToTemplate(permissionTemplate, user1, USER);
+ db.permissionTemplates().addUserToTemplate(permissionTemplate, user1, ADMIN);
+ db.permissionTemplates().addUserToTemplate(permissionTemplate, user1, CODEVIEWER);
+ db.permissionTemplates().addUserToTemplate(permissionTemplate, user2, USER);
+ PermissionTemplateDto anotherPermissionTemplate = db.permissionTemplates().insertTemplate();
+ db.permissionTemplates().addUserToTemplate(anotherPermissionTemplate, user1, USER);
+
+ assertThat(underTest.selectUserLoginsByQueryAndTemplate(dbSession,
+ builder().setOrganizationUuid(organization.getUuid()).setPermission(USER).withAtLeastOnePermission().build(),
+ permissionTemplate.getId()))
+ .containsExactlyInAnyOrder(user1.getLogin(), user2.getLogin());
}
@Test
public void select_only_enable_users() {
- dbTester.prepareDbUnit(getClass(), "select_only_enable_users.xml");
-
- List<String> result = underTest.selectUserLoginsByQueryAndTemplate(dbSession, newQuery().setPermission("user").build(), TEMPLATE_ID);
- assertThat(result).hasSize(2);
-
- // Disabled user should not be returned
- assertThat(result.stream().filter(input -> input.equals("disabledUser")).findFirst()).isEmpty();
+ OrganizationDto organization = db.organizations().insert();
+ UserDto user = db.users().insertUser();
+ UserDto disabledUser = db.users().insertUser(u -> u.setActive(false));
+ db.organizations().addMember(organization, user, disabledUser);
+ PermissionTemplateDto permissionTemplate = db.permissionTemplates().insertTemplate();
+ db.permissionTemplates().addUserToTemplate(permissionTemplate, user, USER);
+ db.permissionTemplates().addUserToTemplate(permissionTemplate, disabledUser, USER);
+
+ assertThat(underTest.selectUserLoginsByQueryAndTemplate(dbSession,
+ builder().setOrganizationUuid(organization.getUuid()).setPermission(USER).build(), permissionTemplate.getId()))
+ .containsExactlyInAnyOrder(user.getLogin());
}
@Test
public void search_by_user_name() {
- dbTester.prepareDbUnit(getClass(), "users_with_permissions.xml");
+ OrganizationDto organization = db.organizations().insert();
+ UserDto user1 = db.users().insertUser(u -> u.setName("User1"));
+ UserDto user2 = db.users().insertUser(u -> u.setName("User2"));
+ UserDto user3 = db.users().insertUser(u -> u.setName("User3"));
+ db.organizations().addMember(organization, user1, user2, user3);
+ PermissionTemplateDto permissionTemplate = db.permissionTemplates().insertTemplate();
+ db.permissionTemplates().addUserToTemplate(permissionTemplate, user1, USER);
+ db.permissionTemplates().addUserToTemplate(permissionTemplate, user2, USER);
- List<String> result = underTest.selectUserLoginsByQueryAndTemplate(
- dbSession, newQuery().withAtLeastOnePermission().setPermission("user").setSearchQuery("SEr1").build(),
- TEMPLATE_ID);
- assertThat(result).containsOnly("user1");
+ assertThat(underTest.selectUserLoginsByQueryAndTemplate(
+ dbSession, builder().setOrganizationUuid(organization.getUuid()).withAtLeastOnePermission().setPermission(USER).setSearchQuery("SEr1").build(),
+ permissionTemplate.getId()))
+ .containsExactlyInAnyOrder(user1.getLogin());
- result = underTest.selectUserLoginsByQueryAndTemplate(
- dbSession, newQuery().withAtLeastOnePermission().setPermission("user").setSearchQuery("user").build(),
- TEMPLATE_ID);
- assertThat(result).hasSize(2);
+ assertThat(underTest.selectUserLoginsByQueryAndTemplate(
+ dbSession, builder().setOrganizationUuid(organization.getUuid()).withAtLeastOnePermission().setPermission(USER).setSearchQuery("user").build(),
+ permissionTemplate.getId()))
+ .containsExactlyInAnyOrder(user1.getLogin(), user2.getLogin());
}
@Test
public void should_be_sorted_by_user_name() {
- dbTester.prepareDbUnit(getClass(), "users_with_permissions_should_be_sorted_by_user_name.xml");
-
- assertThat(underTest.selectUserLoginsByQueryAndTemplate(dbSession, newQuery().build(), TEMPLATE_ID)).containsOnly("user1", "user2", "user3");
+ OrganizationDto organization = db.organizations().insert();
+ UserDto user1 = db.users().insertUser(u -> u.setName("User3"));
+ UserDto user2 = db.users().insertUser(u -> u.setName("User1"));
+ UserDto user3 = db.users().insertUser(u -> u.setName("User2"));
+ db.organizations().addMember(organization, user1, user2, user3);
+ PermissionTemplateDto permissionTemplate = db.permissionTemplates().insertTemplate();
+ db.permissionTemplates().addUserToTemplate(permissionTemplate, user1, USER);
+ db.permissionTemplates().addUserToTemplate(permissionTemplate, user2, USER);
+
+ assertThat(underTest.selectUserLoginsByQueryAndTemplate(dbSession,
+ builder().setOrganizationUuid(organization.getUuid()).build(), permissionTemplate.getId()))
+ .containsExactly(user2.getLogin(), user3.getLogin(), user1.getLogin());
}
@Test
public void should_be_paginated() {
- dbTester.prepareDbUnit(getClass(), "users_with_permissions.xml");
-
- assertThat(underTest.selectUserLoginsByQueryAndTemplate(dbSession, newQuery().setPageIndex(1).setPageSize(2).build(), TEMPLATE_ID)).containsOnly("user1", "user2");
- assertThat(underTest.selectUserLoginsByQueryAndTemplate(dbSession, newQuery().setPageIndex(2).setPageSize(2).build(), TEMPLATE_ID)).containsOnly("user3");
- assertThat(underTest.selectUserLoginsByQueryAndTemplate(dbSession, newQuery().setPageIndex(3).setPageSize(1).build(), TEMPLATE_ID)).containsOnly("user3");
+ OrganizationDto organization = db.organizations().insert();
+ UserDto user1 = db.users().insertUser(u -> u.setName("User1"));
+ UserDto user2 = db.users().insertUser(u -> u.setName("User2"));
+ UserDto user3 = db.users().insertUser(u -> u.setName("User3"));
+ db.organizations().addMember(organization, user1, user2, user3);
+ PermissionTemplateDto permissionTemplate = db.permissionTemplates().insertTemplate();
+ db.permissionTemplates().addUserToTemplate(permissionTemplate, user1, USER);
+ db.permissionTemplates().addUserToTemplate(permissionTemplate, user2, USER);
+
+ assertThat(underTest.selectUserLoginsByQueryAndTemplate(dbSession,
+ builder().setOrganizationUuid(organization.getUuid()).setPageIndex(1).setPageSize(2).build(), permissionTemplate.getId()))
+ .containsExactlyInAnyOrder(user1.getLogin(), user2.getLogin());
+ assertThat(underTest.selectUserLoginsByQueryAndTemplate(dbSession,
+ builder().setOrganizationUuid(organization.getUuid()).setPageIndex(2).setPageSize(2).build(), permissionTemplate.getId()))
+ .containsExactlyInAnyOrder(user3.getLogin());
+ assertThat(underTest.selectUserLoginsByQueryAndTemplate(dbSession,
+ builder().setOrganizationUuid(organization.getUuid()).setPageIndex(3).setPageSize(1).build(), permissionTemplate.getId()))
+ .containsExactlyInAnyOrder(user3.getLogin());
}
@Test
public void count_users() {
- dbTester.prepareDbUnit(getClass(), "users_with_permissions.xml");
-
- assertThat(underTest.countUserLoginsByQueryAndTemplate(dbSession, newQuery().build(), TEMPLATE_ID)).isEqualTo(3);
- assertThat(underTest.countUserLoginsByQueryAndTemplate(dbSession, newQuery().withAtLeastOnePermission().setPermission("user").build(), TEMPLATE_ID)).isEqualTo(2);
+ OrganizationDto organization = db.organizations().insert();
+ UserDto user1 = db.users().insertUser();
+ UserDto user2 = db.users().insertUser();
+ UserDto user3 = db.users().insertUser();
+ db.organizations().addMember(organization, user1, user2, user3);
+ PermissionTemplateDto permissionTemplate = db.permissionTemplates().insertTemplate();
+ db.permissionTemplates().addUserToTemplate(permissionTemplate, user1, USER);
+ db.permissionTemplates().addUserToTemplate(permissionTemplate, user2, USER);
+
+ assertThat(underTest.countUserLoginsByQueryAndTemplate(dbSession,
+ builder().setOrganizationUuid(organization.getUuid()).build(), permissionTemplate.getId()))
+ .isEqualTo(3);
+ assertThat(underTest.countUserLoginsByQueryAndTemplate(dbSession,
+ builder().setOrganizationUuid(organization.getUuid()).withAtLeastOnePermission().setPermission("user").build(), permissionTemplate.getId()))
+ .isEqualTo(2);
}
@Test
public void select_user_permission_templates_by_template_and_logins() {
- dbTester.prepareDbUnit(getClass(), "users_with_permissions.xml");
-
- assertThat(underTest.selectUserPermissionsByTemplateIdAndUserLogins(dbSession, 50L, singletonList("user1")))
+ OrganizationDto organization = db.organizations().insert();
+ UserDto user1 = db.users().insertUser();
+ UserDto user2 = db.users().insertUser();
+ UserDto user3 = db.users().insertUser();
+ db.organizations().addMember(organization, user1, user2, user3);
+ PermissionTemplateDto permissionTemplate = db.permissionTemplates().insertTemplate();
+ db.permissionTemplates().addUserToTemplate(permissionTemplate, user1, USER);
+ db.permissionTemplates().addUserToTemplate(permissionTemplate, user1, ADMIN);
+ db.permissionTemplates().addUserToTemplate(permissionTemplate, user1, CODEVIEWER);
+ db.permissionTemplates().addUserToTemplate(permissionTemplate, user2, USER);
+ PermissionTemplateDto anotherPermissionTemplate = db.permissionTemplates().insertTemplate();
+ db.permissionTemplates().addUserToTemplate(anotherPermissionTemplate, user1, USER);
+
+ assertThat(underTest.selectUserPermissionsByTemplateIdAndUserLogins(dbSession, permissionTemplate.getId(), singletonList(user1.getLogin())))
.extracting(PermissionTemplateUserDto::getUserLogin, PermissionTemplateUserDto::getPermission)
- .containsOnly(
- tuple("user1", UserRole.USER),
- tuple("user1", UserRole.ADMIN),
- tuple("user1", UserRole.CODEVIEWER)
- );
+ .containsExactlyInAnyOrder(
+ tuple(user1.getLogin(), USER),
+ tuple(user1.getLogin(), ADMIN),
+ tuple(user1.getLogin(), CODEVIEWER));
- assertThat(underTest.selectUserPermissionsByTemplateIdAndUserLogins(dbSession, 50L, asList("user1", "user2", "user3")))
+ assertThat(underTest.selectUserPermissionsByTemplateIdAndUserLogins(dbSession, permissionTemplate.getId(), asList(user1.getLogin(), user2.getLogin(), user2.getLogin())))
.extracting(PermissionTemplateUserDto::getUserLogin, PermissionTemplateUserDto::getPermission)
- .containsOnly(
- tuple("user1", UserRole.USER),
- tuple("user1", UserRole.ADMIN),
- tuple("user1", UserRole.CODEVIEWER),
- tuple("user2", UserRole.USER)
- );
-
- assertThat(underTest.selectUserPermissionsByTemplateIdAndUserLogins(dbSession, 50L, singletonList("unknown"))).isEmpty();
- assertThat(underTest.selectUserPermissionsByTemplateIdAndUserLogins(dbSession, 50L, Collections.emptyList())).isEmpty();
- assertThat(underTest.selectUserPermissionsByTemplateIdAndUserLogins(dbSession, 123L, singletonList("user1"))).isEmpty();
- }
-
- private PermissionQuery.Builder newQuery() {
- return builder().setOrganizationUuid("ORG_UUID");
+ .containsExactlyInAnyOrder(
+ tuple(user1.getLogin(), USER),
+ tuple(user1.getLogin(), ADMIN),
+ tuple(user1.getLogin(), CODEVIEWER),
+ tuple(user2.getLogin(), USER));
+
+ assertThat(underTest.selectUserPermissionsByTemplateIdAndUserLogins(dbSession, permissionTemplate.getId(), singletonList("unknown"))).isEmpty();
+ assertThat(underTest.selectUserPermissionsByTemplateIdAndUserLogins(dbSession, permissionTemplate.getId(), Collections.emptyList())).isEmpty();
+ assertThat(underTest.selectUserPermissionsByTemplateIdAndUserLogins(dbSession, 123L, singletonList(user1.getLogin()))).isEmpty();
}
}
import static org.sonar.db.property.PropertyTesting.newComponentPropertyDto;
import static org.sonar.db.property.PropertyTesting.newGlobalPropertyDto;
import static org.sonar.db.property.PropertyTesting.newUserPropertyDto;
-import static org.sonar.db.user.UserTesting.newUserDto;
@RunWith(DataProviderRunner.class)
public class PropertiesDaoTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Rule
- public DbTester dbTester = DbTester.create(system2);
+ public DbTester db = DbTester.create(system2);
- private DbClient dbClient = dbTester.getDbClient();
- private DbSession session = dbTester.getSession();
+ private DbClient dbClient = db.getDbClient();
+ private DbSession session = db.getSession();
- private PropertiesDao underTest = dbTester.getDbClient().propertiesDao();
+ private PropertiesDao underTest = db.getDbClient().propertiesDao();
@Test
- public void shouldFindUsersForNotification() throws SQLException {
+ public void shouldFindUsersForNotification() {
ComponentDto project1 = insertPrivateProject("uuid_45");
ComponentDto project2 = insertPrivateProject("uuid_56");
- UserDto user1 = dbTester.users().insertUser(u -> u.setLogin("user1"));
- UserDto user2 = dbTester.users().insertUser(u -> u.setLogin("user2"));
- UserDto user3 = dbTester.users().insertUser(u -> u.setLogin("user3"));
+ UserDto user1 = db.users().insertUser(u -> u.setLogin("user1"));
+ UserDto user2 = db.users().insertUser(u -> u.setLogin("user2"));
+ UserDto user3 = db.users().insertUser(u -> u.setLogin("user3"));
insertProperty("notification.NewViolations.Email", "true", project1.getId(), user2.getId());
insertProperty("notification.NewViolations.Twitter", "true", null, user3.getId());
insertProperty("notification.NewViolations.Twitter", "true", project2.getId(), user1.getId());
insertProperty("notification.NewViolations.Twitter", "true", project1.getId(), user2.getId());
insertProperty("notification.NewViolations.Twitter", "true", project2.getId(), user3.getId());
- dbTester.users().insertProjectPermissionOnUser(user2, UserRole.USER, project1);
- dbTester.users().insertProjectPermissionOnUser(user3, UserRole.USER, project2);
- dbTester.users().insertProjectPermissionOnUser(user1, UserRole.USER, project2);
+ db.users().insertProjectPermissionOnUser(user2, UserRole.USER, project1);
+ db.users().insertProjectPermissionOnUser(user3, UserRole.USER, project2);
+ db.users().insertProjectPermissionOnUser(user1, UserRole.USER, project2);
assertThat(underTest.findUsersForNotification("NewViolations", "Email", null))
.isEmpty();
}
@Test
- public void hasNotificationSubscribers() throws SQLException {
- int userId1 = dbTester.users().insertUser(u -> u.setLogin("user1")).getId();
- int userId2 = dbTester.users().insertUser(u -> u.setLogin("user2")).getId();
+ public void hasNotificationSubscribers() {
+ int userId1 = db.users().insertUser(u -> u.setLogin("user1")).getId();
+ int userId2 = db.users().insertUser(u -> u.setLogin("user2")).getId();
Long projectId = insertPrivateProject("PROJECT_A").getId();
// global subscription
insertProperty("notification.DispatcherWithGlobalSubscribers.Email", "true", null, userId2);
}
@Test
- public void selectGlobalProperties() throws SQLException {
+ public void selectGlobalProperties() {
// global
long id1 = insertProperty("global.one", "one", null, null);
long id2 = insertProperty("global.two", "two", null, null);
@Test
@UseDataProvider("allValuesForSelect")
- public void selectGlobalProperties_supports_all_values(String dbValue, String expected) throws SQLException {
+ public void selectGlobalProperties_supports_all_values(String dbValue, String expected) {
insertProperty("global.one", dbValue, null, null);
List<PropertyDto> dtos = underTest.selectGlobalProperties();
}
@Test
- public void selectGlobalProperty() throws SQLException {
+ public void selectGlobalProperty() {
// global
insertProperty("global.one", "one", null, null);
insertProperty("global.two", "two", null, null);
@Test
@UseDataProvider("allValuesForSelect")
- public void selectGlobalProperty_supports_all_values(String dbValue, String expected) throws SQLException {
+ public void selectGlobalProperty_supports_all_values(String dbValue, String expected) {
insertProperty("global.one", dbValue, null, null);
assertThatDto(underTest.selectGlobalProperty("global.one"))
}
@Test
- public void selectProjectProperties() throws SQLException {
+ public void selectProjectProperties() {
ComponentDto projectDto = insertPrivateProject("A");
long projectId = projectDto.getId();
// global
@Test
@UseDataProvider("allValuesForSelect")
- public void selectProjectProperties_supports_all_values(String dbValue, String expected) throws SQLException {
+ public void selectProjectProperties_supports_all_values(String dbValue, String expected) {
ComponentDto projectDto = insertPrivateProject("A");
insertProperty("project.one", dbValue, projectDto.getId(), null);
}
@Test
- public void selectProjectProperty() throws SQLException {
+ public void selectProjectProperty() {
insertProperty("project.one", "one", 10L, null);
PropertyDto property = underTest.selectProjectProperty(10L, "project.one");
@Test
public void selectEnabledDescendantModuleProperties() {
- dbTester.prepareDbUnit(getClass(), "select_module_properties_tree.xml");
+ db.prepareDbUnit(getClass(), "select_module_properties_tree.xml");
- List<PropertyDto> properties = underTest.selectEnabledDescendantModuleProperties("ABCD", dbTester.getSession());
+ List<PropertyDto> properties = underTest.selectEnabledDescendantModuleProperties("ABCD", db.getSession());
assertThat(properties.size()).isEqualTo(4);
assertThat(properties).extracting("key").containsOnly("struts.one", "core.one", "core.two", "data.one");
assertThat(properties).extracting("value").containsOnly("one", "two");
- properties = underTest.selectEnabledDescendantModuleProperties("EFGH", dbTester.getSession());
+ properties = underTest.selectEnabledDescendantModuleProperties("EFGH", db.getSession());
assertThat(properties.size()).isEqualTo(3);
assertThat(properties).extracting("key").containsOnly("core.one", "core.two", "data.one");
- properties = underTest.selectEnabledDescendantModuleProperties("FGHI", dbTester.getSession());
+ properties = underTest.selectEnabledDescendantModuleProperties("FGHI", db.getSession());
assertThat(properties.size()).isEqualTo(1);
assertThat(properties).extracting("key").containsOnly("data.one");
- assertThat(underTest.selectEnabledDescendantModuleProperties("unknown-result.xml", dbTester.getSession()).size()).isEqualTo(0);
+ assertThat(underTest.selectEnabledDescendantModuleProperties("unknown-result.xml", db.getSession()).size()).isEqualTo(0);
}
@Test
@UseDataProvider("allValuesForSelect")
- public void selectEnabledDescendantModuleProperties_supports_all_values(String dbValue, String expected) throws SQLException {
+ public void selectEnabledDescendantModuleProperties_supports_all_values(String dbValue, String expected) {
String projectUuid = "A";
ComponentDto project = ComponentTesting.newPrivateProjectDto(OrganizationTesting.newOrganizationDto(), projectUuid);
dbClient.componentDao().insert(session, project);
long projectId = project.getId();
insertProperty("project.one", dbValue, projectId, null);
- List<PropertyDto> dtos = underTest.selectEnabledDescendantModuleProperties(projectUuid, dbTester.getSession());
+ List<PropertyDto> dtos = underTest.selectEnabledDescendantModuleProperties(projectUuid, db.getSession());
assertThat(dtos)
.hasSize(1);
assertThatDto(dtos.iterator().next())
}
@Test
- public void select_by_query() throws SQLException {
+ public void select_by_query() {
// global
insertProperty("global.one", "one", null, null);
insertProperty("global.two", "two", null, null);
// other
insertProperty("other.one", "one", 12L, null);
- List<PropertyDto> results = underTest.selectByQuery(PropertyQuery.builder().setKey("user.two").setComponentId(10L).setUserId(100).build(), dbTester.getSession());
+ List<PropertyDto> results = underTest.selectByQuery(PropertyQuery.builder().setKey("user.two").setComponentId(10L).setUserId(100).build(), db.getSession());
assertThat(results).hasSize(1);
assertThat(results.get(0).getValue()).isEqualTo("two");
- results = underTest.selectByQuery(PropertyQuery.builder().setKey("user.one").setUserId(100).build(), dbTester.getSession());
+ results = underTest.selectByQuery(PropertyQuery.builder().setKey("user.one").setUserId(100).build(), db.getSession());
assertThat(results).hasSize(1);
assertThat(results.get(0).getValue()).isEqualTo("one");
}
@Test
- public void select_global_properties_by_keys() throws Exception {
+ public void select_global_properties_by_keys() {
insertPrivateProject("A");
- int userId = dbTester.users().insertUser(u -> u.setLogin("B")).getId();
+ int userId = db.users().insertUser(u -> u.setLogin("B")).getId();
String key = "key";
String anotherKey = "anotherKey";
@Test
public void select_component_properties_by_ids() {
- ComponentDto project = dbTester.components().insertPrivateProject();
- ComponentDto project2 = dbTester.components().insertPrivateProject();
- UserDto user = dbTester.users().insertUser();
+ ComponentDto project = db.components().insertPrivateProject();
+ ComponentDto project2 = db.components().insertPrivateProject();
+ UserDto user = db.users().insertUser();
String key = "key";
String anotherKey = "anotherKey";
@Test
public void select_properties_by_keys_and_component_ids() {
- ComponentDto project = dbTester.components().insertPrivateProject();
- ComponentDto project2 = dbTester.components().insertPrivateProject();
- UserDto user = dbTester.users().insertUser();
+ ComponentDto project = db.components().insertPrivateProject();
+ ComponentDto project2 = db.components().insertPrivateProject();
+ UserDto user = db.users().insertUser();
String key = "key";
String anotherKey = "anotherKey";
assertThat(underTest.selectPropertiesByKeysAndComponentIds(session, newHashSet("unknown"), newHashSet(123456789L))).isEmpty();
}
+ @Test
+ public void select_by_key_and_matching_value() {
+ ComponentDto project1 = db.components().insertPrivateProject();
+ ComponentDto project2 = db.components().insertPrivateProject();
+ db.properties().insertProperties(
+ newComponentPropertyDto("key", "value", project1),
+ newComponentPropertyDto("key", "value", project2),
+ newGlobalPropertyDto("key", "value"),
+ newComponentPropertyDto("another key", "value", project1));
+
+ assertThat(underTest.selectByKeyAndMatchingValue(db.getSession(), "key", "value"))
+ .extracting(PropertyDto::getValue, PropertyDto::getResourceId)
+ .containsExactlyInAnyOrder(
+ tuple("value", project1.getId()),
+ tuple("value", project2.getId()),
+ tuple("value", null)
+ );
+ }
+
@Test
public void saveProperty_inserts_global_properties_when_they_do_not_exist_in_db() {
when(system2.now()).thenReturn(DATE_1, DATE_2, DATE_3, DATE_4, DATE_5);
}
@Test
- public void delete_project_property() throws SQLException {
+ public void delete_project_property() {
long projectId1 = insertPrivateProject("A").getId();
long projectId2 = insertPrivateProject("B").getId();
long projectId3 = insertPrivateProject("C").getId();
}
@Test
- public void delete_project_properties() throws SQLException {
+ public void delete_project_properties() {
long id1 = insertProperty("sonar.profile.java", "Sonar Way", 1L, null);
long id2 = insertProperty("sonar.profile.java", "Sonar Way", 2L, null);
}
@Test
- public void deleteGlobalProperty() throws SQLException {
+ public void deleteGlobalProperty() {
// global
long id1 = insertProperty("global.key", "new_global", null, null);
long id2 = insertProperty("to_be_deleted", "xxx", null, null);
}
@Test
- public void delete_by_organization_and_user() throws SQLException {
- OrganizationDto organization = dbTester.organizations().insert();
- OrganizationDto anotherOrganization = dbTester.organizations().insert();
- ComponentDto project = dbTester.components().insertPrivateProject(organization);
- ComponentDto anotherProject = dbTester.components().insertPrivateProject(anotherOrganization);
- UserDto user = dbTester.users().insertUser();
- UserDto anotherUser = dbTester.users().insertUser();
+ public void delete_by_organization_and_user() {
+ OrganizationDto organization = db.organizations().insert();
+ OrganizationDto anotherOrganization = db.organizations().insert();
+ ComponentDto project = db.components().insertPrivateProject(organization);
+ ComponentDto anotherProject = db.components().insertPrivateProject(anotherOrganization);
+ UserDto user = db.users().insertUser();
+ UserDto anotherUser = db.users().insertUser();
insertProperty("KEY_11", "VALUE", project.getId(), user.getId());
insertProperty("KEY_12", "VALUE", project.getId(), user.getId());
insertProperty("KEY_11", "VALUE", project.getId(), anotherUser.getId());
}
@Test
- public void delete_by_organization_and_matching_login() throws SQLException {
- OrganizationDto organization = dbTester.organizations().insert();
- OrganizationDto anotherOrganization = dbTester.organizations().insert();
- ComponentDto project = dbTester.components().insertPrivateProject(organization);
- ComponentDto anotherProject = dbTester.components().insertPrivateProject(anotherOrganization);
- UserDto user = dbTester.users().insertUser();
- UserDto anotherUser = dbTester.users().insertUser();
+ public void delete_by_organization_and_matching_login() {
+ OrganizationDto organization = db.organizations().insert();
+ OrganizationDto anotherOrganization = db.organizations().insert();
+ ComponentDto project = db.components().insertPrivateProject(organization);
+ ComponentDto anotherProject = db.components().insertPrivateProject(anotherOrganization);
+ UserDto user = db.users().insertUser();
+ UserDto anotherUser = db.users().insertUser();
insertProperty("KEY_11", user.getLogin(), project.getId(), null);
insertProperty("KEY_12", user.getLogin(), project.getId(), null);
insertProperty("KEY_11", anotherUser.getLogin(), project.getId(), null);
}
@Test
- public void delete_by_key_and_value() throws SQLException {
- ComponentDto project = dbTester.components().insertPrivateProject();
- ComponentDto anotherProject = dbTester.components().insertPrivateProject();
+ public void delete_by_key_and_value() {
+ ComponentDto project = db.components().insertPrivateProject();
+ ComponentDto anotherProject = db.components().insertPrivateProject();
insertProperty("KEY", "VALUE", null, null);
insertProperty("KEY", "VALUE", project.getId(), null);
insertProperty("KEY", "VALUE", null, 100);
insertProperty("ANOTHER_KEY", "VALUE", project.getId(), 100);
underTest.deleteByKeyAndValue(session, "KEY", "VALUE");
- dbTester.commit();
+ db.commit();
- assertThat(dbTester.select("select prop_key as \"key\", text_value as \"value\", resource_id as \"projectId\", user_id as \"userId\" from properties"))
+ assertThat(db.select("select prop_key as \"key\", text_value as \"value\", resource_id as \"projectId\", user_id as \"userId\" from properties"))
.extracting((row) -> row.get("key"), (row) -> row.get("value"), (row) -> row.get("projectId"), (row) -> row.get("userId"))
.containsOnly(tuple("KEY", "ANOTHER_VALUE", null, null), tuple("ANOTHER_KEY", "VALUE", project.getId(), 100L));
}
session.commit();
}
- private long insertProperty(String key, @Nullable String value, @Nullable Long resourceId, @Nullable Integer userId, long createdAt) throws SQLException {
+ private long insertProperty(String key, @Nullable String value, @Nullable Long resourceId, @Nullable Integer userId, long createdAt) {
when(system2.now()).thenReturn(createdAt);
return insertProperty(key, value, resourceId, userId);
}
.setResourceId(resourceId)
.setUserId(userId)
.setValue(value);
- dbTester.properties().insertProperty(dto);
+ db.properties().insertProperty(dto);
- return (long) dbTester.selectFirst(session, "select id as \"id\" from properties" +
+ return (long) db.selectFirst(session, "select id as \"id\" from properties" +
" where prop_key='" + key + "'" +
" and user_id" + (userId == null ? " is null" : "='" + userId + "'") +
" and resource_id" + (resourceId == null ? " is null" : "='" + resourceId + "'")).get("id");
}
private ComponentDto insertPrivateProject(String uuid) {
- String key = "project" + uuid;
- ComponentDto project = ComponentTesting.newPrivateProjectDto(dbTester.getDefaultOrganization(), uuid).setDbKey(key);
- dbClient.componentDao().insert(session, project);
- dbTester.commit();
- return project;
+ return db.components().insertPrivateProject(db.getDefaultOrganization(), uuid);
}
private static PropertyDtoAssert assertThatDto(@Nullable PropertyDto dto) {
}
private PropertiesRowAssert assertThatPropertiesRow(String key, @Nullable Integer userId, @Nullable Integer componentId) {
- return new PropertiesRowAssert(dbTester, key, userId, componentId);
+ return new PropertiesRowAssert(db, key, userId, componentId);
}
private PropertiesRowAssert assertThatPropertiesRow(String key) {
- return new PropertiesRowAssert(dbTester, key);
+ return new PropertiesRowAssert(db, key);
}
private PropertiesRowAssert assertThatPropertiesRow(long id) {
- return new PropertiesRowAssert(dbTester, id);
+ return new PropertiesRowAssert(db, id);
}
}
import static org.sonar.db.user.GroupMembershipQuery.IN;
import static org.sonar.db.user.GroupMembershipQuery.OUT;
import static org.sonar.db.user.GroupMembershipQuery.builder;
-import static org.sonar.db.user.UserTesting.newDisabledUser;
-import static org.sonar.db.user.UserTesting.newUserDto;
public class GroupMembershipDaoTest {
@Before
public void setUp() throws Exception {
organizationDto = db.organizations().insert();
- user1 = db.users().insertUser(newUserDto("admin login", "Admin name", "admin@email.com"));
- user2 = db.users().insertUser(newUserDto("not.admin", "Not Admin", "Not Admin"));
- user3 = db.users().insertUser(newDisabledUser("inactive"));
+ user1 = db.users().insertUser(u -> u.setLogin("admin login").setName("Admin name").setEmail("admin@email.com"));
+ user2 = db.users().insertUser(u -> u.setLogin("not.admin").setName("Not Admin").setEmail("Not Admin"));
+ user3 = db.users().insertUser(u -> u.setLogin("inactive").setActive(false));
group1 = db.users().insertGroup(organizationDto, "sonar-administrators");
group2 = db.users().insertGroup(organizationDto, "sonar-users");
group3 = db.users().insertGroup(organizationDto, "sonar-reviewers");
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import org.junit.Before;
import org.junit.Rule;
when(system2.now()).thenReturn(NOW);
}
+ @Test
+ public void selectByUuid() {
+ UserDto user1 = db.users().insertUser();
+ UserDto user2 = db.users().insertUser(user -> user.setActive(false));
+
+ assertThat(underTest.selectByUuid(session, user1.getUuid())).isNotNull();
+ assertThat(underTest.selectByUuid(session, user2.getUuid())).isNotNull();
+ assertThat(underTest.selectByUuid(session, "unknown")).isNull();
+ }
+
@Test
public void selectUsersIds() {
UserDto user1 = db.users().insertUser(user -> user.setLogin("user1"));
assertThat(users).extracting("login").containsExactlyInAnyOrder("user1", "inactive_user");
}
+ @Test
+ public void selectUsersByUuids() {
+ UserDto user1 = db.users().insertUser();
+ UserDto user2 = db.users().insertUser();
+ UserDto user3 = db.users().insertUser(user -> user.setActive(false));
+
+ assertThat((Collection<UserDto>) underTest.selectByUuids(session, asList(user1.getUuid(), user2.getUuid(), user3.getUuid()))).hasSize(3);
+ assertThat((Collection<UserDto>) underTest.selectByUuids(session, asList(user1.getUuid(), "unknown"))).hasSize(1);
+ assertThat((Collection<UserDto>) underTest.selectByUuids(session, Collections.emptyList())).isEmpty();
+ }
+
@Test
public void selectUsersByLogins_empty_logins() {
// no need to access db
.setSalt("1234")
.setCryptedPassword("abcd")
.setHashMethod("SHA1")
- .setExternalIdentity("johngithub")
+ .setExternalLogin("johngithub")
.setExternalIdentityProvider("github")
+ .setExternalId("EXT_ID")
.setLocal(true)
.setCreatedAt(date)
.setUpdatedAt(date)
assertThat(user.getSalt()).isEqualTo("1234");
assertThat(user.getCryptedPassword()).isEqualTo("abcd");
assertThat(user.getHashMethod()).isEqualTo("SHA1");
- assertThat(user.getExternalIdentity()).isEqualTo("johngithub");
+ assertThat(user.getExternalLogin()).isEqualTo("johngithub");
assertThat(user.getExternalIdentityProvider()).isEqualTo("github");
+ assertThat(user.getExternalId()).isEqualTo("EXT_ID");
assertThat(user.isLocal()).isTrue();
assertThat(user.isRoot()).isFalse();
assertThat(user.getHomepageType()).isEqualTo("project");
.setLocal(true)
.setOnboarded(false));
- UserDto userUpdate = newUserDto()
- .setId(1)
- .setLogin("john")
+ underTest.update(db.getSession(), newUserDto()
+ .setUuid(user.getUuid())
+ .setLogin("johnDoo")
.setName("John Doo")
.setEmail("jodoo@hn.com")
.setScmAccounts(",jo.hn,john2,johndoo,")
.setSalt("12345")
.setCryptedPassword("abcde")
.setHashMethod("BCRYPT")
- .setExternalIdentity("johngithub")
+ .setExternalLogin("johngithub")
.setExternalIdentityProvider("github")
+ .setExternalId("EXT_ID")
.setLocal(false)
.setHomepageType("project")
- .setHomepageParameter("OB1");
- underTest.update(db.getSession(), userUpdate);
+ .setHomepageParameter("OB1"));
- UserDto reloaded = underTest.selectByLogin(db.getSession(), user.getLogin());
+ UserDto reloaded = underTest.selectByUuid(db.getSession(), user.getUuid());
assertThat(reloaded).isNotNull();
assertThat(reloaded.getId()).isEqualTo(user.getId());
- assertThat(reloaded.getLogin()).isEqualTo(user.getLogin());
+ assertThat(reloaded.getLogin()).isEqualTo("johnDoo");
assertThat(reloaded.getName()).isEqualTo("John Doo");
assertThat(reloaded.getEmail()).isEqualTo("jodoo@hn.com");
assertThat(reloaded.isActive()).isFalse();
assertThat(reloaded.getSalt()).isEqualTo("12345");
assertThat(reloaded.getCryptedPassword()).isEqualTo("abcde");
assertThat(reloaded.getHashMethod()).isEqualTo("BCRYPT");
- assertThat(reloaded.getExternalIdentity()).isEqualTo("johngithub");
+ assertThat(reloaded.getExternalLogin()).isEqualTo("johngithub");
assertThat(reloaded.getExternalIdentityProvider()).isEqualTo("github");
+ assertThat(reloaded.getExternalId()).isEqualTo("EXT_ID");
assertThat(reloaded.isLocal()).isFalse();
assertThat(reloaded.isRoot()).isFalse();
assertThat(reloaded.getHomepageType()).isEqualTo("project");
UserDto userReloaded = underTest.selectUserById(session, user.getId());
assertThat(userReloaded.isActive()).isFalse();
+ assertThat(userReloaded.getLogin()).isNotNull();
+ assertThat(userReloaded.getExternalId()).isNotNull();
+ assertThat(userReloaded.getExternalLogin()).isNotNull();
+ assertThat(userReloaded.getExternalIdentityProvider()).isNotNull();
assertThat(userReloaded.getEmail()).isNull();
assertThat(userReloaded.getScmAccounts()).isNull();
assertThat(userReloaded.getSalt()).isNull();
assertThat(userReloaded.getCryptedPassword()).isNull();
- assertThat(userReloaded.getExternalIdentity()).isNull();
- assertThat(userReloaded.getExternalIdentityProvider()).isNull();
assertThat(userReloaded.isRoot()).isFalse();
assertThat(userReloaded.getUpdatedAt()).isEqualTo(NOW);
assertThat(userReloaded.getHomepageType()).isNull();
assertThat(underTest.selectByEmail(session, "unknown")).isNull();
}
+ @Test
+ public void select_by_external_id_and_identity_provider() {
+ UserDto activeUser = db.users().insertUser();
+ UserDto disableUser = db.users().insertUser(u -> u.setActive(false));
+
+ assertThat(underTest.selectByExternalIdAndIdentityProvider(session, activeUser.getExternalId(), activeUser.getExternalIdentityProvider())).isNotNull();
+ assertThat(underTest.selectByExternalIdAndIdentityProvider(session, disableUser.getExternalId(), disableUser.getExternalIdentityProvider())).isNotNull();
+ assertThat(underTest.selectByExternalIdAndIdentityProvider(session, "unknown", "unknown")).isNull();
+ }
+
@Test
public void setRoot_does_not_fail_on_non_existing_login() {
underTest.setRoot(session, "unkown", true);
}
@Test
- public void scrollByLogins() {
+ public void scrollByLUuids() {
UserDto u1 = insertUser(true);
UserDto u2 = insertUser(false);
UserDto u3 = insertUser(false);
List<UserDto> result = new ArrayList<>();
- underTest.scrollByLogins(db.getSession(), asList(u2.getLogin(), u3.getLogin(), "does not exist"), result::add);
+ underTest.scrollByUuids(db.getSession(), asList(u2.getUuid(), u3.getUuid(), "does not exist"), result::add);
- assertThat(result).extracting(UserDto::getLogin, UserDto::getName)
- .containsExactlyInAnyOrder(tuple(u2.getLogin(), u2.getName()), tuple(u3.getLogin(), u3.getName()));
+ assertThat(result).extracting(UserDto::getUuid, UserDto::getName)
+ .containsExactlyInAnyOrder(tuple(u2.getUuid(), u2.getName()), tuple(u3.getUuid(), u3.getName()));
}
@Test
- public void scrollByLogins_scrolls_by_pages_of_1000_logins() {
- List<String> logins = new ArrayList<>();
+ public void scrollByUuids_scrolls_by_pages_of_1000_uuids() {
+ List<String> uuids = new ArrayList<>();
for (int i = 0; i < DatabaseUtils.PARTITION_SIZE_FOR_ORACLE + 10; i++) {
- logins.add(insertUser(true).getLogin());
+ uuids.add(insertUser(true).getUuid());
}
List<UserDto> result = new ArrayList<>();
- underTest.scrollByLogins(db.getSession(), logins, result::add);
+ underTest.scrollByUuids(db.getSession(), uuids, result::add);
assertThat(result)
- .extracting(UserDto::getLogin)
- .containsExactlyInAnyOrder(logins.toArray(new String[0]));
+ .extracting(UserDto::getUuid)
+ .containsExactlyInAnyOrder(uuids.toArray(new String[0]));
}
@Test
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;
public class UserDbTester {
return insertUser(dto);
}
- public UserDto insertUser(Consumer<UserDto> populateUserDto) {
+ @SafeVarargs
+ public final UserDto insertUser(Consumer<UserDto>... populators) {
UserDto dto = newUserDto().setActive(true);
- populateUserDto.accept(dto);
+ stream(populators).forEach(p -> p.accept(dto));
+ return insertUser(dto);
+ }
+
+ @SafeVarargs
+ public final UserDto insertDisabledUser(Consumer<UserDto>... populators) {
+ UserDto dto = newDisabledUser();
+ stream(populators).forEach(p -> p.accept(dto));
return insertUser(dto);
}
.setEmail(randomAlphanumeric(30))
.setOnboarded(nextBoolean())
.setScmAccounts(singletonList(randomAlphanumeric(40)))
- .setExternalIdentity(randomAlphanumeric(40))
+ .setExternalId(randomAlphanumeric(40))
+ .setExternalLogin(randomAlphanumeric(40))
.setExternalIdentityProvider(randomAlphanumeric(40))
.setSalt(randomAlphanumeric(40))
.setCryptedPassword(randomAlphanumeric(40))
.setName(name)
.setEmail(email)
.setLogin(login)
- .setExternalIdentity(login)
+ .setExternalId(login)
+ .setExternalLogin(login)
.setExternalIdentityProvider("sonarqube");
}
.setName(name)
.setEmail(email)
.setLogin(login)
- .setExternalIdentity(randomAlphanumeric(40))
+ .setExternalId(randomAlphanumeric(40))
+ .setExternalLogin(randomAlphanumeric(40))
.setExternalIdentityProvider(randomAlphanumeric(40));
}
- public static UserDto newDisabledUser(String login) {
+ public static UserDto newDisabledUser() {
return newUserDto()
- .setLogin(login)
.setActive(false)
// All these fields are reset when disabling a user
.setScmAccounts((String) null)
- .setExternalIdentity(null)
- .setExternalIdentityProvider(null)
.setEmail(null)
.setCryptedPassword(null)
.setSalt(null);
+++ /dev/null
-<dataset>
-
- <users id="200"
- uuid="user1uuid"
- login="user1"
- name="User1"
- active="[true]"
- is_root="[false]"
- onboarded="[true]"/>
- <users id="201"
- uuid="user2uuid"
- login="user2"
- name="User2"
- active="[true]"
- is_root="[false]"
- onboarded="[true]"/>
- <users id="202"
- uuid="user3uuid"
- login="user3"
- name="User3"
- active="[true]"
- is_root="[false]"
- onboarded="[true]"/>
- <users id="999"
- uuid="user999uuid"
- login="disabledUser"
- name="disabledUser"
- active="[false]"
- is_root="[false]"
- onboarded="[true]"/>
-
- <organization_members
- user_id="200"
- organization_uuid="ORG_UUID"
- />
-
- <organization_members
- user_id="201"
- organization_uuid="ORG_UUID"
- />
-
- <organization_members
- user_id="202"
- organization_uuid="ORG_UUID"
- />
-
- <perm_templates_users id="1"
- user_id="200"
- permission_reference="user"
- template_id="50"/>
- <perm_templates_users id="2"
- user_id="200"
- permission_reference="admin"
- template_id="50"/>
- <perm_templates_users id="3"
- user_id="200"
- permission_reference="codeviewer"
- template_id="50"/>
-
- <perm_templates_users id="4"
- user_id="201"
- permission_reference="user"
- template_id="50"/>
-
-</dataset>
+++ /dev/null
-<dataset>
-
- <users id="200"
- uuid="user1uuid"
- login="user1"
- name="User1"
- active="[true]"
- is_root="[false]"
- onboarded="[true]"/>
- <users id="201"
- uuid="user2uuid"
- login="user2"
- name="User2"
- active="[true]"
- is_root="[false]"
- onboarded="[true]"/>
- <users id="202"
- uuid="user3uuid"
- login="user3"
- name="User3"
- active="[true]"
- is_root="[false]"
- onboarded="[true]"/>
-
- <organization_members
- user_id="200"
- organization_uuid="ORG_UUID"
- />
-
- <organization_members
- user_id="201"
- organization_uuid="ORG_UUID"
- />
-
- <organization_members
- user_id="202"
- organization_uuid="ORG_UUID"
- />
-
- <perm_templates_users id="1"
- user_id="200"
- permission_reference="user"
- template_id="50"/>
- <perm_templates_users id="2"
- user_id="200"
- permission_reference="admin"
- template_id="50"/>
- <perm_templates_users id="3"
- user_id="200"
- permission_reference="codeviewer"
- template_id="50"/>
- <perm_templates_users id="4"
- user_id="200"
- permission_reference="user"
- template_id="51"/>
-
- <perm_templates_users id="5"
- user_id="201"
- permission_reference="user"
- template_id="50"/>
-
-</dataset>
+++ /dev/null
-<dataset>
-
- <users id="200"
- uuid="user3uuid"
- login="user3"
- name="User3"
- active="[true]"
- is_root="[false]"
- onboarded="[true]"/>
- <users id="201"
- uuid="user1uuid"
- login="user1"
- name="User1"
- active="[true]"
- is_root="[false]"
- onboarded="[true]"/>
- <users id="202"
- uuid="user2uuid"
- login="user2"
- name="User2"
- active="[true]"
- is_root="[false]"
- onboarded="[true]"/>
-
- <organization_members
- user_id="200"
- organization_uuid="ORG_UUID"
- />
-
- <organization_members
- user_id="201"
- organization_uuid="ORG_UUID"
- />
-
- <organization_members
- user_id="202"
- organization_uuid="ORG_UUID"
- />
-
- <perm_templates_users id="1"
- user_id="200"
- permission_reference="user"
- template_id="50"/>
- <perm_templates_users id="2"
- user_id="200"
- permission_reference="admin"
- template_id="50"/>
- <perm_templates_users id="3"
- user_id="200"
- permission_reference="codeviewer"
- template_id="50"/>
-
- <perm_templates_users id="4"
- user_id="201"
- permission_reference="user"
- template_id="50"/>
-
-</dataset>
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.v72;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.sql.AddColumnsBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;
+
+public class AddExternalIdToUsers extends DdlChange {
+
+ public AddExternalIdToUsers(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ context.execute(new AddColumnsBuilder(getDialect(), "users")
+ .addColumn(newVarcharColumnDefBuilder()
+ .setColumnName("external_id")
+ .setLimit(255)
+ .setIsNullable(true)
+ .build())
+ .build());
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.v72;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.def.VarcharColumnDef;
+import org.sonar.server.platform.db.migration.sql.CreateIndexBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;
+
+public class AddUniqueIndexesOnUsers extends DdlChange {
+
+ public AddUniqueIndexesOnUsers(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ context.execute(new CreateIndexBuilder(getDialect())
+ .setTable("users")
+ .setName("users_uuid")
+ .setUnique(true)
+ .addColumn(notNullableColumn("uuid", 40))
+ .build());
+
+ context.execute(new CreateIndexBuilder(getDialect())
+ .setTable("users")
+ .setName("uniq_external_id")
+ .setUnique(true)
+ .addColumn(notNullableColumn("external_identity_provider", 100))
+ .addColumn(notNullableColumn("external_id", 255))
+ .build());
+ }
+
+ private static VarcharColumnDef notNullableColumn(String columnName, int limit) {
+ return newVarcharColumnDefBuilder()
+ .setColumnName(columnName)
+ .setLimit(limit)
+ .setIsNullable(false)
+ .build();
+ }
+
+}
.add(2106, "Create PROJECT_MAPPINGS table", CreateProjectMappingsTable.class)
.add(2107, "Add UUID on table USERS", AddUUIDtoUsers.class)
.add(2108, "Populate USERS.UUID with USERS.LOGIN", PopulateUUIDOnUsers.class)
+ .add(2109, "Add EXTERNAL_ID on table users", AddExternalIdToUsers.class)
+ .add(2110, "Rename EXTERNAL_IDENTITY to EXTERNAL_LOGIN on table users", RenameExternalIdentityToExternalLoginOnUsers.class)
+ .add(2111, "Update null values from external columns and login of users", UpdateNullValuesFromExternalColumnsAndLoginOfUsers.class)
+ .add(2112, "Populate EXTERNAL_ID on table users", PopulateExternalIdOnUsers.class)
+ .add(2113, "Makes same columns of table users not nullable", MakeSomeColumnsOfUsersNotNullable.class)
+ .add(2114, "Add unique indexes on table users", AddUniqueIndexesOnUsers.class)
+
;
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.v72;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.def.VarcharColumnDef;
+import org.sonar.server.platform.db.migration.sql.AlterColumnsBuilder;
+import org.sonar.server.platform.db.migration.sql.CreateIndexBuilder;
+import org.sonar.server.platform.db.migration.sql.DropIndexBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;
+
+public class MakeSomeColumnsOfUsersNotNullable extends DdlChange {
+
+ public static final String USERS_TABLE = "users";
+ public static final String USERS_LOGIN_INDEX = "users_login";
+
+ public MakeSomeColumnsOfUsersNotNullable(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ context.execute(new DropIndexBuilder(getDialect())
+ .setTable(USERS_TABLE)
+ .setName(USERS_LOGIN_INDEX)
+ .build());
+
+ context.execute(new AlterColumnsBuilder(getDialect(), USERS_TABLE)
+ .updateColumn(notNullableColumn("uuid", 40))
+ .updateColumn(notNullableColumn("login", 255))
+ .updateColumn(notNullableColumn("external_id", 255))
+ .updateColumn(notNullableColumn("external_login", 255))
+ .updateColumn(notNullableColumn("external_identity_provider", 100))
+ .build());
+
+ context.execute(new CreateIndexBuilder(getDialect())
+ .setTable(USERS_TABLE)
+ .setName(USERS_LOGIN_INDEX)
+ .addColumn(notNullableColumn("login", 255))
+ .setUnique(true)
+ .build());
+ }
+
+ private static VarcharColumnDef notNullableColumn(String columnName, int limit) {
+ return newVarcharColumnDefBuilder()
+ .setColumnName(columnName)
+ .setLimit(limit)
+ .setIsNullable(false)
+ .build();
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.v72;
+
+import java.sql.SQLException;
+import org.sonar.api.utils.System2;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.step.DataChange;
+import org.sonar.server.platform.db.migration.step.MassUpdate;
+
+public class PopulateExternalIdOnUsers extends DataChange {
+
+ private final System2 system2;
+
+ public PopulateExternalIdOnUsers(Database db, System2 system2) {
+ super(db);
+ this.system2 = system2;
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ MassUpdate massUpdate = context.prepareMassUpdate().rowPluralName("users");
+ massUpdate.select("SELECT id, external_login FROM users WHERE external_id IS NULL");
+ massUpdate.update("UPDATE users SET external_id=?, updated_at=? WHERE id=?");
+
+ long now = system2.now();
+ massUpdate.execute((row, update) -> {
+ long id = row.getLong(1);
+ String externalLogin = row.getString(2);
+ update.setString(1, externalLogin);
+ update.setLong(2, now);
+ update.setLong(3, id);
+ return true;
+ });
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.v72;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.sql.RenameColumnsBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;
+
+public class RenameExternalIdentityToExternalLoginOnUsers extends DdlChange {
+
+ public RenameExternalIdentityToExternalLoginOnUsers(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ context.execute(new RenameColumnsBuilder(getDialect(), "users")
+ .renameColumn("external_identity",
+ newVarcharColumnDefBuilder()
+ .setColumnName("external_login")
+ .setLimit(255)
+ .build())
+ .build());
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.v72;
+
+import java.sql.SQLException;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.step.DataChange;
+import org.sonar.server.platform.db.migration.step.MassUpdate;
+
+/**
+ * The goal of this migration is to sanitize disabled USERS, regarding new way of authentication users.
+ * Indeed, authentication will search for user but LOGIN but also buy using EXTERNAL_ID and EXTERNAL_PROVIDER.
+ *
+ * As a consequence, these columns must be set as NOT NULL in order to add a UNIQUE index on them.
+ *
+ * Unfortunately, these columns were previously set as null when disabling a user, that's why we need to populate them.
+ */
+public class UpdateNullValuesFromExternalColumnsAndLoginOfUsers extends DataChange {
+
+ private static final Logger LOG = Loggers.get(UpdateNullValuesFromExternalColumnsAndLoginOfUsers.class);
+
+ private final System2 system2;
+ private UuidFactory uuidFactory;
+
+ public UpdateNullValuesFromExternalColumnsAndLoginOfUsers(Database db, System2 system2, UuidFactory uuidFactory) {
+ super(db);
+ this.system2 = system2;
+ this.uuidFactory = uuidFactory;
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ MassUpdate massUpdate = context.prepareMassUpdate().rowPluralName("users");
+ massUpdate.select("SELECT id, login FROM users WHERE login IS NULL OR external_login IS NULL OR external_identity_provider IS NULL");
+ massUpdate.update("UPDATE users SET login=?, external_login=?, external_identity_provider=?, updated_at=? WHERE id=?");
+
+ long now = system2.now();
+ massUpdate.execute((row, update) -> {
+ long id = row.getLong(1);
+ String login = row.getString(2);
+ if (login == null) {
+ LOG.warn("No login has been found for user id '{}'. A UUID has been generated to not have null value.", id);
+ login = uuidFactory.create();
+ }
+ update.setString(1, login);
+ update.setString(2, login);
+ update.setString(3, "sonarqube");
+ update.setLong(4, now);
+ update.setLong(5, id);
+ return true;
+ });
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.v72;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.db.CoreDbTester;
+
+import static java.sql.Types.VARCHAR;
+
+public class AddExternalIdToUsersTest {
+ @Rule
+ public final CoreDbTester db = CoreDbTester.createForSchema(AddExternalIdToUsersTest.class, "users.sql");
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private AddExternalIdToUsers underTest = new AddExternalIdToUsers(db.database());
+
+ @Test
+ public void column_is_added_to_table() throws SQLException {
+ underTest.execute();
+
+ db.assertColumnDefinition("users", "external_id", VARCHAR, 255, true);
+ }
+
+ @Test
+ public void migration_is_reentrant() throws SQLException {
+ underTest.execute();
+
+ expectedException.expect(IllegalStateException.class);
+
+ underTest.execute();
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.v72;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.db.CoreDbTester;
+
+public class AddUniqueIndexesOnUsersTest {
+
+ @Rule
+ public final CoreDbTester db = CoreDbTester.createForSchema(AddUniqueIndexesOnUsersTest.class, "users.sql");
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private AddUniqueIndexesOnUsers underTest = new AddUniqueIndexesOnUsers(db.database());
+
+ @Test
+ public void add_unique_indexes() throws SQLException {
+ underTest.execute();
+
+ db.assertUniqueIndex("users", "users_uuid", "uuid");
+ db.assertUniqueIndex("users", "uniq_external_id", "external_identity_provider", "external_id");
+ }
+
+ @Test
+ public void migration_is_not_reentrant() throws SQLException {
+ underTest.execute();
+
+ expectedException.expect(IllegalStateException.class);
+
+ underTest.execute();
+ }
+
+}
@Test
public void verify_migration_count() {
- verifyMigrationCount(underTest, 9);
+ verifyMigrationCount(underTest, 15);
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.v72;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+
+import static java.sql.Types.VARCHAR;
+
+public class MakeSomeColumnsOfUsersNotNullableTest {
+
+ @Rule
+ public final CoreDbTester db = CoreDbTester.createForSchema(MakeSomeColumnsOfUsersNotNullableTest.class, "users.sql");
+
+ private MakeSomeColumnsOfUsersNotNullable underTest = new MakeSomeColumnsOfUsersNotNullable(db.database());
+
+ @Test
+ public void columns_are_set_as_not_nullable() throws SQLException {
+ underTest.execute();
+
+ db.assertColumnDefinition("users", "uuid", VARCHAR, 40, false);
+ db.assertColumnDefinition("users", "login", VARCHAR, 255, false);
+ db.assertColumnDefinition("users", "external_id", VARCHAR, 255, false);
+ db.assertColumnDefinition("users", "external_login", VARCHAR, 255, false);
+ db.assertColumnDefinition("users", "external_identity_provider", VARCHAR, 100, false);
+ db.assertUniqueIndex("users", "users_login", "login");
+ }
+
+ @Test
+ public void migration_is_reentrant() throws SQLException {
+ underTest.execute();
+ underTest.execute();
+
+ db.assertColumnDefinition("users", "uuid", VARCHAR, 40, false);
+ db.assertColumnDefinition("users", "login", VARCHAR, 255, false);
+ db.assertColumnDefinition("users", "external_id", VARCHAR, 255, false);
+ db.assertColumnDefinition("users", "external_login", VARCHAR, 255, false);
+ db.assertColumnDefinition("users", "external_identity_provider", VARCHAR, 100, false);
+ db.assertUniqueIndex("users", "users_login", "login");
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.v72;
+
+import java.sql.SQLException;
+import java.util.stream.Collectors;
+import javax.annotation.Nullable;
+import org.assertj.core.groups.Tuple;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.db.CoreDbTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.tuple;
+
+public class PopulateExternalIdOnUsersTest {
+
+ private static final long PAST = 5_000_000_000L;
+ private static final long NOW = 10_000_000_000L;
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(PopulateExternalIdOnUsersTest.class, "users.sql");
+
+ private System2 system2 = new TestSystem2().setNow(NOW);
+
+ private PopulateExternalIdOnUsers underTest = new PopulateExternalIdOnUsers(db.database(), system2);
+
+ @Test
+ public void update_users() throws SQLException {
+ insertUser("USER_1", "user1", null);
+ insertUser("USER_2", "user2", "1234");
+
+ underTest.execute();
+
+ assertUsers(
+ tuple("USER_1", "user1", NOW),
+ tuple("USER_2", "1234", PAST));
+ }
+
+ @Test
+ public void migration_is_reentrant() throws SQLException {
+ insertUser("USER_1", "user1", null);
+ insertUser("USER_2", "user2", "1234");
+
+ underTest.execute();
+ underTest.execute();
+
+ assertUsers(
+ tuple("USER_1", "user1", NOW),
+ tuple("USER_2", "1234", PAST));
+ }
+
+ private void assertUsers(Tuple... expectedTuples) {
+ assertThat(db.select("SELECT LOGIN, EXTERNAL_ID, UPDATED_AT FROM USERS")
+ .stream()
+ .map(map -> new Tuple(map.get("LOGIN"), map.get("EXTERNAL_ID"), map.get("UPDATED_AT")))
+ .collect(Collectors.toList()))
+ .containsExactlyInAnyOrder(expectedTuples);
+ }
+
+ private void insertUser(String login, String externalLogin, @Nullable String externalId) {
+ db.executeInsert("USERS",
+ "LOGIN", login,
+ "EXTERNAL_ID", externalId,
+ "EXTERNAL_LOGIN", externalLogin,
+ "CREATED_AT", PAST,
+ "UPDATED_AT", PAST,
+ "IS_ROOT", false,
+ "ONBOARDED", false);
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.v72;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.db.CoreDbTester;
+
+import static java.sql.Types.VARCHAR;
+
+public class RenameExternalIdentityToExternalLoginOnUsersTest {
+
+ @Rule
+ public final CoreDbTester db = CoreDbTester.createForSchema(RenameExternalIdentityToExternalLoginOnUsersTest.class, "users.sql");
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private RenameExternalIdentityToExternalLoginOnUsers underTest = new RenameExternalIdentityToExternalLoginOnUsers(db.database());
+
+ @Test
+ public void column_is_renamed() throws SQLException {
+ underTest.execute();
+
+ db.assertColumnDefinition("users", "external_login", VARCHAR, 255, true);
+ db.assertColumnDoesNotExist("users", "external_identity");
+ }
+
+ @Test
+ public void migration_is_not_reentrant() throws SQLException {
+ underTest.execute();
+
+ expectedException.expect(IllegalStateException.class);
+
+ underTest.execute();
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.v72;
+
+import java.sql.SQLException;
+import javax.annotation.Nullable;
+import org.assertj.core.groups.Tuple;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.utils.log.LogTester;
+import org.sonar.api.utils.log.LoggerLevel;
+import org.sonar.core.util.SequenceUuidFactory;
+import org.sonar.db.CoreDbTester;
+
+import static java.lang.String.format;
+import static java.util.stream.Collectors.toList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.tuple;
+
+public class UpdateNullValuesFromExternalColumnsAndLoginOfUsersTest {
+
+ private static final long PAST = 5_000_000_000L;
+ private static final long NOW = 10_000_000_000L;
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(UpdateNullValuesFromExternalColumnsAndLoginOfUsersTest.class, "users.sql");
+
+ @Rule
+ public LogTester logTester = new LogTester();
+
+ private System2 system2 = new TestSystem2().setNow(NOW);
+
+ private UpdateNullValuesFromExternalColumnsAndLoginOfUsers underTest = new UpdateNullValuesFromExternalColumnsAndLoginOfUsers(db.database(), system2, new SequenceUuidFactory());
+
+ @Test
+ public void update_users() throws SQLException {
+ insertUser("USER_1", "user1", "github");
+ insertUser("USER_2", null, null);
+ insertUser("USER_3", "user", null);
+ insertUser("USER_4", null, "github");
+ insertUser(null, "user", "bitbucket");
+ insertUser(null, null, null);
+
+ underTest.execute();
+
+ assertUsers(
+ tuple("USER_1", "user1", "github", PAST),
+ tuple("USER_2", "USER_2", "sonarqube", NOW),
+ tuple("USER_3", "USER_3", "sonarqube", NOW),
+ tuple("USER_4", "USER_4", "sonarqube", NOW),
+ tuple("1", "1", "sonarqube", NOW),
+ tuple("2", "2", "sonarqube", NOW));
+ }
+
+ @Test
+ public void log_warning_when_login_is_null() throws SQLException {
+ insertUser(null, "user", "bitbucket");
+ long id = (long) db.selectFirst("SELECT ID FROM USERS").get("ID");
+
+ underTest.execute();
+
+ assertThat(logTester.logs(LoggerLevel.WARN))
+ .containsExactlyInAnyOrder(format("No login has been found for user id '%s'. A UUID has been generated to not have null value.", id));
+ }
+
+ @Test
+ public void is_reentrant() throws SQLException {
+ insertUser("USER_1", null, null);
+
+ underTest.execute();
+ underTest.execute();
+
+ assertUsers(tuple("USER_1", "USER_1", "sonarqube", NOW));
+ }
+
+ private void assertUsers(Tuple... expectedTuples) {
+ assertThat(db.select("SELECT LOGIN, EXTERNAL_LOGIN, EXTERNAL_IDENTITY_PROVIDER, UPDATED_AT FROM USERS")
+ .stream()
+ .map(map -> new Tuple(map.get("LOGIN"), map.get("EXTERNAL_LOGIN"), map.get("EXTERNAL_IDENTITY_PROVIDER"), map.get("UPDATED_AT")))
+ .collect(toList()))
+ .containsExactlyInAnyOrder(expectedTuples);
+ }
+
+ private void insertUser(@Nullable String login, @Nullable String externalLogin, @Nullable String externalIdentityProvider) {
+ db.executeInsert("USERS",
+ "LOGIN", login,
+ "EXTERNAL_LOGIN", externalLogin,
+ "EXTERNAL_IDENTITY_PROVIDER", externalIdentityProvider,
+ "CREATED_AT", PAST,
+ "UPDATED_AT", PAST,
+ "IS_ROOT", false,
+ "ONBOARDED", false);
+ }
+
+}
--- /dev/null
+CREATE TABLE "USERS" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "UUID" VARCHAR(40),
+ "LOGIN" VARCHAR(255),
+ "NAME" VARCHAR(200),
+ "EMAIL" VARCHAR(100),
+ "CRYPTED_PASSWORD" VARCHAR(100),
+ "SALT" VARCHAR(40),
+ "ACTIVE" BOOLEAN DEFAULT TRUE,
+ "SCM_ACCOUNTS" VARCHAR(4000),
+ "EXTERNAL_IDENTITY" VARCHAR(255),
+ "EXTERNAL_IDENTITY_PROVIDER" VARCHAR(100),
+ "IS_ROOT" BOOLEAN NOT NULL,
+ "USER_LOCAL" BOOLEAN,
+ "ONBOARDED" BOOLEAN NOT NULL,
+ "CREATED_AT" BIGINT,
+ "UPDATED_AT" BIGINT,
+ "HOMEPAGE_TYPE" VARCHAR(40),
+ "HOMEPAGE_PARAMETER" VARCHAR(40)
+);
+CREATE UNIQUE INDEX "USERS_LOGIN" ON "USERS" ("LOGIN");
+CREATE INDEX "USERS_UPDATED_AT" ON "USERS" ("UPDATED_AT");
--- /dev/null
+CREATE TABLE "USERS" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "UUID" VARCHAR(40),
+ "LOGIN" VARCHAR(255),
+ "NAME" VARCHAR(200),
+ "EMAIL" VARCHAR(100),
+ "CRYPTED_PASSWORD" VARCHAR(100),
+ "SALT" VARCHAR(40),
+ "ACTIVE" BOOLEAN DEFAULT TRUE,
+ "SCM_ACCOUNTS" VARCHAR(4000),
+ "EXTERNAL_ID" VARCHAR(255),
+ "EXTERNAL_LOGIN" VARCHAR(255),
+ "EXTERNAL_IDENTITY_PROVIDER" VARCHAR(100),
+ "IS_ROOT" BOOLEAN NOT NULL,
+ "USER_LOCAL" BOOLEAN,
+ "ONBOARDED" BOOLEAN NOT NULL,
+ "CREATED_AT" BIGINT,
+ "UPDATED_AT" BIGINT,
+ "HOMEPAGE_TYPE" VARCHAR(40),
+ "HOMEPAGE_PARAMETER" VARCHAR(40)
+);
+CREATE UNIQUE INDEX "USERS_LOGIN" ON "USERS" ("LOGIN");
+CREATE INDEX "USERS_UPDATED_AT" ON "USERS" ("UPDATED_AT");
--- /dev/null
+CREATE TABLE "USERS" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "UUID" VARCHAR(40),
+ "LOGIN" VARCHAR(255),
+ "NAME" VARCHAR(200),
+ "EMAIL" VARCHAR(100),
+ "CRYPTED_PASSWORD" VARCHAR(100),
+ "SALT" VARCHAR(40),
+ "ACTIVE" BOOLEAN DEFAULT TRUE,
+ "SCM_ACCOUNTS" VARCHAR(4000),
+ "EXTERNAL_ID" VARCHAR(255),
+ "EXTERNAL_LOGIN" VARCHAR(255),
+ "EXTERNAL_IDENTITY_PROVIDER" VARCHAR(100),
+ "IS_ROOT" BOOLEAN NOT NULL,
+ "USER_LOCAL" BOOLEAN,
+ "ONBOARDED" BOOLEAN NOT NULL,
+ "CREATED_AT" BIGINT,
+ "UPDATED_AT" BIGINT,
+ "HOMEPAGE_TYPE" VARCHAR(40),
+ "HOMEPAGE_PARAMETER" VARCHAR(40)
+);
+CREATE UNIQUE INDEX "USERS_LOGIN" ON "USERS" ("LOGIN");
+CREATE INDEX "USERS_UPDATED_AT" ON "USERS" ("UPDATED_AT");
--- /dev/null
+CREATE TABLE "USERS" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "UUID" VARCHAR(40),
+ "LOGIN" VARCHAR(255),
+ "NAME" VARCHAR(200),
+ "EMAIL" VARCHAR(100),
+ "CRYPTED_PASSWORD" VARCHAR(100),
+ "SALT" VARCHAR(40),
+ "ACTIVE" BOOLEAN DEFAULT TRUE,
+ "SCM_ACCOUNTS" VARCHAR(4000),
+ "EXTERNAL_ID" VARCHAR(255),
+ "EXTERNAL_LOGIN" VARCHAR(255),
+ "EXTERNAL_IDENTITY_PROVIDER" VARCHAR(100),
+ "IS_ROOT" BOOLEAN NOT NULL,
+ "USER_LOCAL" BOOLEAN,
+ "ONBOARDED" BOOLEAN NOT NULL,
+ "CREATED_AT" BIGINT,
+ "UPDATED_AT" BIGINT,
+ "HOMEPAGE_TYPE" VARCHAR(40),
+ "HOMEPAGE_PARAMETER" VARCHAR(40)
+);
+CREATE UNIQUE INDEX "USERS_LOGIN" ON "USERS" ("LOGIN");
+CREATE INDEX "USERS_UPDATED_AT" ON "USERS" ("UPDATED_AT");
--- /dev/null
+CREATE TABLE "USERS" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "UUID" VARCHAR(40),
+ "LOGIN" VARCHAR(255),
+ "NAME" VARCHAR(200),
+ "EMAIL" VARCHAR(100),
+ "CRYPTED_PASSWORD" VARCHAR(100),
+ "SALT" VARCHAR(40),
+ "ACTIVE" BOOLEAN DEFAULT TRUE,
+ "SCM_ACCOUNTS" VARCHAR(4000),
+ "EXTERNAL_ID" VARCHAR(255),
+ "EXTERNAL_IDENTITY" VARCHAR(255),
+ "EXTERNAL_IDENTITY_PROVIDER" VARCHAR(100),
+ "IS_ROOT" BOOLEAN NOT NULL,
+ "USER_LOCAL" BOOLEAN,
+ "ONBOARDED" BOOLEAN NOT NULL,
+ "CREATED_AT" BIGINT,
+ "UPDATED_AT" BIGINT,
+ "HOMEPAGE_TYPE" VARCHAR(40),
+ "HOMEPAGE_PARAMETER" VARCHAR(40)
+);
+CREATE UNIQUE INDEX "USERS_LOGIN" ON "USERS" ("LOGIN");
+CREATE INDEX "USERS_UPDATED_AT" ON "USERS" ("UPDATED_AT");
--- /dev/null
+CREATE TABLE "USERS" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "UUID" VARCHAR(40),
+ "LOGIN" VARCHAR(255),
+ "NAME" VARCHAR(200),
+ "EMAIL" VARCHAR(100),
+ "CRYPTED_PASSWORD" VARCHAR(100),
+ "SALT" VARCHAR(40),
+ "ACTIVE" BOOLEAN DEFAULT TRUE,
+ "SCM_ACCOUNTS" VARCHAR(4000),
+ "EXTERNAL_ID" VARCHAR(255),
+ "EXTERNAL_LOGIN" VARCHAR(255),
+ "EXTERNAL_IDENTITY_PROVIDER" VARCHAR(100),
+ "IS_ROOT" BOOLEAN NOT NULL,
+ "USER_LOCAL" BOOLEAN,
+ "ONBOARDED" BOOLEAN NOT NULL,
+ "CREATED_AT" BIGINT,
+ "UPDATED_AT" BIGINT,
+ "HOMEPAGE_TYPE" VARCHAR(40),
+ "HOMEPAGE_PARAMETER" VARCHAR(40)
+);
+CREATE UNIQUE INDEX "USERS_LOGIN" ON "USERS" ("LOGIN");
+CREATE INDEX "USERS_UPDATED_AT" ON "USERS" ("UPDATED_AT");
return session.wsClient().userGroups().create(request).getGroup();
}
+ @SafeVarargs
+ public final UserGroups.Group generate(Consumer<CreateRequest>... populators) {
+ return generate(null, populators);
+ }
+
public List<Group> getGroupsOfUser(@Nullable Organizations.Organization organization, String userLogin) {
GroupsRequest request = new GroupsRequest()
.setOrganization(organization != null ? organization.getKey() : null)
.filter(u -> !"admin".equals(u.getLogin()))
.forEach(u -> {
PostRequest request = new PostRequest("api/users/deactivate").setParam("login", u.getLogin());
- session.wsClient().wsConnector().call(request);
+ session.wsClient().wsConnector().call(request).failIfNotSuccessful();
});
}
encodeMessage(email),
encodeMessage(userIdentity.getProviderLogin()),
encodeMessage(provider.getKey()),
- encodeMessage(existingUser.getExternalIdentity()),
+ encodeMessage(existingUser.getExternalLogin()),
encodeMessage(existingUser.getExternalIdentityProvider()));
}
}
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
import org.sonar.api.server.authentication.IdentityProvider;
import org.sonar.api.server.authentication.UserIdentity;
import org.sonar.api.utils.log.Logger;
this.defaultGroupFinder = defaultGroupFinder;
}
- public UserDto authenticate(UserIdentity user, IdentityProvider provider, AuthenticationEvent.Source source, ExistingEmailStrategy existingEmailStrategy) {
+ public UserDto authenticate(UserIdentity userIdentity, IdentityProvider provider, AuthenticationEvent.Source source, ExistingEmailStrategy existingEmailStrategy) {
try (DbSession dbSession = dbClient.openSession(false)) {
- String userLogin = user.getLogin();
- UserDto userDto = dbClient.userDao().selectByLogin(dbSession, userLogin);
- if (userDto != null && userDto.isActive()) {
- registerExistingUser(dbSession, userDto, user, provider, source, existingEmailStrategy);
- return userDto;
+ UserDto userDto = getUser(dbSession, userIdentity, provider);
+ if (userDto == null) {
+ return registerNewUser(dbSession, null, userIdentity, provider, source, existingEmailStrategy);
}
- return registerNewUser(dbSession, user, provider, source, existingEmailStrategy);
+ if (!userDto.isActive()) {
+ return registerNewUser(dbSession, userDto, userIdentity, provider, source, existingEmailStrategy);
+ }
+ return registerExistingUser(dbSession, userDto, userIdentity, provider, source, existingEmailStrategy);
}
}
- private void registerExistingUser(DbSession dbSession, UserDto userDto, UserIdentity identity, IdentityProvider provider, AuthenticationEvent.Source source,
+ @CheckForNull
+ private UserDto getUser(DbSession dbSession, UserIdentity userIdentity, IdentityProvider provider) {
+ String externalId = userIdentity.getProviderId();
+ UserDto user = dbClient.userDao().selectByExternalIdAndIdentityProvider(dbSession, externalId == null ? userIdentity.getProviderLogin() : externalId, provider.getKey());
+ // We need to search by login because :
+ // 1. external id may have not been set before,
+ // 2. user may have been provisioned,
+ // 3. user may have been disabled.
+ return user != null ? user : dbClient.userDao().selectByLogin(dbSession, userIdentity.getLogin());
+ }
+
+ private UserDto registerExistingUser(DbSession dbSession, UserDto userDto, UserIdentity identity, IdentityProvider provider, AuthenticationEvent.Source source,
ExistingEmailStrategy existingEmailStrategy) {
- UpdateUser update = UpdateUser.create(userDto.getLogin())
+ UpdateUser update = new UpdateUser()
+ .setLogin(identity.getLogin())
.setEmail(identity.getEmail())
.setName(identity.getName())
- .setExternalIdentity(new ExternalIdentity(provider.getKey(), identity.getProviderLogin()));
+ .setExternalIdentity(new ExternalIdentity(provider.getKey(), identity.getProviderLogin(), identity.getProviderId()));
Optional<UserDto> otherUserToIndex = validateEmail(dbSession, identity, provider, source, existingEmailStrategy);
- userUpdater.updateAndCommit(dbSession, update, u -> syncGroups(dbSession, identity, u), toArray(otherUserToIndex));
+ userUpdater.updateAndCommit(dbSession, userDto, update, u -> syncGroups(dbSession, identity, u), toArray(otherUserToIndex));
+ return userDto;
}
- private UserDto registerNewUser(DbSession dbSession, UserIdentity identity, IdentityProvider provider, AuthenticationEvent.Source source,
+ private UserDto registerNewUser(DbSession dbSession, @Nullable UserDto disabledUser, UserIdentity identity, IdentityProvider provider, AuthenticationEvent.Source source,
ExistingEmailStrategy existingEmailStrategy) {
- if (!provider.allowsUsersToSignUp()) {
- throw AuthenticationException.newBuilder()
- .setSource(source)
- .setLogin(identity.getLogin())
- .setMessage(format("User signup disabled for provider '%s'", provider.getKey()))
- .setPublicMessage(format("'%s' users are not allowed to sign up", provider.getKey()))
- .build();
- }
Optional<UserDto> otherUserToIndex = validateEmail(dbSession, identity, provider, source, existingEmailStrategy);
- return userUpdater.createAndCommit(dbSession, NewUser.builder()
- .setLogin(identity.getLogin())
- .setEmail(identity.getEmail())
- .setName(identity.getName())
- .setExternalIdentity(new ExternalIdentity(provider.getKey(), identity.getProviderLogin()))
- .build(),
- u -> syncGroups(dbSession, identity, u),
- toArray(otherUserToIndex));
+ NewUser newUser = createNewUser(identity, provider, source);
+ if (disabledUser == null) {
+ return userUpdater.createAndCommit(dbSession, newUser, u -> syncGroups(dbSession, identity, u), toArray(otherUserToIndex));
+ }
+ return userUpdater.reactivateAndCommit(dbSession, disabledUser, newUser, u -> syncGroups(dbSession, identity, u), toArray(otherUserToIndex));
}
private Optional<UserDto> validateEmail(DbSession dbSession, UserIdentity identity, IdentityProvider provider, AuthenticationEvent.Source source,
return Optional.empty();
}
UserDto existingUser = dbClient.userDao().selectByEmail(dbSession, email);
- if (existingUser == null || existingUser.getLogin().equals(identity.getLogin())) {
+ if (existingUser == null
+ || Objects.equals(existingUser.getLogin(), identity.getLogin())
+ || (Objects.equals(existingUser.getExternalId(), identity.getProviderId()) && Objects.equals(existingUser.getExternalIdentityProvider(), provider.getKey()))) {
return Optional.empty();
}
switch (existingEmailStrategy) {
return organizationFlags.isEnabled(dbSession) ? Optional.empty() : Optional.of(defaultGroupFinder.findDefaultGroup(dbSession, defaultOrganizationProvider.get().getUuid()));
}
+ private static NewUser createNewUser(UserIdentity identity, IdentityProvider provider, AuthenticationEvent.Source source) {
+ if (!provider.allowsUsersToSignUp()) {
+ throw AuthenticationException.newBuilder()
+ .setSource(source)
+ .setLogin(identity.getLogin())
+ .setMessage(format("User signup disabled for provider '%s'", provider.getKey()))
+ .setPublicMessage(format("'%s' users are not allowed to sign up", provider.getKey()))
+ .build();
+ }
+ return NewUser.builder()
+ .setLogin(identity.getLogin())
+ .setEmail(identity.getEmail())
+ .setName(identity.getName())
+ .setExternalIdentity(new ExternalIdentity(provider.getKey(), identity.getProviderLogin(), identity.getProviderId()))
+ .build();
+ }
+
private static UserDto[] toArray(Optional<UserDto> userDto) {
- return userDto.map(u -> new UserDto[]{u}).orElse(new UserDto[]{});
+ return userDto.map(u -> new UserDto[] {u}).orElse(new UserDto[] {});
}
}
private void sendNewIssuesNotification(NewIssuesStatistics statistics, Component project, long analysisDate) {
NewIssuesStatistics.Stats globalStatistics = statistics.globalStatistics();
NewIssuesNotification notification = newIssuesNotificationFactory
- .newNewIssuesNotication()
+ .newNewIssuesNotification()
.setProject(project.getPublicKey(), project.getName(), getBranchName(), getPullRequest())
.setProjectVersion(project.getReportAttributes().getVersion())
.setAnalysisDate(new Date(analysisDate))
import org.sonar.api.utils.Durations;
import org.sonar.db.DbClient;
-import org.sonar.server.user.index.UserIndex;
import static org.sonar.server.issue.notification.AbstractNewIssuesEmailTemplate.FIELD_ASSIGNEE;
public static final String MY_NEW_ISSUES_NOTIF_TYPE = "my-new-issues";
- MyNewIssuesNotification(UserIndex userIndex, DbClient dbClient, Durations durations) {
- super(MY_NEW_ISSUES_NOTIF_TYPE, userIndex, dbClient, durations);
+ MyNewIssuesNotification(DbClient dbClient, Durations durations) {
+ super(MY_NEW_ISSUES_NOTIF_TYPE, dbClient, durations);
}
public MyNewIssuesNotification setAssignee(String assignee) {
import org.sonar.db.RowNotFoundException;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.rule.RuleDefinitionDto;
+import org.sonar.db.user.UserDto;
import org.sonar.server.issue.notification.NewIssuesStatistics.Metric;
-import org.sonar.server.user.index.UserDoc;
-import org.sonar.server.user.index.UserIndex;
import static org.sonar.server.issue.notification.AbstractNewIssuesEmailTemplate.FIELD_BRANCH;
import static org.sonar.server.issue.notification.AbstractNewIssuesEmailTemplate.FIELD_PROJECT_VERSION;
private static final String LABEL = ".label";
private static final String DOT = ".";
- private final transient UserIndex userIndex;
private final transient DbClient dbClient;
private final transient Durations durations;
- NewIssuesNotification(UserIndex userIndex, DbClient dbClient, Durations durations) {
- this(TYPE, userIndex, dbClient, durations);
+ NewIssuesNotification(DbClient dbClient, Durations durations) {
+ this(TYPE, dbClient, durations);
}
- protected NewIssuesNotification(String type, UserIndex userIndex, DbClient dbClient, Durations durations) {
+ protected NewIssuesNotification(String type, DbClient dbClient, Durations durations) {
super(type);
- this.userIndex = userIndex;
this.dbClient = dbClient;
this.durations = durations;
}
try (DbSession dbSession = dbClient.openSession(false)) {
setRuleTypeStatistics(stats);
- setAssigneesStatistics(stats);
+ setAssigneesStatistics(dbSession, stats);
setTagsStatistics(stats);
setComponentsStatistics(dbSession, stats);
setRuleStatistics(dbSession, stats);
}
}
- private void setAssigneesStatistics(NewIssuesStatistics.Stats stats) {
+ private void setAssigneesStatistics(DbSession dbSession, NewIssuesStatistics.Stats stats) {
Metric metric = Metric.ASSIGNEE;
int i = 1;
for (Map.Entry<String, MetricStatsInt> assigneeStats : fiveBiggest(stats.getDistributedMetricStats(metric), MetricStatsInt::getOnLeak)) {
String login = assigneeStats.getKey();
- UserDoc user = userIndex.getNullableByLogin(login);
- String name = user == null ? login : user.name();
+ UserDto user = dbClient.userDao().selectByLogin(dbSession, login);
+ String name = user == null ? login : user.getName();
setFieldValue(metric + DOT + i + LABEL, name);
setFieldValue(metric + DOT + i + COUNT, String.valueOf(assigneeStats.getValue().getOnLeak()));
i++;
import org.sonar.api.server.ServerSide;
import org.sonar.api.utils.Durations;
import org.sonar.db.DbClient;
-import org.sonar.server.user.index.UserIndex;
@ServerSide
@ComputeEngineSide
public class NewIssuesNotificationFactory {
- private final UserIndex userIndex;
private final DbClient dbClient;
private final Durations durations;
- public NewIssuesNotificationFactory(UserIndex userIndex, DbClient dbClient, Durations durations) {
- this.userIndex = userIndex;
+ public NewIssuesNotificationFactory(DbClient dbClient, Durations durations) {
this.dbClient = dbClient;
this.durations = durations;
}
public MyNewIssuesNotification newMyNewIssuesNotification() {
- return new MyNewIssuesNotification(userIndex, dbClient, durations);
+ return new MyNewIssuesNotification(dbClient, durations);
}
- public NewIssuesNotification newNewIssuesNotication() {
- return new NewIssuesNotification(userIndex, dbClient, durations);
+ public NewIssuesNotification newNewIssuesNotification() {
+ return new NewIssuesNotification(dbClient, durations);
}
}
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.qualitygate.QualityGateDto;
import org.sonar.db.qualityprofile.QProfileDto;
+import org.sonar.db.user.UserDto;
import org.sonar.server.component.ComponentCleanerService;
import org.sonar.server.organization.BillingValidations;
import org.sonar.server.organization.BillingValidationsProxy;
}
private void deleteOrganization(DbSession dbSession, OrganizationDto organization) {
- Collection<String> logins = dbClient.organizationMemberDao().selectLoginsByOrganizationUuid(dbSession, organization.getUuid());
+ Collection<String> uuids = dbClient.organizationMemberDao().selectUserUuidsByOrganizationUuid(dbSession, organization.getUuid());
dbClient.organizationMemberDao().deleteByOrganizationUuid(dbSession, organization.getUuid());
dbClient.organizationDao().deleteByUuid(dbSession, organization.getUuid());
dbClient.userDao().cleanHomepage(dbSession, organization);
dbClient.webhookDao().selectByOrganizationUuid(dbSession, organization.getUuid())
.forEach(wh -> dbClient.webhookDeliveryDao().deleteByWebhook(dbSession, wh));
dbClient.webhookDao().deleteByOrganization(dbSession, organization);
- userIndexer.commitAndIndexByLogins(dbSession, logins);
+ List<UserDto> users = dbClient.userDao().selectByUuids(dbSession, uuids);
+ userIndexer.commitAndIndex(dbSession, users);
}
private static void preventDeletionOfDefaultOrganization(String key, DefaultOrganization defaultOrganization) {
*/
package org.sonar.server.user;
+import javax.annotation.Nullable;
+
import static java.util.Objects.requireNonNull;
public class ExternalIdentity {
public static final String SQ_AUTHORITY = "sonarqube";
private String provider;
+ private String login;
private String id;
- public ExternalIdentity(String provider, String id) {
+ public ExternalIdentity(String provider, String login, @Nullable String id) {
this.provider = requireNonNull(provider, "Identity provider cannot be null");
- this.id = requireNonNull(id, "Identity id cannot be null");
+ this.login = requireNonNull(login, "Identity login cannot be null");
+ this.id = id == null ? login : id;
}
public String getProvider() {
return provider;
}
+ public String getLogin() {
+ return login;
+ }
+
public String getId() {
return id;
}
*/
package org.sonar.server.user;
-import static com.google.common.base.Preconditions.checkNotNull;
-
import java.util.List;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
private String password;
private ExternalIdentity externalIdentity;
+ private boolean loginChanged;
private boolean nameChanged;
private boolean emailChanged;
private boolean scmAccountsChanged;
private boolean passwordChanged;
private boolean externalIdentityChanged;
- private UpdateUser(String login) {
- // No direct call to this constructor
- this.login = login;
- }
-
+ @CheckForNull
public String login() {
return login;
}
+ public UpdateUser setLogin(@Nullable String login) {
+ this.login = login;
+ loginChanged = true;
+ return this;
+ }
+
@CheckForNull
public String name() {
return name;
return this;
}
+ public boolean isLoginChanged() {
+ return loginChanged;
+ }
+
public boolean isNameChanged() {
return nameChanged;
}
return externalIdentityChanged;
}
- public static UpdateUser create(String login) {
- checkNotNull(login);
- return new UpdateUser(login);
- }
}
import static java.lang.String.format;
import static java.util.Arrays.stream;
import static java.util.stream.Stream.concat;
+import static org.sonar.api.CoreProperties.DEFAULT_ISSUE_ASSIGNEE;
import static org.sonar.core.config.CorePropertyDefinitions.ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS;
import static org.sonar.core.util.stream.MoreCollectors.toList;
-import static org.sonar.server.ws.WsUtils.checkFound;
import static org.sonar.server.ws.WsUtils.checkRequest;
@ServerSide
}
public UserDto createAndCommit(DbSession dbSession, NewUser newUser, Consumer<UserDto> beforeCommit, UserDto... otherUsersToIndex) {
- String login = newUser.login();
- UserDto userDto = dbClient.userDao().selectByLogin(dbSession, newUser.login());
- if (userDto == null) {
- userDto = saveUser(dbSession, createDto(dbSession, newUser));
- } else {
- reactivateUser(dbSession, userDto, login, newUser);
- }
- beforeCommit.accept(userDto);
- userIndexer.commitAndIndex(dbSession, concat(Stream.of(userDto), stream(otherUsersToIndex)).collect(toList()));
+ UserDto userDto = saveUser(dbSession, createDto(dbSession, newUser));
+ return commitUser(dbSession, userDto, beforeCommit, otherUsersToIndex);
+ }
- notifyNewUser(userDto.getLogin(), userDto.getName(), newUser.email());
- return userDto;
+ public UserDto reactivateAndCommit(DbSession dbSession, UserDto disabledUser, NewUser newUser, Consumer<UserDto> beforeCommit, UserDto... otherUsersToIndex) {
+ checkArgument(!disabledUser.isActive(), "An active user with login '%s' already exists", disabledUser.getLogin());
+ reactivateUser(dbSession, disabledUser, newUser);
+ return commitUser(dbSession, disabledUser, beforeCommit, otherUsersToIndex);
}
- private void reactivateUser(DbSession dbSession, UserDto existingUser, String login, NewUser newUser) {
- checkArgument(!existingUser.isActive(), "An active user with login '%s' already exists", login);
- UpdateUser updateUser = UpdateUser.create(login)
+ private void reactivateUser(DbSession dbSession, UserDto disabledUser, NewUser newUser) {
+ UpdateUser updateUser = new UpdateUser()
+ .setLogin(newUser.login())
.setName(newUser.name())
.setEmail(newUser.email())
.setScmAccounts(newUser.scmAccounts())
if (newUser.password() != null) {
updateUser.setPassword(newUser.password());
}
- setOnboarded(existingUser);
- updateDto(dbSession, updateUser, existingUser);
- updateUser(dbSession, existingUser);
- addUserToDefaultOrganizationAndDefaultGroup(dbSession, existingUser);
+ setOnboarded(disabledUser);
+ updateDto(dbSession, updateUser, disabledUser);
+ updateUser(dbSession, disabledUser);
+ addUserToDefaultOrganizationAndDefaultGroup(dbSession, disabledUser);
}
- public void updateAndCommit(DbSession dbSession, UpdateUser updateUser, Consumer<UserDto> beforeCommit, UserDto... otherUsersToIndex) {
- UserDto dto = dbClient.userDao().selectByLogin(dbSession, updateUser.login());
- checkFound(dto, "User with login '%s' has not been found", updateUser.login());
+ public void updateAndCommit(DbSession dbSession, UserDto dto, UpdateUser updateUser, Consumer<UserDto> beforeCommit, UserDto... otherUsersToIndex) {
boolean isUserUpdated = updateDto(dbSession, updateUser, dto);
if (isUserUpdated) {
// at least one change. Database must be updated and Elasticsearch re-indexed
updateUser(dbSession, dto);
- beforeCommit.accept(dto);
- userIndexer.commitAndIndex(dbSession, concat(Stream.of(dto), stream(otherUsersToIndex)).collect(toList()));
- notifyNewUser(dto.getLogin(), dto.getName(), dto.getEmail());
+ commitUser(dbSession, dto, beforeCommit, otherUsersToIndex);
} else {
// no changes but still execute the consumer
beforeCommit.accept(dto);
}
}
+ private UserDto commitUser(DbSession dbSession, UserDto userDto, Consumer<UserDto> beforeCommit, UserDto... otherUsersToIndex) {
+ beforeCommit.accept(userDto);
+ userIndexer.commitAndIndex(dbSession, concat(Stream.of(userDto), stream(otherUsersToIndex)).collect(toList()));
+ notifyNewUser(userDto.getLogin(), userDto.getName(), userDto.getEmail());
+ return userDto;
+ }
+
private UserDto createDto(DbSession dbSession, NewUser newUser) {
UserDto userDto = new UserDto();
List<String> messages = new ArrayList<>();
String login = newUser.login();
if (validateLoginFormat(login, messages)) {
+ checkLoginUniqueness(dbSession, login);
userDto.setLogin(login);
}
userDto.setScmAccounts(scmAccounts);
}
- setExternalIdentity(userDto, newUser.externalIdentity());
+ setExternalIdentity(dbSession, userDto, newUser.externalIdentity());
setOnboarded(userDto);
checkRequest(messages.isEmpty(), messages);
private boolean updateDto(DbSession dbSession, UpdateUser update, UserDto dto) {
List<String> messages = newArrayList();
- boolean changed = updateName(update, dto, messages);
+ boolean changed = updateLogin(dbSession, update, dto, messages);
+ changed |= updateName(update, dto, messages);
changed |= updateEmail(update, dto, messages);
- changed |= updateExternalIdentity(update, dto);
+ changed |= updateExternalIdentity(dbSession, update, dto);
changed |= updatePassword(update, dto, messages);
changed |= updateScmAccounts(dbSession, update, dto, messages);
checkRequest(messages.isEmpty(), messages);
return changed;
}
+ 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)) {
+ checkLoginUniqueness(dbSession, newLogin);
+ dbClient.propertiesDao().selectByKeyAndMatchingValue(dbSession, DEFAULT_ISSUE_ASSIGNEE, userDto.getLogin())
+ .forEach(p -> dbClient.propertiesDao().saveProperty(p.setValue(newLogin)));
+ userDto.setLogin(newLogin);
+ return true;
+ }
+ return false;
+ }
+
private static boolean updateName(UpdateUser updateUser, UserDto userDto, List<String> messages) {
String name = updateUser.name();
if (updateUser.isNameChanged() && validateNameFormat(name, messages) && !Objects.equals(userDto.getName(), name)) {
return false;
}
- private static boolean updateExternalIdentity(UpdateUser updateUser, UserDto userDto) {
+ private boolean updateExternalIdentity(DbSession dbSession, UpdateUser updateUser, UserDto userDto) {
ExternalIdentity externalIdentity = updateUser.externalIdentity();
if (updateUser.isExternalIdentityChanged() && !isSameExternalIdentity(userDto, externalIdentity)) {
- setExternalIdentity(userDto, externalIdentity);
+ setExternalIdentity(dbSession, userDto, externalIdentity);
return true;
}
return false;
private static boolean isSameExternalIdentity(UserDto dto, @Nullable ExternalIdentity externalIdentity) {
return externalIdentity != null
- && Objects.equals(dto.getExternalIdentity(), externalIdentity.getId())
+ && !dto.isLocal()
+ && Objects.equals(dto.getExternalId(), externalIdentity.getId())
+ && Objects.equals(dto.getExternalLogin(), externalIdentity.getLogin())
&& Objects.equals(dto.getExternalIdentityProvider(), externalIdentity.getProvider());
}
- private static void setExternalIdentity(UserDto dto, @Nullable ExternalIdentity externalIdentity) {
+ private void setExternalIdentity(DbSession dbSession, UserDto dto, @Nullable ExternalIdentity externalIdentity) {
if (externalIdentity == null) {
- dto.setExternalIdentity(dto.getLogin());
+ dto.setExternalLogin(dto.getLogin());
dto.setExternalIdentityProvider(SQ_AUTHORITY);
+ dto.setExternalId(dto.getLogin());
dto.setLocal(true);
} else {
- dto.setExternalIdentity(externalIdentity.getId());
+ 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 void setOnboarded(UserDto userDto) {
return Collections.emptyList();
}
+ private void checkLoginUniqueness(DbSession dbSession, String login) {
+ UserDto existingUser = dbClient.userDao().selectByLogin(dbSession, login);
+ checkArgument(existingUser == null, "A user with login '%s' already exists", login);
+ }
+
private UserDto saveUser(DbSession dbSession, UserDto userDto) {
userDto.setActive(true);
UserDto res = dbClient.userDao().insert(dbSession, userDto);
@Override
public String getId() {
- return login();
+ return uuid();
}
@Override
return null;
}
+ public String uuid() {
+ return getField(UserIndexDefinition.FIELD_UUID);
+ }
+
@Override
public String login() {
return getField(UserIndexDefinition.FIELD_LOGIN);
return getField(FIELD_ORGANIZATION_UUIDS);
}
+ public UserDoc setUuid(@Nullable String s) {
+ setField(UserIndexDefinition.FIELD_UUID, s);
+ return this;
+ }
+
public UserDoc setLogin(@Nullable String s) {
setField(UserIndexDefinition.FIELD_LOGIN, s);
return this;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
-import javax.annotation.CheckForNull;
import org.apache.commons.lang.StringUtils;
-import org.elasticsearch.action.get.GetRequestBuilder;
-import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.Operator;
this.system2 = system2;
}
- @CheckForNull
- public UserDoc getNullableByLogin(String login) {
- GetRequestBuilder request = esClient.prepareGet(UserIndexDefinition.INDEX_TYPE_USER, login)
- .setFetchSource(true)
- .setRouting(login);
- GetResponse response = request.get();
- if (response.isExists()) {
- return new UserDoc(response.getSource());
- }
- return null;
- }
-
/**
* Returns the active users (at most 3) who are associated to the given SCM account. This method can be used
* to detect user conflicts.
public class UserIndexDefinition implements IndexDefinition {
public static final IndexType INDEX_TYPE_USER = new IndexType("users", "user");
+ public static final String FIELD_UUID = "uuid";
public static final String FIELD_LOGIN = "login";
public static final String FIELD_NAME = "name";
public static final String FIELD_EMAIL = "email";
// type "user"
NewIndex.NewIndexType mapping = index.createType(INDEX_TYPE_USER.getType());
+ mapping.keywordFieldBuilder(FIELD_UUID).disableNorms().build();
mapping.keywordFieldBuilder(FIELD_LOGIN).addSubFields(USER_SEARCH_GRAMS_ANALYZER).build();
mapping.keywordFieldBuilder(FIELD_NAME).addSubFields(USER_SEARCH_GRAMS_ANALYZER).build();
mapping.keywordFieldBuilder(FIELD_EMAIL).addSubFields(USER_SEARCH_GRAMS_ANALYZER, SORTABLE_ANALYZER).build();
package org.sonar.server.user.index;
import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Maps;
import static java.util.Collections.singletonList;
import static org.sonar.core.util.stream.MoreCollectors.toHashSet;
+import static org.sonar.core.util.stream.MoreCollectors.toList;
import static org.sonar.server.user.index.UserIndexDefinition.INDEX_TYPE_USER;
public class UserIndexer implements ResilientIndexer {
@Override
public void indexOnStartup(Set<IndexType> uninitializedIndexTypes) {
try (DbSession dbSession = dbClient.openSession(false)) {
- ListMultimap<String, String> organizationUuidsByLogin = ArrayListMultimap.create();
- dbClient.organizationMemberDao().selectAllForUserIndexing(dbSession, organizationUuidsByLogin::put);
+ ListMultimap<String, String> organizationUuidsByUserUuid = ArrayListMultimap.create();
+ dbClient.organizationMemberDao().selectAllForUserIndexing(dbSession, organizationUuidsByUserUuid::put);
BulkIndexer bulkIndexer = newBulkIndexer(Size.LARGE, IndexingListener.FAIL_ON_ERROR);
bulkIndexer.start();
dbClient.userDao().scrollAll(dbSession,
// only index requests, no deletion requests.
// Deactivated users are not deleted but updated.
- u -> bulkIndexer.add(newIndexRequest(u, organizationUuidsByLogin)));
+ u -> bulkIndexer.add(newIndexRequest(u, organizationUuidsByUserUuid)));
bulkIndexer.stop();
}
}
public void commitAndIndex(DbSession dbSession, UserDto user) {
- commitAndIndexByLogins(dbSession, singletonList(user.getLogin()));
+ commitAndIndex(dbSession, singletonList(user));
}
public void commitAndIndex(DbSession dbSession, Collection<UserDto> users) {
- commitAndIndexByLogins(dbSession, Collections2.transform(users, UserDto::getLogin));
- }
-
- public void commitAndIndexByLogins(DbSession dbSession, Collection<String> logins) {
- List<EsQueueDto> items = logins.stream()
- .map(l -> EsQueueDto.create(INDEX_TYPE_USER.format(), l))
+ List<String> uuids = users.stream().map(UserDto::getUuid).collect(toList());
+ List<EsQueueDto> items = uuids.stream()
+ .map(uuid -> EsQueueDto.create(INDEX_TYPE_USER.format(), uuid))
.collect(MoreCollectors.toArrayList());
dbClient.esQueueDao().insert(dbSession, items);
dbSession.commit();
- postCommit(dbSession, logins, items);
+ postCommit(dbSession, users.stream().map(UserDto::getLogin).collect(toList()), items);
}
/**
if (items.isEmpty()) {
return new IndexingResult();
}
- Set<String> logins = items
+ Set<String> uuids = items
.stream()
.map(EsQueueDto::getDocId)
.collect(toHashSet(items.size()));
- ListMultimap<String, String> organizationUuidsByLogin = ArrayListMultimap.create();
- dbClient.organizationMemberDao().selectForUserIndexing(dbSession, logins, organizationUuidsByLogin::put);
+ ListMultimap<String, String> organizationUuidsByUserUuid = ArrayListMultimap.create();
+ dbClient.organizationMemberDao().selectForUserIndexing(dbSession, uuids, organizationUuidsByUserUuid::put);
BulkIndexer bulkIndexer = newBulkIndexer(Size.REGULAR, new OneToOneResilientIndexingListener(dbClient, dbSession, items));
bulkIndexer.start();
- dbClient.userDao().scrollByLogins(dbSession, logins,
+ dbClient.userDao().scrollByUuids(dbSession, uuids,
// only index requests, no deletion requests.
// Deactivated users are not deleted but updated.
u -> {
- logins.remove(u.getLogin());
- bulkIndexer.add(newIndexRequest(u, organizationUuidsByLogin));
+ uuids.remove(u.getUuid());
+ bulkIndexer.add(newIndexRequest(u, organizationUuidsByUserUuid));
});
- // the remaining logins reference rows that don't exist in db. They must
+ // the remaining uuids reference rows that don't exist in db. They must
// be deleted from index.
- logins.forEach(l -> bulkIndexer.addDeletion(INDEX_TYPE_USER, l));
+ uuids.forEach(uuid -> bulkIndexer.addDeletion(INDEX_TYPE_USER, uuid));
return bulkIndexer.stop();
}
return new BulkIndexer(esClient, INDEX_TYPE_USER, bulkSize, listener);
}
- private static IndexRequest newIndexRequest(UserDto user, ListMultimap<String, String> organizationUuidsByLogins) {
+ private static IndexRequest newIndexRequest(UserDto user, ListMultimap<String, String> organizationUuidsByUserUuid) {
UserDoc doc = new UserDoc(Maps.newHashMapWithExpectedSize(8));
// all the keys must be present, even if value is null
+ doc.setUuid(user.getUuid());
doc.setLogin(user.getLogin());
doc.setName(user.getName());
doc.setEmail(user.getEmail());
doc.setActive(user.isActive());
doc.setScmAccounts(UserDto.decodeScmAccounts(user.getScmAccounts()));
- doc.setOrganizationUuids(organizationUuidsByLogins.get(user.getLogin()));
+ doc.setOrganizationUuids(organizationUuidsByUserUuid.get(user.getUuid()));
return new IndexRequest(INDEX_TYPE_USER.getIndex(), INDEX_TYPE_USER.getType())
.id(doc.getId())
import org.sonar.server.authentication.LocalAuthentication;
import org.sonar.server.authentication.event.AuthenticationEvent;
import org.sonar.server.authentication.event.AuthenticationException;
+import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.user.UpdateUser;
import org.sonar.server.user.UserSession;
import org.sonar.server.user.UserUpdater;
+import static java.lang.String.format;
+
public class ChangePasswordAction implements UsersWsAction {
private static final String PARAM_LOGIN = "login";
try (DbSession dbSession = dbClient.openSession(false)) {
String login = request.mandatoryParam(PARAM_LOGIN);
+ UserDto user = getUser(dbSession, login);
if (login.equals(userSession.getLogin())) {
String previousPassword = request.mandatoryParam(PARAM_PREVIOUS_PASSWORD);
- checkCurrentPassword(dbSession, login, previousPassword);
+ checkCurrentPassword(dbSession, user, previousPassword);
} else {
userSession.checkIsSystemAdministrator();
}
String password = request.mandatoryParam(PARAM_PASSWORD);
- UpdateUser updateUser = UpdateUser.create(login).setPassword(password);
-
- userUpdater.updateAndCommit(dbSession, updateUser, u -> {});
+ UpdateUser updateUser = new UpdateUser().setPassword(password);
+ userUpdater.updateAndCommit(dbSession, user, updateUser, u -> {
+ });
}
response.noContent();
}
- private void checkCurrentPassword(DbSession dbSession, String login, String password) {
- UserDto user = dbClient.userDao().selectOrFailByLogin(dbSession, login);
+ private UserDto getUser(DbSession dbSession, String login) {
+ UserDto user = dbClient.userDao().selectByLogin(dbSession, login);
+ if (user == null || !user.isActive()) {
+ throw new NotFoundException(format("User with login '%s' has not been found", login));
+ }
+ return user;
+ }
+
+ private void checkCurrentPassword(DbSession dbSession, UserDto user, String password) {
try {
localAuthentication.authenticate(dbSession, user, password, AuthenticationEvent.Method.BASIC);
} catch (AuthenticationException ex) {
private CreateWsResponse doHandle(CreateRequest request) {
try (DbSession dbSession = dbClient.openSession(false)) {
+ String login = request.getLogin();
NewUser.Builder newUser = NewUser.builder()
- .setLogin(request.getLogin())
+ .setLogin(login)
.setName(request.getName())
.setEmail(request.getEmail())
.setScmAccounts(request.getScmAccounts())
.setPassword(request.getPassword());
if (!request.isLocal()) {
- newUser.setExternalIdentity(new ExternalIdentity(SQ_AUTHORITY, request.getLogin()));
+ newUser.setExternalIdentity(new ExternalIdentity(SQ_AUTHORITY, login, login));
}
- UserDto createdUser = userUpdater.createAndCommit(dbSession, newUser.build(), u -> {});
- return buildResponse(createdUser);
+ UserDto existingUser = dbClient.userDao().selectByLogin(dbSession, login);
+ if (existingUser == null) {
+ return buildResponse(userUpdater.createAndCommit(dbSession, newUser.build(), u -> {
+ }));
+ }
+ checkArgument(!existingUser.isActive(), "An active user with login '%s' already exists", login);
+ return buildResponse(userUpdater.reactivateAndCommit(dbSession, existingUser, newUser.build(), u -> {
+ }));
}
}
.setShowOnboardingTutorial(!user.isOnboarded());
setNullable(emptyToNull(user.getEmail()), builder::setEmail);
setNullable(emptyToNull(user.getEmail()), u -> builder.setAvatar(avatarResolver.create(user)));
- setNullable(user.getExternalIdentity(), builder::setExternalIdentity);
+ setNullable(user.getExternalLogin(), builder::setExternalIdentity);
setNullable(user.getExternalIdentityProvider(), builder::setExternalProvider);
return builder.build();
}
setIfNeeded(FIELD_AVATAR, fields, emptyToNull(user.getEmail()), u -> userBuilder.setAvatar(avatarResolver.create(user)));
setIfNeeded(FIELD_ACTIVE, fields, user.isActive(), userBuilder::setActive);
setIfNeeded(FIELD_LOCAL, fields, user.isLocal(), userBuilder::setLocal);
- setIfNeeded(FIELD_EXTERNAL_IDENTITY, fields, user.getExternalIdentity(), userBuilder::setExternalIdentity);
+ setIfNeeded(FIELD_EXTERNAL_IDENTITY, fields, user.getExternalLogin(), userBuilder::setExternalIdentity);
setIfNeeded(FIELD_EXTERNAL_PROVIDER, fields, user.getExternalIdentityProvider(), userBuilder::setExternalProvider);
setIfNeeded(FIELD_TOKENS_COUNT, fields, tokensCount, userBuilder::setTokensCount);
setIfNeeded(isNeeded(FIELD_SCM_ACCOUNTS, fields) && !user.getScmAccountsAsList().isEmpty(), user.getScmAccountsAsList(),
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.user.UserDto;
+import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.user.UpdateUser;
import org.sonar.server.user.UserSession;
import org.sonar.server.user.UserUpdater;
import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Strings.emptyToNull;
import static com.google.common.base.Strings.isNullOrEmpty;
+import static java.lang.String.format;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.sonar.server.user.UserUpdater.EMAIL_MAX_LENGTH;
import static org.sonar.server.user.UserUpdater.LOGIN_MAX_LENGTH;
import static org.sonar.server.user.UserUpdater.NAME_MAX_LENGTH;
import static org.sonar.server.user.ws.EmailValidator.isValidIfPresent;
-import static org.sonar.server.ws.WsUtils.checkFound;
import static org.sonarqube.ws.client.user.UsersWsParameters.ACTION_UPDATE;
import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_EMAIL;
import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_LOGIN;
UpdateRequest updateRequest = toWsRequest(request);
checkArgument(isValidIfPresent(updateRequest.getEmail()), "Email '%s' is not valid", updateRequest.getEmail());
try (DbSession dbSession = dbClient.openSession(false)) {
- doHandle(dbSession, toWsRequest(request));
- writeUser(dbSession, response, updateRequest.getLogin());
+ UserDto user = getUser(dbSession, updateRequest.getLogin());
+ doHandle(dbSession, updateRequest);
+ writeUser(dbSession, response, user.getUuid());
}
}
private void doHandle(DbSession dbSession, UpdateRequest request) {
String login = request.getLogin();
- UpdateUser updateUser = UpdateUser.create(login);
+ UserDto user = getUser(dbSession, login);
+ UpdateUser updateUser = new UpdateUser();
if (request.getName() != null) {
updateUser.setName(request.getName());
}
if (!request.getScmAccounts().isEmpty()) {
updateUser.setScmAccounts(request.getScmAccounts());
}
- userUpdater.updateAndCommit(dbSession, updateUser, u -> {
+ userUpdater.updateAndCommit(dbSession, user, updateUser, u -> {
});
}
- private void writeUser(DbSession dbSession, Response response, String login) {
+ private UserDto getUser(DbSession dbSession, String login) {
+ UserDto user = dbClient.userDao().selectByLogin(dbSession, login);
+ if (user == null || !user.isActive()) {
+ throw new NotFoundException(format("User '%s' doesn't exist", login));
+ }
+ return user;
+ }
+
+ private void writeUser(DbSession dbSession, Response response, String uuid) {
try (JsonWriter json = response.newJsonWriter()) {
json.beginObject();
json.name("user");
- Set<String> groups = new HashSet<>();
- UserDto user = checkFound(dbClient.userDao().selectByLogin(dbSession, login), "User '%s' doesn't exist", login);
- groups.addAll(dbClient.groupMembershipDao().selectGroupsByLogins(dbSession, singletonList(login)).get(login));
+ UserDto user = dbClient.userDao().selectByUuid(dbSession, uuid);
+ checkState(user != null, "User with uuid '%s' doesn't exist", uuid);
+ Set<String> groups = new HashSet<>(dbClient.groupMembershipDao().selectGroupsByLogins(dbSession, singletonList(uuid)).get(uuid));
userWriter.write(json, user, groups, UserJsonWriter.FIELDS);
json.endObject().close();
}
writeIfNeeded(json, user.getEmail(), FIELD_EMAIL, fields);
writeIfNeeded(json, user.isActive(), FIELD_ACTIVE, fields);
writeIfNeeded(json, user.isLocal(), FIELD_LOCAL, fields);
- writeIfNeeded(json, user.getExternalIdentity(), FIELD_EXTERNAL_IDENTITY, fields);
+ writeIfNeeded(json, user.getExternalLogin(), FIELD_EXTERNAL_IDENTITY, fields);
writeIfNeeded(json, user.getExternalIdentityProvider(), FIELD_EXTERNAL_PROVIDER, fields);
writeGroupsIfNeeded(json, groups, fields);
writeScmAccountsIfNeeded(json, fields, user);
@Test
public void redirect_when_failing_because_of_EmailAlreadyExistException() throws Exception {
- UserDto existingUser = newUserDto().setEmail("john@email.com").setExternalIdentity("john.bitbucket").setExternalIdentityProvider("bitbucket");
+ UserDto existingUser = newUserDto().setEmail("john@email.com").setExternalLogin("john.bitbucket").setExternalIdentityProvider("bitbucket");
FailWithEmailAlreadyExistException identityProvider = new FailWithEmailAlreadyExistException("failing", existingUser);
when(request.getRequestURI()).thenReturn("/sessions/init/" + identityProvider.getKey());
identityProviderRepository.addIdentityProvider(identityProvider);
import org.mindrot.jbcrypt.BCrypt;
import org.sonar.db.DbTester;
import org.sonar.db.user.UserDto;
-import org.sonar.db.user.UserTesting;
import org.sonar.server.authentication.event.AuthenticationEvent;
import org.sonar.server.authentication.event.AuthenticationException;
String salt = DigestUtils.sha1Hex(saltRandom);
UserDto user = newUserDto()
- .setHashMethod(SHA1.name())
.setCryptedPassword(null)
+ .setHashMethod(SHA1.name())
.setSalt(salt);
expectedException.expect(AuthenticationException.class);
String password = randomAlphanumeric(60);
UserDto user = newUserDto()
- .setSalt(null)
.setHashMethod(SHA1.name())
- .setCryptedPassword(DigestUtils.sha1Hex("--0242b0b4c0a93ddfe09dd886de50bc25ba000b51--" + password + "--"));
+ .setCryptedPassword(DigestUtils.sha1Hex("--0242b0b4c0a93ddfe09dd886de50bc25ba000b51--" + password + "--"))
+ .setSalt(null);
expectedException.expect(AuthenticationException.class);
expectedException.expectMessage("null salt");
@Test
public void redirect_when_failing_because_of_EmailAlreadyExistException() throws Exception {
- UserDto existingUser = newUserDto().setEmail("john@email.com").setExternalIdentity("john.bitbucket").setExternalIdentityProvider("bitbucket");
+ UserDto existingUser = newUserDto().setEmail("john@email.com").setExternalLogin("john.bitbucket").setExternalIdentityProvider("bitbucket");
FailWithEmailAlreadyExistException identityProvider = new FailWithEmailAlreadyExistException(existingUser);
when(request.getRequestURI()).thenReturn("/oauth2/callback/" + identityProvider.getKey());
identityProviderRepository.addIdentityProvider(identityProvider);
.setLogin(DEFAULT_LOGIN)
.setName(DEFAULT_NAME)
.setEmail(DEFAULT_EMAIL)
- .setExternalIdentity(DEFAULT_LOGIN)
+ .setExternalLogin(DEFAULT_LOGIN)
.setExternalIdentityProvider("sonarqube");
private GroupDto group1;
assertThat(userDto.isActive()).isTrue();
assertThat(userDto.getName()).isEqualTo(expectedName);
assertThat(userDto.getEmail()).isEqualTo(expectedEmail);
- assertThat(userDto.getExternalIdentity()).isEqualTo(expectedLogin);
+ assertThat(userDto.getExternalLogin()).isEqualTo(expectedLogin);
assertThat(userDto.getExternalIdentityProvider()).isEqualTo("sonarqube");
verityUserGroups(expectedLogin, expectedGroups);
}
private static String USER_LOGIN = "github-johndoo";
private static UserIdentity USER_IDENTITY = UserIdentity.builder()
+ .setProviderId("ABCD")
.setProviderLogin("johndoo")
.setLogin(USER_LOGIN)
.setName("John")
assertThat(user.isActive()).isTrue();
assertThat(user.getName()).isEqualTo("John");
assertThat(user.getEmail()).isEqualTo("john@email.com");
- assertThat(user.getExternalIdentity()).isEqualTo("johndoo");
+ assertThat(user.getExternalLogin()).isEqualTo("johndoo");
assertThat(user.getExternalIdentityProvider()).isEqualTo("github");
+ assertThat(user.getExternalId()).isEqualTo("ABCD");
assertThat(user.isRoot()).isFalse();
checkGroupMembership(user);
}
assertThat(existingUserReloaded.getEmail()).isNull();
}
+ @Test
+ public void external_id_is_set_to_provider_login_when_null() {
+ organizationFlags.setEnabled(true);
+ UserIdentity newUser = UserIdentity.builder()
+ .setProviderId(null)
+ .setLogin("john")
+ .setProviderLogin("johndoo")
+ .setName("JOhn")
+ .build();
+
+ underTest.authenticate(newUser, IDENTITY_PROVIDER, Source.local(Method.BASIC), ALLOW);
+
+ assertThat(db.users().selectUserByLogin(newUser.getLogin()).get())
+ .extracting(UserDto::getLogin, UserDto::getExternalId, UserDto::getExternalLogin)
+ .contains("john", "johndoo", "johndoo");
+ }
+
@Test
public void throw_EmailAlreadyExistException_when_authenticating_new_user_when_email_already_exists_and_strategy_is_WARN() {
organizationFlags.setEnabled(true);
}
@Test
- public void authenticate_existing_user() {
+ public void authenticate_existing_user_matching_login() {
db.users().insertUser(u -> u
.setLogin(USER_LOGIN)
.setName("Old name")
.setEmail("Old email")
- .setExternalIdentity("old identity")
+ .setExternalId("old id")
+ .setExternalLogin("old identity")
.setExternalIdentityProvider("old provide"));
underTest.authenticate(USER_IDENTITY, IDENTITY_PROVIDER, Source.local(Method.BASIC), FORBID);
- UserDto userDto = db.users().selectUserByLogin(USER_LOGIN).get();
- assertThat(userDto.isActive()).isTrue();
- assertThat(userDto.getName()).isEqualTo("John");
- assertThat(userDto.getEmail()).isEqualTo("john@email.com");
- assertThat(userDto.getExternalIdentity()).isEqualTo("johndoo");
- assertThat(userDto.getExternalIdentityProvider()).isEqualTo("github");
- assertThat(userDto.isRoot()).isFalse();
+ 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 authenticate_existing_user_matching_external_id() {
+ UserDto user = db.users().insertUser(u -> u
+ .setLogin("Old login")
+ .setName("Old name")
+ .setEmail("Old email")
+ .setExternalId(USER_IDENTITY.getProviderId())
+ .setExternalLogin("old identity")
+ .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
+
+ underTest.authenticate(USER_IDENTITY, IDENTITY_PROVIDER, Source.local(Method.BASIC), FORBID);
+
+ 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_and_update_only_login() {
+ UserDto user = db.users().insertUser(u -> u
+ .setLogin("old login")
+ .setName(USER_IDENTITY.getName())
+ .setEmail(USER_IDENTITY.getEmail())
+ .setExternalId(USER_IDENTITY.getProviderId())
+ .setExternalLogin("old identity")
+ .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
+
+ underTest.authenticate(USER_IDENTITY, IDENTITY_PROVIDER, Source.local(Method.BASIC), FORBID);
+
+ 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_matching_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")
+ .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
+
+ underTest.authenticate(UserIdentity.builder()
+ .setProviderId(null)
+ .setProviderLogin("johndoo")
+ .setLogin(USER_LOGIN)
+ .setName("John")
+ .setEmail("john@email.com")
+ .build(),
+ IDENTITY_PROVIDER, Source.local(Method.BASIC), FORBID);
+
+ 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(), "John", "john@email.com", "johndoo", "johndoo", "github", true);
}
@Test
.setActive(false)
.setName("Old name")
.setEmail("Old email")
- .setExternalIdentity("old identity")
+ .setExternalId("old id")
+ .setExternalLogin("old identity")
.setExternalIdentityProvider("old provide"));
underTest.authenticate(USER_IDENTITY, IDENTITY_PROVIDER, Source.local(Method.BASIC_TOKEN), FORBID);
assertThat(userDto.isActive()).isTrue();
assertThat(userDto.getName()).isEqualTo("John");
assertThat(userDto.getEmail()).isEqualTo("john@email.com");
- assertThat(userDto.getExternalIdentity()).isEqualTo("johndoo");
+ assertThat(userDto.getExternalId()).isEqualTo("ABCD");
+ assertThat(userDto.getExternalLogin()).isEqualTo("johndoo");
assertThat(userDto.getExternalIdentityProvider()).isEqualTo("github");
assertThat(userDto.isRoot()).isFalse();
}
import org.sonar.api.utils.System2;
import org.sonar.api.utils.log.LogTester;
import org.sonar.api.utils.log.LoggerLevel;
+import org.sonar.db.DbTester;
import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.user.UserDto;
import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
import org.sonar.server.computation.task.projectanalysis.analysis.Organization;
import org.sonar.server.es.EsTester;
-import org.sonar.server.user.index.UserDoc;
import org.sonar.server.user.index.UserIndex;
-import org.sonar.server.user.index.UserIndexDefinition;
+import org.sonar.server.user.index.UserIndexer;
import static java.util.Arrays.asList;
-import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;
private static final String ORGANIZATION_UUID = "my-organization";
+ @Rule
+ public DbTester db = DbTester.create();
@Rule
public EsTester es = EsTester.create();
-
@Rule
public LogTester logTester = new LogTester();
@Rule
- public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule()
- .setOrganization(Organization.from(new OrganizationDto().setUuid(ORGANIZATION_UUID).setKey("Key").setName("Name").setDefaultQualityGateUuid("QGate")));
+ public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
+
+ private UserIndexer userIndexer = new UserIndexer(db.getDbClient(), es.client());
@Test
public void load_login_for_scm_account() {
- UserDoc user = new UserDoc()
- .setLogin("charlie")
- .setName("Charlie")
- .setEmail("charlie@hebdo.com")
- .setActive(true)
- .setScmAccounts(asList("charlie", "jesuis@charlie.com"))
- .setOrganizationUuids(singletonList(ORGANIZATION_UUID));
- es.putDocuments(UserIndexDefinition.INDEX_TYPE_USER.getIndex(), UserIndexDefinition.INDEX_TYPE_USER.getType(), user);
+ UserDto user = db.users().insertUser(u -> u.setScmAccounts(asList("charlie", "jesuis@charlie.com")));
+ OrganizationDto organization = db.organizations().insert(o -> o.setUuid(ORGANIZATION_UUID));
+ analysisMetadataHolder.setOrganization(Organization.from(organization));
+ db.organizations().addMember(organization, user);
+ userIndexer.indexOnStartup(null);
UserIndex index = new UserIndex(es.client(), System2.INSTANCE);
ScmAccountToUserLoader underTest = new ScmAccountToUserLoader(index, analysisMetadataHolder);
assertThat(underTest.load("missing")).isNull();
- assertThat(underTest.load("jesuis@charlie.com")).isEqualTo("charlie");
+ assertThat(underTest.load("jesuis@charlie.com")).isEqualTo(user.getLogin());
}
@Test
public void warn_if_multiple_users_share_the_same_scm_account() {
- UserDoc user1 = new UserDoc()
- .setLogin("charlie")
- .setName("Charlie")
- .setEmail("charlie@hebdo.com")
- .setActive(true)
- .setScmAccounts(asList("charlie", "jesuis@charlie.com"))
- .setOrganizationUuids(singletonList(ORGANIZATION_UUID));
- es.putDocuments(UserIndexDefinition.INDEX_TYPE_USER.getIndex(), UserIndexDefinition.INDEX_TYPE_USER.getType(), user1);
-
- UserDoc user2 = new UserDoc()
- .setLogin("another.charlie")
- .setName("Another Charlie")
- .setActive(true)
- .setScmAccounts(singletonList("charlie"))
- .setOrganizationUuids(singletonList(ORGANIZATION_UUID));
- es.putDocuments(UserIndexDefinition.INDEX_TYPE_USER.getIndex(), UserIndexDefinition.INDEX_TYPE_USER.getType(), user2);
+ UserDto user1 = db.users().insertUser(u -> u.setLogin("charlie").setScmAccounts(asList("charlie", "jesuis@charlie.com")));
+ UserDto user2 = db.users().insertUser(u -> u.setLogin("another.charlie").setScmAccounts(asList("charlie")));
+ OrganizationDto organization = db.organizations().insert(o -> o.setUuid(ORGANIZATION_UUID));
+ analysisMetadataHolder.setOrganization(Organization.from(organization));
+ db.organizations().addMember(organization, user1, user2);
+ userIndexer.indexOnStartup(null);
UserIndex index = new UserIndex(es.client(), System2.INSTANCE);
ScmAccountToUserLoader underTest = new ScmAccountToUserLoader(index, analysisMetadataHolder);
underTest = new SendIssueNotificationsStep(issueCache, ruleRepository, treeRootHolder, notificationService, analysisMetadataHolder,
newIssuesNotificationFactory);
- when(newIssuesNotificationFactory.newNewIssuesNotication()).thenReturn(newIssuesNotificationMock);
+ when(newIssuesNotificationFactory.newNewIssuesNotification()).thenReturn(newIssuesNotificationMock);
when(newIssuesNotificationFactory.newMyNewIssuesNotification()).thenReturn(myNewIssuesNotificationMock);
}
import java.io.IOException;
import java.nio.charset.StandardCharsets;
-import java.util.Date;
-import java.util.Locale;
import org.apache.commons.io.IOUtils;
-import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
-import org.mockito.stubbing.Answer;
import org.sonar.api.config.EmailSettings;
+import org.sonar.api.config.internal.MapSettings;
import org.sonar.api.notifications.Notification;
-import org.sonar.core.i18n.DefaultI18n;
import org.sonar.plugins.emailnotifications.api.EmailMessage;
-import org.sonar.server.user.index.UserDoc;
-import org.sonar.server.user.index.UserIndex;
+import org.sonar.server.i18n.I18nRule;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.COMPONENT;
import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.EFFORT;
import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.RULE;
public class MyNewIssuesEmailTemplateTest {
- MyNewIssuesEmailTemplate underTest;
- DefaultI18n i18n;
- UserIndex userIndex;
- Date date;
-
- @Before
- public void setUp() {
- EmailSettings settings = mock(EmailSettings.class);
- when(settings.getServerBaseURL()).thenReturn("http://nemo.sonarsource.org");
- i18n = mock(DefaultI18n.class);
- date = new Date();
- userIndex = mock(UserIndex.class);
- // returns the login passed in parameter
- when(userIndex.getNullableByLogin(anyString()))
- .thenAnswer((Answer<UserDoc>) invocationOnMock -> new UserDoc().setName((String) invocationOnMock.getArguments()[0]));
- when(i18n.message(any(Locale.class), eq("issue.type.BUG"), anyString())).thenReturn("Bug");
- when(i18n.message(any(Locale.class), eq("issue.type.CODE_SMELL"), anyString())).thenReturn("Code Smell");
- when(i18n.message(any(Locale.class), eq("issue.type.VULNERABILITY"), anyString())).thenReturn("Vulnerability");
-
- underTest = new MyNewIssuesEmailTemplate(settings, i18n);
- }
+ @Rule
+ public I18nRule i18n = new I18nRule()
+ .put("issue.type.BUG", "Bug")
+ .put("issue.type.CODE_SMELL", "Code Smell")
+ .put("issue.type.VULNERABILITY", "Vulnerability");
+ private MapSettings settings = new MapSettings()
+ .setProperty("sonar.core.serverBaseURL", "http://nemo.sonarsource.org");
+
+ private MyNewIssuesEmailTemplate underTest = new MyNewIssuesEmailTemplate(new EmailSettings(settings.asConfig()), i18n);
@Test
public void no_format_if_not_the_correct_notif() {
import org.junit.Test;
import org.sonar.api.utils.Durations;
import org.sonar.db.DbClient;
-import org.sonar.server.user.index.UserIndex;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
public class MyNewIssuesNotificationTest {
- MyNewIssuesNotification underTest = new MyNewIssuesNotification(mock(UserIndex.class), mock(DbClient.class), mock(Durations.class));
+ MyNewIssuesNotification underTest = new MyNewIssuesNotification(mock(DbClient.class), mock(Durations.class));
@Test
public void set_assignee() {
import java.io.IOException;
import java.nio.charset.StandardCharsets;
-import java.util.Locale;
import org.apache.commons.io.IOUtils;
-import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
-import org.mockito.stubbing.Answer;
import org.sonar.api.config.EmailSettings;
+import org.sonar.api.config.internal.MapSettings;
import org.sonar.api.notifications.Notification;
-import org.sonar.core.i18n.DefaultI18n;
import org.sonar.plugins.emailnotifications.api.EmailMessage;
-import org.sonar.server.user.index.UserDoc;
-import org.sonar.server.user.index.UserIndex;
+import org.sonar.server.i18n.I18nRule;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.ASSIGNEE;
import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.COMPONENT;
import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.EFFORT;
public class NewIssuesEmailTemplateTest {
- NewIssuesEmailTemplate template;
- DefaultI18n i18n;
- UserIndex userIndex;
-
- @Before
- public void setUp() {
- EmailSettings settings = mock(EmailSettings.class);
- when(settings.getServerBaseURL()).thenReturn("http://nemo.sonarsource.org");
- i18n = mock(DefaultI18n.class);
- userIndex = mock(UserIndex.class);
- // returns the login passed in parameter
- when(userIndex.getNullableByLogin(anyString()))
- .thenAnswer((Answer<UserDoc>) invocationOnMock -> new UserDoc().setName((String) invocationOnMock.getArguments()[0]));
- when(i18n.message(any(Locale.class), eq("issue.type.CODE_SMELL"), anyString())).thenReturn("Code Smell");
- when(i18n.message(any(Locale.class), eq("issue.type.VULNERABILITY"), anyString())).thenReturn("Vulnerability");
- when(i18n.message(any(Locale.class), eq("issue.type.BUG"), anyString())).thenReturn("Bug");
-
- template = new NewIssuesEmailTemplate(settings, i18n);
- }
+ @Rule
+ public I18nRule i18n = new I18nRule()
+ .put("issue.type.BUG", "Bug")
+ .put("issue.type.CODE_SMELL", "Code Smell")
+ .put("issue.type.VULNERABILITY", "Vulnerability");
+ private MapSettings settings = new MapSettings()
+ .setProperty("sonar.core.serverBaseURL", "http://nemo.sonarsource.org");
+
+ private NewIssuesEmailTemplate template = new NewIssuesEmailTemplate(new EmailSettings(settings.asConfig()), i18n);
@Test
public void no_format_is_not_the_correct_notification() {
*/
package org.sonar.server.issue.notification;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import java.util.Arrays;
-import java.util.Collections;
import java.util.Date;
-import java.util.Random;
-import java.util.stream.Collectors;
import java.util.stream.IntStream;
-import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rules.RuleType;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.Duration;
import org.sonar.api.utils.Durations;
-import org.sonar.core.issue.DefaultIssue;
-import org.sonar.core.util.stream.MoreCollectors;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.component.ComponentDao;
+import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.rule.RuleDao;
+import org.sonar.db.issue.IssueDto;
import org.sonar.db.rule.RuleDefinitionDto;
-import org.sonar.server.user.index.UserIndex;
+import org.sonar.db.user.UserDto;
+import static java.util.Arrays.asList;
+import static java.util.Collections.singletonList;
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyCollection;
-import static org.mockito.ArgumentMatchers.same;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import static org.sonar.api.rules.RuleType.BUG;
+import static org.sonar.api.rules.RuleType.CODE_SMELL;
+import static org.sonar.db.component.ComponentTesting.newDirectory;
+import static org.sonar.db.component.ComponentTesting.newFileDto;
import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.ASSIGNEE;
import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.COMPONENT;
import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.EFFORT;
public class NewIssuesNotificationTest {
- private final Random random = new Random();
- private final RuleType randomRuleType = RuleType.values()[random.nextInt(RuleType.values().length)];
- private NewIssuesStatistics.Stats stats = new NewIssuesStatistics.Stats(i -> true);
- private UserIndex userIndex = mock(UserIndex.class);
- private DbClient dbClient = mock(DbClient.class);
- private DbSession dbSession = mock(DbSession.class);
- private ComponentDao componentDao = mock(ComponentDao.class);
- private RuleDao ruleDao = mock(RuleDao.class);
- private Durations durations = mock(Durations.class);
- private NewIssuesNotification underTest = new NewIssuesNotification(userIndex, dbClient, durations);
-
- @Before
- public void setUp() throws Exception {
- when(dbClient.openSession(anyBoolean())).thenReturn(dbSession);
- when(dbClient.componentDao()).thenReturn(componentDao);
- when(dbClient.ruleDao()).thenReturn(ruleDao);
- when(componentDao.selectByUuids(same(dbSession), anyCollection())).thenReturn(Collections.emptyList());
- }
+ @Rule
+ public DbTester db = DbTester.create();
+
+ private NewIssuesNotification underTest = new NewIssuesNotification(db.getDbClient(), new Durations());
@Test
public void set_project_without_branch() {
underTest.setProjectVersion(null);
assertThat(underTest.getFieldValue(NewIssuesEmailTemplate.FIELD_PROJECT_VERSION)).isNull();
-
}
@Test
@Test
public void set_statistics() {
- addIssueNTimes(newIssue1(), 5);
- addIssueNTimes(newIssue2(), 3);
- when(componentDao.selectByUuids(dbSession, ImmutableSet.of("file-uuid", "directory-uuid")))
- .thenReturn(Arrays.asList(
- new ComponentDto().setUuid("file-uuid").setName("file-name"),
- new ComponentDto().setUuid("directory-uuid").setName("directory-name")));
- RuleKey rule1 = RuleKey.of("SonarQube", "rule-the-world");
- RuleKey rule2 = RuleKey.of("SonarQube", "rule-the-universe");
- when(ruleDao.selectDefinitionByKeys(dbSession, ImmutableSet.of(rule1, rule2)))
- .thenReturn(
- ImmutableList.of(newRule(rule1, "Rule the World", "Java"), newRule(rule2, "Rule the Universe", "Clojure")));
-
- underTest.setStatistics("project-long-name", stats);
+ ComponentDto project = db.components().insertPrivateProject();
+ ComponentDto directory = db.components().insertComponent(newDirectory(project, "path"));
+ ComponentDto file = db.components().insertComponent(newFileDto(directory));
+ RuleDefinitionDto rule1 = db.rules().insert(r -> r.setRepositoryKey("SonarQube").setRuleKey("rule1-the-world").setName("Rule the World").setLanguage("Java"));
+ RuleDefinitionDto rule2 = db.rules().insert(r -> r.setRepositoryKey("SonarQube").setRuleKey("rule1-the-universe").setName("Rule the Universe").setLanguage("Clojure"));
+ IssueDto issue1 = db.issues().insert(rule1, project, file, i -> i.setType(BUG).setAssignee("maynard").setTags(asList("bug", "owasp")));
+ IssueDto issue2 = db.issues().insert(rule2, project, directory, i -> i.setType(CODE_SMELL).setAssignee("keenan").setTags(singletonList("owasp")));
+ NewIssuesStatistics.Stats stats = new NewIssuesStatistics.Stats(i -> true);
+ IntStream.rangeClosed(1, 5).forEach(i -> stats.add(issue1.toDefaultIssue()));
+ IntStream.rangeClosed(1, 3).forEach(i -> stats.add(issue2.toDefaultIssue()));
+
+ underTest.setStatistics(project.longName(), stats);
assertThat(underTest.getFieldValue(RULE_TYPE + ".BUG.count")).isEqualTo("5");
assertThat(underTest.getFieldValue(RULE_TYPE + ".CODE_SMELL.count")).isEqualTo("3");
assertThat(underTest.getFieldValue(TAG + ".1.count")).isEqualTo("8");
assertThat(underTest.getFieldValue(TAG + ".2.label")).isEqualTo("bug");
assertThat(underTest.getFieldValue(TAG + ".2.count")).isEqualTo("5");
- assertThat(underTest.getFieldValue(COMPONENT + ".1.label")).isEqualTo("file-name");
+ assertThat(underTest.getFieldValue(COMPONENT + ".1.label")).isEqualTo(file.name());
assertThat(underTest.getFieldValue(COMPONENT + ".1.count")).isEqualTo("5");
- assertThat(underTest.getFieldValue(COMPONENT + ".2.label")).isEqualTo("directory-name");
+ assertThat(underTest.getFieldValue(COMPONENT + ".2.label")).isEqualTo(directory.name());
assertThat(underTest.getFieldValue(COMPONENT + ".2.count")).isEqualTo("3");
assertThat(underTest.getFieldValue(RULE + ".1.label")).isEqualTo("Rule the World (Java)");
assertThat(underTest.getFieldValue(RULE + ".1.count")).isEqualTo("5");
assertThat(underTest.getFieldValue(RULE + ".2.label")).isEqualTo("Rule the Universe (Clojure)");
assertThat(underTest.getFieldValue(RULE + ".2.count")).isEqualTo("3");
- assertThat(underTest.getDefaultMessage()).startsWith("8 new issues on project-long-name");
+ assertThat(underTest.getDefaultMessage()).startsWith("8 new issues on " + project.longName());
+ }
+
+ @Test
+ public void set_assignee() {
+ ComponentDto project = db.components().insertPrivateProject();
+ ComponentDto file = db.components().insertComponent(newFileDto(project));
+ RuleDefinitionDto rule = db.rules().insert();
+ UserDto user = db.users().insertUser();
+ IssueDto issue1 = db.issues().insert(rule, project, file, i -> i.setAssignee(user.getLogin()));
+ IssueDto issue2 = db.issues().insert(rule, project, file, i -> i.setAssignee("no_user"));
+ NewIssuesStatistics.Stats stats = new NewIssuesStatistics.Stats(i -> true);
+ IntStream.rangeClosed(1, 5).forEach(i -> stats.add(issue1.toDefaultIssue()));
+ IntStream.rangeClosed(1, 3).forEach(i -> stats.add(issue2.toDefaultIssue()));
+
+ underTest.setStatistics(project.longName(), stats);
+
+ assertThat(underTest.getFieldValue(ASSIGNEE + ".1.label")).isEqualTo(user.getName());
+ assertThat(underTest.getFieldValue(ASSIGNEE + ".1.count")).isEqualTo("5");
+ assertThat(underTest.getFieldValue(ASSIGNEE + ".2.label")).isEqualTo("no_user");
+ assertThat(underTest.getFieldValue(ASSIGNEE + ".2.count")).isEqualTo("3");
}
@Test
public void add_only_5_assignees_with_biggest_issue_counts() {
- String[] assignees = IntStream.range(0, 6 + random.nextInt(10)).mapToObj(s -> "assignee" + s).toArray(String[]::new);
+ ComponentDto project = db.components().insertPrivateProject();
+ ComponentDto file = db.components().insertComponent(newFileDto(project));
+ RuleDefinitionDto rule = db.rules().insert();
NewIssuesStatistics.Stats stats = new NewIssuesStatistics.Stats(i -> true);
- int i = assignees.length;
- for (String assignee : assignees) {
- IntStream.range(0, i).mapToObj(j -> new DefaultIssue().setType(randomRuleType).setAssignee(assignee)).forEach(stats::add);
- i--;
- }
-
- underTest.setStatistics(randomAlphanumeric(20), stats);
-
- for (int j = 0; j < 5; j++) {
- String fieldBase = ASSIGNEE + "." + (j + 1);
- assertThat(underTest.getFieldValue(fieldBase + ".label")).as("label of %s", fieldBase).isEqualTo(assignees[j]);
- assertThat(underTest.getFieldValue(fieldBase + ".count")).as("count of %s", fieldBase).isEqualTo(String.valueOf(assignees.length - j));
- }
+ IntStream.rangeClosed(1, 10).forEach(i -> stats.add(db.issues().insert(rule, project, file, issue -> issue.setAssignee("assignee_1")).toDefaultIssue()));
+ IntStream.rangeClosed(1, 9).forEach(i -> stats.add(db.issues().insert(rule, project, file, issue -> issue.setAssignee("assignee_2")).toDefaultIssue()));
+ IntStream.rangeClosed(1, 8).forEach(i -> stats.add(db.issues().insert(rule, project, file, issue -> issue.setAssignee("assignee_3")).toDefaultIssue()));
+ IntStream.rangeClosed(1, 7).forEach(i -> stats.add(db.issues().insert(rule, project, file, issue -> issue.setAssignee("assignee_4")).toDefaultIssue()));
+ IntStream.rangeClosed(1, 6).forEach(i -> stats.add(db.issues().insert(rule, project, file, issue -> issue.setAssignee("assignee_5")).toDefaultIssue()));
+ IntStream.rangeClosed(1, 5).forEach(i -> stats.add(db.issues().insert(rule, project, file, issue -> issue.setAssignee("assignee_6")).toDefaultIssue()));
+ IntStream.rangeClosed(1, 4).forEach(i -> stats.add(db.issues().insert(rule, project, file, issue -> issue.setAssignee("assignee_7")).toDefaultIssue()));
+ IntStream.rangeClosed(1, 3).forEach(i -> stats.add(db.issues().insert(rule, project, file, issue -> issue.setAssignee("assignee_8")).toDefaultIssue()));
+
+ underTest.setStatistics(project.longName(), stats);
+
+ assertThat(underTest.getFieldValue(ASSIGNEE + ".1.label")).isEqualTo("assignee_1");
+ assertThat(underTest.getFieldValue(ASSIGNEE + ".1.count")).isEqualTo("10");
+ assertThat(underTest.getFieldValue(ASSIGNEE + ".2.label")).isEqualTo("assignee_2");
+ assertThat(underTest.getFieldValue(ASSIGNEE + ".2.count")).isEqualTo("9");
+ assertThat(underTest.getFieldValue(ASSIGNEE + ".3.label")).isEqualTo("assignee_3");
+ assertThat(underTest.getFieldValue(ASSIGNEE + ".3.count")).isEqualTo("8");
+ assertThat(underTest.getFieldValue(ASSIGNEE + ".4.label")).isEqualTo("assignee_4");
+ assertThat(underTest.getFieldValue(ASSIGNEE + ".4.count")).isEqualTo("7");
+ assertThat(underTest.getFieldValue(ASSIGNEE + ".5.label")).isEqualTo("assignee_5");
+ assertThat(underTest.getFieldValue(ASSIGNEE + ".5.count")).isEqualTo("6");
assertThat(underTest.getFieldValue(ASSIGNEE + ".6.label")).isNull();
assertThat(underTest.getFieldValue(ASSIGNEE + ".6.count")).isNull();
}
@Test
public void add_only_5_components_with_biggest_issue_counts() {
- String[] componentUuids = IntStream.range(0, 6 + random.nextInt(10)).mapToObj(s -> "component_uuid_" + s).toArray(String[]::new);
+ ComponentDto project = db.components().insertPrivateProject();
+ RuleDefinitionDto rule = db.rules().insert();
NewIssuesStatistics.Stats stats = new NewIssuesStatistics.Stats(i -> true);
- int i = componentUuids.length;
- for (String component : componentUuids) {
- IntStream.range(0, i).mapToObj(j -> new DefaultIssue().setType(randomRuleType).setComponentUuid(component)).forEach(stats::add);
- i--;
- }
- when(componentDao.selectByUuids(dbSession, Arrays.stream(componentUuids).limit(5).collect(Collectors.toSet())))
- .thenReturn(
- Arrays.stream(componentUuids).map(uuid -> new ComponentDto().setUuid(uuid).setName("name_" + uuid)).collect(MoreCollectors.toList()));
-
- underTest.setStatistics(randomAlphanumeric(20), stats);
-
- for (int j = 0; j < 5; j++) {
- String fieldBase = COMPONENT + "." + (j + 1);
- assertThat(underTest.getFieldValue(fieldBase + ".label")).as("label of %s", fieldBase).isEqualTo("name_" + componentUuids[j]);
- assertThat(underTest.getFieldValue(fieldBase + ".count")).as("count of %s", fieldBase).isEqualTo(String.valueOf(componentUuids.length - j));
- }
+ ComponentDto file1 = db.components().insertComponent(newFileDto(project));
+ IntStream.rangeClosed(1, 10).forEach(i -> stats.add(db.issues().insert(rule, project, file1).toDefaultIssue()));
+ ComponentDto file2 = db.components().insertComponent(newFileDto(project));
+ IntStream.rangeClosed(1, 9).forEach(i -> stats.add(db.issues().insert(rule, project, file2).toDefaultIssue()));
+ ComponentDto file3 = db.components().insertComponent(newFileDto(project));
+ IntStream.rangeClosed(1, 8).forEach(i -> stats.add(db.issues().insert(rule, project, file3).toDefaultIssue()));
+ ComponentDto file4 = db.components().insertComponent(newFileDto(project));
+ IntStream.rangeClosed(1, 7).forEach(i -> stats.add(db.issues().insert(rule, project, file4).toDefaultIssue()));
+ ComponentDto file5 = db.components().insertComponent(newFileDto(project));
+ IntStream.rangeClosed(1, 6).forEach(i -> stats.add(db.issues().insert(rule, project, file5).toDefaultIssue()));
+ ComponentDto file6 = db.components().insertComponent(newFileDto(project));
+ IntStream.rangeClosed(1, 5).forEach(i -> stats.add(db.issues().insert(rule, project, file6).toDefaultIssue()));
+ ComponentDto file7 = db.components().insertComponent(newFileDto(project));
+ IntStream.rangeClosed(1, 4).forEach(i -> stats.add(db.issues().insert(rule, project, file7).toDefaultIssue()));
+ ComponentDto file8 = db.components().insertComponent(newFileDto(project));
+ IntStream.rangeClosed(1, 3).forEach(i -> stats.add(db.issues().insert(rule, project, file8).toDefaultIssue()));
+
+ underTest.setStatistics(project.longName(), stats);
+
+ assertThat(underTest.getFieldValue(COMPONENT + ".1.label")).isEqualTo(file1.name());
+ assertThat(underTest.getFieldValue(COMPONENT + ".1.count")).isEqualTo("10");
+ assertThat(underTest.getFieldValue(COMPONENT + ".2.label")).isEqualTo(file2.name());
+ assertThat(underTest.getFieldValue(COMPONENT + ".2.count")).isEqualTo("9");
+ assertThat(underTest.getFieldValue(COMPONENT + ".3.label")).isEqualTo(file3.name());
+ assertThat(underTest.getFieldValue(COMPONENT + ".3.count")).isEqualTo("8");
+ assertThat(underTest.getFieldValue(COMPONENT + ".4.label")).isEqualTo(file4.name());
+ assertThat(underTest.getFieldValue(COMPONENT + ".4.count")).isEqualTo("7");
+ assertThat(underTest.getFieldValue(COMPONENT + ".5.label")).isEqualTo(file5.name());
+ assertThat(underTest.getFieldValue(COMPONENT + ".5.count")).isEqualTo("6");
assertThat(underTest.getFieldValue(COMPONENT + ".6.label")).isNull();
assertThat(underTest.getFieldValue(COMPONENT + ".6.count")).isNull();
}
@Test
public void add_only_5_rules_with_biggest_issue_counts() {
- String repository = randomAlphanumeric(4);
- String[] ruleKeys = IntStream.range(0, 6 + random.nextInt(10)).mapToObj(s -> "rule_" + s).toArray(String[]::new);
+ ComponentDto project = db.components().insertPrivateProject();
+ ComponentDto file = db.components().insertComponent(newFileDto(project));
NewIssuesStatistics.Stats stats = new NewIssuesStatistics.Stats(i -> true);
- int i = ruleKeys.length;
- for (String ruleKey : ruleKeys) {
- IntStream.range(0, i).mapToObj(j -> new DefaultIssue().setType(randomRuleType).setRuleKey(RuleKey.of(repository, ruleKey))).forEach(stats::add);
- i--;
- }
- when(ruleDao.selectDefinitionByKeys(dbSession, Arrays.stream(ruleKeys).limit(5).map(s -> RuleKey.of(repository, s)).collect(MoreCollectors.toSet(5))))
- .thenReturn(
- Arrays.stream(ruleKeys).limit(5).map(ruleKey -> new RuleDefinitionDto()
- .setRuleKey(RuleKey.of(repository, ruleKey))
- .setName("name_" + ruleKey)
- .setLanguage("language_" + ruleKey))
- .collect(MoreCollectors.toList(5)));
-
- underTest.setStatistics(randomAlphanumeric(20), stats);
-
- for (int j = 0; j < 5; j++) {
- String fieldBase = RULE + "." + (j + 1);
- assertThat(underTest.getFieldValue(fieldBase + ".label")).as("label of %s", fieldBase).isEqualTo("name_" + ruleKeys[j] + " (language_" + ruleKeys[j] + ")");
- assertThat(underTest.getFieldValue(fieldBase + ".count")).as("count of %s", fieldBase).isEqualTo(String.valueOf(ruleKeys.length - j));
- }
+ RuleDefinitionDto rule1 = db.rules().insert(r -> r.setLanguage("Java"));
+ IntStream.rangeClosed(1, 10).forEach(i -> stats.add(db.issues().insert(rule1, project, file).toDefaultIssue()));
+ RuleDefinitionDto rule2 = db.rules().insert(r -> r.setLanguage("Java"));
+ IntStream.rangeClosed(1, 9).forEach(i -> stats.add(db.issues().insert(rule2, project, file).toDefaultIssue()));
+ RuleDefinitionDto rule3 = db.rules().insert(r -> r.setLanguage("Java"));
+ IntStream.rangeClosed(1, 8).forEach(i -> stats.add(db.issues().insert(rule3, project, file).toDefaultIssue()));
+ RuleDefinitionDto rule4 = db.rules().insert(r -> r.setLanguage("Java"));
+ IntStream.rangeClosed(1, 7).forEach(i -> stats.add(db.issues().insert(rule4, project, file).toDefaultIssue()));
+ RuleDefinitionDto rule5 = db.rules().insert(r -> r.setLanguage("Java"));
+ IntStream.rangeClosed(1, 6).forEach(i -> stats.add(db.issues().insert(rule5, project, file).toDefaultIssue()));
+ RuleDefinitionDto rule6 = db.rules().insert(r -> r.setLanguage("Java"));
+ IntStream.rangeClosed(1, 5).forEach(i -> stats.add(db.issues().insert(rule6, project, file).toDefaultIssue()));
+ RuleDefinitionDto rule7 = db.rules().insert(r -> r.setLanguage("Java"));
+ IntStream.rangeClosed(1, 4).forEach(i -> stats.add(db.issues().insert(rule7, project, file).toDefaultIssue()));
+ RuleDefinitionDto rule8 = db.rules().insert(r -> r.setLanguage("Java"));
+ IntStream.rangeClosed(1, 3).forEach(i -> stats.add(db.issues().insert(rule8, project, file).toDefaultIssue()));
+
+ underTest.setStatistics(project.longName(), stats);
+
+ String javaSuffix = " (Java)";
+ assertThat(underTest.getFieldValue(RULE + ".1.label")).isEqualTo(rule1.getName() + javaSuffix);
+ assertThat(underTest.getFieldValue(RULE + ".1.count")).isEqualTo("10");
+ assertThat(underTest.getFieldValue(RULE + ".2.label")).isEqualTo(rule2.getName() + javaSuffix);
+ assertThat(underTest.getFieldValue(RULE + ".2.count")).isEqualTo("9");
+ assertThat(underTest.getFieldValue(RULE + ".3.label")).isEqualTo(rule3.getName() + javaSuffix);
+ assertThat(underTest.getFieldValue(RULE + ".3.count")).isEqualTo("8");
+ assertThat(underTest.getFieldValue(RULE + ".4.label")).isEqualTo(rule4.getName() + javaSuffix);
+ assertThat(underTest.getFieldValue(RULE + ".4.count")).isEqualTo("7");
+ assertThat(underTest.getFieldValue(RULE + ".5.label")).isEqualTo(rule5.getName() + javaSuffix);
+ assertThat(underTest.getFieldValue(RULE + ".5.count")).isEqualTo("6");
assertThat(underTest.getFieldValue(RULE + ".6.label")).isNull();
assertThat(underTest.getFieldValue(RULE + ".6.count")).isNull();
}
@Test
public void set_debt() {
- when(durations.format(any(Duration.class))).thenReturn("55 min");
-
underTest.setDebt(Duration.create(55));
- assertThat(underTest.getFieldValue(EFFORT + ".count")).isEqualTo("55 min");
- }
-
- private void addIssueNTimes(DefaultIssue issue, int times) {
- for (int i = 0; i < times; i++) {
- stats.add(issue);
- }
+ assertThat(underTest.getFieldValue(EFFORT + ".count")).isEqualTo("55min");
}
- private DefaultIssue newIssue1() {
- return new DefaultIssue()
- .setAssignee("maynard")
- .setComponentUuid("file-uuid")
- .setType(RuleType.BUG)
- .setTags(Lists.newArrayList("bug", "owasp"))
- .setRuleKey(RuleKey.of("SonarQube", "rule-the-world"))
- .setEffort(Duration.create(5L));
- }
-
- private DefaultIssue newIssue2() {
- return new DefaultIssue()
- .setAssignee("keenan")
- .setComponentUuid("directory-uuid")
- .setType(RuleType.CODE_SMELL)
- .setTags(Lists.newArrayList("owasp"))
- .setRuleKey(RuleKey.of("SonarQube", "rule-the-universe"))
- .setEffort(Duration.create(10L));
- }
-
- private RuleDefinitionDto newRule(RuleKey ruleKey, String name, String language) {
- return new RuleDefinitionDto()
- .setRuleKey(ruleKey)
- .setName(name)
- .setLanguage(language);
- }
}
import org.sonar.db.rule.RuleDto;
import org.sonar.db.rule.RuleTesting;
import org.sonar.db.user.UserDto;
-import org.sonar.db.user.UserTesting;
import org.sonar.server.es.EsTester;
import org.sonar.server.es.SearchOptions;
import org.sonar.server.es.StartupIndexer;
import static org.assertj.core.groups.Tuple.tuple;
import static org.sonar.api.web.UserRole.ISSUE_ADMIN;
import static org.sonar.db.component.ComponentTesting.newFileDto;
-import static org.sonar.db.user.UserTesting.newUserDto;
import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_BRANCH;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.DEPRECATED_FACET_MODE_DEBT;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.FACET_MODE_EFFORT;
@Test
public void filter_by_assigned_to_me() {
- dbClient.userDao().insert(session, newUserDto().setLogin("john").setName("John").setEmail("john@email.com"));
+ db.users().insertUser(u -> u.setLogin("john").setName("John").setEmail("john@email.com"));
ComponentDto project = insertComponent(ComponentTesting.newPublicProjectDto(defaultOrganization, "PROJECT_ID").setDbKey("PROJECT_KEY"));
indexPermissions();
@Test
public void assigned_to_me_facet_is_sticky_relative_to_assignees() {
- dbClient.userDao().insert(session, newUserDto().setLogin("alice").setName("Alice").setEmail("alice@email.com"));
+ db.users().insertUser(u -> u.setLogin("alice").setName("Alice").setEmail("alice@email.com"));
ComponentDto project = insertComponent(ComponentTesting.newPublicProjectDto(otherOrganization2, "PROJECT_ID").setDbKey("PROJECT_KEY"));
indexPermissions();
import org.sonar.db.metric.MetricTesting;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.permission.OrganizationPermission;
-import org.sonar.db.user.UserDto;
-import org.sonar.db.user.UserTesting;
import org.sonar.server.component.TestComponentFinder;
import org.sonar.server.es.EsTester;
import org.sonar.server.exceptions.BadRequestException;
import static org.sonar.api.measures.Metric.ValueType.LEVEL;
import static org.sonar.api.measures.Metric.ValueType.STRING;
import static org.sonar.api.measures.Metric.ValueType.WORK_DUR;
-import static org.sonar.db.user.UserTesting.newUserDto;
import static org.sonar.server.util.TypeValidationsTesting.newFullTypeValidations;
public class CreateActionTest {
ws = new WsTester(new CustomMeasuresWs(new CreateAction(dbClient, userSession, System2.INSTANCE, new CustomMeasureValidator(newFullTypeValidations()),
new CustomMeasureJsonWriter(new UserJsonWriter(userSession)), TestComponentFinder.from(db))));
- db.getDbClient().userDao().insert(dbSession, newUserDto()
- .setLogin("login")
+ db.users().insertUser(u -> u.setLogin("login")
.setName("Login")
.setEmail("login@login.com")
.setActive(true));
- dbSession.commit();
OrganizationDto organizationDto = db.organizations().insert();
project = ComponentTesting.newPrivateProjectDto(organizationDto, DEFAULT_PROJECT_UUID).setDbKey(DEFAULT_PROJECT_KEY);
import org.sonar.server.es.EsTester;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.user.index.UserDoc;
-import org.sonar.server.user.index.UserIndexDefinition;
import org.sonar.server.ws.WsTester;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.server.measure.custom.ws.CustomMeasuresWs.ENDPOINT;
import static org.sonar.server.measure.custom.ws.MetricsAction.ACTION;
-
public class MetricsActionTest {
private static final String DEFAULT_PROJECT_UUID = "project-uuid";
private static final String DEFAULT_PROJECT_KEY = "project-key";
private final DbClient dbClient = db.getDbClient();
private final DbSession dbSession = db.getSession();
- private WsTester ws;
private ComponentDto defaultProject;
+ private WsTester ws;
@Before
public void setUp() throws Exception {
- es.putDocuments(UserIndexDefinition.INDEX_TYPE_USER.getIndex(), UserIndexDefinition.INDEX_TYPE_USER.getType(), new UserDoc()
- .setLogin("login")
- .setName("Login")
- .setEmail("login@login.com")
- .setActive(true));
- ws = new WsTester(new CustomMeasuresWs(new MetricsAction(dbClient, userSession, TestComponentFinder.from(db))));
defaultProject = insertDefaultProject();
userSession.logIn().addProjectPermission(UserRole.ADMIN, defaultProject);
+ ws = new WsTester(new CustomMeasuresWs(new MetricsAction(dbClient, userSession, TestComponentFinder.from(db))));
}
@Test
import org.sonar.db.component.SnapshotTesting;
import org.sonar.db.measure.custom.CustomMeasureDto;
import org.sonar.db.metric.MetricDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.db.user.UserTesting;
import org.sonar.server.component.TestComponentFinder;
import org.sonar.server.es.EsTester;
import org.sonar.server.exceptions.ForbiddenException;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.db.measure.custom.CustomMeasureTesting.newCustomMeasureDto;
import static org.sonar.db.metric.MetricTesting.newMetricDto;
-import static org.sonar.db.user.UserTesting.newUserDto;
public class SearchActionTest {
ws = new WsTester(new CustomMeasuresWs(new SearchAction(dbClient, customMeasureJsonWriter, userSessionRule, TestComponentFinder.from(db))));
defaultProject = insertDefaultProject();
userSessionRule.logIn().addProjectPermission(UserRole.ADMIN, defaultProject);
-
- db.getDbClient().userDao().insert(dbSession, newUserDto()
- .setLogin("login")
+ db.users().insertUser(u -> u.setLogin("login")
.setName("Login")
.setEmail("login@login.com")
- .setActive(true)
- );
- dbSession.commit();
+ .setActive(true));
}
@Test
import org.sonar.db.metric.MetricDto;
import org.sonar.db.metric.MetricTesting;
import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.db.user.UserTesting;
import org.sonar.server.es.EsTester;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.ServerException;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonar.db.measure.custom.CustomMeasureTesting.newCustomMeasureDto;
-import static org.sonar.db.user.UserTesting.newUserDto;
import static org.sonar.server.measure.custom.ws.UpdateAction.PARAM_DESCRIPTION;
import static org.sonar.server.measure.custom.ws.UpdateAction.PARAM_ID;
import static org.sonar.server.measure.custom.ws.UpdateAction.PARAM_VALUE;
ws = new WsTester(new CustomMeasuresWs(new UpdateAction(dbClient, userSessionRule, system, validator, new CustomMeasureJsonWriter(new UserJsonWriter(userSessionRule)))));
- db.getDbClient().userDao().insert(dbSession, newUserDto()
- .setLogin("login")
+ db.users().insertUser(u -> u.setLogin("login")
.setName("Login")
.setEmail("login@login.com")
.setActive(true)
import org.sonar.server.qualityprofile.BuiltInQProfileRepository;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.user.index.UserIndex;
+import org.sonar.server.user.index.UserIndexDefinition;
import org.sonar.server.user.index.UserIndexer;
import org.sonar.server.usergroups.DefaultGroupCreatorImpl;
import org.sonar.server.ws.TestRequest;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
+import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
+import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.mockito.Mockito.mock;
import static org.sonar.core.config.CorePropertyDefinitions.ORGANIZATIONS_ANYONE_CAN_CREATE;
import static org.sonar.server.organization.ws.OrganizationsWsSupport.PARAM_KEY;
import static org.sonar.server.organization.ws.OrganizationsWsSupport.PARAM_NAME;
import static org.sonar.server.organization.ws.OrganizationsWsTestSupport.STRING_257_CHARS_LONG;
import static org.sonar.server.organization.ws.OrganizationsWsTestSupport.STRING_65_CHARS_LONG;
+import static org.sonar.server.user.index.UserIndexDefinition.FIELD_ORGANIZATION_UUIDS;
+import static org.sonar.server.user.index.UserIndexDefinition.FIELD_UUID;
import static org.sonar.test.JsonAssert.assertJson;
public class CreateActionTest {
}
@Test
- public void request_set_user_as_member_of_organization() {
+ public void set_user_as_member_of_organization() {
UserDto user = dbTester.users().insertUser();
userSession.logIn(user).setSystemAdministrator();
dbTester.qualityGates().insertBuiltInQualityGate();
OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, "bar").get();
assertThat(dbClient.organizationMemberDao().select(dbSession, organization.getUuid(), user.getId())).isPresent();
- assertThat(userIndex.getNullableByLogin(user.getLogin()).organizationUuids()).contains(organization.getUuid());
+ assertThat(es.client().prepareSearch(UserIndexDefinition.INDEX_TYPE_USER)
+ .setQuery(boolQuery()
+ .must(termQuery(FIELD_ORGANIZATION_UUIDS, organization.getUuid()))
+ .must(termQuery(FIELD_UUID, user.getUuid()))).get().getHits().getHits()).hasSize(1);
}
@Test
}
private static void populateRequest(@Nullable String name, @Nullable String key, @Nullable String description, @Nullable String url, @Nullable String avatar,
- TestRequest request) {
+ TestRequest request) {
OrganizationsWsTestSupport.setParam(request, "name", name);
OrganizationsWsTestSupport.setParam(request, "key", key);
OrganizationsWsTestSupport.setParam(request, "description", description);
import java.util.HashSet;
import javax.annotation.Nullable;
+import org.elasticsearch.action.search.SearchRequestBuilder;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.user.index.UserIndex;
+import org.sonar.server.user.index.UserIndexDefinition;
import org.sonar.server.user.index.UserIndexer;
import org.sonar.server.user.index.UserQuery;
import org.sonar.server.ws.TestRequest;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.groups.Tuple.tuple;
+import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
+import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.sonar.api.CoreProperties.DEFAULT_ISSUE_ASSIGNEE;
import static org.sonar.api.web.UserRole.CODEVIEWER;
import static org.sonar.api.web.UserRole.USER;
import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_GATES;
import static org.sonar.db.permission.OrganizationPermission.SCAN;
import static org.sonar.server.organization.ws.OrganizationsWsSupport.PARAM_ORGANIZATION;
+import static org.sonar.server.user.index.UserIndexDefinition.FIELD_ORGANIZATION_UUIDS;
+import static org.sonar.server.user.index.UserIndexDefinition.FIELD_UUID;
public class RemoveMemberActionTest {
@Rule
private void assertNotAMember(String organizationUuid, UserDto user) {
assertThat(dbClient.organizationMemberDao().select(dbSession, organizationUuid, user.getId())).isNotPresent();
- assertThat(userIndex.search(UserQuery.builder().setOrganizationUuid(organizationUuid).setTextQuery(user.getLogin()).build(), new SearchOptions()).getDocs()).isEmpty();
+ assertMemberInIndex(organizationUuid, user, false);
}
private void assertMember(String organizationUuid, UserDto user) {
assertThat(dbClient.organizationMemberDao().select(dbSession, organizationUuid, user.getId())).isPresent();
- assertThat(userIndex.getNullableByLogin(user.getLogin()).organizationUuids()).contains(organizationUuid);
+ assertThat(userIndex.search(UserQuery.builder()
+ .setOrganizationUuid(organizationUuid)
+ .setTextQuery(user.getLogin())
+ .build(),
+ new SearchOptions()).getDocs())
+ .hasSize(1);
+ assertMemberInIndex(organizationUuid, user, true);
+ }
+
+ private void assertMemberInIndex(String organizationUuid, UserDto user, boolean isMember) {
+ SearchRequestBuilder request = es.client().prepareSearch(UserIndexDefinition.INDEX_TYPE_USER)
+ .setQuery(boolQuery()
+ .must(termQuery(FIELD_ORGANIZATION_UUIDS, organizationUuid))
+ .must(termQuery(FIELD_UUID, user.getUuid())));
+ if (isMember) {
+ assertThat(request.get().getHits().getHits()).hasSize(1);
+ } else {
+ assertThat(request.get().getHits().getHits()).isEmpty();
+ }
}
private void assertOrgPermissionsOfUser(UserDto user, OrganizationDto organization, OrganizationPermission... permissions) {
import org.sonar.db.DbTester;
import org.sonar.db.user.UserDto;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.nullValue;
-import static org.junit.Assert.assertThat;
-import static org.sonar.db.DbTester.create;
+import static org.assertj.core.api.Java6Assertions.assertThat;
public class DeprecatedUserFinderTest {
@Rule
- public DbTester dbTester = create(System2.INSTANCE);
- private DeprecatedUserFinder underTest = new DeprecatedUserFinder(dbTester.getDbClient());
+ public DbTester db = DbTester.create(System2.INSTANCE);
+
+ private DeprecatedUserFinder underTest = new DeprecatedUserFinder(db.getDbClient());
@Test
public void shouldFindUserByLogin() {
+ UserDto user1 = db.users().insertUser();
+ UserDto user2 = db.users().insertUser();
- UserDto simon = dbTester.users().insertUser(u -> u.setLogin("simon").setName("Simon Brandhof").setEmail("simon.brandhof@sonarsource.com"));
- UserDto evgeny = dbTester.users().insertUser(u -> u.setLogin("godin").setName("Evgeny Mandrikov").setEmail("evgeny.mandrikov@sonarsource.com"));
-
- User user = underTest.findByLogin(simon.getLogin());
- assertThat(user.getId(), is(simon.getId()));
- assertThat(user.getLogin(), is("simon"));
- assertThat(user.getName(), is("Simon Brandhof"));
- assertThat(user.getEmail(), is("simon.brandhof@sonarsource.com"));
+ User user = underTest.findByLogin(user1.getLogin());
+ assertThat(user.getId()).isEqualTo(user1.getId());
+ assertThat(user.getLogin()).isEqualTo(user1.getLogin());
+ assertThat(user.getName()).isEqualTo(user1.getName());
+ assertThat(user.getEmail()).isEqualTo(user1.getEmail());
- user = underTest.findByLogin(evgeny.getLogin());
- assertThat(user.getId(), is(evgeny.getId()));
- assertThat(user.getLogin(), is("godin"));
- assertThat(user.getName(), is("Evgeny Mandrikov"));
- assertThat(user.getEmail(), is("evgeny.mandrikov@sonarsource.com"));
-
- user = underTest.findByLogin("user");
- assertThat(user, nullValue());
+ assertThat(underTest.findByLogin("unknown")).isNull();
}
@Test
public void shouldFindUserById() {
- UserDto simon = dbTester.users().insertUser(u -> u.setLogin("simon").setName("Simon Brandhof").setEmail("simon.brandhof@sonarsource.com"));
- UserDto evgeny = dbTester.users().insertUser(u -> u.setLogin("godin").setName("Evgeny Mandrikov").setEmail("evgeny.mandrikov@sonarsource.com"));
-
- User user = underTest.findById(simon.getId());
- assertThat(user.getId(), is(simon.getId()));
- assertThat(user.getLogin(), is("simon"));
- assertThat(user.getName(), is("Simon Brandhof"));
- assertThat(user.getEmail(), is("simon.brandhof@sonarsource.com"));
+ UserDto user1 = db.users().insertUser();
+ UserDto user2 = db.users().insertUser();
- user = underTest.findById(evgeny.getId());
- assertThat(user.getId(), is(evgeny.getId()));
- assertThat(user.getLogin(), is("godin"));
- assertThat(user.getName(), is("Evgeny Mandrikov"));
- assertThat(user.getEmail(), is("evgeny.mandrikov@sonarsource.com"));
+ User user = underTest.findById(user1.getId());
+ assertThat(user.getId()).isEqualTo(user1.getId());
+ assertThat(user.getLogin()).isEqualTo(user1.getLogin());
+ assertThat(user.getName()).isEqualTo(user1.getName());
+ assertThat(user.getEmail()).isEqualTo(user1.getEmail());
- user = underTest.findById(999);
- assertThat(user, nullValue());
+ assertThat(underTest.findById(321)).isNull();
}
}
@Test
public void create_external_identity() {
- ExternalIdentity externalIdentity = new ExternalIdentity("github", "login");
- assertThat(externalIdentity.getId()).isEqualTo("login");
+ ExternalIdentity externalIdentity = new ExternalIdentity("github", "login", "ABCD");
+ assertThat(externalIdentity.getLogin()).isEqualTo("login");
+ assertThat(externalIdentity.getProvider()).isEqualTo("github");
+ assertThat(externalIdentity.getId()).isEqualTo("ABCD");
+ }
+
+ @Test
+ public void login_is_used_when_id_is_not_provided() {
+ ExternalIdentity externalIdentity = new ExternalIdentity("github", "login", null);
+ assertThat(externalIdentity.getLogin()).isEqualTo("login");
assertThat(externalIdentity.getProvider()).isEqualTo("github");
+ assertThat(externalIdentity.getId()).isEqualTo("login");
}
@Test
thrown.expect(NullPointerException.class);
thrown.expectMessage("Identity provider cannot be null");
- new ExternalIdentity(null, "login");
+ new ExternalIdentity(null, "login", "ABCD");
}
@Test
- public void fail_with_NPE_when_identity_id_is_null() {
+ public void fail_with_NPE_when_identity_login_is_null() {
thrown.expect(NullPointerException.class);
- thrown.expectMessage("Identity id cannot be null");
+ thrown.expectMessage("Identity login cannot be null");
- new ExternalIdentity("github", null);
+ new ExternalIdentity("github", null, "ABCD");
}
}
.setLogin("login")
.setName("name")
.setEmail("email")
- .setExternalIdentity(new ExternalIdentity("github", "github_login"))
+ .setExternalIdentity(new ExternalIdentity("github", "github_login", "ABCD"))
.build();
assertThat(newUser.externalIdentity().getProvider()).isEqualTo("github");
- assertThat(newUser.externalIdentity().getId()).isEqualTo("github_login");
+ assertThat(newUser.externalIdentity().getLogin()).isEqualTo("github_login");
+ assertThat(newUser.externalIdentity().getId()).isEqualTo("ABCD");
}
@Test
.setName("name")
.setEmail("email")
.setPassword("password")
- .setExternalIdentity(new ExternalIdentity("github", "github_login"))
+ .setExternalIdentity(new ExternalIdentity("github", "github_login", "ABCD"))
.build();
}
}
import java.util.Arrays;
import javax.annotation.Nullable;
-import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.db.DbClient;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.ComponentTesting;
import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.permission.OrganizationPermission;
import org.sonar.db.user.GroupDto;
import org.sonar.db.user.UserDto;
import org.sonar.server.exceptions.ForbiddenException;
import static org.sonar.core.permission.GlobalPermissions.PROVISIONING;
import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
import static org.sonar.db.component.ComponentTesting.newChildComponent;
+import static org.sonar.db.component.ComponentTesting.newFileDto;
import static org.sonar.db.permission.OrganizationPermission.ADMINISTER;
import static org.sonar.db.permission.OrganizationPermission.PROVISION_PROJECTS;
import static org.sonar.db.permission.OrganizationPermission.SCAN;
public class ServerUserSessionTest {
- private static final String LOGIN = "marius";
-
- private static final String PUBLIC_PROJECT_UUID = "public_project";
- private static final String PRIVATE_PROJECT_UUID = "private_project";
- private static final String FILE_KEY = "com.foo:Bar:BarFile.xoo";
- private static final String FILE_UUID = "BCDE";
- private static final UserDto ROOT_USER_DTO = new UserDto() {
- {
- setRoot(true);
- }
- }.setLogin("root_user");
- private static final UserDto NON_ROOT_USER_DTO = new UserDto() {
- {
- setRoot(false);
- }
- }.setLogin("regular_user");
@Rule
public DbTester db = DbTester.create(System2.INSTANCE);
public ExpectedException expectedException = ExpectedException.none();
private DbClient dbClient = db.getDbClient();
- private UserDto user;
- private GroupDto groupOfUser;
private TestOrganizationFlags organizationFlags = TestOrganizationFlags.standalone();
private TestDefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
- private OrganizationDto organization;
- private ComponentDto publicProject;
- private ComponentDto privateProject;
-
- @Before
- public void setUp() throws Exception {
- organization = db.organizations().insert();
- publicProject = db.components().insertPublicProject(organization, PUBLIC_PROJECT_UUID);
- privateProject = db.components().insertPrivateProject(organization, dto -> dto.setUuid(PRIVATE_PROJECT_UUID).setProjectUuid(PRIVATE_PROJECT_UUID).setPrivate(true));
- db.components().insertComponent(ComponentTesting.newFileDto(publicProject, null, FILE_UUID).setDbKey(FILE_KEY));
- user = db.users().insertUser(LOGIN);
- groupOfUser = db.users().insertGroup(organization);
- }
@Test
public void anonymous_is_not_logged_in_and_does_not_have_login() {
@Test
public void getGroups_is_empty_if_user_is_not_member_of_any_group() {
+ UserDto user = db.users().insertUser();
assertThat(newUserSession(user).getGroups()).isEmpty();
}
@Test
public void getGroups_returns_the_groups_of_logged_in_user() {
+ UserDto user = db.users().insertUser();
GroupDto group1 = db.users().insertGroup();
GroupDto group2 = db.users().insertGroup();
db.users().insertMember(group1, user);
@Test
public void getGroups_keeps_groups_in_cache() {
+ UserDto user = db.users().insertUser();
GroupDto group1 = db.users().insertGroup();
GroupDto group2 = db.users().insertGroup();
db.users().insertMember(group1, user);
@Test
public void isRoot_is_false_is_flag_root_is_false_on_UserDto() {
- assertThat(newUserSession(ROOT_USER_DTO).isRoot()).isTrue();
- assertThat(newUserSession(NON_ROOT_USER_DTO).isRoot()).isFalse();
+ UserDto root = db.users().insertUser();
+ root = db.users().makeRoot(root);
+ assertThat(newUserSession(root).isRoot()).isTrue();
+
+ UserDto notRoot = db.users().insertUser();
+ assertThat(newUserSession(notRoot).isRoot()).isFalse();
}
@Test
public void checkIsRoot_throws_IPFE_if_flag_root_is_false_on_UserDto() {
- UserSession underTest = newUserSession(NON_ROOT_USER_DTO);
+ UserDto user = db.users().insertUser();
+ UserSession underTest = newUserSession(user);
expectInsufficientPrivilegesForbiddenException();
@Test
public void checkIsRoot_does_not_fail_if_flag_root_is_true_on_UserDto() {
- UserSession underTest = newUserSession(ROOT_USER_DTO);
+ UserDto root = db.users().insertUser();
+ root = db.users().makeRoot(root);
+
+ UserSession underTest = newUserSession(root);
assertThat(underTest.checkIsRoot()).isSameAs(underTest);
}
@Test
public void hasComponentUuidPermission_returns_true_when_flag_root_is_true_on_UserDto_no_matter_if_user_has_project_permission_for_given_uuid() {
- UserSession underTest = newUserSession(ROOT_USER_DTO);
+ UserDto root = db.users().insertUser();
+ root = db.users().makeRoot(root);
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto project = db.components().insertPrivateProject(organization);
+ ComponentDto file = db.components().insertComponent(newFileDto(project));
+
+ UserSession underTest = newUserSession(root);
- assertThat(underTest.hasComponentUuidPermission(UserRole.USER, FILE_UUID)).isTrue();
- assertThat(underTest.hasComponentUuidPermission(UserRole.CODEVIEWER, FILE_UUID)).isTrue();
- assertThat(underTest.hasComponentUuidPermission(UserRole.ADMIN, FILE_UUID)).isTrue();
+ assertThat(underTest.hasComponentUuidPermission(UserRole.USER, file.uuid())).isTrue();
+ assertThat(underTest.hasComponentUuidPermission(UserRole.CODEVIEWER, file.uuid())).isTrue();
+ assertThat(underTest.hasComponentUuidPermission(UserRole.ADMIN, file.uuid())).isTrue();
assertThat(underTest.hasComponentUuidPermission("whatever", "who cares?")).isTrue();
}
@Test
public void checkComponentUuidPermission_succeeds_if_user_has_permission_for_specified_uuid_in_db() {
- UserSession underTest = newUserSession(ROOT_USER_DTO);
+ UserDto root = db.users().insertUser();
+ root = db.users().makeRoot(root);
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto project = db.components().insertPrivateProject(organization);
+ ComponentDto file = db.components().insertComponent(newFileDto(project));
- assertThat(underTest.checkComponentUuidPermission(UserRole.USER, FILE_UUID)).isSameAs(underTest);
+ UserSession underTest = newUserSession(root);
+
+ assertThat(underTest.checkComponentUuidPermission(UserRole.USER, file.uuid())).isSameAs(underTest);
assertThat(underTest.checkComponentUuidPermission("whatever", "who cares?")).isSameAs(underTest);
}
@Test
public void checkComponentUuidPermission_fails_with_FE_when_user_has_not_permission_for_specified_uuid_in_db() {
- addProjectPermissions(privateProject, UserRole.USER);
+ UserDto user = db.users().insertUser();
+ ComponentDto project = db.components().insertPrivateProject();
+ db.users().insertProjectPermissionOnUser(user, UserRole.USER, project);
UserSession session = newUserSession(user);
expectInsufficientPrivilegesForbiddenException();
@Test
public void checkPermission_throws_ForbiddenException_when_user_doesnt_have_the_specified_permission_on_organization() {
OrganizationDto org = db.organizations().insert();
- db.users().insertUser(NON_ROOT_USER_DTO);
+ UserDto user = db.users().insertUser();
expectInsufficientPrivilegesForbiddenException();
- newUserSession(NON_ROOT_USER_DTO).checkPermission(PROVISION_PROJECTS, org);
+ newUserSession(user).checkPermission(PROVISION_PROJECTS, org);
}
@Test
public void checkPermission_succeeds_when_user_has_the_specified_permission_on_organization() {
OrganizationDto org = db.organizations().insert();
- db.users().insertUser(NON_ROOT_USER_DTO);
- db.users().insertPermissionOnUser(org, NON_ROOT_USER_DTO, PROVISIONING);
+ UserDto root = db.users().insertUser();
+ root = db.users().makeRoot(root);
+ db.users().insertPermissionOnUser(org, root, PROVISIONING);
- newUserSession(NON_ROOT_USER_DTO).checkPermission(PROVISION_PROJECTS, org);
+ newUserSession(root).checkPermission(PROVISION_PROJECTS, org);
}
@Test
public void checkPermission_succeeds_when_user_is_root() {
OrganizationDto org = db.organizations().insert();
+ UserDto root = db.users().insertUser();
+ root = db.users().makeRoot(root);
- newUserSession(ROOT_USER_DTO).checkPermission(PROVISION_PROJECTS, org);
+ newUserSession(root).checkPermission(PROVISION_PROJECTS, org);
}
@Test
public void test_hasPermission_on_organization_for_logged_in_user() {
OrganizationDto org = db.organizations().insert();
ComponentDto project = db.components().insertPrivateProject(org);
+ UserDto user = db.users().insertUser();
db.users().insertPermissionOnUser(org, user, PROVISION_PROJECTS);
db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, project);
@Test
public void hasPermission_on_organization_keeps_cache_of_permissions_of_logged_in_user() {
OrganizationDto org = db.organizations().insert();
+ UserDto user = db.users().insertUser();
db.users().insertPermissionOnUser(org, user, PROVISIONING);
UserSession session = newUserSession(user);
@Test
public void hasComponentPermissionByDtoOrUuid_returns_true_for_anonymous_user_for_permissions_USER_and_CODEVIEWER_on_public_projects_without_permissions() {
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto publicProject = db.components().insertPublicProject(organization);
+
ServerUserSession underTest = newAnonymousSession();
assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.USER, publicProject)).isTrue();
@Test
public void hasComponentPermissionByDtoOrUuid_returns_true_for_anonymous_user_for_permissions_USER_and_CODEVIEWER_on_public_projects_with_global_permissions() {
- ServerUserSession underTest = newAnonymousSession();
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto publicProject = db.components().insertPublicProject(organization);
db.users().insertProjectPermissionOnAnyone("p1", publicProject);
+ ServerUserSession underTest = newAnonymousSession();
+
assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.USER, publicProject)).isTrue();
assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.CODEVIEWER, publicProject)).isTrue();
}
@Test
public void hasComponentPermissionByDtoOrUuid_returns_true_for_anonymous_user_for_permissions_USER_and_CODEVIEWER_on_public_projects_with_group_permissions() {
- ServerUserSession underTest = newAnonymousSession();
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto publicProject = db.components().insertPublicProject(organization);
db.users().insertProjectPermissionOnGroup(db.users().insertGroup(organization), "p1", publicProject);
+ ServerUserSession underTest = newAnonymousSession();
+
assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.USER, publicProject)).isTrue();
assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.CODEVIEWER, publicProject)).isTrue();
}
@Test
public void hasComponentPermissionByDtoOrUuid_returns_true_for_anonymous_user_for_permissions_USER_and_CODEVIEWER_on_public_projects_with_user_permissions() {
- ServerUserSession underTest = newAnonymousSession();
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto publicProject = db.components().insertPublicProject(organization);
db.users().insertProjectPermissionOnUser(db.users().insertUser(), "p1", publicProject);
+ ServerUserSession underTest = newAnonymousSession();
+
assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.USER, publicProject)).isTrue();
assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.CODEVIEWER, publicProject)).isTrue();
}
@Test
public void hasComponentPermissionByDtoOrUuid_returns_false_for_authenticated_user_for_permissions_USER_and_CODEVIEWER_on_private_projects_without_permissions() {
+ UserDto user = db.users().insertUser();
+ ComponentDto privateProject = db.components().insertPrivateProject();
+
ServerUserSession underTest = newUserSession(user);
assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.USER, privateProject)).isFalse();
@Test
public void hasComponentPermissionByDtoOrUuid_returns_false_for_authenticated_user_for_permissions_USER_and_CODEVIEWER_on_private_projects_with_group_permissions() {
- ServerUserSession underTest = newUserSession(user);
+ UserDto user = db.users().insertUser();
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto privateProject = db.components().insertPrivateProject(organization);
db.users().insertProjectPermissionOnGroup(db.users().insertGroup(organization), "p1", privateProject);
+ ServerUserSession underTest = newUserSession(user);
+
assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.USER, privateProject)).isFalse();
assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.CODEVIEWER, privateProject)).isFalse();
}
@Test
public void hasComponentPermissionByDtoOrUuid_returns_false_for_authenticated_user_for_permissions_USER_and_CODEVIEWER_on_private_projects_with_user_permissions() {
- ServerUserSession underTest = newUserSession(user);
+ UserDto user = db.users().insertUser();
+ ComponentDto privateProject = db.components().insertPrivateProject();
db.users().insertProjectPermissionOnUser(db.users().insertUser(), "p1", privateProject);
+ ServerUserSession underTest = newUserSession(user);
+
assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.USER, privateProject)).isFalse();
assertThat(hasComponentPermissionByDtoOrUuid(underTest, UserRole.CODEVIEWER, privateProject)).isFalse();
}
@Test
public void hasComponentPermissionByDtoOrUuid_returns_true_for_anonymous_user_for_inserted_permissions_on_group_AnyOne_on_public_projects() {
- ServerUserSession underTest = newAnonymousSession();
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto publicProject = db.components().insertPublicProject(organization);
db.users().insertProjectPermissionOnAnyone("p1", publicProject);
+ ServerUserSession underTest = newAnonymousSession();
+
assertThat(hasComponentPermissionByDtoOrUuid(underTest, "p1", publicProject)).isTrue();
}
@Test
public void hasComponentPermissionByDtoOrUuid_returns_false_for_anonymous_user_for_inserted_permissions_on_group_on_public_projects() {
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto publicProject = db.components().insertPublicProject(organization);
+ GroupDto group = db.users().insertGroup(organization);
+ db.users().insertProjectPermissionOnGroup(group, "p1", publicProject);
+
ServerUserSession underTest = newAnonymousSession();
- db.users().insertProjectPermissionOnGroup(groupOfUser, "p1", publicProject);
assertThat(hasComponentPermissionByDtoOrUuid(underTest, "p1", publicProject)).isFalse();
}
@Test
public void hasComponentPermissionByDtoOrUuid_returns_false_for_anonymous_user_for_inserted_permissions_on_group_on_private_projects() {
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto privateProject = db.components().insertPrivateProject(organization);
+ GroupDto group = db.users().insertGroup(organization);
+ db.users().insertProjectPermissionOnGroup(group, "p1", privateProject);
+
ServerUserSession underTest = newAnonymousSession();
- db.users().insertProjectPermissionOnGroup(groupOfUser, "p1", privateProject);
assertThat(hasComponentPermissionByDtoOrUuid(underTest, "p1", privateProject)).isFalse();
}
@Test
public void hasComponentPermissionByDtoOrUuid_returns_false_for_anonymous_user_for_inserted_permissions_on_user_on_public_projects() {
- ServerUserSession underTest = newAnonymousSession();
+ UserDto user = db.users().insertUser();
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto publicProject = db.components().insertPublicProject(organization);
db.users().insertProjectPermissionOnUser(user, "p1", publicProject);
+ ServerUserSession underTest = newAnonymousSession();
+
assertThat(hasComponentPermissionByDtoOrUuid(underTest, "p1", publicProject)).isFalse();
}
@Test
public void hasComponentPermissionByDtoOrUuid_returns_false_for_anonymous_user_for_inserted_permissions_on_user_on_private_projects() {
+ UserDto user = db.users().insertUser();
+ ComponentDto project = db.components().insertPrivateProject();
+ db.users().insertProjectPermissionOnUser(user, "p1", project);
+
ServerUserSession underTest = newAnonymousSession();
- db.users().insertProjectPermissionOnUser(user, "p1", privateProject);
- assertThat(hasComponentPermissionByDtoOrUuid(underTest, "p1", privateProject)).isFalse();
+ assertThat(hasComponentPermissionByDtoOrUuid(underTest, "p1", project)).isFalse();
}
@Test
public void hasComponentPermissionByDtoOrUuid_returns_true_for_any_project_or_permission_for_root_user() {
- ServerUserSession underTest = newUserSession(ROOT_USER_DTO);
+ UserDto root = db.users().insertUser();
+ root = db.users().makeRoot(root);
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto publicProject = db.components().insertPublicProject(organization);
+
+ ServerUserSession underTest = newUserSession(root);
assertThat(hasComponentPermissionByDtoOrUuid(underTest, "does not matter", publicProject)).isTrue();
}
@Test
public void hasComponentPermissionByDtoOrUuid_keeps_cache_of_permissions_of_logged_in_user() {
+ UserDto user = db.users().insertUser();
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto publicProject = db.components().insertPublicProject(organization);
db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, publicProject);
UserSession underTest = newUserSession(user);
@Test
public void hasComponentPermissionByDtoOrUuid_keeps_cache_of_permissions_of_anonymous_user() {
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto publicProject = db.components().insertPublicProject(organization);
db.users().insertProjectPermissionOnAnyone(UserRole.ADMIN, publicProject);
UserSession underTest = newAnonymousSession();
@Test
public void keepAuthorizedComponents_returns_empty_list_if_no_permissions_are_granted() {
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto publicProject = db.components().insertPublicProject(organization);
+ ComponentDto privateProject = db.components().insertPrivateProject(organization);
+
UserSession underTest = newAnonymousSession();
assertThat(underTest.keepAuthorizedComponents(UserRole.ADMIN, Arrays.asList(privateProject, publicProject))).isEmpty();
@Test
public void keepAuthorizedComponents_filters_components_with_granted_permissions_for_logged_in_user() {
- UserSession underTest = newUserSession(user);
+ UserDto user = db.users().insertUser();
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto publicProject = db.components().insertPublicProject(organization);
+ ComponentDto privateProject = db.components().insertPrivateProject(organization);
db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, privateProject);
+ UserSession underTest = newUserSession(user);
+
assertThat(underTest.keepAuthorizedComponents(UserRole.ISSUE_ADMIN, Arrays.asList(privateProject, publicProject))).isEmpty();
assertThat(underTest.keepAuthorizedComponents(UserRole.ADMIN, Arrays.asList(privateProject, publicProject))).containsExactly(privateProject);
}
@Test
public void keepAuthorizedComponents_filters_components_with_granted_permissions_for_anonymous() {
- UserSession underTest = newAnonymousSession();
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto publicProject = db.components().insertPublicProject(organization);
+ ComponentDto privateProject = db.components().insertPrivateProject(organization);
db.users().insertProjectPermissionOnAnyone(UserRole.ISSUE_ADMIN, publicProject);
+ UserSession underTest = newAnonymousSession();
+
assertThat(underTest.keepAuthorizedComponents(UserRole.ADMIN, Arrays.asList(privateProject, publicProject))).isEmpty();
assertThat(underTest.keepAuthorizedComponents(UserRole.ISSUE_ADMIN, Arrays.asList(privateProject, publicProject))).containsExactly(publicProject);
}
@Test
public void keepAuthorizedComponents_returns_all_specified_components_if_root() {
- user = db.users().makeRoot(user);
- UserSession underTest = newUserSession(user);
+ UserDto root = db.users().insertUser();
+ root = db.users().makeRoot(root);
+ OrganizationDto organization = db.organizations().insert();
+ ComponentDto publicProject = db.components().insertPublicProject(organization);
+ ComponentDto privateProject = db.components().insertPrivateProject(organization);
+
+ UserSession underTest = newUserSession(root);
assertThat(underTest.keepAuthorizedComponents(UserRole.ADMIN, Arrays.asList(privateProject, publicProject)))
.containsExactly(privateProject, publicProject);
@Test
public void keepAuthorizedComponents_on_branches() {
- user = db.users().insertUser();
+ UserDto user = db.users().insertUser();
+ ComponentDto privateProject = db.components().insertPrivateProject();
db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, privateProject);
ComponentDto privateBranchProject = db.components().insertProjectBranch(privateProject);
+
UserSession underTest = newUserSession(user);
assertThat(underTest.keepAuthorizedComponents(UserRole.ADMIN, asList(privateProject, privateBranchProject)))
@Test
public void isSystemAdministrator_returns_true_if_org_feature_is_enabled_and_user_is_root() {
organizationFlags.setEnabled(true);
- user = db.users().makeRoot(user);
- UserSession session = newUserSession(user);
+ UserDto root = db.users().insertUser();
+ root = db.users().makeRoot(root);
+
+ UserSession session = newUserSession(root);
assertThat(session.isSystemAdministrator()).isTrue();
}
@Test
public void isSystemAdministrator_returns_false_if_org_feature_is_enabled_and_user_is_not_root() {
organizationFlags.setEnabled(true);
- user = db.users().makeNotRoot(user);
+ UserDto user = db.users().insertUser();
+
UserSession session = newUserSession(user);
assertThat(session.isSystemAdministrator()).isFalse();
@Test
public void isSystemAdministrator_returns_false_if_org_feature_is_enabled_and_user_is_administrator_of_default_organization() {
organizationFlags.setEnabled(true);
- user = db.users().makeNotRoot(user);
+ UserDto user = db.users().insertUser();
db.users().insertPermissionOnUser(db.getDefaultOrganization(), user, SYSTEM_ADMIN);
+
UserSession session = newUserSession(user);
assertThat(session.isSystemAdministrator()).isFalse();
@Test
public void isSystemAdministrator_returns_true_if_org_feature_is_disabled_and_user_is_administrator_of_default_organization() {
organizationFlags.setEnabled(false);
- user = db.users().makeNotRoot(user);
+ UserDto user = db.users().insertUser();
db.users().insertPermissionOnUser(db.getDefaultOrganization(), user, SYSTEM_ADMIN);
+
UserSession session = newUserSession(user);
assertThat(session.isSystemAdministrator()).isTrue();
@Test
public void isSystemAdministrator_returns_false_if_org_feature_is_disabled_and_user_is_not_administrator_of_default_organization() {
organizationFlags.setEnabled(true);
- user = db.users().makeNotRoot(user);
+ UserDto user = db.users().insertUser();
db.users().insertPermissionOnUser(db.getDefaultOrganization(), user, PROVISIONING);
+
UserSession session = newUserSession(user);
assertThat(session.isSystemAdministrator()).isFalse();
@Test
public void keep_isSystemAdministrator_flag_in_cache() {
organizationFlags.setEnabled(false);
- user = db.users().makeNotRoot(user);
+ UserDto user = db.users().insertUser();
db.users().insertPermissionOnUser(db.getDefaultOrganization(), user, SYSTEM_ADMIN);
+
UserSession session = newUserSession(user);
session.checkIsSystemAdministrator();
@Test
public void checkIsSystemAdministrator_succeeds_if_system_administrator() {
organizationFlags.setEnabled(true);
- user = db.users().makeRoot(user);
- UserSession session = newUserSession(user);
+ UserDto root = db.users().insertUser();
+ root = db.users().makeRoot(root);
+
+ UserSession session = newUserSession(root);
session.checkIsSystemAdministrator();
}
@Test
public void checkIsSystemAdministrator_throws_ForbiddenException_if_not_system_administrator() {
organizationFlags.setEnabled(true);
- user = db.users().makeNotRoot(user);
+ UserDto user = db.users().insertUser();
+
UserSession session = newUserSession(user);
expectedException.expect(ForbiddenException.class);
@Test
public void hasComponentPermission_on_branch_checks_permissions_of_its_project() {
+ UserDto user = db.users().insertUser();
+ ComponentDto privateProject = db.components().insertPrivateProject();
ComponentDto branch = db.components().insertProjectBranch(privateProject, b -> b.setKey("feature/foo"));
ComponentDto fileInBranch = db.components().insertComponent(newChildComponent("fileUuid", branch, branch));
db.users().insertProjectPermissionOnUser(user, "p1", privateProject);
UserSession underTest = newUserSession(user);
+
assertThat(hasComponentPermissionByDtoOrUuid(underTest, "p1", privateProject)).isTrue();
assertThat(hasComponentPermissionByDtoOrUuid(underTest, "p1", branch)).isTrue();
assertThat(hasComponentPermissionByDtoOrUuid(underTest, "p1", fileInBranch)).isTrue();
return newUserSession(null);
}
- private void addProjectPermissions(ComponentDto component, String... permissions) {
- addPermissions(component, permissions);
- }
-
- private void addPermissions(@Nullable ComponentDto component, String... permissions) {
- for (String permission : permissions) {
- if (component == null) {
- db.users().insertPermissionOnUser(user, OrganizationPermission.fromKey(permission));
- } else {
- db.users().insertProjectPermissionOnUser(user, permission, component);
- }
- }
- }
-
private void expectInsufficientPrivilegesForbiddenException() {
expectedException.expect(ForbiddenException.class);
expectedException.expectMessage("Insufficient privileges");
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.user.GroupDto;
-import org.sonar.db.user.GroupTesting;
import org.sonar.db.user.UserDto;
import org.sonar.server.authentication.LocalAuthentication;
import org.sonar.server.authentication.LocalAuthentication.HashMethod;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.sonar.core.config.CorePropertyDefinitions.ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS;
-import static org.sonar.db.user.UserTesting.newDisabledUser;
import static org.sonar.db.user.UserTesting.newLocalUser;
import static org.sonar.server.user.ExternalIdentity.SQ_AUTHORITY;
.setPassword("PASSWORD")
.setScmAccounts(ImmutableList.of("u1", "u_1", "User 1"))
.build(), u -> {
- });
+ });
assertThat(dto.getId()).isNotNull();
assertThat(dto.getLogin()).isEqualTo("user");
.setLogin("us")
.setName("User")
.build(), u -> {
- });
+ });
UserDto dto = dbClient.userDao().selectByLogin(session, "us");
assertThat(dto.getId()).isNotNull();
.setName("User")
.setPassword("password")
.build(), u -> {
- });
+ });
UserDto dto = dbClient.userDao().selectByLogin(session, "user");
- assertThat(dto.getExternalIdentity()).isEqualTo("user");
+ assertThat(dto.getExternalLogin()).isEqualTo("user");
assertThat(dto.getExternalIdentityProvider()).isEqualTo("sonarqube");
assertThat(dto.isLocal()).isTrue();
}
underTest.createAndCommit(db.getSession(), NewUser.builder()
.setLogin("user")
.setName("User")
- .setExternalIdentity(new ExternalIdentity("github", "github-user"))
+ .setExternalIdentity(new ExternalIdentity("github", "github-user", "ABCD"))
.build(), u -> {
- });
+ });
UserDto dto = dbClient.userDao().selectByLogin(session, "user");
assertThat(dto.isLocal()).isFalse();
- assertThat(dto.getExternalIdentity()).isEqualTo("github-user");
+ assertThat(dto.getExternalId()).isEqualTo("ABCD");
+ assertThat(dto.getExternalLogin()).isEqualTo("github-user");
assertThat(dto.getExternalIdentityProvider()).isEqualTo("github");
assertThat(dto.getCryptedPassword()).isNull();
assertThat(dto.getSalt()).isNull();
underTest.createAndCommit(db.getSession(), NewUser.builder()
.setLogin("user")
.setName("User")
- .setExternalIdentity(new ExternalIdentity(SQ_AUTHORITY, "user"))
+ .setExternalIdentity(new ExternalIdentity(SQ_AUTHORITY, "user", null))
.build(), u -> {
- });
+ });
UserDto dto = dbClient.userDao().selectByLogin(session, "user");
assertThat(dto.isLocal()).isFalse();
- assertThat(dto.getExternalIdentity()).isEqualTo("user");
+ assertThat(dto.getExternalId()).isEqualTo("user");
+ assertThat(dto.getExternalLogin()).isEqualTo("user");
assertThat(dto.getExternalIdentityProvider()).isEqualTo("sonarqube");
assertThat(dto.getCryptedPassword()).isNull();
assertThat(dto.getSalt()).isNull();
.setPassword("password")
.setScmAccounts(asList("u1", "", null))
.build(), u -> {
- });
+ });
assertThat(dbClient.userDao().selectByLogin(session, "user").getScmAccountsAsList()).containsOnly("u1");
}
.setPassword("password")
.setScmAccounts(asList(""))
.build(), u -> {
- });
+ });
assertThat(dbClient.userDao().selectByLogin(session, "user").getScmAccounts()).isNull();
}
.setPassword("password")
.setScmAccounts(asList("u1", "u1"))
.build(), u -> {
- });
+ });
assertThat(dbClient.userDao().selectByLogin(session, "user").getScmAccountsAsList()).containsOnly("u1");
}
.setLogin("user")
.setName("User")
.build(), u -> {
- });
+ });
assertThat(dbClient.userDao().selectByLogin(session, "user").isOnboarded()).isTrue();
}
.setLogin("user")
.setName("User")
.build(), u -> {
- });
+ });
assertThat(dbClient.userDao().selectByLogin(session, "user").isOnboarded()).isFalse();
}
.setEmail("user@mail.com")
.setPassword("PASSWORD")
.build(), u -> {
- }, otherUser);
+ }, otherUser);
- assertThat(es.getIds(UserIndexDefinition.INDEX_TYPE_USER)).containsExactlyInAnyOrder(created.getLogin(), otherUser.getLogin());
+ assertThat(es.getIds(UserIndexDefinition.INDEX_TYPE_USER)).containsExactlyInAnyOrder(created.getUuid(), otherUser.getUuid());
}
@Test
.setEmail("marius@mail.com")
.setPassword("password")
.build(), u -> {
- });
+ });
}
@Test
.setEmail("marius@mail.com")
.setPassword("password")
.build(), u -> {
- });
+ });
}
@Test
.setEmail("marius@mail.com")
.setPassword("password")
.build(), u -> {
- });
+ });
}
@Test
.setEmail("marius@mail.com")
.setPassword("password")
.build(), u -> {
- });
+ });
}
@Test
.setEmail("marius@mail.com")
.setPassword("password")
.build(), u -> {
- });
+ });
}
@Test
.setEmail("marius@mail.com")
.setPassword("password")
.build(), u -> {
- });
+ });
}
@Test
.setEmail("marius@mail.com")
.setPassword("password")
.build(), u -> {
- });
+ });
}
@Test
.setEmail(Strings.repeat("m", 101))
.setPassword("password")
.build(), u -> {
- });
+ });
}
@Test
.setEmail("marius@mail.com")
.setPassword("")
.build(), u -> {
- });
+ });
fail();
} catch (BadRequestException e) {
assertThat(e.errors()).hasSize(3);
.setPassword("password")
.setScmAccounts(asList("jo"))
.build(), u -> {
- });
+ });
}
@Test
.setPassword("password")
.setScmAccounts(asList("john@email.com"))
.build(), u -> {
- });
+ });
}
@Test
.setPassword("password2")
.setScmAccounts(asList(DEFAULT_LOGIN))
.build(), u -> {
- });
+ });
}
@Test
.setPassword("password2")
.setScmAccounts(asList("marius2@mail.com"))
.build(), u -> {
+ });
+ }
+
+ @Test
+ public void fail_to_create_user_when_login_already_exists() {
+ createDefaultGroup();
+ UserDto existingUser = db.users().insertUser(u -> u.setLogin("existing_login"));
+
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("A user with login 'existing_login' already exists");
+
+ underTest.createAndCommit(db.getSession(), NewUser.builder()
+ .setLogin(existingUser.getLogin())
+ .setName("User")
+ .setPassword("PASSWORD")
+ .build(), 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 -> {
});
}
.setPassword("password")
.setScmAccounts(asList("u1", "u_1"))
.build(), u -> {
- });
+ });
verify(newUserNotifier).onNewUser(newUserHandler.capture());
assertThat(newUserHandler.getValue().getLogin()).isEqualTo("user");
.setEmail("user@mail.com")
.setPassword("password")
.build(), u -> {
- });
+ });
Multimap<String, String> groups = dbClient.groupMembershipDao().selectGroupsByLogins(session, asList("user"));
assertThat(groups.get("user")).containsOnly(defaultGroup.getName());
.setEmail("user@mail.com")
.setPassword("password")
.build(), u -> {
- });
+ });
Multimap<String, String> groups = dbClient.groupMembershipDao().selectGroupsByLogins(session, asList("user"));
assertThat(groups.get("user")).isEmpty();
.setPassword("password")
.setScmAccounts(asList("u1", "u_1"))
.build(), u -> {
- });
+ });
}
@Test
.setEmail("user@mail.com")
.setPassword("PASSWORD")
.build(), u -> {
- });
+ });
verify(organizationCreation).createForUser(any(DbSession.class), eq(dto));
}
.setEmail("user@mail.com")
.setPassword("PASSWORD")
.build(), u -> {
- });
+ });
assertThat(dbClient.organizationMemberDao().select(db.getSession(), defaultOrganizationProvider.get().getUuid(), dto.getId())).isPresent();
}
.setEmail("user@mail.com")
.setPassword("PASSWORD")
.build(), u -> {
- });
-
- assertThat(dbClient.organizationMemberDao().select(db.getSession(), defaultOrganizationProvider.get().getUuid(), dto.getId())).isNotPresent();
- }
-
- @Test
- public void reactivate_user_when_creating_user_with_existing_login() {
- UserDto user = db.users().insertUser(newDisabledUser(DEFAULT_LOGIN)
- .setLocal(false));
- createDefaultGroup();
-
- UserDto dto = underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin(DEFAULT_LOGIN)
- .setName("Marius2")
- .setEmail("marius2@mail.com")
- .setPassword("password2")
- .build(), u -> {
- });
- session.commit();
-
- assertThat(dto.isActive()).isTrue();
- assertThat(dto.getName()).isEqualTo("Marius2");
- assertThat(dto.getEmail()).isEqualTo("marius2@mail.com");
- assertThat(dto.getScmAccounts()).isNull();
- assertThat(dto.isLocal()).isTrue();
-
- assertThat(dto.getSalt()).isNull();
- assertThat(dto.getHashMethod()).isEqualTo(HashMethod.BCRYPT.name());
- assertThat(dto.getCryptedPassword()).isNotNull().isNotEqualTo("650d2261c98361e2f67f90ce5c65a95e7d8ea2fg");
- assertThat(dto.getCreatedAt()).isEqualTo(user.getCreatedAt());
- assertThat(dto.getUpdatedAt()).isGreaterThan(user.getCreatedAt());
-
- assertThat(dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN).isActive()).isTrue();
- }
-
- @Test
- public void reactivate_user_not_having_password() {
- UserDto user = db.users().insertUser(newDisabledUser("marius").setName("Marius").setEmail("marius@lesbronzes.fr")
- .setSalt(null)
- .setCryptedPassword(null));
- createDefaultGroup();
-
- UserDto dto = underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin(DEFAULT_LOGIN)
- .setName("Marius2")
- .setEmail("marius2@mail.com")
- .build(), u -> {
- });
- session.commit();
-
- assertThat(dto.isActive()).isTrue();
- assertThat(dto.getName()).isEqualTo("Marius2");
- assertThat(dto.getEmail()).isEqualTo("marius2@mail.com");
- assertThat(dto.getScmAccounts()).isNull();
-
- assertThat(dto.getSalt()).isNull();
- assertThat(dto.getCryptedPassword()).isNull();
- assertThat(dto.getCreatedAt()).isEqualTo(user.getCreatedAt());
- assertThat(dto.getUpdatedAt()).isGreaterThan(user.getCreatedAt());
- }
-
- @Test
- public void reactivate_user_with_external_provider() {
- db.users().insertUser(newDisabledUser(DEFAULT_LOGIN)
- .setLocal(true));
- createDefaultGroup();
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin(DEFAULT_LOGIN)
- .setName("Marius2")
- .setExternalIdentity(new ExternalIdentity("github", "john"))
- .build(), u -> {
- });
- session.commit();
-
- UserDto dto = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN);
- assertThat(dto.isLocal()).isFalse();
- assertThat(dto.getExternalIdentity()).isEqualTo("john");
- assertThat(dto.getExternalIdentityProvider()).isEqualTo("github");
- }
-
- @Test
- public void reactivate_user_with_local_provider() {
- db.users().insertUser(newDisabledUser(DEFAULT_LOGIN)
- .setLocal(true));
- createDefaultGroup();
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin(DEFAULT_LOGIN)
- .setName("Marius2")
- .setPassword("password")
- .build(), u -> {
- });
- session.commit();
-
- UserDto dto = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN);
- assertThat(dto.isLocal()).isTrue();
- assertThat(dto.getExternalIdentity()).isEqualTo(DEFAULT_LOGIN);
- assertThat(dto.getExternalIdentityProvider()).isEqualTo("sonarqube");
- }
-
- @Test
- public void fail_to_reactivate_user_if_not_disabled() {
- db.users().insertUser(newLocalUser("marius", "Marius", "marius@lesbronzes.fr"));
- createDefaultGroup();
-
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("An active user with login 'marius' already exists");
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin(DEFAULT_LOGIN)
- .setName("Marius2")
- .setEmail("marius2@mail.com")
- .setPassword("password2")
- .build(), u -> {
- });
- }
-
- @Test
- public void associate_default_groups_when_reactivating_user_and_organizations_are_disabled() {
- organizationFlags.setEnabled(false);
- UserDto userDto = db.users().insertUser(newDisabledUser(DEFAULT_LOGIN)
- .setLocal(true));
- db.organizations().insertForUuid("org1");
- GroupDto groupDto = db.users().insertGroup(GroupTesting.newGroupDto().setName("sonar-devs").setOrganizationUuid("org1"));
- db.users().insertMember(groupDto, userDto);
- GroupDto defaultGroup = createDefaultGroup();
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin(DEFAULT_LOGIN)
- .setName("Marius2")
- .setEmail("marius2@mail.com")
- .setPassword("password2")
- .build(), u -> {
- });
- session.commit();
-
- Multimap<String, String> groups = dbClient.groupMembershipDao().selectGroupsByLogins(session, asList(DEFAULT_LOGIN));
- assertThat(groups.get(DEFAULT_LOGIN).stream().anyMatch(g -> g.equals(defaultGroup.getName()))).isTrue();
- }
-
- @Test
- public void does_not_associate_default_groups_when_reactivating_user_and_organizations_are_enabled() {
- organizationFlags.setEnabled(true);
- UserDto userDto = db.users().insertUser(newDisabledUser(DEFAULT_LOGIN)
- .setLocal(true));
- db.organizations().insertForUuid("org1");
- GroupDto groupDto = db.users().insertGroup(GroupTesting.newGroupDto().setName("sonar-devs").setOrganizationUuid("org1"));
- db.users().insertMember(groupDto, userDto);
- GroupDto defaultGroup = createDefaultGroup();
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin(DEFAULT_LOGIN)
- .setName("Marius2")
- .setEmail("marius2@mail.com")
- .setPassword("password2")
- .build(), u -> {
- });
- session.commit();
-
- Multimap<String, String> groups = dbClient.groupMembershipDao().selectGroupsByLogins(session, asList(DEFAULT_LOGIN));
- assertThat(groups.get(DEFAULT_LOGIN).stream().anyMatch(g -> g.equals(defaultGroup.getName()))).isFalse();
- }
-
- @Test
- public void add_user_as_member_of_default_organization_when_reactivating_user_and_organizations_are_disabled() {
- organizationFlags.setEnabled(false);
- db.users().insertUser(newDisabledUser(DEFAULT_LOGIN));
- createDefaultGroup();
-
- UserDto dto = underTest.createAndCommit(db.getSession(), NewUser.builder().setLogin(DEFAULT_LOGIN).setName("Name").build(), u -> {
- });
- session.commit();
-
- assertThat(dbClient.organizationMemberDao().select(db.getSession(), defaultOrganizationProvider.get().getUuid(), dto.getId())).isPresent();
- }
-
- @Test
- public void does_not_add_user_as_member_of_default_organization_when_reactivating_user_and_organizations_are_enabled() {
- organizationFlags.setEnabled(true);
- db.users().insertUser(newDisabledUser(DEFAULT_LOGIN));
- createDefaultGroup();
-
- UserDto dto = underTest.createAndCommit(db.getSession(), NewUser.builder().setLogin(DEFAULT_LOGIN).setName("Name").build(), u -> {
- });
- session.commit();
+ });
assertThat(dbClient.organizationMemberDao().select(db.getSession(), defaultOrganizationProvider.get().getUuid(), dto.getId())).isNotPresent();
}
- @Test
- public void reactivate_not_onboarded_user_if_onboarding_setting_is_set_to_false() {
- settings.setProperty(ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS, false);
- UserDto user = db.users().insertUser(u -> u
- .setActive(false)
- .setOnboarded(false));
- createDefaultGroup();
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin(user.getLogin())
- .setName("name")
- .build(), u -> {
- });
-
- assertThat(dbClient.userDao().selectByLogin(session, user.getLogin()).isOnboarded()).isTrue();
- }
-
- @Test
- public void reactivate_onboarded_user_if_onboarding_setting_is_set_to_true() {
- settings.setProperty(ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS, true);
- UserDto user = db.users().insertUser(u -> u
- .setActive(false)
- .setOnboarded(true));
- createDefaultGroup();
-
- underTest.createAndCommit(db.getSession(), NewUser.builder()
- .setLogin(user.getLogin())
- .setName("name")
- .build(), u -> {
- });
-
- assertThat(dbClient.userDao().selectByLogin(session, user.getLogin()).isOnboarded()).isFalse();
- }
-
private GroupDto createDefaultGroup() {
return db.users().insertDefaultGroup(db.getDefaultOrganization());
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.user;
+
+import com.google.common.collect.Multimap;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.user.GroupDto;
+import org.sonar.db.user.GroupTesting;
+import org.sonar.db.user.UserDto;
+import org.sonar.server.authentication.LocalAuthentication;
+import org.sonar.server.authentication.LocalAuthentication.HashMethod;
+import org.sonar.server.es.EsTester;
+import org.sonar.server.organization.DefaultOrganizationProvider;
+import org.sonar.server.organization.OrganizationCreation;
+import org.sonar.server.organization.TestDefaultOrganizationProvider;
+import org.sonar.server.organization.TestOrganizationFlags;
+import org.sonar.server.user.index.UserIndexer;
+import org.sonar.server.usergroups.DefaultGroupFinder;
+
+import static java.lang.String.format;
+import static java.util.Collections.singletonList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.sonar.core.config.CorePropertyDefinitions.ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS;
+
+public class UserUpdaterReactivateTest {
+
+ private System2 system2 = new AlwaysIncreasingSystem2();
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ @Rule
+ public EsTester es = EsTester.create();
+
+ @Rule
+ public DbTester db = DbTester.create(system2);
+
+ private DbClient dbClient = db.getDbClient();
+ private NewUserNotifier newUserNotifier = mock(NewUserNotifier.class);
+ private DbSession session = db.getSession();
+ private UserIndexer userIndexer = new UserIndexer(dbClient, es.client());
+ private OrganizationCreation organizationCreation = mock(OrganizationCreation.class);
+ private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
+ private TestOrganizationFlags organizationFlags = TestOrganizationFlags.standalone();
+ private MapSettings settings = new MapSettings();
+ private LocalAuthentication localAuthentication = new LocalAuthentication(db.getDbClient());
+ private UserUpdater underTest = new UserUpdater(newUserNotifier, dbClient, userIndexer, organizationFlags, defaultOrganizationProvider, organizationCreation,
+ new DefaultGroupFinder(dbClient), settings.asConfig(), localAuthentication);
+
+ @Test
+ public void reactivate_user() {
+ UserDto user = db.users().insertUser(u -> u.setActive(false));
+ createDefaultGroup();
+
+ underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder()
+ .setLogin("marius")
+ .setName("Marius2")
+ .setEmail("marius2@mail.com")
+ .setPassword("password2")
+ .build(),
+ u -> {
+ });
+
+ UserDto reloaded = dbClient.userDao().selectByUuid(session, user.getUuid());
+ assertThat(reloaded.isActive()).isTrue();
+ assertThat(reloaded.getLogin()).isEqualTo("marius");
+ assertThat(reloaded.getName()).isEqualTo("Marius2");
+ assertThat(reloaded.getEmail()).isEqualTo("marius2@mail.com");
+ assertThat(reloaded.getScmAccounts()).isNull();
+ assertThat(reloaded.isLocal()).isTrue();
+ assertThat(reloaded.getSalt()).isNull();
+ assertThat(reloaded.getHashMethod()).isEqualTo(HashMethod.BCRYPT.name());
+ assertThat(reloaded.getCryptedPassword()).isNotNull().isNotEqualTo("650d2261c98361e2f67f90ce5c65a95e7d8ea2fg");
+ assertThat(reloaded.getCreatedAt()).isEqualTo(user.getCreatedAt());
+ assertThat(reloaded.getUpdatedAt()).isGreaterThan(user.getCreatedAt());
+ }
+
+ @Test
+ public void reactivate_user_not_having_password() {
+ UserDto user = db.users().insertDisabledUser(u -> u.setSalt(null).setCryptedPassword(null));
+ createDefaultGroup();
+
+ UserDto dto = underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder()
+ .setLogin(user.getLogin())
+ .setName(user.getName())
+ .build(),
+ u -> {
+ });
+
+ assertThat(dto.isActive()).isTrue();
+ assertThat(dto.getName()).isEqualTo(user.getName());
+ assertThat(dto.getScmAccounts()).isNull();
+ assertThat(dto.getSalt()).isNull();
+ assertThat(dto.getCryptedPassword()).isNull();
+ assertThat(dto.getCreatedAt()).isEqualTo(user.getCreatedAt());
+ assertThat(dto.getUpdatedAt()).isGreaterThan(user.getCreatedAt());
+ }
+
+ @Test
+ public void reactivate_user_with_external_provider() {
+ UserDto user = db.users().insertDisabledUser(u -> u.setLocal(true));
+ 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 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 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 fail_to_reactivate_user_if_active() {
+ UserDto user = db.users().insertUser();
+ createDefaultGroup();
+
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage(format("An active user with login '%s' already exists", user.getLogin()));
+
+ underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder()
+ .setLogin(user.getLogin())
+ .setName(user.getName())
+ .build(), u -> {
+ });
+ }
+
+ @Test
+ public void associate_default_groups_when_reactivating_user_and_organizations_are_disabled() {
+ organizationFlags.setEnabled(false);
+ UserDto userDto = db.users().insertDisabledUser();
+ db.organizations().insertForUuid("org1");
+ GroupDto groupDto = db.users().insertGroup(GroupTesting.newGroupDto().setName("sonar-devs").setOrganizationUuid("org1"));
+ db.users().insertMember(groupDto, userDto);
+ GroupDto defaultGroup = createDefaultGroup();
+
+ underTest.reactivateAndCommit(db.getSession(), userDto, NewUser.builder()
+ .setLogin(userDto.getLogin())
+ .setName(userDto.getName())
+ .build(), u -> {
+ });
+ session.commit();
+
+ Multimap<String, String> groups = dbClient.groupMembershipDao().selectGroupsByLogins(session, singletonList(userDto.getLogin()));
+ assertThat(groups.get(userDto.getLogin()).stream().anyMatch(g -> g.equals(defaultGroup.getName()))).isTrue();
+ }
+
+ @Test
+ public void does_not_associate_default_groups_when_reactivating_user_and_organizations_are_enabled() {
+ organizationFlags.setEnabled(true);
+ UserDto userDto = db.users().insertDisabledUser();
+ db.organizations().insertForUuid("org1");
+ GroupDto groupDto = db.users().insertGroup(GroupTesting.newGroupDto().setName("sonar-devs").setOrganizationUuid("org1"));
+ db.users().insertMember(groupDto, userDto);
+ GroupDto defaultGroup = createDefaultGroup();
+
+ underTest.reactivateAndCommit(db.getSession(), userDto, NewUser.builder()
+ .setLogin(userDto.getLogin())
+ .setName(userDto.getName())
+ .build(), u -> {
+ });
+ session.commit();
+
+ Multimap<String, String> groups = dbClient.groupMembershipDao().selectGroupsByLogins(session, singletonList(userDto.getLogin()));
+ assertThat(groups.get(userDto.getLogin()).stream().anyMatch(g -> g.equals(defaultGroup.getName()))).isFalse();
+ }
+
+ @Test
+ public void add_user_as_member_of_default_organization_when_reactivating_user_and_organizations_are_disabled() {
+ organizationFlags.setEnabled(false);
+ UserDto user = db.users().insertDisabledUser();
+ createDefaultGroup();
+
+ UserDto dto = underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder().setLogin(user.getLogin()).setName(user.getName()).build(), u -> {
+ });
+
+ assertThat(dbClient.organizationMemberDao().select(db.getSession(), defaultOrganizationProvider.get().getUuid(), dto.getId())).isPresent();
+ }
+
+ @Test
+ public void does_not_add_user_as_member_of_default_organization_when_reactivating_user_and_organizations_are_enabled() {
+ organizationFlags.setEnabled(true);
+ UserDto user = db.users().insertDisabledUser();
+ createDefaultGroup();
+
+ UserDto dto = underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder().setLogin(user.getLogin()).setName(user.getName()).build(), u -> {
+ });
+
+ assertThat(dbClient.organizationMemberDao().select(db.getSession(), defaultOrganizationProvider.get().getUuid(), dto.getId())).isNotPresent();
+ }
+
+ @Test
+ public void reactivate_not_onboarded_user_if_onboarding_setting_is_set_to_false() {
+ settings.setProperty(ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS, false);
+ UserDto user = db.users().insertDisabledUser(u -> u.setOnboarded(false));
+ createDefaultGroup();
+
+ underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder()
+ .setLogin(user.getLogin())
+ .setName(user.getName())
+ .build(), u -> {
+ });
+
+ assertThat(dbClient.userDao().selectByLogin(session, user.getLogin()).isOnboarded()).isTrue();
+ }
+
+ @Test
+ public void reactivate_onboarded_user_if_onboarding_setting_is_set_to_true() {
+ settings.setProperty(ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS, true);
+ UserDto user = db.users().insertDisabledUser(u -> u.setOnboarded(true));
+ createDefaultGroup();
+
+ underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder()
+ .setLogin(user.getLogin())
+ .setName(user.getName())
+ .build(), u -> {
+ });
+
+ assertThat(dbClient.userDao().selectByLogin(session, user.getLogin()).isOnboarded()).isFalse();
+ }
+
+ @Test
+ public void fail_to_reactivate_user_when_login_already_exists() {
+ createDefaultGroup();
+ UserDto user = db.users().insertUser(u -> u.setActive(false));
+ UserDto existingUser = db.users().insertUser(u -> u.setLogin("existing_login"));
+
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("A user with login 'existing_login' already exists");
+
+ underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder()
+ .setLogin(existingUser.getLogin())
+ .setName("Marius2")
+ .setPassword("password2")
+ .build(),
+ u -> {
+ });
+ }
+
+ @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 -> {
+ });
+ }
+
+ private GroupDto createDefaultGroup() {
+ return db.users().insertDefaultGroup(db.getDefaultOrganization());
+ }
+
+}
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
-import org.mockito.ArgumentCaptor;
import org.sonar.api.config.internal.MapSettings;
-import org.sonar.api.platform.NewUserHandler;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.property.PropertyDto;
+import org.sonar.db.property.PropertyQuery;
import org.sonar.db.user.GroupDto;
import org.sonar.db.user.UserDto;
import org.sonar.db.user.UserTesting;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.tuple;
import static org.assertj.core.data.MapEntry.entry;
import static org.mockito.Mockito.mock;
+import static org.sonar.api.CoreProperties.DEFAULT_ISSUE_ASSIGNEE;
import static org.sonar.db.user.UserTesting.newLocalUser;
import static org.sonar.db.user.UserTesting.newUserDto;
@Test
public void update_user() {
UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@email.com")
- .setScmAccounts(asList("ma", "marius33"))
- .setSalt("79bd6a8e79fb8c76ac8b121cc7e8e11ad1af8365")
- .setCryptedPassword("650d2261c98361e2f67f90ce5c65a95e7d8ea2fg"));
+ .setScmAccounts(asList("ma", "marius33")));
createDefaultGroup();
+ userIndexer.indexOnStartup(null);
- underTest.updateAndCommit(session, UpdateUser.create(DEFAULT_LOGIN)
+ underTest.updateAndCommit(session, user, new UpdateUser()
.setName("Marius2")
.setEmail("marius2@mail.com")
- .setPassword("password2")
- .setScmAccounts(asList("ma2")), u -> {
- });
+ .setScmAccounts(singletonList("ma2")), u -> {
+ });
UserDto updatedUser = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN);
assertThat(updatedUser.isActive()).isTrue();
assertThat(updatedUser.getName()).isEqualTo("Marius2");
assertThat(updatedUser.getEmail()).isEqualTo("marius2@mail.com");
assertThat(updatedUser.getScmAccountsAsList()).containsOnly("ma2");
-
- assertThat(updatedUser.getSalt()).isNotEqualTo(user.getSalt());
- assertThat(updatedUser.getCryptedPassword()).isNotEqualTo(user.getCryptedPassword());
assertThat(updatedUser.getCreatedAt()).isEqualTo(user.getCreatedAt());
assertThat(updatedUser.getUpdatedAt()).isGreaterThan(user.getCreatedAt());
UserDto user = db.users().insertUser(UserTesting.newExternalUser(DEFAULT_LOGIN, "Marius", "marius@email.com"));
createDefaultGroup();
- underTest.updateAndCommit(session, UpdateUser.create(DEFAULT_LOGIN)
+ underTest.updateAndCommit(session, user, new UpdateUser()
.setName("Marius2")
.setEmail("marius2@email.com")
- .setExternalIdentity(new ExternalIdentity("github", "john")), u -> {
- });
+ .setExternalIdentity(new ExternalIdentity("github", "john", "ABCD")), u -> {
+ });
UserDto dto = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN);
- assertThat(dto.getExternalIdentity()).isEqualTo("john");
+ assertThat(dto.getExternalId()).isEqualTo("ABCD");
+ assertThat(dto.getExternalLogin()).isEqualTo("john");
assertThat(dto.getExternalIdentityProvider()).isEqualTo("github");
assertThat(dto.getUpdatedAt()).isGreaterThan(user.getCreatedAt());
}
UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@email.com"));
createDefaultGroup();
- underTest.updateAndCommit(session, UpdateUser.create(DEFAULT_LOGIN)
+ underTest.updateAndCommit(session, user, new UpdateUser()
.setName("Marius2")
.setEmail("marius2@email.com")
- .setExternalIdentity(new ExternalIdentity("github", "john")), u -> {
- });
+ .setExternalIdentity(new ExternalIdentity("github", "john", "ABCD")), u -> {
+ });
UserDto dto = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN);
- assertThat(dto.getExternalIdentity()).isEqualTo("john");
+ assertThat(dto.getExternalId()).isEqualTo("ABCD");
+ assertThat(dto.getExternalLogin()).isEqualTo("john");
assertThat(dto.getExternalIdentityProvider()).isEqualTo("github");
// Password must be removed
assertThat(dto.getCryptedPassword()).isNull();
}
@Test
- public void reactivate_user_on_update() {
+ public void update_user_with_scm_accounts_containing_blank_entry() {
UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr")
- .setScmAccounts(asList("ma", "marius33"))
- .setSalt("salt")
- .setCryptedPassword("crypted password"));
+ .setScmAccounts(asList("ma", "marius33")));
createDefaultGroup();
- underTest.updateAndCommit(session, UpdateUser.create(DEFAULT_LOGIN)
+ underTest.updateAndCommit(session, user, new UpdateUser()
.setName("Marius2")
.setEmail("marius2@mail.com")
.setPassword("password2")
- .setScmAccounts(asList("ma2")), u -> {
- });
+ .setScmAccounts(asList("ma2", "", null)), u -> {
+ });
UserDto dto = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN);
- assertThat(dto.isActive()).isTrue();
- assertThat(dto.getName()).isEqualTo("Marius2");
- assertThat(dto.getEmail()).isEqualTo("marius2@mail.com");
assertThat(dto.getScmAccountsAsList()).containsOnly("ma2");
+ }
+
+ @Test
+ public void update_only_login() {
+ UserDto oldUser = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr"));
+ createDefaultGroup();
+
+ underTest.updateAndCommit(session, oldUser, new UpdateUser()
+ .setLogin("new_login"), u -> {
+ });
- assertThat(dto.getSalt()).isNotEqualTo(user.getSalt());
- assertThat(dto.getCryptedPassword()).isNotEqualTo(user.getCryptedPassword());
- assertThat(dto.getCreatedAt()).isEqualTo(user.getCreatedAt());
- assertThat(dto.getUpdatedAt()).isGreaterThan(user.getUpdatedAt());
+ assertThat(dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN)).isNull();
+ UserDto dto = dbClient.userDao().selectByUuid(session, oldUser.getUuid());
+ assertThat(dto.getLogin()).isEqualTo("new_login");
+ // Following fields has not changed
+ assertThat(dto.getName()).isEqualTo(oldUser.getName());
+ assertThat(dto.getEmail()).isEqualTo(oldUser.getEmail());
+ assertThat(dto.getScmAccountsAsList()).containsAll(oldUser.getScmAccountsAsList());
+ assertThat(dto.getSalt()).isEqualTo(oldUser.getSalt());
+ assertThat(dto.getCryptedPassword()).isEqualTo(oldUser.getCryptedPassword());
+ }
+
+ @Test
+ public void update_index_when_updating_user_login() {
+ UserDto oldUser = db.users().insertUser();
+ createDefaultGroup();
+ userIndexer.indexOnStartup(null);
+
+ underTest.updateAndCommit(session, oldUser, new UpdateUser()
+ .setLogin("new_login"), u -> {
+ });
List<SearchHit> indexUsers = es.getDocuments(UserIndexDefinition.INDEX_TYPE_USER);
assertThat(indexUsers).hasSize(1);
assertThat(indexUsers.get(0).getSource())
- .contains(
- entry("login", DEFAULT_LOGIN),
- entry("name", "Marius2"),
- entry("email", "marius2@mail.com"));
+ .contains(entry("login", "new_login"));
}
@Test
- public void update_user_with_scm_accounts_containing_blank_entry() {
- db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr")
- .setScmAccounts(asList("ma", "marius33")));
+ public void update_default_assignee_when_updating_login() {
createDefaultGroup();
-
- underTest.updateAndCommit(session, UpdateUser.create(DEFAULT_LOGIN)
- .setName("Marius2")
- .setEmail("marius2@mail.com")
- .setPassword("password2")
- .setScmAccounts(asList("ma2", "", null)), u -> {
- });
-
- UserDto dto = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN);
- assertThat(dto.getScmAccountsAsList()).containsOnly("ma2");
+ UserDto oldUser = db.users().insertUser();
+ ComponentDto project1 = db.components().insertPrivateProject();
+ ComponentDto project2 = db.components().insertPrivateProject();
+ ComponentDto anotherProject = db.components().insertPrivateProject();
+ db.properties().insertProperties(
+ new PropertyDto().setKey(DEFAULT_ISSUE_ASSIGNEE).setValue(oldUser.getLogin()),
+ new PropertyDto().setKey(DEFAULT_ISSUE_ASSIGNEE).setValue(oldUser.getLogin()).setResourceId(project1.getId()),
+ new PropertyDto().setKey(DEFAULT_ISSUE_ASSIGNEE).setValue(oldUser.getLogin()).setResourceId(project2.getId()),
+ new PropertyDto().setKey(DEFAULT_ISSUE_ASSIGNEE).setValue("another login").setResourceId(anotherProject.getId())
+ );
+ userIndexer.indexOnStartup(null);
+
+ underTest.updateAndCommit(session, oldUser, new UpdateUser()
+ .setLogin("new_login"), u -> {
+ });
+
+ assertThat(db.getDbClient().propertiesDao().selectByQuery(PropertyQuery.builder().setKey(DEFAULT_ISSUE_ASSIGNEE).build(), db.getSession()))
+ .extracting(PropertyDto::getValue, PropertyDto::getResourceId)
+ .containsOnly(
+ tuple("new_login", null),
+ tuple("new_login", project1.getId()),
+ tuple("new_login", project2.getId()),
+ tuple("another login", anotherProject.getId())
+ );
}
@Test
public void update_only_user_name() {
- db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr")
+ UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr")
.setScmAccounts(asList("ma", "marius33"))
.setSalt("salt")
.setCryptedPassword("crypted password"));
createDefaultGroup();
- underTest.updateAndCommit(session, UpdateUser.create(DEFAULT_LOGIN)
+ underTest.updateAndCommit(session, user, new UpdateUser()
.setName("Marius2"), u -> {
- });
+ });
UserDto dto = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN);
assertThat(dto.getName()).isEqualTo("Marius2");
@Test
public void update_only_user_email() {
- db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr")
+ UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr")
.setScmAccounts(asList("ma", "marius33"))
.setSalt("salt")
.setCryptedPassword("crypted password"));
createDefaultGroup();
- underTest.updateAndCommit(session, UpdateUser.create(DEFAULT_LOGIN)
+ underTest.updateAndCommit(session, user, new UpdateUser()
.setEmail("marius2@mail.com"), u -> {
- });
+ });
UserDto dto = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN);
assertThat(dto.getEmail()).isEqualTo("marius2@mail.com");
@Test
public void update_only_scm_accounts() {
- db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr")
+ UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr")
.setScmAccounts(asList("ma", "marius33"))
.setSalt("salt")
.setCryptedPassword("crypted password"));
createDefaultGroup();
- underTest.updateAndCommit(session, UpdateUser.create(DEFAULT_LOGIN)
+ underTest.updateAndCommit(session, user, new UpdateUser()
.setScmAccounts(asList("ma2")), u -> {
- });
+ });
UserDto dto = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN);
assertThat(dto.getScmAccountsAsList()).containsOnly("ma2");
@Test
public void update_scm_accounts_with_same_values() {
- db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr")
+ UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr")
.setScmAccounts(asList("ma", "marius33")));
createDefaultGroup();
- underTest.updateAndCommit(session, UpdateUser.create(DEFAULT_LOGIN)
+ underTest.updateAndCommit(session, user, new UpdateUser()
.setScmAccounts(asList("ma", "marius33")), u -> {
- });
+ });
UserDto dto = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN);
assertThat(dto.getScmAccountsAsList()).containsOnly("ma", "marius33");
@Test
public void remove_scm_accounts() {
- db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr")
+ UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr")
.setScmAccounts(asList("ma", "marius33")));
createDefaultGroup();
- underTest.updateAndCommit(session, UpdateUser.create(DEFAULT_LOGIN)
+ underTest.updateAndCommit(session, user, new UpdateUser()
.setScmAccounts(null), u -> {
- });
+ });
UserDto dto = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN);
assertThat(dto.getScmAccounts()).isNull();
@Test
public void update_only_user_password() {
- db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr")
+ UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr")
.setScmAccounts(asList("ma", "marius33"))
.setSalt("salt")
.setCryptedPassword("crypted password"));
createDefaultGroup();
- underTest.updateAndCommit(session, UpdateUser.create(DEFAULT_LOGIN)
+ underTest.updateAndCommit(session, user, new UpdateUser()
.setPassword("password2"), u -> {
- });
+ });
UserDto dto = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN);
assertThat(dto.getSalt()).isNotEqualTo("salt");
}
@Test
- public void update_only_external_identity_id() {
- db.users().insertUser(UserTesting.newExternalUser(DEFAULT_LOGIN, "Marius", "marius@email.com")
- .setExternalIdentity("john")
+ public void update_only_external_id() {
+ UserDto user = db.users().insertUser(UserTesting.newExternalUser(DEFAULT_LOGIN, "Marius", "marius@email.com")
+ .setExternalId("1234")
+ .setExternalLogin("john.smith")
.setExternalIdentityProvider("github"));
createDefaultGroup();
- underTest.updateAndCommit(session, UpdateUser.create(DEFAULT_LOGIN).setExternalIdentity(new ExternalIdentity("github", "john.smith")), u -> {
+ underTest.updateAndCommit(session, user, new UpdateUser().setExternalIdentity(new ExternalIdentity("github", "john.smith", "ABCD")), u -> {
});
assertThat(dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN))
- .extracting(UserDto::getExternalIdentity, UserDto::getExternalIdentityProvider)
+ .extracting(UserDto::getExternalId)
+ .containsOnly("ABCD");
+ }
+
+ @Test
+ public void update_only_external_login() {
+ UserDto user = db.users().insertUser(UserTesting.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 update_only_external_identity_provider() {
- db.users().insertUser(UserTesting.newExternalUser(DEFAULT_LOGIN, "Marius", "marius@email.com")
- .setExternalIdentity("john")
+ UserDto user = db.users().insertUser(UserTesting.newExternalUser(DEFAULT_LOGIN, "Marius", "marius@email.com")
+ .setExternalId("ABCD")
+ .setExternalLogin("john")
.setExternalIdentityProvider("github"));
createDefaultGroup();
- underTest.updateAndCommit(session, UpdateUser.create(DEFAULT_LOGIN).setExternalIdentity(new ExternalIdentity("bitbucket", "john")), u -> {
+ underTest.updateAndCommit(session, user, new UpdateUser().setExternalIdentity(new ExternalIdentity("bitbucket", "john", "ABCD")), u -> {
});
assertThat(dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN))
- .extracting(UserDto::getExternalIdentity, UserDto::getExternalIdentityProvider)
+ .extracting(UserDto::getExternalLogin, UserDto::getExternalIdentityProvider)
.containsOnly("john", "bitbucket");
}
@Test
public void does_not_update_user_when_no_change() {
UserDto user = UserTesting.newExternalUser(DEFAULT_LOGIN, "Marius", "marius@email.com")
- .setExternalIdentity("john")
- .setExternalIdentityProvider("github")
.setScmAccounts(asList("ma1", "ma2"));
db.users().insertUser(user);
createDefaultGroup();
- underTest.updateAndCommit(session, UpdateUser.create(user.getLogin())
+ underTest.updateAndCommit(session, user, new UpdateUser()
.setName(user.getName())
.setEmail(user.getEmail())
.setScmAccounts(user.getScmAccountsAsList())
- .setExternalIdentity(new ExternalIdentity(user.getExternalIdentityProvider(), user.getExternalIdentity())), u -> {
- });
+ .setExternalIdentity(new ExternalIdentity(user.getExternalIdentityProvider(), user.getExternalLogin(), user.getExternalId())), u -> {
+ });
assertThat(dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN).getUpdatedAt()).isEqualTo(user.getUpdatedAt());
}
@Test
public void does_not_update_user_when_no_change_and_scm_account_reordered() {
UserDto user = UserTesting.newExternalUser(DEFAULT_LOGIN, "Marius", "marius@email.com")
- .setExternalIdentity("john")
- .setExternalIdentityProvider("github")
.setScmAccounts(asList("ma1", "ma2"));
db.users().insertUser(user);
createDefaultGroup();
- underTest.updateAndCommit(session, UpdateUser.create(user.getLogin())
+ underTest.updateAndCommit(session, user, new UpdateUser()
.setName(user.getName())
.setEmail(user.getEmail())
.setScmAccounts(asList("ma2", "ma1"))
- .setExternalIdentity(new ExternalIdentity(user.getExternalIdentityProvider(), user.getExternalIdentity())), u -> {
- });
+ .setExternalIdentity(new ExternalIdentity(user.getExternalIdentityProvider(), user.getExternalLogin(), user.getExternalId())), u -> {
+ });
assertThat(dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN).getUpdatedAt()).isEqualTo(user.getUpdatedAt());
}
.setScmAccounts(asList("ma", "marius33")));
UserDto otherUser = db.users().insertUser();
- underTest.updateAndCommit(session, UpdateUser.create(DEFAULT_LOGIN)
+ underTest.updateAndCommit(session, user, new UpdateUser()
.setName("Marius2")
.setEmail("marius2@mail.com")
.setPassword("password2")
.setScmAccounts(asList("ma2")), u -> {
- }, otherUser);
+ }, otherUser);
- assertThat(es.getIds(UserIndexDefinition.INDEX_TYPE_USER)).containsExactlyInAnyOrder(user.getLogin(), otherUser.getLogin());
+ assertThat(es.getIds(UserIndexDefinition.INDEX_TYPE_USER)).containsExactlyInAnyOrder(user.getUuid(), otherUser.getUuid());
}
@Test
public void fail_to_set_null_password_when_local_user() {
- db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@email.com"));
+ UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@email.com"));
createDefaultGroup();
expectedException.expect(BadRequestException.class);
expectedException.expectMessage("Password can't be empty");
- underTest.updateAndCommit(session, UpdateUser.create(DEFAULT_LOGIN).setPassword(null), u -> {
+ underTest.updateAndCommit(session, user, new UpdateUser().setPassword(null), u -> {
});
}
@Test
public void fail_to_update_password_when_user_is_not_local() {
- db.users().insertUser(newUserDto()
+ UserDto user = db.users().insertUser(newUserDto()
.setLogin(DEFAULT_LOGIN)
.setLocal(false));
createDefaultGroup();
expectedException.expect(BadRequestException.class);
expectedException.expectMessage("Password cannot be changed when external authentication is used");
- underTest.updateAndCommit(session, UpdateUser.create(DEFAULT_LOGIN).setPassword("password2"), u -> {
+ underTest.updateAndCommit(session, user, new UpdateUser().setPassword("password2"), u -> {
});
}
@Test
public void not_associate_default_group_when_updating_user() {
- db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@email.com"));
+ UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@email.com"));
GroupDto defaultGroup = createDefaultGroup();
// Existing user, he has no group, and should not be associated to the default one
- underTest.updateAndCommit(session, UpdateUser.create(DEFAULT_LOGIN)
+ underTest.updateAndCommit(session, user, new UpdateUser()
.setName("Marius2")
.setEmail("marius2@mail.com")
.setPassword("password2")
.setScmAccounts(asList("ma2")), u -> {
- });
+ });
Multimap<String, String> groups = dbClient.groupMembershipDao().selectGroupsByLogins(session, asList(DEFAULT_LOGIN));
assertThat(groups.get(DEFAULT_LOGIN).stream().anyMatch(g -> g.equals(defaultGroup.getName()))).isFalse();
Multimap<String, String> groups = dbClient.groupMembershipDao().selectGroupsByLogins(session, asList(DEFAULT_LOGIN));
assertThat(groups.get(DEFAULT_LOGIN).stream().anyMatch(g -> g.equals(defaultGroup.getName()))).as("Current user groups : %s", groups.get(defaultGroup.getName())).isTrue();
- underTest.updateAndCommit(session, UpdateUser.create(DEFAULT_LOGIN)
+ underTest.updateAndCommit(session, user, new UpdateUser()
.setName("Marius2")
.setEmail("marius2@mail.com")
.setPassword("password2")
.setScmAccounts(asList("ma2")), u -> {
- });
+ });
// Nothing as changed
groups = dbClient.groupMembershipDao().selectGroupsByLogins(session, asList(DEFAULT_LOGIN));
@Test
public void fail_to_update_user_when_scm_account_is_already_used() {
- db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@email.com").setScmAccounts(singletonList("ma")));
+ UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@email.com").setScmAccounts(singletonList("ma")));
db.users().insertUser(newLocalUser("john", "John", "john@email.com").setScmAccounts(singletonList("jo")));
createDefaultGroup();
expectedException.expect(BadRequestException.class);
expectedException.expectMessage("The scm account 'jo' is already used by user(s) : 'John (john)'");
- underTest.updateAndCommit(session, UpdateUser.create(DEFAULT_LOGIN)
+ underTest.updateAndCommit(session, user, new UpdateUser()
.setName("Marius2")
.setEmail("marius2@mail.com")
.setPassword("password2")
.setScmAccounts(asList("jo")), u -> {
- });
+ });
}
@Test
public void fail_to_update_user_when_scm_account_is_user_login() {
- db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr"));
+ UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr"));
createDefaultGroup();
expectedException.expect(BadRequestException.class);
expectedException.expectMessage("Login and email are automatically considered as SCM accounts");
- underTest.updateAndCommit(session, UpdateUser.create(DEFAULT_LOGIN).setScmAccounts(asList(DEFAULT_LOGIN)), u -> {
+ underTest.updateAndCommit(session, user, new UpdateUser().setScmAccounts(asList(DEFAULT_LOGIN)), u -> {
});
}
@Test
public void fail_to_update_user_when_scm_account_is_existing_user_email() {
- db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr"));
+ UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr"));
createDefaultGroup();
expectedException.expect(BadRequestException.class);
expectedException.expectMessage("Login and email are automatically considered as SCM accounts");
- underTest.updateAndCommit(session, UpdateUser.create(DEFAULT_LOGIN).setScmAccounts(asList("marius@lesbronzes.fr")), u -> {
+ underTest.updateAndCommit(session, user, new UpdateUser().setScmAccounts(asList("marius@lesbronzes.fr")), u -> {
});
}
@Test
public void fail_to_update_user_when_scm_account_is_new_user_email() {
- db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr"));
+ UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr"));
createDefaultGroup();
expectedException.expect(BadRequestException.class);
expectedException.expectMessage("Login and email are automatically considered as SCM accounts");
- underTest.updateAndCommit(session, UpdateUser.create(DEFAULT_LOGIN)
+ underTest.updateAndCommit(session, user, new UpdateUser()
.setEmail("marius@newmail.com")
.setScmAccounts(asList("marius@newmail.com")), u -> {
+ });
+ }
+
+ @Test
+ public void fail_to_update_login_when_format_is_invalid() {
+ UserDto user = db.users().insertUser();
+ createDefaultGroup();
+
+ expectedException.expect(BadRequestException.class);
+ expectedException.expectMessage("Use only letters, numbers, and .-_@ please.");
+
+ underTest.updateAndCommit(session, user, new UpdateUser().setLogin("With space"), u -> {
});
}
+ @Test
+ public void fail_to_update_user_when_login_already_exists() {
+ createDefaultGroup();
+ UserDto user = db.users().insertUser(u -> u.setActive(false));
+ UserDto existingUser = db.users().insertUser(u -> u.setLogin("existing_login"));
+
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("A user with login 'existing_login' already exists");
+
+ underTest.updateAndCommit(session, user, new UpdateUser().setLogin(existingUser.getLogin()), u -> {
+ });
+ }
+
+ @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 -> {
+ });
+ }
+
private GroupDto createDefaultGroup() {
return db.users().insertDefaultGroup(db.getDefaultOrganization());
}
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.utils.System2;
+import org.sonar.core.util.Uuids;
import org.sonar.server.es.EsTester;
import org.sonar.server.es.SearchOptions;
private UserIndex underTest = new UserIndex(es.client(), System2.INSTANCE);
private UserQuery.Builder userQuery = UserQuery.builder();
- @Test
- public void get_nullable_by_login() {
- UserDoc user1 = newUser(USER1_LOGIN, asList("scmA", "scmB"));
- es.putDocuments(INDEX_TYPE_USER, user1);
- es.putDocuments(INDEX_TYPE_USER, newUser(USER2_LOGIN, Collections.emptyList()));
-
- UserDoc userDoc = underTest.getNullableByLogin(USER1_LOGIN);
- assertThat(userDoc).isNotNull();
- assertThat(userDoc.login()).isEqualTo(user1.login());
- assertThat(userDoc.name()).isEqualTo(user1.name());
- assertThat(userDoc.email()).isEqualTo(user1.email());
- assertThat(userDoc.active()).isTrue();
- assertThat(userDoc.scmAccounts()).isEqualTo(user1.scmAccounts());
-
- assertThat(underTest.getNullableByLogin("")).isNull();
- assertThat(underTest.getNullableByLogin("unknown")).isNull();
- }
-
- @Test
- public void getNullableByLogin_is_case_sensitive() {
- UserDoc user1 = newUser(USER1_LOGIN, asList("scmA", "scmB"));
- es.putDocuments(INDEX_TYPE_USER, user1);
-
- assertThat(underTest.getNullableByLogin(USER1_LOGIN)).isNotNull();
- assertThat(underTest.getNullableByLogin("UsEr1")).isNull();
- }
-
@Test
public void getAtMostThreeActiveUsersForScmAccount_returns_the_users_with_specified_scm_account() {
UserDoc user1 = newUser("user1", asList("user_1", "u1"));
private static UserDoc newUser(String login, List<String> scmAccounts) {
return new UserDoc()
+ .setUuid(Uuids.createFast())
.setLogin(login)
.setName(login.toUpperCase(Locale.ENGLISH))
.setEmail(login + "@mail.com")
private static UserDoc newUser(String login, String email, List<String> scmAccounts) {
return new UserDoc()
+ .setUuid(Uuids.createFast())
.setLogin(login)
.setName(login.toUpperCase(Locale.ENGLISH))
.setEmail(email)
import org.junit.Test;
import org.sonar.api.utils.System2;
import org.sonar.db.DbTester;
+import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.user.UserDto;
-import org.sonar.db.user.UserTesting;
import org.sonar.server.es.EsTester;
import static java.util.Arrays.asList;
+import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.tuple;
public class UserIndexerTest {
@Test
public void indexOnStartup_adds_all_users_to_index() {
- UserDto user = db.users().insertUser(u -> u
- .setScmAccounts(asList("user_1", "u1")));
+ UserDto user = db.users().insertUser(u -> u.setScmAccounts(asList("user_1", "u1")));
underTest.indexOnStartup(new HashSet<>());
List<UserDoc> docs = es.getDocuments(UserIndexDefinition.INDEX_TYPE_USER, UserDoc.class);
assertThat(docs).hasSize(1);
UserDoc doc = docs.get(0);
+ assertThat(doc.uuid()).isEqualTo(user.getUuid());
assertThat(doc.login()).isEqualTo(user.getLogin());
assertThat(doc.name()).isEqualTo(user.getName());
assertThat(doc.email()).isEqualTo(user.getEmail());
assertThat(doc.active()).isEqualTo(user.isActive());
assertThat(doc.scmAccounts()).isEqualTo(user.getScmAccountsAsList());
+ assertThat(doc.organizationUuids()).isEmpty();
+ }
+
+ @Test
+ public void indexOnStartup_adds_all_users_with_organizations() {
+ OrganizationDto organization1 = db.organizations().insert();
+ OrganizationDto organization2 = db.organizations().insert();
+ UserDto user = db.users().insertUser();
+ db.organizations().addMember(organization1, user);
+ db.organizations().addMember(organization2, user);
+
+ underTest.indexOnStartup(new HashSet<>());
+
+ List<UserDoc> docs = es.getDocuments(UserIndexDefinition.INDEX_TYPE_USER, UserDoc.class);
+ assertThat(docs).hasSize(1);
+ UserDoc doc = docs.get(0);
+ assertThat(doc.uuid()).isEqualTo(user.getUuid());
+ assertThat(doc.login()).isEqualTo(user.getLogin());
+ assertThat(doc.organizationUuids()).containsExactlyInAnyOrder(organization1.getUuid(), organization2.getUuid());
}
@Test
underTest.commitAndIndex(db.getSession(), user);
List<UserDoc> docs = es.getDocuments(UserIndexDefinition.INDEX_TYPE_USER, UserDoc.class);
- assertThat(docs).hasSize(1);
- assertThat(docs).extracting(UserDoc::login)
- .containsExactly(user.getLogin())
- .doesNotContain(anotherUser.getLogin());
+ assertThat(docs)
+ .extracting(UserDoc::uuid)
+ .containsExactlyInAnyOrder(user.getUuid())
+ .doesNotContain(anotherUser.getUuid());
+ }
+
+ @Test
+ public void commitAndIndex_single_user_belonging_to_organizations() {
+ OrganizationDto organization1 = db.organizations().insert();
+ OrganizationDto organization2 = db.organizations().insert();
+ UserDto user = db.users().insertUser();
+ db.organizations().addMember(organization1, user);
+ db.organizations().addMember(organization2, user);
+ UserDto anotherUser = db.users().insertUser();
+ db.organizations().addMember(organization1, anotherUser);
+
+ underTest.commitAndIndex(db.getSession(), user);
+
+ List<UserDoc> docs = es.getDocuments(UserIndexDefinition.INDEX_TYPE_USER, UserDoc.class);
+ assertThat(docs)
+ .extracting(UserDoc::uuid, UserDoc::organizationUuids)
+ .containsExactlyInAnyOrder(tuple(user.getUuid(), asList(organization1.getUuid(), organization2.getUuid())));
}
@Test
public void commitAndIndex_multiple_users() {
- UserDto user1 = db.getDbClient().userDao().insert(db.getSession(), UserTesting.newUserDto());
- UserDto user2 = db.getDbClient().userDao().insert(db.getSession(), UserTesting.newUserDto());
+ OrganizationDto organization1 = db.organizations().insert();
+ UserDto user1 = db.users().insertUser();
+ db.organizations().addMember(organization1, user1);
+ OrganizationDto organization2 = db.organizations().insert();
+ UserDto user2 = db.users().insertUser();
+ db.organizations().addMember(organization2, user2);
underTest.commitAndIndex(db.getSession(), asList(user1, user2));
List<UserDoc> docs = es.getDocuments(UserIndexDefinition.INDEX_TYPE_USER, UserDoc.class);
- assertThat(docs).extracting(UserDoc::login).containsExactlyInAnyOrder(user1.getLogin(), user2.getLogin());
+ assertThat(docs)
+ .extracting(UserDoc::login, UserDoc::organizationUuids)
+ .containsExactlyInAnyOrder(
+ tuple(user1.getLogin(), singletonList(organization1.getUuid())),
+ tuple(user2.getLogin(), singletonList(organization2.getUuid())));
assertThat(db.countRowsOfTable(db.getSession(), "users")).isEqualTo(2);
}
}
import org.sonar.server.organization.TestDefaultOrganizationProvider;
import org.sonar.server.organization.TestOrganizationFlags;
import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.user.ExternalIdentity;
import org.sonar.server.user.NewUser;
import org.sonar.server.user.NewUserNotifier;
import org.sonar.server.user.UserUpdater;
import org.sonar.server.user.index.UserIndexer;
import org.sonar.server.usergroups.DefaultGroupFinder;
-import org.sonar.server.ws.WsTester;
+import org.sonar.server.ws.TestResponse;
+import org.sonar.server.ws.WsActionTester;
-import static com.google.common.collect.Lists.newArrayList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
+import static org.sonar.db.user.UserTesting.newExternalUser;
+import static org.sonar.db.user.UserTesting.newLocalUser;
public class ChangePasswordActionTest {
@Rule
new MapSettings().asConfig(),
localAuthentication);
- private WsTester tester = new WsTester(new UsersWs(new ChangePasswordAction(db.getDbClient(), userUpdater, userSessionRule, localAuthentication)));
+ private WsActionTester tester = new WsActionTester(new ChangePasswordAction(db.getDbClient(), userUpdater, userSessionRule, localAuthentication));
@Before
public void setUp() {
}
@Test
- public void fail_on_missing_permission() throws Exception {
- createUser();
- userSessionRule.logIn("polop");
+ public void a_user_can_update_his_password() {
+ userUpdater.createAndCommit(db.getSession(), NewUser.builder()
+ .setEmail("john@email.com")
+ .setLogin("john")
+ .setName("John")
+ .setPassword("Valar Dohaeris")
+ .build(), u -> {
+ });
+ String oldCryptedPassword = db.getDbClient().userDao().selectOrFailByLogin(db.getSession(), "john").getCryptedPassword();
+ userSessionRule.logIn("john");
- expectedException.expect(ForbiddenException.class);
- tester.newPostRequest("api/users", "change_password")
+ TestResponse response = tester.newRequest()
.setParam("login", "john")
+ .setParam("previousPassword", "Valar Dohaeris")
+ .setParam("password", "Valar Morghulis")
.execute();
- }
- @Test
- public void fail_on_unknown_user() throws Exception {
- userSessionRule.logIn().setSystemAdministrator();
-
- expectedException.expect(NotFoundException.class);
-
- tester.newPostRequest("api/users", "change_password")
- .setParam("login", "polop")
- .setParam("password", "polop")
- .execute();
+ assertThat(response.getStatus()).isEqualTo(204);
+ String newCryptedPassword = db.getDbClient().userDao().selectOrFailByLogin(db.getSession(), "john").getCryptedPassword();
+ assertThat(newCryptedPassword).isNotEqualTo(oldCryptedPassword);
}
@Test
- public void system_administrator_can_update_password_of_user() throws Exception {
+ public void system_administrator_can_update_password_of_user() {
userSessionRule.logIn().setSystemAdministrator();
- createUser();
+ createLocalUser();
String originalPassword = db.getDbClient().userDao().selectOrFailByLogin(db.getSession(), "john").getCryptedPassword();
- tester.newPostRequest("api/users", "change_password")
+ tester.newRequest()
.setParam("login", "john")
.setParam("password", "Valar Morghulis")
- .execute()
- .assertNoContent();
+ .execute();
String newPassword = db.getDbClient().userDao().selectOrFailByLogin(db.getSession(), "john").getCryptedPassword();
assertThat(newPassword).isNotEqualTo(originalPassword);
}
@Test
- public void a_user_can_update_his_password() throws Exception {
- createUser();
- String originalPassword = db.getDbClient().userDao().selectOrFailByLogin(db.getSession(), "john").getCryptedPassword();
+ public void fail_on_missing_permission() {
+ createLocalUser();
+ userSessionRule.logIn("polop");
- userSessionRule.logIn("john");
- tester.newPostRequest("api/users", "change_password")
+ expectedException.expect(ForbiddenException.class);
+ tester.newRequest()
.setParam("login", "john")
- .setParam("previousPassword", "Valar Dohaeris")
- .setParam("password", "Valar Morghulis")
- .execute()
- .assertNoContent();
+ .execute();
+ }
- String newPassword = db.getDbClient().userDao().selectOrFailByLogin(db.getSession(), "john").getCryptedPassword();
- assertThat(newPassword).isNotEqualTo(originalPassword);
+ @Test
+ public void fail_on_unknown_user() {
+ userSessionRule.logIn().setSystemAdministrator();
+
+ expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage("User with login 'polop' has not been found");
+
+ tester.newRequest()
+ .setParam("login", "polop")
+ .setParam("password", "polop")
+ .execute();
+ }
+
+ @Test
+ public void fail_on_disabled_user() {
+ db.users().insertUser(u -> u.setLogin( "polop").setActive(false));
+ userSessionRule.logIn().setSystemAdministrator();
+
+ expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage("User with login 'polop' has not been found");
+
+ tester.newRequest()
+ .setParam("login", "polop")
+ .setParam("password", "polop")
+ .execute();
}
@Test
- public void fail_to_update_password_on_self_without_old_password() throws Exception {
- createUser();
+ public void fail_to_update_password_on_self_without_old_password() {
+ createLocalUser();
userSessionRule.logIn("john");
expectedException.expect(IllegalArgumentException.class);
- tester.newPostRequest("api/users", "change_password")
+
+ tester.newRequest()
.setParam("login", "john")
.setParam("password", "Valar Morghulis")
.execute();
}
@Test
- public void fail_to_update_password_on_self_with_bad_old_password() throws Exception {
- createUser();
+ public void fail_to_update_password_on_self_with_bad_old_password() {
+ createLocalUser();
userSessionRule.logIn("john");
expectedException.expect(IllegalArgumentException.class);
- tester.newPostRequest("api/users", "change_password")
+
+ tester.newRequest()
.setParam("login", "john")
.setParam("previousPassword", "I dunno")
.setParam("password", "Valar Morghulis")
}
@Test
- public void fail_to_update_password_on_external_auth() throws Exception {
+ public void fail_to_update_password_on_external_auth() {
userSessionRule.logIn().setSystemAdministrator();
-
- NewUser newUser = NewUser.builder()
- .setEmail("john@email.com")
- .setLogin("john")
- .setName("John")
- .setScmAccounts(newArrayList("jn"))
- .setExternalIdentity(new ExternalIdentity("gihhub", "john"))
- .build();
- userUpdater.createAndCommit(db.getSession(), newUser, u -> {
- });
+ db.users().insertUser(newExternalUser("john", "John", "john@email.com"));
expectedException.expect(BadRequestException.class);
- tester.newPostRequest("api/users", "change_password")
+
+ tester.newRequest()
.setParam("login", "john")
.setParam("password", "Valar Morghulis")
.execute();
}
- private void createUser() {
- userUpdater.createAndCommit(db.getSession(), NewUser.builder()
- .setEmail("john@email.com")
- .setLogin("john")
- .setName("John")
- .setScmAccounts(newArrayList("jn"))
- .setPassword("Valar Dohaeris")
- .build(), u -> {
- });
+ private void createLocalUser() {
+ db.users().insertUser(newLocalUser("john", "John", "john@email.com"));
}
}
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.user.NewUserNotifier;
import org.sonar.server.user.UserUpdater;
-import org.sonar.server.user.index.UserDoc;
import org.sonar.server.user.index.UserIndex;
+import org.sonar.server.user.index.UserIndexDefinition;
import org.sonar.server.user.index.UserIndexer;
import org.sonar.server.user.ws.CreateAction.CreateRequest;
import org.sonar.server.usergroups.DefaultGroupFinder;
import org.sonarqube.ws.Users.CreateWsResponse;
import org.sonarqube.ws.Users.CreateWsResponse.User;
+import static java.lang.String.format;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
+import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.sonar.core.util.Protobuf.setNullable;
import static org.sonar.db.user.UserTesting.newUserDto;
+import static org.sonar.server.user.index.UserIndexDefinition.FIELD_EMAIL;
+import static org.sonar.server.user.index.UserIndexDefinition.FIELD_LOGIN;
+import static org.sonar.server.user.index.UserIndexDefinition.FIELD_NAME;
+import static org.sonar.server.user.index.UserIndexDefinition.FIELD_SCM_ACCOUNTS;
public class CreateActionTest {
.extracting(User::getLogin, User::getName, User::getEmail, User::getScmAccountsList, User::getLocal)
.containsOnly("john", "John", "john@email.com", singletonList("jn"), true);
- UserDoc user = index.getNullableByLogin("john");
- assertThat(user.login()).isEqualTo("john");
- assertThat(user.name()).isEqualTo("John");
- assertThat(user.email()).isEqualTo("john@email.com");
- assertThat(user.scmAccounts()).containsOnly("jn");
+ // exists in index
+ assertThat(es.client().prepareSearch(UserIndexDefinition.INDEX_TYPE_USER)
+ .setQuery(boolQuery()
+ .must(termQuery(FIELD_LOGIN, "john"))
+ .must(termQuery(FIELD_NAME, "John"))
+ .must(termQuery(FIELD_EMAIL, "john@email.com"))
+ .must(termQuery(FIELD_SCM_ACCOUNTS, "jn")))
+ .get().getHits().getHits()).hasSize(1);
// exists in db
Optional<UserDto> dbUser = db.users().selectUserByLogin("john");
.build());
assertThat(db.users().selectUserByLogin("john").get())
- .extracting(UserDto::isLocal, UserDto::getExternalIdentityProvider, UserDto::getExternalIdentity, UserDto::isRoot)
+ .extracting(UserDto::isLocal, UserDto::getExternalIdentityProvider, UserDto::getExternalLogin, UserDto::isRoot)
.containsOnly(true, "sonarqube", "john", false);
}
.build());
assertThat(db.users().selectUserByLogin("john").get())
- .extracting(UserDto::isLocal, UserDto::getExternalIdentityProvider, UserDto::getExternalIdentity, UserDto::isRoot)
+ .extracting(UserDto::isLocal, UserDto::getExternalIdentityProvider, UserDto::getExternalLogin, UserDto::isRoot)
.containsOnly(false, "sonarqube", "john", false);
}
.build());
assertThat(db.users().selectUserByLogin("john").get())
- .extracting(UserDto::getExternalIdentity)
+ .extracting(UserDto::getExternalLogin)
.containsOnly("john");
}
assertThat(db.users().selectUserByLogin("john").get().isActive()).isTrue();
}
+ @Test
+ public void fail_to_reactivate_user_when_active_user_exists() {
+ logInAsSystemAdministrator();
+ UserDto user = db.users().insertUser();
+
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage(format("An active user with login '%s' already exists", user.getLogin()));
+
+ call(CreateRequest.builder()
+ .setLogin(user.getLogin())
+ .setName("John")
+ .setPassword("1234")
+ .build());
+ }
+
@Test
public void fail_when_missing_login() {
logInAsSystemAdministrator();
executeRequest("john");
}
- private void setDefaultGroupProperty(GroupDto adminGroup) {
- settings.setProperty("sonar.defaultGroup", adminGroup.getName());
- }
-
private CreateWsResponse executeRequest(String login) {
return call(CreateRequest.builder()
.setLogin(login)
.setName("Obiwan Kenobi")
.setEmail("obiwan.kenobi@starwars.com")
.setLocal(true)
- .setExternalIdentity("obiwan")
+ .setExternalLogin("obiwan")
.setExternalIdentityProvider("sonarqube")
.setScmAccounts(newArrayList("obiwan:github", "obiwan:bitbucket"))
.setOnboarded(false));
.setName("Obiwan Kenobi")
.setEmail(null)
.setLocal(true)
- .setExternalIdentity("obiwan")
+ .setExternalLogin("obiwan")
.setExternalIdentityProvider("sonarqube")
.setScmAccounts((String) null));
userSessionRule.logIn("obiwan.kenobi");
.setName("Obiwan Kenobi")
.setEmail("obiwan.kenobi@starwars.com")
.setLocal(true)
- .setExternalIdentity("obiwan.kenobi")
+ .setExternalLogin("obiwan.kenobi")
.setExternalIdentityProvider("sonarqube")
.setScmAccounts(newArrayList("obiwan:github", "obiwan:bitbucket"))
.setOnboarded(true)
import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.organization.TestDefaultOrganizationProvider;
import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.user.index.UserIndex;
+import org.sonar.server.user.index.UserIndexDefinition;
import org.sonar.server.user.index.UserIndexer;
import org.sonar.server.ws.TestResponse;
import org.sonar.server.ws.WsActionTester;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
+import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.sonar.api.web.UserRole.CODEVIEWER;
import static org.sonar.api.web.UserRole.USER;
import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
import static org.sonar.db.property.PropertyTesting.newUserPropertyDto;
import static org.sonar.db.user.UserTesting.newUserDto;
import static org.sonar.db.user.UserTokenTesting.newUserToken;
+import static org.sonar.server.user.index.UserIndexDefinition.FIELD_ACTIVE;
+import static org.sonar.server.user.index.UserIndexDefinition.FIELD_UUID;
import static org.sonar.test.JsonAssert.assertJson;
public class DeactivateActionTest {
public UserSessionRule userSession = UserSessionRule.standalone();
private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
- private UserIndex index = new UserIndex(es.client(), system2);
private DbClient dbClient = db.getDbClient();
private UserIndexer userIndexer = new UserIndexer(dbClient, es.client());
private DbSession dbSession = db.getSession();
deactivate(user.getLogin()).getInput();
verifyThatUserIsDeactivated(user.getLogin());
- assertThat(index.getNullableByLogin(user.getLogin()).active()).isFalse();
+ assertThat(es.client().prepareSearch(UserIndexDefinition.INDEX_TYPE_USER)
+ .setQuery(boolQuery()
+ .must(termQuery(FIELD_UUID, user.getUuid()))
+ .must(termQuery(FIELD_ACTIVE, "false")))
+ .get().getHits().getHits()).hasSize(1);
}
@Test
deactivate(user.getLogin()).getInput();
assertThat(db.getDbClient().permissionTemplateDao().selectUserPermissionsByTemplateId(dbSession, template.getId())).extracting(PermissionTemplateUserDto::getUserId).isEmpty();
- assertThat(db.getDbClient().permissionTemplateDao().selectUserPermissionsByTemplateId(dbSession, anotherTemplate.getId())).extracting(PermissionTemplateUserDto::getUserId).isEmpty();
+ assertThat(db.getDbClient().permissionTemplateDao().selectUserPermissionsByTemplateId(dbSession, anotherTemplate.getId())).extracting(PermissionTemplateUserDto::getUserId)
+ .isEmpty();
}
@Test
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.db.user.GroupTesting.newGroupDto;
-import static org.sonar.db.user.UserTesting.newUserDto;
import static org.sonar.db.user.UserTokenTesting.newUserToken;
import static org.sonar.test.JsonAssert.assertJson;
@Test
public void test_json_example() throws Exception {
- UserDto fmallet = db.users().insertUser(newUserDto("fmallet", "Freddy Mallet", "f@m.com")
+ UserDto fmallet = db.users().insertUser(u -> u.setLogin("fmallet").setName("Freddy Mallet").setEmail("f@m.com")
.setActive(true)
.setLocal(true)
.setScmAccounts(emptyList())
- .setExternalIdentity("fmallet")
+ .setExternalLogin("fmallet")
.setExternalIdentityProvider("sonarqube"));
- UserDto simon = db.users().insertUser(newUserDto("sbrandhof", "Simon", "s.brandhof@company.tld")
+ UserDto simon = db.users().insertUser(u -> u.setLogin("sbrandhof").setName("Simon").setEmail("s.brandhof@company.tld")
.setActive(true)
.setLocal(false)
- .setExternalIdentity("sbrandhof@ldap.com")
+ .setExternalLogin("sbrandhof@ldap.com")
.setExternalIdentityProvider("LDAP")
.setScmAccounts(newArrayList("simon.brandhof", "s.brandhof@company.tld")));
GroupDto sonarUsers = db.users().insertGroup(newGroupDto().setName("sonar-users"));
public void only_return_login_and_name_when_not_logged() throws Exception {
userSession.anonymous();
- dbClient.userDao().insert(dbSession, newUserDto("john", "John", "john@email.com"));
+ db.users().insertUser(u -> u.setLogin("john").setName("John").setEmail("john@email.com"));
dbSession.commit();
userIndexer.indexOnStartup(null);
String name = String.format("User %d", index);
List<String> scmAccounts = singletonList(String.format("user-%d", index));
- UserDto userDto = dbClient.userDao().insert(dbSession, newUserDto()
- .setActive(true)
+ UserDto userDto = db.users().insertUser(u -> u.setActive(true)
.setEmail(email)
.setLogin(login)
.setName(name)
.setScmAccounts(scmAccounts)
.setLocal(true)
- .setExternalIdentity(login)
+ .setExternalLogin(login)
.setExternalIdentityProvider("sonarqube"));
userDtos.add(userDto);
@Test
public void fail_on_unknown_user() {
expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage("User 'john' doesn't exist");
+
+ ws.newRequest()
+ .setParam("login", "john")
+ .execute();
+ }
+
+ @Test
+ public void fail_on_disabled_user() {
+ db.users().insertUser(u -> u.setLogin("john").setActive(false));
+
+ expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage("User 'john' doesn't exist");
ws.newRequest()
.setParam("login", "john")
.setScmAccounts(newArrayList("jn"))
.setActive(true)
.setLocal(true)
- .setExternalIdentity("jo")
+ .setExternalLogin("jo")
.setExternalIdentityProvider("sonarqube");
dbClient.userDao().insert(dbSession, userDto);
userIndexer.commitAndIndex(dbSession, userDto);
@Immutable
public final class UserIdentity {
+ private final String id;
private final String providerLogin;
private final String login;
private final String name;
private final Set<String> groups;
private UserIdentity(Builder builder) {
+ this.id = builder.id;
this.providerLogin = builder.providerLogin;
this.login = builder.login;
this.name = builder.name;
this.groups = builder.groups;
}
+ /**
+ * Optional unique ID for the related {@link IdentityProvider}.
+ * If two {@link IdentityProvider} define two users with the same ID, then users are considered as identical.
+ *
+ * When the ID is not provided, the provider login {@link #getProviderLogin()} is used.
+ *
+ * @since 7.2
+ */
+ @CheckForNull
+ public String getProviderId() {
+ return id;
+ }
+
/**
* Non-blank user login for the related {@link IdentityProvider}.
*/
}
public static class Builder {
+ private String id;
private String providerLogin;
private String login;
private String name;
private Builder() {
}
+ /**
+ * @see UserIdentity#getProviderId()
+ * @since 7.2
+ */
+ public Builder setProviderId(@Nullable String id) {
+ this.id = id;
+ return this;
+ }
+
/**
* @see UserIdentity#getProviderLogin()
*/
}
public UserIdentity build() {
+ validateId(id);
validateProviderLogin(providerLogin);
validateLogin(login);
validateName(name);
return new UserIdentity(this);
}
+ private static void validateId(@Nullable String id) {
+ checkArgument(id == null || id.length() <= 255, "ID is too big (255 characters max)");
+ }
+
private static void validateProviderLogin(String providerLogin) {
checkArgument(isNotBlank(providerLogin), "Provider login must not be blank");
checkArgument(providerLogin.length() <= 255, "Provider login size is incorrect (maximum 255 characters)");
public ExpectedException thrown = ExpectedException.none();
@Test
- public void create_user() throws Exception {
+ public void create_user() {
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");
}
@Test
- public void create_user_without_email() throws Exception {
+ public void create_user_with_minimum_fields() {
UserIdentity underTest = UserIdentity.builder()
.setProviderLogin("john")
.setLogin("1234")
.setName("John")
.build();
+ assertThat(underTest.getProviderId()).isNull();
+ assertThat(underTest.getProviderLogin()).isEqualTo("john");
+ assertThat(underTest.getLogin()).isEqualTo("1234");
+ assertThat(underTest.getName()).isEqualTo("John");
assertThat(underTest.getEmail()).isNull();
+ assertThat(underTest.shouldSyncGroups()).isFalse();
+ assertThat(underTest.getGroups()).isEmpty();
+ }
+
+ @Test
+ public void fail_when_id_is_too_long() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("ID is too big (255 characters max)");
+ UserIdentity.builder()
+ .setProviderId(Strings.repeat("1", 256))
+ .setProviderLogin("john")
+ .setLogin("1234")
+ .setName("John")
+ .build();
}
@Test
- public void fail_when_login_is_empty() throws Exception {
+ public void fail_when_login_is_empty() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("User login must not be blank");
UserIdentity.builder()
}
@Test
- public void fail_when_login_is_too_long() throws Exception {
+ 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()
}
@Test
- public void fail_when_login_is_too_small() throws Exception {
+ 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()
}
@Test
- public void fail_when_provider_login_is_null() throws Exception {
+ public void fail_when_provider_login_is_null() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Provider login must not be blank");
UserIdentity.builder()
}
@Test
- public void fail_when_provider_login_is_empty() throws Exception {
+ public void fail_when_provider_login_is_empty() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Provider login must not be blank");
UserIdentity.builder()
}
@Test
- public void fail_when_provider_login_is_too_long() throws Exception {
+ public void fail_when_provider_login_is_too_long() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Provider login size is incorrect (maximum 255 characters)");
UserIdentity.builder()
}
@Test
- public void fail_when_name_is_null() throws Exception {
+ public void fail_when_name_is_null() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("User name must not be blank");
UserIdentity.builder()
}
@Test
- public void fail_when_name_is_empty() throws Exception {
+ public void fail_when_name_is_empty() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("User name must not be blank");
UserIdentity.builder()
}
@Test
- public void fail_when_name_is_loo_long() throws Exception {
+ public void fail_when_name_is_loo_long() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("User name size is too big (200 characters max)");
UserIdentity.builder()
}
@Test
- public void fail_when_email_is_loo_long() throws Exception {
+ public void fail_when_email_is_loo_long() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("User email size is too big (100 characters max)");
UserIdentity.builder()
}
@Test
- public void create_user_with_groups() throws Exception {
+ public void create_user_with_groups() {
UserIdentity underTest = UserIdentity.builder()
.setProviderLogin("john")
.setLogin("1234")
}
@Test
- public void fail_when_groups_are_null() throws Exception {
+ public void fail_when_groups_are_null() {
thrown.expect(NullPointerException.class);
thrown.expectMessage("Groups cannot be null, please don't use this method if groups should not be synchronized.");
}
@Test
- public void fail_when_groups_contain_empty_group_name() throws Exception {
+ public void fail_when_groups_contain_empty_group_name() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Group name cannot be empty");
}
@Test
- public void fail_when_groups_contain_only_blank_space() throws Exception {
+ public void fail_when_groups_contain_only_blank_space() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Group name cannot be empty");
}
@Test
- public void fail_when_groups_contain_null_group_name() throws Exception {
+ public void fail_when_groups_contain_null_group_name() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Group name cannot be empty");
}
@Test
- public void fail_when_groups_contain_anyone() throws Exception {
+ public void fail_when_groups_contain_anyone() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Anyone group cannot be used");
}
@Test
- public void fail_when_groups_contain_too_long_group_name() throws Exception {
+ public void fail_when_groups_contain_too_long_group_name() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Group name cannot be longer than 255 characters");
+
/*
* SonarQube
* Copyright (C) 2009-2018 SonarSource SA
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+
import java.io.IOException;
import org.sonar.api.config.Settings;
import org.sonar.api.server.authentication.BaseIdentityProvider;
String[] userInfos = userInfoProperty.split(",");
UserIdentity.Builder builder = UserIdentity.builder()
- .setLogin(userInfos[0])
- .setProviderLogin(userInfos[1])
- .setName(userInfos[2])
- .setEmail(userInfos[3]);
+ .setLogin(emptyToNull(userInfos[0]))
+ .setProviderId(emptyToNull(userInfos[1]))
+ .setProviderLogin(emptyToNull(userInfos[2]))
+ .setName(emptyToNull(userInfos[3]))
+ .setEmail(emptyToNull(userInfos[4]));
if (settings.getBoolean(ENABLED_GROUPS_SYNC)) {
builder.setGroups(newHashSet(settings.getStringArray(GROUPS)));
// If property is not defined, default behaviour is not always allow users to sign up
return true;
}
+
+ private static String emptyToNull(String s) {
+ if (s == null) {
+ return null;
+ }
+ String trim = s.trim();
+ if (trim.isEmpty()) {
+ return null;
+ }
+ return trim;
+ }
}
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+
import org.sonar.api.config.Settings;
import org.sonar.api.server.authentication.Display;
import org.sonar.api.server.authentication.OAuth2IdentityProvider;
String[] userInfos = userInfoProperty.split(",");
context.authenticate(UserIdentity.builder()
- .setLogin(userInfos[0])
- .setProviderLogin(userInfos[1])
- .setName(userInfos[2])
- .setEmail(userInfos[3])
+ .setLogin(emptyToNull(userInfos[0]))
+ .setProviderId(emptyToNull(userInfos[1]))
+ .setProviderLogin(emptyToNull(userInfos[2]))
+ .setName(emptyToNull(userInfos[3]))
+ .setEmail(emptyToNull(userInfos[4]))
.build());
context.redirectToRequestedPage();
}
}
// If property is not defined, default behaviour is not always allow users to sign up
return true;
+ }
+ private static String emptyToNull(String s) {
+ if (s == null) {
+ return null;
+ }
+ String trim = s.trim();
+ if (trim.isEmpty()) {
+ return null;
+ }
+ return trim;
}
}
import org.sonarqube.tests.qualityProfile.QualityProfilesWsTest;
import org.sonarqube.tests.rule.RulesMarkdownTest;
import org.sonarqube.tests.rule.RulesWsTest;
-import org.sonarqube.tests.user.OrganizationIdentityProviderTest;
import static util.ItUtils.newOrchestratorBuilder;
import static util.ItUtils.pluginArtifact;
@Deprecated
@RunWith(Suite.class)
@Suite.SuiteClasses({
- OrganizationIdentityProviderTest.class,
OrganizationIssuesPageTest.class,
OrganizationQualityProfilesUiTest.class,
BuiltInQualityProfilesTest.class,
.setServerProperty("sonar.notifications.delay", "1")
.addPlugin(xooPlugin())
- .addPlugin(pluginArtifact("base-auth-plugin"))
.addPlugin(pluginArtifact("ui-extensions-plugin"))
.setServerProperty("sonar.sonarcloud.enabled", "true")
import com.google.common.base.Joiner;
import com.sonar.orchestrator.Orchestrator;
import java.io.File;
-import java.util.Optional;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.annotation.Nullable;
import org.apache.commons.io.FileUtils;
import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
import org.junit.ClassRule;
+import org.junit.Rule;
import org.junit.Test;
-import org.junit.rules.RuleChain;
+import org.sonarqube.qa.util.Tester;
import org.sonarqube.qa.util.pageobjects.Navigation;
+import org.sonarqube.ws.Users.SearchWsResponse.User;
import org.sonarqube.ws.client.GetRequest;
-import org.sonarqube.ws.client.WsClient;
+import org.sonarqube.ws.client.usergroups.DeleteRequest;
import org.sonarqube.ws.client.users.CreateRequest;
-import util.user.UserRule;
-import util.user.Users;
+import org.sonarqube.ws.client.users.DeactivateRequest;
+import org.sonarqube.ws.client.users.GroupsRequest;
+import org.sonarqube.ws.client.users.SearchRequest;
import static org.assertj.core.api.Assertions.assertThat;
-import static util.ItUtils.newAdminWsClient;
-import static util.ItUtils.resetSettings;
-import static util.ItUtils.setServerProperty;
+import static org.assertj.core.api.Assertions.tuple;
+import static org.sonarqube.ws.UserGroups.Group;
import static util.selenium.Selenese.runSelenese;
-/**
- * TODO : Add missing ITs
- * - display multiple identity provider plugins (probably in another class)
- */
public class BaseIdentityProviderTest {
@ClassRule
public static Orchestrator ORCHESTRATOR = UserSuite.ORCHESTRATOR;
- private static UserRule userRule = UserRule.from(ORCHESTRATOR);
-
- @ClassRule
- public static RuleChain ruleChain = RuleChain.outerRule(ORCHESTRATOR).around(userRule);
-
- static String FAKE_PROVIDER_KEY = "fake-base-id-provider";
+ @Rule
+ public Tester tester = new Tester(ORCHESTRATOR).disableOrganizations();
- static String USER_LOGIN = "john";
- static String USER_PROVIDER_ID = "fake-john";
- static String USER_NAME = "John";
- static String USER_EMAIL = "john@email.com";
+ private static String FAKE_PROVIDER_KEY = "fake-base-id-provider";
- static String USER_NAME_UPDATED = "John Doe";
- static String USER_EMAIL_UPDATED = "john.doe@email.com";
+ private static String USER_LOGIN = "john";
+ private static String USER_PROVIDER_ID = "ABCD";
+ private static String USER_PROVIDER_LOGIN = "fake-john";
+ private static String USER_NAME = "John";
+ private static String USER_EMAIL = "john@email.com";
- static String GROUP1 = "group1";
- static String GROUP2 = "group2";
- static String GROUP3 = "group3";
-
- static WsClient adminWsClient;
-
- @BeforeClass
- public static void setUp() {
- ORCHESTRATOR.resetData();
- adminWsClient = newAdminWsClient(ORCHESTRATOR);
- }
-
- @Before
@After
public void resetData() {
- userRule.resetUsers();
- userRule.removeGroups(GROUP1, GROUP2, GROUP3);
- resetSettings(ORCHESTRATOR, null,
+ tester.settings().resetSettings(
"sonar.auth.fake-base-id-provider.enabled",
"sonar.auth.fake-base-id-provider.user",
"sonar.auth.fake-base-id-provider.throwUnauthorizedMessage",
@Test
public void create_new_user_when_authenticate() {
enablePlugin();
- setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_NAME, USER_EMAIL);
-
- userRule.verifyUserDoesNotExist(USER_LOGIN);
+ setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_PROVIDER_LOGIN, USER_NAME, USER_EMAIL);
+ assertThat(tester.users().getByLogin(USER_LOGIN)).isNotPresent();
// First connection, user is created
authenticateWithFakeAuthProvider();
- userRule.verifyUserExists(USER_LOGIN, USER_NAME, USER_EMAIL, false);
+ assertThat(tester.users().service().search(new SearchRequest().setQ(USER_LOGIN)).getUsersList())
+ .extracting(User::getLogin, User::getName, User::getEmail, User::getExternalProvider, User::getExternalIdentity, User::getLocal)
+ .containsExactlyInAnyOrder(tuple(USER_LOGIN, USER_NAME, USER_EMAIL, FAKE_PROVIDER_KEY, USER_PROVIDER_LOGIN, false));
}
@Test
public void authenticate_user_through_ui() {
enablePlugin();
- setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_NAME, USER_EMAIL);
+ setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_PROVIDER_LOGIN, USER_NAME, USER_EMAIL);
Navigation.create(ORCHESTRATOR).openLogin().useOAuth2().shouldBeLoggedIn();
- userRule.verifyUserExists(USER_LOGIN, USER_NAME, USER_EMAIL);
+ assertThat(tester.users().service().search(new SearchRequest().setQ(USER_LOGIN)).getUsersList())
+ .extracting(User::getLogin, User::getName, User::getEmail, User::getExternalProvider, User::getExternalIdentity, User::getLocal)
+ .containsExactlyInAnyOrder(tuple(USER_LOGIN, USER_NAME, USER_EMAIL, FAKE_PROVIDER_KEY, USER_PROVIDER_LOGIN, false));
}
@Test
public void display_unauthorized_page_when_authentication_failed() {
enablePlugin();
// As this property is null, the plugin will throw an exception
- setServerProperty(ORCHESTRATOR, "sonar.auth.fake-base-id-provider.user", null);
+ tester.settings().setGlobalSettings("sonar.auth.fake-base-id-provider.user", null);
runSelenese(ORCHESTRATOR, "/user/BaseIdentityProviderTest/display_unauthorized_page_when_authentication_failed.html");
- userRule.verifyUserDoesNotExist(USER_LOGIN);
+ assertThat(tester.users().getByLogin(USER_LOGIN)).isNotPresent();
}
@Test
public void fail_when_email_already_exists() throws Exception {
enablePlugin();
- setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_NAME, USER_EMAIL);
- userRule.createUser("another", "Another", USER_EMAIL, "another");
+ setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_PROVIDER_LOGIN, USER_NAME, USER_EMAIL);
+ tester.users().generate(u -> u.setLogin("another").setName("Another").setEmail(USER_EMAIL).setPassword("another"));
runSelenese(ORCHESTRATOR, "/user/BaseIdentityProviderTest/fail_when_email_already_exists.html");
@Test
public void fail_to_authenticate_when_not_allowed_to_sign_up() {
enablePlugin();
- setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_NAME, USER_EMAIL);
- setServerProperty(ORCHESTRATOR, "sonar.auth.fake-base-id-provider.allowsUsersToSignUp", "false");
+ setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_PROVIDER_LOGIN, USER_NAME, USER_EMAIL);
+ tester.settings().setGlobalSettings("sonar.auth.fake-base-id-provider.allowsUsersToSignUp", "false");
runSelenese(ORCHESTRATOR, "/user/BaseIdentityProviderTest/fail_to_authenticate_when_not_allowed_to_sign_up.html");
- userRule.verifyUserDoesNotExist(USER_LOGIN);
+ assertThat(tester.users().getByLogin(USER_LOGIN)).isNotPresent();
}
@Test
public void update_existing_user_when_authenticate() {
enablePlugin();
- setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_NAME, USER_EMAIL);
+ setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_PROVIDER_LOGIN, USER_NAME, USER_EMAIL);
// First connection, user is created
authenticateWithFakeAuthProvider();
- setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_NAME_UPDATED, USER_EMAIL_UPDATED);
+ String newName = "John Doe";
+ String newEmail = "john.doe@email.com";
+ setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_PROVIDER_LOGIN, newName, newEmail);
// Second connection, user should be updated
authenticateWithFakeAuthProvider();
- userRule.verifyUserExists(USER_LOGIN, USER_NAME_UPDATED, USER_EMAIL_UPDATED);
+ assertThat(tester.users().service().search(new SearchRequest().setQ(USER_LOGIN)).getUsersList())
+ .extracting(User::getLogin, User::getName, User::getEmail, User::getExternalProvider, User::getExternalIdentity, User::getLocal)
+ .containsExactlyInAnyOrder(tuple(USER_LOGIN, newName, newEmail, FAKE_PROVIDER_KEY, USER_PROVIDER_LOGIN, false));
}
@Test
public void reactivate_disabled_user() {
enablePlugin();
- setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_NAME, USER_EMAIL);
-
- userRule.verifyUserDoesNotExist(USER_LOGIN);
-
+ setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_PROVIDER_LOGIN, USER_NAME, USER_EMAIL);
// First connection, user is created
authenticateWithFakeAuthProvider();
-
- Optional<Users.User> user = userRule.getUserByLogin(USER_LOGIN);
- assertThat(user).isPresent();
-
// Disable user
- userRule.deactivateUsers(USER_LOGIN);
+ tester.users().service().deactivate(new DeactivateRequest().setLogin(USER_LOGIN));
// Second connection, user is reactivated
authenticateWithFakeAuthProvider();
- userRule.verifyUserExists(USER_LOGIN, USER_NAME, USER_EMAIL);
+
+ assertThat(tester.users().service().search(new SearchRequest().setQ(USER_LOGIN)).getUsersList())
+ .extracting(User::getLogin, User::getName, User::getEmail, User::getExternalProvider, User::getExternalIdentity, User::getLocal)
+ .containsExactlyInAnyOrder(tuple(USER_LOGIN, USER_NAME, USER_EMAIL, FAKE_PROVIDER_KEY, USER_PROVIDER_LOGIN, false));
}
@Test
public void not_authenticate_when_plugin_is_disabled() {
- setServerProperty(ORCHESTRATOR, "sonar.auth.fake-base-id-provider.enabled", "false");
- setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_NAME, USER_EMAIL);
+ tester.settings().setGlobalSettings("sonar.auth.fake-base-id-provider.enabled", "false");
+ setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_PROVIDER_LOGIN, USER_NAME, USER_EMAIL);
authenticateWithFakeAuthProvider();
// User is not created as nothing plugin is disabled
- userRule.verifyUserDoesNotExist(USER_LOGIN);
+ assertThat(tester.users().getByLogin(USER_LOGIN)).isNotPresent();
// TODO Add Selenium test to check login form
}
@Test
public void display_message_in_ui_but_not_in_log_when_unauthorized_exception() throws Exception {
enablePlugin();
- setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_NAME, USER_EMAIL);
- setServerProperty(ORCHESTRATOR, "sonar.auth.fake-base-id-provider.throwUnauthorizedMessage", "true");
+ setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_PROVIDER_LOGIN, USER_NAME, USER_EMAIL);
+ tester.settings().setGlobalSettings("sonar.auth.fake-base-id-provider.throwUnauthorizedMessage", "true");
runSelenese(ORCHESTRATOR,
"/user/BaseIdentityProviderTest/display_message_in_ui_but_not_in_log_when_unauthorized_exception.html");
assertThat(FileUtils.readFileToString(logFile)).doesNotContain("A functional error has happened");
assertThat(FileUtils.readFileToString(logFile)).doesNotContain("UnauthorizedException");
- userRule.verifyUserDoesNotExist(USER_LOGIN);
+ assertThat(tester.users().getByLogin(USER_LOGIN)).isNotPresent();
}
@Test
public void synchronize_groups_for_new_user() {
enablePlugin();
- userRule.createGroup(GROUP1);
- userRule.createGroup(GROUP2);
- setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_NAME, USER_EMAIL);
- // Group3 doesn't exist in DB, user won't belong to this group
- setGroupsReturnedByAuthPlugin(GROUP1, GROUP2, GROUP3);
-
- authenticateWithFakeAuthProvider();
-
- userRule.verifyUserGroupMembership(USER_LOGIN, GROUP1, GROUP2, "sonar-users");
+ Group group1 = tester.groups().generate();
+ Group group2 = tester.groups().generate();
+ Group group3 = tester.groups().generate();
+ try {
+ setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_PROVIDER_LOGIN, USER_NAME, USER_EMAIL);
+ setGroupsReturnedByAuthPlugin(group1.getName(), group2.getName(), "Another group");
+
+ authenticateWithFakeAuthProvider();
+
+ assertThat(tester.users().service().groups(new GroupsRequest().setLogin(USER_LOGIN)).getGroupsList())
+ .extracting(org.sonarqube.ws.Users.GroupsWsResponse.Group::getName)
+ .containsExactlyInAnyOrder(group1.getName(), group2.getName(), "sonar-users");
+ } finally {
+ deleteGroups(group1, group2, group3);
+ }
}
@Test
public void synchronize_groups_for_existing_user() {
enablePlugin();
- userRule.createGroup(GROUP1);
- userRule.createGroup(GROUP2);
- userRule.createGroup(GROUP3);
- userRule.createUser(USER_LOGIN, "password");
- userRule.associateGroupsToUser(USER_LOGIN, GROUP1, GROUP2);
- setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_NAME, USER_EMAIL);
- // Group1 is not returned by the plugin, user won't belong anymore to this group
- setGroupsReturnedByAuthPlugin(GROUP2, GROUP3);
-
- authenticateWithFakeAuthProvider();
-
- userRule.verifyUserGroupMembership(USER_LOGIN, GROUP2, GROUP3, "sonar-users");
+ Group group1 = tester.groups().generate();
+ Group group2 = tester.groups().generate();
+ Group group3 = tester.groups().generate();
+ try {
+ tester.users().generate(u -> u.setLogin(USER_LOGIN).setPassword("password"));
+ tester.groups().addMemberToGroups(tester.organizations().getDefaultOrganization(), USER_LOGIN, group1.getName(), group2.getName());
+ setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_PROVIDER_LOGIN, USER_NAME, USER_EMAIL);
+ // Group1 is not returned by the plugin, user won't belong anymore to this group
+ setGroupsReturnedByAuthPlugin(group2.getName(), group3.getName());
+
+ authenticateWithFakeAuthProvider();
+
+ assertThat(tester.users().service().groups(new GroupsRequest().setLogin(USER_LOGIN)).getGroupsList())
+ .extracting(org.sonarqube.ws.Users.GroupsWsResponse.Group::getName)
+ .containsExactlyInAnyOrder(group2.getName(), group3.getName(), "sonar-users");
+ } finally {
+ deleteGroups(group1, group2, group3);
+ }
}
@Test
public void remove_user_groups_when_groups_provided_by_plugin_are_empty() {
enablePlugin();
- userRule.createGroup(GROUP1);
- userRule.createUser(USER_LOGIN, "password");
- userRule.associateGroupsToUser(USER_LOGIN, GROUP1);
- setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_NAME, USER_EMAIL);
- // No group is returned by the plugin
- setGroupsReturnedByAuthPlugin();
-
- authenticateWithFakeAuthProvider();
-
- // User is not member to any group
- userRule.verifyUserGroupMembership(USER_LOGIN, "sonar-users");
+ Group group = tester.groups().generate();
+ try {
+ tester.users().generate(u -> u.setLogin(USER_LOGIN).setPassword("password"));
+ tester.groups().addMemberToGroups(tester.organizations().getDefaultOrganization(), USER_LOGIN, group.getName());
+ setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_PROVIDER_LOGIN, USER_NAME, USER_EMAIL);
+ // No group is returned by the plugin
+ setGroupsReturnedByAuthPlugin();
+
+ authenticateWithFakeAuthProvider();
+
+ // User is not member to any group
+ assertThat(tester.users().service().groups(new GroupsRequest().setLogin(USER_LOGIN)).getGroupsList())
+ .extracting(org.sonarqube.ws.Users.GroupsWsResponse.Group::getName)
+ .containsExactlyInAnyOrder("sonar-users");
+ } finally {
+ deleteGroups(group);
+ }
}
@Test
public void allow_user_login_with_2_characters() {
enablePlugin();
String login = "jo";
- setUserCreatedByAuthPlugin(login, USER_PROVIDER_ID, USER_NAME, USER_EMAIL);
- userRule.verifyUserDoesNotExist(login);
+ setUserCreatedByAuthPlugin(login, login, login, USER_NAME, USER_EMAIL);
+ assertThat(tester.users().getByLogin(login)).isNotPresent();
// First connection, user is created
authenticateWithFakeAuthProvider();
- userRule.verifyUserExists(login, USER_NAME, USER_EMAIL, false);
+ assertThat(tester.users().getByLogin(login)).isPresent();
}
@Test
public void provision_user_before_authentication() {
enablePlugin();
- setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_NAME, USER_EMAIL);
+ setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_PROVIDER_LOGIN, USER_NAME, USER_EMAIL);
// Provision none local user in database
- newAdminWsClient(ORCHESTRATOR).users().create(new CreateRequest()
+ tester.users().service().create(new CreateRequest()
.setLogin(USER_LOGIN)
.setName(USER_NAME)
.setEmail(USER_EMAIL)
.setLocal("false"));
- assertThat(userRule.getUserByLogin(USER_LOGIN).get())
- .extracting(Users.User::isLocal, Users.User::getExternalIdentity, Users.User::getExternalProvider)
- .containsOnly(false, USER_LOGIN, "sonarqube");
+ assertThat(tester.users().service().search(new SearchRequest().setQ(USER_LOGIN)).getUsersList())
+ .extracting(User::getLogin, User::getExternalProvider, User::getExternalIdentity, User::getLocal)
+ .containsExactlyInAnyOrder(tuple(USER_LOGIN, "sonarqube", USER_LOGIN, false));
// Authenticate with external system -> It will update external provider info
authenticateWithFakeAuthProvider();
- assertThat(userRule.getUserByLogin(USER_LOGIN).get())
- .extracting(Users.User::isLocal, Users.User::getExternalIdentity, Users.User::getExternalProvider)
- .containsOnly(false, USER_PROVIDER_ID, FAKE_PROVIDER_KEY);
+ assertThat(tester.users().service().search(new SearchRequest().setQ(USER_LOGIN)).getUsersList())
+ .extracting(User::getLogin, User::getExternalProvider, User::getExternalIdentity, User::getLocal)
+ .containsExactlyInAnyOrder(tuple(USER_LOGIN, FAKE_PROVIDER_KEY, USER_PROVIDER_LOGIN, false));
}
- private static void enablePlugin() {
- setServerProperty(ORCHESTRATOR, "sonar.auth.fake-base-id-provider.enabled", "true");
+ @Test
+ public void update_login() {
+ enablePlugin();
+ String oldLogin = "login_to_update@base";
+ setUserCreatedByAuthPlugin(oldLogin, "login_to_update_id", "old_provider_login", USER_NAME, USER_EMAIL);
+ assertThat(tester.users().getByLogin(USER_LOGIN)).isNotPresent();
+ authenticateWithFakeAuthProvider();
+
+ // Login is updated
+ String newLogin = "new_login@base";
+ setUserCreatedByAuthPlugin(newLogin, "login_to_update_id", "new_provider_login", USER_NAME, USER_EMAIL);
+ authenticateWithFakeAuthProvider();
+
+ assertThat(tester.users().getByLogin(oldLogin)).isNotPresent();
+ assertThat(tester.users().service().search(new SearchRequest().setQ(newLogin)).getUsersList())
+ .extracting(User::getLogin, User::getName, User::getEmail, User::getExternalProvider, User::getExternalIdentity, User::getLocal)
+ .containsExactlyInAnyOrder(tuple(newLogin, USER_NAME, USER_EMAIL, FAKE_PROVIDER_KEY, "new_provider_login", false));
+ // Check that searching for old login return nothing
+ assertThat(tester.users().service().search(new SearchRequest().setQ(oldLogin)).getPaging().getTotal()).isZero();
}
- private static void setUserCreatedByAuthPlugin(String login, String providerId, String name, String email) {
- setServerProperty(ORCHESTRATOR, "sonar.auth.fake-base-id-provider.user", login + "," + providerId + "," + name + "," + email);
+ @Test
+ public void authenticate_with_external_id_null() {
+ enablePlugin();
+ String login = "no_external_id_login";
+ setUserCreatedByAuthPlugin(login, null, "no_external_id_provider_login", USER_NAME, USER_EMAIL);
+
+ // First authentication
+ authenticateWithFakeAuthProvider();
+ assertThat(tester.users().getByLogin(login)).isPresent();
+
+ // De-activate and re-authenticate to check everything is ok
+ tester.users().service().deactivate(new DeactivateRequest().setLogin(login));
+ authenticateWithFakeAuthProvider();
+ assertThat(tester.users().getByLogin(login)).isPresent();
}
- private static void setGroupsReturnedByAuthPlugin(String... groups) {
- setServerProperty(ORCHESTRATOR, "sonar.auth.fake-base-id-provider.enabledGroupsSync", "true");
+ @Test
+ public void update_external_id() {
+ enablePlugin();
+ String login = "update_external_id_login";
+ setUserCreatedByAuthPlugin(login, "old_external_id", login, USER_NAME, USER_EMAIL);
+ authenticateWithFakeAuthProvider();
+ assertThat(tester.users().getByLogin(login)).isPresent();
+
+ setUserCreatedByAuthPlugin(login, "new_external_id", login, USER_NAME, USER_EMAIL);
+ authenticateWithFakeAuthProvider();
+ assertThat(tester.users().getByLogin(login)).isPresent();
+ }
+
+ private void enablePlugin() {
+ tester.settings().setGlobalSettings("sonar.auth.fake-base-id-provider.enabled", "true");
+ }
+
+ private void setUserCreatedByAuthPlugin(String login, @Nullable String providerId, String providerLogin, String name, String email) {
+ tester.settings().setGlobalSettings("sonar.auth.fake-base-id-provider.user", login + "," + (providerId == null ? "" : providerId) + "," + providerLogin + "," + name + "," + email);
+ }
+
+ private void setGroupsReturnedByAuthPlugin(String... groups) {
+ tester.settings().setGlobalSettings("sonar.auth.fake-base-id-provider.enabledGroupsSync", "true");
if (groups.length > 0) {
- setServerProperty(ORCHESTRATOR, "sonar.auth.fake-base-id-provider.groups", Joiner.on(",").join(groups));
+ tester.settings().setGlobalSettings("sonar.auth.fake-base-id-provider.groups", Joiner.on(",").join(groups));
}
}
- private static void authenticateWithFakeAuthProvider() {
- adminWsClient.wsConnector().call(
+ private void authenticateWithFakeAuthProvider() {
+ tester.wsClient().wsConnector().call(
new GetRequest("/sessions/init/" + FAKE_PROVIDER_KEY))
.failIfNotSuccessful();
}
+ private void deleteGroups(Group... groups) {
+ List<String> allGroups = tester.wsClient().userGroups().search(new org.sonarqube.ws.client.usergroups.SearchRequest()).getGroupsList().stream().map(Group::getName)
+ .collect(Collectors.toList());
+ Arrays.stream(groups)
+ .filter(g -> allGroups.contains(g.getName()))
+ .forEach(g -> tester.wsClient().userGroups().delete(new DeleteRequest().setName(g.getName())));
+ }
+
}
private static String FAKE_PROVIDER_KEY = "fake-oauth2-id-provider";
private static String USER_LOGIN = "john";
- private static String USER_PROVIDER_ID = "fake-john";
+ private static String USER_PROVIDER_ID = "ABCD";
+ private static String USER_PROVIDER_LOGIN = "fake-john";
private static String USER_NAME = "John";
private static String USER_EMAIL = "john@email.com";
user = tester.users().getByLogin(USER_LOGIN).get();
assertThat(user.getLocal()).isFalse();
- assertThat(user.getExternalIdentity()).isEqualTo(USER_PROVIDER_ID);
+ assertThat(user.getExternalIdentity()).isEqualTo(USER_PROVIDER_LOGIN);
assertThat(user.getExternalProvider()).isEqualTo(FAKE_PROVIDER_KEY);
}
+ @Test
+ public void update_login() {
+ simulateRedirectionToCallback();
+ enablePlugin();
+
+ String oldLogin = "login_to_update@oauth2";
+ tester.settings().setGlobalSettings("sonar.auth.fake-oauth2-id-provider.user", oldLogin + "," + "login_to_update_id" + "," + "old_provider_login" + "," + USER_NAME + "," + USER_EMAIL);
+ authenticateWithFakeAuthProvider();
+
+ String newLogin = "new_logine@oauth2";
+ tester.settings().setGlobalSettings("sonar.auth.fake-oauth2-id-provider.user", newLogin + "," + "login_to_update_id" + "," + "new_provider_login" + "," + USER_NAME + "," + USER_EMAIL);
+ authenticateWithFakeAuthProvider();
+
+ verifyUser(newLogin, USER_NAME, USER_EMAIL);
+ }
+
private void verifyUser(String login, String name, String email) {
User user = tester.users().getByLogin(login).orElseThrow(IllegalStateException::new);
assertThat(user.getLogin()).isEqualTo(login);
private void enablePlugin() {
tester.settings().setGlobalSettings("sonar.auth.fake-oauth2-id-provider.enabled", "true");
tester.settings().setGlobalSettings("sonar.auth.fake-oauth2-id-provider.url", fakeServerAuthProviderUrl);
- tester.settings().setGlobalSettings("sonar.auth.fake-oauth2-id-provider.user", USER_LOGIN + "," + USER_PROVIDER_ID + "," + USER_NAME + "," + USER_EMAIL);
+ tester.settings().setGlobalSettings("sonar.auth.fake-oauth2-id-provider.user", USER_LOGIN + "," + USER_PROVIDER_ID + "," + USER_PROVIDER_LOGIN + "," + USER_NAME + "," + USER_EMAIL);
}
private void assertThatUserDoesNotExist(String login) {
import org.junit.Rule;
import org.junit.Test;
import org.sonarqube.qa.util.Tester;
-import org.sonarqube.tests.Category6Suite;
import org.sonarqube.ws.UserGroups.Group;
import org.sonarqube.ws.Users.CreateWsResponse.User;
import org.sonarqube.ws.client.GetRequest;
public class OrganizationIdentityProviderTest {
@ClassRule
- public static Orchestrator orchestrator = Category6Suite.ORCHESTRATOR;
+ public static Orchestrator orchestrator = SonarCloudUserSuite.ORCHESTRATOR;
@Rule
public Tester tester = new Tester(orchestrator);
@After
public void tearDown() {
- tester.settings().resetSettings("sonar.auth.fake-base-id-provider.enabled", "sonar.auth.fake-base-id-provider.user",
- "sonar.auth.fake-base-id-provider.throwUnauthorizedMessage", "sonar.auth.fake-base-id-provider.enabledGroupsSync", "sonar.auth.fake-base-id-provider.groups",
+ tester.settings().resetSettings("sonar.auth.fake-base-id-provider.enabled",
+ "sonar.auth.fake-base-id-provider.user",
+ "sonar.auth.fake-base-id-provider.throwUnauthorizedMessage",
+ "sonar.auth.fake-base-id-provider.enabledGroupsSync",
+ "sonar.auth.fake-base-id-provider.groups",
"sonar.auth.fake-base-id-provider.allowsUsersToSignUp");
}
@Test
- public void default_group_is_not_added_for_new_user_when_organizations_are_enabled() {
- Group group = tester.groups().generate(null);
+ public void default_group_is_not_added_for_new_user() {
+ Group group = tester.groups().generate();
enableUserCreationByAuthPlugin("aLogin");
setGroupsReturnedByAuthPlugin(group.getName());
}
@Test
- public void default_group_is_not_sync_for_existing_user_when_organizations_are_enabled() {
- Group group = tester.groups().generate(null);
+ public void default_group_is_not_sync_for_existing_user() {
+ Group group = tester.groups().generate();
User user = tester.users().generate();
enableUserCreationByAuthPlugin(user.getLogin());
setGroupsReturnedByAuthPlugin(group.getName());
}
@Test
- public void remove_default_group_when_organizations_are_enabled() {
- Group group = tester.groups().generate(null);
+ public void remove_default_group() {
+ Group group = tester.groups().generate();
User user = tester.users().generate();
// Add user as member of default organization
tester.wsClient().organizations().addMember(new AddMemberRequest().setOrganization("default-organization").setLogin(user.getLogin()));
}
private void enableUserCreationByAuthPlugin(String login) {
- tester.settings().setGlobalSettings("sonar.auth.fake-base-id-provider.user", login + ",fake-john,John,john@email.com");
+ tester.settings().setGlobalSettings("sonar.auth.fake-base-id-provider.user", login +"," + login + ",fake-" + login + ",John,john@email.com");
}
private void setGroupsReturnedByAuthPlugin(String... groups) {
import org.sonarqube.qa.util.pageobjects.Navigation;
import org.sonarqube.qa.util.pageobjects.SystemInfoPage;
import org.sonarqube.qa.util.pageobjects.UsersManagementPage;
+import org.sonarqube.ws.Users.SearchWsResponse.User;
import org.sonarqube.ws.client.GetRequest;
import org.sonarqube.ws.client.WsResponse;
import org.sonarqube.ws.client.users.CreateRequest;
+import org.sonarqube.ws.client.users.SearchRequest;
import util.user.UserRule;
-import util.user.Users;
import static java.net.HttpURLConnection.HTTP_OK;
import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.groups.Tuple.tuple;
import static org.junit.Assert.fail;
import static util.ItUtils.newOrchestratorBuilder;
import static util.ItUtils.newUserWsClient;
updateUsersInExtAuth(users);
// Then
verifyAuthenticationIsOk(username, password);
+ verifyUser();
// with external details and groups
runSelenese(orchestrator, "/user/ExternalAuthenticationTest/external-user-details.html");
updateUsersInExtAuth(users);
// Then
verifyAuthenticationIsOk(username, password);
+ verifyUser();
// with external details and groups
// TODO replace by WS ? Or with new Selenese utils
updateUsersInExtAuth(users);
// Then
verifyAuthenticationIsOk(username, password);
+ verifyUser();
verifyAuthenticationIsNotOk(username, "wrong");
}
updateUsersInExtAuth(users);
// check that the deleted/deactivated user "tester" has been reactivated and can now log in
verifyAuthenticationIsOk(login, password);
+ verifyUser();
}
/**
updateUsersInExtAuth(users);
verifyAuthenticationIsOk(login, password);
+ verifyUser();
verifyAuthenticationIsNotOk("wrong", password);
verifyAuthenticationIsNotOk(login, "wrong");
verifyAuthenticationIsNotOk(login, null);
USER_LOGIN + ".email", "tester@example.org"));
verifyAuthenticationIsOk(USER_LOGIN, "123");
- assertThat(userRule.getUserByLogin(USER_LOGIN).get())
- .extracting(Users.User::isLocal, Users.User::getExternalIdentity, Users.User::getExternalProvider)
- .containsOnly(false, USER_LOGIN, "sonarqube");
+ verifyUser();
}
@Test
assertThat(checkAuthenticationWithWebService(login, password).code()).isEqualTo(HTTP_UNAUTHORIZED);
}
+ private void verifyUser(){
+ assertThat(tester.wsClient().users().search(new SearchRequest().setQ(USER_LOGIN)).getUsersList())
+ .extracting(User::getLogin, User::getExternalIdentity, User::getExternalProvider, User::getLocal)
+ .containsExactlyInAnyOrder(tuple(USER_LOGIN, USER_LOGIN, "sonarqube", false));
+ }
+
private WsResponse checkAuthenticationWithWebService(String login, String password) {
// Call any WS
return newUserWsClient(orchestrator, login, password).wsConnector().call(new GetRequest("api/rules/search"));
import org.junit.runners.Suite;
import static util.ItUtils.newOrchestratorBuilder;
+import static util.ItUtils.pluginArtifact;
import static util.ItUtils.xooPlugin;
@RunWith(Suite.class)
@Suite.SuiteClasses({
+ OrganizationIdentityProviderTest.class,
SonarCloudHomepageTest.class,
SonarCloudNotificationsWsTest.class
})
public static final Orchestrator ORCHESTRATOR = newOrchestratorBuilder()
.addPlugin(xooPlugin())
+ // Used by OrganizationIdentityProviderTest
+ .addPlugin(pluginArtifact("base-auth-plugin"))
+
.setServerProperty("sonar.sonarcloud.enabled", "true")
// reduce memory for Elasticsearch
String login = randomAlphabetic(10);
String group = randomAlphabetic(10);
tester.users().generate(u -> u.setLogin(login).setPassword(login));
- tester.groups().generate(null, g -> g.setName(group));
+ tester.groups().generate(g -> g.setName(group));
tester.groups().addMemberToGroups(tester.organizations().getDefaultOrganization(), login, group);
List<Users.GroupsWsResponse.Group> result = tester.as(adminUser.getLogin()).wsClient().users().groups(new GroupsRequest().setLogin(login)).getGroupsList();