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); } }
private boolean canExecuteTransition(DefaultIssue issue, String transitionKey) { return transitionService.listTransitions(issue) .stream() .map(Transition::key) .collect(MoreCollectors.toSet()) .contains(transitionKey); }
private void addActions() { actions.add(new org.sonar.server.issue.AssignAction(db.getDbClient(), issueFieldsSetter)); actions.add(new org.sonar.server.issue.SetSeverityAction(issueFieldsSetter, userSession)); actions.add(new org.sonar.server.issue.SetTypeAction(issueFieldsSetter, userSession)); actions.add(new org.sonar.server.issue.TransitionAction(new TransitionService(userSession, issueWorkflow))); actions.add(new org.sonar.server.issue.AddTagsAction(issueFieldsSetter)); actions.add(new org.sonar.server.issue.RemoveTagsAction(issueFieldsSetter)); actions.add(new org.sonar.server.issue.CommentAction(issueFieldsSetter)); }
@Override public boolean execute(Map<String, Object> properties, Context context) { DefaultIssue issue = context.issue(); String transition = transition(properties); return canExecuteTransition(issue, transition) && transitionService.doTransition(context.issue(), context.issueChangeContext(), transition(properties)); }
@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); }
private void loadActionsAndTransitions(SearchResponseData result, Set<SearchAdditionalField> fields) { if (fields.contains(ACTIONS) || fields.contains(TRANSITIONS)) { Map<String, ComponentDto> componentsByProjectUuid = result.getComponents() .stream() .filter(ComponentDto::isRootProject) .collect(MoreCollectors.uniqueIndex(ComponentDto::projectUuid)); for (IssueDto issueDto : result.getIssues()) { // so that IssueDto can be used. if (fields.contains(ACTIONS)) { ComponentDto project = componentsByProjectUuid.get(issueDto.getProjectUuid()); result.addActions(issueDto.getKey(), listAvailableActions(issueDto, project)); } if (fields.contains(TRANSITIONS) && !issueDto.isExternal()) { // TODO workflow and action engines must not depend on org.sonar.api.issue.Issue but on a generic interface DefaultIssue issue = issueDto.toDefaultIssue(); result.addTransitions(issue.key(), transitionService.listTransitions(issue)); } } } }
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); } }
@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"); } }
@Test public void list_transitions_returns_nothing_when_not_logged() { 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)); List<Transition> result = underTest.listTransitions(issue.toDefaultIssue()); assertThat(result).isEmpty(); }
@Override public boolean execute(Map<String, Object> properties, Context context) { DefaultIssue issue = context.issue(); String transition = transition(properties); return canExecuteTransition(issue, transition) && transitionService.doTransition(context.issue(), context.issueChangeContext(), transition(properties)); }
@Test public void list_transitions_returns_empty_list_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)); userSession.logIn().addProjectPermission(ISSUE_ADMIN, project); List<Transition> result = underTest.listTransitions(externalIssue.toDefaultIssue()); assertThat(result).isEmpty(); }
@Test public void list_transitions_returns_only_transitions_that_do_not_requires_issue_admin_permission() { 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)); userSession.logIn(); List<Transition> result = underTest.listTransitions(issue.toDefaultIssue()); assertThat(result).extracting(Transition::key).containsOnly("confirm", "resolve"); }
@Test public void list_transitions() { 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)); userSession.logIn().addProjectPermission(ISSUE_ADMIN, project); List<Transition> result = underTest.listTransitions(issue.toDefaultIssue()); assertThat(result).extracting(Transition::key).containsOnly("confirm", "resolve", "falsepositive", "wontfix"); }
private boolean canExecuteTransition(DefaultIssue issue, String transitionKey) { checkArgument(!issue.isFromExternalRuleEngine(), "No transition allowed on issue from externally define rule"); return transitionService.listTransitions(issue) .stream() .map(Transition::key) .collect(MoreCollectors.toSet()) .contains(transitionKey); }
private void loadActionsAndTransitions(Collector collector, SearchResponseData result) { if (collector.contains(ACTIONS) || collector.contains(TRANSITIONS)) { Map<String, ComponentDto> componentsByProjectUuid = result.getComponents() .stream() .filter(ComponentDto::isRootProject) .collect(MoreCollectors.uniqueIndex(ComponentDto::projectUuid)); for (IssueDto issueDto : result.getIssues()) { // so that IssueDto can be used. if (collector.contains(ACTIONS)) { ComponentDto project = componentsByProjectUuid.get(issueDto.getProjectUuid()); result.addActions(issueDto.getKey(), listAvailableActions(issueDto, project)); } if (collector.contains(TRANSITIONS) && !issueDto.isExternal()) { // TODO workflow and action engines must not depend on org.sonar.api.issue.Issue but on a generic interface DefaultIssue issue = issueDto.toDefaultIssue(); result.addTransitions(issue.key(), transitionService.listTransitions(issue)); } } } }