ソースを参照

SONAR-20156 Create api/dismiss_message/dismiss endpoint

tags/10.2.0.77647
Nolwenn Cadic 9ヶ月前
コミット
fad21dcc76
35個のファイルの変更679行の追加159行の削除
  1. 2
    2
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/language/HandleUnanalyzedLanguagesStep.java
  2. 2
    2
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/language/HandleUnanalyzedLanguagesStepTest.java
  3. 2
    2
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistAnalysisWarningsStepTest.java
  4. 5
    5
      server/sonar-ce-task/src/main/java/org/sonar/ce/task/log/CeTaskMessages.java
  5. 2
    1
      server/sonar-db-dao/src/it/java/org/sonar/db/ce/CeActivityDaoIT.java
  6. 13
    12
      server/sonar-db-dao/src/it/java/org/sonar/db/ce/CeTaskMessageDaoIT.java
  7. 4
    4
      server/sonar-db-dao/src/it/java/org/sonar/db/purge/PurgeCommandsIT.java
  8. 5
    5
      server/sonar-db-dao/src/it/java/org/sonar/db/purge/PurgeDaoIT.java
  9. 39
    26
      server/sonar-db-dao/src/it/java/org/sonar/db/user/UserDismissedMessagesDaoIT.java
  10. 2
    1
      server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeTaskMessageDao.java
  11. 10
    3
      server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeTaskMessageDto.java
  12. 9
    4
      server/sonar-db-dao/src/main/java/org/sonar/db/dismissmessage/MessageType.java
  13. 10
    7
      server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDismissedMessageDto.java
  14. 10
    5
      server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDismissedMessagesDao.java
  15. 4
    2
      server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDismissedMessagesMapper.java
  16. 15
    5
      server/sonar-db-dao/src/main/resources/org/sonar/db/user/UserDismissedMessagesMapper.xml
  17. 13
    3
      server/sonar-db-dao/src/testFixtures/java/org/sonar/db/user/UserDbTester.java
  18. 5
    5
      server/sonar-webserver-common/src/it/java/org/sonar/server/common/user/service/UserServiceIT.java
  19. 14
    14
      server/sonar-webserver-core/src/it/java/org/sonar/server/startup/UpgradeSuggestionsCleanerIT.java
  20. 3
    3
      server/sonar-webserver-core/src/main/java/org/sonar/server/startup/UpgradeSuggestionsCleaner.java
  21. 2
    2
      server/sonar-webserver-webapi/src/it/java/org/sonar/server/ce/ws/ActivityActionIT.java
  22. 6
    6
      server/sonar-webserver-webapi/src/it/java/org/sonar/server/ce/ws/AnalysisStatusActionIT.java
  23. 2
    2
      server/sonar-webserver-webapi/src/it/java/org/sonar/server/ce/ws/ComponentActionIT.java
  24. 20
    12
      server/sonar-webserver-webapi/src/it/java/org/sonar/server/ce/ws/DismissAnalysisWarningActionIT.java
  25. 7
    7
      server/sonar-webserver-webapi/src/it/java/org/sonar/server/ce/ws/TaskActionIT.java
  26. 122
    0
      server/sonar-webserver-webapi/src/it/java/org/sonar/server/dismissmessage/ws/DismissActionIT.java
  27. 106
    0
      server/sonar-webserver-webapi/src/it/java/org/sonar/server/dismissmessage/ws/DismissActionParameterizedIT.java
  28. 5
    5
      server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/DeactivateActionIT.java
  29. 4
    8
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/ce/ws/DismissAnalysisWarningAction.java
  30. 129
    0
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/dismissmessage/ws/DismissAction.java
  31. 41
    0
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/dismissmessage/ws/DismissActionWs.java
  32. 25
    0
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/dismissmessage/ws/DismissMessageWsAction.java
  33. 31
    0
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/dismissmessage/ws/DismissMessageWsModule.java
  34. 6
    6
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/ce/ws/TaskFormatterTest.java
  35. 4
    0
      server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java

+ 2
- 2
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/language/HandleUnanalyzedLanguagesStep.java ファイルの表示

@@ -36,7 +36,7 @@ import org.sonar.ce.task.projectanalysis.metric.MetricRepository;
import org.sonar.ce.task.step.ComputationStep;
import org.sonar.core.platform.EditionProvider;
import org.sonar.core.platform.PlatformEditionProvider;
import org.sonar.db.ce.CeTaskMessageType;
import org.sonar.db.dismissmessage.MessageType;

import static java.lang.String.format;
import static org.sonar.core.language.UnanalyzedLanguages.C;
@@ -124,7 +124,7 @@ public class HandleUnanalyzedLanguagesStep implements ComputationStep {
}

String message = format(LANGUAGE_UPGRADE_MESSAGE, fileCountLabel, languageLabel, sortedLanguageMap.size() == 1 ? "this file" : "these files");
return new CeTaskMessages.Message(message, system.now(), CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
return new CeTaskMessages.Message(message, system.now(), MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
}

private void computeMeasures(Map<String, Integer> filesPerLanguage) {

+ 2
- 2
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/language/HandleUnanalyzedLanguagesStepTest.java ファイルの表示

@@ -40,7 +40,7 @@ import org.sonar.ce.task.projectanalysis.metric.MetricRepositoryRule;
import org.sonar.ce.task.step.TestComputationStepContext;
import org.sonar.core.platform.EditionProvider;
import org.sonar.core.platform.PlatformEditionProvider;
import org.sonar.db.ce.CeTaskMessageType;
import org.sonar.db.dismissmessage.MessageType;
import org.sonar.scanner.protocol.output.ScannerReport;

import static com.google.common.collect.ImmutableList.of;
@@ -112,7 +112,7 @@ public class HandleUnanalyzedLanguagesStepTest {
" C++ and SomeLang cannot be analyzed with your current SonarQube edition. Please consider" +
" <a target=\"_blank\" href=\"https://www.sonarqube.org/trial-request/developer-edition/?referrer=sonarqube-cpp\">upgrading to Developer Edition</a> to find Bugs," +
" Code Smells, Vulnerabilities and Security Hotspots in these files.",
CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE));
MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE));
assertThat(measureRepository.getAddedRawMeasure(PROJECT_REF, UNANALYZED_C_KEY).get().getIntValue()).isEqualTo(10);
assertThat(measureRepository.getAddedRawMeasure(PROJECT_REF, UNANALYZED_CPP_KEY).get().getIntValue()).isEqualTo(20);
}

+ 2
- 2
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistAnalysisWarningsStepTest.java ファイルの表示

@@ -30,7 +30,7 @@ import org.mockito.junit.MockitoJUnitRunner;
import org.sonar.ce.task.log.CeTaskMessages;
import org.sonar.ce.task.projectanalysis.batch.BatchReportReaderRule;
import org.sonar.ce.task.step.TestComputationStepContext;
import org.sonar.db.ce.CeTaskMessageType;
import org.sonar.db.dismissmessage.MessageType;
import org.sonar.scanner.protocol.output.ScannerReport;

import static com.google.common.collect.ImmutableList.of;
@@ -71,7 +71,7 @@ public class PersistAnalysisWarningsStepTest {
verify(ceTaskMessages, times(1)).addAll(argumentCaptor.capture());
assertThat(argumentCaptor.getValue())
.extracting(CeTaskMessages.Message::getText, CeTaskMessages.Message::getType)
.containsExactly(tuple("warning 1", CeTaskMessageType.GENERIC), tuple("warning 2", CeTaskMessageType.GENERIC));
.containsExactly(tuple("warning 1", MessageType.GENERIC), tuple("warning 2", MessageType.GENERIC));
}

@Test

+ 5
- 5
server/sonar-ce-task/src/main/java/org/sonar/ce/task/log/CeTaskMessages.java ファイルの表示

@@ -23,7 +23,7 @@ import java.util.Collection;
import java.util.Objects;
import javax.annotation.concurrent.Immutable;
import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.db.ce.CeTaskMessageType;
import org.sonar.db.dismissmessage.MessageType;

