private BulkChangeResult executeBulkChange(DbSession dbSession, Request request) { BulkChangeData bulkChangeData = new BulkChangeData(dbSession, request); BulkChangeResult result = new BulkChangeResult(bulkChangeData.issues.size()); IssueChangeContext issueChangeContext = IssueChangeContext.createUser(new Date(system2.now()), userSession.getUuid()); List<DefaultIssue> items = bulkChangeData.issues.stream() .filter(bulkChange(issueChangeContext, bulkChangeData, result)) .collect(MoreCollectors.toList()); issueStorage.save(dbSession, items); refreshLiveMeasures(dbSession, bulkChangeData, result); Set<String> assigneeUuids = items.stream().map(DefaultIssue::assignee).filter(Objects::nonNull).collect(toSet()); Map<String, UserDto> userDtoByUuid = dbClient.userDao().selectByUuids(dbSession, assigneeUuids).stream().collect(toMap(UserDto::getUuid, u -> u)); String authorUuid = requireNonNull(userSession.getUuid(), "User uuid cannot be null"); UserDto author = dbClient.userDao().selectByUuid(dbSession, authorUuid); checkState(author != null, "User with uuid '%s' does not exist"); items.forEach(sendNotification(bulkChangeData, userDtoByUuid, author)); return result; }
@Before public void setUp() throws Exception { workflow.start(); when(context.issue()).thenReturn(issue); when(context.issueChangeContext()).thenReturn(IssueChangeContext.createUser(new Date(), "user_uuid")); }
@Test public void test_end_user_context() { Date now = new Date(); IssueChangeContext context = IssueChangeContext.createUser(now, "user_uuid"); assertThat(context.scan()).isFalse(); assertThat(context.userUuid()).isEqualTo("user_uuid"); assertThat(context.date()).isEqualTo(now); } }
private SearchResponseData doTransition(DbSession session, IssueDto issueDto, String transitionKey) { DefaultIssue defaultIssue = issueDto.toDefaultIssue(); IssueChangeContext context = IssueChangeContext.createUser(new Date(system2.now()), userSession.getUuid()); transitionService.checkTransitionPermission(transitionKey, defaultIssue); if (transitionService.doTransition(defaultIssue, context, transitionKey)) { return issueUpdater.saveIssueAndPreloadSearchResponseData(session, defaultIssue, context, null, true); } return new SearchResponseData(issueDto); } }
@Override public void onIssue(Component component, DefaultIssue issue) { if (component.getType() != Component.Type.FILE || component.getUuid().equals(issue.componentUuid())) { return; } Optional<OriginalFile> originalFileOptional = movedFilesRepository.getOriginalFile(component); checkState(originalFileOptional.isPresent(), "Issue %s for component %s has a different component key but no original file exist in MovedFilesRepository", issue, component); OriginalFile originalFile = originalFileOptional.get(); checkState(originalFile.getUuid().equals(issue.componentUuid()), "Issue %s doesn't belong to file %s registered as original file of current file %s", issue, originalFile.getUuid(), component); // changes the issue's component uuid, add a change and set issue as changed to enforce it is persisted to DB issueUpdater.setIssueMoved(issue, component.getUuid(), IssueChangeContext.createUser(new Date(analysisMetadataHolder.getAnalysisDate()), null)); // other fields (such as module, modulePath, componentKey) are read-only and set/reset for consistency only issue.setComponentKey(component.getKey()); issue.setModuleUuid(null); issue.setModuleUuidPath(null); } }
private SearchResponseData setTags(String issueKey, List<String> tags) { userSession.checkLoggedIn(); try (DbSession session = dbClient.openSession(false)) { IssueDto issueDto = issueFinder.getByKey(session, issueKey); DefaultIssue issue = issueDto.toDefaultIssue(); IssueChangeContext context = IssueChangeContext.createUser(new Date(), userSession.getUuid()); if (issueFieldsSetter.setTags(issue, tags, context)) { return issueUpdater.saveIssueAndPreloadSearchResponseData(session, issue, context, null, false); } return new SearchResponseData(issueDto); } }
private SearchResponseData assign(String issueKey, @Nullable String login) { try (DbSession dbSession = dbClient.openSession(false)) { IssueDto issueDto = issueFinder.getByKey(dbSession, issueKey); DefaultIssue issue = issueDto.toDefaultIssue(); checkArgument(issue.type() != RuleType.SECURITY_HOTSPOT,"It is not allowed to assign a security hotspot"); UserDto user = getUser(dbSession, login); if (user != null) { checkMembership(dbSession, issueDto, user); } IssueChangeContext context = IssueChangeContext.createUser(new Date(system2.now()), userSession.getUuid()); if (issueFieldsSetter.assign(issue, user, context)) { return issueUpdater.saveIssueAndPreloadSearchResponseData(dbSession, issue, context, null, false); } return new SearchResponseData(issueDto); } }
private SearchResponseData setType(DbSession session, String issueKey, String severity) { IssueDto issueDto = issueFinder.getByKey(session, issueKey); DefaultIssue issue = issueDto.toDefaultIssue(); userSession.checkComponentUuidPermission(ISSUE_ADMIN, issue.projectUuid()); IssueChangeContext context = IssueChangeContext.createUser(new Date(), userSession.getUuid()); if (issueFieldsSetter.setManualSeverity(issue, severity, context)) { return issueUpdater.saveIssueAndPreloadSearchResponseData(session, issue, context, null, true); } return new SearchResponseData(issueDto); } }
private SearchResponseData setType(DbSession session, String issueKey, RuleType ruleType) { IssueDto issueDto = issueFinder.getByKey(session, issueKey); DefaultIssue issue = issueDto.toDefaultIssue(); if (issue.isFromHotspot()) { throw new IllegalArgumentException("Changing type of a security hotspot is not permitted"); } userSession.checkComponentUuidPermission(ISSUE_ADMIN, issue.projectUuid()); IssueChangeContext context = IssueChangeContext.createUser(new Date(system2.now()), userSession.getUuid()); if (issueFieldsSetter.setType(issue, ruleType, context)) { return issueUpdater.saveIssueAndPreloadSearchResponseData(session, issue, context, null, true); } return new SearchResponseData(issueDto); }
private Collection<? extends DefaultIssue> migrateIssuesToTheRoot(List<DefaultIssue> issuesOnModule, String modulePath) { for (DefaultIssue i : issuesOnModule) { // changes the issue's component uuid, add a change and set issue as changed to enforce it is persisted to DB IssueChangeContext context = IssueChangeContext.createUser(new Date(analysisMetadataHolder.getAnalysisDate()), null); if (StringUtils.isNotBlank(modulePath)) { issueUpdater.setMessage(i, "[" + modulePath + "] " + i.getMessage(), context); } issueUpdater.setIssueMoved(i, component.getUuid(), context); // other fields (such as module, modulePath, componentKey) are read-only and set/reset for consistency only i.setComponentKey(component.getKey()); i.setModuleUuid(null); i.setModuleUuidPath(null); } return issuesOnModule; } }
@Test public void set_severity() { IssueDto issueDto = newIssue().setSeverity(MAJOR); DefaultIssue issue = issueDto.toDefaultIssue(); setUserWithBrowseAndAdministerIssuePermission(issueDto); BulkChangeAction.ActionContext context = new BulkChangeAction.ActionContext(issue, IssueChangeContext.createUser(NOW, userSession.getUuid()), null); action.execute(ImmutableMap.of("severity", MINOR), context); assertThat(issue.severity()).isEqualTo(MINOR); assertThat(issue.isChanged()).isTrue(); assertThat(issue.manualSeverity()).isTrue(); assertThat(issue.updateDate()).isEqualTo(NOW); assertThat(issue.mustSendNotifications()).isTrue(); Map<String, FieldDiffs.Diff> change = issue.currentChange().diffs(); assertThat(change.get("severity").newValue()).isEqualTo(MINOR); assertThat(change.get("severity").oldValue()).isEqualTo(MAJOR); }
@Test public void set_type() { IssueDto issueDto = newIssue().setType(BUG); DefaultIssue issue = issueDto.toDefaultIssue(); setUserWithBrowseAndAdministerIssuePermission(issueDto); action.execute(ImmutableMap.of("type", VULNERABILITY.name()), new BulkChangeAction.ActionContext(issue, IssueChangeContext.createUser(NOW, userSession.getUuid()), null)); assertThat(issue.type()).isEqualTo(VULNERABILITY); assertThat(issue.isChanged()).isTrue(); assertThat(issue.updateDate()).isEqualTo(NOW); assertThat(issue.mustSendNotifications()).isFalse(); Map<String, FieldDiffs.Diff> change = issue.currentChange().diffs(); assertThat(change.get("type").newValue()).isEqualTo(VULNERABILITY); assertThat(change.get("type").oldValue()).isEqualTo(BUG); }
@Override public void handle(Request request, Response response) { userSession.checkLoggedIn(); AddCommentRequest wsRequest = toWsRequest(request); try (DbSession dbSession = dbClient.openSession(false)) { IssueDto issueDto = issueFinder.getByKey(dbSession, wsRequest.getIssue()); IssueChangeContext context = IssueChangeContext.createUser(new Date(system2.now()), userSession.getUuid()); DefaultIssue defaultIssue = issueDto.toDefaultIssue(); issueFieldsSetter.addComment(defaultIssue, wsRequest.getText(), context); SearchResponseData preloadedSearchResponseData = issueUpdater.saveIssueAndPreloadSearchResponseData(dbSession, defaultIssue, context, wsRequest.getText(), false); responseWriter.write(defaultIssue.key(), preloadedSearchResponseData, request, response); } }
@Test public void do_transition() { ComponentDto project = db.components().insertPrivateProject(); ComponentDto file = db.components().insertComponent(newFileDto(project)); RuleDefinitionDto rule = db.rules().insert(); IssueDto issue = db.issues().insert(rule, project, file, i -> i.setStatus(STATUS_OPEN).setResolution(null)); DefaultIssue defaultIssue = issue.toDefaultIssue(); boolean result = underTest.doTransition(defaultIssue, IssueChangeContext.createUser(new Date(), "user_uuid"), "confirm"); assertThat(result).isTrue(); assertThat(defaultIssue.status()).isEqualTo(STATUS_CONFIRMED); }
@Test public void update_issue() { DefaultIssue issue = db.issues().insertIssue(i -> i.setSeverity(MAJOR)).toDefaultIssue(); IssueChangeContext context = IssueChangeContext.createUser(new Date(), "user_uuid"); issueFieldsSetter.setSeverity(issue, BLOCKER, context); underTest.saveIssue(db.getSession(), issue, context, null); IssueDto issueReloaded = dbClient.issueDao().selectByKey(db.getSession(), issue.key()).get(); assertThat(issueReloaded.getSeverity()).isEqualTo(BLOCKER); }
@Test public void verify_notification_on_branch() { RuleDto rule = db.rules().insertRule(); ComponentDto project = db.components().insertMainBranch(); ComponentDto branch = db.components().insertProjectBranch(project); ComponentDto file = db.components().insertComponent(newFileDto(branch)); RuleType randomTypeExceptHotspot = RuleType.values()[nextInt(RuleType.values().length - 1)]; DefaultIssue issue = db.issues().insertIssue(IssueTesting.newIssue(rule.getDefinition(), branch, file) .setType(randomTypeExceptHotspot)).setSeverity(MAJOR).toDefaultIssue(); IssueChangeContext context = IssueChangeContext.createUser(new Date(), "user_uuid"); issueFieldsSetter.setSeverity(issue, BLOCKER, context); underTest.saveIssue(db.getSession(), issue, context, "increase severity"); verify(notificationManager).scheduleForSending(notificationArgumentCaptor.capture()); IssueChangeNotification issueChangeNotification = notificationArgumentCaptor.getValue(); assertThat(issueChangeNotification.getFieldValue("key")).isEqualTo(issue.key()); assertThat(issueChangeNotification.getFieldValue("projectKey")).isEqualTo(project.getDbKey()); assertThat(issueChangeNotification.getFieldValue("projectName")).isEqualTo(project.name()); assertThat(issueChangeNotification.getFieldValue("branch")).isEqualTo(branch.getBranch()); }
@Test public void saveIssue_populates_specified_SearchResponseData_with_no_rule_but_with_project_and_component_if_rule_is_removed() { RuleDto rule = db.rules().insertRule(r -> r.setStatus(RuleStatus.REMOVED)); ComponentDto project = db.components().insertPrivateProject(); ComponentDto file = db.components().insertComponent(newFileDto(project)); IssueDto issueDto = IssueTesting.newIssue(rule.getDefinition(), project, file); DefaultIssue issue = db.issues().insertIssue(issueDto).setSeverity(MAJOR).toDefaultIssue(); IssueChangeContext context = IssueChangeContext.createUser(new Date(), "user_uuid"); issueFieldsSetter.setSeverity(issue, BLOCKER, context); SearchResponseData preloadedSearchResponseData = underTest.saveIssueAndPreloadSearchResponseData(db.getSession(), issue, context, null, false); assertThat(preloadedSearchResponseData.getIssues()) .hasSize(1); assertThat(preloadedSearchResponseData.getIssues().iterator().next()) .isNotSameAs(issueDto); assertThat(preloadedSearchResponseData.getRules()).isNullOrEmpty(); assertThat(preloadedSearchResponseData.getComponents()) .extracting(ComponentDto::uuid) .containsOnly(project.uuid(), file.uuid()); }
@Test public void verify_notification_when_issue_is_linked_on_removed_rule() { RuleDto rule = db.rules().insertRule(r -> r.setStatus(RuleStatus.REMOVED)); ComponentDto project = db.components().insertPrivateProject(); ComponentDto file = db.components().insertComponent(newFileDto(project)); RuleType randomTypeExceptHotspot = RuleType.values()[nextInt(RuleType.values().length - 1)]; DefaultIssue issue = db.issues().insertIssue(IssueTesting.newIssue(rule.getDefinition(), project, file) .setType(randomTypeExceptHotspot)).setSeverity(MAJOR).toDefaultIssue(); IssueChangeContext context = IssueChangeContext.createUser(new Date(), "user_uuid"); issueFieldsSetter.setSeverity(issue, BLOCKER, context); underTest.saveIssue(db.getSession(), issue, context, null); verify(notificationManager).scheduleForSending(notificationArgumentCaptor.capture()); assertThat(notificationArgumentCaptor.getValue().getFieldValue("ruleName")).isNull(); }
@Test public void verify_no_notification_on_hotspot() { UserDto assignee = db.users().insertUser(); RuleDto rule = db.rules().insertRule(); ComponentDto project = db.components().insertPrivateProject(); ComponentDto file = db.components().insertComponent(newFileDto(project)); DefaultIssue issue = db.issues().insertIssue(IssueTesting.newIssue(rule.getDefinition(), project, file) .setType(RuleType.SECURITY_HOTSPOT)) .setSeverity(MAJOR) .setAssigneeUuid(assignee.getUuid()) .toDefaultIssue(); UserDto changeAuthor = db.users().insertUser(); IssueChangeContext context = IssueChangeContext.createUser(new Date(), changeAuthor.getUuid()); issueFieldsSetter.setSeverity(issue, BLOCKER, context); underTest.saveIssue(db.getSession(), issue, context, "increase severity"); verify(notificationManager, never()).scheduleForSending(any()); }
@Test public void do_transition_fail_on_external_issue() { ComponentDto project = db.components().insertPrivateProject(); ComponentDto file = db.components().insertComponent(newFileDto(project)); RuleDefinitionDto externalRule = db.rules().insert(r -> r.setIsExternal(true)); IssueDto externalIssue = db.issues().insert(externalRule, project, file, i -> i.setStatus(STATUS_OPEN).setResolution(null)); DefaultIssue defaultIssue = externalIssue.toDefaultIssue(); expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("Transition is not allowed on issues imported from external rule engines"); underTest.doTransition(defaultIssue, IssueChangeContext.createUser(new Date(), "user_uuid"), "confirm"); } }