import java.util.Objects;
import java.util.Optional;
import java.util.Set;
+import java.util.stream.Stream;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.api.rule.RuleKey;
import static java.util.Collections.singleton;
import static java.util.Optional.ofNullable;
import static org.sonar.api.utils.DateUtils.formatDateTime;
+import static org.sonar.core.util.stream.MoreCollectors.toSet;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
public class ShowAction implements HotspotsWsAction {
RuleDefinitionDto rule = loadRule(dbSession, hotspot);
ShowWsResponse.Builder responseBuilder = ShowWsResponse.newBuilder();
+ Common.User.Builder userBuilder = Common.User.newBuilder();
formatHotspot(responseBuilder, hotspot);
- formatUsers(responseBuilder, users, hotspot);
+ formatHotspotAuthorAndAssignee(responseBuilder, userBuilder, users, hotspot);
formatComponents(components, responseBuilder);
formatRule(responseBuilder, rule);
- formatTextRange(hotspot, responseBuilder);
- formatChangeLogAndComments(dbSession, hotspot, components, responseBuilder);
+ formatTextRange(responseBuilder, hotspot);
+ FormattingContext formattingContext = formatChangeLogAndComments(dbSession, hotspot, users, components, responseBuilder);
+ formatUsers(responseBuilder, userBuilder, users, formattingContext);
writeProtobuf(responseBuilder.build(), request, response);
}
builder.setUpdateDate(formatDateTime(hotspot.getIssueUpdateDate()));
}
- private void formatUsers(ShowWsResponse.Builder responseBuilder, Users users, IssueDto hotspot) {
- Common.User.Builder userBuilder = Common.User.newBuilder();
+ private void formatHotspotAuthorAndAssignee(ShowWsResponse.Builder responseBuilder,
+ Common.User.Builder userBuilder, Users users, IssueDto hotspot) {
users.getAssignee().map(t -> userFormatter.formatUser(userBuilder, t)).ifPresent(responseBuilder::setAssignee);
Common.User author = users.getAuthor()
responseBuilder.setRule(ruleBuilder.build());
}
- private void formatTextRange(IssueDto hotspot, ShowWsResponse.Builder responseBuilder) {
+ private void formatTextRange(ShowWsResponse.Builder responseBuilder, IssueDto hotspot) {
textRangeFormatter.formatTextRange(hotspot, responseBuilder::setTextRange);
}
- private void formatChangeLogAndComments(DbSession dbSession, IssueDto hotspot, Components components, ShowWsResponse.Builder responseBuilder) {
+ private FormattingContext formatChangeLogAndComments(DbSession dbSession, IssueDto hotspot, Users users, Components components, ShowWsResponse.Builder responseBuilder) {
+ Set<UserDto> preloadedUsers = Stream.of(users.getAssignee(), users.getAuthor())
+ .filter(Optional::isPresent)
+ .map(Optional::get)
+ .collect(toSet());
Set<ComponentDto> preloadedComponents = ImmutableSet.of(components.project, components.component);
FormattingContext formattingContext = issueChangeSupport
- .newFormattingContext(dbSession, singleton(hotspot), Load.ALL, ImmutableSet.of(), preloadedComponents);
+ .newFormattingContext(dbSession, singleton(hotspot), Load.ALL, preloadedUsers, preloadedComponents);
issueChangeSupport.formatChangelog(hotspot, formattingContext)
.forEach(responseBuilder::addChangelog);
issueChangeSupport.formatComments(hotspot, Common.Comment.newBuilder(), formattingContext)
.forEach(responseBuilder::addComment);
+
+ return formattingContext;
+ }
+
+ private void formatUsers(ShowWsResponse.Builder responseBuilder, Common.User.Builder userBuilder, Users users, FormattingContext formattingContext) {
+ Stream.concat(
+ Stream.of(users.getAssignee(), users.getAuthor())
+ .filter(Optional::isPresent)
+ .map(Optional::get),
+ formattingContext.getUsers().stream())
+ .distinct()
+ .map(user -> userFormatter.formatUser(userBuilder, user))
+ .forEach(responseBuilder::addUsers);
}
private RuleDefinitionDto loadRule(DbSession dbSession, IssueDto hotspot) {
import java.util.stream.IntStream;
import java.util.stream.Stream;
import javax.annotation.Nullable;
+import org.assertj.core.groups.Tuple;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.sonar.db.rule.RuleDefinitionDto;
import org.sonar.db.rule.RuleTesting;
import org.sonar.db.user.UserDto;
+import org.sonar.db.user.UserTesting;
import org.sonar.server.es.EsTester;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.NotFoundException;
import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
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.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anySet;
import static org.mockito.ArgumentMatchers.argThat;
ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
RuleDefinitionDto rule = newRule(SECURITY_HOTSPOT);
IssueDto hotspot = dbTester.issues().insertIssue(newHotspot(project, file, rule));
+ mockChangelogAndCommentsFormattingContext();
Hotspots.ShowWsResponse response = newRequest(hotspot)
.executeProtobuf(Hotspots.ShowWsResponse.class);
ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
RuleDefinitionDto rule = newRule(SECURITY_HOTSPOT);
IssueDto hotspot = dbTester.issues().insertIssue(newHotspot(project, file, rule));
+ mockChangelogAndCommentsFormattingContext();
Hotspots.ShowWsResponse response = newRequest(hotspot)
.executeProtobuf(Hotspots.ShowWsResponse.class);
ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
RuleDefinitionDto rule = newRule(SECURITY_HOTSPOT);
IssueDto hotspot = dbTester.issues().insertIssue(newHotspot(project, file, rule).setStatus(status).setResolution(resolution));
+ mockChangelogAndCommentsFormattingContext();
Hotspots.ShowWsResponse response = newRequest(hotspot)
.executeProtobuf(Hotspots.ShowWsResponse.class);
ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
RuleDefinitionDto rule = newRule(SECURITY_HOTSPOT);
IssueDto hotspot = dbTester.issues().insertIssue(newHotspot(project, file, rule));
+ mockChangelogAndCommentsFormattingContext();
Hotspots.ShowWsResponse response = newRequest(hotspot)
.executeProtobuf(Hotspots.ShowWsResponse.class);
RuleDefinitionDto rule = newRule(SECURITY_HOTSPOT);
IssueDto hotspot = dbTester.issues().insertIssue(newHotspot(project, file, rule)
.setLocations(DbIssues.Locations.newBuilder().build()));
+ mockChangelogAndCommentsFormattingContext();
Hotspots.ShowWsResponse response = newRequest(hotspot)
.executeProtobuf(Hotspots.ShowWsResponse.class);
.setEndOffset(endOffset)
.build())
.build()));
+ mockChangelogAndCommentsFormattingContext();
Hotspots.ShowWsResponse response = newRequest(hotspot)
.executeProtobuf(Hotspots.ShowWsResponse.class);
+
assertThat(response.hasTextRange()).isTrue();
Common.TextRange textRange = response.getTextRange();
assertThat(textRange.getStartLine()).isEqualTo(startLine);
RuleDefinitionDto rule = newRule(SECURITY_HOTSPOT);
IssueDto hotspot = dbTester.issues().insertIssue(newHotspot(project, file, rule)
.setAssigneeUuid(randomAlphabetic(10)));
+ mockChangelogAndCommentsFormattingContext();
Hotspots.ShowWsResponse response = newRequest(hotspot)
.executeProtobuf(Hotspots.ShowWsResponse.class);
UserDto assignee = dbTester.users().insertUser();
IssueDto hotspot = dbTester.issues().insertIssue(newHotspot(project, file, rule)
.setAssigneeUuid(assignee.getUuid()));
+ mockChangelogAndCommentsFormattingContext();
Hotspots.ShowWsResponse response = newRequest(hotspot)
.executeProtobuf(Hotspots.ShowWsResponse.class);
UserDto assignee = dbTester.users().insertUser(t -> t.setEmail(null));
IssueDto hotspot = dbTester.issues().insertIssue(newHotspot(project, file, rule)
.setAssigneeUuid(assignee.getUuid()));
+ mockChangelogAndCommentsFormattingContext();
Hotspots.ShowWsResponse response = newRequest(hotspot)
.executeProtobuf(Hotspots.ShowWsResponse.class);
UserDto assignee = dbTester.users().insertUser(t -> t.setActive(false));
IssueDto hotspot = dbTester.issues().insertIssue(newHotspot(project, file, rule)
.setAssigneeUuid(assignee.getUuid()));
+ mockChangelogAndCommentsFormattingContext();
Hotspots.ShowWsResponse response = newRequest(hotspot)
.executeProtobuf(Hotspots.ShowWsResponse.class);
assertThat(response.getAssignee().getActive()).isFalse();
+ assertThat(response.getUsersList()).hasSize(1);
+ assertThat(response.getUsersList().iterator().next().getActive()).isFalse();
}
@Test
String authorLogin = randomAlphabetic(10);
IssueDto hotspot = dbTester.issues().insertIssue(newHotspot(project, file, rule)
.setAuthorLogin(authorLogin));
+ mockChangelogAndCommentsFormattingContext();
Hotspots.ShowWsResponse response = newRequest(hotspot)
.executeProtobuf(Hotspots.ShowWsResponse.class);
assertThat(wsAuthor.hasName()).isFalse();
assertThat(wsAuthor.hasActive()).isFalse();
assertThat(wsAuthor.hasAvatar()).isFalse();
+ assertThat(response.getUsersList()).isEmpty();
}
@Test
UserDto author = dbTester.users().insertUser();
IssueDto hotspot = dbTester.issues().insertIssue(newHotspot(project, file, rule)
.setAuthorLogin(author.getLogin()));
+ mockChangelogAndCommentsFormattingContext();
Hotspots.ShowWsResponse response = newRequest(hotspot)
.executeProtobuf(Hotspots.ShowWsResponse.class);
assertThat(wsAuthor.getName()).isEqualTo(author.getName());
assertThat(wsAuthor.getActive()).isEqualTo(author.isActive());
assertThat(wsAuthor.getAvatar()).isEqualTo(avatarResolver.create(author));
+ assertThat(response.getUsersList()).hasSize(1);
+ User wsAuthorFromList = response.getUsersList().iterator().next();
+ assertThat(wsAuthorFromList.getLogin()).isEqualTo(author.getLogin());
+ assertThat(wsAuthorFromList.getName()).isEqualTo(author.getName());
+ assertThat(wsAuthorFromList.getActive()).isEqualTo(author.isActive());
+ assertThat(wsAuthorFromList.getAvatar()).isEqualTo(avatarResolver.create(author));
}
@Test
UserDto author = dbTester.users().insertUser(t -> t.setEmail(null));
IssueDto hotspot = dbTester.issues().insertIssue(newHotspot(project, file, rule)
.setAuthorLogin(author.getLogin()));
+ mockChangelogAndCommentsFormattingContext();
Hotspots.ShowWsResponse response = newRequest(hotspot)
.executeProtobuf(Hotspots.ShowWsResponse.class);
assertThat(response.getAuthor().hasAvatar()).isFalse();
+ assertThat(response.getUsersList()).hasSize(1);
+ assertThat(response.getUsersList().iterator().next().hasAvatar()).isFalse();
}
@Test
UserDto author = dbTester.users().insertUser(t -> t.setActive(false));
IssueDto hotspot = dbTester.issues().insertIssue(newHotspot(project, file, rule)
.setAuthorLogin(author.getLogin()));
+ mockChangelogAndCommentsFormattingContext();
Hotspots.ShowWsResponse response = newRequest(hotspot)
.executeProtobuf(Hotspots.ShowWsResponse.class);
.setLocations(DbIssues.Locations.newBuilder()
.setTextRange(DbCommons.TextRange.newBuilder().build())
.build()));
+ mockChangelogAndCommentsFormattingContext();
Hotspots.ShowWsResponse response = newRequest(hotspot)
.executeProtobuf(Hotspots.ShowWsResponse.class);
.setLocations(DbIssues.Locations.newBuilder()
.setTextRange(DbCommons.TextRange.newBuilder().build())
.build()));
+ mockChangelogAndCommentsFormattingContext();
Hotspots.ShowWsResponse response = newRequest(hotspot)
.executeProtobuf(Hotspots.ShowWsResponse.class);
.setLocations(DbIssues.Locations.newBuilder()
.setTextRange(DbCommons.TextRange.newBuilder().build())
.build()));
+ mockChangelogAndCommentsFormattingContext();
Hotspots.ShowWsResponse response = newRequest(hotspot)
.executeProtobuf(Hotspots.ShowWsResponse.class);
.setLocations(DbIssues.Locations.newBuilder()
.setTextRange(DbCommons.TextRange.newBuilder().build())
.build()));
+ mockChangelogAndCommentsFormattingContext();
Hotspots.ShowWsResponse response = newRequest(hotspot)
.executeProtobuf(Hotspots.ShowWsResponse.class);
.setLocations(DbIssues.Locations.newBuilder()
.setTextRange(DbCommons.TextRange.newBuilder().build())
.build()));
+ mockChangelogAndCommentsFormattingContext();
Hotspots.ShowWsResponse response = newRequest(hotspot)
.executeProtobuf(Hotspots.ShowWsResponse.class);
.setLocations(DbIssues.Locations.newBuilder()
.setTextRange(DbCommons.TextRange.newBuilder().build())
.build()));
- FormattingContext formattingContext = Mockito.mock(FormattingContext.class);
List<Common.Changelog> changelog = IntStream.range(0, 1 + new Random().nextInt(12))
.mapToObj(i -> Common.Changelog.newBuilder().setUser("u" + i).build())
.collect(Collectors.toList());
List<Common.Comment> comments = IntStream.range(0, 1 + new Random().nextInt(12))
.mapToObj(i -> Common.Comment.newBuilder().setKey("u" + i).build())
.collect(Collectors.toList());
- when(issueChangeSupport.newFormattingContext(any(), any(), any(), anySet(), anySet())).thenReturn(formattingContext);
+ FormattingContext formattingContext = mockChangelogAndCommentsFormattingContext();
when(issueChangeSupport.formatChangelog(any(), any())).thenReturn(changelog.stream());
when(issueChangeSupport.formatComments(any(), any(), any())).thenReturn(comments.stream());
verify(issueChangeSupport).formatComments(argThat(new IssueDtoArgumentMatcher(hotspot)), any(Common.Comment.Builder.class), eq(formattingContext));
}
- public void verifyRule(Hotspots.Rule wsRule, RuleDefinitionDto dto) {
+ @Test
+ public void returns_user_details_of_users_from_ChangelogAndComments() {
+ ComponentDto project = dbTester.components().insertPublicProject();
+ userSessionRule.registerComponents(project);
+ RuleDefinitionDto rule = newRule(SECURITY_HOTSPOT);
+ ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
+ IssueDto hotspot = dbTester.issues().insertIssue(newHotspot(project, file, rule));
+ FormattingContext formattingContext = mockChangelogAndCommentsFormattingContext();
+ Set<UserDto> changeLogAndCommentsUsers = IntStream.range(0, 1 + RANDOM.nextInt(14))
+ .mapToObj(i -> UserTesting.newUserDto())
+ .collect(Collectors.toSet());
+ when(formattingContext.getUsers()).thenReturn(changeLogAndCommentsUsers);
+
+ Hotspots.ShowWsResponse response = newRequest(hotspot)
+ .executeProtobuf(Hotspots.ShowWsResponse.class);
+
+ assertThat(response.getUsersList())
+ .extracting(User::getLogin, User::getName, User::getActive)
+ .containsExactlyInAnyOrder(
+ changeLogAndCommentsUsers.stream()
+ .map(t -> tuple(t.getLogin(), t.getName(), t.isActive()))
+ .toArray(Tuple[]::new));
+ }
+
+ @Test
+ public void returns_user_of_users_from_ChangelogAndComments_and_assignee_and_author() {
+ ComponentDto project = dbTester.components().insertPublicProject();
+ userSessionRule.registerComponents(project);
+ RuleDefinitionDto rule = newRule(SECURITY_HOTSPOT);
+ ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
+ UserDto author = dbTester.users().insertUser();
+ UserDto assignee = dbTester.users().insertUser();
+ IssueDto hotspot = dbTester.issues().insertIssue(newHotspot(project, file, rule)
+ .setAuthorLogin(author.getLogin())
+ .setAssigneeUuid(assignee.getUuid()));
+ FormattingContext formattingContext = mockChangelogAndCommentsFormattingContext();
+ Set<UserDto> changeLogAndCommentsUsers = IntStream.range(0, 1 + RANDOM.nextInt(14))
+ .mapToObj(i -> UserTesting.newUserDto())
+ .collect(Collectors.toSet());
+ when(formattingContext.getUsers()).thenReturn(changeLogAndCommentsUsers);
+
+ Hotspots.ShowWsResponse response = newRequest(hotspot)
+ .executeProtobuf(Hotspots.ShowWsResponse.class);
+
+ assertThat(response.getUsersList())
+ .extracting(User::getLogin, User::getName, User::getActive)
+ .containsExactlyInAnyOrder(
+ Stream.concat(
+ Stream.of(author, assignee),
+ changeLogAndCommentsUsers.stream())
+ .map(t -> tuple(t.getLogin(), t.getName(), t.isActive()))
+ .toArray(Tuple[]::new));
+ }
+
+ @Test
+ public void do_not_duplicate_user_if_author_assignee_ChangeLogComment_user() {
+ ComponentDto project = dbTester.components().insertPublicProject();
+ userSessionRule.registerComponents(project);
+ RuleDefinitionDto rule = newRule(SECURITY_HOTSPOT);
+ ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
+ UserDto author = dbTester.users().insertUser();
+ IssueDto hotspot = dbTester.issues().insertIssue(newHotspot(project, file, rule)
+ .setAuthorLogin(author.getLogin())
+ .setAssigneeUuid(author.getUuid()));
+ FormattingContext formattingContext = mockChangelogAndCommentsFormattingContext();
+ when(formattingContext.getUsers()).thenReturn(ImmutableSet.of(author));
+
+ Hotspots.ShowWsResponse response = newRequest(hotspot)
+ .executeProtobuf(Hotspots.ShowWsResponse.class);
+
+ assertThat(response.getUsersList())
+ .extracting(User::getLogin, User::getName, User::getActive)
+ .containsOnly(tuple(author.getLogin(), author.getName(), author.isActive()));
+ }
+
+ private FormattingContext mockChangelogAndCommentsFormattingContext() {
+ FormattingContext formattingContext = Mockito.mock(FormattingContext.class);
+ when(issueChangeSupport.newFormattingContext(any(), any(), any(), anySet(), anySet())).thenReturn(formattingContext);
+ return formattingContext;
+ }
+
+ private void verifyRule(Hotspots.Rule wsRule, RuleDefinitionDto dto) {
assertThat(wsRule.getKey()).isEqualTo(dto.getKey().toString());
assertThat(wsRule.getName()).isEqualTo(dto.getName());
assertThat(wsRule.getSecurityCategory()).isEqualTo(SQCategory.OTHERS.getKey());
FormattingContext formattingContext = underTest.newFormattingContext(dbTester.getSession(), singleton(issue), Load.CHANGE_LOG);
+ assertThat(formattingContext.getUsers())
+ .extracting(UserDto::getUuid)
+ .containsExactlyInAnyOrder(user1.getUuid(), user2.getUuid());
assertThat(formattingContext.getUserByUuid(user1.getUuid())).isNotEmpty();
assertThat(formattingContext.getUserByUuid(user2.getUuid())).isNotEmpty();
assertThat(formattingContext.getUserByUuid(user3.getUuid())).isEmpty();
FormattingContext formattingContext = underTest.newFormattingContext(dbTester.getSession(), singleton(issue), Load.COMMENTS);
+ assertThat(formattingContext.getUsers())
+ .extracting(UserDto::getUuid)
+ .containsExactlyInAnyOrder(user1.getUuid(), user2.getUuid());
assertThat(formattingContext.getUserByUuid(user1.getUuid())).isNotEmpty();
assertThat(formattingContext.getUserByUuid(user2.getUuid())).isNotEmpty();
assertThat(formattingContext.getUserByUuid(user3.getUuid())).isEmpty();
FormattingContext formattingContext = underTest.newFormattingContext(dbTester.getSession(), singleton(issue), Load.ALL);
+ assertThat(formattingContext.getUsers())
+ .extracting(UserDto::getUuid)
+ .containsExactlyInAnyOrder(user1.getUuid(), user2.getUuid(), user4.getUuid());
assertThat(formattingContext.getUserByUuid(user1.getUuid())).isNotEmpty();
assertThat(formattingContext.getUserByUuid(user2.getUuid())).isNotEmpty();
assertThat(formattingContext.getUserByUuid(user3.getUuid())).isEmpty();
// no users are preloaded
FormattingContext formattingContext = underTest.newFormattingContext(dbTester.getSession(), singleton(issue), Load.ALL,
emptySet(), emptySet());
+ assertThat(formattingContext.getUsers())
+ .extracting(UserDto::getUuid)
+ .containsExactlyInAnyOrder(user1.getUuid(), user2.getUuid(), user3.getUuid(), user4.getUuid());
assertThat(formattingContext.getUserByUuid(user1.getUuid()).get().getEmail()).isNotEqualTo(user1.getEmail());
assertThat(formattingContext.getUserByUuid(user2.getUuid()).get().getEmail()).isNotEqualTo(user2.getEmail());
assertThat(formattingContext.getUserByUuid(user3.getUuid()).get().getEmail()).isNotEqualTo(user3.getEmail());
// some users are preloaded
formattingContext = underTest.newFormattingContext(dbTester.getSession(), singleton(issue), Load.ALL,
ImmutableSet.of(user1, user4), emptySet());
+ assertThat(formattingContext.getUsers())
+ .extracting(UserDto::getUuid)
+ .containsExactlyInAnyOrder(user1.getUuid(), user2.getUuid(), user3.getUuid(), user4.getUuid());
assertThat(formattingContext.getUserByUuid(user1.getUuid()).get().getEmail()).isEqualTo(user1.getEmail());
assertThat(formattingContext.getUserByUuid(user2.getUuid()).get().getEmail()).isNotEqualTo(user2.getEmail());
assertThat(formattingContext.getUserByUuid(user3.getUuid()).get().getEmail()).isNotEqualTo(user3.getEmail());
// all users are preloaded
formattingContext = underTest.newFormattingContext(dbTester.getSession(), singleton(issue), Load.ALL,
ImmutableSet.of(user1, user2, user3, user4), emptySet());
+ assertThat(formattingContext.getUsers())
+ .extracting(UserDto::getUuid)
+ .containsExactlyInAnyOrder(user1.getUuid(), user2.getUuid(), user3.getUuid(), user4.getUuid());
assertThat(formattingContext.getUserByUuid(user1.getUuid()).get().getEmail()).isEqualTo(user1.getEmail());
assertThat(formattingContext.getUserByUuid(user2.getUuid()).get().getEmail()).isEqualTo(user2.getEmail());
assertThat(formattingContext.getUserByUuid(user3.getUuid()).get().getEmail()).isEqualTo(user3.getEmail());