]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10597 Update RULES_METADATA#NOTE_USER_LOGIN to NOTE_USER_UUID
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Fri, 11 May 2018 07:41:17 +0000 (09:41 +0200)
committerSonarTech <sonartech@sonarsource.com>
Wed, 23 May 2018 18:20:47 +0000 (20:20 +0200)
* 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

24 files changed:
server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl
server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java
server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleMetadataDto.java
server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml
server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDbTester.java
server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleTesting.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v72/DbVersion72.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v72/RenameNoteUserLoginToNoteUserUuidOnTableRulesMetadata.java [new file with mode: 0644]
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/DbVersion72Test.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/RenameNoteUserLoginToNoteUserUuidOnTableRulesMetadataTest.java [new file with mode: 0644]
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v72/RenameNoteUserLoginToNoteUserUuidOnTableRulesMetadataTest/rules_metadata.sql [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdater.java
server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleMapper.java
server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleWsSupport.java
server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java
server/sonar-server/src/main/java/org/sonar/server/rule/ws/ShowAction.java
server/sonar-server/src/main/java/org/sonar/server/rule/ws/UpdateAction.java
server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesTest.java
server/sonar-server/src/test/java/org/sonar/server/rule/RuleUpdaterTest.java
server/sonar-server/src/test/java/org/sonar/server/rule/ws/SearchActionTest.java
server/sonar-server/src/test/java/org/sonar/server/rule/ws/ShowActionTest.java
server/sonar-server/src/test/java/org/sonar/server/rule/ws/UpdateActionTest.java
tests/src/test/java/org/sonarqube/tests/user/SonarCloudUpdateLoginDuringAuthenticationTest.java

index 4f8a73a1ff45f84b122c78f02a29655af68e0ca5..62d8774d7fe6d554f31c29210f5cf28f72ae3b7a 100644 (file)
@@ -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),
index 6d5d64c9eca0ef31709e9f6a3822781583940dc9..3441baff04d2c6e3617a3bc6d729947f5b081c9a 100644 (file)
@@ -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;
   }
 
index 05fac04da0b8a3fbb3a2a1a2ab48a4a96453697f..64e1130be7f8f37a10ed7f4a747abe141097ec37 100644 (file)
@@ -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 + '\'' +
index 7b7dabe472ca0c1686870ffba17c1361867e4545..487a02f4e0870b0175719ddf4e6f5b74470fed0d 100644 (file)
@@ -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",
       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",
       rule_id,
       organization_uuid,
       note_data,
-      note_user_login,
+      note_user_uuid,
       note_created_at,
       note_updated_at,
       remediation_function,
       #{ruleId,jdbcType=INTEGER},
       #{organizationUuid,jdbcType=VARCHAR},
       #{noteData,jdbcType=CLOB},
-      #{noteUserLogin,jdbcType=VARCHAR},
+      #{noteUserUuid,jdbcType=VARCHAR},
       #{noteCreatedAt,jdbcType=BIGINT},
       #{noteUpdatedAt,jdbcType=BIGINT},
       #{remediationFunction,jdbcType=VARCHAR},
   <update id="updateMetadata" parameterType="org.sonar.db.rule.RuleMetadataDto">
     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},
index 03bad9b6c8b70444522308e60cc0e47e5322407d..a4f3034566c40ff6d55c4e9d2889bb3e8fa0880e 100644 (file)
@@ -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");
index 1a7f32e792a7469e3db1e96b68c23674eaf27940..3ab4a154a034237d92b357e7213296eb0bb77905 100644 (file)
@@ -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<RuleMetadataDto>... 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();
index 4a90d86466d79ee3d4169826679405f47289b592..b979f66f9535a5aa61263769ea6d6d804a8aba87 100644 (file)
@@ -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())
index 20d40419ebe02e9bf66c11e62fe216d309d593a2..65d99312ce4b388d5eb3faac273d9d505af33667 100644 (file)
@@ -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 (file)
index 0000000..8736107
--- /dev/null
@@ -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());
+  }
+}
index 87922b1bf3944e944b417558e10e8e6f003fbf12..f83902a41d26c1493ed0efbc5ec228c0388bc523 100644 (file)
@@ -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 (file)
index 0000000..1470479
--- /dev/null
@@ -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 (file)
index 0000000..69c506a
--- /dev/null
@@ -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
index 10b6297f02da543bea4312a72257673ffa33f92e..3248fbbeae2f91ade36d827a12de0f2d1a17d68b 100644 (file)
@@ -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());
     }
   }
 
