From 2e0c39c865767de5d9edd16a848282b57e217532 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Fri, 11 May 2018 09:24:33 +0200 Subject: [PATCH] SONAR-10597 Update MANUAL_MEASURES#USER_LOGIN to USER_UUID * SONAR-10597 Update MANUAL_MEASURES#USER_LOGIN to USER_UUD in DB * SONAR-10597 Update api/custom_measures/create to use user uuid * SONAR-10597 Update api/custom_measures/update to use user uuid * SONAR-10597 Remove CustomMeasureDao#selectOrFail * SONAR-10597 Update api/custom_measures/search to use user uuid * SONAR-10597 Clean up no more needed code * SONAR-10597 Add ITs to check manual measure after login update --- .../org/sonar/db/version/schema-h2.ddl | 2 +- .../db/measure/custom/CustomMeasureDao.java | 9 - .../db/measure/custom/CustomMeasureDto.java | 13 +- .../java/org/sonar/db/metric/MetricDao.java | 7 - .../main/java/org/sonar/db/user/UserDao.java | 9 - .../db/measure/custom/CustomMeasureMapper.xml | 8 +- .../org/sonar/db/measure/MeasureDbTester.java | 20 +- .../measure/custom/CustomMeasureDaoTest.java | 140 ++--- .../measure/custom/CustomMeasureTesting.java | 2 +- .../org/sonar/db/metric/MetricDaoTest.java | 16 - .../java/org/sonar/db/user/UserDaoTest.java | 21 +- .../select_by_metric_key_and_text_value.xml | 14 - .../db/migration/version/v72/DbVersion72.java | 1 + ...rLoginToUserUuidOnTableManualMeasures.java | 48 ++ .../version/v72/DbVersion72Test.java | 2 +- ...inToUserUuidOnTableManualMeasuresTest.java | 57 ++ .../manual_measures.sql | 12 + .../measure/custom/ws/CreateAction.java | 25 +- .../custom/ws/CustomMeasureJsonWriter.java | 15 +- .../measure/custom/ws/DeleteAction.java | 5 +- .../measure/custom/ws/SearchAction.java | 52 +- .../measure/custom/ws/UpdateAction.java | 16 +- .../measure/custom/ws/CreateActionTest.java | 508 ++++++++++-------- .../measure/custom/ws/DeleteActionTest.java | 4 +- .../measure/custom/ws/SearchActionTest.java | 506 ++++++++++------- .../measure/custom/ws/UpdateActionTest.java | 341 +++++------- .../user/ws/ChangePasswordActionTest.java | 8 +- .../ws/CreateActionTest/custom-measure.json | 17 - ...udUpdateLoginDuringAuthenticationTest.java | 64 +++ 29 files changed, 1079 insertions(+), 863 deletions(-) delete mode 100644 server/sonar-db-dao/src/test/resources/org/sonar/db/measure/custom/CustomMeasureDaoTest/select_by_metric_key_and_text_value.xml create mode 100644 server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v72/RenameUserLoginToUserUuidOnTableManualMeasures.java create mode 100644 server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/RenameUserLoginToUserUuidOnTableManualMeasuresTest.java create mode 100644 server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v72/RenameUserLoginToUserUuidOnTableManualMeasuresTest/manual_measures.sql delete mode 100644 server/sonar-server/src/test/resources/org/sonar/server/measure/custom/ws/CreateActionTest/custom-measure.json diff --git a/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl b/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl index 3c5de10a498..4f8a73a1ff4 100644 --- a/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl +++ b/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl @@ -404,7 +404,7 @@ CREATE TABLE "MANUAL_MEASURES" ( "COMPONENT_UUID" VARCHAR(50) NOT NULL, "VALUE" DOUBLE, "TEXT_VALUE" VARCHAR(4000), - "USER_LOGIN" VARCHAR(255), + "USER_UUID" VARCHAR(255), "DESCRIPTION" VARCHAR(4000), "CREATED_AT" BIGINT, "UPDATED_AT" BIGINT diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/custom/CustomMeasureDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/custom/CustomMeasureDao.java index 0f0aa3887d1..0530d537580 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/custom/CustomMeasureDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/custom/CustomMeasureDao.java @@ -25,7 +25,6 @@ import org.apache.ibatis.session.RowBounds; import org.sonar.db.Dao; import org.sonar.db.DatabaseUtils; import org.sonar.db.DbSession; -import org.sonar.db.RowNotFoundException; public class CustomMeasureDao implements Dao { public void insert(DbSession session, CustomMeasureDto customMeasureDto) { @@ -49,14 +48,6 @@ public class CustomMeasureDao implements Dao { return mapper(session).selectById(id); } - public CustomMeasureDto selectOrFail(DbSession session, long id) { - CustomMeasureDto customMeasure = selectById(session, id); - if (customMeasure == null) { - throw new RowNotFoundException(String.format("Custom measure '%d' not found.", id)); - } - return customMeasure; - } - public List selectByMetricId(DbSession session, int metricId) { return mapper(session).selectByMetricId(metricId); } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/custom/CustomMeasureDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/custom/CustomMeasureDto.java index 0282bce1a26..4cf4d0f41a8 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/custom/CustomMeasureDto.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/custom/CustomMeasureDto.java @@ -29,26 +29,27 @@ public class CustomMeasureDto { private String componentUuid; private double value; private String textValue; - private String userLogin; + private String userUuid; private String description; private long createdAt; private long updatedAt; + @CheckForNull public String getDescription() { return description; } - public CustomMeasureDto setDescription(String description) { + public CustomMeasureDto setDescription(@Nullable String description) { this.description = description; return this; } - public String getUserLogin() { - return userLogin; + public String getUserUuid() { + return userUuid; } - public CustomMeasureDto setUserLogin(String userLogin) { - this.userLogin = userLogin; + public CustomMeasureDto setUserUuid(String userUuid) { + this.userUuid = userUuid; return this; } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/metric/MetricDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/metric/MetricDao.java index 0f27ac2bae9..344cbb6e164 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/metric/MetricDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/metric/MetricDao.java @@ -141,11 +141,4 @@ public class MetricDao implements Dao { return mapper(session).selectById(id); } - public MetricDto selectOrFailById(DbSession session, long id) { - MetricDto metric = mapper(session).selectById(id); - if (metric == null) { - throw new RowNotFoundException(String.format("Metric id '%d' not found", id)); - } - return metric; - } } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDao.java index 4bd8de97b52..79318d4d02a 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDao.java @@ -35,7 +35,6 @@ import org.sonar.api.utils.System2; import org.sonar.core.util.UuidFactory; import org.sonar.db.Dao; import org.sonar.db.DbSession; -import org.sonar.db.RowNotFoundException; import org.sonar.db.component.ComponentDto; import org.sonar.db.organization.OrganizationDto; @@ -153,14 +152,6 @@ public class UserDao implements Dao { return mapper(session).selectByLogin(login); } - public UserDto selectOrFailByLogin(DbSession session, String login) { - UserDto user = selectByLogin(session, login); - if (user == null) { - throw new RowNotFoundException(String.format("User with login '%s' has not been found", login)); - } - return user; - } - public List selectByScmAccountOrLoginOrEmail(DbSession session, String scmAccountOrLoginOrEmail) { String like = new StringBuilder().append("%") .append(UserDto.SCM_ACCOUNTS_SEPARATOR).append(scmAccountOrLoginOrEmail) diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/custom/CustomMeasureMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/custom/CustomMeasureMapper.xml index 8735cb8dea5..ef334040b42 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/custom/CustomMeasureMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/custom/CustomMeasureMapper.xml @@ -8,7 +8,7 @@ m.component_uuid as componentUuid, m.value, m.text_value as textValue, - m.user_login as userLogin, + m.user_uuid as userUuid, m.description, m.created_at as createdAt, m.updated_at as updatedAt @@ -47,11 +47,11 @@ INSERT INTO manual_measures ( - metric_id, component_uuid, value, text_value, user_login, description, created_at, updated_at + metric_id, component_uuid, value, text_value, user_uuid, description, created_at, updated_at ) VALUES ( #{metricId, jdbcType=INTEGER}, #{componentUuid, jdbcType=VARCHAR}, - #{value, jdbcType=DOUBLE}, #{textValue, jdbcType=VARCHAR}, #{userLogin, jdbcType=VARCHAR}, + #{value, jdbcType=DOUBLE}, #{textValue, jdbcType=VARCHAR}, #{userUuid, jdbcType=VARCHAR}, #{description, jdbcType=VARCHAR}, #{createdAt, jdbcType=BIGINT}, #{updatedAt, jdbcType=BIGINT} ) @@ -61,7 +61,7 @@ set value = #{value, jdbcType=DOUBLE}, text_value = #{textValue, jdbcType=VARCHAR}, description = #{description, jdbcType=VARCHAR}, - user_login = #{userLogin, jdbcType=VARCHAR}, + user_uuid = #{userUuid, jdbcType=VARCHAR}, updated_at = #{updatedAt, jdbcType=BIGINT} where id = #{id} diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureDbTester.java b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureDbTester.java index dd5289151b3..597fdddc18c 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureDbTester.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureDbTester.java @@ -19,6 +19,7 @@ */ package org.sonar.db.measure; +import com.google.common.base.Preconditions; import java.util.Arrays; import java.util.function.Consumer; import org.sonar.db.DbClient; @@ -26,10 +27,13 @@ import org.sonar.db.DbSession; import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.SnapshotDto; +import org.sonar.db.measure.custom.CustomMeasureDto; import org.sonar.db.metric.MetricDto; +import org.sonar.db.user.UserDto; import static org.sonar.db.measure.MeasureTesting.newLiveMeasure; import static org.sonar.db.measure.MeasureTesting.newMeasureDto; +import static org.sonar.db.measure.custom.CustomMeasureTesting.newCustomMeasureDto; import static org.sonar.db.metric.MetricTesting.newMetricDto; public class MeasureDbTester { @@ -42,7 +46,7 @@ public class MeasureDbTester { } @SafeVarargs - public final MeasureDto insertMeasure(ComponentDto component, SnapshotDto analysis, MetricDto metricDto, Consumer... consumers){ + public final MeasureDto insertMeasure(ComponentDto component, SnapshotDto analysis, MetricDto metricDto, Consumer... consumers) { MeasureDto measureDto = newMeasureDto(metricDto, component, analysis); Arrays.stream(consumers).forEach(c -> c.accept(measureDto)); dbClient.measureDao().insert(dbSession, measureDto); @@ -51,7 +55,7 @@ public class MeasureDbTester { } @SafeVarargs - public final LiveMeasureDto insertLiveMeasure(ComponentDto component, MetricDto metric, Consumer... consumers){ + public final LiveMeasureDto insertLiveMeasure(ComponentDto component, MetricDto metric, Consumer... consumers) { LiveMeasureDto dto = newLiveMeasure(component, metric); Arrays.stream(consumers).forEach(c -> c.accept(dto)); dbClient.liveMeasureDao().insert(dbSession, dto); @@ -60,7 +64,17 @@ public class MeasureDbTester { } @SafeVarargs - public final MetricDto insertMetric(Consumer... consumers){ + public final CustomMeasureDto insertCustomMeasure(UserDto user, ComponentDto component, MetricDto metricDto, Consumer... consumers) { + Preconditions.checkArgument(metricDto.isUserManaged(),"Custom measure must be created from a custom metric"); + CustomMeasureDto dto = newCustomMeasureDto().setUserUuid(user.getUuid()).setComponentUuid(component.uuid()).setMetricId(metricDto.getId()); + Arrays.stream(consumers).forEach(c -> c.accept(dto)); + dbClient.customMeasureDao().insert(dbSession, dto); + dbSession.commit(); + return dto; + } + + @SafeVarargs + public final MetricDto insertMetric(Consumer... consumers) { MetricDto metricDto = newMetricDto(); Arrays.stream(consumers).forEach(c -> c.accept(metricDto)); dbClient.metricDao().insert(dbSession, metricDto); diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/custom/CustomMeasureDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/custom/CustomMeasureDaoTest.java index 4f4adcac167..ef24c3fbb3b 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/custom/CustomMeasureDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/custom/CustomMeasureDaoTest.java @@ -19,49 +19,48 @@ */ package org.sonar.db.measure.custom; -import java.util.Arrays; import java.util.List; -import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.sonar.api.utils.System2; import org.sonar.db.DbSession; import org.sonar.db.DbTester; -import org.sonar.db.RowNotFoundException; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.metric.MetricDto; +import org.sonar.db.user.UserDto; +import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.offset; +import static org.assertj.core.api.Assertions.tuple; import static org.sonar.db.measure.custom.CustomMeasureTesting.newCustomMeasureDto; - public class CustomMeasureDaoTest { @Rule public DbTester db = DbTester.create(System2.INSTANCE); - @Rule - public ExpectedException expectedException = ExpectedException.none(); - CustomMeasureDao underTest; - DbSession session; + private DbSession session = db.getSession(); - @Before - public void setUp() { - session = db.getSession(); - underTest = new CustomMeasureDao(); - } + private CustomMeasureDao underTest = new CustomMeasureDao(); @Test public void insert() { - CustomMeasureDto measure = newCustomMeasureDto(); + UserDto user = db.users().insertUser(); + ComponentDto project = db.components().insertPrivateProject(); + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true)); + CustomMeasureDto measure = newCustomMeasureDto() + .setComponentUuid(project.uuid()) + .setMetricId(metric.getId()) + .setUserUuid(user.getUuid()); underTest.insert(session, measure); - CustomMeasureDto result = underTest.selectOrFail(session, measure.getId()); + CustomMeasureDto result = underTest.selectById(session, measure.getId()); assertThat(result.getId()).isEqualTo(measure.getId()); - assertThat(result.getMetricId()).isEqualTo(measure.getMetricId()); - assertThat(result.getComponentUuid()).isEqualTo(measure.getComponentUuid()); + assertThat(result.getMetricId()).isEqualTo(metric.getId()); + assertThat(result.getComponentUuid()).isEqualTo(project.uuid()); + assertThat(result.getUserUuid()).isEqualTo(user.getUuid()); assertThat(result.getDescription()).isEqualTo(measure.getDescription()); - assertThat(result.getUserLogin()).isEqualTo(measure.getUserLogin()); assertThat(result.getTextValue()).isEqualTo(measure.getTextValue()); assertThat(result.getValue()).isCloseTo(measure.getValue(), offset(0.001d)); assertThat(result.getCreatedAt()).isEqualTo(measure.getCreatedAt()); @@ -70,60 +69,76 @@ public class CustomMeasureDaoTest { @Test public void delete_by_metric_id() { - CustomMeasureDto measure = newCustomMeasureDto(); - underTest.insert(session, measure); - assertThat(underTest.selectById(session, measure.getId())).isNotNull(); + UserDto user = db.users().insertUser(); + ComponentDto project = db.components().insertPrivateProject(); + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true)); + CustomMeasureDto measure = db.measures().insertCustomMeasure(user, project, metric); - underTest.deleteByMetricIds(session, Arrays.asList(measure.getMetricId())); + underTest.deleteByMetricIds(session, singletonList(measure.getMetricId())); assertThat(underTest.selectById(session, measure.getId())).isNull(); } @Test public void update() { - CustomMeasureDto measure = newCustomMeasureDto().setDescription("old-description"); - underTest.insert(session, measure); - measure.setDescription("new-description"); + UserDto user = db.users().insertUser(); + ComponentDto project = db.components().insertPrivateProject(); + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true)); + CustomMeasureDto measure = db.measures().insertCustomMeasure(user, project, metric, m -> m.setDescription("old-description")); - underTest.update(session, measure); + underTest.update(session, measure.setDescription("new-description")); assertThat(underTest.selectById(session, measure.getId()).getDescription()).isEqualTo("new-description"); } @Test public void delete() { - CustomMeasureDto measure = newCustomMeasureDto(); - underTest.insert(session, measure); + UserDto user = db.users().insertUser(); + ComponentDto project = db.components().insertPrivateProject(); + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true)); + CustomMeasureDto measure = db.measures().insertCustomMeasure(user, project, metric); underTest.delete(session, measure.getId()); + assertThat(underTest.selectById(session, measure.getId())).isNull(); } @Test public void select_by_component_uuid() { - underTest.insert(session, newCustomMeasureDto().setComponentUuid("u1")); - underTest.insert(session, newCustomMeasureDto().setComponentUuid("u1")); - underTest.insert(session, newCustomMeasureDto().setComponentUuid("u2")); - session.commit(); - - List result = underTest.selectByComponentUuid(session, "u1"); - - assertThat(result).hasSize(2); - assertThat(result).extracting("componentUuid").containsOnly("u1"); - assertThat(underTest.countByComponentUuid(session, "u1")).isEqualTo(2); + UserDto user = db.users().insertUser(); + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true)); + ComponentDto project1 = db.components().insertPrivateProject(); + CustomMeasureDto measure1 = db.measures().insertCustomMeasure(user, project1, metric); + CustomMeasureDto measure2 = db.measures().insertCustomMeasure(user, project1, metric); + ComponentDto project2 = db.components().insertPrivateProject(); + CustomMeasureDto measure3 = db.measures().insertCustomMeasure(user, project2, metric); + + assertThat(underTest.selectByComponentUuid(session, project1.uuid())) + .extracting(CustomMeasureDto::getId, CustomMeasureDto::getComponentUuid) + .containsOnly( + tuple(measure1.getId(), project1.uuid()), + tuple(measure2.getId(), project1.uuid())) + .doesNotContain(tuple(measure3.getId(), project2.uuid())); + + assertThat(underTest.countByComponentUuid(session, project1.uuid())).isEqualTo(2); } @Test public void select_by_component_uuid_with_options() { - underTest.insert(session, newCustomMeasureDto().setComponentUuid("u1")); - underTest.insert(session, newCustomMeasureDto().setComponentUuid("u1")); - underTest.insert(session, newCustomMeasureDto().setComponentUuid("u2")); - session.commit(); - - List result = underTest.selectByComponentUuid(session, "u1", 0, 100); - - assertThat(result).hasSize(2); - assertThat(result).extracting("componentUuid").containsOnly("u1"); + UserDto user = db.users().insertUser(); + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true)); + ComponentDto project1 = db.components().insertPrivateProject(); + CustomMeasureDto measure1 = db.measures().insertCustomMeasure(user, project1, metric); + CustomMeasureDto measure2 = db.measures().insertCustomMeasure(user, project1, metric); + ComponentDto project2 = db.components().insertPrivateProject(); + CustomMeasureDto measure3 = db.measures().insertCustomMeasure(user, project2, metric); + + assertThat(underTest.selectByComponentUuid(session, project1.uuid(), 0, 100)) + .extracting(CustomMeasureDto::getId, CustomMeasureDto::getComponentUuid) + .containsOnly( + tuple(measure1.getId(), project1.uuid()), + tuple(measure2.getId(), project1.uuid())) + .doesNotContain(tuple(measure3.getId(), project2.uuid())); } @Test @@ -146,22 +161,21 @@ public class CustomMeasureDaoTest { assertThat(count).isEqualTo(2); } - @Test - public void select_by_id_fail_if_no_measure_found() { - expectedException.expect(RowNotFoundException.class); - - underTest.selectOrFail(session, 42L); - } - @Test public void select_by_metric_key_and_text_value() { - db.prepareDbUnit(getClass(), "select_by_metric_key_and_text_value.xml"); - - List result = underTest.selectByMetricKeyAndTextValue(session, "customKey", "value1"); - - assertThat(result).extracting("id").containsOnly(20L, 21L); - - assertThat(underTest.selectByMetricKeyAndTextValue(session, "customKey", "unknown")).isEmpty(); - assertThat(underTest.selectByMetricKeyAndTextValue(session, "unknown", "value1")).isEmpty(); + UserDto user = db.users().insertUser(); + ComponentDto project = db.components().insertPrivateProject(); + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true)); + CustomMeasureDto customMeasure1 = db.measures().insertCustomMeasure(user, project, metric, m -> m.setTextValue("value")); + CustomMeasureDto customMeasure2 = db.measures().insertCustomMeasure(user, project, metric, m -> m.setTextValue("value")); + CustomMeasureDto customMeasure3 = db.measures().insertCustomMeasure(user, project, metric, m -> m.setTextValue("other value")); + + assertThat(underTest.selectByMetricKeyAndTextValue(session, metric.getKey(), "value")) + .extracting(CustomMeasureDto::getId) + .containsExactlyInAnyOrder(customMeasure1.getId(), customMeasure2.getId()) + .doesNotContain(customMeasure3.getId()); + + assertThat(underTest.selectByMetricKeyAndTextValue(session, metric.getKey(), "unknown")).isEmpty(); + assertThat(underTest.selectByMetricKeyAndTextValue(session, "unknown", "value")).isEmpty(); } } diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/custom/CustomMeasureTesting.java b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/custom/CustomMeasureTesting.java index 90dd2db8b80..4e812989b8d 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/measure/custom/CustomMeasureTesting.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/measure/custom/CustomMeasureTesting.java @@ -32,7 +32,7 @@ public class CustomMeasureTesting { return new CustomMeasureDto() .setDescription(RandomStringUtils.randomAlphanumeric(255)) .setTextValue(RandomStringUtils.randomAlphanumeric(255)) - .setUserLogin(RandomStringUtils.randomAlphanumeric(255)) + .setUserUuid("userUuid" + RandomStringUtils.randomAlphanumeric(100)) .setValue(RandomUtils.nextDouble()) .setMetricId(RandomUtils.nextInt()) .setComponentUuid(RandomStringUtils.randomAlphanumeric(50)) diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/metric/MetricDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/metric/MetricDaoTest.java index 34dbc169e36..6e56af068ed 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/metric/MetricDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/metric/MetricDaoTest.java @@ -197,22 +197,6 @@ public class MetricDaoTest { assertThat(result).isNotNull(); } - @Test - public void selectOrFailById() { - MetricDto metric = underTest.insert(dbSession, newMetricDto()); - - MetricDto result = underTest.selectOrFailById(dbSession, metric.getId()); - - assertThat(result).isNotNull(); - } - - @Test - public void fail_when_no_id_selectOrFailById() { - expectedException.expect(RowNotFoundException.class); - - underTest.selectOrFailById(dbSession, 42L); - } - @Test public void selectByIds() { MetricDto metric1 = underTest.insert(dbSession, newMetricDto()); diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/user/UserDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/user/UserDaoTest.java index 7a725cf13be..1ca0e6a9c01 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/user/UserDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/user/UserDaoTest.java @@ -26,7 +26,6 @@ import java.util.List; import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.sonar.api.user.UserQuery; import org.sonar.api.utils.DateUtils; import org.sonar.api.utils.System2; @@ -34,7 +33,6 @@ import org.sonar.db.DatabaseUtils; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; -import org.sonar.db.RowNotFoundException; import org.sonar.db.component.ComponentDto; import org.sonar.db.organization.OrganizationDto; @@ -43,7 +41,6 @@ import static java.util.Collections.emptyList; import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.groups.Tuple.tuple; -import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.sonar.db.user.GroupTesting.newGroupDto; @@ -54,8 +51,6 @@ public class UserDaoTest { private System2 system2 = mock(System2.class); - @Rule - public ExpectedException thrown = ExpectedException.none(); @Rule public DbTester db = DbTester.create(system2); @@ -509,7 +504,7 @@ public class UserDaoTest { underTest.insert(session, user); session.commit(); - underTest.cleanHomepage(session,user); + underTest.cleanHomepage(session, user); UserDto reloaded = underTest.selectUserById(session, user.getId()); assertThat(reloaded.getUpdatedAt()).isEqualTo(NOW); @@ -538,7 +533,7 @@ public class UserDaoTest { UserDto user2 = db.users().insertUser(); underTest.setRoot(session, user2.getLogin(), true); - UserDto dto = underTest.selectOrFailByLogin(session, user1.getLogin()); + UserDto dto = underTest.selectByLogin(session, user1.getLogin()); assertThat(dto.getId()).isEqualTo(user1.getId()); assertThat(dto.getLogin()).isEqualTo("marius"); assertThat(dto.getName()).isEqualTo("Marius"); @@ -553,7 +548,7 @@ public class UserDaoTest { assertThat(dto.getHomepageType()).isEqualTo("project"); assertThat(dto.getHomepageParameter()).isEqualTo("OB1"); - dto = underTest.selectOrFailByLogin(session, user2.getLogin()); + dto = underTest.selectByLogin(session, user2.getLogin()); assertThat(dto.isRoot()).isTrue(); } @@ -579,16 +574,6 @@ public class UserDaoTest { assertThat(results).hasSize(2); } - @Test - public void select_by_login_with_unknown_login() { - try { - underTest.selectOrFailByLogin(session, "unknown"); - fail(); - } catch (Exception e) { - assertThat(e).isInstanceOf(RowNotFoundException.class).hasMessage("User with login 'unknown' has not been found"); - } - } - @Test public void select_nullable_by_login() { db.users().insertUser(user -> user.setLogin("marius")); diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/measure/custom/CustomMeasureDaoTest/select_by_metric_key_and_text_value.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/measure/custom/CustomMeasureDaoTest/select_by_metric_key_and_text_value.xml deleted file mode 100644 index ff00f759c69..00000000000 --- a/server/sonar-db-dao/src/test/resources/org/sonar/db/measure/custom/CustomMeasureDaoTest/select_by_metric_key_and_text_value.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v72/DbVersion72.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v72/DbVersion72.java index c8cf8a2fbb1..20d40419ebe 100644 --- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v72/DbVersion72.java +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v72/DbVersion72.java @@ -47,6 +47,7 @@ public class DbVersion72 implements DbVersion { .add(2117, "Drop USER_ID from table organizations", DropUserIdFromOrganizations.class) .add(2118, "Rename USER_LOGIN TO USER_UUID on table QPROFILE_CHANGES", RenameUserLoginToUserUuidOnTableQProfileChanges.class) .add(2119, "Rename LOGIN TO USER_UUID on table USER_TOKENS", RenameLoginToUserUuidOnTableUserTokens.class) + .add(2120, "Rename USER_LOGIN TO USER_UUID on table MANUAL_MEASURES", RenameUserLoginToUserUuidOnTableManualMeasures.class); ; } } diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v72/RenameUserLoginToUserUuidOnTableManualMeasures.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v72/RenameUserLoginToUserUuidOnTableManualMeasures.java new file mode 100644 index 00000000000..924ab02eb33 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v72/RenameUserLoginToUserUuidOnTableManualMeasures.java @@ -0,0 +1,48 @@ +/* + * 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 RenameUserLoginToUserUuidOnTableManualMeasures extends DdlChange { + + private static final String TABLE = "manual_measures"; + + public RenameUserLoginToUserUuidOnTableManualMeasures(Database db) { + super(db); + } + + @Override + public void execute(Context context) throws SQLException { + context.execute(new RenameColumnsBuilder(getDialect(), TABLE) + .renameColumn("user_login", + newVarcharColumnDefBuilder() + .setColumnName("user_uuid") + .setLimit(255) + .setIsNullable(true) + .build()) + .build()); + } +} diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/DbVersion72Test.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/DbVersion72Test.java index 4cd2886c568..87922b1bf39 100644 --- a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/DbVersion72Test.java +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/DbVersion72Test.java @@ -34,7 +34,7 @@ public class DbVersion72Test { @Test public void verify_migration_count() { - verifyMigrationCount(underTest, 20); + verifyMigrationCount(underTest, 21); } } diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/RenameUserLoginToUserUuidOnTableManualMeasuresTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/RenameUserLoginToUserUuidOnTableManualMeasuresTest.java new file mode 100644 index 00000000000..2ab573ac3e8 --- /dev/null +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/RenameUserLoginToUserUuidOnTableManualMeasuresTest.java @@ -0,0 +1,57 @@ +/* + * 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 RenameUserLoginToUserUuidOnTableManualMeasuresTest { + + @Rule + public final CoreDbTester db = CoreDbTester.createForSchema(RenameUserLoginToUserUuidOnTableManualMeasuresTest.class, "manual_measures.sql"); + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private RenameUserLoginToUserUuidOnTableManualMeasures underTest = new RenameUserLoginToUserUuidOnTableManualMeasures(db.database()); + + @Test + public void rename_column() throws SQLException { + underTest.execute(); + + db.assertColumnDefinition("manual_measures", "user_uuid", VARCHAR, 255, true); + db.assertColumnDoesNotExist("manual_measures", "user_login"); + } + + public void migration_is_not_reentrant() throws SQLException { + underTest.execute(); + + expectedException.expect(IllegalStateException.class); + + underTest.execute(); + } + +} diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v72/RenameUserLoginToUserUuidOnTableManualMeasuresTest/manual_measures.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v72/RenameUserLoginToUserUuidOnTableManualMeasuresTest/manual_measures.sql new file mode 100644 index 00000000000..598cb6885d2 --- /dev/null +++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v72/RenameUserLoginToUserUuidOnTableManualMeasuresTest/manual_measures.sql @@ -0,0 +1,12 @@ +CREATE TABLE "MANUAL_MEASURES" ( + "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "METRIC_ID" INTEGER NOT NULL, + "COMPONENT_UUID" VARCHAR(50) NOT NULL, + "VALUE" DOUBLE, + "TEXT_VALUE" VARCHAR(4000), + "USER_LOGIN" VARCHAR(255), + "DESCRIPTION" VARCHAR(4000), + "CREATED_AT" BIGINT, + "UPDATED_AT" BIGINT +); +CREATE INDEX "MANUAL_MEASURES_COMPONENT_UUID" ON "MANUAL_MEASURES" ("COMPONENT_UUID"); \ No newline at end of file diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CreateAction.java b/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CreateAction.java index 658c23167db..69dbbe4e213 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CreateAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CreateAction.java @@ -35,6 +35,8 @@ import org.sonar.server.component.ComponentFinder; import org.sonar.server.user.UserSession; import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; +import static java.util.Objects.requireNonNull; import static org.sonar.server.component.ComponentFinder.ParamNames.PROJECT_ID_AND_KEY; import static org.sonar.server.measure.custom.ws.CustomMeasureValidator.checkPermissions; import static org.sonar.server.measure.custom.ws.CustomMeasureValueDescription.measureValueDescription; @@ -115,12 +117,14 @@ public class CreateAction implements CustomMeasuresWsAction { checkPermissions(userSession, component); checkIsProjectOrModule(component); checkMeasureDoesNotExistAlready(dbSession, component, metric); - UserDto user = dbClient.userDao().selectOrFailByLogin(dbSession, userSession.getLogin()); + String userUuid = requireNonNull(userSession.getUuid(), "User uuid should not be null"); + UserDto user = dbClient.userDao().selectByUuid(dbSession, userUuid); + checkState(user != null, "User with uuid '%s' does not exist", userUuid); CustomMeasureDto measure = new CustomMeasureDto() .setComponentUuid(component.uuid()) .setMetricId(metric.getId()) .setDescription(description) - .setUserLogin(user.getLogin()) + .setUserUuid(user.getUuid()) .setCreatedAt(now) .setUpdatedAt(now); validator.setMeasureValue(measure, valueAsString, metric); @@ -134,14 +138,14 @@ public class CreateAction implements CustomMeasuresWsAction { } private static void checkIsProjectOrModule(ComponentDto component) { - checkRequest(Scopes.PROJECT.equals(component.scope()), "Component '%s' (id: %s) must be a project or a module.", component.getDbKey(), component.uuid()); + checkRequest(Scopes.PROJECT.equals(component.scope()), "Component '%s' must be a project or a module.", component.getDbKey()); } private void checkMeasureDoesNotExistAlready(DbSession dbSession, ComponentDto component, MetricDto metric) { int nbMeasuresOnSameMetricAndMeasure = dbClient.customMeasureDao().countByComponentIdAndMetricId(dbSession, component.uuid(), metric.getId()); checkRequest(nbMeasuresOnSameMetricAndMeasure == 0, - "A measure already exists for project '%s' (id: %s) and metric '%s' (id: '%d')", - component.getDbKey(), component.uuid(), metric.getKey(), metric.getId()); + "A measure already exists for project '%s' and metric '%s'", + component.getDbKey(), metric.getKey()); } private MetricDto searchMetric(DbSession dbSession, Request request) { @@ -149,10 +153,13 @@ public class CreateAction implements CustomMeasuresWsAction { String metricKey = request.param(PARAM_METRIC_KEY); checkArgument(metricId != null ^ metricKey != null, "Either the metric id or the metric key must be provided"); - if (metricId != null) { - return dbClient.metricDao().selectOrFailById(dbSession, metricId); + if (metricId == null) { + MetricDto metric = dbClient.metricDao().selectByKey(dbSession, metricKey); + checkArgument(metric != null, "Metric with key '%s' does not exist", metricKey); + return metric; } - - return dbClient.metricDao().selectOrFailByKey(dbSession, metricKey); + MetricDto metric = dbClient.metricDao().selectById(dbSession, metricId); + checkArgument(metric != null, "Metric with id '%s' does not exist", metricId); + return metric; } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CustomMeasureJsonWriter.java b/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CustomMeasureJsonWriter.java index 117570c2a95..c686e3ab093 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CustomMeasureJsonWriter.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CustomMeasureJsonWriter.java @@ -22,8 +22,6 @@ package org.sonar.server.measure.custom.ws; import com.google.common.collect.ImmutableSet; import java.util.Collection; import java.util.Date; -import java.util.List; -import java.util.Map; import java.util.Set; import javax.annotation.Nullable; import org.sonar.api.measures.Metric; @@ -59,7 +57,8 @@ public class CustomMeasureJsonWriter { this.userJsonWriter = userJsonWriter; } - public void write(JsonWriter json, CustomMeasureDto measure, MetricDto metric, ComponentDto component, UserDto user, boolean isPending, Collection fieldsToReturn) { + public void write(JsonWriter json, CustomMeasureDto measure, MetricDto metric, ComponentDto component, UserDto user, boolean isPending, + @Nullable Collection fieldsToReturn) { json.beginObject(); json.prop(FIELD_ID, String.valueOf(measure.getId())); writeIfNeeded(json, measureValue(measure, metric), FIELD_VALUE, fieldsToReturn); @@ -109,14 +108,4 @@ public class CustomMeasureJsonWriter { } } - public void write(JsonWriter json, List customMeasures, ComponentDto project, Map metricsById, Map usersByLogin, - @Nullable Long lastAnalysisTimestamp, Collection fieldsToReturn) { - json.name("customMeasures"); - json.beginArray(); - for (CustomMeasureDto customMeasure : customMeasures) { - boolean pending = lastAnalysisTimestamp == null || lastAnalysisTimestamp < customMeasure.getUpdatedAt(); - write(json, customMeasure, metricsById.get(customMeasure.getMetricId()), project, usersByLogin.get(customMeasure.getUserLogin()), pending, fieldsToReturn); - } - json.endArray(); - } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/DeleteAction.java b/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/DeleteAction.java index 2ab63b63628..e9130a9d4af 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/DeleteAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/DeleteAction.java @@ -29,6 +29,8 @@ import org.sonar.db.component.ComponentDto; import org.sonar.db.measure.custom.CustomMeasureDto; import org.sonar.server.user.UserSession; +import static com.google.common.base.Preconditions.checkArgument; + public class DeleteAction implements CustomMeasuresWsAction { private static final String ACTION = "delete"; @@ -61,7 +63,8 @@ public class DeleteAction implements CustomMeasuresWsAction { long id = request.mandatoryParamAsLong(PARAM_ID); try (DbSession dbSession = dbClient.openSession(false)) { - CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectOrFail(dbSession, id); + CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectById(dbSession, id); + checkArgument(customMeasure != null, "Custom measure with id '%s' does not exist", id); checkPermission(dbSession, customMeasure); dbClient.customMeasureDao().delete(dbSession, id); dbSession.commit(); diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/SearchAction.java index f6aa74f6be8..14af7c1a21c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/SearchAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/SearchAction.java @@ -20,12 +20,13 @@ package org.sonar.server.measure.custom.ws; import com.google.common.base.Function; -import com.google.common.collect.FluentIterable; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import javax.annotation.CheckForNull; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -33,6 +34,7 @@ import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; import org.sonar.api.utils.text.JsonWriter; +import org.sonar.core.util.stream.MoreCollectors; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.component.ComponentDto; @@ -103,10 +105,10 @@ public class SearchAction implements CustomMeasuresWsAction { Long lastAnalysisDateMs = searchLastSnapshotDate(dbSession, component); List customMeasures = searchCustomMeasures(dbSession, component, searchOptions); int nbCustomMeasures = countTotalOfCustomMeasures(dbSession, component); - Map usersByLogin = usersByLogin(dbSession, customMeasures); + Map usersByUuid = usersByUuid(dbSession, customMeasures); Map metricsById = metricsById(dbSession, customMeasures); - writeResponse(response, customMeasures, nbCustomMeasures, component, metricsById, usersByLogin, lastAnalysisDateMs, searchOptions, fieldsToReturn); + writeResponse(response, customMeasures, nbCustomMeasures, component, metricsById, usersByUuid, lastAnalysisDateMs, searchOptions, fieldsToReturn); } } @@ -126,44 +128,36 @@ public class SearchAction implements CustomMeasuresWsAction { } private void writeResponse(Response response, List customMeasures, int nbCustomMeasures, ComponentDto project, Map metricsById, - Map usersByLogin, @Nullable Long lastAnalysisDate, SearchOptions searchOptions, List fieldsToReturn) { + Map usersByUuid, @Nullable Long lastAnalysisDate, SearchOptions searchOptions, @Nullable List fieldsToReturn) { JsonWriter json = response.newJsonWriter(); json.beginObject(); - customMeasureJsonWriter.write(json, customMeasures, project, metricsById, usersByLogin, lastAnalysisDate, fieldsToReturn); + writeUsers(json, customMeasures, project, metricsById, usersByUuid, lastAnalysisDate, fieldsToReturn); searchOptions.writeJson(json, nbCustomMeasures); json.endObject(); json.close(); } + private void writeUsers(JsonWriter json, List customMeasures, ComponentDto project, Map metricsById, Map usersByUuids, + @Nullable Long lastAnalysisTimestamp, @Nullable Collection fieldsToReturn) { + json.name("customMeasures"); + json.beginArray(); + for (CustomMeasureDto customMeasure : customMeasures) { + boolean pending = lastAnalysisTimestamp == null || lastAnalysisTimestamp < customMeasure.getUpdatedAt(); + customMeasureJsonWriter.write(json, customMeasure, metricsById.get(customMeasure.getMetricId()), project, usersByUuids.get(customMeasure.getUserUuid()), pending, + fieldsToReturn); + } + json.endArray(); + } + private Map metricsById(DbSession dbSession, List customMeasures) { List metrics = dbClient.metricDao().selectByIds(dbSession, newHashSet(Lists.transform(customMeasures, CustomMeasureToMetricIdFunction.INSTANCE))); return Maps.uniqueIndex(metrics, MetricToIdFunction.INSTANCE); } - private Map usersByLogin(DbSession dbSession, List customMeasures) { - List logins = FluentIterable.from(customMeasures) - .transform(CustomMeasureToUserLoginFunction.INSTANCE) - .toList(); - List userDtos = dbClient.userDao().selectByLogins(dbSession, logins); - return FluentIterable.from(userDtos).uniqueIndex(UserDtoToLogin.INSTANCE); - } - - private enum CustomMeasureToUserLoginFunction implements Function { - INSTANCE; - - @Override - public String apply(@Nonnull CustomMeasureDto customMeasure) { - return customMeasure.getUserLogin(); - } - } - - private enum UserDtoToLogin implements Function { - INSTANCE; - - @Override - public String apply(@Nonnull UserDto input) { - return input.getLogin(); - } + private Map usersByUuid(DbSession dbSession, List customMeasures) { + Set userUuids = customMeasures.stream().map(CustomMeasureDto::getUserUuid).collect(MoreCollectors.toSet()); + List users = dbClient.userDao().selectByUuids(dbSession, userUuids); + return users.stream().collect(MoreCollectors.uniqueIndex(UserDto::getUuid)); } private enum CustomMeasureToMetricIdFunction implements Function { diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/UpdateAction.java b/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/UpdateAction.java index 09d8d8ca842..7e83e7a02e1 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/UpdateAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/UpdateAction.java @@ -33,6 +33,9 @@ import org.sonar.db.metric.MetricDto; import org.sonar.db.user.UserDto; import org.sonar.server.user.UserSession; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; +import static java.util.Objects.requireNonNull; import static org.sonar.server.measure.custom.ws.CustomMeasureValidator.checkPermissions; import static org.sonar.server.measure.custom.ws.CustomMeasureValueDescription.measureValueDescription; @@ -86,15 +89,20 @@ public class UpdateAction implements CustomMeasuresWsAction { checkParameters(value, description); try (DbSession dbSession = dbClient.openSession(true)) { - CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectOrFail(dbSession, id); - MetricDto metric = dbClient.metricDao().selectOrFailById(dbSession, customMeasure.getMetricId()); + CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectById(dbSession, id); + checkArgument(customMeasure != null, "Custom measure with id '%s' does not exist", id); + int customMetricId = customMeasure.getMetricId(); + MetricDto metric = dbClient.metricDao().selectById(dbSession, customMetricId); + checkState(metric != null, "Metric with id '%s' does not exist", customMetricId); ComponentDto component = dbClient.componentDao().selectOrFailByUuid(dbSession, customMeasure.getComponentUuid()); checkPermissions(userSession, component); - UserDto user = dbClient.userDao().selectOrFailByLogin(dbSession, userSession.getLogin()); + String userUuid = requireNonNull(userSession.getUuid(), "User uuid should not be null"); + UserDto user = dbClient.userDao().selectByUuid(dbSession, userUuid); + checkState(user != null, "User with uuid '%s' does not exist", userUuid); setValue(customMeasure, value, metric); setDescription(customMeasure, description); - customMeasure.setUserLogin(user.getLogin()); + customMeasure.setUserUuid(user.getUuid()); customMeasure.setUpdatedAt(system.now()); dbClient.customMeasureDao().update(dbSession, customMeasure); dbSession.commit(); diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/CreateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/CreateActionTest.java index 1b8ef114ca7..9c06cb624c6 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/CreateActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/CreateActionTest.java @@ -19,52 +19,43 @@ */ package org.sonar.server.measure.custom.ws; -import java.util.List; -import org.assertj.core.data.Offset; -import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.sonar.api.measures.Metric; -import org.sonar.api.measures.Metric.ValueType; import org.sonar.api.utils.System2; -import org.sonar.api.web.UserRole; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; import org.sonar.db.DbTester; -import org.sonar.db.RowNotFoundException; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ComponentTesting; import org.sonar.db.measure.custom.CustomMeasureDto; import org.sonar.db.metric.MetricDto; -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.server.component.TestComponentFinder; import org.sonar.server.es.EsTester; import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.NotFoundException; -import org.sonar.server.exceptions.ServerException; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.user.ws.UserJsonWriter; -import org.sonar.server.ws.WsTester; +import org.sonar.server.ws.WsActionTester; +import static java.lang.String.format; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.data.Offset.offset; +import static org.assertj.core.api.Assertions.tuple; import static org.sonar.api.measures.Metric.ValueType.BOOL; import static org.sonar.api.measures.Metric.ValueType.FLOAT; import static org.sonar.api.measures.Metric.ValueType.INT; 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.api.web.UserRole.ADMIN; +import static org.sonar.db.component.ComponentTesting.newModuleDto; import static org.sonar.server.util.TypeValidationsTesting.newFullTypeValidations; +import static org.sonar.test.JsonAssert.assertJson; public class CreateActionTest { - private static final String DEFAULT_PROJECT_UUID = "project-uuid"; - private static final String DEFAULT_PROJECT_KEY = "project-key"; - @Rule public UserSessionRule userSession = UserSessionRule.standalone(); @Rule @@ -74,284 +65,311 @@ public class CreateActionTest { @Rule public EsTester es = EsTester.create(); - private DbClient dbClient = db.getDbClient(); - private ComponentDto project; - private final DbSession dbSession = db.getSession(); - private WsTester ws; - - @Before - public void setUp() { - ws = new WsTester(new CustomMeasuresWs(new CreateAction(dbClient, userSession, System2.INSTANCE, new CustomMeasureValidator(newFullTypeValidations()), - new CustomMeasureJsonWriter(new UserJsonWriter(userSession)), TestComponentFinder.from(db)))); - - db.users().insertUser(u -> u.setLogin("login") - .setName("Login") - .setEmail("login@login.com") - .setActive(true)); - - OrganizationDto organizationDto = db.organizations().insert(); - project = ComponentTesting.newPrivateProjectDto(organizationDto, DEFAULT_PROJECT_UUID).setDbKey(DEFAULT_PROJECT_KEY); - dbClient.componentDao().insert(dbSession, project); - dbSession.commit(); - userSession.logIn("login").addProjectPermission(UserRole.ADMIN, project); - } + private WsActionTester ws = new WsActionTester( + new CreateAction(db.getDbClient(), userSession, System2.INSTANCE, new CustomMeasureValidator(newFullTypeValidations()), + new CustomMeasureJsonWriter(new UserJsonWriter(userSession)), TestComponentFinder.from(db))); @Test - public void create_boolean_custom_measure_in_db() throws Exception { - MetricDto metric = insertMetric(BOOL); - - newRequest() - .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID) - .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString()) + public void create_boolean_custom_measure_in_db() { + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(BOOL.name())); + ComponentDto project = db.components().insertPrivateProject(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).addProjectPermission(ADMIN, project); + + ws.newRequest() + .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid()) + .setParam(CreateAction.PARAM_METRIC_ID, Integer.toString(metric.getId())) .setParam(CreateAction.PARAM_DESCRIPTION, "custom-measure-description") .setParam(CreateAction.PARAM_VALUE, "true") .execute(); - List customMeasures = dbClient.customMeasureDao().selectByMetricId(dbSession, metric.getId()); - CustomMeasureDto customMeasure = customMeasures.get(0); - assertThat(customMeasures).hasSize(1); - assertThat(customMeasure.getDescription()).isEqualTo("custom-measure-description"); - assertThat(customMeasure.getTextValue()).isNullOrEmpty(); - assertThat(customMeasure.getValue()).isCloseTo(1.0d, offset(0.01d)); - assertThat(customMeasure.getComponentUuid()).isEqualTo(DEFAULT_PROJECT_UUID); + assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId())) + .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getComponentUuid) + .containsExactlyInAnyOrder(tuple("custom-measure-description", null, 1d, project.uuid())); } @Test - public void create_int_custom_measure_in_db() throws Exception { - MetricDto metric = insertMetric(INT); - - newRequest() - .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID) + public void create_int_custom_measure_in_db() { + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(INT.name())); + ComponentDto project = db.components().insertPrivateProject(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).addProjectPermission(ADMIN, project); + + ws.newRequest() + .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid()) .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString()) .setParam(CreateAction.PARAM_VALUE, "42") .execute(); - CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectByMetricId(dbSession, metric.getId()).get(0); - assertThat(customMeasure.getTextValue()).isNullOrEmpty(); - assertThat(customMeasure.getValue()).isCloseTo(42.0d, offset(0.01d)); - } - - @Test - public void create_text_custom_measure_in_db() throws Exception { - MetricDto metric = insertMetric(STRING); - - newRequest() - .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID) - .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString()) - .setParam(CreateAction.PARAM_VALUE, "custom-measure-free-text") - .execute(); - - CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectByMetricId(dbSession, metric.getId()).get(0); - assertThat(customMeasure.getTextValue()).isEqualTo("custom-measure-free-text"); + assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId())) + .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getComponentUuid) + .containsExactlyInAnyOrder(tuple(null, null, 42d, project.uuid())); } @Test - public void create_text_custom_measure_as_project_admin() throws Exception { - MetricDto metric = insertMetric(STRING); - userSession.logIn("login").addProjectPermission(UserRole.ADMIN, project); - - newRequest() - .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID) + public void create_text_custom_measure_in_db() { + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + ComponentDto project = db.components().insertPrivateProject(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).addProjectPermission(ADMIN, project); + + ws.newRequest() + .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid()) .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString()) .setParam(CreateAction.PARAM_VALUE, "custom-measure-free-text") .execute(); - CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectByMetricId(dbSession, metric.getId()).get(0); - assertThat(customMeasure).isNotNull(); + assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId())) + .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getComponentUuid) + .containsExactlyInAnyOrder(tuple(null, "custom-measure-free-text", 0d, project.uuid())); } @Test - public void create_text_custom_measure_with_metric_key() throws Exception { - MetricDto metric = insertMetric(STRING); - - newRequest() - .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID) + public void create_text_custom_measure_with_metric_key() { + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + ComponentDto project = db.components().insertPrivateProject(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).addProjectPermission(ADMIN, project); + + ws.newRequest() + .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid()) .setParam(CreateAction.PARAM_METRIC_KEY, metric.getKey()) .setParam(CreateAction.PARAM_VALUE, "whatever-value") .execute(); - CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectByMetricId(dbSession, metric.getId()).get(0); - assertThat(customMeasure).isNotNull(); + assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId())) + .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getComponentUuid) + .containsExactlyInAnyOrder(tuple(null, "whatever-value", 0d, project.uuid())); } @Test - public void create_text_custom_measure_with_project_key() throws Exception { - MetricDto metric = insertMetric(STRING); - - newRequest() - .setParam(CreateAction.PARAM_PROJECT_KEY, DEFAULT_PROJECT_KEY) + public void create_text_custom_measure_with_project_key() { + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + ComponentDto project = db.components().insertPrivateProject(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).addProjectPermission(ADMIN, project); + + ws.newRequest() + .setParam(CreateAction.PARAM_PROJECT_KEY, project.getKey()) .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString()) .setParam(CreateAction.PARAM_VALUE, "whatever-value") .execute(); - CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectByMetricId(dbSession, metric.getId()).get(0); - assertThat(customMeasure).isNotNull(); + assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId())) + .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getComponentUuid) + .containsExactlyInAnyOrder(tuple(null, "whatever-value", 0d, project.uuid())); } @Test - public void create_float_custom_measure_in_db() throws Exception { - MetricDto metric = insertMetric(FLOAT); - - newRequest() - .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID) + public void create_float_custom_measure_in_db() { + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(FLOAT.name())); + ComponentDto project = db.components().insertPrivateProject(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).addProjectPermission(ADMIN, project); + + ws.newRequest() + .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid()) .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString()) .setParam(CreateAction.PARAM_VALUE, "4.2") .execute(); - CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectByMetricId(dbSession, metric.getId()).get(0); - assertThat(customMeasure.getValue()).isCloseTo(4.2d, Offset.offset(0.01d)); - assertThat(customMeasure.getTextValue()).isNullOrEmpty(); + assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId())) + .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getComponentUuid) + .containsExactlyInAnyOrder(tuple(null, null, 4.2d, project.uuid())); } @Test - public void create_work_duration_custom_measure_in_db() throws Exception { - MetricDto metric = insertMetric(WORK_DUR); - - newRequest() - .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID) + public void create_work_duration_custom_measure_in_db() { + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(WORK_DUR.name())); + ComponentDto project = db.components().insertPrivateProject(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).addProjectPermission(ADMIN, project); + + ws.newRequest() + .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid()) .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString()) .setParam(CreateAction.PARAM_VALUE, "253") .execute(); - CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectByMetricId(dbSession, metric.getId()).get(0); - assertThat(customMeasure.getTextValue()).isNullOrEmpty(); - assertThat(customMeasure.getValue()).isCloseTo(253, offset(0.01d)); + assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId())) + .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getComponentUuid) + .containsExactlyInAnyOrder(tuple(null, null, 253d, project.uuid())); } @Test - public void create_level_type_custom_measure_in_db() throws Exception { - MetricDto metric = insertMetric(LEVEL); - - newRequest() - .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID) + public void create_level_type_custom_measure_in_db() { + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(LEVEL.name())); + ComponentDto project = db.components().insertPrivateProject(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).addProjectPermission(ADMIN, project); + + ws.newRequest() + .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid()) .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString()) .setParam(CreateAction.PARAM_VALUE, Metric.Level.WARN.name()) .execute(); - CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectByMetricId(dbSession, metric.getId()).get(0); - assertThat(customMeasure.getTextValue()).isEqualTo(Metric.Level.WARN.name()); + assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId())) + .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getComponentUuid) + .containsExactlyInAnyOrder(tuple(null, Metric.Level.WARN.name(), 0d, project.uuid())); } @Test - public void response_with_object_and_id() throws Exception { - MetricDto metric = insertMetric(STRING); - - WsTester.Result response = newRequest() - .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID) + public void response_with_object_and_id() { + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + ComponentDto project = db.components().insertPrivateProject(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).addProjectPermission(ADMIN, project); + + String response = ws.newRequest() + .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid()) .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString()) .setParam(CreateAction.PARAM_DESCRIPTION, "custom-measure-description") .setParam(CreateAction.PARAM_VALUE, "custom-measure-free-text") - .execute(); - - CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectByMetricId(dbSession, metric.getId()).get(0); - response.assertJson(getClass(), "custom-measure.json"); - assertThat(response.outputAsString()).matches(String.format(".*\"id\"\\s*:\\s*\"%d\".*", customMeasure.getId())); - assertThat(response.outputAsString()).matches(String.format(".*\"id\"\\s*:\\s*\"%d\".*", metric.getId())); + .execute() + .getInput(); + + CustomMeasureDto customMeasure = db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId()).get(0); + assertJson(response).isSimilarTo("{\n" + + " \"id\": \"" + customMeasure.getId() + "\",\n" + + " \"value\": \"custom-measure-free-text\",\n" + + " \"description\": \"custom-measure-description\",\n" + + " \"metric\": {\n" + + " \"id\": \"" + metric.getId() + "\",\n" + + " \"key\": \"" + metric.getKey() + "\",\n" + + " \"type\": \"" + metric.getValueType() + "\",\n" + + " \"name\": \"" + metric.getShortName() + "\",\n" + + " \"domain\": \"" + metric.getDomain() + "\"\n" + + " },\n" + + " \"projectId\": \"" + project.uuid() + "\",\n" + + " \"projectKey\": \"" + project.getKey() + "\",\n" + + " \"pending\": true\n" + + "}"); } @Test - public void create_custom_measure_on_a_view() throws Exception { - String viewUuid = "VIEW_UUID"; - ComponentDto view = ComponentTesting.newView(db.organizations().insert(), viewUuid); - dbClient.componentDao().insert(dbSession, view); - dbSession.commit(); - MetricDto metric = insertMetric(BOOL); - userSession.logIn("login").addProjectPermission(UserRole.ADMIN, view); - - newRequest() - .setParam(CreateAction.PARAM_PROJECT_ID, viewUuid) - .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString()) + public void create_custom_measure_on_module() { + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(BOOL.name())); + ComponentDto project = db.components().insertPrivateProject(); + ComponentDto module = db.components().insertComponent(newModuleDto(project)); + UserDto user = db.users().insertUser(); + userSession.logIn(user).addProjectPermission(ADMIN, project); + + ws.newRequest() + .setParam(CreateAction.PARAM_PROJECT_ID, module.uuid()) + .setParam(CreateAction.PARAM_METRIC_ID, Integer.toString(metric.getId())) .setParam(CreateAction.PARAM_DESCRIPTION, "custom-measure-description") .setParam(CreateAction.PARAM_VALUE, "true") .execute(); - List customMeasures = dbClient.customMeasureDao().selectByMetricId(dbSession, metric.getId()); - CustomMeasureDto customMeasure = customMeasures.get(0); - assertThat(customMeasures).hasSize(1); - assertThat(customMeasure.getComponentUuid()).isEqualTo(viewUuid); + assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId())) + .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getComponentUuid) + .containsExactlyInAnyOrder(tuple("custom-measure-description", null, 1d, module.uuid())); } @Test - public void create_custom_measure_on_a_sub_view() throws Exception { - String subViewUuid = "SUB_VIEW_UUID"; - - ComponentDto view = ComponentTesting.newView(db.organizations().insert()); - dbClient.componentDao().insert(dbSession, view); - dbClient.componentDao().insert(dbSession, ComponentTesting.newSubView(view, subViewUuid, "SUB_VIEW_KEY")); - dbSession.commit(); - MetricDto metric = insertMetric(BOOL); - userSession.logIn("login").addProjectPermission(UserRole.ADMIN, view); - - newRequest() - .setParam(CreateAction.PARAM_PROJECT_ID, subViewUuid) + public void create_custom_measure_on_a_view() { + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(BOOL.name())); + OrganizationDto organization = db.organizations().insert(); + ComponentDto view = db.components().insertPrivatePortfolio(organization); + UserDto user = db.users().insertUser(); + userSession.logIn(user).addProjectPermission(ADMIN, view); + + ws.newRequest() + .setParam(CreateAction.PARAM_PROJECT_ID, view.uuid()) .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString()) .setParam(CreateAction.PARAM_DESCRIPTION, "custom-measure-description") .setParam(CreateAction.PARAM_VALUE, "true") .execute(); - List customMeasures = dbClient.customMeasureDao().selectByMetricId(dbSession, metric.getId()); - CustomMeasureDto customMeasure = customMeasures.get(0); - assertThat(customMeasures).hasSize(1); - assertThat(customMeasure.getComponentUuid()).isEqualTo(subViewUuid); + assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId())) + .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getComponentUuid) + .containsExactlyInAnyOrder(tuple("custom-measure-description", null, 1d, view.uuid())); } @Test - public void fail_when_get_request() throws Exception { - expectedException.expect(ServerException.class); - - ws.newGetRequest(CustomMeasuresWs.ENDPOINT, CreateAction.ACTION) - .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID) - .setParam(CreateAction.PARAM_METRIC_ID, "whatever-id") - .setParam(CreateAction.PARAM_VALUE, "custom-measure-free-text") + public void create_custom_measure_on_a_sub_view() { + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(BOOL.name())); + OrganizationDto organization = db.organizations().insert(); + ComponentDto view = db.components().insertPrivatePortfolio(organization); + ComponentDto subView = db.components().insertSubView(view); + UserDto user = db.users().insertUser(); + userSession.logIn(user).addProjectPermission(ADMIN, view); + + ws.newRequest() + .setParam(CreateAction.PARAM_PROJECT_ID, subView.uuid()) + .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString()) + .setParam(CreateAction.PARAM_DESCRIPTION, "custom-measure-description") + .setParam(CreateAction.PARAM_VALUE, "true") .execute(); + + assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId())) + .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getComponentUuid) + .containsExactlyInAnyOrder(tuple("custom-measure-description", null, 1d, subView.uuid())); } @Test - public void fail_when_project_id_nor_project_key_provided() throws Exception { + public void fail_when_project_id_nor_project_key_provided() { + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + ComponentDto project = db.components().insertPrivateProject(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).addProjectPermission(ADMIN, project); + expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("Either 'projectId' or 'projectKey' must be provided"); - MetricDto metric = insertMetric(STRING); - newRequest() + ws.newRequest() .setParam(CreateAction.PARAM_METRIC_ID, "whatever-id") .setParam(CreateAction.PARAM_VALUE, metric.getId().toString()) .execute(); } @Test - public void fail_when_project_id_and_project_key_are_provided() throws Exception { + public void fail_when_project_id_and_project_key_are_provided() { + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + ComponentDto project = db.components().insertPrivateProject(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).addProjectPermission(ADMIN, project); + expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("Either 'projectId' or 'projectKey' must be provided"); - MetricDto metric = insertMetric(STRING); - newRequest() - .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID) - .setParam(CreateAction.PARAM_PROJECT_KEY, DEFAULT_PROJECT_KEY) + ws.newRequest() + .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid()) + .setParam(CreateAction.PARAM_PROJECT_KEY, project.getKey()) .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString()) .setParam(CreateAction.PARAM_VALUE, "whatever-value") .execute(); } @Test - public void fail_when_project_key_does_not_exist_in_db() throws Exception { + public void fail_when_project_key_does_not_exist_in_db() { + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + ComponentDto project = db.components().insertPrivateProject(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).addProjectPermission(ADMIN, project); + expectedException.expect(NotFoundException.class); expectedException.expectMessage("Component key 'another-project-key' not found"); - insertMetric(STRING); - newRequest() + ws.newRequest() .setParam(CreateAction.PARAM_PROJECT_KEY, "another-project-key") - .setParam(CreateAction.PARAM_METRIC_ID, "whatever-id") + .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString()) .setParam(CreateAction.PARAM_VALUE, "whatever-value") .execute(); } @Test - public void fail_when_project_id_does_not_exist_in_db() throws Exception { + public void fail_when_project_id_does_not_exist_in_db() { + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + ComponentDto project = db.components().insertPrivateProject(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).addProjectPermission(ADMIN, project); + expectedException.expect(NotFoundException.class); expectedException.expectMessage("Component id 'another-project-uuid' not found"); - MetricDto metric = insertMetric(STRING); - newRequest() + ws.newRequest() .setParam(CreateAction.PARAM_PROJECT_ID, "another-project-uuid") .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString()) .setParam(CreateAction.PARAM_VALUE, "whatever-value") @@ -359,25 +377,32 @@ public class CreateActionTest { } @Test - public void fail_when_metric_id_nor_metric_key_is_provided() throws Exception { + public void fail_when_metric_id_nor_metric_key_is_provided() { + ComponentDto project = db.components().insertPrivateProject(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).addProjectPermission(ADMIN, project); + expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("Either the metric id or the metric key must be provided"); - insertMetric(STRING); - newRequest() - .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID) + ws.newRequest() + .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid()) .setParam(CreateAction.PARAM_VALUE, "whatever-value") .execute(); } @Test - public void fail_when_metric_id_and_metric_key_are_provided() throws Exception { + public void fail_when_metric_id_and_metric_key_are_provided() { + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + ComponentDto project = db.components().insertPrivateProject(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).addProjectPermission(ADMIN, project); + expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("Either the metric id or the metric key must be provided"); - MetricDto metric = insertMetric(STRING); - newRequest() - .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID) + ws.newRequest() + .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid()) .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString()) .setParam(CreateAction.PARAM_METRIC_KEY, metric.getKey()) .setParam(CreateAction.PARAM_VALUE, "whatever-value") @@ -385,89 +410,104 @@ public class CreateActionTest { } @Test - public void fail_when_metric_is_not_found_in_db() throws Exception { - expectedException.expect(RowNotFoundException.class); - expectedException.expectMessage("Metric id '42' not found"); + public void fail_when_metric_key_is_not_found_in_db() { + ComponentDto project = db.components().insertPrivateProject(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).addProjectPermission(ADMIN, project); - newRequest() - .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID) - .setParam(CreateAction.PARAM_METRIC_ID, "42") + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Metric with key 'unknown' does not exist"); + + ws.newRequest() + .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid()) + .setParam(CreateAction.PARAM_METRIC_KEY, "unknown") .setParam(CreateAction.PARAM_VALUE, "whatever-value") .execute(); } @Test - public void fail_when_measure_already_exists_on_same_project_and_same_metric() throws Exception { - MetricDto metric = insertMetric(STRING); + public void fail_when_metric_id_is_not_found_in_db() { + ComponentDto project = db.components().insertPrivateProject(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).addProjectPermission(ADMIN, project); - expectedException.expect(ServerException.class); - expectedException.expectMessage(String.format("A measure already exists for project 'project-key' (id: project-uuid) and metric 'metric-key' (id: '%d')", metric.getId())); + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Metric with id '42' does not exist"); - newRequest() - .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID) - .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString()) + ws.newRequest() + .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid()) + .setParam(CreateAction.PARAM_METRIC_ID, "42") .setParam(CreateAction.PARAM_VALUE, "whatever-value") .execute(); - newRequest() - .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID) + } + + @Test + public void fail_when_measure_already_exists_on_same_project_and_same_metric() { + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + ComponentDto project = db.components().insertPrivateProject(); + UserDto userMeasureCreator = db.users().insertUser(); + db.measures().insertCustomMeasure(userMeasureCreator, project, metric); + UserDto userAuthenticated = db.users().insertUser(); + userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project); + + expectedException.expect(BadRequestException.class); + expectedException.expectMessage(format("A measure already exists for project '%s' and metric '%s'", project.getKey(), metric.getKey())); + + ws.newRequest() + .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid()) .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString()) .setParam(CreateAction.PARAM_VALUE, "whatever-value") .execute(); } @Test - public void fail_when_value_is_not_well_formatted() throws Exception { - MetricDto metric = insertMetric(BOOL); + public void fail_when_value_is_not_well_formatted() { + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(BOOL.name())); + ComponentDto project = db.components().insertPrivateProject(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).addProjectPermission(ADMIN, project); expectedException.expect(BadRequestException.class); + expectedException.expectMessage("Value 'non-correct-boolean-value' must be one of \"true\" or \"false\""); - newRequest() - .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID) + ws.newRequest() + .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid()) .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString()) .setParam(CreateAction.PARAM_VALUE, "non-correct-boolean-value") .execute(); } @Test - public void fail_when_system_administrator() throws Exception { - userSession.logIn().setSystemAdministrator().addPermission(OrganizationPermission.ADMINISTER, db.getDefaultOrganization()); - MetricDto metric = insertMetric(STRING); + public void fail_when_system_administrator() { + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(BOOL.name())); + ComponentDto project = db.components().insertPrivateProject(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).setSystemAdministrator(); expectedException.expect(ForbiddenException.class); - newRequest() - .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID) + ws.newRequest() + .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid()) .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString()) .setParam(CreateAction.PARAM_VALUE, "whatever-value") .execute(); } @Test - public void fail_when_not_a_project() throws Exception { - MetricDto metric = MetricTesting.newMetricDto().setEnabled(true).setValueType(STRING.name()).setKey("metric-key"); - dbClient.metricDao().insert(dbSession, metric); - dbClient.componentDao().insert(dbSession, ComponentTesting.newDirectory(project, "directory-uuid", "path/to/directory").setDbKey("directory-key")); - dbSession.commit(); + public void fail_when_not_a_project() { + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(BOOL.name())); + ComponentDto project = db.components().insertPrivateProject(); + ComponentDto directory = db.components().insertComponent(ComponentTesting.newDirectory(project, "dir")); + UserDto user = db.users().insertUser(); + userSession.logIn(user).addProjectPermission(ADMIN, project); - expectedException.expect(ServerException.class); - expectedException.expectMessage("Component 'directory-key' (id: directory-uuid) must be a project or a module."); + expectedException.expect(BadRequestException.class); + expectedException.expectMessage(format("Component '%s' must be a project or a module.", directory.getKey())); - newRequest() - .setParam(CreateAction.PARAM_PROJECT_ID, "directory-uuid") + ws.newRequest() + .setParam(CreateAction.PARAM_PROJECT_ID, directory.uuid()) .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString()) .setParam(CreateAction.PARAM_VALUE, "whatever-value") .execute(); } - - private WsTester.TestRequest newRequest() { - return ws.newPostRequest(CustomMeasuresWs.ENDPOINT, CreateAction.ACTION); - } - - private MetricDto insertMetric(ValueType metricType) { - MetricDto metric = MetricTesting.newMetricDto().setEnabled(true).setValueType(metricType.name()).setKey("metric-key"); - dbClient.metricDao().insert(dbSession, metric); - dbSession.commit(); - return metric; - } - } diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/DeleteActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/DeleteActionTest.java index cb7c51d6e76..4863fac7dd3 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/DeleteActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/DeleteActionTest.java @@ -28,7 +28,6 @@ import org.sonar.api.web.UserRole; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; -import org.sonar.db.RowNotFoundException; import org.sonar.db.component.ComponentDto; import org.sonar.db.measure.custom.CustomMeasureDto; import org.sonar.server.exceptions.ForbiddenException; @@ -74,7 +73,8 @@ public class DeleteActionTest { @Test public void throw_RowNotFoundException_if_id_does_not_exist() throws Exception { - expectedException.expect(RowNotFoundException.class); + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Custom measure with id '42' does not exist"); newRequest().setParam(PARAM_ID, "42").execute(); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/SearchActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/SearchActionTest.java index adff6e1b933..40a61870a0e 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/SearchActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/SearchActionTest.java @@ -19,150 +19,300 @@ */ package org.sonar.server.measure.custom.ws; +import java.util.ArrayList; import java.util.Date; -import org.apache.commons.lang.StringUtils; -import org.junit.Before; +import java.util.List; +import java.util.stream.IntStream; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sonar.api.measures.Metric.ValueType; import org.sonar.api.server.ws.WebService; import org.sonar.api.utils.DateUtils; import org.sonar.api.utils.System2; -import org.sonar.api.web.UserRole; -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.component.ComponentTesting; -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.server.component.TestComponentFinder; import org.sonar.server.es.EsTester; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.user.ws.UserJsonWriter; -import org.sonar.server.ws.WsTester; +import org.sonar.server.ws.WsActionTester; 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.api.measures.Metric.ValueType.STRING; +import static org.sonar.api.web.UserRole.ADMIN; +import static org.sonar.api.web.UserRole.USER; +import static org.sonar.test.JsonAssert.assertJson; public class SearchActionTest { - private static final String DEFAULT_PROJECT_UUID = "project-uuid"; - private static final String DEFAULT_PROJECT_KEY = "project-key"; - private static final String METRIC_KEY_PREFIX = "metric-key-"; - @Rule public ExpectedException expectedException = ExpectedException.none(); @Rule - public UserSessionRule userSessionRule = UserSessionRule.standalone(); + public UserSessionRule userSession = UserSessionRule.standalone(); @Rule public DbTester db = DbTester.create(System2.INSTANCE); @Rule public EsTester es = EsTester.create(); - private WsTester ws; - private DbClient dbClient = db.getDbClient(); - private DbSession dbSession = db.getSession(); - private ComponentDto defaultProject; - - @Before - public void setUp() { - CustomMeasureJsonWriter customMeasureJsonWriter = new CustomMeasureJsonWriter(new UserJsonWriter(userSessionRule)); - ws = new WsTester(new CustomMeasuresWs(new SearchAction(dbClient, customMeasureJsonWriter, userSessionRule, TestComponentFinder.from(db)))); - defaultProject = insertDefaultProject(); - userSessionRule.logIn().addProjectPermission(UserRole.ADMIN, defaultProject); - db.users().insertUser(u -> u.setLogin("login") - .setName("Login") - .setEmail("login@login.com") - .setActive(true)); - } + private WsActionTester ws = new WsActionTester( + new SearchAction(db.getDbClient(), new CustomMeasureJsonWriter(new UserJsonWriter(userSession)), userSession, TestComponentFinder.from(db))); @Test - public void json_well_formatted() throws Exception { - MetricDto metric1 = insertCustomMetric(1); - MetricDto metric2 = insertCustomMetric(2); - MetricDto metric3 = insertCustomMetric(3); - CustomMeasureDto customMeasure1 = insertCustomMeasure(1, metric1); - CustomMeasureDto customMeasure2 = insertCustomMeasure(2, metric2); - CustomMeasureDto customMeasure3 = insertCustomMeasure(3, metric3); - - WsTester.Result response = newRequest() - .setParam(SearchAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID) - .execute(); + public void json_well_formatted() { + ComponentDto project = db.components().insertPrivateProject(); + UserDto userAuthenticated = db.users().insertUser(); + userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project); + UserDto userMeasureCreator = db.users().insertUser(); + MetricDto metric1 = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + MetricDto metric2 = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + MetricDto metric3 = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + CustomMeasureDto customMeasure1 = db.measures().insertCustomMeasure(userMeasureCreator, project, metric1, m -> m.setValue(0d)); + CustomMeasureDto customMeasure2 = db.measures().insertCustomMeasure(userMeasureCreator, project, metric2, m -> m.setValue(0d)); + CustomMeasureDto customMeasure3 = db.measures().insertCustomMeasure(userMeasureCreator, project, metric3, m -> m.setValue(0d)); + + String response = ws.newRequest() + .setParam(SearchAction.PARAM_PROJECT_ID, project.uuid()) + .execute() + .getInput(); + + assertJson(response).isSimilarTo("{\n" + + " \"customMeasures\": [\n" + + " {\n" + + " \"id\": \"" + customMeasure1.getId() + "\",\n" + + " \"value\": \"" + customMeasure1.getTextValue() + "\",\n" + + " \"description\": \"" + customMeasure1.getDescription() + "\",\n" + + " \"metric\": {\n" + + " \"id\": \"" + metric1.getId() + "\",\n" + + " \"key\": \"" + metric1.getKey() + "\",\n" + + " \"type\": \"" + metric1.getValueType() + "\",\n" + + " \"name\": \"" + metric1.getShortName() + "\",\n" + + " \"domain\": \"" + metric1.getDomain() + "\"\n" + + " },\n" + + " \"projectId\": \"" + project.uuid() + "\",\n" + + " \"projectKey\": \"" + project.getKey() + "\",\n" + + " \"pending\": true,\n" + + " },\n" + + " {\n" + + " \"id\": \"" + customMeasure2.getId() + "\",\n" + + " \"value\": \"" + customMeasure2.getTextValue() + "\",\n" + + " \"description\": \"" + customMeasure2.getDescription() + "\",\n" + + " \"metric\": {\n" + + " \"id\": \"" + metric2.getId() + "\",\n" + + " \"key\": \"" + metric2.getKey() + "\",\n" + + " \"type\": \"" + metric2.getValueType() + "\",\n" + + " \"name\": \"" + metric2.getShortName() + "\",\n" + + " \"domain\": \"" + metric2.getDomain() + "\"\n" + + " },\n" + + " \"projectId\": \"" + project.uuid() + "\",\n" + + " \"projectKey\": \"" + project.getKey() + "\",\n" + + " \"pending\": true,\n" + + " },\n" + + " {\n" + + " \"id\": \"" + customMeasure3.getId() + "\",\n" + + " \"value\": \"" + customMeasure3.getTextValue() + "\",\n" + + " \"description\": \"" + customMeasure3.getDescription() + "\",\n" + + " \"metric\": {\n" + + " \"id\": \"" + metric3.getId() + "\",\n" + + " \"key\": \"" + metric3.getKey() + "\",\n" + + " \"type\": \"" + metric3.getValueType() + "\",\n" + + " \"name\": \"" + metric3.getShortName() + "\",\n" + + " \"domain\": \"" + metric3.getDomain() + "\"\n" + + " },\n" + + " \"projectId\": \"" + project.uuid() + "\",\n" + + " \"projectKey\": \"" + project.getKey() + "\",\n" + + " \"pending\": true,\n" + + " }\n" + + " ],\n" + + " \"total\": 3,\n" + + " \"p\": 1,\n" + + " \"ps\": 100\n" + + "}"); + } - response.assertJson(getClass(), "custom-measures.json"); - String responseAsString = response.outputAsString(); - assertThat(responseAsString).matches(nameStringValuePattern("id", metric1.getId().toString())); - assertThat(responseAsString).matches(nameStringValuePattern("id", metric2.getId().toString())); - assertThat(responseAsString).matches(nameStringValuePattern("id", metric3.getId().toString())); - assertThat(responseAsString).matches(nameStringValuePattern("id", String.valueOf(customMeasure1.getId()))); - assertThat(responseAsString).matches(nameStringValuePattern("id", String.valueOf(customMeasure2.getId()))); - assertThat(responseAsString).matches(nameStringValuePattern("id", String.valueOf(customMeasure3.getId()))); - assertThat(responseAsString).contains("createdAt", "updatedAt"); + @Test + public void return_users() { + ComponentDto project = db.components().insertPrivateProject(); + UserDto userAuthenticated = db.users().insertUser(); + userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project); + UserDto user1 = db.users().insertUser(); + UserDto user2 = db.users().insertUser(); + MetricDto metric1 = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + MetricDto metric2 = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + MetricDto metric3 = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + CustomMeasureDto customMeasure1 = db.measures().insertCustomMeasure(user1, project, metric1, m -> m.setValue(0d)); + CustomMeasureDto customMeasure2 = db.measures().insertCustomMeasure(user1, project, metric2, m -> m.setValue(0d)); + CustomMeasureDto customMeasure3 = db.measures().insertCustomMeasure(user2, project, metric3, m -> m.setValue(0d)); + + String response = ws.newRequest() + .setParam(SearchAction.PARAM_PROJECT_ID, project.uuid()) + .execute() + .getInput(); + + assertJson(response).isSimilarTo("{\n" + + " \"customMeasures\": [\n" + + " {\n" + + " \"id\": \"" + customMeasure1.getId() + "\",\n" + + " \"user\": {\n" + + " \"login\": \"" + user1.getLogin() +"\",\n" + + " \"name\": \"" + user1.getName() +"\",\n" + + " \"email\": \"" + user1.getEmail() +"\",\n" + + " \"active\": true\n" + + " }" + + " },\n" + + " {\n" + + " \"id\": \"" + customMeasure2.getId() + "\",\n" + + " \"user\": {\n" + + " \"login\": \"" + user1.getLogin() +"\",\n" + + " \"name\": \"" + user1.getName() +"\",\n" + + " \"email\": \"" + user1.getEmail() +"\",\n" + + " \"active\": true\n" + + " }" + + " },\n" + + " {\n" + + " \"id\": \"" + customMeasure3.getId() + "\",\n" + + " \"user\": {\n" + + " \"login\": \"" + user2.getLogin() +"\",\n" + + " \"name\": \"" + user2.getName() +"\",\n" + + " \"email\": \"" + user2.getEmail() +"\",\n" + + " \"active\": true\n" + + " }" + + " }\n" + + " ]\n" + + "}"); } @Test - public void search_by_project_uuid() throws Exception { - MetricDto metric1 = insertCustomMetric(1); - MetricDto metric2 = insertCustomMetric(2); - MetricDto metric3 = insertCustomMetric(3); - insertCustomMeasure(1, metric1); - insertCustomMeasure(2, metric2); - insertCustomMeasure(3, metric3); - - String response = newRequest() - .setParam(SearchAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID) - .execute().outputAsString(); - - assertThat(response).contains("text-value-1", "text-value-2", "text-value-3"); + public void search_by_project_uuid() { + ComponentDto project = db.components().insertPrivateProject(); + UserDto userAuthenticated = db.users().insertUser(); + userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project); + UserDto userMeasureCreator = db.users().insertUser(); + MetricDto metric1 = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + MetricDto metric2 = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + MetricDto metric3 = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + CustomMeasureDto customMeasure1 = db.measures().insertCustomMeasure(userMeasureCreator, project, metric1, m -> m.setValue(0d)); + CustomMeasureDto customMeasure2 = db.measures().insertCustomMeasure(userMeasureCreator, project, metric2, m -> m.setValue(0d)); + CustomMeasureDto customMeasure3 = db.measures().insertCustomMeasure(userMeasureCreator, project, metric3, m -> m.setValue(0d)); + + String response = ws.newRequest() + .setParam(SearchAction.PARAM_PROJECT_ID, project.uuid()) + .execute() + .getInput(); + + assertJson(response).isSimilarTo("{\n" + + " \"customMeasures\": [\n" + + " {\n" + + " \"id\": \"" + customMeasure1.getId() + "\",\n" + + " \"value\": \"" + customMeasure1.getTextValue() + "\"\n" + + " },\n" + + " {\n" + + " \"id\": \"" + customMeasure2.getId() + "\",\n" + + " \"value\": \"" + customMeasure2.getTextValue() + "\"\n" + + " },\n" + + " {\n" + + " \"id\": \"" + customMeasure3.getId() + "\",\n" + + " \"value\": \"" + customMeasure3.getTextValue() + "\"\n" + + " }\n" + + " ],\n" + + " \"total\": 3,\n" + + " \"p\": 1,\n" + + " \"ps\": 100\n" + + "}"); } @Test - public void search_by_project_key() throws Exception { - MetricDto metric1 = insertCustomMetric(1); - MetricDto metric2 = insertCustomMetric(2); - MetricDto metric3 = insertCustomMetric(3); - insertCustomMeasure(1, metric1); - insertCustomMeasure(2, metric2); - insertCustomMeasure(3, metric3); - - String response = newRequest() - .setParam(SearchAction.PARAM_PROJECT_KEY, DEFAULT_PROJECT_KEY) - .execute().outputAsString(); - - assertThat(response).contains("text-value-1", "text-value-2", "text-value-3"); + public void search_by_project_key() { + ComponentDto project = db.components().insertPrivateProject(); + UserDto userAuthenticated = db.users().insertUser(); + userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project); + UserDto userMeasureCreator = db.users().insertUser(); + MetricDto metric1 = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + MetricDto metric2 = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + MetricDto metric3 = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + CustomMeasureDto customMeasure1 = db.measures().insertCustomMeasure(userMeasureCreator, project, metric1, m -> m.setValue(0d)); + CustomMeasureDto customMeasure2 = db.measures().insertCustomMeasure(userMeasureCreator, project, metric2, m -> m.setValue(0d)); + CustomMeasureDto customMeasure3 = db.measures().insertCustomMeasure(userMeasureCreator, project, metric3, m -> m.setValue(0d)); + + String response = ws.newRequest() + .setParam(SearchAction.PARAM_PROJECT_KEY, project.getKey()) + .execute() + .getInput(); + + assertJson(response).isSimilarTo("{\n" + + " \"customMeasures\": [\n" + + " {\n" + + " \"id\": \"" + customMeasure1.getId() + "\",\n" + + " \"value\": \"" + customMeasure1.getTextValue() + "\"\n" + + " },\n" + + " {\n" + + " \"id\": \"" + customMeasure2.getId() + "\",\n" + + " \"value\": \"" + customMeasure2.getTextValue() + "\"\n" + + " },\n" + + " {\n" + + " \"id\": \"" + customMeasure3.getId() + "\",\n" + + " \"value\": \"" + customMeasure3.getTextValue() + "\"\n" + + " }\n" + + " ],\n" + + " \"total\": 3,\n" + + " \"p\": 1,\n" + + " \"ps\": 100\n" + + "}"); } @Test - public void search_with_pagination() throws Exception { - for (int i = 0; i < 10; i++) { - MetricDto metric = insertCustomMetric(i); - insertCustomMeasure(i, metric); - } - - String response = newRequest() - .setParam(SearchAction.PARAM_PROJECT_KEY, DEFAULT_PROJECT_KEY) + public void search_with_pagination() { + ComponentDto project = db.components().insertPrivateProject(); + UserDto userAuthenticated = db.users().insertUser(); + userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project); + UserDto userMeasureCreator = db.users().insertUser(); + List measureById = new ArrayList<>(); + IntStream.range(0, 10).forEach(i -> { + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true)); + CustomMeasureDto customMeasure = db.measures().insertCustomMeasure(userMeasureCreator, project, metric); + measureById.add(customMeasure); + }); + + String response = ws.newRequest() + .setParam(SearchAction.PARAM_PROJECT_KEY, project.getKey()) .setParam(WebService.Param.PAGE, "3") .setParam(WebService.Param.PAGE_SIZE, "4") - .execute().outputAsString(); - - assertThat(StringUtils.countMatches(response, "text-value")).isEqualTo(2); + .execute() + .getInput(); + + assertJson(response).isSimilarTo("{\n" + + " \"customMeasures\": [\n" + + " {\n" + + " \"id\": \"" + measureById.get(8).getId() + "\",\n" + + " },\n" + + " {\n" + + " \"id\": \"" + measureById.get(9).getId() + "\",\n" + + " },\n" + + " ],\n" + + " \"total\": 10,\n" + + " \"p\": 3,\n" + + " \"ps\": 4\n" + + "}"); } @Test - public void search_with_selectable_fields() throws Exception { - MetricDto metric = insertCustomMetric(1); - insertCustomMeasure(1, metric); - - String response = newRequest() - .setParam(SearchAction.PARAM_PROJECT_KEY, DEFAULT_PROJECT_KEY) + public void search_with_selectable_fields() { + ComponentDto project = db.components().insertPrivateProject(); + UserDto userAuthenticated = db.users().insertUser(); + userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project); + UserDto userMeasureCreator = db.users().insertUser(); + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + db.measures().insertCustomMeasure(userMeasureCreator, project, metric, m -> m.setValue(0d)); + + String response = ws.newRequest() + .setParam(SearchAction.PARAM_PROJECT_KEY, project.getKey()) .setParam(WebService.Param.FIELDS, "value, description") - .execute().outputAsString(); + .execute() + .getInput(); assertThat(response).contains("id", "value", "description") .doesNotContain("createdAt") @@ -172,137 +322,99 @@ public class SearchActionTest { } @Test - public void search_with_more_recent_analysis() throws Exception { + public void search_with_more_recent_analysis() { long yesterday = DateUtils.addDays(new Date(), -1).getTime(); - MetricDto metric = insertCustomMetric(1); - dbClient.customMeasureDao().insert(dbSession, newCustomMeasure(1, metric) - .setCreatedAt(yesterday) - .setUpdatedAt(yesterday)); - dbClient.snapshotDao().insert(dbSession, SnapshotTesting.newAnalysis(defaultProject)); - dbSession.commit(); - - String response = newRequest() - .setParam(SearchAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID) - .execute().outputAsString(); - - assertThat(response).matches(nameValuePattern("pending", "false")); + ComponentDto project = db.components().insertPrivateProject(); + UserDto userAuthenticated = db.users().insertUser(); + userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project); + UserDto userMeasureCreator = db.users().insertUser(); + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + CustomMeasureDto customMeasure = db.measures().insertCustomMeasure(userMeasureCreator, project, metric, m -> m.setCreatedAt(yesterday).setUpdatedAt(yesterday)); + db.components().insertSnapshot(project); + + String response = ws.newRequest() + .setParam(SearchAction.PARAM_PROJECT_ID, project.uuid()) + .execute() + .getInput(); + + assertJson(response).isSimilarTo("{\n" + + " \"customMeasures\": [\n" + + " {\n" + + " \"id\": \"" + customMeasure.getId() + "\",\n" + + " \"value\": \"" + customMeasure.getTextValue() + "\",\n" + + " \"pending\": false\n" + + " },\n" + + " ]\n" + + "}"); } @Test - public void search_as_project_admin() throws Exception { - userSessionRule.logIn("login").addProjectPermission(UserRole.ADMIN, defaultProject); - MetricDto metric1 = insertCustomMetric(1); - insertCustomMeasure(1, metric1); - - String response = newRequest() - .setParam(SearchAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID) - .execute().outputAsString(); - - assertThat(response).contains("text-value-1"); + public void empty_json_when_no_measure() { + ComponentDto project = db.components().insertPrivateProject(); + UserDto userAuthenticated = db.users().insertUser(); + userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project); + + String response = ws.newRequest() + .setParam(SearchAction.PARAM_PROJECT_KEY, project.getKey()) + .execute() + .getInput(); + + assertJson(response).isSimilarTo("{\n" + + " \"customMeasures\": [],\n" + + " \"total\": 0,\n" + + " \"p\": 1,\n" + + " \"ps\": 100\n" + + "}"); } @Test - public void empty_json_when_no_measure() throws Exception { - WsTester.Result response = newRequest() - .setParam(SearchAction.PARAM_PROJECT_KEY, DEFAULT_PROJECT_KEY) - .execute(); - - response.assertJson(getClass(), "empty.json"); - } + public void fail_when_project_id_and_project_key_provided() { + ComponentDto project = db.components().insertPrivateProject(); + UserDto userAuthenticated = db.users().insertUser(); + userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project); - @Test - public void fail_when_project_id_and_project_key_provided() throws Exception { expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("Either 'projectId' or 'projectKey' must be provided"); - newRequest() - .setParam(SearchAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID) - .setParam(SearchAction.PARAM_PROJECT_KEY, DEFAULT_PROJECT_KEY) + ws.newRequest() + .setParam(SearchAction.PARAM_PROJECT_ID, project.uuid()) + .setParam(SearchAction.PARAM_PROJECT_KEY, project.getKey()) .execute(); } @Test - public void fail_when_project_id_nor_project_key_provided() throws Exception { + public void fail_when_project_id_nor_project_key_provided() { expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("Either 'projectId' or 'projectKey' must be provided"); - newRequest().execute(); + + ws.newRequest() + .execute(); } @Test - public void fail_when_project_not_found_in_db() throws Exception { + public void fail_when_project_not_found_in_db() { expectedException.expect(NotFoundException.class); expectedException.expectMessage("Component id 'wrong-project-uuid' not found"); - newRequest().setParam(SearchAction.PARAM_PROJECT_ID, "wrong-project-uuid").execute(); + ws.newRequest() + .setParam(SearchAction.PARAM_PROJECT_ID, "wrong-project-uuid") + .execute(); } @Test - public void fail_when_not_enough_privileges() throws Exception { + public void fail_when_not_enough_privileges() { + ComponentDto project = db.components().insertPrivateProject(); + UserDto userAuthenticated = db.users().insertUser(); + userSession.logIn(userAuthenticated).addProjectPermission(USER, project); + expectedException.expect(ForbiddenException.class); - userSessionRule.logIn("login"); - MetricDto metric1 = insertCustomMetric(1); - insertCustomMeasure(1, metric1); - String response = newRequest() - .setParam(SearchAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID) - .execute().outputAsString(); + String response = ws.newRequest() + .setParam(SearchAction.PARAM_PROJECT_ID, project.uuid()) + .execute() + .getInput(); assertThat(response).contains("text-value-1"); } - private ComponentDto insertDefaultProject() { - return insertProject(DEFAULT_PROJECT_UUID, DEFAULT_PROJECT_KEY); - } - - private ComponentDto insertProject(String projectUuid, String projectKey) { - ComponentDto project = ComponentTesting.newPrivateProjectDto(db.organizations().insert(), projectUuid) - .setDbKey(projectKey); - dbClient.componentDao().insert(dbSession, project); - dbSession.commit(); - - return project; - } - - private MetricDto insertCustomMetric(int id) { - MetricDto metric = newCustomMetric(METRIC_KEY_PREFIX + id); - dbClient.metricDao().insert(dbSession, metric); - dbSession.commit(); - - return metric; - } - - private static MetricDto newCustomMetric(String metricKey) { - return newMetricDto().setEnabled(true).setUserManaged(true).setKey(metricKey).setDomain(metricKey + "-domain").setShortName(metricKey + "-name") - .setValueType(ValueType.STRING.name()); - } - - private CustomMeasureDto insertCustomMeasure(int id, MetricDto metric) { - CustomMeasureDto customMeasure = newCustomMeasure(id, metric); - dbClient.customMeasureDao().insert(dbSession, customMeasure); - dbSession.commit(); - - return customMeasure; - } - - private CustomMeasureDto newCustomMeasure(int id, MetricDto metric) { - return newCustomMeasureDto() - .setUserLogin("login") - .setValue(id) - .setTextValue("text-value-" + id) - .setDescription("description-" + id) - .setMetricId(metric.getId()) - .setComponentUuid(defaultProject.uuid()); - } - - private WsTester.TestRequest newRequest() { - return ws.newGetRequest(CustomMeasuresWs.ENDPOINT, SearchAction.ACTION); - } - - private static String nameStringValuePattern(String name, String value) { - return String.format(".*\"%s\"\\s*:\\s*\"%s\".*", name, value); - } - - private static String nameValuePattern(String name, String value) { - return String.format(".*\"%s\"\\s*:\\s*%s.*", name, value); - } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/UpdateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/UpdateActionTest.java index f1d0adf3e03..0691f196468 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/UpdateActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/UpdateActionTest.java @@ -19,246 +19,196 @@ */ package org.sonar.server.measure.custom.ws; -import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sonar.api.measures.Metric.ValueType; import org.sonar.api.utils.System2; -import org.sonar.api.web.UserRole; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; +import org.sonar.api.utils.internal.TestSystem2; import org.sonar.db.DbTester; -import org.sonar.db.RowNotFoundException; import org.sonar.db.component.ComponentDto; -import org.sonar.db.component.ComponentTesting; import org.sonar.db.measure.custom.CustomMeasureDto; 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.server.es.EsTester; import org.sonar.server.exceptions.ForbiddenException; -import org.sonar.server.exceptions.ServerException; import org.sonar.server.exceptions.UnauthorizedException; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.user.ws.UserJsonWriter; -import org.sonar.server.ws.WsTester; +import org.sonar.server.ws.WsActionTester; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.data.Offset.offset; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.sonar.db.measure.custom.CustomMeasureTesting.newCustomMeasureDto; +import static org.assertj.core.api.Assertions.tuple; +import static org.sonar.api.measures.Metric.ValueType.INT; +import static org.sonar.api.measures.Metric.ValueType.STRING; +import static org.sonar.api.web.UserRole.ADMIN; +import static org.sonar.api.web.UserRole.USER; 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; import static org.sonar.server.util.TypeValidationsTesting.newFullTypeValidations; +import static org.sonar.test.JsonAssert.assertJson; public class UpdateActionTest { + + private static final long NOW = 10_000_000_000L; + + private System2 system = new TestSystem2().setNow(NOW); + @Rule public ExpectedException expectedException = ExpectedException.none(); @Rule - public UserSessionRule userSessionRule = UserSessionRule.standalone(); + public UserSessionRule userSession = UserSessionRule.standalone(); @Rule - public DbTester db = DbTester.create(System2.INSTANCE); + public DbTester db = DbTester.create(); @Rule public EsTester es = EsTester.create(); - private DbClient dbClient = db.getDbClient(); - private DbSession dbSession = db.getSession(); - private System2 system = mock(System2.class); - private WsTester ws; - - @Before - public void setUp() { - CustomMeasureValidator validator = new CustomMeasureValidator(newFullTypeValidations()); - - ws = new WsTester(new CustomMeasuresWs(new UpdateAction(dbClient, userSessionRule, system, validator, new CustomMeasureJsonWriter(new UserJsonWriter(userSessionRule))))); - - db.users().insertUser(u -> u.setLogin("login") - .setName("Login") - .setEmail("login@login.com") - .setActive(true) - ); - dbSession.commit(); - } + private WsActionTester ws = new WsActionTester(new UpdateAction(db.getDbClient(), userSession, system, new CustomMeasureValidator(newFullTypeValidations()), + new CustomMeasureJsonWriter(new UserJsonWriter(userSession)))); @Test - public void update_text_value_and_description_in_db() throws Exception { - MetricDto metric = insertNewMetric(ValueType.STRING); - ComponentDto component = db.components().insertPrivateProject(db.getDefaultOrganization(), "project-uuid"); - CustomMeasureDto customMeasure = newCustomMeasure(component, metric) - .setDescription("custom-measure-description") - .setTextValue("text-measure-value"); - dbClient.customMeasureDao().insert(dbSession, customMeasure); - dbSession.commit(); - when(system.now()).thenReturn(123_456_789L); - logInAsProjectAdministrator(component); - - ws.newPostRequest(CustomMeasuresWs.ENDPOINT, UpdateAction.ACTION) + public void update_text_value_and_description_in_db() { + ComponentDto project = db.components().insertPrivateProject(); + UserDto userAuthenticated = db.users().insertUser(); + userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project); + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + UserDto userMeasureCreator = db.users().insertUser(); + CustomMeasureDto customMeasure = db.measures().insertCustomMeasure(userMeasureCreator, project, metric, m -> m.setValue(0d)); + + ws.newRequest() .setParam(PARAM_ID, String.valueOf(customMeasure.getId())) .setParam(PARAM_DESCRIPTION, "new-custom-measure-description") .setParam(PARAM_VALUE, "new-text-measure-value") .execute(); - logInAsProjectAdministrator(component); - CustomMeasureDto updatedCustomMeasure = dbClient.customMeasureDao().selectOrFail(dbSession, customMeasure.getId()); - assertThat(updatedCustomMeasure.getTextValue()).isEqualTo("new-text-measure-value"); - assertThat(updatedCustomMeasure.getDescription()).isEqualTo("new-custom-measure-description"); - assertThat(updatedCustomMeasure.getUpdatedAt()).isEqualTo(123_456_789L); - assertThat(customMeasure.getCreatedAt()).isEqualTo(updatedCustomMeasure.getCreatedAt()); + assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId())) + .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getUserUuid, CustomMeasureDto::getComponentUuid, + CustomMeasureDto::getCreatedAt, CustomMeasureDto::getUpdatedAt) + .containsExactlyInAnyOrder( + tuple("new-custom-measure-description", "new-text-measure-value", 0d, userAuthenticated.getUuid(), project.uuid(), customMeasure.getCreatedAt(), NOW)); } @Test - public void update_double_value_and_description_in_db() throws Exception { - MetricDto metric = insertNewMetric(ValueType.INT); - OrganizationDto organizationDto = db.organizations().insert(); - ComponentDto component = db.components().insertPrivateProject(organizationDto, "project-uuid"); - CustomMeasureDto customMeasure = newCustomMeasure(component, metric) - .setDescription("custom-measure-description") - .setValue(42d); - dbClient.customMeasureDao().insert(dbSession, customMeasure); - dbSession.commit(); - logInAsProjectAdministrator(component); - - ws.newPostRequest(CustomMeasuresWs.ENDPOINT, UpdateAction.ACTION) + public void update_int_value_and_description_in_db() { + ComponentDto project = db.components().insertPrivateProject(); + UserDto userAuthenticated = db.users().insertUser(); + userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project); + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(INT.name())); + UserDto userMeasureCreator = db.users().insertUser(); + CustomMeasureDto customMeasure = db.measures().insertCustomMeasure(userMeasureCreator, project, metric, m -> m.setValue(42d).setTextValue(null)); + + ws.newRequest() .setParam(PARAM_ID, String.valueOf(customMeasure.getId())) .setParam(PARAM_DESCRIPTION, "new-custom-measure-description") .setParam(PARAM_VALUE, "1984") .execute(); - CustomMeasureDto updatedCustomMeasure = dbClient.customMeasureDao().selectOrFail(dbSession, customMeasure.getId()); - assertThat(updatedCustomMeasure.getValue()).isCloseTo(1984d, offset(0.01d)); - assertThat(updatedCustomMeasure.getDescription()).isEqualTo("new-custom-measure-description"); - assertThat(customMeasure.getCreatedAt()).isEqualTo(updatedCustomMeasure.getCreatedAt()); + assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId())) + .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getUserUuid, CustomMeasureDto::getComponentUuid, + CustomMeasureDto::getCreatedAt, CustomMeasureDto::getUpdatedAt) + .containsExactlyInAnyOrder( + tuple("new-custom-measure-description", null, 1984d, userAuthenticated.getUuid(), project.uuid(), customMeasure.getCreatedAt(), NOW)); } @Test - public void returns_full_object_in_response() throws Exception { - MetricDto metric = MetricTesting.newMetricDto().setEnabled(true) - .setValueType(ValueType.STRING.name()) - .setKey("metric-key"); - dbClient.metricDao().insert(dbSession, metric); - OrganizationDto organizationDto = db.organizations().insert(); - ComponentDto component = ComponentTesting.newPrivateProjectDto(organizationDto, "project-uuid").setDbKey("project-key"); - dbClient.componentDao().insert(dbSession, component); - CustomMeasureDto customMeasure = newCustomMeasure(component, metric) - .setCreatedAt(100_000_000L) - .setDescription("custom-measure-description") - .setTextValue("text-measure-value"); - dbClient.customMeasureDao().insert(dbSession, customMeasure); - dbSession.commit(); - when(system.now()).thenReturn(123_456_789L); - logInAsProjectAdministrator(component); - - WsTester.Result response = ws.newPostRequest(CustomMeasuresWs.ENDPOINT, UpdateAction.ACTION) + public void returns_full_object_in_response() { + ComponentDto project = db.components().insertPrivateProject(); + UserDto userAuthenticated = db.users().insertUser(); + userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project); + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + UserDto userMeasureCreator = db.users().insertUser(); + CustomMeasureDto customMeasure = db.measures().insertCustomMeasure(userMeasureCreator, project, metric, m -> m.setValue(0d).setCreatedAt(100_000_000L)); + + String response = ws.newRequest() .setParam(PARAM_ID, String.valueOf(customMeasure.getId())) .setParam(PARAM_DESCRIPTION, "new-custom-measure-description") .setParam(PARAM_VALUE, "new-text-measure-value") - .execute(); - - response.assertJson(getClass(), "custom-measure.json"); - String responseAsString = response.outputAsString(); - assertThat(responseAsString).matches(String.format(".*\"id\"\\s*:\\s*\"%s\".*", customMeasure.getId())); - assertThat(responseAsString).matches(String.format(".*\"id\"\\s*:\\s*\"%s\".*", metric.getId())); - assertThat(responseAsString).matches(".*createdAt.*updatedAt.*"); + .execute() + .getInput(); + + assertJson(response).isSimilarTo("{\n" + + " \"id\": \"" + customMeasure.getId() + "\",\n" + + " \"value\": \"new-text-measure-value\",\n" + + " \"description\": \"new-custom-measure-description\",\n" + + " \"metric\": {\n" + + " \"id\": \"" + metric.getId() + "\",\n" + + " \"key\": \"" + metric.getKey() + "\",\n" + + " \"type\": \"" + metric.getValueType() + "\",\n" + + " \"name\": \"" + metric.getShortName() + "\",\n" + + " \"domain\": \"" + metric.getDomain() + "\"\n" + + " },\n" + + " \"projectId\": \"" + project.uuid() + "\",\n" + + " \"projectKey\": \"" + project.getKey() + "\",\n" + + "}"); } @Test - public void update_value_only() throws Exception { - MetricDto metric = insertNewMetric(ValueType.STRING); - ComponentDto component = db.components().insertPrivateProject(db.getDefaultOrganization(), "project-uuid"); - CustomMeasureDto customMeasure = newCustomMeasure(component, metric) - .setDescription("custom-measure-description") - .setTextValue("text-measure-value"); - dbClient.customMeasureDao().insert(dbSession, customMeasure); - dbSession.commit(); - when(system.now()).thenReturn(123_456_789L); - logInAsProjectAdministrator(component); - - ws.newPostRequest(CustomMeasuresWs.ENDPOINT, UpdateAction.ACTION) + public void update_description_only() { + ComponentDto project = db.components().insertPrivateProject(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).addProjectPermission(ADMIN, project); + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + CustomMeasureDto customMeasure = db.measures().insertCustomMeasure(user, project, metric); + + ws.newRequest() .setParam(PARAM_ID, String.valueOf(customMeasure.getId())) .setParam(PARAM_DESCRIPTION, "new-custom-measure-description") .execute(); - logInAsProjectAdministrator(component); - CustomMeasureDto updatedCustomMeasure = dbClient.customMeasureDao().selectOrFail(dbSession, customMeasure.getId()); - assertThat(updatedCustomMeasure.getTextValue()).isEqualTo("text-measure-value"); - assertThat(updatedCustomMeasure.getDescription()).isEqualTo("new-custom-measure-description"); - assertThat(updatedCustomMeasure.getUpdatedAt()).isEqualTo(123_456_789L); - assertThat(customMeasure.getCreatedAt()).isEqualTo(updatedCustomMeasure.getCreatedAt()); + assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId())) + .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue) + .containsExactlyInAnyOrder( + tuple("new-custom-measure-description", customMeasure.getTextValue(), customMeasure.getValue())); } @Test - public void update_description_only() throws Exception { - MetricDto metric = insertNewMetric(ValueType.STRING); - OrganizationDto organizationDto = db.organizations().insert(); - ComponentDto component = db.components().insertPrivateProject(organizationDto, "project-uuid"); - CustomMeasureDto customMeasure = newCustomMeasure(component, metric) - .setMetricId(metric.getId()) - .setComponentUuid(component.uuid()) - .setCreatedAt(system.now()) - .setDescription("custom-measure-description") - .setTextValue("text-measure-value"); - dbClient.customMeasureDao().insert(dbSession, customMeasure); - dbSession.commit(); - when(system.now()).thenReturn(123_456_789L); - logInAsProjectAdministrator(component); - - ws.newPostRequest(CustomMeasuresWs.ENDPOINT, UpdateAction.ACTION) + public void update_value_only() { + ComponentDto project = db.components().insertPrivateProject(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).addProjectPermission(ADMIN, project); + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + CustomMeasureDto customMeasure = db.measures().insertCustomMeasure(user, project, metric); + + ws.newRequest() .setParam(PARAM_ID, String.valueOf(customMeasure.getId())) .setParam(PARAM_VALUE, "new-text-measure-value") .execute(); - CustomMeasureDto updatedCustomMeasure = dbClient.customMeasureDao().selectOrFail(dbSession, customMeasure.getId()); - assertThat(updatedCustomMeasure.getTextValue()).isEqualTo("new-text-measure-value"); - assertThat(updatedCustomMeasure.getDescription()).isEqualTo("custom-measure-description"); - assertThat(updatedCustomMeasure.getUpdatedAt()).isEqualTo(123_456_789L); - assertThat(customMeasure.getCreatedAt()).isEqualTo(updatedCustomMeasure.getCreatedAt()); + assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId())) + .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue) + .containsExactlyInAnyOrder( + tuple(customMeasure.getDescription(), "new-text-measure-value", customMeasure.getValue())); } @Test - public void fail_if_get_request() throws Exception { - expectedException.expect(ServerException.class); - - ws.newGetRequest(CustomMeasuresWs.ENDPOINT, UpdateAction.ACTION) - .setParam(PARAM_ID, "42") - .setParam(PARAM_DESCRIPTION, "new-custom-measure-description") - .setParam(PARAM_VALUE, "1984") - .execute(); - } + public void fail_if_measure_is_not_in_db() { + ComponentDto project = db.components().insertPrivateProject(); + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + UserDto user = db.users().insertUser(); + db.measures().insertCustomMeasure(user, project, metric); + userSession.logIn(user).addProjectPermission(ADMIN, project); - @Test - public void fail_if_not_in_db() throws Exception { - expectedException.expect(RowNotFoundException.class); - expectedException.expectMessage("Custom measure '42' not found."); + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Custom measure with id '0' does not exist"); - ws.newPostRequest(CustomMeasuresWs.ENDPOINT, UpdateAction.ACTION) - .setParam(PARAM_ID, "42") + ws.newRequest() + .setParam(PARAM_ID, "0") .setParam(PARAM_DESCRIPTION, "new-custom-measure-description") .setParam(PARAM_VALUE, "1984") .execute(); } @Test - public void fail_if_insufficient_privileges() throws Exception { - userSessionRule.logIn(); - MetricDto metric = MetricTesting.newMetricDto().setEnabled(true).setValueType(ValueType.STRING.name()); - dbClient.metricDao().insert(dbSession, metric); - ComponentDto component = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization(), "project-uuid"); - dbClient.componentDao().insert(dbSession, component); - CustomMeasureDto customMeasure = newCustomMeasureDto() - .setMetricId(metric.getId()) - .setComponentUuid(component.uuid()) - .setCreatedAt(system.now()) - .setDescription("custom-measure-description") - .setTextValue("text-measure-value"); - dbClient.customMeasureDao().insert(dbSession, customMeasure); - dbSession.commit(); + public void fail_if_insufficient_privileges() { + ComponentDto project = db.components().insertPrivateProject(); + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + UserDto user = db.users().insertUser(); + CustomMeasureDto customMeasure = db.measures().insertCustomMeasure(user, project, metric); + userSession.logIn(user).addProjectPermission(USER, project); expectedException.expect(ForbiddenException.class); - ws.newPostRequest(CustomMeasuresWs.ENDPOINT, UpdateAction.ACTION) + ws.newRequest() .setParam(PARAM_ID, String.valueOf(customMeasure.getId())) .setParam(PARAM_DESCRIPTION, "new-custom-measure-description") .setParam(PARAM_VALUE, "1984") @@ -266,24 +216,16 @@ public class UpdateActionTest { } @Test - public void fail_if_not_logged_in() throws Exception { - userSessionRule.anonymous(); + public void fail_if_not_logged_in() { + ComponentDto project = db.components().insertPrivateProject(); + UserDto user = db.users().insertUser(); + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + CustomMeasureDto customMeasure = db.measures().insertCustomMeasure(user, project, metric); + userSession.anonymous(); + expectedException.expect(UnauthorizedException.class); - MetricDto metric = MetricTesting.newMetricDto().setEnabled(true).setValueType(ValueType.STRING.name()); - dbClient.metricDao().insert(dbSession, metric); - OrganizationDto organizationDto = db.organizations().insert(); - ComponentDto component = ComponentTesting.newPrivateProjectDto(organizationDto, "project-uuid"); - dbClient.componentDao().insert(dbSession, component); - CustomMeasureDto customMeasure = newCustomMeasureDto() - .setMetricId(metric.getId()) - .setComponentUuid(component.uuid()) - .setCreatedAt(system.now()) - .setDescription("custom-measure-description") - .setTextValue("text-measure-value"); - dbClient.customMeasureDao().insert(dbSession, customMeasure); - dbSession.commit(); - - ws.newPostRequest(CustomMeasuresWs.ENDPOINT, UpdateAction.ACTION) + + ws.newRequest() .setParam(PARAM_ID, String.valueOf(customMeasure.getId())) .setParam(PARAM_DESCRIPTION, "new-custom-measure-description") .setParam(PARAM_VALUE, "1984") @@ -291,39 +233,36 @@ public class UpdateActionTest { } @Test - public void fail_if_custom_measure_id_is_missing_in_request() throws Exception { + public void fail_if_custom_measure_id_is_missing_in_request() { + ComponentDto project = db.components().insertPrivateProject(); + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + UserDto user = db.users().insertUser(); + db.measures().insertCustomMeasure(user, project, metric); + userSession.logIn(user).addProjectPermission(ADMIN, project); + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("The 'id' parameter is missing"); - ws.newPostRequest(CustomMeasuresWs.ENDPOINT, UpdateAction.ACTION) + ws.newRequest() .setParam(PARAM_DESCRIPTION, "new-custom-measure-description") .setParam(PARAM_VALUE, "1984") .execute(); } @Test - public void fail_if_custom_measure_value_and_description_are_missing_in_request() throws Exception { + public void fail_if_custom_measure_value_and_description_are_missing_in_request() { + ComponentDto project = db.components().insertPrivateProject(); + MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name())); + UserDto user = db.users().insertUser(); + db.measures().insertCustomMeasure(user, project, metric); + userSession.logIn(user).addProjectPermission(ADMIN, project); + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Value or description must be provided."); - ws.newPostRequest(CustomMeasuresWs.ENDPOINT, UpdateAction.ACTION) + ws.newRequest() .setParam(PARAM_ID, "42") .execute(); } - private MetricDto insertNewMetric(ValueType metricType) { - MetricDto metric = MetricTesting.newMetricDto().setEnabled(true).setValueType(metricType.name()); - dbClient.metricDao().insert(dbSession, metric); - - return metric; - } - - private CustomMeasureDto newCustomMeasure(ComponentDto project, MetricDto metric) { - return newCustomMeasureDto() - .setMetricId(metric.getId()) - .setComponentUuid(project.uuid()) - .setCreatedAt(system.now()); - } - - private void logInAsProjectAdministrator(ComponentDto component) { - userSessionRule.logIn("login").addProjectPermission(UserRole.ADMIN, component); - } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/ws/ChangePasswordActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/ws/ChangePasswordActionTest.java index c8f99ed0895..df6242d80f1 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/user/ws/ChangePasswordActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/user/ws/ChangePasswordActionTest.java @@ -84,7 +84,7 @@ public class ChangePasswordActionTest { .setPassword("Valar Dohaeris") .build(), u -> { }); - String oldCryptedPassword = db.getDbClient().userDao().selectOrFailByLogin(db.getSession(), "john").getCryptedPassword(); + String oldCryptedPassword = db.getDbClient().userDao().selectByLogin(db.getSession(), "john").getCryptedPassword(); userSessionRule.logIn("john"); TestResponse response = tester.newRequest() @@ -94,7 +94,7 @@ public class ChangePasswordActionTest { .execute(); assertThat(response.getStatus()).isEqualTo(204); - String newCryptedPassword = db.getDbClient().userDao().selectOrFailByLogin(db.getSession(), "john").getCryptedPassword(); + String newCryptedPassword = db.getDbClient().userDao().selectByLogin(db.getSession(), "john").getCryptedPassword(); assertThat(newCryptedPassword).isNotEqualTo(oldCryptedPassword); } @@ -102,14 +102,14 @@ public class ChangePasswordActionTest { public void system_administrator_can_update_password_of_user() { userSessionRule.logIn().setSystemAdministrator(); createLocalUser(); - String originalPassword = db.getDbClient().userDao().selectOrFailByLogin(db.getSession(), "john").getCryptedPassword(); + String originalPassword = db.getDbClient().userDao().selectByLogin(db.getSession(), "john").getCryptedPassword(); tester.newRequest() .setParam("login", "john") .setParam("password", "Valar Morghulis") .execute(); - String newPassword = db.getDbClient().userDao().selectOrFailByLogin(db.getSession(), "john").getCryptedPassword(); + String newPassword = db.getDbClient().userDao().selectByLogin(db.getSession(), "john").getCryptedPassword(); assertThat(newPassword).isNotEqualTo(originalPassword); } diff --git a/server/sonar-server/src/test/resources/org/sonar/server/measure/custom/ws/CreateActionTest/custom-measure.json b/server/sonar-server/src/test/resources/org/sonar/server/measure/custom/ws/CreateActionTest/custom-measure.json deleted file mode 100644 index 939b57e5f02..00000000000 --- a/server/sonar-server/src/test/resources/org/sonar/server/measure/custom/ws/CreateActionTest/custom-measure.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "projectId": "project-uuid", - "projectKey": "project-key", - "metric": { - "key": "metric-key", - "type": "STRING" - }, - "value": "custom-measure-free-text", - "description": "custom-measure-description", - "pending":true, - "user": { - "active": true, - "email": "login@login.com", - "login": "login", - "name": "Login" - } -} diff --git a/tests/src/test/java/org/sonarqube/tests/user/SonarCloudUpdateLoginDuringAuthenticationTest.java b/tests/src/test/java/org/sonarqube/tests/user/SonarCloudUpdateLoginDuringAuthenticationTest.java index 6278ab11cbc..e6c6e0eb62f 100644 --- a/tests/src/test/java/org/sonarqube/tests/user/SonarCloudUpdateLoginDuringAuthenticationTest.java +++ b/tests/src/test/java/org/sonarqube/tests/user/SonarCloudUpdateLoginDuringAuthenticationTest.java @@ -34,21 +34,25 @@ import org.sonarqube.ws.Issues; import org.sonarqube.ws.Issues.Issue; import org.sonarqube.ws.Organizations.Organization; import org.sonarqube.ws.Projects; +import org.sonarqube.ws.Projects.CreateWsResponse.Project; import org.sonarqube.ws.Qualityprofiles; import org.sonarqube.ws.Settings; import org.sonarqube.ws.UserTokens; import org.sonarqube.ws.Users; import org.sonarqube.ws.client.GetRequest; import org.sonarqube.ws.client.WsClient; +import org.sonarqube.ws.client.custommeasures.CreateRequest; import org.sonarqube.ws.client.issues.AssignRequest; import org.sonarqube.ws.client.organizations.AddMemberRequest; import org.sonarqube.ws.client.organizations.SearchRequest; +import org.sonarqube.ws.client.permissions.AddUserRequest; import org.sonarqube.ws.client.qualityprofiles.ChangelogRequest; import org.sonarqube.ws.client.settings.SetRequest; import org.sonarqube.ws.client.settings.ValuesRequest; import org.sonarqube.ws.client.usertokens.GenerateRequest; 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.skyscreamer.jsonassert.JSONAssert.assertEquals; import static util.ItUtils.projectDir; @@ -262,6 +266,66 @@ public class SonarCloudUpdateLoginDuringAuthenticationTest { .contains("token1", "token2"); } + @Test + public void manual_measure_after_login_update() throws JSONException { + tester.settings().setGlobalSettings("sonar.organizations.anyoneCanCreate", "true"); + String providerId = tester.users().generateProviderId(); + String oldLogin = tester.users().generateLogin(); + + // Create user using authentication + authenticate(oldLogin, providerId); + String userToken = tester.wsClient().userTokens().generate(new GenerateRequest().setLogin(oldLogin).setName("token")).getToken(); + WsClient userWsClient = tester.as(userToken, null).wsClient(); + + // Grant user the admin permission on a project + Organization organization = tester.organizations().generate(); + Project project = tester.projects().provision(organization); + tester.organizations().service().addMember(new AddMemberRequest().setOrganization(organization.getKey()).setLogin(oldLogin)); + String customMetricKey = randomAlphanumeric(50); + tester.wsClient().metrics().create(new org.sonarqube.ws.client.metrics.CreateRequest().setKey(customMetricKey).setName("custom").setType("INT")); + tester.wsClient().permissions().addUser(new AddUserRequest().setLogin(oldLogin).setProjectKey(project.getKey()).setPermission("admin")); + + // Create a manual metric and a manual measure on it + userWsClient.customMeasures().create(new CreateRequest().setMetricKey(customMetricKey).setProjectKey(project.getKey()).setValue("50")); + String manualMeasures = tester.wsClient().customMeasures().search(new org.sonarqube.ws.client.custommeasures.SearchRequest().setProjectKey(project.getKey())); + assertEquals( + "{\n" + + " \"customMeasures\": [\n" + + " {\n" + + " \"projectKey\": \"" + project.getKey() + "\",\n" + + " \"user\": {\n" + + " \"login\": \"" + oldLogin + "\",\n" + + " \"name\": \"John\",\n" + + " \"email\": \"john@email.com\",\n" + + " \"active\": true\n" + + " }" + + " }" + + " ]\n" + + "}", + manualMeasures, + false); + + // Update login during authentication, check manual measure contains new user login + String newLogin = tester.users().generateLogin(); + authenticate(newLogin, providerId); + assertEquals( + "{\n" + + " \"customMeasures\": [\n" + + " {\n" + + " \"projectKey\": \"" + project.getKey() + "\",\n" + + " \"user\": {\n" + + " \"login\": \"" + newLogin + "\",\n" + + " \"name\": \"John\",\n" + + " \"email\": \"john@email.com\",\n" + + " \"active\": true\n" + + " }" + + " }" + + " ]\n" + + "}", + tester.wsClient().customMeasures().search(new org.sonarqube.ws.client.custommeasures.SearchRequest().setProjectKey(project.getKey())), + false); + } + private void authenticate(String login, String providerId) { tester.settings().setGlobalSettings("sonar.auth.fake-base-id-provider.user", login + "," + providerId + ",fake-" + login + ",John,john@email.com"); tester.wsClient().wsConnector().call( -- 2.39.5