From: Julien Lancelot Date: Fri, 11 May 2018 07:41:17 +0000 (+0200) Subject: SONAR-10597 Update RULES_METADATA#NOTE_USER_LOGIN to NOTE_USER_UUID X-Git-Tag: 7.5~1161 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=bc2c99babb24274510edf8be7b213dbe6280573f;p=sonarqube.git SONAR-10597 Update RULES_METADATA#NOTE_USER_LOGIN to NOTE_USER_UUID * SONAR-10597 Update RULES_METADATA#NOTE_USER_LOGIN to NOTE_USER_UUD in DB * SONAR-10597 Update rules ws to use user note uuid * SONAR-10597 Add ITs to check rule note after login update --- 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 4f8a73a1ff4..62d8774d7fe 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 @@ -206,7 +206,7 @@ CREATE TABLE "RULES_METADATA" ( "RULE_ID" INTEGER NOT NULL, "ORGANIZATION_UUID" VARCHAR(40) NOT NULL, "NOTE_DATA" CLOB, - "NOTE_USER_LOGIN" VARCHAR(255), + "NOTE_USER_UUID" VARCHAR(255), "NOTE_CREATED_AT" BIGINT, "NOTE_UPDATED_AT" BIGINT, "REMEDIATION_FUNCTION" VARCHAR(20), diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java index 6d5d64c9eca..3441baff04d 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java @@ -361,12 +361,12 @@ public class RuleDto { } @CheckForNull - public String getNoteUserLogin() { - return metadata.getNoteUserLogin(); + public String getNoteUserUuid() { + return metadata.getNoteUserUuid(); } - public RuleDto setNoteUserLogin(@Nullable String noteUserLogin) { - metadata.setNoteUserLogin(noteUserLogin); + public RuleDto setNoteUserUuid(@Nullable String noteUserUuid) { + metadata.setNoteUserUuid(noteUserUuid); return this; } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleMetadataDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleMetadataDto.java index 05fac04da0b..64e1130be7f 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleMetadataDto.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleMetadataDto.java @@ -33,7 +33,7 @@ public class RuleMetadataDto { private int ruleId; private String organizationUuid; private String noteData; - private String noteUserLogin; + private String noteUserUuid; private Long noteCreatedAt; private Long noteUpdatedAt; private String remediationFunction; @@ -72,12 +72,12 @@ public class RuleMetadataDto { } @CheckForNull - public String getNoteUserLogin() { - return noteUserLogin; + public String getNoteUserUuid() { + return noteUserUuid; } - public RuleMetadataDto setNoteUserLogin(@Nullable String noteUserLogin) { - this.noteUserLogin = noteUserLogin; + public RuleMetadataDto setNoteUserUuid(@Nullable String noteUserUuid) { + this.noteUserUuid = noteUserUuid; return this; } @@ -178,7 +178,7 @@ public class RuleMetadataDto { "ruleId=" + ruleId + ", organizationUuid='" + organizationUuid + '\'' + ", noteData='" + noteData + '\'' + - ", noteUserLogin='" + noteUserLogin + '\'' + + ", noteUserUuid='" + noteUserUuid + '\'' + ", noteCreatedAt=" + noteCreatedAt + ", noteUpdatedAt=" + noteUpdatedAt + ", remediationFunction='" + remediationFunction + '\'' + diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml index 7b7dabe472c..487a02f4e08 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml @@ -38,7 +38,7 @@ r.created_at as "createdAtFromDefinition", r.updated_at as "updatedAtFromDefinition", rm.note_data as "noteData", - rm.note_user_login as "noteUserLogin", + rm.note_user_uuid as "noteUserUuid", rm.note_created_at as "noteCreatedAt", rm.note_updated_at as "noteUpdatedAt", rm.remediation_function as "remediationFunction", @@ -187,7 +187,7 @@ rm.rule_id as "ruleId", rm.organization_uuid as "organizationUuid", rm.note_data as "noteData", - rm.note_user_login as "noteUserLogin", + rm.note_user_uuid as "noteUserUuid", rm.note_created_at as "noteCreatedAt", rm.note_updated_at as "noteUpdatedAt", rm.remediation_function as "remediationFunction", @@ -378,7 +378,7 @@ rule_id, organization_uuid, note_data, - note_user_login, + note_user_uuid, note_created_at, note_updated_at, remediation_function, @@ -392,7 +392,7 @@ #{ruleId,jdbcType=INTEGER}, #{organizationUuid,jdbcType=VARCHAR}, #{noteData,jdbcType=CLOB}, - #{noteUserLogin,jdbcType=VARCHAR}, + #{noteUserUuid,jdbcType=VARCHAR}, #{noteCreatedAt,jdbcType=BIGINT}, #{noteUpdatedAt,jdbcType=BIGINT}, #{remediationFunction,jdbcType=VARCHAR}, @@ -407,7 +407,7 @@ update rules_metadata set note_data=#{noteData,jdbcType=CLOB}, - note_user_login=#{noteUserLogin,jdbcType=VARCHAR}, + note_user_uuid=#{noteUserUuid,jdbcType=VARCHAR}, note_created_at=#{noteCreatedAt,jdbcType=BIGINT}, note_updated_at=#{noteUpdatedAt,jdbcType=BIGINT}, remediation_function=#{remediationFunction,jdbcType=VARCHAR}, diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java index 03bad9b6c8b..a4f3034566c 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java @@ -584,7 +584,7 @@ public class RuleDaoTest { .setRuleId(1) .setOrganizationUuid(organizationUuid) .setNoteData("My note") - .setNoteUserLogin("admin") + .setNoteUserUuid("admin") .setNoteCreatedAt(DateUtils.parseDate("2013-12-19").getTime()) .setNoteUpdatedAt(DateUtils.parseDate("2013-12-20").getTime()) .setRemediationFunction(DebtRemediationFunction.Type.LINEAR.toString()) @@ -611,7 +611,7 @@ public class RuleDaoTest { assertThat(ruleDto.isTemplate()).isFalse(); assertThat(ruleDto.getTemplateId()).isNull(); assertThat(ruleDto.getNoteData()).isEqualTo("My note"); - assertThat(ruleDto.getNoteUserLogin()).isEqualTo("admin"); + assertThat(ruleDto.getNoteUserUuid()).isEqualTo("admin"); assertThat(ruleDto.getNoteCreatedAt()).isNotNull(); assertThat(ruleDto.getNoteUpdatedAt()).isNotNull(); assertThat(ruleDto.getRemediationFunction()).isEqualTo("LINEAR"); @@ -642,7 +642,7 @@ public class RuleDaoTest { .setRuleId(1) .setOrganizationUuid(organizationUuid) .setNoteData("My note") - .setNoteUserLogin("admin") + .setNoteUserUuid("admin") .setNoteCreatedAt(DateUtils.parseDate("2013-12-19").getTime()) .setNoteUpdatedAt(DateUtils.parseDate("2013-12-20").getTime()) .setRemediationFunction(DebtRemediationFunction.Type.LINEAR.toString()) @@ -669,7 +669,7 @@ public class RuleDaoTest { assertThat(ruleDto.isTemplate()).isFalse(); assertThat(ruleDto.getTemplateId()).isNull(); assertThat(ruleDto.getNoteData()).isNull(); - assertThat(ruleDto.getNoteUserLogin()).isNull(); + assertThat(ruleDto.getNoteUserUuid()).isNull(); assertThat(ruleDto.getNoteCreatedAt()).isNull(); assertThat(ruleDto.getNoteUpdatedAt()).isNull(); assertThat(ruleDto.getRemediationFunction()).isNull(); @@ -701,7 +701,7 @@ public class RuleDaoTest { assertThat(ruleDto.isTemplate()).isFalse(); assertThat(ruleDto.getTemplateId()).isNull(); assertThat(ruleDto.getNoteData()).isEqualTo("My note"); - assertThat(ruleDto.getNoteUserLogin()).isEqualTo("admin"); + assertThat(ruleDto.getNoteUserUuid()).isEqualTo("admin"); assertThat(ruleDto.getNoteCreatedAt()).isNotNull(); assertThat(ruleDto.getNoteUpdatedAt()).isNotNull(); assertThat(ruleDto.getRemediationFunction()).isEqualTo("LINEAR"); diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDbTester.java b/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDbTester.java index 1a7f32e792a..3ab4a154a03 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDbTester.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDbTester.java @@ -24,6 +24,7 @@ import org.sonar.api.rule.RuleKey; import org.sonar.api.server.rule.RuleParamType; import org.sonar.db.DbTester; import org.sonar.db.organization.OrganizationDto; +import org.sonar.db.user.UserDto; import static java.util.Arrays.asList; import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; @@ -79,6 +80,13 @@ public class RuleDbTester { return insertOrUpdateMetadata(dto); } + @SafeVarargs + public final RuleMetadataDto insertOrUpdateMetadata(RuleDefinitionDto rule, UserDto noteUser, OrganizationDto organization, Consumer... populaters) { + RuleMetadataDto dto = RuleTesting.newRuleMetadata(rule, noteUser, organization); + asList(populaters).forEach(populater -> populater.accept(dto)); + return insertOrUpdateMetadata(dto); + } + public RuleMetadataDto insertOrUpdateMetadata(RuleMetadataDto metadata) { db.getDbClient().ruleDao().insertOrUpdate(db.getSession(), metadata); db.commit(); diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleTesting.java b/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleTesting.java index 4a90d86466d..b979f66f953 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleTesting.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleTesting.java @@ -33,6 +33,7 @@ import org.sonar.core.util.UuidFactoryFast; import org.sonar.db.organization.OrganizationDto; import org.sonar.db.rule.RuleDto.Format; import org.sonar.db.rule.RuleDto.Scope; +import org.sonar.db.user.UserDto; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.ImmutableSet.copyOf; @@ -96,7 +97,7 @@ public class RuleTesting { .setRemediationFunction("LINEAR_OFFSET") .setTags(newHashSet("tag_" + randomAlphanumeric(5), "tag_" + randomAlphanumeric(5))) .setNoteData("noteData_" + randomAlphanumeric(5)) - .setNoteUserLogin("noteLogin_" + randomAlphanumeric(5)) + .setNoteUserUuid("noteUserUuid_" + randomAlphanumeric(5)) .setNoteCreatedAt(System.currentTimeMillis() - 200) .setNoteUpdatedAt(System.currentTimeMillis() - 150) .setCreatedAt(System.currentTimeMillis() - 100) @@ -109,6 +110,11 @@ public class RuleTesting { .setOrganizationUuid(organization.getUuid()); } + public static RuleMetadataDto newRuleMetadata(RuleDefinitionDto rule, UserDto noteUser, OrganizationDto organization) { + return newRuleMetadata(rule, organization) + .setNoteUserUuid(noteUser.getUuid()); + } + public static RuleParamDto newRuleParam(RuleDefinitionDto rule) { return new RuleParamDto() .setRuleId(rule.getId()) 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 20d40419ebe..65d99312ce4 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,7 +47,8 @@ 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); + .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) ; } } diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v72/RenameNoteUserLoginToNoteUserUuidOnTableRulesMetadata.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v72/RenameNoteUserLoginToNoteUserUuidOnTableRulesMetadata.java new file mode 100644 index 00000000000..87361076df7 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v72/RenameNoteUserLoginToNoteUserUuidOnTableRulesMetadata.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 RenameNoteUserLoginToNoteUserUuidOnTableRulesMetadata extends DdlChange { + + private static final String TABLE = "rules_metadata"; + + public RenameNoteUserLoginToNoteUserUuidOnTableRulesMetadata(Database db) { + super(db); + } + + @Override + public void execute(Context context) throws SQLException { + context.execute(new RenameColumnsBuilder(getDialect(), TABLE) + .renameColumn("note_user_login", + newVarcharColumnDefBuilder() + .setColumnName("note_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 87922b1bf39..f83902a41d2 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, 21); + verifyMigrationCount(underTest, 22); } } diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/RenameNoteUserLoginToNoteUserUuidOnTableRulesMetadataTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/RenameNoteUserLoginToNoteUserUuidOnTableRulesMetadataTest.java new file mode 100644 index 00000000000..1470479922b --- /dev/null +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/RenameNoteUserLoginToNoteUserUuidOnTableRulesMetadataTest.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 RenameNoteUserLoginToNoteUserUuidOnTableRulesMetadataTest { + + @Rule + public final CoreDbTester db = CoreDbTester.createForSchema(RenameNoteUserLoginToNoteUserUuidOnTableRulesMetadataTest.class, "rules_metadata.sql"); + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private RenameNoteUserLoginToNoteUserUuidOnTableRulesMetadata underTest = new RenameNoteUserLoginToNoteUserUuidOnTableRulesMetadata(db.database()); + + @Test + public void rename_column() throws SQLException { + underTest.execute(); + + db.assertColumnDefinition("rules_metadata", "note_user_uuid", VARCHAR, 255, true); + db.assertColumnDoesNotExist("rules_metadata", "note_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/RenameNoteUserLoginToNoteUserUuidOnTableRulesMetadataTest/rules_metadata.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v72/RenameNoteUserLoginToNoteUserUuidOnTableRulesMetadataTest/rules_metadata.sql new file mode 100644 index 00000000000..69c506a80b1 --- /dev/null +++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v72/RenameNoteUserLoginToNoteUserUuidOnTableRulesMetadataTest/rules_metadata.sql @@ -0,0 +1,15 @@ +CREATE TABLE "RULES_METADATA" ( + "RULE_ID" INTEGER NOT NULL, + "ORGANIZATION_UUID" VARCHAR(40) NOT NULL, + "NOTE_DATA" CLOB, + "NOTE_USER_LOGIN" VARCHAR(255), + "NOTE_CREATED_AT" BIGINT, + "NOTE_UPDATED_AT" BIGINT, + "REMEDIATION_FUNCTION" VARCHAR(20), + "REMEDIATION_GAP_MULT" VARCHAR(20), + "REMEDIATION_BASE_EFFORT" VARCHAR(20), + "TAGS" VARCHAR(4000), + "CREATED_AT" BIGINT NOT NULL, + "UPDATED_AT" BIGINT NOT NULL, + CONSTRAINT PK_RULES_METADATA PRIMARY KEY (RULE_ID,ORGANIZATION_UUID) +); \ No newline at end of file diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdater.java b/server/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdater.java index 10b6297f02d..3248fbbeae2 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdater.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdater.java @@ -191,13 +191,13 @@ public class RuleUpdater { rule.setNoteData(null); rule.setNoteCreatedAt(null); rule.setNoteUpdatedAt(null); - rule.setNoteUserLogin(null); + rule.setNoteUserUuid(null); } else { long now = system.now(); rule.setNoteData(update.getMarkdownNote()); rule.setNoteCreatedAt(rule.getNoteCreatedAt() != null ? rule.getNoteCreatedAt() : now); rule.setNoteUpdatedAt(now); - rule.setNoteUserLogin(userSession.getLogin()); + rule.setNoteUserUuid(userSession.getUuid()); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleMapper.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleMapper.java index 9a70c738b52..ad20629b98f 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleMapper.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleMapper.java @@ -23,6 +23,7 @@ import com.google.common.base.Function; import com.google.common.collect.FluentIterable; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Set; import javax.annotation.CheckForNull; import javax.annotation.Nonnull; @@ -34,6 +35,7 @@ import org.sonar.db.rule.RuleDefinitionDto; import org.sonar.db.rule.RuleDto.Scope; import org.sonar.db.rule.RuleMetadataDto; import org.sonar.db.rule.RuleParamDto; +import org.sonar.db.user.UserDto; import org.sonar.markdown.Markdown; import org.sonar.server.rule.ws.SearchAction.SearchResult; import org.sonar.server.text.MacroInterpreter; @@ -63,10 +65,10 @@ import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_PARAMS; import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_REM_FUNCTION; import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_REM_FUNCTION_OVERLOADED; import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_REPO; +import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_SCOPE; import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_SEVERITY; import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_STATUS; import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_SYSTEM_TAGS; -import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_SCOPE; import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_TAGS; import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_TEMPLATE_KEY; @@ -89,10 +91,10 @@ public class RuleMapper { return ruleResponse.build(); } - public Rules.Rule toWsRule(RuleDefinitionDto ruleDefinitionDto, SearchResult result, Set fieldsToReturn, RuleMetadataDto metadata) { + public Rules.Rule toWsRule(RuleDefinitionDto ruleDefinitionDto, SearchResult result, Set fieldsToReturn, RuleMetadataDto metadata, Map usersByUuid) { Rules.Rule.Builder ruleResponse = Rules.Rule.newBuilder(); applyRuleDefinition(ruleResponse, ruleDefinitionDto, result, fieldsToReturn); - applyRuleMetadata(ruleResponse, metadata, fieldsToReturn); + applyRuleMetadata(ruleResponse, metadata, usersByUuid, fieldsToReturn); setDebtRemediationFunctionFields(ruleResponse, ruleDefinitionDto, metadata, fieldsToReturn); return ruleResponse.build(); } @@ -101,7 +103,7 @@ public class RuleMapper { // Mandatory fields ruleResponse.setKey(ruleDefinitionDto.getKey().toString()); - ruleResponse.setType(Common.RuleType.valueOf(ruleDefinitionDto.getType())); + ruleResponse.setType(Common.RuleType.forNumber(ruleDefinitionDto.getType())); // Optional fields setRepository(ruleResponse, ruleDefinitionDto, fieldsToReturn); @@ -124,9 +126,9 @@ public class RuleMapper { return ruleResponse; } - private void applyRuleMetadata(Rules.Rule.Builder ruleResponse, RuleMetadataDto metadata, Set fieldsToReturn) { + private void applyRuleMetadata(Rules.Rule.Builder ruleResponse, RuleMetadataDto metadata, Map usersByUuid, Set fieldsToReturn) { setTags(ruleResponse, metadata, fieldsToReturn); - setNotesFields(ruleResponse, metadata, fieldsToReturn); + setNotesFields(ruleResponse, metadata, usersByUuid, fieldsToReturn); setIsRemediationFunctionOverloaded(ruleResponse, metadata, fieldsToReturn); } @@ -282,21 +284,24 @@ public class RuleMapper { } } - private void setNotesFields(Rules.Rule.Builder ruleResponse, RuleMetadataDto ruleDto, Set fieldsToReturn) { - if (shouldReturnField(fieldsToReturn, "htmlNote") && ruleDto.getNoteData() != null) { - ruleResponse.setHtmlNote(macroInterpreter.interpret(Markdown.convertToHtml(ruleDto.getNoteData()))); + private void setNotesFields(Rules.Rule.Builder ruleResponse, RuleMetadataDto ruleDto, Map usersByUuid, Set fieldsToReturn) { + String noteData = ruleDto.getNoteData(); + if (shouldReturnField(fieldsToReturn, "htmlNote") && noteData != null) { + ruleResponse.setHtmlNote(macroInterpreter.interpret(Markdown.convertToHtml(noteData))); } - if (shouldReturnField(fieldsToReturn, "mdNote") && ruleDto.getNoteData() != null) { - ruleResponse.setMdNote(ruleDto.getNoteData()); + if (shouldReturnField(fieldsToReturn, "mdNote") && noteData != null) { + ruleResponse.setMdNote(noteData); } - if (shouldReturnField(fieldsToReturn, FIELD_NOTE_LOGIN) && ruleDto.getNoteUserLogin() != null) { - ruleResponse.setNoteLogin(ruleDto.getNoteUserLogin()); + String userUuid = ruleDto.getNoteUserUuid(); + if (shouldReturnField(fieldsToReturn, FIELD_NOTE_LOGIN) && userUuid != null) { + ruleResponse.setNoteLogin(usersByUuid.get(userUuid).getLogin()); } } private static void setSeverity(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, Set fieldsToReturn) { - if (shouldReturnField(fieldsToReturn, FIELD_SEVERITY) && ruleDto.getSeverityString() != null) { - ruleResponse.setSeverity(ruleDto.getSeverityString()); + String severity = ruleDto.getSeverityString(); + if (shouldReturnField(fieldsToReturn, FIELD_SEVERITY) && severity != null) { + ruleResponse.setSeverity(severity); } } @@ -307,8 +312,9 @@ public class RuleMapper { } private static void setLanguage(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, Set fieldsToReturn) { - if (shouldReturnField(fieldsToReturn, FIELD_LANGUAGE) && ruleDto.getLanguage() != null) { - ruleResponse.setLang(ruleDto.getLanguage()); + String language = ruleDto.getLanguage(); + if (shouldReturnField(fieldsToReturn, FIELD_LANGUAGE) && language != null) { + ruleResponse.setLang(language); } } @@ -385,8 +391,9 @@ public class RuleMapper { if (param.getDescription() != null) { paramResponse.setHtmlDesc(Markdown.convertToHtml(param.getDescription())); } - if (param.getDefaultValue() != null) { - paramResponse.setDefaultValue(param.getDefaultValue()); + String defaultValue = param.getDefaultValue(); + if (defaultValue != null) { + paramResponse.setDefaultValue(defaultValue); } if (param.getType() != null) { paramResponse.setType(param.getType()); diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleWsSupport.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleWsSupport.java index cb27fc6fcaf..ecd4b1bf592 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleWsSupport.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleWsSupport.java @@ -19,16 +19,24 @@ */ package org.sonar.server.rule.ws; +import java.util.List; +import java.util.Map; +import java.util.Objects; import java.util.Optional; +import java.util.Set; import javax.annotation.Nullable; import org.sonar.api.server.ServerSide; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.organization.OrganizationDto; +import org.sonar.db.rule.RuleDto; +import org.sonar.db.user.UserDto; import org.sonar.server.organization.DefaultOrganizationProvider; import org.sonar.server.user.UserSession; import org.sonar.server.ws.WsUtils; +import static org.sonar.core.util.stream.MoreCollectors.toSet; +import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex; import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES; @ServerSide @@ -58,4 +66,9 @@ public class RuleWsSupport { "No organization with key '%s'", organizationOrDefaultKey); } + Map getUsersByUuid(DbSession dbSession, List rules) { + Set userUuids = rules.stream().map(RuleDto::getNoteUserUuid).filter(Objects::nonNull).collect(toSet()); + return dbClient.userDao().selectByUuids(dbSession, userUuids).stream().collect(uniqueIndex(UserDto::getUuid)); + } + } diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java index 99f2bec9699..0027b0542fa 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java @@ -49,6 +49,7 @@ import org.sonar.db.DbSession; import org.sonar.db.rule.RuleDefinitionDto; import org.sonar.db.rule.RuleDto; import org.sonar.db.rule.RuleParamDto; +import org.sonar.db.user.UserDto; import org.sonar.server.es.Facets; import org.sonar.server.es.SearchIdResult; import org.sonar.server.es.SearchOptions; @@ -118,13 +119,16 @@ public class SearchAction implements RulesWsAction { private final RuleIndex ruleIndex; private final ActiveRuleCompleter activeRuleCompleter; private final RuleMapper mapper; + private final RuleWsSupport ruleWsSupport; - public SearchAction(RuleIndex ruleIndex, ActiveRuleCompleter activeRuleCompleter, RuleQueryFactory ruleQueryFactory, DbClient dbClient, RuleMapper mapper) { + public SearchAction(RuleIndex ruleIndex, ActiveRuleCompleter activeRuleCompleter, RuleQueryFactory ruleQueryFactory, DbClient dbClient, RuleMapper mapper, + RuleWsSupport ruleWsSupport) { this.ruleIndex = ruleIndex; this.activeRuleCompleter = activeRuleCompleter; this.ruleQueryFactory = ruleQueryFactory; this.dbClient = dbClient; this.mapper = mapper; + this.ruleWsSupport = ruleWsSupport; } @Override @@ -330,10 +334,9 @@ public class SearchAction implements RulesWsAction { .setSince("6.4"); } - private void writeRules(SearchResponse.Builder response, SearchResult result, SearchOptions context) { - for (RuleDto rule : result.rules) { - response.addRules(mapper.toWsRule(rule.getDefinition(), result, context.getFields(), rule.getMetadata())); - } + private void writeRules(DbSession dbSession, SearchResponse.Builder response, SearchResult result, SearchOptions context) { + Map usersByUuid = ruleWsSupport.getUsersByUuid(dbSession, result.rules); + result.rules.forEach(rule -> response.addRules(mapper.toWsRule(rule.getDefinition(), result, context.getFields(), rule.getMetadata(), usersByUuid))); } private static SearchOptions buildSearchOptions(SearchRequest request) { @@ -392,7 +395,7 @@ public class SearchAction implements RulesWsAction { private void doContextResponse(DbSession dbSession, SearchRequest request, SearchResult result, SearchResponse.Builder response, RuleQuery query) { SearchOptions contextForResponse = loadCommonContext(request); - writeRules(response, result, contextForResponse); + writeRules(dbSession, response, result, contextForResponse); if (contextForResponse.getFields().contains("actives")) { activeRuleCompleter.completeSearch(dbSession, query, result.rules, response); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/ShowAction.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/ShowAction.java index 1f603dcb051..0b1faf67fd0 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/ShowAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/ShowAction.java @@ -33,8 +33,6 @@ import org.sonar.db.rule.RuleDefinitionDto; import org.sonar.db.rule.RuleDto; import org.sonar.db.rule.RuleParamDto; import org.sonar.server.exceptions.NotFoundException; -import org.sonar.server.organization.DefaultOrganizationProvider; -import org.sonar.server.ws.WsUtils; import org.sonarqube.ws.Rules.ShowResponse; import static java.util.Collections.singletonList; @@ -53,13 +51,13 @@ public class ShowAction implements RulesWsAction { private final DbClient dbClient; private final RuleMapper mapper; private final ActiveRuleCompleter activeRuleCompleter; - private final DefaultOrganizationProvider defaultOrganizationProvider; + private final RuleWsSupport ruleWsSupport; - public ShowAction(DbClient dbClient, RuleMapper mapper, ActiveRuleCompleter activeRuleCompleter, DefaultOrganizationProvider defaultOrganizationProvider) { + public ShowAction(DbClient dbClient, RuleMapper mapper, ActiveRuleCompleter activeRuleCompleter, RuleWsSupport ruleWsSupport) { this.dbClient = dbClient; this.activeRuleCompleter = activeRuleCompleter; this.mapper = mapper; - this.defaultOrganizationProvider = defaultOrganizationProvider; + this.ruleWsSupport = ruleWsSupport; } @Override @@ -105,7 +103,7 @@ public class ShowAction implements RulesWsAction { public void handle(Request request, Response response) throws Exception { RuleKey key = RuleKey.parse(request.mandatoryParam(PARAM_KEY)); try (DbSession dbSession = dbClient.openSession(false)) { - OrganizationDto organization = getOrganization(request, dbSession); + OrganizationDto organization = ruleWsSupport.getOrganizationByKey(dbSession, request.param(PARAM_ORGANIZATION)); RuleDto rule = dbClient.ruleDao().selectByKey(dbSession, organization, key) .orElseThrow(() -> new NotFoundException(String.format("Rule not found: %s", key))); @@ -124,24 +122,15 @@ public class ShowAction implements RulesWsAction { } } - private OrganizationDto getOrganization(Request request, DbSession dbSession) { - String organizationKey = ofNullable(request.param(PARAM_ORGANIZATION)) - .orElseGet(() -> defaultOrganizationProvider.get().getKey()); - return WsUtils.checkFoundWithOptional( - dbClient.organizationDao().selectByKey(dbSession, organizationKey), - "No organization with key '%s'", organizationKey); - } - private ShowResponse buildResponse(DbSession dbSession, OrganizationDto organization, Request request, SearchAction.SearchResult searchResult) { ShowResponse.Builder responseBuilder = ShowResponse.newBuilder(); RuleDto rule = searchResult.getRules().get(0); - responseBuilder.setRule(mapper.toWsRule(rule.getDefinition(), searchResult, Collections.emptySet(), rule.getMetadata())); - + responseBuilder.setRule(mapper.toWsRule(rule.getDefinition(), searchResult, Collections.emptySet(), rule.getMetadata(), + ruleWsSupport.getUsersByUuid(dbSession, searchResult.getRules()))); if (request.mandatoryParamAsBoolean(PARAM_ACTIVES)) { - activeRuleCompleter.completeShow(dbSession, organization, rule.getDefinition()).stream() - .forEach(responseBuilder::addActives); + activeRuleCompleter.completeShow(dbSession, organization, rule.getDefinition()).forEach(responseBuilder::addActives); } - return responseBuilder.build(); } + } diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/UpdateAction.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/UpdateAction.java index b8f2ef6318a..d93e3e1e85a 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/UpdateAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/UpdateAction.java @@ -40,11 +40,9 @@ import org.sonar.db.rule.RuleDefinitionDto; import org.sonar.db.rule.RuleDto; import org.sonar.db.rule.RuleParamDto; import org.sonar.server.exceptions.NotFoundException; -import org.sonar.server.organization.DefaultOrganizationProvider; import org.sonar.server.rule.RuleUpdate; import org.sonar.server.rule.RuleUpdater; import org.sonar.server.user.UserSession; -import org.sonar.server.ws.WsUtils; import org.sonarqube.ws.Rules.UpdateResponse; import static com.google.common.collect.Sets.newHashSet; @@ -79,15 +77,14 @@ public class UpdateAction implements RulesWsAction { private final RuleUpdater ruleUpdater; private final RuleMapper mapper; private final UserSession userSession; - private final DefaultOrganizationProvider defaultOrganizationProvider; + private final RuleWsSupport ruleWsSupport; - public UpdateAction(DbClient dbClient, RuleUpdater ruleUpdater, RuleMapper mapper, UserSession userSession, - DefaultOrganizationProvider defaultOrganizationProvider) { + public UpdateAction(DbClient dbClient, RuleUpdater ruleUpdater, RuleMapper mapper, UserSession userSession, RuleWsSupport ruleWsSupport) { this.dbClient = dbClient; this.ruleUpdater = ruleUpdater; this.mapper = mapper; this.userSession = userSession; - this.defaultOrganizationProvider = defaultOrganizationProvider; + this.ruleWsSupport = ruleWsSupport; } @Override @@ -181,7 +178,7 @@ public class UpdateAction implements RulesWsAction { public void handle(Request request, Response response) throws Exception { userSession.checkLoggedIn(); try (DbSession dbSession = dbClient.openSession(false)) { - OrganizationDto organization = getOrganization(request, dbSession); + OrganizationDto organization = ruleWsSupport.getOrganizationByKey(dbSession, request.param(PARAM_ORGANIZATION)); userSession.checkPermission(ADMINISTER_QUALITY_PROFILES, organization); RuleUpdate update = readRequest(dbSession, request, organization); ruleUpdater.update(dbSession, update, organization, userSession); @@ -191,14 +188,6 @@ public class UpdateAction implements RulesWsAction { } } - private OrganizationDto getOrganization(Request request, DbSession dbSession) { - String organizationKey = ofNullable(request.param(PARAM_ORGANIZATION)) - .orElseGet(() -> defaultOrganizationProvider.get().getKey()); - return WsUtils.checkFoundWithOptional( - dbClient.organizationDao().selectByKey(dbSession, organizationKey), - "No organization with key '%s'", organizationKey); - } - private RuleUpdate readRequest(DbSession dbSession, Request request, OrganizationDto organization) { RuleKey key = RuleKey.parse(request.mandatoryParam(PARAM_KEY)); RuleUpdate update = createRuleUpdate(dbSession, key, organization); @@ -289,7 +278,8 @@ public class UpdateAction implements RulesWsAction { .setTemplateRules(templateRules) .setRuleParameters(ruleParameters) .setTotal(1L); - responseBuilder.setRule(mapper.toWsRule(rule.getDefinition(), searchResult, Collections.emptySet(), rule.getMetadata())); + responseBuilder + .setRule(mapper.toWsRule(rule.getDefinition(), searchResult, Collections.emptySet(), rule.getMetadata(), ruleWsSupport.getUsersByUuid(dbSession, singletonList(rule)))); return responseBuilder.build(); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesTest.java index 5200a483073..580e22dc528 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesTest.java @@ -269,7 +269,7 @@ public class RegisterRulesTest { // user adds tags and sets markdown note rule1.setTags(newHashSet("usertag1", "usertag2")); rule1.setNoteData("user *note*"); - rule1.setNoteUserLogin("marius"); + rule1.setNoteUserUuid("marius"); dbClient.ruleDao().insertOrUpdate(dbTester.getSession(), rule1.getMetadata()); dbTester.getSession().commit(); @@ -285,7 +285,7 @@ public class RegisterRulesTest { assertThat(rule1.getSystemTags()).containsOnly("tag1", "tag4"); assertThat(rule1.getConfigKey()).isEqualTo("config1 v2"); assertThat(rule1.getNoteData()).isEqualTo("user *note*"); - assertThat(rule1.getNoteUserLogin()).isEqualTo("marius"); + assertThat(rule1.getNoteUserUuid()).isEqualTo("marius"); assertThat(rule1.getStatus()).isEqualTo(RuleStatus.READY); assertThat(rule1.getType()).isEqualTo(RuleType.BUG.getDbConstant()); assertThat(rule1.getCreatedAt()).isEqualTo(DATE1.getTime()); diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/RuleUpdaterTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/RuleUpdaterTest.java index da570b0b559..ecc257754b6 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/RuleUpdaterTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/RuleUpdaterTest.java @@ -46,6 +46,7 @@ import org.sonar.db.rule.RuleDefinitionDto; import org.sonar.db.rule.RuleDto; import org.sonar.db.rule.RuleParamDto; import org.sonar.db.rule.RuleTesting; +import org.sonar.db.user.UserDto; import org.sonar.server.es.EsTester; import org.sonar.server.es.SearchOptions; import org.sonar.server.qualityprofile.QProfileTesting; @@ -105,7 +106,7 @@ public class RuleUpdaterTest { RuleDto ruleDto = RuleTesting.newDto(RULE_KEY, db.getDefaultOrganization()) // the following fields are not supposed to be updated .setNoteData("my *note*") - .setNoteUserLogin("me") + .setNoteUserUuid("me") .setTags(ImmutableSet.of("tag1")) .setRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE.name()) .setRemediationGapMultiplier("1d") @@ -121,7 +122,7 @@ public class RuleUpdaterTest { dbSession.clearCache(); RuleDto rule = db.getDbClient().ruleDao().selectOrFailByKey(dbSession, db.getDefaultOrganization(), RULE_KEY); assertThat(rule.getNoteData()).isEqualTo("my *note*"); - assertThat(rule.getNoteUserLogin()).isEqualTo("me"); + assertThat(rule.getNoteUserUuid()).isEqualTo("me"); assertThat(rule.getTags()).containsOnly("tag1"); assertThat(rule.getRemediationFunction()).isEqualTo(DebtRemediationFunction.Type.CONSTANT_ISSUE.name()); assertThat(rule.getRemediationGapMultiplier()).isEqualTo("1d"); @@ -130,11 +131,12 @@ public class RuleUpdaterTest { @Test public void set_markdown_note() { - userSessionRule.logIn("me"); + UserDto user = db.users().insertUser(); + userSessionRule.logIn(user); RuleDto ruleDto = RuleTesting.newDto(RULE_KEY, db.getDefaultOrganization()) .setNoteData(null) - .setNoteUserLogin(null) + .setNoteUserUuid(null) // the following fields are not supposed to be updated .setTags(ImmutableSet.of("tag1")) @@ -153,7 +155,7 @@ public class RuleUpdaterTest { dbSession.clearCache(); RuleDto rule = db.getDbClient().ruleDao().selectOrFailByKey(dbSession, db.getDefaultOrganization(), RULE_KEY); assertThat(rule.getNoteData()).isEqualTo("my *note*"); - assertThat(rule.getNoteUserLogin()).isEqualTo("me"); + assertThat(rule.getNoteUserUuid()).isEqualTo(user.getUuid()); assertThat(rule.getNoteCreatedAt()).isNotNull(); assertThat(rule.getNoteUpdatedAt()).isNotNull(); // no other changes @@ -167,7 +169,7 @@ public class RuleUpdaterTest { public void remove_markdown_note() { RuleDto ruleDto = RuleTesting.newDto(RULE_KEY, db.getDefaultOrganization()) .setNoteData("my *note*") - .setNoteUserLogin("me"); + .setNoteUserUuid("me"); db.rules().insert(ruleDto.getDefinition()); db.rules().insertOrUpdateMetadata(ruleDto.getMetadata().setRuleId(ruleDto.getId())); dbSession.commit(); @@ -180,7 +182,7 @@ public class RuleUpdaterTest { dbSession.clearCache(); RuleDto rule = db.getDbClient().ruleDao().selectOrFailByKey(dbSession, db.getDefaultOrganization(), RULE_KEY); assertThat(rule.getNoteData()).isNull(); - assertThat(rule.getNoteUserLogin()).isNull(); + assertThat(rule.getNoteUserUuid()).isNull(); assertThat(rule.getNoteCreatedAt()).isNull(); assertThat(rule.getNoteUpdatedAt()).isNull(); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/SearchActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/SearchActionTest.java index 82cc8dfb3de..93c88fffd81 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/SearchActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/SearchActionTest.java @@ -43,6 +43,7 @@ import org.sonar.db.qualityprofile.QProfileDto; import org.sonar.db.rule.RuleDefinitionDto; import org.sonar.db.rule.RuleMetadataDto; import org.sonar.db.rule.RuleParamDto; +import org.sonar.db.user.UserDto; import org.sonar.server.es.EsTester; import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.language.LanguageTesting; @@ -113,7 +114,8 @@ public class SearchActionTest { private RuleQueryFactory ruleQueryFactory = new RuleQueryFactory(db.getDbClient(), wsSupport); private MacroInterpreter macroInterpreter = mock(MacroInterpreter.class); private RuleMapper ruleMapper = new RuleMapper(languages, macroInterpreter); - private SearchAction underTest = new SearchAction(ruleIndex, activeRuleCompleter, ruleQueryFactory, db.getDbClient(), ruleMapper); + private SearchAction underTest = new SearchAction(ruleIndex, activeRuleCompleter, ruleQueryFactory, db.getDbClient(), ruleMapper, + new RuleWsSupport(db.getDbClient(), userSession, defaultOrganizationProvider)); private TypeValidations typeValidations = new TypeValidations(asList(new StringTypeValidation(), new IntegerTypeValidation())); private RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, db.getDbClient(), typeValidations, userSession); private QProfileRules qProfileRules = new QProfileRulesImpl(db.getDbClient(), ruleActivator, ruleIndex, activeRuleIndexer); @@ -162,6 +164,29 @@ public class SearchActionTest { }, rule1, rule2); } + @Test + public void return_note_login() { + OrganizationDto organization = db.organizations().insert(); + UserDto user1 = db.users().insertUser(); + RuleDefinitionDto rule1 = db.rules().insert(); + db.rules().insertOrUpdateMetadata(rule1, user1, organization); + UserDto disableUser = db.users().insertDisabledUser(); + RuleDefinitionDto rule2 = db.rules().insert(); + db.rules().insertOrUpdateMetadata(rule2, disableUser, organization); + indexRules(); + + SearchResponse result = ws.newRequest() + .setParam("f", "noteLogin") + .setParam("organization", organization.getKey()) + .executeProtobuf(SearchResponse.class); + + assertThat(result.getRulesList()) + .extracting(Rule::getKey, Rule::getNoteLogin) + .containsExactlyInAnyOrder( + tuple(rule1.getKey().toString(), user1.getLogin()), + tuple(rule2.getKey().toString(), disableUser.getLogin())); + } + @Test public void filter_by_rule_key() { RuleDefinitionDto rule1 = createJavaRule(); @@ -324,6 +349,7 @@ public class SearchActionTest { indexRules(); SearchResponse result = ws.newRequest() + .setParam("f", "repo,name") .setParam("facets", "tags") .setParam("organization", organization.getKey()) .executeProtobuf(SearchResponse.class); @@ -341,6 +367,7 @@ public class SearchActionTest { indexRules(); SearchResponse result = ws.newRequest() + .setParam("f", "repo,name") .setParam("facets", "tags") .setParam("organization", organization.getKey()) .executeProtobuf(SearchResponse.class); @@ -409,8 +436,7 @@ public class SearchActionTest { .extracting(v -> tuple(v.getVal(), v.getCount())) .containsExactly( tuple("system1", 1L), - tuple("system2", 1L) - ); + tuple("system2", 1L)); } @Test @@ -455,11 +481,10 @@ public class SearchActionTest { @Test public void search_debt_rules_with_default_and_overridden_debt_values() { - RuleDefinitionDto rule = db.rules().insert(r -> - r.setLanguage("java") - .setDefRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) - .setDefRemediationGapMultiplier("1h") - .setDefRemediationBaseEffort("15min")); + RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("java") + .setDefRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) + .setDefRemediationGapMultiplier("1h") + .setDefRemediationBaseEffort("15min")); RuleMetadataDto metadata = insertMetadata(db.getDefaultOrganization(), rule, r -> r.setRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) @@ -490,11 +515,10 @@ public class SearchActionTest { @Test public void search_debt_rules_with_default_linear_offset_and_overridden_constant_debt() { - RuleDefinitionDto rule = db.rules().insert(r -> - r.setLanguage("java") - .setDefRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) - .setDefRemediationGapMultiplier("1h") - .setDefRemediationBaseEffort("15min")); + RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("java") + .setDefRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) + .setDefRemediationGapMultiplier("1h") + .setDefRemediationBaseEffort("15min")); RuleMetadataDto metadata = insertMetadata(db.getDefaultOrganization(), rule, r -> r.setRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE.name()) @@ -525,11 +549,10 @@ public class SearchActionTest { @Test public void search_debt_rules_with_default_linear_offset_and_overridden_linear_debt() { - RuleDefinitionDto rule = db.rules().insert(r -> - r.setLanguage("java") - .setDefRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) - .setDefRemediationGapMultiplier("1h") - .setDefRemediationBaseEffort("15min")); + RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("java") + .setDefRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) + .setDefRemediationGapMultiplier("1h") + .setDefRemediationBaseEffort("15min")); RuleMetadataDto metadata = insertMetadata(db.getDefaultOrganization(), rule, r -> r.setRemediationFunction(DebtRemediationFunction.Type.LINEAR.name()) @@ -560,12 +583,10 @@ public class SearchActionTest { @Test public void search_template_rules() { - RuleDefinitionDto templateRule = db.rules().insert(r -> - r.setLanguage("java") - .setIsTemplate(true)); - RuleDefinitionDto rule = db.rules().insert(r -> - r.setLanguage("java") - .setTemplateId(templateRule.getId())); + RuleDefinitionDto templateRule = db.rules().insert(r -> r.setLanguage("java") + .setIsTemplate(true)); + RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("java") + .setTemplateId(templateRule.getId())); indexRules(); @@ -584,12 +605,10 @@ public class SearchActionTest { @Test public void search_custom_rules_from_template_key() { - RuleDefinitionDto templateRule = db.rules().insert(r -> - r.setLanguage("java") - .setIsTemplate(true)); - RuleDefinitionDto rule = db.rules().insert(r -> - r.setLanguage("java") - .setTemplateId(templateRule.getId())); + RuleDefinitionDto templateRule = db.rules().insert(r -> r.setLanguage("java") + .setIsTemplate(true)); + RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("java") + .setTemplateId(templateRule.getId())); indexRules(); @@ -639,24 +658,21 @@ public class SearchActionTest { RuleDefinitionDto rule = createJavaRule(); - RuleParamDto ruleParam1 = db.rules().insertRuleParam(rule, p -> - p.setDefaultValue("some value") - .setType("STRING") - .setDescription("My small description") - .setName("my_var")); + RuleParamDto ruleParam1 = db.rules().insertRuleParam(rule, p -> p.setDefaultValue("some value") + .setType("STRING") + .setDescription("My small description") + .setName("my_var")); - RuleParamDto ruleParam2 = db.rules().insertRuleParam(rule, p -> - p.setDefaultValue("1") - .setType("INTEGER") - .setDescription("My small description") - .setName("the_var")); + RuleParamDto ruleParam2 = db.rules().insertRuleParam(rule, p -> p.setDefaultValue("1") + .setType("INTEGER") + .setDescription("My small description") + .setName("the_var")); // SONAR-7083 - RuleParamDto ruleParam3 = db.rules().insertRuleParam(rule, p -> - p.setDefaultValue(null) - .setType("STRING") - .setDescription("Empty Param") - .setName("empty_var")); + RuleParamDto ruleParam3 = db.rules().insertRuleParam(rule, p -> p.setDefaultValue(null) + .setType("STRING") + .setDescription("Empty Param") + .setName("empty_var")); RuleActivation activation = RuleActivation.create(rule.getId()); List activeRuleChanges1 = qProfileRules.activateAndCommit(db.getSession(), profile, singleton(activation)); @@ -688,8 +704,7 @@ public class SearchActionTest { assertThat(activeList.getParamsCount()).isEqualTo(2); assertThat(activeList.getParamsList()).extracting("key", "value").containsExactlyInAnyOrder( tuple(ruleParam1.getName(), ruleParam1.getDefaultValue()), - tuple(ruleParam2.getName(), ruleParam2.getDefaultValue()) - ); + tuple(ruleParam2.getName(), ruleParam2.getDefaultValue())); String unknownProfile = "unknown_profile" + randomAlphanumeric(5); expectedException.expect(NotFoundException.class); @@ -708,11 +723,10 @@ public class SearchActionTest { RuleDefinitionDto rule = createJavaRule(); - RuleParamDto ruleParam = db.rules().insertRuleParam(rule, p -> - p.setDefaultValue("some value") - .setType("STRING") - .setDescription("My small description") - .setName("my_var")); + RuleParamDto ruleParam = db.rules().insertRuleParam(rule, p -> p.setDefaultValue("some value") + .setType("STRING") + .setDescription("My small description") + .setName("my_var")); RuleActivation activation = RuleActivation.create(rule.getId()); List activeRuleChanges = qProfileRules.activateAndCommit(db.getSession(), profile, singleton(activation)); @@ -744,8 +758,7 @@ public class SearchActionTest { assertThat(activeList.getParamsCount()).isEqualTo(2); assertThat(activeList.getParamsList()).extracting("key", "value").containsExactlyInAnyOrder( tuple(ruleParam.getName(), ruleParam.getDefaultValue()), - tuple(activeRuleParam.getKey(), "") - ); + tuple(activeRuleParam.getKey(), "")); } /** @@ -757,8 +770,7 @@ public class SearchActionTest { OrganizationDto organization = db.organizations().insert(); QProfileDto profile = db.qualityProfiles().insert(organization, q -> q - .setLanguage("language1") - ); + .setLanguage("language1")); // on same language, not activated => match RuleDefinitionDto rule1 = db.rules().insert(r -> r @@ -811,51 +823,45 @@ public class SearchActionTest { tuple(rule1.getLanguage(), 1L), // known limitation: irrelevant languages are shown in this case (SONAR-9683) - tuple(rule3.getLanguage(), 1L) - ); + tuple(rule3.getLanguage(), 1L)); assertThat(result.getFacets().getFacetsList().stream().filter(f -> "tags".equals(f.getProperty())).findAny().get().getValuesList()) .extracting(Common.FacetValue::getVal, Common.FacetValue::getCount) .as("Facet tags") .containsExactlyInAnyOrder( - tuple(rule1.getSystemTags().iterator().next(), 1L) - ); + tuple(rule1.getSystemTags().iterator().next(), 1L)); assertThat(result.getFacets().getFacetsList().stream().filter(f -> "repositories".equals(f.getProperty())).findAny().get().getValuesList()) .extracting(Common.FacetValue::getVal, Common.FacetValue::getCount) .as("Facet repositories") .containsExactlyInAnyOrder( - tuple(rule1.getRepositoryKey(), 1L) - ); + tuple(rule1.getRepositoryKey(), 1L)); assertThat(result.getFacets().getFacetsList().stream().filter(f -> "severities".equals(f.getProperty())).findAny().get().getValuesList()) .extracting(Common.FacetValue::getVal, Common.FacetValue::getCount) .as("Facet severities") .containsExactlyInAnyOrder( - tuple("BLOCKER" /*rule2*/, 0L), - tuple("CRITICAL"/*rule1*/, 1L), + tuple("BLOCKER" /* rule2 */, 0L), + tuple("CRITICAL"/* rule1 */, 1L), tuple("MAJOR", 0L), tuple("MINOR", 0L), - tuple("INFO", 0L) - ); + tuple("INFO", 0L)); assertThat(result.getFacets().getFacetsList().stream().filter(f -> "statuses".equals(f.getProperty())).findAny().get().getValuesList()) .extracting(Common.FacetValue::getVal, Common.FacetValue::getCount) .as("Facet statuses") .containsExactlyInAnyOrder( - tuple("READY"/*rule2*/, 0L), - tuple("BETA" /*rule1*/, 1L), - tuple("DEPRECATED", 0L) - ); + tuple("READY"/* rule2 */, 0L), + tuple("BETA" /* rule1 */, 1L), + tuple("DEPRECATED", 0L)); assertThat(result.getFacets().getFacetsList().stream().filter(f -> "types".equals(f.getProperty())).findAny().get().getValuesList()) .extracting(Common.FacetValue::getVal, Common.FacetValue::getCount) .as("Facet types") .containsExactlyInAnyOrder( - tuple("BUG" /*rule2*/, 0L), - tuple("CODE_SMELL"/*rule1*/, 1L), - tuple("VULNERABILITY", 0L) - ); + tuple("BUG" /* rule2 */, 0L), + tuple("CODE_SMELL"/* rule1 */, 1L), + tuple("VULNERABILITY", 0L)); } @Test @@ -875,8 +881,7 @@ public class SearchActionTest { assertThat(result.getRulesList()).extracting("key", "status.name").containsExactlyInAnyOrder( tuple(rule1.getKey().toString(), rule1.getStatus().name()), tuple(rule2.getKey().toString(), rule2.getStatus().name()), - tuple(rule3.getKey().toString(), rule3.getStatus().name()) - ); + tuple(rule3.getKey().toString(), rule3.getStatus().name())); } @Test diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/ShowActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/ShowActionTest.java index be0ffb160b6..eda926b60dc 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/ShowActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/ShowActionTest.java @@ -47,6 +47,7 @@ import org.sonar.db.rule.RuleDto.Scope; import org.sonar.db.rule.RuleMetadataDto; import org.sonar.db.rule.RuleParamDto; import org.sonar.db.rule.RuleTesting; +import org.sonar.db.user.UserDto; import org.sonar.server.es.EsClient; import org.sonar.server.es.EsTester; import org.sonar.server.es.StartupIndexer; @@ -59,6 +60,7 @@ import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; import org.sonar.server.rule.NewCustomRule; import org.sonar.server.rule.RuleCreator; import org.sonar.server.rule.index.RuleIndexer; +import org.sonar.server.tester.UserSessionRule; import org.sonar.server.text.MacroInterpreter; import org.sonar.server.util.TypeValidations; import org.sonar.server.ws.TestResponse; @@ -87,21 +89,23 @@ public class ShowActionTest { private static final String INTERPRETED = "interpreted"; @org.junit.Rule - public DbTester dbTester = DbTester.create(); + public UserSessionRule userSession = UserSessionRule.standalone(); + @org.junit.Rule + public DbTester db = DbTester.create(); @org.junit.Rule public EsTester es = EsTester.create(); @org.junit.Rule public ExpectedException thrown = ExpectedException.none(); - private DbClient dbClient = dbTester.getDbClient(); + private DbClient dbClient = db.getDbClient(); private EsClient esClient = es.client(); - private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(dbTester); + private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db); private MacroInterpreter macroInterpreter = mock(MacroInterpreter.class); private Languages languages = new Languages(LanguageTesting.newLanguage("xoo", "Xoo")); private RuleMapper mapper = new RuleMapper(languages, macroInterpreter); private ActiveRuleCompleter activeRuleCompleter = mock(ActiveRuleCompleter.class); - private WsAction underTest = new ShowAction(dbClient, mapper, activeRuleCompleter, defaultOrganizationProvider); + private WsAction underTest = new ShowAction(dbClient, mapper, activeRuleCompleter, new RuleWsSupport(db.getDbClient(), userSession, defaultOrganizationProvider)); private WsActionTester actionTester = new WsActionTester(underTest); private RuleIndexer ruleIndexer = new RuleIndexer(esClient, dbClient); @@ -124,7 +128,7 @@ public class ShowActionTest { @Test public void should_show_rule_tags_in_default_organization() { RuleDefinitionDto rule = insertRule(); - RuleMetadataDto metadata = insertMetadata(dbTester.getDefaultOrganization(), rule, setTags("tag1", "tag2")); + RuleMetadataDto metadata = insertMetadata(db.getDefaultOrganization(), rule, setTags("tag1", "tag2"), m -> m.setNoteData(null).setNoteUserUuid(null)); Rules.ShowResponse result = actionTester.newRequest() .setParam(PARAM_KEY, rule.getKey().toString()) @@ -136,8 +140,8 @@ public class ShowActionTest { @Test public void should_show_rule_tags_in_specific_organization() { RuleDefinitionDto rule = insertRule(); - OrganizationDto organization = dbTester.organizations().insert(); - RuleMetadataDto metadata = insertMetadata(organization, rule, setTags("tag1", "tag2")); + OrganizationDto organization = db.organizations().insert(); + RuleMetadataDto metadata = insertMetadata(organization, rule, setTags("tag1", "tag2"), m -> m.setNoteData(null).setNoteUserUuid(null)); Rules.ShowResponse result = actionTester.newRequest() .setParam(PARAM_KEY, rule.getKey().toString()) @@ -149,14 +153,13 @@ public class ShowActionTest { @Test public void show_rule_with_activation() { - OrganizationDto organization = dbTester.organizations().insert(); - + OrganizationDto organization = db.organizations().insert(); QProfileDto profile = QProfileTesting.newXooP1(organization); - dbClient.qualityProfileDao().insert(dbTester.getSession(), profile); - dbTester.commit(); + dbClient.qualityProfileDao().insert(db.getSession(), profile); + db.commit(); RuleDefinitionDto rule = insertRule(); - RuleMetadataDto ruleMetadata = dbTester.rules().insertOrUpdateMetadata(rule, organization); + RuleMetadataDto ruleMetadata = db.rules().insertOrUpdateMetadata(rule, organization, m -> m.setNoteData(null).setNoteUserUuid(null)); ArgumentCaptor orgCaptor = ArgumentCaptor.forClass(OrganizationDto.class); ArgumentCaptor ruleCaptor = ArgumentCaptor.forClass(RuleDefinitionDto.class); @@ -192,16 +195,16 @@ public class ShowActionTest { @Test public void show_rule_without_activation() { - OrganizationDto organization = dbTester.organizations().insert(); + OrganizationDto organization = db.organizations().insert(); QProfileDto profile = QProfileTesting.newXooP1(organization); - dbClient.qualityProfileDao().insert(dbTester.getSession(), profile); - dbTester.commit(); + dbClient.qualityProfileDao().insert(db.getSession(), profile); + db.commit(); RuleDefinitionDto rule = insertRule(); - RuleMetadataDto ruleMetadata = dbTester.rules().insertOrUpdateMetadata(rule, organization); + RuleMetadataDto ruleMetadata = db.rules().insertOrUpdateMetadata(rule, organization, m -> m.setNoteData(null).setNoteUserUuid(null)); - dbTester.qualityProfiles().activateRule(profile, rule, a -> a.setSeverity("BLOCKER")); + db.qualityProfiles().activateRule(profile, rule, a -> a.setSeverity("BLOCKER")); ActiveRuleIndexer activeRuleIndexer = new ActiveRuleIndexer(dbClient, esClient); activeRuleIndexer.indexOnStartup(activeRuleIndexer.getIndexTypes()); @@ -221,7 +224,7 @@ public class ShowActionTest { @Test public void throw_NotFoundException_if_organization_cannot_be_found() { - RuleDefinitionDto rule = dbTester.rules().insert(); + RuleDefinitionDto rule = db.rules().insert(); thrown.expect(NotFoundException.class); @@ -232,8 +235,8 @@ public class ShowActionTest { } @Test - public void show_rule() throws Exception { - RuleDto ruleDto = RuleTesting.newDto(RuleKey.of("java", "S001"), dbTester.getDefaultOrganization()) + public void show_rule() { + RuleDto ruleDto = RuleTesting.newDto(RuleKey.of("java", "S001"), db.getDefaultOrganization()) .setName("Rule S001") .setDescription("Rule S001 description") .setDescriptionFormat(Format.HTML) @@ -247,7 +250,7 @@ public class ShowActionTest { .setScope(Scope.ALL); RuleDefinitionDto definition = ruleDto.getDefinition(); RuleDao ruleDao = dbClient.ruleDao(); - DbSession session = dbTester.getSession(); + DbSession session = db.getSession(); ruleDao.insert(session, definition); ruleDao.insertOrUpdate(session, ruleDto.getMetadata().setRuleId(ruleDto.getId())); RuleParamDto param = RuleParamDto.createFor(definition).setName("regex").setType("STRING").setDescription("Reg *exp*").setDefaultValue(".*"); @@ -261,8 +264,8 @@ public class ShowActionTest { } @Test - public void show_rule_with_default_debt_infos() throws Exception { - RuleDto ruleDto = RuleTesting.newDto(RuleKey.of("java", "S001"), dbTester.getDefaultOrganization()) + public void show_rule_with_default_debt_infos() { + RuleDto ruleDto = RuleTesting.newDto(RuleKey.of("java", "S001"), db.getDefaultOrganization()) .setName("Rule S001") .setDescription("Rule S001 description") .setSeverity(MINOR) @@ -277,7 +280,7 @@ public class ShowActionTest { .setRemediationBaseEffort(null) .setScope(Scope.ALL); RuleDao ruleDao = dbClient.ruleDao(); - DbSession session = dbTester.getSession(); + DbSession session = db.getSession(); ruleDao.insert(session, ruleDto.getDefinition()); ruleDao.insertOrUpdate(session, ruleDto.getMetadata()); session.commit(); @@ -290,8 +293,8 @@ public class ShowActionTest { } @Test - public void show_rule_with_overridden_debt() throws Exception { - RuleDto ruleDto = RuleTesting.newDto(RuleKey.of("java", "S001"), dbTester.getDefaultOrganization()) + public void show_rule_with_overridden_debt() { + RuleDto ruleDto = RuleTesting.newDto(RuleKey.of("java", "S001"), db.getDefaultOrganization()) .setName("Rule S001") .setDescription("Rule S001 description") .setSeverity(MINOR) @@ -306,7 +309,7 @@ public class ShowActionTest { .setRemediationBaseEffort("10h") .setScope(Scope.ALL); RuleDao ruleDao = dbClient.ruleDao(); - DbSession session = dbTester.getSession(); + DbSession session = db.getSession(); ruleDao.insert(session, ruleDto.getDefinition()); ruleDao.insertOrUpdate(session, ruleDto.getMetadata().setRuleId(ruleDto.getId())); session.commit(); @@ -318,8 +321,8 @@ public class ShowActionTest { } @Test - public void show_rule_with_default_and_overridden_debt_infos() throws Exception { - RuleDto ruleDto = RuleTesting.newDto(RuleKey.of("java", "S001"), dbTester.getDefaultOrganization()) + public void show_rule_with_default_and_overridden_debt_infos() { + RuleDto ruleDto = RuleTesting.newDto(RuleKey.of("java", "S001"), db.getDefaultOrganization()) .setName("Rule S001") .setDescription("Rule S001 description") .setSeverity(MINOR) @@ -334,7 +337,7 @@ public class ShowActionTest { .setRemediationBaseEffort("10h") .setScope(Scope.ALL); RuleDao ruleDao = dbClient.ruleDao(); - DbSession session = dbTester.getSession(); + DbSession session = db.getSession(); ruleDao.insert(session, ruleDto.getDefinition()); ruleDao.insertOrUpdate(session, ruleDto.getMetadata().setRuleId(ruleDto.getId())); session.commit(); @@ -346,7 +349,7 @@ public class ShowActionTest { } @Test - public void show_rule_with_no_default_and_no_overridden_debt() throws Exception { + public void show_rule_with_no_default_and_no_overridden_debt() { RuleDefinitionDto ruleDto = RuleTesting.newRule(RuleKey.of("java", "S001")) .setName("Rule S001") .setDescription("Rule S001 description") @@ -360,7 +363,7 @@ public class ShowActionTest { .setDefRemediationBaseEffort(null) .setScope(Scope.ALL); RuleDao ruleDao = dbClient.ruleDao(); - DbSession session = dbTester.getSession(); + DbSession session = db.getSession(); ruleDao.insert(session, ruleDto); session.commit(); session.clearCache(); @@ -375,7 +378,7 @@ public class ShowActionTest { // Template rule RuleDto templateRule = RuleTesting.newTemplateRule(RuleKey.of("java", "S001")); RuleDao ruleDao = dbClient.ruleDao(); - DbSession session = dbTester.getSession(); + DbSession session = db.getSession(); ruleDao.insert(session, templateRule.getDefinition()); session.commit(); @@ -385,7 +388,7 @@ public class ShowActionTest { .setSeverity(MINOR) .setStatus(RuleStatus.READY) .setMarkdownDescription("
line1\nline2
"); - RuleKey customRuleKey = new RuleCreator(System2.INSTANCE, ruleIndexer, dbClient, new TypeValidations(asList()), TestDefaultOrganizationProvider.from(dbTester)).create(session, customRule); + RuleKey customRuleKey = new RuleCreator(System2.INSTANCE, ruleIndexer, dbClient, new TypeValidations(asList()), TestDefaultOrganizationProvider.from(db)).create(session, customRule); session.clearCache(); doReturn("<div>line1
line2</div>").when(macroInterpreter).interpret("
line1\nline2
"); @@ -402,8 +405,8 @@ public class ShowActionTest { } @Test - public void show_deprecated_rule_rem_function_fields() throws Exception { - RuleDto ruleDto = RuleTesting.newDto(RuleKey.of("java", "S001"), dbTester.getDefaultOrganization()) + public void show_deprecated_rule_rem_function_fields() { + RuleDto ruleDto = RuleTesting.newDto(RuleKey.of("java", "S001"), db.getDefaultOrganization()) .setName("Rule S001") .setDescription("Rule S001 description") .setSeverity(MINOR) @@ -418,7 +421,7 @@ public class ShowActionTest { .setRemediationBaseEffort("10h") .setScope(Scope.ALL); RuleDao ruleDao = dbClient.ruleDao(); - DbSession session = dbTester.getSession(); + DbSession session = db.getSession(); ruleDao.insert(session, ruleDto.getDefinition()); ruleDao.insertOrUpdate(session, ruleDto.getMetadata().setRuleId(ruleDto.getId())); session.commit(); @@ -429,7 +432,7 @@ public class ShowActionTest { } @Test - public void show_rule_when_activated() throws Exception { + public void show_rule_when_activated() { RuleDefinitionDto ruleDto = RuleTesting.newRule(RuleKey.of("java", "S001")) .setName("Rule S001") .setDescription("Rule S001 description") @@ -442,7 +445,7 @@ public class ShowActionTest { .setUpdatedAt(new Date().getTime()) .setScope(Scope.ALL); RuleDao ruleDao = dbClient.ruleDao(); - DbSession session = dbTester.getSession(); + DbSession session = db.getSession(); ruleDao.insert(session, ruleDto); session.commit(); ruleIndexer.commitAndIndex(session, ruleDto.getId()); @@ -473,7 +476,7 @@ public class ShowActionTest { activeRuleIndexer.indexOnStartup(activeRuleIndexer.getIndexTypes()); ActiveRuleCompleter activeRuleCompleter = new ActiveRuleCompleter(dbClient, languages); - WsAction underTest = new ShowAction(dbClient, mapper, activeRuleCompleter, defaultOrganizationProvider); + WsAction underTest = new ShowAction(dbClient, mapper, activeRuleCompleter, new RuleWsSupport(db.getDbClient(), userSession, defaultOrganizationProvider)); WsActionTester actionTester = new WsActionTester(underTest); actionTester.newRequest() @@ -482,6 +485,22 @@ public class ShowActionTest { .execute().assertJson(getClass(), "show_rule_when_activated.json"); } + @Test + public void show_rule_with_note_login() { + RuleDefinitionDto rule = insertRule(); + UserDto user = db.users().insertUser(); + OrganizationDto organization = db.organizations().insert(); + db.rules().insertOrUpdateMetadata(rule, user, organization); + ruleIndexer.commitAndIndex(db.getSession(), rule.getId(), organization); + + Rules.ShowResponse result = actionTester.newRequest() + .setParam(PARAM_KEY, rule.getKey().toString()) + .setParam(PARAM_ORGANIZATION, organization.getKey()) + .executeProtobuf(Rules.ShowResponse.class); + + assertThat(result.getRule().getNoteLogin()).isEqualTo(user.getLogin()); + } + private void assertEqual(RuleDefinitionDto rule, RuleMetadataDto ruleMetadata, Rule resultRule) { assertThat(resultRule.getKey()).isEqualTo(rule.getKey().toString()); assertThat(resultRule.getRepo()).isEqualTo(rule.getRepositoryKey()); @@ -497,15 +516,15 @@ public class ShowActionTest { } private RuleDefinitionDto insertRule() { - RuleDefinitionDto rule = dbTester.rules().insert(); - ruleIndexer.commitAndIndex(dbTester.getSession(), rule.getId()); + RuleDefinitionDto rule = db.rules().insert(); + ruleIndexer.commitAndIndex(db.getSession(), rule.getId()); return rule; } @SafeVarargs private final RuleMetadataDto insertMetadata(OrganizationDto organization, RuleDefinitionDto rule, Consumer... populaters) { - RuleMetadataDto metadata = dbTester.rules().insertOrUpdateMetadata(rule, organization, populaters); - ruleIndexer.commitAndIndex(dbTester.getSession(), rule.getId(), organization); + RuleMetadataDto metadata = db.rules().insertOrUpdateMetadata(rule, organization, populaters); + ruleIndexer.commitAndIndex(db.getSession(), rule.getId(), organization); return metadata; } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/UpdateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/UpdateActionTest.java index c66bc2e0b49..0399cc063fb 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/UpdateActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/UpdateActionTest.java @@ -33,6 +33,7 @@ import org.sonar.db.organization.OrganizationDto; import org.sonar.db.rule.RuleDefinitionDto; import org.sonar.db.rule.RuleMetadataDto; import org.sonar.db.rule.RuleTesting; +import org.sonar.db.user.UserDto; import org.sonar.server.es.EsClient; import org.sonar.server.es.EsTester; import org.sonar.server.exceptions.ForbiddenException; @@ -63,6 +64,7 @@ import static org.sonar.server.rule.ws.UpdateAction.DEPRECATED_PARAM_REMEDIATION import static org.sonar.server.rule.ws.UpdateAction.DEPRECATED_PARAM_REMEDIATION_FN_OFFSET; import static org.sonar.server.rule.ws.UpdateAction.DEPRECATED_PARAM_REMEDIATION_FN_TYPE; import static org.sonar.server.rule.ws.UpdateAction.PARAM_KEY; +import static org.sonar.server.rule.ws.UpdateAction.PARAM_MARKDOWN_NOTE; import static org.sonar.server.rule.ws.UpdateAction.PARAM_ORGANIZATION; import static org.sonar.server.rule.ws.UpdateAction.PARAM_REMEDIATION_FN_BASE_EFFORT; import static org.sonar.server.rule.ws.UpdateAction.PARAM_REMEDIATION_FN_GAP_MULTIPLIER; @@ -94,7 +96,7 @@ public class UpdateActionTest { private RuleMapper mapper = new RuleMapper(languages, createMacroInterpreter()); private RuleIndexer ruleIndexer = new RuleIndexer(esClient, dbClient); private RuleUpdater ruleUpdater = new RuleUpdater(dbClient, ruleIndexer, System2.INSTANCE); - private WsAction underTest = new UpdateAction(dbClient, ruleUpdater, mapper, userSession, defaultOrganizationProvider); + private WsAction underTest = new UpdateAction(dbClient, ruleUpdater, mapper, userSession, new RuleWsSupport(db.getDbClient(), userSession, defaultOrganizationProvider)); private WsActionTester ws = new WsActionTester(underTest); @Test @@ -153,7 +155,7 @@ public class UpdateActionTest { logInAsQProfileAdministrator(); RuleDefinitionDto rule = db.rules().insert(setSystemTags("stag1", "stag2")); - db.rules().insertOrUpdateMetadata(rule, db.getDefaultOrganization(), setTags("tag1", "tag2")); + db.rules().insertOrUpdateMetadata(rule, db.getDefaultOrganization(), setTags("tag1", "tag2"), m -> m.setNoteData(null).setNoteUserUuid(null)); Rules.UpdateResponse result = ws.newRequest().setMethod("POST") .setParam(PARAM_KEY, rule.getKey().toString()) @@ -174,7 +176,7 @@ public class UpdateActionTest { logInAsQProfileAdministrator(organization.getUuid()); RuleDefinitionDto rule = db.rules().insert(setSystemTags("stag1", "stag2")); - db.rules().insertOrUpdateMetadata(rule, organization, setTags("tagAlt1", "tagAlt2")); + db.rules().insertOrUpdateMetadata(rule, organization, setTags("tagAlt1", "tagAlt2"), m -> m.setNoteData(null).setNoteUserUuid(null)); Rules.UpdateResponse result = ws.newRequest().setMethod("POST") .setParam(PARAM_KEY, rule.getKey().toString()) @@ -279,6 +281,33 @@ public class UpdateActionTest { assertThat(updatedRule.getGapDescription()).isEqualTo(rule.getGapDescription()); } + @Test + public void update_note() { + OrganizationDto organization = db.organizations().insert(); + RuleDefinitionDto rule = db.rules().insert(); + UserDto userHavingUpdatingNote = db.users().insertUser(); + db.rules().insertOrUpdateMetadata(rule, userHavingUpdatingNote, organization, m -> m.setNoteData("old data")); + UserDto userAuthenticated = db.users().insertUser(); + userSession.logIn(userAuthenticated).addPermission(ADMINISTER_QUALITY_PROFILES, organization); + + Rules.UpdateResponse result = ws.newRequest().setMethod("POST") + .setParam(PARAM_KEY, rule.getKey().toString()) + .setParam(PARAM_MARKDOWN_NOTE, "new data") + .setParam(PARAM_ORGANIZATION, organization.getKey()) + .executeProtobuf(Rules.UpdateResponse.class); + + Rules.Rule updatedRule = result.getRule(); + + // check response + assertThat(updatedRule.getMdNote()).isEqualTo("new data"); + assertThat(updatedRule.getNoteLogin()).isEqualTo(userAuthenticated.getLogin()); + + // check database + RuleMetadataDto metadataOfSpecificOrg = db.getDbClient().ruleDao().selectMetadataByKey(db.getSession(), rule.getKey(), organization).get(); + assertThat(metadataOfSpecificOrg.getNoteData()).isEqualTo("new data"); + assertThat(metadataOfSpecificOrg.getNoteUserUuid()).isEqualTo(userAuthenticated.getUuid()); + } + @Test public void fail_to_update_custom_when_description_is_empty() { logInAsQProfileAdministrator(); 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 e6c6e0eb62f..b7ec0965057 100644 --- a/tests/src/test/java/org/sonarqube/tests/user/SonarCloudUpdateLoginDuringAuthenticationTest.java +++ b/tests/src/test/java/org/sonarqube/tests/user/SonarCloudUpdateLoginDuringAuthenticationTest.java @@ -36,6 +36,7 @@ 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.Rules; import org.sonarqube.ws.Settings; import org.sonarqube.ws.UserTokens; import org.sonarqube.ws.Users; @@ -47,6 +48,7 @@ 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.rules.UpdateRequest; import org.sonarqube.ws.client.settings.SetRequest; import org.sonarqube.ws.client.settings.ValuesRequest; import org.sonarqube.ws.client.usertokens.GenerateRequest; @@ -54,6 +56,7 @@ 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.assertj.core.api.Assertions.tuple; import static org.skyscreamer.jsonassert.JSONAssert.assertEquals; import static util.ItUtils.projectDir; @@ -326,6 +329,38 @@ public class SonarCloudUpdateLoginDuringAuthenticationTest { false); } + @Test + public void rule_note_login_after_login_update() { + 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 qprofile admin permission on the organization + Organization organization = tester.organizations().generate(); + tester.organizations().service().addMember(new AddMemberRequest().setOrganization(organization.getKey()).setLogin(oldLogin)); + tester.wsClient().permissions().addUser(new AddUserRequest().setLogin(oldLogin).setOrganization(organization.getKey()).setPermission("profileadmin")); + + // Add a note on a rule + userWsClient.rules().update(new UpdateRequest().setOrganization(organization.getKey()).setKey("xoo:OneIssuePerLine").setMarkdownNote("A user note")); + assertThat( + tester.wsClient().rules().search(new org.sonarqube.ws.client.rules.SearchRequest().setOrganization(organization.getKey()).setRuleKey("xoo:OneIssuePerLine")).getRulesList()) + .extracting(Rules.Rule::getKey, Rules.Rule::getNoteLogin, Rules.Rule::getMdNote) + .containsExactlyInAnyOrder(tuple("xoo:OneIssuePerLine", oldLogin, "A user note")); + + // Update login during authentication, check rule note contains new user login + String newLogin = tester.users().generateLogin(); + authenticate(newLogin, providerId); + assertThat( + tester.wsClient().rules().search(new org.sonarqube.ws.client.rules.SearchRequest().setOrganization(organization.getKey()).setRuleKey("xoo:OneIssuePerLine")).getRulesList()) + .extracting(Rules.Rule::getKey, Rules.Rule::getNoteLogin, Rules.Rule::getMdNote) + .containsExactlyInAnyOrder(tuple("xoo:OneIssuePerLine", newLogin, "A user note")); + } + 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(