import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;
@@ -49,9 +49,9 @@ public interface CeTaskMessages {
class Message {
private final String text;
private final long timestamp;
private final CeTaskMessageType type;
private final MessageType type;

public Message(String text, long timestamp, CeTaskMessageType type) {
public Message(String text, long timestamp, MessageType type) {
requireNonNull(text, "Text can't be null");
checkArgument(!text.isEmpty(), "Text can't be empty");
checkArgument(timestamp >= 0, "Timestamp can't be less than 0");
@@ -61,7 +61,7 @@ public interface CeTaskMessages {
}

public Message(String text, long timestamp) {
this(text, timestamp, CeTaskMessageType.GENERIC);
this(text, timestamp, MessageType.GENERIC);
}

public String getText() {
@@ -72,7 +72,7 @@ public interface CeTaskMessages {
return timestamp;
}

public CeTaskMessageType getType() {
public MessageType getType() {
return type;
}


+ 2
- 1
server/sonar-db-dao/src/it/java/org/sonar/db/ce/CeActivityDaoIT.java ファイルの表示

@@ -47,6 +47,7 @@ import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.Pagination;
import org.sonar.db.component.BranchDto;
import org.sonar.db.dismissmessage.MessageType;
import org.sonar.db.project.ProjectDto;

import static java.util.Collections.emptyList;
@@ -153,7 +154,7 @@ public class CeActivityDaoIT {
.setUuid(UuidFactoryFast.getInstance().create())
.setTaskUuid(task.getUuid())
.setMessage("message_" + task.getUuid() + "_" + i)
.setType(CeTaskMessageType.GENERIC)
.setType(MessageType.GENERIC)
.setCreatedAt(task.getUuid().hashCode() + i);
}


+ 13
- 12
server/sonar-db-dao/src/it/java/org/sonar/db/ce/CeTaskMessageDaoIT.java ファイルの表示

@@ -27,6 +27,7 @@ import org.junit.Test;
import org.sonar.api.utils.System2;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.dismissmessage.MessageType;
import org.sonar.db.project.ProjectDto;
import org.sonar.db.user.UserDto;

@@ -44,7 +45,7 @@ public class CeTaskMessageDaoIT {
.setUuid("uuid_1")
.setTaskUuid("task_uuid_1")
.setMessage("message_1")
.setType(CeTaskMessageType.GENERIC)
.setType(MessageType.GENERIC)
.setCreatedAt(1_222_333L));
dbTester.getSession().commit();

@@ -52,9 +53,9 @@ public class CeTaskMessageDaoIT {
dbTester.select("select uuid as \"UUID\", task_uuid as \"TASK_UUID\", message as \"MESSAGE\", message_type as \"TYPE\", " +
"created_at as \"CREATED_AT\" from ce_task_message"))
.hasSize(1)
.extracting(t -> t.get("UUID"), t -> t.get("TASK_UUID"), t -> t.get("MESSAGE"), t -> CeTaskMessageType.valueOf((String) t.get("TYPE")),
.extracting(t -> t.get("UUID"), t -> t.get("TASK_UUID"), t -> t.get("MESSAGE"), t -> MessageType.valueOf((String) t.get("TYPE")),
t -> t.get("CREATED_AT"))
.containsOnly(Tuple.tuple("uuid_1", "task_uuid_1", "message_1", CeTaskMessageType.GENERIC, 1_222_333L));
.containsOnly(Tuple.tuple("uuid_1", "task_uuid_1", "message_1", MessageType.GENERIC, 1_222_333L));
}

@Test
@@ -78,13 +79,13 @@ public class CeTaskMessageDaoIT {
public void deleteByType_deletes_messages_of_given_type() {
String task1 = "task1";
CeTaskMessageDto[] messages = {
insertMessage(task1, 0, 1_222_333L, CeTaskMessageType.GENERIC),
insertMessage(task1, 1, 2_222_333L, CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE),
insertMessage(task1, 2, 1_111_333L, CeTaskMessageType.GENERIC),
insertMessage(task1, 3, 1_222_111L, CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE)
insertMessage(task1, 0, 1_222_333L, MessageType.GENERIC),
insertMessage(task1, 1, 2_222_333L, MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE),
insertMessage(task1, 2, 1_111_333L, MessageType.GENERIC),
insertMessage(task1, 3, 1_222_111L, MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE)
};

underTest.deleteByType(dbTester.getSession(), CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
underTest.deleteByType(dbTester.getSession(), MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);

assertThat(underTest.selectByUuid(dbTester.getSession(), messages[0].getUuid())).isPresent();
assertThat(underTest.selectByUuid(dbTester.getSession(), messages[1].getUuid())).isEmpty();
@@ -106,10 +107,10 @@ public class CeTaskMessageDaoIT {
public void selectNonDismissedByUserAndTask_returns_non_dismissed_messages() {
UserDto user = dbTester.users().insertUser();
ProjectDto project = dbTester.components().insertPrivateProject().getProjectDto();
dbTester.users().insertUserDismissedMessage(user, project, CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
dbTester.users().insertUserDismissedMessageOnProject(user, project, MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
String taskUuid = "17ae66e6-fe83-4c80-b704-4b04e9c5abe8";
CeTaskMessageDto msg1 = insertMessage(taskUuid, 1, 1_222_333L);
insertMessage(taskUuid, 2, 1_222_334L, CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
insertMessage(taskUuid, 2, 1_222_334L, MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
CeTaskMessageDto msg3 = insertMessage(taskUuid, 3, 1_222_335L);
List<CeTaskMessageDto> messages = underTest.selectNonDismissedByUserAndTask(dbTester.getSession(), taskUuid, user.getUuid());

@@ -118,10 +119,10 @@ public class CeTaskMessageDaoIT {
}

private CeTaskMessageDto insertMessage(String taskUuid, int i, long createdAt) {
return insertMessage(taskUuid, i, createdAt, CeTaskMessageType.GENERIC);
return insertMessage(taskUuid, i, createdAt, MessageType.GENERIC);
}

private CeTaskMessageDto insertMessage(String taskUuid, int i, long createdAt, CeTaskMessageType messageType) {
private CeTaskMessageDto insertMessage(String taskUuid, int i, long createdAt, MessageType messageType) {
CeTaskMessageDto res = new CeTaskMessageDto()
.setUuid("message_" + i)
.setTaskUuid(taskUuid)

+ 4
- 4
server/sonar-db-dao/src/it/java/org/sonar/db/purge/PurgeCommandsIT.java ファイルの表示

@@ -42,7 +42,7 @@ import org.sonar.api.issue.impact.SoftwareQuality;
import org.sonar.api.utils.System2;
import org.sonar.core.util.UuidFactoryFast;
import org.sonar.db.DbTester;
import org.sonar.db.ce.CeTaskMessageType;
import org.sonar.db.dismissmessage.MessageType;
import org.sonar.db.component.BranchDto;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentTesting;
@@ -702,9 +702,9 @@ public class PurgeCommandsIT {
UserDto user2 = dbTester.users().insertUser();
ProjectDto project = dbTester.components().insertPrivateProject().getProjectDto();
ProjectDto anotherProject = dbTester.components().insertPrivateProject().getProjectDto();
dbTester.users().insertUserDismissedMessage(user1, project, CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
dbTester.users().insertUserDismissedMessage(user2, project, CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
dbTester.users().insertUserDismissedMessage(user1, anotherProject, CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
dbTester.users().insertUserDismissedMessageOnProject(user1, project, MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
dbTester.users().insertUserDismissedMessageOnProject(user2, project, MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
dbTester.users().insertUserDismissedMessageOnProject(user1, anotherProject, MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
PurgeCommands purgeCommands = new PurgeCommands(dbTester.getSession(), profiler, system2);

purgeCommands.deleteUserDismissedMessages(project.getUuid());

+ 5
- 5
server/sonar-db-dao/src/it/java/org/sonar/db/purge/PurgeDaoIT.java ファイルの表示

@@ -62,7 +62,7 @@ import org.sonar.db.ce.CeQueueDto;
import org.sonar.db.ce.CeQueueDto.Status;
import org.sonar.db.ce.CeTaskCharacteristicDto;
import org.sonar.db.ce.CeTaskMessageDto;
import org.sonar.db.ce.CeTaskMessageType;
import org.sonar.db.dismissmessage.MessageType;
import org.sonar.db.ce.CeTaskTypes;
import org.sonar.db.component.BranchDto;
import org.sonar.db.component.BranchType;
@@ -910,9 +910,9 @@ public class PurgeDaoIT {
ProjectDto project = db.components().insertPrivateProject().getProjectDto();
ProjectDto anotherProject = db.components().insertPrivateProject().getProjectDto();

UserDismissedMessageDto msg1 = db.users().insertUserDismissedMessage(user1, project, CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
UserDismissedMessageDto msg2 = db.users().insertUserDismissedMessage(user2, project, CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
UserDismissedMessageDto msg3 = db.users().insertUserDismissedMessage(user1, anotherProject, CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
UserDismissedMessageDto msg1 = db.users().insertUserDismissedMessageOnProject(user1, project, MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
UserDismissedMessageDto msg2 = db.users().insertUserDismissedMessageOnProject(user2, project, MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
UserDismissedMessageDto msg3 = db.users().insertUserDismissedMessageOnProject(user1, anotherProject, MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);

assertThat(uuidsIn("user_dismissed_messages")).containsOnly(msg1.getUuid(), msg2.getUuid(), msg3.getUuid());

@@ -2002,7 +2002,7 @@ public class PurgeDaoIT {
.setUuid(UuidFactoryFast.getInstance().create())
.setTaskUuid(uuid)
.setMessage("key_" + uuid.hashCode() + i)
.setType(CeTaskMessageType.GENERIC)
.setType(MessageType.GENERIC)
.setCreatedAt(2_333_444L + i))
.forEach(dto -> dbClient.ceTaskMessageDao().insert(dbSession, dto));
dbSession.commit();

+ 39
- 26
server/sonar-db-dao/src/it/java/org/sonar/db/user/UserDismissedMessagesDaoIT.java ファイルの表示

@@ -26,12 +26,12 @@ import org.junit.Test;
import org.sonar.api.utils.System2;
import org.sonar.core.util.Uuids;
import org.sonar.db.DbTester;
import org.sonar.db.ce.CeTaskMessageType;
import org.sonar.db.dismissmessage.MessageType;
import org.sonar.db.project.ProjectDto;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
import static org.sonar.db.ce.CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE;
import static org.sonar.db.dismissmessage.MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE;

public class UserDismissedMessagesDaoIT {

@@ -48,13 +48,13 @@ public class UserDismissedMessagesDaoIT {

underTest.insert(db.getSession(), dto);

Optional<UserDismissedMessageDto> dtoFromDb = underTest.selectByUserAndProjectAndMessageType(db.getSession(), user, project, dto.getCeMessageType());
Optional<UserDismissedMessageDto> dtoFromDb = underTest.selectByUserAndProjectAndMessageType(db.getSession(), user.getUuid(), project, dto.getMessageType());
assertThat(dtoFromDb).isPresent();
assertThat(dtoFromDb.get().getUuid()).isEqualTo(dto.getUuid());
assertThat(dtoFromDb.get().getUserUuid()).isEqualTo(dto.getUserUuid());
assertThat(dtoFromDb.get().getProjectUuid()).isEqualTo(dto.getProjectUuid());
assertThat(dtoFromDb.get().getCeMessageType()).isEqualTo(dto.getCeMessageType());
assertThat(dtoFromDb.get().getCeMessageType().isDismissible()).isEqualTo(dto.getCeMessageType().isDismissible());
assertThat(dtoFromDb.get().getMessageType()).isEqualTo(dto.getMessageType());
assertThat(dtoFromDb.get().getMessageType().isDismissible()).isEqualTo(dto.getMessageType().isDismissible());
assertThat(dtoFromDb.get().getCreatedAt()).isEqualTo(dto.getCreatedAt());
}

@@ -62,23 +62,36 @@ public class UserDismissedMessagesDaoIT {
public void selectByUserAndProjectAndMessageType_returns_object_if_record_found() {
UserDto user = db.users().insertUser();
ProjectDto project = db.components().insertPrivateProject().getProjectDto();
db.users().insertUserDismissedMessage(user, project, CeTaskMessageType.GENERIC);
db.users().insertUserDismissedMessageOnProject(user, project, MessageType.GENERIC);

Optional<UserDismissedMessageDto> result = underTest.selectByUserAndProjectAndMessageType(db.getSession(), user, project, CeTaskMessageType.GENERIC);
Optional<UserDismissedMessageDto> result = underTest.selectByUserAndProjectAndMessageType(db.getSession(), user.getUuid(), project, MessageType.GENERIC);

assertThat(result).isPresent();
assertThat(result.get().getUserUuid()).isEqualTo(user.getUuid());
assertThat(result.get().getProjectUuid()).isEqualTo(project.getUuid());
assertThat(result.get().getCeMessageType()).isEqualTo(CeTaskMessageType.GENERIC);
assertThat(result.get().getMessageType()).isEqualTo(MessageType.GENERIC);
}

@Test
public void selectByUserAndMessageType_returns_object_if_record_found() {
UserDto user = db.users().insertUser();
db.users().insertUserDismissedMessageOnInstance(user, MessageType.GENERIC);

Optional<UserDismissedMessageDto> result = underTest.selectByUserUuidAndMessageType(db.getSession(), user.getUuid(),MessageType.GENERIC);

assertThat(result).isPresent();
assertThat(result.get().getUserUuid()).isEqualTo(user.getUuid());
assertThat(result.get().getProjectUuid()).isNull();
assertThat(result.get().getMessageType()).isEqualTo(MessageType.GENERIC);
}

@Test
public void selectByUserAndProjectAndMessageType_returns_absent_if_no_record_found() {
UserDto user = db.users().insertUser();
ProjectDto project = db.components().insertPrivateProject().getProjectDto();
db.users().insertUserDismissedMessage(user, project, CeTaskMessageType.GENERIC);
db.users().insertUserDismissedMessageOnProject(user, project, MessageType.GENERIC);

Optional<UserDismissedMessageDto> result = underTest.selectByUserAndProjectAndMessageType(db.getSession(), user, project, SUGGEST_DEVELOPER_EDITION_UPGRADE);
Optional<UserDismissedMessageDto> result = underTest.selectByUserAndProjectAndMessageType(db.getSession(), user.getUuid(), project, SUGGEST_DEVELOPER_EDITION_UPGRADE);

assertThat(result).isNotPresent();
}
@@ -89,19 +102,19 @@ public class UserDismissedMessagesDaoIT {
UserDto user2 = db.users().insertUser();
ProjectDto project1 = db.components().insertPrivateProject().getProjectDto();
ProjectDto project2 = db.components().insertPrivateProject().getProjectDto();
db.users().insertUserDismissedMessage(user1, project1, CeTaskMessageType.GENERIC);
db.users().insertUserDismissedMessage(user1, project2, CeTaskMessageType.GENERIC);
UserDismissedMessageDto dto1 = db.users().insertUserDismissedMessage(user2, project1, CeTaskMessageType.GENERIC);
UserDismissedMessageDto dto2 = db.users().insertUserDismissedMessage(user2, project2, CeTaskMessageType.GENERIC);
db.users().insertUserDismissedMessageOnProject(user1, project1, MessageType.GENERIC);
db.users().insertUserDismissedMessageOnProject(user1, project2, MessageType.GENERIC);
UserDismissedMessageDto dto1 = db.users().insertUserDismissedMessageOnProject(user2, project1, MessageType.GENERIC);
UserDismissedMessageDto dto2 = db.users().insertUserDismissedMessageOnProject(user2, project2, MessageType.GENERIC);

List<UserDismissedMessageDto> result = underTest.selectByUser(db.getSession(), user2);

assertThat(result).hasSize(2);
assertThat(result).extracting(UserDismissedMessageDto::getUuid, UserDismissedMessageDto::getUserUuid, UserDismissedMessageDto::getProjectUuid,
UserDismissedMessageDto::getCeMessageType)
UserDismissedMessageDto::getMessageType)
.containsExactlyInAnyOrder(
tuple(dto1.getUuid(), user2.getUuid(), project1.getUuid(), CeTaskMessageType.GENERIC),
tuple(dto2.getUuid(), user2.getUuid(), project2.getUuid(), CeTaskMessageType.GENERIC));
tuple(dto1.getUuid(), user2.getUuid(), project1.getUuid(), MessageType.GENERIC),
tuple(dto2.getUuid(), user2.getUuid(), project2.getUuid(), MessageType.GENERIC));
}

@Test
@@ -110,10 +123,10 @@ public class UserDismissedMessagesDaoIT {
UserDto user2 = db.users().insertUser();
ProjectDto project1 = db.components().insertPrivateProject().getProjectDto();
ProjectDto project2 = db.components().insertPrivateProject().getProjectDto();
db.users().insertUserDismissedMessage(user1, project1, CeTaskMessageType.GENERIC);
db.users().insertUserDismissedMessage(user1, project2, CeTaskMessageType.GENERIC);
db.users().insertUserDismissedMessage(user2, project1, CeTaskMessageType.GENERIC);
db.users().insertUserDismissedMessage(user2, project2, CeTaskMessageType.GENERIC);
db.users().insertUserDismissedMessageOnProject(user1, project1, MessageType.GENERIC);
db.users().insertUserDismissedMessageOnProject(user1, project2, MessageType.GENERIC);
db.users().insertUserDismissedMessageOnProject(user2, project1, MessageType.GENERIC);
db.users().insertUserDismissedMessageOnProject(user2, project2, MessageType.GENERIC);

underTest.deleteByUser(db.getSession(), user2);

@@ -127,10 +140,10 @@ public class UserDismissedMessagesDaoIT {
UserDto user2 = db.users().insertUser();
ProjectDto project1 = db.components().insertPrivateProject().getProjectDto();
ProjectDto project2 = db.components().insertPrivateProject().getProjectDto();
UserDismissedMessageDto dto1 = db.users().insertUserDismissedMessage(user1, project1, CeTaskMessageType.GENERIC);
db.users().insertUserDismissedMessage(user1, project2, SUGGEST_DEVELOPER_EDITION_UPGRADE);
db.users().insertUserDismissedMessage(user2, project1, SUGGEST_DEVELOPER_EDITION_UPGRADE);
UserDismissedMessageDto dto2 = db.users().insertUserDismissedMessage(user2, project2, CeTaskMessageType.GENERIC);
UserDismissedMessageDto dto1 = db.users().insertUserDismissedMessageOnProject(user1, project1, MessageType.GENERIC);
db.users().insertUserDismissedMessageOnProject(user1, project2, SUGGEST_DEVELOPER_EDITION_UPGRADE);
db.users().insertUserDismissedMessageOnProject(user2, project1, SUGGEST_DEVELOPER_EDITION_UPGRADE);
UserDismissedMessageDto dto2 = db.users().insertUserDismissedMessageOnProject(user2, project2, MessageType.GENERIC);

underTest.deleteByType(db.getSession(), SUGGEST_DEVELOPER_EDITION_UPGRADE);

@@ -145,7 +158,7 @@ public class UserDismissedMessagesDaoIT {
public static UserDismissedMessageDto newDto(ProjectDto project, UserDto user) {
return new UserDismissedMessageDto()
.setUuid(Uuids.createFast())
.setCeMessageType(CeTaskMessageType.GENERIC)
.setMessageType(MessageType.GENERIC)
.setUserUuid(user.getUuid())
.setProjectUuid(project.getUuid());
}

+ 2
- 1
server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeTaskMessageDao.java ファイルの表示

@@ -23,6 +23,7 @@ import java.util.List;
import java.util.Optional;
import org.sonar.db.Dao;
import org.sonar.db.DbSession;
import org.sonar.db.dismissmessage.MessageType;

public class CeTaskMessageDao implements Dao {
public void insert(DbSession dbSession, CeTaskMessageDto dto) {
@@ -41,7 +42,7 @@ public class CeTaskMessageDao implements Dao {
return getMapper(dbSession).selectNonDismissedByUserAndTask(taskUuid, userUuid);
}

public void deleteByType(DbSession session, CeTaskMessageType type) {
public void deleteByType(DbSession session, MessageType type) {
getMapper(session).deleteByType(type.name());
}


+ 10
- 3
server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeTaskMessageDto.java ファイルの表示

@@ -20,6 +20,7 @@
package org.sonar.db.ce;

import com.google.common.annotations.VisibleForTesting;
import org.sonar.db.dismissmessage.MessageType;

import static com.google.common.base.Preconditions.checkArgument;
import static org.apache.commons.lang.StringUtils.abbreviate;
@@ -35,19 +36,25 @@ public class CeTaskMessageDto {
* UUID of the task the message belongs to. Not null
*/
private String taskUuid;

/**
* The text of the message. Not null
*/
private String message;

/**
* Type of the message
*/
private CeTaskMessageType type;
private MessageType type;
/**
* Timestamp the message was created. Not null
*/
private long createdAt;

public CeTaskMessageDto() {
//Nothing to do
}

public String getUuid() {
return uuid;
}
@@ -76,11 +83,11 @@ public class CeTaskMessageDto {
return this;
}

public CeTaskMessageType getType() {
public MessageType getType() {
return type;
}

public CeTaskMessageDto setType(CeTaskMessageType type) {
public CeTaskMessageDto setType(MessageType type) {
this.type = type;
return this;
}

server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeTaskMessageType.java → server/sonar-db-dao/src/main/java/org/sonar/db/dismissmessage/MessageType.java ファイルの表示

@@ -17,17 +17,22 @@
* 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.db.ce;
package org.sonar.db.dismissmessage;

public enum CeTaskMessageType {
public enum MessageType {
INFO(false, false),
GENERIC(false, true),
SUGGEST_DEVELOPER_EDITION_UPGRADE(true, true);
SUGGEST_DEVELOPER_EDITION_UPGRADE(true, true),
GLOBAL_NCD_90(true, false),
GLOBAL_NCD_PAGE_90(true, false),
PROJECT_NCD_90(true, false),
PROJECT_NCD_PAGE_90(true, false),
BRANCH_NCD_90(true, false);

private final boolean dismissible;
private final boolean isWarning;

CeTaskMessageType(boolean dismissible, boolean isWarning) {
MessageType(boolean dismissible, boolean isWarning) {
this.dismissible = dismissible;
this.isWarning = isWarning;
}

+ 10
- 7
server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDismissedMessageDto.java ファイルの表示

@@ -19,7 +19,9 @@
*/
package org.sonar.db.user;

import org.sonar.db.ce.CeTaskMessageType;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.db.dismissmessage.MessageType;

public class UserDismissedMessageDto {

@@ -31,11 +33,12 @@ public class UserDismissedMessageDto {
/**
* Uuid of the project for which the message type was dismissed
*/
@CheckForNull
private String projectUuid;
/**
* Message type of the dismissed message
*/
private CeTaskMessageType ceMessageType;
private MessageType messageType;
/**
* Technical creation date
*/
@@ -67,17 +70,17 @@ public class UserDismissedMessageDto {
return projectUuid;
}

public UserDismissedMessageDto setProjectUuid(String projectUuid) {
public UserDismissedMessageDto setProjectUuid(@Nullable String projectUuid) {
this.projectUuid = projectUuid;
return this;
}

public CeTaskMessageType getCeMessageType() {
return ceMessageType;
public MessageType getMessageType() {
return messageType;
}

public UserDismissedMessageDto setCeMessageType(CeTaskMessageType ceMessageType) {
this.ceMessageType = ceMessageType;
public UserDismissedMessageDto setMessageType(MessageType messageType) {
this.messageType = messageType;
return this;
}


+ 10
- 5
server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDismissedMessagesDao.java ファイルの表示

@@ -24,7 +24,7 @@ import java.util.Optional;
import org.sonar.api.utils.System2;
import org.sonar.db.Dao;
import org.sonar.db.DbSession;
import org.sonar.db.ce.CeTaskMessageType;
import org.sonar.db.dismissmessage.MessageType;
import org.sonar.db.project.ProjectDto;

public class UserDismissedMessagesDao implements Dao {
@@ -40,9 +40,14 @@ public class UserDismissedMessagesDao implements Dao {
return dto;
}

public Optional<UserDismissedMessageDto> selectByUserAndProjectAndMessageType(DbSession session, UserDto user, ProjectDto project,
CeTaskMessageType ceMessageType) {
return mapper(session).selectByUserUuidAndProjectUuidAndMessageType(user.getUuid(), project.getUuid(), ceMessageType.name());
public Optional<UserDismissedMessageDto> selectByUserAndProjectAndMessageType(DbSession session, String userUuid, ProjectDto project,
MessageType messageType) {
return mapper(session).selectByUserUuidAndProjectUuidAndMessageType(userUuid, project.getUuid(), messageType.name());
}

public Optional<UserDismissedMessageDto> selectByUserUuidAndMessageType(DbSession session, String userUuid,
MessageType messageType) {
return mapper(session).selectByUserUuidAndMessageType(userUuid, messageType.name());
}

public List<UserDismissedMessageDto> selectByUser(DbSession session, UserDto user) {
@@ -53,7 +58,7 @@ public class UserDismissedMessagesDao implements Dao {
mapper(session).deleteByUserUuid(user.getUuid());
}

public void deleteByType(DbSession session, CeTaskMessageType type) {
public void deleteByType(DbSession session, MessageType type) {
mapper(session).deleteByType(type.name());
}


+ 4
- 2
server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDismissedMessagesMapper.java ファイルの表示

@@ -27,11 +27,13 @@ public interface UserDismissedMessagesMapper {
void insert(@Param("dto") UserDismissedMessageDto dto);

Optional<UserDismissedMessageDto> selectByUserUuidAndProjectUuidAndMessageType(@Param("userUuid") String userUuid, @Param("projectUuid") String projectUuid,
@Param("ceMessageType") String ceMessageType);
@Param("messageType") String messageType);

Optional<UserDismissedMessageDto> selectByUserUuidAndMessageType(@Param("userUuid") String userUuid, @Param("messageType") String messageType);

List<UserDismissedMessageDto> selectByUserUuid(@Param("userUuid") String userUuid);

void deleteByUserUuid(@Param("userUuid") String userUuid);

void deleteByType(@Param("ceMessageType") String ceMessageType);
void deleteByType(@Param("messageType") String messageType);
}

+ 15
- 5
server/sonar-db-dao/src/main/resources/org/sonar/db/user/UserDismissedMessagesMapper.xml ファイルの表示

@@ -7,7 +7,7 @@
udm.uuid,
udm.user_uuid as userUuid,
udm.project_uuid as projectUuid,
udm.message_type as ceMessageType,
udm.message_type as messageType,
udm.created_at as createdAt
</sql>

@@ -24,7 +24,7 @@
#{dto.uuid,jdbcType=VARCHAR},
#{dto.userUuid,jdbcType=VARCHAR},
#{dto.projectUuid,jdbcType=VARCHAR},
#{dto.ceMessageType,jdbcType=VARCHAR},
#{dto.messageType,jdbcType=VARCHAR},
#{dto.createdAt,jdbcType=BIGINT}
)
</insert>
@@ -37,10 +37,20 @@
where
udm.user_uuid=#{userUuid,jdbcType=VARCHAR} and
udm.project_uuid=#{projectUuid,jdbcType=VARCHAR} and
udm.message_type=#{ceMessageType,jdbcType=VARCHAR}
udm.message_type=#{messageType,jdbcType=VARCHAR}
</select>

<select id="selectByUserUuid" resultType="org.sonar.db.user.UserDismissedMessageDto" parameterType="String">
<select id="selectByUserUuidAndMessageType" resultType="org.sonar.db.user.UserDismissedMessageDto">
select
<include refid="columns"/>
from
user_dismissed_messages udm
where
udm.user_uuid=#{userUuid,jdbcType=VARCHAR} and
udm.message_type=#{messageType,jdbcType=VARCHAR}
</select>

<select id="selectByUserUuid" resultType="org.sonar.db.user.UserDismissedMessageDto" parameterType="String">
select
<include refid="columns"/>
from
@@ -54,7 +64,7 @@
</delete>

<delete id="deleteByType" parameterType="String">
delete from user_dismissed_messages where message_type = #{ceMessageType, jdbcType=VARCHAR}
delete from user_dismissed_messages where message_type = #{messageType, jdbcType=VARCHAR}
</delete>

</mapper>

+ 13
- 3
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/user/UserDbTester.java ファイルの表示

@@ -32,7 +32,7 @@ import org.sonar.api.web.UserRole;
import org.sonar.core.util.Uuids;
import org.sonar.db.DbClient;
import org.sonar.db.DbTester;
import org.sonar.db.ce.CeTaskMessageType;
import org.sonar.db.dismissmessage.MessageType;
import org.sonar.db.component.BranchDto;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.entity.EntityDto;
@@ -489,12 +489,22 @@ public class UserDbTester {
return dto;
}

public final UserDismissedMessageDto insertUserDismissedMessage(UserDto userDto, ProjectDto projectDto, CeTaskMessageType messageType) {
public final UserDismissedMessageDto insertUserDismissedMessageOnProject(UserDto userDto, ProjectDto projectDto, MessageType messageType) {
UserDismissedMessageDto dto = new UserDismissedMessageDto()
.setUuid(Uuids.create())
.setUserUuid(userDto.getUuid())
.setProjectUuid(projectDto.getUuid())
.setCeMessageType(messageType);
.setMessageType(messageType);
db.getDbClient().userDismissedMessagesDao().insert(db.getSession(), dto);
db.commit();
return dto;
}

public final UserDismissedMessageDto insertUserDismissedMessageOnInstance(UserDto userDto, MessageType messageType) {
UserDismissedMessageDto dto = new UserDismissedMessageDto()
.setUuid(Uuids.create())
.setUserUuid(userDto.getUuid())
.setMessageType(messageType);
db.getDbClient().userDismissedMessagesDao().insert(db.getSession(), dto);
db.commit();
return dto;

+ 5
- 5
server/sonar-webserver-common/src/it/java/org/sonar/server/common/user/service/UserServiceIT.java ファイルの表示

@@ -38,7 +38,7 @@ import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.alm.setting.AlmSettingDto;
import org.sonar.db.audit.NoOpAuditPersister;
import org.sonar.db.ce.CeTaskMessageType;
import org.sonar.db.dismissmessage.MessageType;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.permission.GlobalPermission;
import org.sonar.db.permission.template.PermissionTemplateDto;
@@ -617,11 +617,11 @@ public class UserServiceIT {
ProjectDto project2 = db.components().insertPrivateProject().getProjectDto();
UserDto user = db.users().insertUser();

db.users().insertUserDismissedMessage(user, project1, CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
db.users().insertUserDismissedMessage(user, project2, CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
db.users().insertUserDismissedMessageOnProject(user, project1, MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
db.users().insertUserDismissedMessageOnProject(user, project2, MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
UserDto anotherUser = db.users().insertUser();
UserDismissedMessageDto msg3 = db.users().insertUserDismissedMessage(anotherUser, project1, CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
UserDismissedMessageDto msg4 = db.users().insertUserDismissedMessage(anotherUser, project2, CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
UserDismissedMessageDto msg3 = db.users().insertUserDismissedMessageOnProject(anotherUser, project1, MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
UserDismissedMessageDto msg4 = db.users().insertUserDismissedMessageOnProject(anotherUser, project2, MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);

userService.deactivate(user.getLogin(), false);


+ 14
- 14
server/sonar-webserver-core/src/it/java/org/sonar/server/startup/UpgradeSuggestionsCleanerIT.java ファイルの表示

@@ -34,7 +34,7 @@ import org.sonar.db.DbTester;
import org.sonar.db.ce.CeActivityDto;
import org.sonar.db.ce.CeQueueDto;
import org.sonar.db.ce.CeTaskMessageDto;
import org.sonar.db.ce.CeTaskMessageType;
import org.sonar.db.dismissmessage.MessageType;
import org.sonar.db.user.UserDismissedMessageDto;
import org.sonar.db.user.UserDto;

@@ -83,11 +83,11 @@ public class UpgradeSuggestionsCleanerIT {
public void start_cleans_up_obsolete_upgrade_suggestions(SonarEdition edition) {
when(sonarRuntime.getEdition()).thenReturn(edition);
insertTask(TASK_UUID);
insertCeTaskMessage("ctm1", CeTaskMessageType.GENERIC, "msg1");
insertCeTaskMessage("ctm2", CeTaskMessageType.GENERIC, "msg2");
insertCeTaskMessage("ctm3", CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE, "upgrade-msg-1");
insertInUserDismissedMessages("u1", CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
insertInUserDismissedMessages("u2", CeTaskMessageType.GENERIC);
insertCeTaskMessage("ctm1", MessageType.GENERIC, "msg1");
insertCeTaskMessage("ctm2", MessageType.GENERIC, "msg2");
insertCeTaskMessage("ctm3", MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE, "upgrade-msg-1");
insertInUserDismissedMessages("u1", MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
insertInUserDismissedMessages("u2", MessageType.GENERIC);

underTest.start();
underTest.stop();
@@ -104,11 +104,11 @@ public class UpgradeSuggestionsCleanerIT {
public void start_does_nothing_in_community_edition() {
when(sonarRuntime.getEdition()).thenReturn(SonarEdition.COMMUNITY);
insertTask(TASK_UUID);
insertCeTaskMessage("ctm1", CeTaskMessageType.GENERIC, "msg1");
insertCeTaskMessage("ctm2", CeTaskMessageType.GENERIC, "msg2");
insertCeTaskMessage("ctm3", CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE, "upgrade-msg-1");
insertInUserDismissedMessages("u1", CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
insertInUserDismissedMessages("u2", CeTaskMessageType.GENERIC);
insertCeTaskMessage("ctm1", MessageType.GENERIC, "msg1");
insertCeTaskMessage("ctm2", MessageType.GENERIC, "msg2");
insertCeTaskMessage("ctm3", MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE, "upgrade-msg-1");
insertInUserDismissedMessages("u1", MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
insertInUserDismissedMessages("u2", MessageType.GENERIC);

underTest.start();

@@ -140,7 +140,7 @@ public class UpgradeSuggestionsCleanerIT {
new CeActivityDto(new CeQueueDto().setUuid(taskUuid).setTaskType("ISSUE_SYNC")).setStatus(CeActivityDto.Status.FAILED));
}

private void insertCeTaskMessage(String uuid, CeTaskMessageType messageType, String msg) {
private void insertCeTaskMessage(String uuid, MessageType messageType, String msg) {
CeTaskMessageDto dto = new CeTaskMessageDto()
.setUuid(uuid)
.setMessage(msg)
@@ -150,12 +150,12 @@ public class UpgradeSuggestionsCleanerIT {
dbTester.getSession().commit();
}

private void insertInUserDismissedMessages(String uuid, CeTaskMessageType messageType) {
private void insertInUserDismissedMessages(String uuid, MessageType messageType) {
UserDismissedMessageDto dto = new UserDismissedMessageDto()
.setUuid(uuid)
.setUserUuid(user.getUuid())
.setProjectUuid("PROJECT_1")
.setCeMessageType(messageType);
.setMessageType(messageType);
dbTester.getDbClient().userDismissedMessagesDao().insert(dbTester.getSession(), dto);
dbTester.getSession().commit();
}

+ 3
- 3
server/sonar-webserver-core/src/main/java/org/sonar/server/startup/UpgradeSuggestionsCleaner.java ファイルの表示

@@ -27,7 +27,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.ce.CeTaskMessageType;
import org.sonar.db.dismissmessage.MessageType;

/**
* Clean up messages (like removing upgrade suggestions after an edition upgrade)
@@ -57,8 +57,8 @@ public class UpgradeSuggestionsCleaner implements Startable {
private void deleteUpgradeMessageDismissals() {
LOGGER.info("Dismissed messages cleanup");
try (DbSession dbSession = dbClient.openSession(false)) {
dbClient.userDismissedMessagesDao().deleteByType(dbSession, CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
dbClient.ceTaskMessageDao().deleteByType(dbSession, CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
dbClient.userDismissedMessagesDao().deleteByType(dbSession, MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
dbClient.ceTaskMessageDao().deleteByType(dbSession, MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
dbSession.commit();
}
}

+ 2
- 2
server/sonar-webserver-webapi/src/it/java/org/sonar/server/ce/ws/ActivityActionIT.java ファイルの表示

@@ -37,7 +37,7 @@ import org.sonar.db.ce.CeActivityDto.Status;
import org.sonar.db.ce.CeQueueDto;
import org.sonar.db.ce.CeTaskCharacteristicDto;
import org.sonar.db.ce.CeTaskMessageDto;
import org.sonar.db.ce.CeTaskMessageType;
import org.sonar.db.dismissmessage.MessageType;
import org.sonar.db.ce.CeTaskTypes;
import org.sonar.db.component.BranchType;
import org.sonar.db.component.ComponentDto;
@@ -268,7 +268,7 @@ public class ActivityActionIT {
.setUuid("uuid_" + taskUuid + "_" + i)
.setTaskUuid(taskUuid)
.setMessage("m_" + taskUuid + "_" + i)
.setType(CeTaskMessageType.GENERIC)
.setType(MessageType.GENERIC)
.setCreatedAt(taskUuid.hashCode() + i))
.toList();


+ 6
- 6
server/sonar-webserver-webapi/src/it/java/org/sonar/server/ce/ws/AnalysisStatusActionIT.java ファイルの表示

@@ -29,7 +29,7 @@ import org.sonar.db.DbTester;
import org.sonar.db.ce.CeActivityDto;
import org.sonar.db.ce.CeQueueDto;
import org.sonar.db.ce.CeTaskMessageDto;
import org.sonar.db.ce.CeTaskMessageType;
import org.sonar.db.dismissmessage.MessageType;
import org.sonar.db.component.BranchDto;
import org.sonar.db.component.BranchType;
import org.sonar.db.component.ProjectData;
@@ -93,7 +93,7 @@ public class AnalysisStatusActionIT {
SnapshotDto analysis = db.components().insertSnapshot(project);
CeActivityDto activity = insertActivity("task-uuid" + counter++, projectData.getMainBranchDto(), SUCCESS, analysis, REPORT);
createTaskMessage(activity, WARNING_IN_MAIN);
createTaskMessage(activity, "Dismissible warning", CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
createTaskMessage(activity, "Dismissible warning", MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);

Ce.AnalysisStatusWsResponse response = ws.newRequest()
.setParam(PARAM_COMPONENT, project.getKey())
@@ -111,7 +111,7 @@ public class AnalysisStatusActionIT {
SnapshotDto analysis = db.components().insertSnapshot(project);
CeActivityDto activity = insertActivity("task-uuid" + counter++, projectData.getMainBranchDto(), SUCCESS, analysis, REPORT);
CeTaskMessageDto taskMessage = createTaskMessage(activity, WARNING_IN_MAIN);
CeTaskMessageDto taskMessageDismissible = createTaskMessage(activity, "Dismissible warning", CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
CeTaskMessageDto taskMessageDismissible = createTaskMessage(activity, "Dismissible warning", MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);

Ce.AnalysisStatusWsResponse response = ws.newRequest()
.setParam(PARAM_COMPONENT, project.getKey())
@@ -307,7 +307,7 @@ public class AnalysisStatusActionIT {
.setUuid("AU-Tpxb--iU5OvuD2FLy")
.setTaskUuid(activity.getUuid())
.setMessage("Property \"sonar.jacoco.reportPaths\" is no longer supported. Use JaCoCo xml report and sonar-jacoco plugin.")
.setType(CeTaskMessageType.GENERIC)
.setType(MessageType.GENERIC)
.setCreatedAt(counter);
db.getDbClient().ceTaskMessageDao().insert(db.getSession(), ceTaskMessage);
db.commit();
@@ -348,10 +348,10 @@ public class AnalysisStatusActionIT {
}

private CeTaskMessageDto createTaskMessage(CeActivityDto activity, String warning) {
return createTaskMessage(activity, warning, CeTaskMessageType.GENERIC);
return createTaskMessage(activity, warning, MessageType.GENERIC);
}

private CeTaskMessageDto createTaskMessage(CeActivityDto activity, String warning, CeTaskMessageType messageType) {
private CeTaskMessageDto createTaskMessage(CeActivityDto activity, String warning, MessageType messageType) {
CeTaskMessageDto ceTaskMessageDto = new CeTaskMessageDto()
.setUuid("m-uuid-" + counter++)
.setTaskUuid(activity.getUuid())

+ 2
- 2
server/sonar-webserver-webapi/src/it/java/org/sonar/server/ce/ws/ComponentActionIT.java ファイルの表示

@@ -33,7 +33,7 @@ import org.sonar.db.ce.CeActivityDto;
import org.sonar.db.ce.CeQueueDto;
import org.sonar.db.ce.CeTaskCharacteristicDto;
import org.sonar.db.ce.CeTaskMessageDto;
import org.sonar.db.ce.CeTaskMessageType;
import org.sonar.db.dismissmessage.MessageType;
import org.sonar.db.ce.CeTaskTypes;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ProjectData;
@@ -259,7 +259,7 @@ public class ComponentActionIT {
.setUuid("uuid_" + i)
.setTaskUuid(activity.getUuid())
.setMessage("m_" + i)
.setType(CeTaskMessageType.GENERIC)
.setType(MessageType.GENERIC)
.setCreatedAt(i))
.toList();


+ 20
- 12
server/sonar-webserver-webapi/src/it/java/org/sonar/server/ce/ws/DismissAnalysisWarningActionIT.java ファイルの表示

@@ -29,7 +29,7 @@ import org.sonar.db.DbTester;
import org.sonar.db.ce.CeActivityDto;
import org.sonar.db.ce.CeQueueDto;
import org.sonar.db.ce.CeTaskMessageDto;
import org.sonar.db.ce.CeTaskMessageType;
import org.sonar.db.dismissmessage.MessageType;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ProjectData;
import org.sonar.db.component.SnapshotDto;
@@ -46,8 +46,8 @@ import org.sonar.server.ws.WsActionTester;

import static java.lang.String.format;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.tuple;
import static org.junit.Assert.assertThrows;
import static org.sonar.db.ce.CeActivityDto.Status.SUCCESS;
import static org.sonar.db.ce.CeTaskTypes.REPORT;

@@ -80,7 +80,9 @@ public class DismissAnalysisWarningActionIT {
.setParam("component", "6653f062-7c03-4b55-bcd2-0dac67640c4d")
.setParam("warning", "55c40b35-4145-4b78-bdf2-dfb242c25f15");

assertThrows("Authentication is required", UnauthorizedException.class, request::execute);
assertThatThrownBy(request::execute)
.isInstanceOf(UnauthorizedException.class)
.hasMessage("Authentication is required");
}

@Test
@@ -93,7 +95,9 @@ public class DismissAnalysisWarningActionIT {
.setParam("component", project.getKee())
.setParam("warning", "55c40b35-4145-4b78-bdf2-dfb242c25f15");

assertThrows("Insufficient privileges", ForbiddenException.class, request::execute);
assertThatThrownBy(request::execute)
.isInstanceOf(ForbiddenException.class)
.hasMessage("Insufficient privileges");
}

@Test
@@ -103,7 +107,7 @@ public class DismissAnalysisWarningActionIT {
userSession.logIn(user).addProjectPermission(UserRole.USER, project.getProjectDto());
SnapshotDto analysis = db.components().insertSnapshot(project.getMainBranchComponent());
CeActivityDto activity = insertActivity("task-uuid" + counter++, project.getMainBranchComponent(), SUCCESS, analysis, REPORT);
CeTaskMessageDto taskMessageDismissible = createTaskMessage(activity, "dismissable warning", CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
CeTaskMessageDto taskMessageDismissible = createTaskMessage(activity, "dismissable warning", MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);

TestResponse response = underTest.newRequest()
.setParam("component", project.projectKey())
@@ -113,7 +117,7 @@ public class DismissAnalysisWarningActionIT {
assertThat(response.getStatus()).isEqualTo(204);
assertThat(db.select("select * from user_dismissed_messages"))
.extracting("USER_UUID", "PROJECT_UUID", "MESSAGE_TYPE")
.containsExactly(tuple(userSession.getUuid(), project.projectUuid(), CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE.name()));
.containsExactly(tuple(userSession.getUuid(), project.projectUuid(), MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE.name()));
}

@Test
@@ -123,7 +127,7 @@ public class DismissAnalysisWarningActionIT {
userSession.logIn(user).addProjectPermission(UserRole.USER, project.getProjectDto());
SnapshotDto analysis = db.components().insertSnapshot(project.getMainBranchComponent());
CeActivityDto activity = insertActivity("task-uuid" + counter++, project.getMainBranchComponent(), SUCCESS, analysis, REPORT);
CeTaskMessageDto taskMessageDismissible = createTaskMessage(activity, "dismissable warning", CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
CeTaskMessageDto taskMessageDismissible = createTaskMessage(activity, "dismissable warning", MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);

underTest.newRequest()
.setParam("component", project.projectKey())
@@ -137,7 +141,7 @@ public class DismissAnalysisWarningActionIT {
assertThat(response.getStatus()).isEqualTo(204);
assertThat(db.select("select * from user_dismissed_messages"))
.extracting("USER_UUID", "PROJECT_UUID", "MESSAGE_TYPE")
.containsExactly(tuple(userSession.getUuid(), project.projectUuid(), CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE.name()));
.containsExactly(tuple(userSession.getUuid(), project.projectUuid(), MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE.name()));
}

@Test
@@ -153,7 +157,9 @@ public class DismissAnalysisWarningActionIT {
.setParam("component", project.projectKey())
.setParam("warning", taskMessage.getUuid());

assertThrows(format("Message '%s' cannot be dismissed.", taskMessage.getUuid()), IllegalArgumentException.class, request::execute);
assertThatThrownBy(request::execute)
.isInstanceOf(IllegalArgumentException.class)
.hasMessage(format("Message '%s' cannot be dismissed.", taskMessage.getUuid()));
assertThat(db.countRowsOfTable("USER_DISMISSED_MESSAGES")).isZero();
}

@@ -170,15 +176,17 @@ public class DismissAnalysisWarningActionIT {
.setParam("component", project.projectKey())
.setParam("warning", warningUuid);

assertThrows(format("Message '%s' not found", warningUuid), NotFoundException.class, request::execute);
assertThatThrownBy(request::execute)
.isInstanceOf(NotFoundException.class)
.hasMessage(format("Message '%s' not found.", warningUuid));
assertThat(db.countRowsOfTable("USER_DISMISSED_MESSAGES")).isZero();
}

private CeTaskMessageDto createTaskMessage(CeActivityDto activity, String warning) {
return createTaskMessage(activity, warning, CeTaskMessageType.GENERIC);
return createTaskMessage(activity, warning, MessageType.GENERIC);
}

private CeTaskMessageDto createTaskMessage(CeActivityDto activity, String warning, CeTaskMessageType messageType) {
private CeTaskMessageDto createTaskMessage(CeActivityDto activity, String warning, MessageType messageType) {
CeTaskMessageDto ceTaskMessageDto = new CeTaskMessageDto()
.setUuid("m-uuid-" + counter++)
.setTaskUuid(activity.getUuid())

+ 7
- 7
server/sonar-webserver-webapi/src/it/java/org/sonar/server/ce/ws/TaskActionIT.java ファイルの表示

@@ -36,7 +36,7 @@ import org.sonar.db.ce.CeActivityDto;
import org.sonar.db.ce.CeQueueDto;
import org.sonar.db.ce.CeTaskCharacteristicDto;
import org.sonar.db.ce.CeTaskMessageDto;
import org.sonar.db.ce.CeTaskMessageType;
import org.sonar.db.dismissmessage.MessageType;
import org.sonar.db.ce.CeTaskTypes;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ProjectData;
@@ -129,7 +129,7 @@ public class TaskActionIT {
.setUuid("u_" + i)
.setTaskUuid(queueDto.getUuid())
.setMessage("m_" + i)
.setType(CeTaskMessageType.GENERIC)
.setType(MessageType.GENERIC)
.setCreatedAt(queueDto.getUuid().hashCode() + i)));
db.commit();

@@ -500,8 +500,8 @@ public class TaskActionIT {
logInAsSystemAdministrator();

CeActivityDto activityDto = persist(createActivityDto("uuid1"));
insertMessage(activityDto, 1, CeTaskMessageType.INFO);
CeTaskMessageDto warning = insertMessage(activityDto, 2, CeTaskMessageType.GENERIC);
insertMessage(activityDto, 1, MessageType.INFO);
CeTaskMessageDto warning = insertMessage(activityDto, 2, MessageType.GENERIC);

callEndpointAndAssertWarnings(activityDto, List.of(warning));
}
@@ -520,15 +520,15 @@ public class TaskActionIT {
}

private CeTaskMessageDto insertWarning(CeActivityDto task, int i) {
return insertMessage(task, i, CeTaskMessageType.GENERIC);
return insertMessage(task, i, MessageType.GENERIC);
}

private CeTaskMessageDto insertMessage(CeActivityDto task, int i, CeTaskMessageType ceTaskMessageType) {
private CeTaskMessageDto insertMessage(CeActivityDto task, int i, MessageType messageType) {
CeTaskMessageDto res = new CeTaskMessageDto()
.setUuid(UuidFactoryFast.getInstance().create())
.setTaskUuid(task.getUuid())
.setMessage("msg_" + task.getUuid() + "_" + i)
.setType(ceTaskMessageType)
.setType(messageType)
.setCreatedAt(task.getUuid().hashCode() + i);
db.getDbClient().ceTaskMessageDao().insert(db.getSession(), res);
db.getSession().commit();

+ 122
- 0
server/sonar-webserver-webapi/src/it/java/org/sonar/server/dismissmessage/ws/DismissActionIT.java ファイルの表示

@@ -0,0 +1,122 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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.dismissmessage.ws;

import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.System2;
import org.sonar.db.DbTester;
import org.sonar.db.dismissmessage.MessageType;
import org.sonar.db.component.ProjectData;
import org.sonar.db.user.UserDto;
import org.sonar.server.component.TestComponentFinder;
import org.sonar.server.exceptions.UnauthorizedException;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.TestResponse;
import org.sonar.server.ws.WsActionTester;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.tuple;

public class DismissActionIT {

private static final String PROJECT_KEY = "project-key";

@Rule
public UserSessionRule userSession = UserSessionRule.standalone();

@Rule
public DbTester db = DbTester.create(System2.INSTANCE);


private final WsActionTester underTest = new WsActionTester(new DismissAction(userSession, db.getDbClient(), TestComponentFinder.from(db)));

@Test
public void definition() {
WebService.Action def = underTest.getDef();
assertThat(def.key()).isEqualTo("dismiss");
assertThat(def.isInternal()).isTrue();
assertThat(def.isPost()).isTrue();
assertThat(def.params()).extracting(WebService.Param::key, WebService.Param::isRequired).containsOnly(
tuple("projectKey", false),
tuple("messageType", true));
}

@Test
public void return_401_if_user_is_not_logged_in() {
userSession.anonymous();
TestRequest request = underTest.newRequest()
.setParam("projectKey", PROJECT_KEY)
.setParam("messageType", MessageType.PROJECT_NCD_90.name());

assertThatThrownBy(request::execute)
.isInstanceOf(UnauthorizedException.class)
.hasMessage("Authentication is required");
}

@Test
public void throw_IAE_if_messageType_is_not_valid() {
UserDto user = db.users().insertUser();
userSession.logIn(user);
TestRequest request = underTest.newRequest()
.setParam("projectKey", PROJECT_KEY)
.setParam("messageType", "invalid");

assertThatThrownBy(request::execute)
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("Invalid message type: invalid");

}

@Test
public void throw_IAE_if_messageType_is_missing() {
UserDto user = db.users().insertUser();
userSession.logIn(user);
TestRequest request = underTest.newRequest()
.setParam("projectKey", PROJECT_KEY);

assertThatThrownBy(request::execute)
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("The 'messageType' parameter is missing");

}


@Test
public void return_204_on_success() {
UserDto user = db.users().insertUser();
ProjectData project = db.components().insertPrivateProject();
userSession.logIn(user);

TestResponse response = underTest.newRequest()
.setParam("projectKey", project.projectKey())
.setParam("messageType", MessageType.BRANCH_NCD_90.name())
.execute();

assertThat(response.getStatus()).isEqualTo(204);
assertThat(db.select("select * from user_dismissed_messages"))
.extracting("USER_UUID", "PROJECT_UUID", "MESSAGE_TYPE")
.containsExactly(tuple(userSession.getUuid(), project.projectUuid(), MessageType.BRANCH_NCD_90.name()));
}

}

+ 106
- 0
server/sonar-webserver-webapi/src/it/java/org/sonar/server/dismissmessage/ws/DismissActionParameterizedIT.java ファイルの表示

@@ -0,0 +1,106 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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.dismissmessage.ws;

import java.util.Arrays;
import java.util.Collection;
import javax.annotation.Nullable;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.sonar.api.utils.System2;
import org.sonar.db.DbTester;
import org.sonar.db.dismissmessage.MessageType;
import org.sonar.db.component.ProjectData;
import org.sonar.db.user.UserDto;
import org.sonar.server.component.TestComponentFinder;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.TestResponse;
import org.sonar.server.ws.WsActionTester;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

@RunWith(Parameterized.class)
public class DismissActionParameterizedIT {

@Rule
public UserSessionRule userSession = UserSessionRule.standalone();

@Rule
public DbTester db = DbTester.create(System2.INSTANCE);

@Nullable
private final boolean isProjectKeyNull;

private final MessageType messageType;

private final Class<? extends Throwable> expectedException;
private final WsActionTester underTest = new WsActionTester(new DismissAction(userSession, db.getDbClient(), TestComponentFinder.from(db)));

public DismissActionParameterizedIT(boolean isProjectKeyNull, MessageType messageType, Class<? extends Throwable> expectedException) {
this.isProjectKeyNull = isProjectKeyNull;
this.messageType = messageType;
this.expectedException = expectedException;
}

@Test
public void test_verifyProjectKeyAndMessageType() {
UserDto user = db.users().insertUser();
userSession.logIn(user);

TestRequest request = underTest.newRequest()
.setParam("messageType", messageType.name());

if(!isProjectKeyNull) {
ProjectData project = db.components().insertPrivateProject();
request.setParam("projectKey", project.projectKey());
}

if(expectedException != null) {
assertThatThrownBy(request::execute)
.isInstanceOf(expectedException);
} else {
TestResponse response = request.execute();
assertThat(response.getStatus()).isEqualTo(204);
}
}

@Parameterized.Parameters
public static Collection<Object[]> parameterCombination() {
return Arrays.asList(new Object[][]{
{true, MessageType.INFO, IllegalArgumentException.class},
{true, MessageType.GENERIC, IllegalArgumentException.class},
{true, MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE, IllegalArgumentException.class},
{false, MessageType.GLOBAL_NCD_90, IllegalArgumentException.class},
{false, MessageType.GLOBAL_NCD_PAGE_90, IllegalArgumentException.class},
{true, MessageType.PROJECT_NCD_90, IllegalArgumentException.class},
{true, MessageType.PROJECT_NCD_PAGE_90, IllegalArgumentException.class},
{true, MessageType.BRANCH_NCD_90, IllegalArgumentException.class},
{true, MessageType.GLOBAL_NCD_90, null},
{true, MessageType.GLOBAL_NCD_PAGE_90, null},
{false, MessageType.PROJECT_NCD_90, null},
{false, MessageType.PROJECT_NCD_PAGE_90, null},
{false, MessageType.BRANCH_NCD_90, null},
});
}
}

+ 5
- 5
server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/DeactivateActionIT.java ファイルの表示

@@ -30,7 +30,7 @@ import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.alm.setting.AlmSettingDto;
import org.sonar.db.ce.CeTaskMessageType;
import org.sonar.db.dismissmessage.MessageType;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.permission.GlobalPermission;
import org.sonar.db.permission.template.PermissionTemplateDto;
@@ -289,11 +289,11 @@ public class DeactivateActionIT {
ProjectDto project2 = db.components().insertPrivateProject().getProjectDto();
UserDto user = db.users().insertUser();

db.users().insertUserDismissedMessage(user, project1, CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
db.users().insertUserDismissedMessage(user, project2, CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
db.users().insertUserDismissedMessageOnProject(user, project1, MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
db.users().insertUserDismissedMessageOnProject(user, project2, MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
UserDto anotherUser = db.users().insertUser();
UserDismissedMessageDto msg3 = db.users().insertUserDismissedMessage(anotherUser, project1, CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
UserDismissedMessageDto msg4 = db.users().insertUserDismissedMessage(anotherUser, project2, CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
UserDismissedMessageDto msg3 = db.users().insertUserDismissedMessageOnProject(anotherUser, project1, MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
UserDismissedMessageDto msg4 = db.users().insertUserDismissedMessageOnProject(anotherUser, project2, MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);

deactivate(user.getLogin());


+ 4
- 8
server/sonar-webserver-webapi/src/main/java/org/sonar/server/ce/ws/DismissAnalysisWarningAction.java ファイルの表示

@@ -79,12 +79,10 @@ public class DismissAnalysisWarningAction implements CeWsAction {
@Override
public void handle(Request request, Response response) throws Exception {
userSession.checkLoggedIn();
String userLogin = requireNonNull(userSession.getLogin());
String projectKey = request.mandatoryParam(PARAM_COMPONENT_KEY);
String messageKey = request.mandatoryParam(PARAM_MESSAGE_KEY);

try (DbSession dbSession = dbClient.openSession(false)) {
UserDto user = getUser(dbSession, userLogin);
ProjectDto project = componentFinder.getProjectByKey(dbSession, projectKey);
userSession.checkEntityPermission(UserRole.USER, project);

@@ -95,13 +93,14 @@ public class DismissAnalysisWarningAction implements CeWsAction {
throw new IllegalArgumentException(format(MESSAGE_CANNOT_BE_DISMISSED, messageKey));
}

Optional<UserDismissedMessageDto> result = dbClient.userDismissedMessagesDao().selectByUserAndProjectAndMessageType(dbSession, user, project, messageDto.getType());
Optional<UserDismissedMessageDto> result = dbClient.userDismissedMessagesDao().selectByUserAndProjectAndMessageType(dbSession,
userSession.getUuid(), project, messageDto.getType());
if (!result.isPresent()) {
dbClient.userDismissedMessagesDao().insert(dbSession, new UserDismissedMessageDto()
.setUuid(Uuids.create())
.setUserUuid(user.getUuid())
.setUserUuid(userSession.getUuid())
.setProjectUuid(project.getUuid())
.setCeMessageType(messageDto.getType()));
.setMessageType(messageDto.getType()));
dbSession.commit();
}

@@ -109,7 +108,4 @@ public class DismissAnalysisWarningAction implements CeWsAction {
}
}

private UserDto getUser(DbSession dbSession, String userLogin) {
return checkFound(dbClient.userDao().selectByLogin(dbSession, userLogin), "User '%s' not found", userLogin);
}
}

+ 129
- 0
server/sonar-webserver-webapi/src/main/java/org/sonar/server/dismissmessage/ws/DismissAction.java ファイルの表示

@@ -0,0 +1,129 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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.dismissmessage.ws;

import java.util.Optional;
import javax.annotation.Nullable;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.core.util.Uuids;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.dismissmessage.MessageType;
import org.sonar.db.project.ProjectDto;
import org.sonar.db.user.UserDismissedMessageDto;
import org.sonar.server.component.ComponentFinder;
import org.sonar.server.user.UserSession;

public class DismissAction implements DismissMessageWsAction {


private static final String PARAM_PROJECT_KEY = "projectKey";
private static final String PARAM_MESSAGE_TYPE = "messageType";
private final UserSession userSession;
private final DbClient dbClient;
private final ComponentFinder componentFinder;

public DismissAction(UserSession userSession, DbClient dbClient, ComponentFinder componentFinder) {
this.userSession = userSession;
this.dbClient = dbClient;
this.componentFinder = componentFinder;
}
@Override
public void define(WebService.NewController context) {
WebService.NewAction action = context.createAction("dismiss")
.setDescription("Dismiss a message.")
.setSince("10.2")
.setPost(true)
.setInternal(true)
.setHandler(this);

action.createParam(PARAM_PROJECT_KEY)
.setDescription("The project key");

action.createParam(PARAM_MESSAGE_TYPE)
.setDescription("The type of the message dismissed")
.setRequired(true);
}

@Override
public void handle(Request request, Response response) throws Exception {
userSession.checkLoggedIn();
ProjectDto project = null;
String projectKey = request.param(PARAM_PROJECT_KEY);
String messageType = request.mandatoryParam(PARAM_MESSAGE_TYPE);

MessageType type = parseMessageType(messageType);
verifyProjectKeyAndMessageType(projectKey, type);
try (DbSession dbSession = dbClient.openSession(false)) {
if(projectKey != null) {
project = componentFinder.getProjectByKey(dbSession, projectKey);
}
dismissMessage(dbSession, project, type);
dbSession.commit();
}

response.noContent();

}

private void dismissMessage(DbSession dbSession, @Nullable ProjectDto project, MessageType type) {
Optional<UserDismissedMessageDto> result;
if (project == null) {
result = dbClient.userDismissedMessagesDao().selectByUserUuidAndMessageType(dbSession, userSession.getUuid(), type);
} else {
result = dbClient.userDismissedMessagesDao().selectByUserAndProjectAndMessageType(dbSession, userSession.getUuid(), project, type);
}
if (!result.isPresent()) {
dbClient.userDismissedMessagesDao().insert(dbSession, new UserDismissedMessageDto()
.setUuid(Uuids.create())
.setUserUuid(userSession.getUuid())
.setProjectUuid(project == null ? null: project.getUuid())
.setMessageType(type));
}
}

private static MessageType parseMessageType(String messageType) throws IllegalArgumentException {
try {
return MessageType.valueOf(messageType);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("Invalid message type: " + messageType);
}
}

private static void verifyProjectKeyAndMessageType(@Nullable String projectKey, MessageType type) {
switch (type) {
case GLOBAL_NCD_90, GLOBAL_NCD_PAGE_90 -> {
if (projectKey != null) {
throw new IllegalArgumentException("The 'projectKey' parameter is not expected for message type: " + type);
}
}
case PROJECT_NCD_90, PROJECT_NCD_PAGE_90, BRANCH_NCD_90 -> {
if(projectKey == null) {
throw new IllegalArgumentException("The 'projectKey' parameter is missing for message type: " + type);
}
}
default -> throw new IllegalArgumentException("Unexpected message type: " + type);
}
}


}

+ 41
- 0
server/sonar-webserver-webapi/src/main/java/org/sonar/server/dismissmessage/ws/DismissActionWs.java ファイルの表示

@@ -0,0 +1,41 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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.dismissmessage.ws;

import org.sonar.api.server.ws.WebService;

public class DismissActionWs implements WebService {

private final DismissMessageWsAction[] actions;
public DismissActionWs(DismissMessageWsAction... actions) {
this.actions = actions;
}

@Override
public void define(Context context) {
NewController controller = context.createController("api/dismiss_message")
.setDescription("Manage message dismissal.")
.setSince("10.2");
for (DismissMessageWsAction action : actions) {
action.define(controller);
}
controller.done();
}
}

+ 25
- 0
server/sonar-webserver-webapi/src/main/java/org/sonar/server/dismissmessage/ws/DismissMessageWsAction.java ファイルの表示

@@ -0,0 +1,25 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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.dismissmessage.ws;

import org.sonar.server.ws.WsAction;

public interface DismissMessageWsAction extends WsAction {
}

+ 31
- 0
server/sonar-webserver-webapi/src/main/java/org/sonar/server/dismissmessage/ws/DismissMessageWsModule.java ファイルの表示

@@ -0,0 +1,31 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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.dismissmessage.ws;

import org.sonar.core.platform.Module;

public class DismissMessageWsModule extends Module {
@Override
protected void configureModule() {
add(
DismissActionWs.class,
DismissAction.class);
}
}

+ 6
- 6
server/sonar-webserver-webapi/src/test/java/org/sonar/server/ce/ws/TaskFormatterTest.java ファイルの表示

@@ -33,7 +33,7 @@ import org.sonar.db.DbTester;
import org.sonar.db.ce.CeActivityDto;
import org.sonar.db.ce.CeQueueDto;
import org.sonar.db.ce.CeTaskMessageDto;
import org.sonar.db.ce.CeTaskMessageType;
import org.sonar.db.dismissmessage.MessageType;
import org.sonar.db.ce.CeTaskTypes;
import org.sonar.db.user.UserDto;
import org.sonarqube.ws.Ce;
@@ -44,7 +44,7 @@ import static org.assertj.core.api.Assertions.tuple;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonar.db.ce.CeQueueTesting.makeInProgress;
import static org.sonar.db.ce.CeTaskMessageType.INFO;
import static org.sonar.db.dismissmessage.MessageType.INFO;

public class TaskFormatterTest {

@@ -202,8 +202,8 @@ public class TaskFormatterTest {
@Test
public void formatActivity_filterNonWarnings_andSetMessagesAndCount() {
TestActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED, null);
CeTaskMessageDto warning1 = createCeTaskMessageDto(1998, CeTaskMessageType.GENERIC);
CeTaskMessageDto warning2 = createCeTaskMessageDto(1999, CeTaskMessageType.GENERIC);
CeTaskMessageDto warning1 = createCeTaskMessageDto(1998, MessageType.GENERIC);
CeTaskMessageDto warning2 = createCeTaskMessageDto(1999, MessageType.GENERIC);

List<CeTaskMessageDto> ceTaskMessageDtos = new ArrayList<>(dto.getCeTaskMessageDtos());
ceTaskMessageDtos.add(warning1);
@@ -292,12 +292,12 @@ public class TaskFormatterTest {
.setAnalysisUuid("U1");
}

private CeTaskMessageDto createCeTaskMessageDto(int i, CeTaskMessageType ceTaskMessageType) {
private CeTaskMessageDto createCeTaskMessageDto(int i, MessageType messageType) {
CeTaskMessageDto ceTaskMessageDto = new CeTaskMessageDto();
ceTaskMessageDto.setMessage("message_" + i);
ceTaskMessageDto.setCreatedAt(system2.now());
ceTaskMessageDto.setTaskUuid("uuid_" + i);
ceTaskMessageDto.setType(ceTaskMessageType);
ceTaskMessageDto.setType(messageType);
return ceTaskMessageDto;
}


+ 4
- 0
server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java ファイルの表示

@@ -85,6 +85,7 @@ import org.sonar.server.component.index.EntityDefinitionIndexer;
import org.sonar.server.component.ws.ComponentViewerJsonWriter;
import org.sonar.server.component.ws.ComponentsWsModule;
import org.sonar.server.developers.ws.DevelopersWsModule;
import org.sonar.server.dismissmessage.ws.DismissMessageWsModule;
import org.sonar.server.duplication.ws.DuplicationsParser;
import org.sonar.server.duplication.ws.DuplicationsWs;
import org.sonar.server.duplication.ws.ShowResponseBuilder;
@@ -623,6 +624,9 @@ public class PlatformLevel4 extends PlatformLevel {
// monitoring
ServerMonitoringMetrics.class,

// dismiss message
new DismissMessageWsModule(),

AzureMetricsTask.class,
BitbucketMetricsTask.class,
GithubMetricsTask.class,

読み込み中…
キャンセル
保存