From 67012b8a06c3d2c929eb7c4391f5fa25368ee75b Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Wed, 9 May 2018 17:30:25 +0200 Subject: [PATCH] SONAR-10597 Update CE_ACTIVITY#SUBMITTER_LOGIN to SUBMITTER_UUID --- .../org/sonar/db/version/schema-h2.ddl | 2 +- .../java/org/sonar/db/ce/CeActivityDto.java | 11 ++-- .../org/sonar/db/ce/CeActivityMapper.xml | 6 +- .../org/sonar/db/ce/CeActivityDaoTest.java | 2 +- .../db/migration/version/v72/DbVersion72.java | 1 + ...LoginToSubmitterUuidOnTableCeActivity.java | 47 +++++++++++++++ .../version/v72/DbVersion72Test.java | 2 +- ...nToSubmitterUuidOnTableCeActivityTest.java | 57 +++++++++++++++++++ .../ce_activity.sql | 27 +++++++++ .../org/sonar/server/ce/ws/TaskFormatter.java | 49 +++++++++------- .../sonar/server/ce/ws/TaskFormatterTest.java | 48 +++++++++------- ...udUpdateLoginDuringAuthenticationTest.java | 44 ++++++++++++++ 12 files changed, 244 insertions(+), 52 deletions(-) create mode 100644 server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v72/RenameSubmitterLoginToSubmitterUuidOnTableCeActivity.java create mode 100644 server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/RenameSubmitterLoginToSubmitterUuidOnTableCeActivityTest.java create mode 100644 server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v72/RenameSubmitterLoginToSubmitterUuidOnTableCeActivityTest/ce_activity.sql 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 99ad46f3a05..1718c97533d 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 @@ -655,7 +655,7 @@ CREATE TABLE "CE_ACTIVITY" ( "STATUS" VARCHAR(15) NOT NULL, "IS_LAST" BOOLEAN NOT NULL, "IS_LAST_KEY" VARCHAR(55) NOT NULL, - "SUBMITTER_LOGIN" VARCHAR(255) NULL, + "SUBMITTER_UUID" VARCHAR(255) NULL, "WORKER_UUID" VARCHAR(40) NULL, "EXECUTION_COUNT" INTEGER NOT NULL, "SUBMITTED_AT" BIGINT NOT NULL, diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeActivityDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeActivityDto.java index 1be750ac323..df5d9aa8b00 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeActivityDto.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeActivityDto.java @@ -42,7 +42,7 @@ public class CeActivityDto { private String taskType; private boolean isLast; private String isLastKey; - private String submitterLogin; + private String submitterUuid; private String workerUuid; private long submittedAt; private Long startedAt; @@ -92,8 +92,7 @@ public class CeActivityDto { this.taskType = queueDto.getTaskType(); this.componentUuid = queueDto.getComponentUuid(); this.isLastKey = format("%s%s", taskType, Strings.nullToEmpty(componentUuid)); - // FIXME - this.submitterLogin = queueDto.getSubmitterUuid(); + this.submitterUuid = queueDto.getSubmitterUuid(); this.workerUuid = queueDto.getWorkerUuid(); this.submittedAt = queueDto.getCreatedAt(); this.startedAt = queueDto.getStartedAt(); @@ -152,8 +151,8 @@ public class CeActivityDto { } @CheckForNull - public String getSubmitterLogin() { - return submitterLogin; + public String getSubmitterUuid() { + return submitterUuid; } public long getSubmittedAt() { @@ -294,7 +293,7 @@ public class CeActivityDto { ", taskType='" + taskType + '\'' + ", isLast=" + isLast + ", isLastKey='" + isLastKey + '\'' + - ", submitterLogin='" + submitterLogin + '\'' + + ", submitterUuid='" + submitterUuid + '\'' + ", workerUuid='" + workerUuid + '\'' + ", submittedAt=" + submittedAt + ", startedAt=" + startedAt + diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml index 127b1e2098c..6c4779f6e93 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml @@ -22,7 +22,7 @@ ca.component_uuid as componentUuid, ca.analysis_uuid as analysisUuid, ca.status as status, - ca.submitter_login as submitterLogin, + ca.submitter_uuid as submitterUuid, ca.submitted_at as submittedAt, ca.worker_uuid as workerUuid, ca.started_at as startedAt, @@ -140,7 +140,7 @@ task_type, is_last, is_last_key, - submitter_login, + submitter_uuid, submitted_at, worker_uuid, execution_count, @@ -161,7 +161,7 @@ #{taskType,jdbcType=VARCHAR}, #{isLast,jdbcType=BOOLEAN}, #{isLastKey,jdbcType=VARCHAR}, - #{submitterLogin,jdbcType=VARCHAR}, + #{submitterUuid,jdbcType=VARCHAR}, #{submittedAt,jdbcType=BIGINT}, #{workerUuid,jdbcType=VARCHAR}, 0, diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/ce/CeActivityDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/ce/CeActivityDaoTest.java index b8ed217c8ed..f03acf46547 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/ce/CeActivityDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/ce/CeActivityDaoTest.java @@ -63,7 +63,7 @@ public class CeActivityDaoTest { assertThat(dto.getUuid()).isEqualTo("TASK_1"); assertThat(dto.getComponentUuid()).isEqualTo("PROJECT_1"); assertThat(dto.getStatus()).isEqualTo(CeActivityDto.Status.SUCCESS); - assertThat(dto.getSubmitterLogin()).isEqualTo("submitter uuid"); + assertThat(dto.getSubmitterUuid()).isEqualTo("submitter uuid"); assertThat(dto.getSubmittedAt()).isEqualTo(1_300_000_000_000L); assertThat(dto.getWorkerUuid()).isEqualTo("worker uuid"); assertThat(dto.getIsLast()).isTrue(); 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 598349bb821..d072d970386 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 @@ -50,6 +50,7 @@ public class DbVersion72 implements DbVersion { .add(2120, "Rename USER_LOGIN TO USER_UUID on table MANUAL_MEASURES", RenameUserLoginToUserUuidOnTableManualMeasures.class) .add(2121, "Rename NOTE_USER_LOGIN TO NOTE_USER_UUID on table RULES_METADATA", RenameNoteUserLoginToNoteUserUuidOnTableRulesMetadata.class) .add(2122, "Rename SUBMITTER_LOGIN TO SUBMITTER_UUID on table CE_QUEUE", RenameSubmitterLoginToSubmitterUuidOnTableCeQueue.class) + .add(2123, "Rename SUBMITTER_LOGIN TO SUBMITTER_UUID on table CE_ACTIVITY", RenameSubmitterLoginToSubmitterUuidOnTableCeActivity.class) ; } } diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v72/RenameSubmitterLoginToSubmitterUuidOnTableCeActivity.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v72/RenameSubmitterLoginToSubmitterUuidOnTableCeActivity.java new file mode 100644 index 00000000000..b57f575e700 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v72/RenameSubmitterLoginToSubmitterUuidOnTableCeActivity.java @@ -0,0 +1,47 @@ +/* + * 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 RenameSubmitterLoginToSubmitterUuidOnTableCeActivity extends DdlChange { + + public RenameSubmitterLoginToSubmitterUuidOnTableCeActivity(Database db) { + super(db); + } + + @Override + public void execute(Context context) throws SQLException { + context.execute(new RenameColumnsBuilder(getDialect(), "ce_activity") + .renameColumn("submitter_login", + newVarcharColumnDefBuilder() + .setColumnName("submitter_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 899207322d4..3109b8f8735 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, 23); + verifyMigrationCount(underTest, 24); } } diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/RenameSubmitterLoginToSubmitterUuidOnTableCeActivityTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/RenameSubmitterLoginToSubmitterUuidOnTableCeActivityTest.java new file mode 100644 index 00000000000..988b2bec020 --- /dev/null +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/RenameSubmitterLoginToSubmitterUuidOnTableCeActivityTest.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 RenameSubmitterLoginToSubmitterUuidOnTableCeActivityTest { + + @Rule + public final CoreDbTester db = CoreDbTester.createForSchema(RenameSubmitterLoginToSubmitterUuidOnTableCeActivityTest.class, "ce_activity.sql"); + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private RenameSubmitterLoginToSubmitterUuidOnTableCeActivity underTest = new RenameSubmitterLoginToSubmitterUuidOnTableCeActivity(db.database()); + + @Test + public void rename_column() throws SQLException { + underTest.execute(); + + db.assertColumnDefinition("ce_activity", "submitter_uuid", VARCHAR, 255, true); + db.assertColumnDoesNotExist("ce_activity", "submitter_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/RenameSubmitterLoginToSubmitterUuidOnTableCeActivityTest/ce_activity.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v72/RenameSubmitterLoginToSubmitterUuidOnTableCeActivityTest/ce_activity.sql new file mode 100644 index 00000000000..fe5d1ba980b --- /dev/null +++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v72/RenameSubmitterLoginToSubmitterUuidOnTableCeActivityTest/ce_activity.sql @@ -0,0 +1,27 @@ +CREATE TABLE "CE_ACTIVITY" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "UUID" VARCHAR(40) NOT NULL, + "TASK_TYPE" VARCHAR(15) NOT NULL, + "COMPONENT_UUID" VARCHAR(40) NULL, + "ANALYSIS_UUID" VARCHAR(50) NULL, + "STATUS" VARCHAR(15) NOT NULL, + "IS_LAST" BOOLEAN NOT NULL, + "IS_LAST_KEY" VARCHAR(55) NOT NULL, + "SUBMITTER_LOGIN" VARCHAR(255) NULL, + "WORKER_UUID" VARCHAR(40) NULL, + "EXECUTION_COUNT" INTEGER NOT NULL, + "SUBMITTED_AT" BIGINT NOT NULL, + "STARTED_AT" BIGINT NULL, + "EXECUTED_AT" BIGINT NULL, + "CREATED_AT" BIGINT NOT NULL, + "UPDATED_AT" BIGINT NOT NULL, + "EXECUTION_TIME_MS" BIGINT NULL, + "ERROR_MESSAGE" VARCHAR(1000), + "ERROR_STACKTRACE" CLOB, + "ERROR_TYPE" VARCHAR(20) +); + +CREATE UNIQUE INDEX "CE_ACTIVITY_UUID" ON "CE_ACTIVITY" ("UUID"); +CREATE INDEX "CE_ACTIVITY_COMPONENT_UUID" ON "CE_ACTIVITY" ("COMPONENT_UUID"); +CREATE INDEX "CE_ACTIVITY_ISLASTKEY" ON "CE_ACTIVITY" ("IS_LAST_KEY"); +CREATE INDEX "CE_ACTIVITY_ISLAST_STATUS" ON "CE_ACTIVITY" ("IS_LAST", "STATUS"); \ No newline at end of file diff --git a/server/sonar-server/src/main/java/org/sonar/server/ce/ws/TaskFormatter.java b/server/sonar-server/src/main/java/org/sonar/server/ce/ws/TaskFormatter.java index 9b20e1f3400..54e48e3c160 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/ce/ws/TaskFormatter.java +++ b/server/sonar-server/src/main/java/org/sonar/server/ce/ws/TaskFormatter.java @@ -68,36 +68,30 @@ public class TaskFormatter { public List formatQueue(DbSession dbSession, List dtos) { DtoCache cache = DtoCache.forQueueDtos(dbClient, dbSession, dtos); - Map usersByUuid = getUsersByUuid(dbSession, dtos); - return dtos.stream().map(input -> formatQueue(input, cache, usersByUuid)).collect(MoreCollectors.toList(dtos.size())); + return dtos.stream().map(input -> formatQueue(input, cache)).collect(MoreCollectors.toList(dtos.size())); } public Ce.Task formatQueue(DbSession dbSession, CeQueueDto queue) { - return formatQueue(queue, DtoCache.forQueueDtos(dbClient, dbSession, singletonList(queue)), getUsersByUuid(dbSession, singletonList(queue))); + return formatQueue(queue, DtoCache.forQueueDtos(dbClient, dbSession, singletonList(queue))); } - private Map getUsersByUuid(DbSession dbSession, Collection dtos) { - Set submitterUuids = dtos.stream().map(CeQueueDto::getSubmitterUuid).filter(Objects::nonNull).collect(toSet()); - return dbClient.userDao().selectByUuids(dbSession, submitterUuids).stream().collect(uniqueIndex(UserDto::getUuid)); - } - - private Ce.Task formatQueue(CeQueueDto dto, DtoCache componentDtoCache, Map usersByUuid) { + private Ce.Task formatQueue(CeQueueDto dto, DtoCache cache) { Ce.Task.Builder builder = Ce.Task.newBuilder(); - String organizationKey = componentDtoCache.getOrganizationKey(dto.getComponentUuid()); + String organizationKey = cache.getOrganizationKey(dto.getComponentUuid()); setNullable(organizationKey, builder::setOrganization); if (dto.getComponentUuid() != null) { builder.setComponentId(dto.getComponentUuid()); - setComponent(builder, dto.getComponentUuid(), componentDtoCache); + setComponent(builder, dto.getComponentUuid(), cache); } builder.setId(dto.getUuid()); builder.setStatus(Ce.TaskStatus.valueOf(dto.getStatus().name())); builder.setType(dto.getTaskType()); builder.setLogs(false); - setNullable(dto.getSubmitterUuid(), s -> builder.setSubmitterLogin(usersByUuid.get(s).getLogin())); + cache.getUser(dto.getSubmitterUuid()).ifPresent(user -> builder.setSubmitterLogin(user.getLogin())); builder.setSubmittedAt(formatDateTime(new Date(dto.getCreatedAt()))); setNullable(dto.getStartedAt(), builder::setStartedAt, DateUtils::formatDateTime); setNullable(computeExecutionTimeMs(dto), builder::setExecutionTimeMs); - setBranchOrPullRequest(builder, dto.getUuid(), componentDtoCache); + setBranchOrPullRequest(builder, dto.getUuid(), cache); return builder.build(); } @@ -112,20 +106,20 @@ public class TaskFormatter { .collect(MoreCollectors.toList(dtos.size())); } - private static Ce.Task formatActivity(CeActivityDto dto, DtoCache componentDtoCache, @Nullable String scannerContext) { + private static Ce.Task formatActivity(CeActivityDto dto, DtoCache cache, @Nullable String scannerContext) { Ce.Task.Builder builder = Ce.Task.newBuilder(); - String organizationKey = componentDtoCache.getOrganizationKey(dto.getComponentUuid()); + String organizationKey = cache.getOrganizationKey(dto.getComponentUuid()); setNullable(organizationKey, builder::setOrganization); builder.setId(dto.getUuid()); builder.setStatus(Ce.TaskStatus.valueOf(dto.getStatus().name())); builder.setType(dto.getTaskType()); builder.setLogs(false); - setNullable(dto.getComponentUuid(), uuid -> setComponent(builder, uuid, componentDtoCache).setComponentId(uuid)); + setNullable(dto.getComponentUuid(), uuid -> setComponent(builder, uuid, cache).setComponentId(uuid)); String analysisUuid = dto.getAnalysisUuid(); setNullable(analysisUuid, builder::setAnalysisId); - setBranchOrPullRequest(builder, dto.getUuid(), componentDtoCache); + setBranchOrPullRequest(builder, dto.getUuid(), cache); setNullable(analysisUuid, builder::setAnalysisId); - setNullable(dto.getSubmitterLogin(), builder::setSubmitterLogin); + cache.getUser(dto.getSubmitterUuid()).ifPresent(user -> builder.setSubmitterLogin(user.getLogin())); builder.setSubmittedAt(formatDateTime(new Date(dto.getSubmittedAt()))); setNullable(dto.getStartedAt(), builder::setStartedAt, DateUtils::formatDateTime); setNullable(dto.getExecutedAt(), builder::setExecutedAt, DateUtils::formatDateTime); @@ -172,12 +166,14 @@ public class TaskFormatter { private final Map componentsByUuid; private final Map organizationsByUuid; private final Multimap characteristicsByTaskUuid; + private final Map usersByUuid; private DtoCache(Map componentsByUuid, Map organizationsByUuid, - Multimap characteristicsByTaskUuid) { + Multimap characteristicsByTaskUuid, Map usersByUuid) { this.componentsByUuid = componentsByUuid; this.organizationsByUuid = organizationsByUuid; this.characteristicsByTaskUuid = characteristicsByTaskUuid; + this.usersByUuid = usersByUuid; } static DtoCache forQueueDtos(DbClient dbClient, DbSession dbSession, Collection ceQueueDtos) { @@ -187,7 +183,9 @@ public class TaskFormatter { Multimap characteristicsByTaskUuid = dbClient.ceTaskCharacteristicsDao() .selectByTaskUuids(dbSession, ceQueueDtos.stream().map(CeQueueDto::getUuid).collect(Collectors.toList())) .stream().collect(MoreCollectors.index(CeTaskCharacteristicDto::getTaskUuid)); - return new DtoCache(componentsByUuid, buildOrganizationsByUuid(dbClient, dbSession, componentsByUuid), characteristicsByTaskUuid); + Set submitterUuids = ceQueueDtos.stream().map(CeQueueDto::getSubmitterUuid).filter(Objects::nonNull).collect(toSet()); + Map usersByUuid = dbClient.userDao().selectByUuids(dbSession, submitterUuids).stream().collect(uniqueIndex(UserDto::getUuid)); + return new DtoCache(componentsByUuid, buildOrganizationsByUuid(dbClient, dbSession, componentsByUuid), characteristicsByTaskUuid, usersByUuid); } private static Set componentUuidsOfCeQueues(Collection ceQueueDtos) { @@ -207,7 +205,9 @@ public class TaskFormatter { Multimap characteristicsByTaskUuid = dbClient.ceTaskCharacteristicsDao() .selectByTaskUuids(dbSession, ceActivityDtos.stream().map(CeActivityDto::getUuid).collect(Collectors.toList())) .stream().collect(MoreCollectors.index(CeTaskCharacteristicDto::getTaskUuid)); - return new DtoCache(componentsByUuid, buildOrganizationsByUuid(dbClient, dbSession, componentsByUuid), characteristicsByTaskUuid); + Set submitterUuids = ceActivityDtos.stream().map(CeActivityDto::getSubmitterUuid).filter(Objects::nonNull).collect(toSet()); + Map usersByUuid = dbClient.userDao().selectByUuids(dbSession, submitterUuids).stream().collect(uniqueIndex(UserDto::getUuid)); + return new DtoCache(componentsByUuid, buildOrganizationsByUuid(dbClient, dbSession, componentsByUuid), characteristicsByTaskUuid, usersByUuid); } private static Set getComponentUuidsOfCeActivities(Collection ceActivityDtos) { @@ -271,6 +271,13 @@ public class TaskFormatter { .map(CeTaskCharacteristicDto::getValue) .findAny(); } + + Optional getUser(@Nullable String userUuid) { + if (userUuid == null) { + return Optional.empty(); + } + return Optional.ofNullable(usersByUuid.get(userUuid)); + } } /** diff --git a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskFormatterTest.java b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskFormatterTest.java index 6e51cee0dd4..42a81c4a6d5 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskFormatterTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskFormatterTest.java @@ -21,6 +21,7 @@ package org.sonar.server.ce.ws; import java.util.Collections; import java.util.Date; +import javax.annotation.Nullable; import org.junit.Rule; import org.junit.Test; import org.sonar.api.utils.DateUtils; @@ -35,6 +36,7 @@ import org.sonarqube.ws.Ce; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -158,7 +160,8 @@ public class TaskFormatterTest { @Test public void formatActivity() { - CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED); + UserDto user = db.users().insertUser(); + CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED, user); Ce.Task wsTask = underTest.formatActivity(db.getSession(), dto, null); @@ -166,6 +169,7 @@ public class TaskFormatterTest { assertThat(wsTask.getId()).isEqualTo("UUID"); assertThat(wsTask.getStatus()).isEqualTo(Ce.TaskStatus.FAILED); assertThat(wsTask.getSubmittedAt()).isEqualTo(DateUtils.formatDateTime(new Date(1_450_000_000_000L))); + assertThat(wsTask.getSubmitterLogin()).isEqualTo(user.getLogin()); assertThat(wsTask.getExecutionTimeMs()).isEqualTo(500L); assertThat(wsTask.getAnalysisId()).isEqualTo("U1"); assertThat(wsTask.getLogs()).isFalse(); @@ -174,7 +178,7 @@ public class TaskFormatterTest { @Test public void formatActivity_set_scanner_context_if_argument_is_non_null() { - CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED); + CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED, null); String expected = "scanner context baby!"; Ce.Task wsTask = underTest.formatActivity(db.getSession(), dto, expected); @@ -185,17 +189,23 @@ public class TaskFormatterTest { @Test public void formatActivities() { - CeActivityDto dto1 = newActivity("UUID1", "COMPONENT_UUID", CeActivityDto.Status.FAILED); - CeActivityDto dto2 = newActivity("UUID2", "COMPONENT_UUID", CeActivityDto.Status.SUCCESS); + UserDto user1 = db.users().insertUser(); + UserDto user2 = db.users().insertUser(); + CeActivityDto dto1 = newActivity("UUID1", "COMPONENT_UUID", CeActivityDto.Status.FAILED, user1); + CeActivityDto dto2 = newActivity("UUID2", "COMPONENT_UUID", CeActivityDto.Status.SUCCESS, user2); Iterable wsTasks = underTest.formatActivity(db.getSession(), asList(dto1, dto2)); - assertThat(wsTasks).extracting("id").containsExactly("UUID1", "UUID2"); + assertThat(wsTasks) + .extracting(Ce.Task::getId, Ce.Task::getSubmitterLogin) + .containsExactlyInAnyOrder( + tuple("UUID1", user1.getLogin()), + tuple("UUID2", user2.getLogin())); } @Test public void formatActivity_with_both_error_message_and_stacktrace() { - CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED) + CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED, null) .setErrorMessage("error msg") .setErrorStacktrace("error stacktrace") .setErrorType("anErrorType"); @@ -209,7 +219,7 @@ public class TaskFormatterTest { @Test public void formatActivity_with_both_error_message_only() { - CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED) + CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED, null) .setErrorMessage("error msg"); Ce.Task task = underTest.formatActivity(db.getSession(), Collections.singletonList(dto)).iterator().next(); @@ -220,7 +230,7 @@ public class TaskFormatterTest { @Test public void formatActivity_with_both_error_message_and_only_stacktrace_flag() { - CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED) + CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED, null) .setErrorMessage("error msg"); Ce.Task task = underTest.formatActivity(db.getSession(), Collections.singletonList(dto)).iterator().next(); @@ -229,16 +239,16 @@ public class TaskFormatterTest { assertThat(task.hasErrorStacktrace()).isFalse(); } - private CeActivityDto newActivity(String taskUuid, String componentUuid, CeActivityDto.Status status) { - CeQueueDto queueDto = new CeQueueDto(); - queueDto.setCreatedAt(1_450_000_000_000L); - queueDto.setTaskType(CeTaskTypes.REPORT); - queueDto.setComponentUuid(componentUuid); - queueDto.setUuid(taskUuid); - CeActivityDto activityDto = new CeActivityDto(queueDto); - activityDto.setStatus(status); - activityDto.setExecutionTimeMs(500L); - activityDto.setAnalysisUuid("U1"); - return activityDto; + private CeActivityDto newActivity(String taskUuid, String componentUuid, CeActivityDto.Status status, @Nullable UserDto user) { + CeQueueDto queueDto = new CeQueueDto() + .setCreatedAt(1_450_000_000_000L) + .setTaskType(CeTaskTypes.REPORT) + .setComponentUuid(componentUuid) + .setSubmitterUuid(user == null ? null : user.getUuid()) + .setUuid(taskUuid); + return new CeActivityDto(queueDto) + .setStatus(status) + .setExecutionTimeMs(500L) + .setAnalysisUuid("U1"); } } 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 b7ec0965057..9240e14e0a5 100644 --- a/tests/src/test/java/org/sonarqube/tests/user/SonarCloudUpdateLoginDuringAuthenticationTest.java +++ b/tests/src/test/java/org/sonarqube/tests/user/SonarCloudUpdateLoginDuringAuthenticationTest.java @@ -20,6 +20,7 @@ package org.sonarqube.tests.user; import com.sonar.orchestrator.Orchestrator; +import com.sonar.orchestrator.build.BuildResult; import com.sonar.orchestrator.build.SonarScanner; import java.util.List; import org.json.JSONException; @@ -30,6 +31,7 @@ import org.junit.Rule; import org.junit.Test; import org.sonarqube.qa.util.Tester; import org.sonarqube.qa.util.TesterSession; +import org.sonarqube.ws.Ce; import org.sonarqube.ws.Issues; import org.sonarqube.ws.Issues.Issue; import org.sonarqube.ws.Organizations.Organization; @@ -42,6 +44,8 @@ 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.ce.ActivityRequest; +import org.sonarqube.ws.client.ce.TaskRequest; import org.sonarqube.ws.client.custommeasures.CreateRequest; import org.sonarqube.ws.client.issues.AssignRequest; import org.sonarqube.ws.client.organizations.AddMemberRequest; @@ -58,6 +62,7 @@ import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; import static org.skyscreamer.jsonassert.JSONAssert.assertEquals; +import static util.ItUtils.extractCeTaskId; import static util.ItUtils.projectDir; public class SonarCloudUpdateLoginDuringAuthenticationTest { @@ -361,6 +366,37 @@ public class SonarCloudUpdateLoginDuringAuthenticationTest { .containsExactlyInAnyOrder(tuple("xoo:OneIssuePerLine", newLogin, "A user note")); } + @Test + public void ce_task_and_activity_after_login_update() { + 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(); + + // Execute an analysis using user token + Organization organization = tester.organizations().generate(); + Project project = tester.projects().provision(organization); + tester.organizations().service().addMember(new AddMemberRequest().setOrganization(organization.getKey()).setLogin(oldLogin)); + tester.wsClient().permissions().addUser(new AddUserRequest().setLogin(oldLogin).setOrganization(organization.getKey()).setPermission("scan")); + String analysisTaskId = executeAnalysisOnSampleProject(organization, project, userToken); + + // Check login in ce task and activity + assertThat(tester.wsClient().ce().task(new TaskRequest().setId(analysisTaskId)).getTask().getSubmitterLogin()).isEqualTo(oldLogin); + assertThat(tester.wsClient().ce().activity(new ActivityRequest().setQ(analysisTaskId)).getTasksList()) + .extracting(Ce.Task::getComponentKey, Ce.Task::getSubmitterLogin) + .containsExactlyInAnyOrder(tuple(project.getKey(), oldLogin)); + + // Update login during authentication, check ce task and activity contains new login + String newLogin = tester.users().generateLogin(); + authenticate(newLogin, providerId); + assertThat(tester.wsClient().ce().task(new TaskRequest().setId(analysisTaskId)).getTask().getSubmitterLogin()).isEqualTo(newLogin); + assertThat(tester.wsClient().ce().activity(new ActivityRequest().setQ(analysisTaskId)).getTasksList()) + .extracting(Ce.Task::getComponentKey, Ce.Task::getSubmitterLogin) + .containsExactlyInAnyOrder(tuple(project.getKey(), newLogin)); + } + 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( @@ -368,6 +404,14 @@ public class SonarCloudUpdateLoginDuringAuthenticationTest { .failIfNotSuccessful(); } + private static String executeAnalysisOnSampleProject(Organization organization, Project project, String userToken) { + BuildResult buildResult = orchestrator.executeBuild(SonarScanner.create(projectDir("shared/xoo-sample"), + "sonar.organization", organization.getKey(), + "sonar.projectKey", project.getKey(), + "sonar.login", userToken)); + return extractCeTaskId(buildResult); + } + private Issue getIssue(Organization organization, String issueKey) { List issues = tester.wsClient().issues().search(new org.sonarqube.ws.client.issues.SearchRequest() .setIssues(singletonList(issueKey)) -- 2.39.5