3 * Copyright (C) 2009-2023 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.server.ce.ws;
22 import javax.annotation.Nullable;
23 import org.junit.Rule;
24 import org.junit.Test;
25 import org.sonar.api.server.ws.WebService;
26 import org.sonar.api.utils.System2;
27 import org.sonar.api.web.UserRole;
28 import org.sonar.db.DbTester;
29 import org.sonar.db.ce.CeActivityDto;
30 import org.sonar.db.ce.CeQueueDto;
31 import org.sonar.db.ce.CeTaskMessageDto;
32 import org.sonar.db.ce.CeTaskMessageType;
33 import org.sonar.db.component.ComponentDto;
34 import org.sonar.db.component.ProjectData;
35 import org.sonar.db.component.SnapshotDto;
36 import org.sonar.db.project.ProjectDto;
37 import org.sonar.db.user.UserDto;
38 import org.sonar.server.component.TestComponentFinder;
39 import org.sonar.server.exceptions.ForbiddenException;
40 import org.sonar.server.exceptions.NotFoundException;
41 import org.sonar.server.exceptions.UnauthorizedException;
42 import org.sonar.server.tester.UserSessionRule;
43 import org.sonar.server.ws.TestRequest;
44 import org.sonar.server.ws.TestResponse;
45 import org.sonar.server.ws.WsActionTester;
47 import static java.lang.String.format;
48 import static org.assertj.core.api.Assertions.assertThat;
49 import static org.assertj.core.api.Assertions.tuple;
50 import static org.junit.Assert.assertThrows;
51 import static org.sonar.db.ce.CeActivityDto.Status.SUCCESS;
52 import static org.sonar.db.ce.CeTaskTypes.REPORT;
54 public class DismissAnalysisWarningActionIT {
56 public UserSessionRule userSession = UserSessionRule.standalone();
59 public DbTester db = DbTester.create(System2.INSTANCE);
61 private static int counter = 1;
63 private final WsActionTester underTest = new WsActionTester(new DismissAnalysisWarningAction(userSession, db.getDbClient(), TestComponentFinder.from(db)));
66 public void definition() {
67 WebService.Action def = underTest.getDef();
68 assertThat(def.key()).isEqualTo("dismiss_analysis_warning");
69 assertThat(def.isInternal()).isTrue();
70 assertThat(def.isPost()).isTrue();
71 assertThat(def.params()).extracting(WebService.Param::key, WebService.Param::isRequired).containsOnly(
72 tuple("component", true),
73 tuple("warning", true));
77 public void return_401_if_user_is_not_logged_in() {
78 userSession.anonymous();
79 TestRequest request = underTest.newRequest()
80 .setParam("component", "6653f062-7c03-4b55-bcd2-0dac67640c4d")
81 .setParam("warning", "55c40b35-4145-4b78-bdf2-dfb242c25f15");
83 assertThrows("Authentication is required", UnauthorizedException.class, request::execute);
87 public void return_403_if_user_has_no_browse_permission_on_private_project() {
88 ProjectDto project = db.components().insertPrivateProject().getProjectDto();
89 UserDto user = db.users().insertUser();
90 userSession.logIn(user);
92 TestRequest request = underTest.newRequest()
93 .setParam("component", project.getKee())
94 .setParam("warning", "55c40b35-4145-4b78-bdf2-dfb242c25f15");
96 assertThrows("Insufficient privileges", ForbiddenException.class, request::execute);
100 public void return_204_on_success() {
101 UserDto user = db.users().insertUser();
102 ProjectData project = db.components().insertPrivateProject();
103 userSession.logIn(user).addProjectPermission(UserRole.USER, project.getProjectDto());
104 SnapshotDto analysis = db.components().insertSnapshot(project.getMainBranchComponent());
105 CeActivityDto activity = insertActivity("task-uuid" + counter++, project.getMainBranchComponent(), SUCCESS, analysis, REPORT);
106 CeTaskMessageDto taskMessageDismissible = createTaskMessage(activity, "dismissable warning", CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
108 TestResponse response = underTest.newRequest()
109 .setParam("component", project.projectKey())
110 .setParam("warning", taskMessageDismissible.getUuid())
113 assertThat(response.getStatus()).isEqualTo(204);
114 assertThat(db.select("select * from user_dismissed_messages"))
115 .extracting("USER_UUID", "PROJECT_UUID", "MESSAGE_TYPE")
116 .containsExactly(tuple(userSession.getUuid(), project.projectUuid(), CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE.name()));
120 public void is_idempotent() {
121 UserDto user = db.users().insertUser();
122 ProjectData project = db.components().insertPrivateProject();
123 userSession.logIn(user).addProjectPermission(UserRole.USER, project.getProjectDto());
124 SnapshotDto analysis = db.components().insertSnapshot(project.getMainBranchComponent());
125 CeActivityDto activity = insertActivity("task-uuid" + counter++, project.getMainBranchComponent(), SUCCESS, analysis, REPORT);
126 CeTaskMessageDto taskMessageDismissible = createTaskMessage(activity, "dismissable warning", CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
128 underTest.newRequest()
129 .setParam("component", project.projectKey())
130 .setParam("warning", taskMessageDismissible.getUuid())
132 TestResponse response = underTest.newRequest()
133 .setParam("component", project.projectKey())
134 .setParam("warning", taskMessageDismissible.getUuid())
137 assertThat(response.getStatus()).isEqualTo(204);
138 assertThat(db.select("select * from user_dismissed_messages"))
139 .extracting("USER_UUID", "PROJECT_UUID", "MESSAGE_TYPE")
140 .containsExactly(tuple(userSession.getUuid(), project.projectUuid(), CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE.name()));
144 public void returns_400_if_warning_is_not_dismissable() {
145 UserDto user = db.users().insertUser();
146 ProjectData project = db.components().insertPrivateProject();
147 userSession.logIn(user).addProjectPermission(UserRole.USER, project.getProjectDto());
148 SnapshotDto analysis = db.components().insertSnapshot(project.getMainBranchComponent());
149 CeActivityDto activity = insertActivity("task-uuid" + counter++, project.getMainBranchComponent(), SUCCESS, analysis, REPORT);
150 CeTaskMessageDto taskMessage = createTaskMessage(activity, "generic warning");
152 TestRequest request = underTest.newRequest()
153 .setParam("component", project.projectKey())
154 .setParam("warning", taskMessage.getUuid());
156 assertThrows(format("Message '%s' cannot be dismissed.", taskMessage.getUuid()), IllegalArgumentException.class, request::execute);
157 assertThat(db.countRowsOfTable("USER_DISMISSED_MESSAGES")).isZero();
161 public void returns_404_if_warning_does_not_exist() {
162 UserDto user = db.users().insertUser();
163 ProjectData project = db.components().insertPrivateProject();
164 userSession.logIn(user).addProjectPermission(UserRole.USER, project.getProjectDto());
165 SnapshotDto analysis = db.components().insertSnapshot(project.getMainBranchComponent());
166 insertActivity("task-uuid" + counter++, project.getMainBranchComponent(), SUCCESS, analysis, REPORT);
167 String warningUuid = "78d1e2ff-3e67-4037-ba58-0d57d5f88e44";
169 TestRequest request = underTest.newRequest()
170 .setParam("component", project.projectKey())
171 .setParam("warning", warningUuid);
173 assertThrows(format("Message '%s' not found", warningUuid), NotFoundException.class, request::execute);
174 assertThat(db.countRowsOfTable("USER_DISMISSED_MESSAGES")).isZero();
177 private CeTaskMessageDto createTaskMessage(CeActivityDto activity, String warning) {
178 return createTaskMessage(activity, warning, CeTaskMessageType.GENERIC);
181 private CeTaskMessageDto createTaskMessage(CeActivityDto activity, String warning, CeTaskMessageType messageType) {
182 CeTaskMessageDto ceTaskMessageDto = new CeTaskMessageDto()
183 .setUuid("m-uuid-" + counter++)
184 .setTaskUuid(activity.getUuid())
186 .setType(messageType)
187 .setCreatedAt(counter);
188 db.getDbClient().ceTaskMessageDao().insert(db.getSession(), ceTaskMessageDto);
190 return ceTaskMessageDto;
193 private CeActivityDto insertActivity(String taskUuid, ComponentDto component, CeActivityDto.Status status, @Nullable SnapshotDto analysis, String taskType) {
194 CeQueueDto queueDto = new CeQueueDto();
195 queueDto.setTaskType(taskType);
196 queueDto.setComponentUuid(component.uuid());
197 queueDto.setUuid(taskUuid);
198 CeActivityDto activityDto = new CeActivityDto(queueDto);
199 activityDto.setStatus(status);
200 activityDto.setExecutionTimeMs(500L);
201 activityDto.setAnalysisUuid(analysis == null ? null : analysis.getUuid());
202 activityDto.setExecutedAt((long) counter++);
203 activityDto.setTaskType(taskType);
204 activityDto.setComponentUuid(component.uuid());
205 db.getDbClient().ceActivityDao().insert(db.getSession(), activityDto);
206 db.getSession().commit();