aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-webserver-webapi
diff options
context:
space:
mode:
authorAlain Kermis <alain.kermis@sonarsource.com>2023-05-23 10:46:57 +0200
committersonartech <sonartech@sonarsource.com>2023-05-30 20:02:52 +0000
commit716a2667e6392f29f9c2d651eb7a7a9fbbc1fccb (patch)
treea9f4110e1e1b26cc6794fc06f43fa43f4aae8e87 /server/sonar-webserver-webapi
parent1998f37bb4c45c5f3160705a9b70ad73d9cc04cc (diff)
downloadsonarqube-716a2667e6392f29f9c2d651eb7a7a9fbbc1fccb.tar.gz
sonarqube-716a2667e6392f29f9c2d651eb7a7a9fbbc1fccb.zip
SONAR-19340 Raise event whenever hotspots change in WS
Diffstat (limited to 'server/sonar-webserver-webapi')
-rw-r--r--server/sonar-webserver-webapi/src/it/java/org/sonar/server/hotspot/ws/AssignActionIT.java92
-rw-r--r--server/sonar-webserver-webapi/src/it/java/org/sonar/server/hotspot/ws/ChangeStatusActionIT.java66
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/AssignAction.java26
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/ChangeStatusAction.java27
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/DoTransitionAction.java2
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/IssueUpdater.java21
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SetSeverityAction.java2
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SetTypeAction.java2
8 files changed, 202 insertions, 36 deletions
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/hotspot/ws/AssignActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/hotspot/ws/AssignActionIT.java
index 019bda572a7..bab03f3c1df 100644
--- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/hotspot/ws/AssignActionIT.java
+++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/hotspot/ws/AssignActionIT.java
@@ -30,6 +30,7 @@ import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import org.assertj.core.api.Condition;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -44,6 +45,8 @@ import org.sonar.core.issue.IssueChangeContext;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
+import org.sonar.db.component.BranchDto;
+import org.sonar.db.component.BranchType;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.issue.IssueDto;
import org.sonar.db.rule.RuleDto;
@@ -53,6 +56,8 @@ import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.issue.IssueFieldsSetter;
import org.sonar.server.issue.ws.IssueUpdater;
+import org.sonar.server.pushapi.hotspots.HotspotChangeEventService;
+import org.sonar.server.pushapi.hotspots.HotspotChangedEvent;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.WsActionTester;
@@ -68,6 +73,7 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import static org.sonar.api.issue.Issue.RESOLUTION_ACKNOWLEDGED;
@@ -90,15 +96,22 @@ public class AssignActionIT {
private final DbClient dbClient = dbTester.getDbClient();
private final IssueUpdater issueUpdater = mock(IssueUpdater.class);
+ private HotspotChangeEventService hotspotChangeEventService = mock(HotspotChangeEventService.class);
private final System2 system2 = mock(System2.class);
private final IssueFieldsSetter issueFieldsSetter = mock(IssueFieldsSetter.class);
private final HotspotWsSupport hotspotWsSupport = new HotspotWsSupport(dbClient, userSessionRule, system2);
- private final AssignAction underTest = new AssignAction(dbClient, hotspotWsSupport, issueFieldsSetter, issueUpdater);
+ private final AssignAction underTest = new AssignAction(dbClient, hotspotWsSupport, issueFieldsSetter, issueUpdater, hotspotChangeEventService);
private final WsActionTester actionTester = new WsActionTester(underTest);
+ private BranchDto branchDto = mock(BranchDto.class);
+
+ @Before
+ public void setMock() {
+ when(issueUpdater.getBranch(any(), any())).thenReturn(branchDto);
+ }
@Test
- public void ws_definition_check() {
+ public void wsExecution_whenDefined() {
WebService.Action wsDefinition = actionTester.getDef();
assertThat(wsDefinition.isPost()).isTrue();
@@ -120,7 +133,7 @@ public class AssignActionIT {
}
@Test
- public void assign_hotspot_to_someone_for_public_project() {
+ public void wsExecution_whenAssignedForPublicProject() {
ComponentDto project = dbTester.components().insertPublicProject().getMainBranchComponent();
ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
IssueDto hotspot = dbTester.issues().insertHotspot(project, file);
@@ -137,7 +150,7 @@ public class AssignActionIT {
}
@Test
- public void unassign_hotspot_for_public_project() {
+ public void wsExecution_whenUnassignedForPublicProject() {
ComponentDto project = dbTester.components().insertPublicProject().getMainBranchComponent();
ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
UserDto assignee = insertUser(randomAlphanumeric(15));
@@ -154,7 +167,7 @@ public class AssignActionIT {
}
@Test
- public void assign_hotspot_to_me_for_public_project() {
+ public void wsExecution_whenMyselfAssignedForPublicProject() {
ComponentDto project = dbTester.components().insertPublicProject().getMainBranchComponent();
ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
IssueDto hotspot = dbTester.issues().insertHotspot(project, file);
@@ -170,7 +183,7 @@ public class AssignActionIT {
}
@Test
- public void unassign_hotspot_myself_for_public_project() {
+ public void wsExecution_whenMyselfUnassignedForPublicProject() {
ComponentDto project = dbTester.components().insertPublicProject().getMainBranchComponent();
ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
UserDto me = insertUser(randomAlphanumeric(10));
@@ -185,7 +198,7 @@ public class AssignActionIT {
}
@Test
- public void assign_hotspot_to_someone_for_private_project() {
+ public void wsExecution_whenAssigneeForPrivateProject() {
ComponentDto project = dbTester.components().insertPrivateProject().getMainBranchComponent();
ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
IssueDto hotspot = dbTester.issues().insertHotspot(project, file);
@@ -201,7 +214,7 @@ public class AssignActionIT {
}
@Test
- public void unassign_hotspot_for_private_project() {
+ public void wsExecution_whenUnassignedForPrivateProject() {
ComponentDto project = dbTester.components().insertPrivateProject().getMainBranchComponent();
ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
UserDto assignee = insertUser(randomAlphanumeric(15));
@@ -217,7 +230,7 @@ public class AssignActionIT {
}
@Test
- public void assign_hotspot_to_someone_for_private_project_branch() {
+ public void wsExecution_whenAssigneeForPrivateProjectBranch() {
ComponentDto project = dbTester.components().insertPrivateProject().getMainBranchComponent();
ComponentDto branch = dbTester.components().insertProjectBranch(project);
ComponentDto file = dbTester.components().insertComponent(newFileDto(branch, project.uuid()));
@@ -235,7 +248,7 @@ public class AssignActionIT {
}
@Test
- public void fail_if_assignee_does_not_have_access_for_private_project() {
+ public void wsExecution_whenAssigneeDoesNotHaveAccessToPrivateProject_shouldFail() {
ComponentDto project = dbTester.components().insertPrivateProject().getMainBranchComponent();
ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
IssueDto hotspot = dbTester.issues().insertHotspot(project, file);
@@ -252,7 +265,7 @@ public class AssignActionIT {
}
@Test
- public void fail_if_assignee_does_not_have_access_for_private_project_branch() {
+ public void wsExecution_whenAssigneeDoesNotHaveAccessToPrivateProjectBranch_shouldFail() {
ComponentDto project = dbTester.components().insertPrivateProject().getMainBranchComponent();
ComponentDto branch = dbTester.components().insertProjectBranch(project);
ComponentDto file = dbTester.components().insertComponent(newFileDto(branch, project.uuid()));
@@ -271,7 +284,7 @@ public class AssignActionIT {
}
@Test
- public void assign_hotspot_to_me_for_private_project() {
+ public void wsExecution_whenAssignHotspotToMeForPrivateProject() {
ComponentDto project = dbTester.components().insertPrivateProject().getMainBranchComponent();
ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
@@ -287,7 +300,7 @@ public class AssignActionIT {
}
@Test
- public void assign_hotspot_with_comment() {
+ public void wsExecution_whenAssignHotspotWithComment() {
ComponentDto project = dbTester.components().insertPublicProject().getMainBranchComponent();
ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
@@ -307,7 +320,7 @@ public class AssignActionIT {
}
@Test
- public void assign_twice_same_user_to_hotspot_does_not_reload() {
+ public void wsExecution_whenAssignTwiceSameUserHotspotDoesNotReload_shouldFail() {
ComponentDto project = dbTester.components().insertPublicProject().getMainBranchComponent();
ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
IssueDto hotspot = dbTester.issues().insertHotspot(project, file);
@@ -326,7 +339,42 @@ public class AssignActionIT {
}
@Test
- public void fail_if_assigning_to_not_existing_user() {
+ public void wsExecution_whenBranchTypeIsBranch_shouldDistributeEvents() {
+ ComponentDto project = dbTester.components().insertPublicProject().getMainBranchComponent();
+ ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
+ IssueDto hotspot = dbTester.issues().insertHotspot(project, file);
+
+ UserDto userDto = insertUser(randomAlphanumeric(10));
+ userSessionRule.logIn(userDto).registerComponents(project);
+
+ UserDto assignee = insertUser(randomAlphanumeric(15));
+ when(branchDto.getBranchType()).thenReturn(BranchType.BRANCH);
+ when(issueFieldsSetter.assign(eq(hotspot.toDefaultIssue()), userMatcher(assignee), any(IssueChangeContext.class))).thenReturn(true);
+
+ executeRequest(hotspot, assignee.getLogin(), null);
+ verify(hotspotChangeEventService).distributeHotspotChangedEvent(eq(project.uuid()), any(HotspotChangedEvent.class));
+ }
+
+ @Test
+ public void wsExecution_whenBranchIsPullRequest_shouldNotDistributeEvents() {
+ ComponentDto project = dbTester.components().insertPublicProject().getMainBranchComponent();
+ ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
+ IssueDto hotspot = dbTester.issues().insertHotspot(project, file);
+
+ UserDto userDto = insertUser(randomAlphanumeric(10));
+ userSessionRule.logIn(userDto).registerComponents(project);
+
+ UserDto assignee = insertUser(randomAlphanumeric(15));
+ when(branchDto.getBranchType()).thenReturn(BranchType.PULL_REQUEST);
+ when(issueFieldsSetter.assign(eq(hotspot.toDefaultIssue()), userMatcher(assignee), any(IssueChangeContext.class))).thenReturn(true);
+
+ executeRequest(hotspot, assignee.getLogin(), null);
+ verifyNoInteractions(hotspotChangeEventService);
+ }
+
+
+ @Test
+ public void wsExecution_whenAssigningToNonExistingUser_shouldFail() {
ComponentDto project = dbTester.components().insertPublicProject().getMainBranchComponent();
ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
IssueDto hotspot = dbTester.issues().insertHotspot(project, file);
@@ -343,7 +391,7 @@ public class AssignActionIT {
@Test
@UseDataProvider("allIssueStatusesAndResolutionsThatThrowOnAssign")
- public void fail_if_assign_user_to_hotspot_for_which_it_is_forbidden(String status, String resolution) {
+ public void wsExecution_whenAssigningToUserIfForbidden_shouldFail(String status, String resolution) {
ComponentDto project = dbTester.components().insertPublicProject().getMainBranchComponent();
ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
@@ -373,7 +421,7 @@ public class AssignActionIT {
@Test
@UseDataProvider("allIssueStatusesAndResolutionsThatDoNotThrowOnAssign")
- public void fail_if_assign_user_to_hotspot_for_which_it_is_allowed(String status, String resolution) {
+ public void wsExecution_whenAssigningToUserIfAllowed_shouldNotFail(String status, String resolution) {
ComponentDto project = dbTester.components().insertPublicProject().getMainBranchComponent();
ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
IssueDto hotspot = dbTester.issues().insertHotspot(project, file, h -> {
@@ -397,7 +445,7 @@ public class AssignActionIT {
}
@Test
- public void fail_if_not_authenticated() {
+ public void wsExecution_whenNotAuthenticated_shouldFail() {
ComponentDto project = dbTester.components().insertPublicProject().getMainBranchComponent();
ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
IssueDto hotspot = dbTester.issues().insertHotspot(project, file);
@@ -413,7 +461,7 @@ public class AssignActionIT {
}
@Test
- public void fail_if_missing_browse_permission() {
+ public void wsExecution_whenMissingBrowserAthentication_shouldFail() {
ComponentDto project = dbTester.components().insertPrivateProject().getMainBranchComponent();
ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
IssueDto hotspot = dbTester.issues().insertHotspot(project, file);
@@ -429,7 +477,7 @@ public class AssignActionIT {
}
@Test
- public void fail_if_hotspot_does_not_exist() {
+ public void wsExecution_whenHotspotDoesNotExist_shouldFail() {
ComponentDto project = dbTester.components().insertPublicProject().getMainBranchComponent();
UserDto me = insertUser(randomAlphanumeric(10));
@@ -444,7 +492,7 @@ public class AssignActionIT {
@Test
@UseDataProvider("allRuleTypesWithStatusesExceptHotspot")
- public void fail_if_trying_to_assign_issue(RuleType ruleType, String status) {
+ public void wsExecution_whenAssigningToNonexistantIssue_shouldFail(RuleType ruleType, String status) {
ComponentDto project = dbTester.components().insertPublicProject().getMainBranchComponent();
ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
RuleDto rule = newRule(ruleType);
@@ -478,7 +526,7 @@ public class AssignActionIT {
}
@Test
- public void fail_with_NotFoundException_if_hotspot_is_closed() {
+ public void wsExecution_whenHotspotIsClosed_shouldFailWithNotFoundException() {
ComponentDto project = dbTester.components().insertPublicProject().getMainBranchComponent();
ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
RuleDto rule = newRule(SECURITY_HOTSPOT);
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/hotspot/ws/ChangeStatusActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/hotspot/ws/ChangeStatusActionIT.java
index 9249030980e..b0b02683772 100644
--- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/hotspot/ws/ChangeStatusActionIT.java
+++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/hotspot/ws/ChangeStatusActionIT.java
@@ -29,6 +29,7 @@ import java.util.Random;
import java.util.function.Consumer;
import java.util.stream.Stream;
import javax.annotation.Nullable;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -43,9 +44,13 @@ import org.sonar.core.issue.IssueChangeContext;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
+import org.sonar.db.component.BranchDto;
+import org.sonar.db.component.BranchType;
+import org.sonar.db.component.ComponentDbTester;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.issue.IssueDto;
import org.sonar.db.issue.IssueTesting;
+import org.sonar.db.project.ProjectDto;
import org.sonar.db.rule.RuleDto;
import org.sonar.db.rule.RuleTesting;
import org.sonar.server.exceptions.ForbiddenException;
@@ -54,6 +59,8 @@ import org.sonar.server.exceptions.UnauthorizedException;
import org.sonar.server.issue.IssueFieldsSetter;
import org.sonar.server.issue.TransitionService;
import org.sonar.server.issue.ws.IssueUpdater;
+import org.sonar.server.pushapi.hotspots.HotspotChangeEventService;
+import org.sonar.server.pushapi.hotspots.HotspotChangedEvent;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.WsActionTester;
@@ -92,11 +99,19 @@ public class ChangeStatusActionIT {
private DbClient dbClient = dbTester.getDbClient();
private TransitionService transitionService = mock(TransitionService.class);
private IssueUpdater issueUpdater = mock(IssueUpdater.class);
+ private HotspotChangeEventService hotspotChangeEventService = mock(HotspotChangeEventService.class);
private System2 system2 = mock(System2.class);
private IssueFieldsSetter issueFieldsSetter = mock(IssueFieldsSetter.class);
private HotspotWsSupport hotspotWsSupport = new HotspotWsSupport(dbClient, userSessionRule, system2);
- private ChangeStatusAction underTest = new ChangeStatusAction(dbClient, hotspotWsSupport, transitionService, issueFieldsSetter, issueUpdater);
+ private ChangeStatusAction underTest = new ChangeStatusAction(dbClient, hotspotWsSupport, transitionService, issueFieldsSetter, issueUpdater, hotspotChangeEventService);
private WsActionTester actionTester = new WsActionTester(underTest);
+ private final ComponentDbTester componentDbTester = new ComponentDbTester(dbTester);
+ private BranchDto branchDto = mock(BranchDto.class);
+
+ @Before
+ public void setMock() {
+ when(issueUpdater.getBranch(any(), any())).thenReturn(branchDto);
+ }
@Test
public void define_shouldMarkWebServiceAsPublic() {
@@ -426,6 +441,55 @@ public class ChangeStatusActionIT {
}
}
+ @Test
+ public void wsExecution_whenOnMainBranch_shouldDistributeEvents() {
+ ComponentDto project = dbTester.components().insertPublicProject().getMainBranchComponent();
+ userSessionRule.logIn().registerComponents(project)
+ .addProjectPermission(UserRole.SECURITYHOTSPOT_ADMIN, project);
+ ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
+ when(branchDto.getBranchType()).thenReturn(BranchType.BRANCH);
+ IssueDto hotspot = dbTester.issues().insertHotspot(project, file);
+ when(transitionService.doTransition(any(), any(), any())).thenReturn(true);
+
+ newRequest(hotspot, STATUS_REVIEWED, RESOLUTION_FIXED, NO_COMMENT).execute();
+
+ verify(hotspotChangeEventService).distributeHotspotChangedEvent(eq(project.uuid()), any(HotspotChangedEvent.class));
+ }
+
+ @Test
+ public void wsExecution_whenOnNonMainBranch_shouldDistributeEvents() {
+ ProjectDto project = dbTester.components().insertPublicProject().getProjectDto();
+ ComponentDto projectComponentDto = dbTester.components().getComponentDto(project);
+ BranchDto branch = dbTester.components().insertProjectBranch(project, b -> b.setKey("develop"));
+ ComponentDto branchComponentDto = dbTester.components().getComponentDto(branch);
+
+ ComponentDto file = dbTester.components().insertComponent(newFileDto(branchComponentDto));
+ when(branchDto.getBranchType()).thenReturn(BranchType.BRANCH);
+ IssueDto hotspot = dbTester.issues().insertHotspot(branchComponentDto, file);
+ when(transitionService.doTransition(any(), any(), any())).thenReturn(true);
+
+ userSessionRule.logIn().registerComponents(projectComponentDto)
+ .addProjectPermission(UserRole.SECURITYHOTSPOT_ADMIN, projectComponentDto, branchComponentDto);
+ newRequest(hotspot, STATUS_REVIEWED, RESOLUTION_FIXED, NO_COMMENT).execute();
+
+ verify(hotspotChangeEventService).distributeHotspotChangedEvent(eq(branchComponentDto.uuid()), any(HotspotChangedEvent.class));
+ }
+
+ @Test
+ public void wsExecution_whenBranchTypeIsPullRequest_shouldNotDistributeEvents() {
+ ComponentDto project = dbTester.components().insertPublicProject().getMainBranchComponent();
+ userSessionRule.logIn().registerComponents(project)
+ .addProjectPermission(UserRole.SECURITYHOTSPOT_ADMIN, project);
+ ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
+ when(branchDto.getBranchType()).thenReturn(BranchType.PULL_REQUEST);
+ IssueDto hotspot = dbTester.issues().insertHotspot(project, file);
+ when(transitionService.doTransition(any(), any(), any())).thenReturn(true);
+
+ newRequest(hotspot, STATUS_REVIEWED, RESOLUTION_FIXED, NO_COMMENT).execute();
+
+ verifyNoInteractions(hotspotChangeEventService);
+ }
+
@DataProvider
public static Object[][] reviewedResolutionsAndExpectedTransitionKey() {
return new Object[][] {
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/AssignAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/AssignAction.java
index 31b961e38e0..24f141d7efb 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/AssignAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/AssignAction.java
@@ -30,15 +30,19 @@ import org.sonar.core.issue.IssueChangeContext;
import org.sonar.core.util.Uuids;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
+import org.sonar.db.component.BranchDto;
import org.sonar.db.issue.IssueDto;
import org.sonar.db.project.ProjectDto;
import org.sonar.db.user.UserDto;
import org.sonar.server.issue.IssueFieldsSetter;
import org.sonar.server.issue.ws.IssueUpdater;
+import org.sonar.server.pushapi.hotspots.HotspotChangeEventService;
+import org.sonar.server.pushapi.hotspots.HotspotChangedEvent;
import static com.google.common.base.Strings.isNullOrEmpty;
import static org.sonar.api.issue.Issue.RESOLUTION_ACKNOWLEDGED;
import static org.sonar.api.issue.Issue.STATUS_TO_REVIEW;
+import static org.sonar.db.component.BranchType.BRANCH;
import static org.sonar.server.exceptions.NotFoundException.checkFound;
import static org.sonar.server.exceptions.NotFoundException.checkFoundWithOptional;
@@ -53,13 +57,15 @@ public class AssignAction implements HotspotsWsAction {
private final HotspotWsSupport hotspotWsSupport;
private final IssueFieldsSetter issueFieldsSetter;
private final IssueUpdater issueUpdater;
+ private final HotspotChangeEventService hotspotChangeEventService;
public AssignAction(DbClient dbClient, HotspotWsSupport hotspotWsSupport, IssueFieldsSetter issueFieldsSetter,
- IssueUpdater issueUpdater) {
+ IssueUpdater issueUpdater, HotspotChangeEventService hotspotChangeEventService) {
this.dbClient = dbClient;
this.hotspotWsSupport = hotspotWsSupport;
this.issueFieldsSetter = issueFieldsSetter;
this.issueUpdater = issueUpdater;
+ this.hotspotChangeEventService = hotspotChangeEventService;
}
@Override
@@ -121,6 +127,12 @@ public class AssignAction implements HotspotsWsAction {
if (issueFieldsSetter.assign(defaultIssue, assignee, context)) {
issueUpdater.saveIssueAndPreloadSearchResponseData(dbSession, defaultIssue, context);
+
+ BranchDto branch = issueUpdater.getBranch(dbSession, defaultIssue);
+ if (BRANCH.equals(branch.getBranchType())) {
+ HotspotChangedEvent hotspotChangedEvent = buildEventData(defaultIssue, assignee, hotspotDto.getFilePath());
+ hotspotChangeEventService.distributeHotspotChangedEvent(defaultIssue.projectUuid(), hotspotChangedEvent);
+ }
}
}
}
@@ -147,4 +159,16 @@ public class AssignAction implements HotspotsWsAction {
private boolean hasProjectPermission(DbSession dbSession, String userUuid, String projectUuid) {
return dbClient.authorizationDao().selectProjectPermissions(dbSession, projectUuid, userUuid).contains(UserRole.USER);
}
+
+ private static HotspotChangedEvent buildEventData(DefaultIssue defaultIssue, @Nullable UserDto assignee, String filePath) {
+ return new HotspotChangedEvent.Builder()
+ .setKey(defaultIssue.key())
+ .setProjectKey(defaultIssue.projectKey())
+ .setStatus(defaultIssue.status())
+ .setResolution(defaultIssue.resolution())
+ .setUpdateDate(defaultIssue.updateDate())
+ .setAssignee(assignee == null ? null : assignee.getLogin())
+ .setFilePath(filePath)
+ .build();
+ }
}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/ChangeStatusAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/ChangeStatusAction.java
index 8a7cf079fb7..98cb5a079a0 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/ChangeStatusAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/ChangeStatusAction.java
@@ -33,10 +33,13 @@ import org.sonar.core.issue.IssueChangeContext;
import org.sonar.core.util.Uuids;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
+import org.sonar.db.component.BranchDto;
import org.sonar.db.issue.IssueDto;
import org.sonar.server.issue.IssueFieldsSetter;
import org.sonar.server.issue.TransitionService;
import org.sonar.server.issue.ws.IssueUpdater;
+import org.sonar.server.pushapi.hotspots.HotspotChangeEventService;
+import org.sonar.server.pushapi.hotspots.HotspotChangedEvent;
import static com.google.common.base.Preconditions.checkArgument;
import static org.apache.commons.lang.StringUtils.trimToNull;
@@ -45,6 +48,7 @@ import static org.sonar.api.issue.Issue.RESOLUTION_FIXED;
import static org.sonar.api.issue.Issue.SECURITY_HOTSPOT_RESOLUTIONS;
import static org.sonar.api.issue.Issue.STATUS_REVIEWED;
import static org.sonar.api.issue.Issue.STATUS_TO_REVIEW;
+import static org.sonar.db.component.BranchType.BRANCH;
public class ChangeStatusAction implements HotspotsWsAction {
@@ -58,14 +62,16 @@ public class ChangeStatusAction implements HotspotsWsAction {
private final TransitionService transitionService;
private final IssueFieldsSetter issueFieldsSetter;
private final IssueUpdater issueUpdater;
+ private final HotspotChangeEventService hotspotChangeEventService;
public ChangeStatusAction(DbClient dbClient, HotspotWsSupport hotspotWsSupport, TransitionService transitionService,
- IssueFieldsSetter issueFieldsSetter, IssueUpdater issueUpdater) {
+ IssueFieldsSetter issueFieldsSetter, IssueUpdater issueUpdater, HotspotChangeEventService hotspotChangeEventService) {
this.dbClient = dbClient;
this.hotspotWsSupport = hotspotWsSupport;
this.transitionService = transitionService;
this.issueFieldsSetter = issueFieldsSetter;
this.issueUpdater = issueUpdater;
+ this.hotspotChangeEventService = hotspotChangeEventService;
}
@Override
@@ -155,8 +161,27 @@ public class ChangeStatusAction implements HotspotsWsAction {
if (comment != null) {
issueFieldsSetter.addComment(defaultIssue, comment, context);
}
+
issueUpdater.saveIssueAndPreloadSearchResponseData(session, defaultIssue, context);
+
+ BranchDto branch = issueUpdater.getBranch(session, defaultIssue);
+ if (BRANCH.equals(branch.getBranchType())) {
+ HotspotChangedEvent hotspotChangedEvent = buildEventData(defaultIssue, issueDto);
+ hotspotChangeEventService.distributeHotspotChangedEvent(defaultIssue.projectUuid(), hotspotChangedEvent);
+ }
}
}
+ private static HotspotChangedEvent buildEventData(DefaultIssue defaultIssue, IssueDto issueDto) {
+ return new HotspotChangedEvent.Builder()
+ .setKey(defaultIssue.key())
+ .setProjectKey(defaultIssue.projectKey())
+ .setStatus(defaultIssue.status())
+ .setResolution(defaultIssue.resolution())
+ .setUpdateDate(defaultIssue.updateDate())
+ .setAssignee(issueDto.getAssigneeLogin())
+ .setFilePath(issueDto.getFilePath())
+ .build();
+ }
+
}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/DoTransitionAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/DoTransitionAction.java
index f9db25c4734..134e68f7e21 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/DoTransitionAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/DoTransitionAction.java
@@ -119,7 +119,7 @@ public class DoTransitionAction implements IssuesWsAction {
IssueChangeContext context = issueChangeContextByUserBuilder(new Date(system2.now()), userSession.getUuid()).withRefreshMeasures().build();
transitionService.checkTransitionPermission(transitionKey, defaultIssue);
if (transitionService.doTransition(defaultIssue, context, transitionKey)) {
- BranchDto branch = issueUpdater.getBranch(session, defaultIssue, defaultIssue.projectUuid());
+ BranchDto branch = issueUpdater.getBranch(session, defaultIssue);
SearchResponseData response = issueUpdater.saveIssueAndPreloadSearchResponseData(session, defaultIssue, context, branch);
if (branch.getBranchType().equals(BRANCH) && response.getComponentByUuid(defaultIssue.projectUuid()) != null) {
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/IssueUpdater.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/IssueUpdater.java
index 85669dfdf57..680f3912abf 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/IssueUpdater.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/IssueUpdater.java
@@ -19,6 +19,7 @@
*/
package org.sonar.server.issue.ws;
+import java.util.Date;
import java.util.List;
import java.util.Optional;
import javax.annotation.Nullable;
@@ -70,7 +71,7 @@ public class IssueUpdater {
}
public SearchResponseData saveIssueAndPreloadSearchResponseData(DbSession dbSession, DefaultIssue issue, IssueChangeContext context) {
- BranchDto branch = getBranch(dbSession, issue, issue.projectUuid());
+ BranchDto branch = getBranch(dbSession, issue);
return saveIssueAndPreloadSearchResponseData(dbSession, issue, context, branch);
}
@@ -94,20 +95,24 @@ public class IssueUpdater {
return result;
}
- protected BranchDto getBranch(DbSession dbSession, DefaultIssue issue, @Nullable String projectUuid) {
+ public BranchDto getBranch(DbSession dbSession, DefaultIssue issue) {
String issueKey = issue.key();
- checkState(projectUuid != null, "Issue '%s' has no project", issueKey);
- BranchDto component = dbClient.branchDao().selectByUuid(dbSession, projectUuid).orElse(null);
- checkState(component != null, "Branch uuid '%s' for issue key '%s' cannot be found", projectUuid, issueKey);
- return component;
+ String componentUuid = issue.componentUuid();
+ checkState(componentUuid != null, "Component uuid for issue key '%s' cannot be null", issueKey);
+ Optional<ComponentDto> componentDto = dbClient.componentDao().selectByUuid(dbSession, componentUuid);
+ checkState(componentDto.isPresent(), "Component not found for issue with key '%s'", issueKey);
+ BranchDto branchDto = dbClient.branchDao().selectByUuid(dbSession, componentDto.get().branchUuid()).orElse(null);
+ checkState(branchDto != null, "Branch not found for issue with key '%s'", issueKey);
+ return branchDto;
}
private IssueDto doSaveIssue(DbSession session, DefaultIssue issue, IssueChangeContext context,
@Nullable RuleDto ruleDto, ComponentDto project, BranchDto branchDto) {
IssueDto issueDto = issueStorage.save(session, singletonList(issue)).iterator().next();
+ Date updateDate = issue.updateDate();
if (
// since this method is called after an update of the issue, date should never be null
- issue.updateDate() == null
+ updateDate == null
// name of rule is displayed in notification, rule must therefor be present
|| ruleDto == null
// notification are not supported on PRs
@@ -133,7 +138,7 @@ public class IssueUpdater {
.setBranchName(branchDto.isMain() ? null : branchDto.getKey())
.build())
.build()),
- new UserChange(issue.updateDate().getTime(), new User(author.getUuid(), author.getLogin(), author.getName())));
+ new UserChange(updateDate.getTime(), new User(author.getUuid(), author.getLogin(), author.getName())));
notificationService.scheduleForSending(notificationSerializer.serialize(notificationBuilder));
return issueDto;
}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SetSeverityAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SetSeverityAction.java
index a00dd2afa7d..d5ce9ebe9e1 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SetSeverityAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SetSeverityAction.java
@@ -115,7 +115,7 @@ public class SetSeverityAction implements IssuesWsAction {
IssueChangeContext context = issueChangeContextByUserBuilder(new Date(), userSession.getUuid()).withRefreshMeasures().build();
if (issueFieldsSetter.setManualSeverity(issue, severity, context)) {
- BranchDto branch = issueUpdater.getBranch(session, issue, issue.projectUuid());
+ BranchDto branch = issueUpdater.getBranch(session, issue);
SearchResponseData response = issueUpdater.saveIssueAndPreloadSearchResponseData(session, issue, context, branch);
if (branch.getBranchType().equals(BRANCH) && response.getComponentByUuid(issue.projectUuid()) != null) {
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SetTypeAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SetTypeAction.java
index 6807f29186d..dbaf40cfd1f 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SetTypeAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SetTypeAction.java
@@ -120,7 +120,7 @@ public class SetTypeAction implements IssuesWsAction {
IssueChangeContext context = issueChangeContextByUserBuilder(new Date(system2.now()), userSession.getUuid()).withRefreshMeasures().build();
if (issueFieldsSetter.setType(issue, ruleType, context)) {
- BranchDto branch = issueUpdater.getBranch(session, issue, issue.projectUuid());
+ BranchDto branch = issueUpdater.getBranch(session, issue);
SearchResponseData response = issueUpdater.saveIssueAndPreloadSearchResponseData(session, issue, context, branch);
if (branch.getBranchType().equals(BRANCH) && response.getComponentByUuid(issue.projectUuid()) != null) {
issueChangeEventService.distributeIssueChangeEvent(issue, null, ruleType.name(), null, branch,