index 9a70c738b52c197a2560fc22a4e6f5909c6dc927..ad20629b98f88d79cb94b1f0d57f1950cc6ecb19 100644 (file)
@@ -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<String> fieldsToReturn, RuleMetadataDto metadata) {
+  public Rules.Rule toWsRule(RuleDefinitionDto ruleDefinitionDto, SearchResult result, Set<String> fieldsToReturn, RuleMetadataDto metadata, Map<String, UserDto> 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<String> fieldsToReturn) {
+  private void applyRuleMetadata(Rules.Rule.Builder ruleResponse, RuleMetadataDto metadata, Map<String, UserDto> usersByUuid, Set<String> 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<String> 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<String, UserDto> usersByUuid, Set<String> 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<String> 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<String> 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());
index cb27fc6fcaf112569ee41efa8581d9b337bb492b..ecd4b1bf5926eb2fab1cefff8e1f46a065cfe07d 100644 (file)
  */
 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<String, UserDto> getUsersByUuid(DbSession dbSession, List<RuleDto> rules) {
+    Set<String> userUuids = rules.stream().map(RuleDto::getNoteUserUuid).filter(Objects::nonNull).collect(toSet());
+    return dbClient.userDao().selectByUuids(dbSession, userUuids).stream().collect(uniqueIndex(UserDto::getUuid));
+  }
+
 }
index 99f2bec969981ce8b399a435121fededd01474b8..0027b0542faec3826b9248613030db2342192c28 100644 (file)
@@ -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<String, UserDto> 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);
     }
index 1f603dcb0517572f837f0d9110ac76630727358c..0b1faf67fd0ec1233e3055a59e5bfeac0ca52950 100644 (file)
@@ -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();
   }
+
 }
index b8f2ef6318a37079c4f8debf0e8862d159282e12..d93e3e1e85a3524d327517722ba297038ed55fd3 100644 (file)
@@ -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();
   }
index 5200a4830736d14ef5f75479c7dbe754bcfed60c..580e22dc528f444aa3375d256fdd029fb2557616 100644 (file)
@@ -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());
index da570b0b559076e3aad3a0b3b5410884561cbead..ecc257754b686697a77db79a114725219e814187 100644 (file)
@@ -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();
   }
index 82cc8dfb3de7e000c0b08da7297f50ceaa2547c8..93c88fffd811026b1d8fedf417ee6eb998721603 100644 (file)
@@ -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<ActiveRuleChange> 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<ActiveRuleChange> 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
index be0ffb160b66e9ea41a4133296e83b97e35e4fc4..eda926b60dc23dc9dc1c9829b7bf68eeb384badb 100644 (file)
@@ -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<OrganizationDto> orgCaptor = ArgumentCaptor.forClass(OrganizationDto.class);
     ArgumentCaptor<RuleDefinitionDto> 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 <b>description</b>")
       .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 <b>description</b>")
       .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 <b>description</b>")
       .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 <b>description</b>")
       .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 <b>description</b>")
@@ -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("<div>line1\nline2</div>");
-    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("&lt;div&gt;line1<br/>line2&lt;/div&gt;").when(macroInterpreter).interpret("<div>line1\nline2</div>");
@@ -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 <b>description</b>")
       .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 <b>description</b>")
@@ -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<RuleMetadataDto>... 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;
   }
 }
index c66bc2e0b49b2bb1004d4e0c7c3f330e054ee5a4..0399cc063fb6e61ea01d4bc8617a4f5f7ff328e8 100644 (file)
@@ -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();
index e6c6e0eb62f2832aecd47fff69bb78762ab30d01..b7ec0965057ec1e5ccd4a58afb030896e65e5438 100644 (file)
@@ -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(