]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-23142 Fix SSF (#12040)
authorAnita Stanisz <106669481+anita-stanisz-sonarsource@users.noreply.github.com>
Fri, 11 Oct 2024 15:03:44 +0000 (17:03 +0200)
committersonartech <sonartech@sonarsource.com>
Fri, 11 Oct 2024 20:02:44 +0000 (20:02 +0000)
29 files changed:
server/sonar-webserver-webapi/src/it/java/org/sonar/server/issue/ws/AddCommentActionIT.java
server/sonar-webserver-webapi/src/it/java/org/sonar/server/issue/ws/DeleteCommentActionIT.java
server/sonar-webserver-webapi/src/it/java/org/sonar/server/issue/ws/DoTransitionActionIT.java
server/sonar-webserver-webapi/src/it/java/org/sonar/server/issue/ws/EditCommentActionIT.java
server/sonar-webserver-webapi/src/it/java/org/sonar/server/issue/ws/SearchActionIT.java
server/sonar-webserver-webapi/src/it/java/org/sonar/server/issue/ws/SetSeverityActionIT.java
server/sonar-webserver-webapi/src/it/java/org/sonar/server/issue/ws/SetTagsActionIT.java
server/sonar-webserver-webapi/src/it/java/org/sonar/server/issue/ws/SetTypeActionIT.java
server/sonar-webserver-webapi/src/it/java/org/sonar/server/source/ws/LinesActionIT.java
server/sonar-webserver-webapi/src/it/java/org/sonar/server/source/ws/ScmActionIT.java
server/sonar-webserver-webapi/src/it/resources/org/sonar/server/source/ws/LinesActionIT/hide_scmAuthors.json [deleted file]
server/sonar-webserver-webapi/src/it/resources/org/sonar/server/source/ws/ScmActionIT/hide_author.json [new file with mode: 0644]
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/AddCommentAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/AssignAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/DeleteCommentAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/DoTransitionAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/EditCommentAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/ListAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/OperationResponseWriter.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchResponseFormat.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SetSeverityAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SetTagsAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SetTypeAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/source/ws/IssueSnippetsAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/source/ws/LinesAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/source/ws/LinesJsonWriter.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/source/ws/ScmAction.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchResponseFormatFormatOperationTest.java

index 1f57f24af9b0a44fd02d26a98ad57f0f27a9c14c..2065ae43ebaf20131365ca5e3c218a1062a6f598 100644 (file)
@@ -113,7 +113,7 @@ public class AddCommentActionIT {
 
     call(issueDto.getKey(), "please fix it");
 
-    verify(responseWriter).write(eq(issueDto.getKey()), preloadedSearchResponseDataCaptor.capture(), any(Request.class), any(Response.class));
+    verify(responseWriter).write(eq(issueDto.getKey()), preloadedSearchResponseDataCaptor.capture(), any(Request.class), any(Response.class), eq(true));
     verifyContentOfPreloadedSearchResponseData(issueDto);
 
     IssueChangeDto issueComment = dbClient.issueChangeDao().selectByTypeAndIssueKeys(dbTester.getSession(), singletonList(issueDto.getKey()), TYPE_COMMENT).get(0);
index ec99b6bb6b4e01d5bb5dcf160bd4470f2706a9ac..da49b5c16183b244c32706e272dedcfe574aee91 100644 (file)
@@ -75,7 +75,7 @@ public class DeleteCommentActionIT {
 
     call(commentDto.getKey());
 
-    verify(responseWriter).write(eq(issueDto.getKey()), preloadedSearchResponseDataCaptor.capture(), any(Request.class), any(Response.class));
+    verify(responseWriter).write(eq(issueDto.getKey()), preloadedSearchResponseDataCaptor.capture(), any(Request.class), any(Response.class), eq(true));
     assertThat(dbClient.issueChangeDao().selectCommentByKey(dbTester.getSession(), commentDto.getKey())).isNotPresent();
     verifyContentOfPreloadedSearchResponseData(issueDto);
   }
index d3337046d7140682728f5cb1a13b984bb4275487..c740e978cc50afd5d24df420d3d50de04450883c 100644 (file)
@@ -125,7 +125,7 @@ public class DoTransitionActionIT {
 
     call(issue.getKey(), "confirm");
 
-    verify(responseWriter).write(eq(issue.getKey()), preloadedSearchResponseDataCaptor.capture(), any(Request.class), any(Response.class));
+    verify(responseWriter).write(eq(issue.getKey()), preloadedSearchResponseDataCaptor.capture(), any(Request.class), any(Response.class), eq(true));
     verifyContentOfPreloadedSearchResponseData(issue);
     verify(issueChangeEventService).distributeIssueChangeEvent(any(), any(), any(), any(), any(), any());
     IssueDto issueReloaded = db.getDbClient().issueDao().selectByKey(db.getSession(), issue.getKey()).get();
index 02419e3f813b3d4e427d3434582778c33052e8db..fd3a236db30ee51ee10a3ceda0577ff1d0a31f44 100644 (file)
@@ -86,7 +86,7 @@ public class EditCommentActionIT {
 
     call(commentDto.getKey(), "please have a look");
 
-    verify(responseWriter).write(eq(issueDto.getKey()), preloadedSearchResponseDataCaptor.capture(), any(Request.class), any(Response.class));
+    verify(responseWriter).write(eq(issueDto.getKey()), preloadedSearchResponseDataCaptor.capture(), any(Request.class), any(Response.class), eq(true));
 
     verifyContentOfPreloadedSearchResponseData(issueDto);
     IssueChangeDto issueComment = dbClient.issueChangeDao().selectCommentByKey(dbTester.getSession(), commentDto.getKey()).get();
index 4f45dd7f18825336c624304febeff88fef8beb75..5be14479c46c0a864bf75981af350c7dbb82f14e 100644 (file)
@@ -1213,6 +1213,7 @@ public class SearchActionIT {
 
   @Test
   public void search_by_author() {
+    userSession.logIn();
     ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
     ComponentDto file = db.components().insertComponent(newFileDto(project));
     RuleDto rule = db.rules().insertIssueRule();
@@ -1243,6 +1244,27 @@ public class SearchActionIT {
       .isEmpty();
   }
 
+  @Test
+  public void hide_author_if_not_logged_in() {
+    ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
+    ComponentDto file = db.components().insertComponent(newFileDto(project));
+    RuleDto rule = db.rules().insertIssueRule();
+    db.issues().insertIssue(rule, project, file, i -> i.setAuthorLogin("leia"));
+    db.issues().insertIssue(rule, project, file, i -> i.setAuthorLogin("luke"));
+    db.issues().insertIssue(rule, project, file, i -> i.setAuthorLogin("han, solo"));
+    indexPermissionsAndIssues();
+
+    SearchWsResponse response = ws.newRequest()
+      .setMultiParam("author", asList("leia", "han, solo"))
+      .setParam(FACETS, "author")
+      .executeProtobuf(SearchWsResponse.class);
+
+    assertThat(response.getIssuesList())
+      .extracting(Issue::getAuthor)
+      .containsExactlyInAnyOrder("", "");
+   assertThat(response.getFacets().getFacetsList()).isEmpty();
+  }
+
   @Test
   public void filter_by_test_scope() {
     ProjectData projectData = db.components().insertPublicProject("PROJECT_ID",
index 9eca22c0077f31d36343be63a52e5cfe1c43715e..68ee1ca0a8fa0244ebb3edfef9aac0ba5913512f 100644 (file)
@@ -111,7 +111,7 @@ public class SetSeverityActionIT {
 
     call(issueDto.getKey(), MINOR);
 
-    verify(responseWriter).write(eq(issueDto.getKey()), preloadedSearchResponseDataCaptor.capture(), any(Request.class), any(Response.class));
+    verify(responseWriter).write(eq(issueDto.getKey()), preloadedSearchResponseDataCaptor.capture(), any(Request.class), any(Response.class), eq(true));
     verifyContentOfPreloadedSearchResponseData(issueDto);
     verify(issueChangeEventService).distributeIssueChangeEvent(any(), any(), any(), any(), any(), any());
 
index c53aa00b7eb376ea28d6aca44fa27dcae2b13744..c01516e703f62f1b557ef37c0cca9a8b5638aeff 100644 (file)
@@ -102,7 +102,7 @@ public class SetTagsActionIT {
 
     call(issueDto.getKey(), "bug", "todo");
 
-    verify(responseWriter).write(eq(issueDto.getKey()), preloadedSearchResponseDataCaptor.capture(), any(Request.class), any(Response.class));
+    verify(responseWriter).write(eq(issueDto.getKey()), preloadedSearchResponseDataCaptor.capture(), any(Request.class), any(Response.class), eq(true));
     verifyContentOfPreloadedSearchResponseData(issueDto);
     IssueDto issueReloaded = dbClient.issueDao().selectByKey(db.getSession(), issueDto.getKey()).get();
     assertThat(issueReloaded.getTags()).containsOnly("bug", "todo");
index 02aef358912a5623c1e7e913795f752cc63b0791..80be6b3d1a1663448e18ac69e4984e5f752623a5 100644 (file)
@@ -127,7 +127,7 @@ public class SetTypeActionIT {
 
     call(issueDto.getKey(), to.name());
 
-    verify(responseWriter).write(eq(issueDto.getKey()), preloadedSearchResponseDataCaptor.capture(), any(Request.class), any(Response.class));
+    verify(responseWriter).write(eq(issueDto.getKey()), preloadedSearchResponseDataCaptor.capture(), any(Request.class), any(Response.class), eq(true));
     IssueDto issueReloaded = dbClient.issueDao().selectByKey(dbTester.getSession(), issueDto.getKey()).get();
     assertThat(issueReloaded.getType()).isEqualTo(to.getDbConstant());
 
index 65ff0b8fc14df2a61d594d96546694b35970b9e6..17b7caf6b8907004b47fcad9d8ce9ef519506c2f 100644 (file)
@@ -50,6 +50,7 @@ import org.sonar.server.ws.WsActionTester;
 
 import static java.lang.String.format;
 import static org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric;
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.mock;
@@ -69,7 +70,8 @@ public class LinesActionIT {
   private final HtmlSourceDecorator htmlSourceDecorator = mock(HtmlSourceDecorator.class);
   private final SourceService sourceService = new SourceService(db.getDbClient(), htmlSourceDecorator);
   private final LinesJsonWriter linesJsonWriter = new LinesJsonWriter(htmlSourceDecorator);
-  private final LinesAction underTest = new LinesAction(TestComponentFinder.from(db), db.getDbClient(), sourceService, linesJsonWriter, userSession);
+  private final LinesAction underTest = new LinesAction(TestComponentFinder.from(db), db.getDbClient(), sourceService, linesJsonWriter,
+    userSession);
   private final WsActionTester tester = new WsActionTester(underTest);
 
   @Before
@@ -363,10 +365,12 @@ public class LinesActionIT {
 
     ComponentDto file = insertFileWithData(data, mainBranch);
 
-    tester.newRequest()
+    String response = tester.newRequest()
       .setParam("uuid", file.uuid())
       .execute()
-      .assertJson(getClass(), "hide_scmAuthors.json");
+      .getInput();
+
+    assertThat(response).doesNotContain("isaac@asimov.com");
   }
 
   @Test
index 90bff44de7ee5c3bb9575b63ad6d4e39d88c7a7a..e777708e623f653de7f292c6fb16125823d163ae 100644 (file)
@@ -73,6 +73,7 @@ public class ScmActionIT {
 
   @Test
   public void show_scm() {
+    userSessionRule.logIn();
     userSessionRule.addProjectPermission(UserRole.CODEVIEWER, project.getProjectDto())
       .registerBranches(project.getMainBranchDto());
 
@@ -90,8 +91,28 @@ public class ScmActionIT {
       .assertJson(getClass(), "show_scm.json");
   }
 
+  @Test
+  public void hide_author_if_not_logged_in() {
+    userSessionRule.addProjectPermission(UserRole.CODEVIEWER, project.getProjectDto())
+      .registerBranches(project.getMainBranchDto());
+
+    dbTester.getDbClient().fileSourceDao().insert(dbSession, new FileSourceDto()
+      .setUuid(Uuids.createFast())
+      .setProjectUuid(PROJECT_UUID)
+      .setFileUuid(FILE_UUID)
+      .setSourceData(DbFileSources.Data.newBuilder().addLines(
+        newSourceLine("julien", "123-456-789", DateUtils.parseDateTime("2015-03-30T12:34:56+0000"), 1)).build()));
+    dbSession.commit();
+
+    tester.newRequest()
+      .setParam("key", FILE_KEY)
+      .execute()
+      .assertJson(getClass(), "hide_author.json");
+  }
+
   @Test
   public void show_scm_from_given_range_lines() {
+    userSessionRule.logIn();
     userSessionRule.addProjectPermission(UserRole.CODEVIEWER, project.getProjectDto())
       .registerBranches(project.getMainBranchDto());
 
@@ -117,6 +138,7 @@ public class ScmActionIT {
 
   @Test
   public void not_group_lines_by_commit() {
+    userSessionRule.logIn();
     userSessionRule.addProjectPermission(UserRole.CODEVIEWER, project.getProjectDto())
       .registerBranches(project.getMainBranchDto());
 
@@ -142,6 +164,7 @@ public class ScmActionIT {
 
   @Test
   public void group_lines_by_commit() {
+    userSessionRule.logIn();
     userSessionRule.addProjectPermission(UserRole.CODEVIEWER, project.getProjectDto())
       .registerBranches(project.getMainBranchDto());
 
@@ -167,6 +190,7 @@ public class ScmActionIT {
 
   @Test
   public void accept_negative_value_in_from_parameter() {
+    userSessionRule.logIn();
     userSessionRule.addProjectPermission(UserRole.CODEVIEWER, project.getProjectDto())
       .registerBranches(project.getMainBranchDto());
 
diff --git a/server/sonar-webserver-webapi/src/it/resources/org/sonar/server/source/ws/LinesActionIT/hide_scmAuthors.json b/server/sonar-webserver-webapi/src/it/resources/org/sonar/server/source/ws/LinesActionIT/hide_scmAuthors.json
deleted file mode 100644 (file)
index 2fd4764..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "sources": [
-    {
-      "line": 1,
-      "code": "\u003cp\u003eSOURCE_1\u003c/p\u003e",
-      "scmRevision": "REVISION_1",
-      "scmDate": "1974-10-03T03:40:00+0100",
-      "duplicated": false,
-      "isNew": false
-    }
-  ]
-}
diff --git a/server/sonar-webserver-webapi/src/it/resources/org/sonar/server/source/ws/ScmActionIT/hide_author.json b/server/sonar-webserver-webapi/src/it/resources/org/sonar/server/source/ws/ScmActionIT/hide_author.json
new file mode 100644 (file)
index 0000000..711dd67
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  "scm": [
+    [1, "","2015-03-30T12:34:56+0000", "123-456-789"]
+  ]
+}
index d0173ab9795800533c250ad1b2316ed479ff6d82..14b7a96a709ce0b4fff93dc4761145f51ec93fb2 100644 (file)
@@ -105,7 +105,7 @@ public class AddCommentAction implements IssuesWsAction {
       DefaultIssue defaultIssue = issueDto.toDefaultIssue();
       issueFieldsSetter.addComment(defaultIssue, wsRequest.getText(), context);
       SearchResponseData preloadedSearchResponseData = issueUpdater.saveIssueAndPreloadSearchResponseData(dbSession, issueDto, defaultIssue, context);
-      responseWriter.write(defaultIssue.key(), preloadedSearchResponseData, request, response);
+      responseWriter.write(defaultIssue.key(), preloadedSearchResponseData, request, response, true);
     }
   }
 
index e3d68704935a9a80de8ef486e65651a0abe7b5b6..4b355cc478a9176a8e56322b8418f7ad3420aea1 100644 (file)
@@ -102,7 +102,7 @@ public class AssignAction implements IssuesWsAction {
     String assignee = getAssignee(request);
     String key = request.mandatoryParam(PARAM_ISSUE);
     SearchResponseData preloadedResponseData = assign(key, assignee);
-    responseWriter.write(key, preloadedResponseData, request, response);
+    responseWriter.write(key, preloadedResponseData, request, response, true);
   }
 
   private SearchResponseData assign(String issueKey, @Nullable String login) {
index c11eabca6019741bbd9bfa01f963e355922f4471..7d8ffca8cc898230859a8abb1174dd07782957fb 100644 (file)
@@ -88,7 +88,7 @@ public class DeleteCommentAction implements IssuesWsAction {
       CommentData commentData = loadCommentData(dbSession, request);
       deleteComment(dbSession, commentData);
       IssueDto issueDto = commentData.getIssueDto();
-      responseWriter.write(issueDto.getKey(), new SearchResponseData(issueDto), request, response);
+      responseWriter.write(issueDto.getKey(), new SearchResponseData(issueDto), request, response, true);
     }
   }
 
index 59454a238703cf8283914d94318225c962a045e6..44c3f178c1b35496511b5a12f6e5ab5d4846e2f8 100644 (file)
@@ -119,7 +119,7 @@ public class DoTransitionAction implements IssuesWsAction {
     try (DbSession dbSession = dbClient.openSession(false)) {
       IssueDto issueDto = issueFinder.getByKey(dbSession, issue);
       SearchResponseData preloadedSearchResponseData = doTransition(dbSession, issueDto, request.mandatoryParam(PARAM_TRANSITION));
-      responseWriter.write(issue, preloadedSearchResponseData, request, response);
+      responseWriter.write(issue, preloadedSearchResponseData, request, response, true);
     }
   }
 
index 190fa3752e83c6538b35d3a967fd21f9085a0ebc..f76abc920a24c68d2e26316592eaa9f6c96c5d0d 100644 (file)
@@ -98,7 +98,7 @@ public class EditCommentAction implements IssuesWsAction {
       CommentData commentData = loadCommentData(dbSession, toWsRequest(request));
       updateComment(dbSession, commentData);
       IssueDto issueDto = commentData.getIssueDto();
-      responseWriter.write(issueDto.getKey(), new SearchResponseData(issueDto), request, response);
+      responseWriter.write(issueDto.getKey(), new SearchResponseData(issueDto), request, response, true);
     }
   }
 
index 4b4421c857836cb0dddaf21d01501102999f0cb6..59f9c72d270312e580e227532a8975fab1513f99 100644 (file)
@@ -242,7 +242,7 @@ public class ListAction implements IssuesWsAction {
     Paging paging = forPageIndex(request.page)
       .withPageSize(request.pageSize)
       .andTotal(request.pageSize);
-    return searchResponseFormat.formatList(additionalFields, data, paging);
+    return searchResponseFormat.formatList(additionalFields, data, paging, userSession.isLoggedIn());
   }
 
   private void collectLoggedInUser(SearchResponseLoader.Collector collector) {
index 24d1778e7c067ea71ca128b54085736e2a33e0ae..20d7d3596993437c1bce48330d31d6b48a499ed6 100644 (file)
@@ -37,11 +37,11 @@ public class OperationResponseWriter {
     this.format = format;
   }
 
-  public void write(String issueKey, SearchResponseData preloadedResponseData, Request request, Response response) {
+  public void write(String issueKey, SearchResponseData preloadedResponseData, Request request, Response response, boolean showAuthor) {
     SearchResponseLoader.Collector collector = new SearchResponseLoader.Collector(singletonList(issueKey));
     SearchResponseData data = loader.load(preloadedResponseData, collector, ALL_ADDITIONAL_FIELDS, null);
 
-    Issues.Operation responseBody = format.formatOperation(data);
+    Issues.Operation responseBody = format.formatOperation(data, showAuthor);
 
     WsUtils.writeProtobuf(responseBody, request, response);
   }
index 9caf366a7e5406cc4da9e6507681b77f29823b4f..12ddb6f846c674293fc775e0d2251fd74671dee2 100644 (file)
@@ -557,7 +557,7 @@ public class SearchAction implements IssuesWsAction {
 
     // FIXME allow long in Paging
     Paging paging = forPageIndex(options.getPage()).withPageSize(options.getLimit()).andTotal((int) getTotalHits(result).value);
-    return searchResponseFormat.formatSearch(additionalFields, data, paging, facets);
+    return searchResponseFormat.formatSearch(additionalFields, data, paging, facets, userSession.isLoggedIn());
   }
 
   private static TotalHits getTotalHits(SearchResponse response) {
@@ -565,15 +565,21 @@ public class SearchAction implements IssuesWsAction {
       "results"));
   }
 
-  private static SearchOptions createSearchOptionsFromRequest(SearchRequest request) {
+  private SearchOptions createSearchOptionsFromRequest(SearchRequest request) {
     SearchOptions options = new SearchOptions();
     options.setPage(request.getPage(), request.getPageSize());
 
     List<String> facets = request.getFacets();
-    if (facets != null && !facets.isEmpty()) {
-      options.addFacets(facets);
+
+    if (facets == null || facets.isEmpty()) {
+      return options;
     }
 
+    List<String> requestedFacets = new ArrayList<>(facets);
+    if (!userSession.isLoggedIn()) {
+      requestedFacets.remove(PARAM_AUTHOR);
+    }
+    options.addFacets(requestedFacets);
     return options;
   }
 
index 49e9e0a6cb0e6a22536b7778c1748a9e1a43373c..b04eeee8b6601479e1e9add63432eb5cef24ba77 100644 (file)
@@ -94,19 +94,21 @@ public class SearchResponseFormat {
   private final TextRangeResponseFormatter textRangeFormatter;
   private final UserResponseFormatter userFormatter;
 
-  public SearchResponseFormat(Durations durations, Languages languages, TextRangeResponseFormatter textRangeFormatter, UserResponseFormatter userFormatter) {
+  public SearchResponseFormat(Durations durations, Languages languages, TextRangeResponseFormatter textRangeFormatter,
+    UserResponseFormatter userFormatter) {
     this.durations = durations;
     this.languages = languages;
     this.textRangeFormatter = textRangeFormatter;
     this.userFormatter = userFormatter;
   }
 
-  SearchWsResponse formatSearch(Set<SearchAdditionalField> fields, SearchResponseData data, Paging paging, Facets facets) {
+  SearchWsResponse formatSearch(Set<SearchAdditionalField> fields, SearchResponseData data, Paging paging, Facets facets,
+    boolean showAuthor) {
     SearchWsResponse.Builder response = SearchWsResponse.newBuilder();
 
     formatPaging(paging, response);
     ofNullable(data.getEffortTotal()).ifPresent(response::setEffortTotal);
-    response.addAllIssues(createIssues(fields, data));
+    response.addAllIssues(createIssues(fields, data, showAuthor));
     response.addAllComponents(formatComponents(data));
     formatFacets(data, facets, response);
     if (fields.contains(SearchAdditionalField.RULES)) {
@@ -121,23 +123,23 @@ public class SearchResponseFormat {
     return response.build();
   }
 
-  Issues.ListWsResponse formatList(Set<SearchAdditionalField> fields, SearchResponseData data, Paging paging) {
+  Issues.ListWsResponse formatList(Set<SearchAdditionalField> fields, SearchResponseData data, Paging paging, boolean showAuthor) {
     Issues.ListWsResponse.Builder response = Issues.ListWsResponse.newBuilder();
 
     response.setPaging(Common.Paging.newBuilder()
       .setPageIndex(paging.pageIndex())
       .setPageSize(data.getIssues().size()));
-    response.addAllIssues(createIssues(fields, data));
+    response.addAllIssues(createIssues(fields, data, showAuthor));
     response.addAllComponents(formatComponents(data));
     return response.build();
   }
 
-  Operation formatOperation(SearchResponseData data) {
+  Operation formatOperation(SearchResponseData data, boolean showAuthor) {
     Operation.Builder response = Operation.newBuilder();
 
     if (data.getIssues().size() == 1) {
       IssueDto dto = data.getIssues().get(0);
-      response.setIssue(createIssue(ALL_ADDITIONAL_FIELDS, data, dto));
+      response.setIssue(createIssue(ALL_ADDITIONAL_FIELDS, data, dto, showAuthor));
     }
     response.addAllComponents(formatComponents(data));
     response.addAllRules(formatRules(data).getRulesList());
@@ -159,20 +161,20 @@ public class SearchResponseFormat {
       .setTotal(paging.total());
   }
 
-  private List<Issues.Issue> createIssues(Collection<SearchAdditionalField> fields, SearchResponseData data) {
+  private List<Issues.Issue> createIssues(Collection<SearchAdditionalField> fields, SearchResponseData data, boolean showAuthor) {
     return data.getIssues().stream()
-      .map(dto -> createIssue(fields, data, dto))
+      .map(dto -> createIssue(fields, data, dto, showAuthor))
       .toList();
   }
 
-  private Issue createIssue(Collection<SearchAdditionalField> fields, SearchResponseData data, IssueDto dto) {
+  private Issue createIssue(Collection<SearchAdditionalField> fields, SearchResponseData data, IssueDto dto, boolean showAuthor) {
     Issue.Builder issueBuilder = Issue.newBuilder();
-    addMandatoryFieldsToIssueBuilder(issueBuilder, dto, data);
+    addMandatoryFieldsToIssueBuilder(issueBuilder, dto, data, showAuthor);
     addAdditionalFieldsToIssueBuilder(fields, data, dto, issueBuilder);
     return issueBuilder.build();
   }
 
-  private void addMandatoryFieldsToIssueBuilder(Issue.Builder issueBuilder, IssueDto dto, SearchResponseData data) {
+  private void addMandatoryFieldsToIssueBuilder(Issue.Builder issueBuilder, IssueDto dto, SearchResponseData data, boolean showAuthor) {
     issueBuilder.setKey(dto.getKey());
     issueBuilder.setType(Common.RuleType.forNumber(dto.getType()));
 
@@ -204,6 +206,7 @@ public class SearchResponseFormat {
       issueBuilder.setSeverity(Common.Severity.valueOf(dto.getSeverity()));
     }
     ofNullable(data.getUserByUuid(dto.getAssigneeUuid())).ifPresent(assignee -> issueBuilder.setAssignee(assignee.getLogin()));
     ofNullable(emptyToNull(dto.getResolution())).ifPresent(issueBuilder::setResolution);
     issueBuilder.setStatus(dto.getStatus());
     ofNullable(dto.getIssueStatus()).map(IssueStatus::name).ifPresent(issueBuilder::setIssueStatus);
@@ -221,7 +224,9 @@ public class SearchResponseFormat {
     ofNullable(emptyToNull(dto.getChecksum())).ifPresent(issueBuilder::setHash);
     completeIssueLocations(dto, issueBuilder, data);
 
-    issueBuilder.setAuthor(nullToEmpty(dto.getAuthorLogin()));
+    if (showAuthor) {
+      issueBuilder.setAuthor(nullToEmpty(dto.getAuthorLogin()));
+    }
     ofNullable(dto.getIssueCreationDate()).map(DateUtils::formatDateTime).ifPresent(issueBuilder::setCreationDate);
     ofNullable(dto.getIssueUpdateDate()).map(DateUtils::formatDateTime).ifPresent(issueBuilder::setUpdateDate);
     ofNullable(dto.getIssueCloseDate()).map(DateUtils::formatDateTime).ifPresent(issueBuilder::setCloseDate);
@@ -235,7 +240,8 @@ public class SearchResponseFormat {
     Optional.ofNullable(dto.getCveId()).ifPresent(issueBuilder::setCveId);
   }
 
-  private static void addAdditionalFieldsToIssueBuilder(Collection<SearchAdditionalField> fields, SearchResponseData data, IssueDto dto, Issue.Builder issueBuilder) {
+  private static void addAdditionalFieldsToIssueBuilder(Collection<SearchAdditionalField> fields, SearchResponseData data, IssueDto dto,
+    Issue.Builder issueBuilder) {
     if (fields.contains(ACTIONS)) {
       issueBuilder.setActions(createIssueActions(data, dto));
     }
index 68f21d732e73e59aa62759058a03ce9a2be46bee..13bbde31fd28db7e25299c47391262a509356987 100644 (file)
@@ -109,7 +109,7 @@ public class SetSeverityAction implements IssuesWsAction {
     String severity = request.mandatoryParam(PARAM_SEVERITY);
     try (DbSession session = dbClient.openSession(false)) {
       SearchResponseData preloadedSearchResponseData = setType(session, issueKey, severity);
-      responseWriter.write(issueKey, preloadedSearchResponseData, request, response);
+      responseWriter.write(issueKey, preloadedSearchResponseData, request, response, true);
     }
   }
 
index 5879340701b451b0aff8d0f5f729eb577f4c46cd..081955fef7b4ea4210e10881a6d43fb839b4e8c4 100644 (file)
@@ -100,7 +100,7 @@ public class SetTagsAction implements IssuesWsAction {
     String key = request.mandatoryParam(PARAM_ISSUE);
     List<String> tags = MoreObjects.firstNonNull(request.paramAsStrings(PARAM_TAGS), Collections.emptyList());
     SearchResponseData preloadedSearchResponseData = setTags(key, tags);
-    responseWriter.write(key, preloadedSearchResponseData, request, response);
+    responseWriter.write(key, preloadedSearchResponseData, request, response, true);
   }
 
   private SearchResponseData setTags(String issueKey, List<String> tags) {
index c14ade37a00441bf3b133f6c736ff790fea43e2b..126c3550e94597bc1cad08f8f66cfae14162ce5f 100644 (file)
@@ -113,7 +113,7 @@ public class SetTypeAction implements IssuesWsAction {
     RuleType ruleType = RuleType.valueOf(request.mandatoryParam(PARAM_TYPE));
     try (DbSession session = dbClient.openSession(false)) {
       SearchResponseData preloadedSearchResponseData = setType(session, issueKey, ruleType);
-      responseWriter.write(issueKey, preloadedSearchResponseData, request, response);
+      responseWriter.write(issueKey, preloadedSearchResponseData, request, response, true);
     }
   }
 
index b84eb6b6229fe4936da93e56b9ae0bc9c1213d00..e805317ae3749262214b5d6d5369533b91f06607 100644 (file)
@@ -147,7 +147,7 @@ public class IssueSnippetsAction implements SourcesWsAction {
     componentViewerJsonWriter.writeComponentWithoutFav(writer, projectDto, fileDto, branch, pullRequest);
     componentViewerJsonWriter.writeMeasures(writer, fileDto, dbSession);
     writer.endObject();
-    linesJsonWriter.writeSource(lineSources, writer, periodDateSupplier);
+    linesJsonWriter.writeSource(lineSources, writer, periodDateSupplier, userSession.isLoggedIn());
 
     writer.endObject();
   }
index ccea427077d4a967bfe982f6fd65e09c973d9c47..41a1a0d251762e9aa58b02c6e4aa04c198a69ea4 100644 (file)
@@ -150,7 +150,7 @@ public class LinesAction implements SourcesWsAction {
         "No source found for file '%s' (uuid: %s)", file.getKey(), file.uuid());
       try (JsonWriter json = response.newJsonWriter()) {
         json.beginObject();
-        linesJsonWriter.writeSource(lines, json, periodDateSupplier);
+        linesJsonWriter.writeSource(lines, json, periodDateSupplier, userSession.isLoggedIn());
         json.endObject();
       }
     }
index 34bacaed64ed1c46ff58a48d602033df1b284730..b23bbd65134b7359c99c1ba4302ee979c50660a8 100644 (file)
@@ -34,7 +34,8 @@ public class LinesJsonWriter {
     this.htmlSourceDecorator = htmlSourceDecorator;
   }
 
-  public void writeSource(Iterable<DbFileSources.Line> lines, JsonWriter json, Supplier<Optional<Long>> periodDateSupplier) {
+  public void writeSource(Iterable<DbFileSources.Line> lines, JsonWriter json, Supplier<Optional<Long>> periodDateSupplier,
+    boolean showAuthor) {
     Long periodDate = null;
 
     json.name("sources").beginArray();
@@ -43,7 +44,9 @@ public class LinesJsonWriter {
         .prop("line", line.getLine())
         .prop("code", htmlSourceDecorator.getDecoratedSourceAsHtml(line.getSource(), line.getHighlighting(), line.getSymbols()))
         .prop("scmRevision", line.getScmRevision());
-      json.prop("scmAuthor", line.getScmAuthor());
+      if (showAuthor) {
+        json.prop("scmAuthor", line.getScmAuthor());
+      }
       if (line.hasScmDate()) {
         json.prop("scmDate", DateUtils.formatDateTime(new Date(line.getScmDate())));
       }
index a504735a0633df6400e210ca2f32d3eae974bb2c..36cc9cba0626632c7ddddc5890b13a8b4481968e 100644 (file)
@@ -104,7 +104,8 @@ public class ScmAction implements SourcesWsAction {
     try (DbSession dbSession = dbClient.openSession(false)) {
       ComponentDto file = componentFinder.getByKey(dbSession, fileKey);
       userSession.checkComponentPermission(UserRole.CODEVIEWER, file);
-      Iterable<DbFileSources.Line> sourceLines = checkFoundWithOptional(sourceService.getLines(dbSession, file.uuid(), from, to), "File '%s' has no sources", fileKey);
+      Iterable<DbFileSources.Line> sourceLines = checkFoundWithOptional(sourceService.getLines(dbSession, file.uuid(), from, to), "File " +
+        "'%s' has no sources", fileKey);
       try (JsonWriter json = response.newJsonWriter()) {
         json.beginObject();
         writeSource(sourceLines, commitsByLine, json);
@@ -113,7 +114,7 @@ public class ScmAction implements SourcesWsAction {
     }
   }
 
-  private static void writeSource(Iterable<DbFileSources.Line> lines, boolean showCommitsByLine, JsonWriter json) {
+  private void writeSource(Iterable<DbFileSources.Line> lines, boolean showCommitsByLine, JsonWriter json) {
     json.name("scm").beginArray();
 
     DbFileSources.Line previousLine = null;
@@ -121,8 +122,8 @@ public class ScmAction implements SourcesWsAction {
     for (DbFileSources.Line lineDoc : lines) {
       if (hasScm(lineDoc) && (!started || showCommitsByLine || !isSameCommit(previousLine, lineDoc))) {
         json.beginArray()
-          .value(lineDoc.getLine())
-          .value(lineDoc.getScmAuthor());
+          .value(lineDoc.getLine());
+        json.value(userSession.isLoggedIn() ? lineDoc.getScmAuthor() : "");
         json.value(lineDoc.hasScmDate() ? DateUtils.formatDateTime(new Date(lineDoc.getScmDate())) : null);
         json.value(lineDoc.getScmRevision());
         json.endArray();
index f68802909fa461894c59b1ed38262e1a002572f3..422f1d870b3fd5330b2a64c81aaaeec4f1ac0968 100644 (file)
@@ -24,11 +24,11 @@ import java.util.Collection;
 import java.util.Date;
 import java.util.List;
 import java.util.Set;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.junit.MockitoJUnitRunner;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.mockito.junit.jupiter.MockitoExtension;
 import org.sonar.api.issue.IssueStatus;
 import org.sonar.api.resources.Languages;
 import org.sonar.api.rules.CleanCodeAttribute;
@@ -71,54 +71,62 @@ import static org.sonar.db.user.UserTesting.newUserDto;
 import static org.sonar.server.issue.index.IssueScope.MAIN;
 import static org.sonar.server.issue.index.IssueScope.TEST;
 
-@RunWith(MockitoJUnitRunner.class)
-public class SearchResponseFormatFormatOperationTest {
-  @Rule
-  public DbTester db = DbTester.create();
+@ExtendWith(MockitoExtension.class)
+class SearchResponseFormatFormatOperationTest {
+  @RegisterExtension
+  DbTester db = DbTester.create();
   private final Durations durations = new Durations();
   private final Languages languages = mock(Languages.class);
   private final TextRangeResponseFormatter textRangeResponseFormatter = mock(TextRangeResponseFormatter.class);
   private final UserResponseFormatter userResponseFormatter = mock(UserResponseFormatter.class);
   private final Common.User user = mock(Common.User.class);
-  private final SearchResponseFormat searchResponseFormat = new SearchResponseFormat(durations, languages, textRangeResponseFormatter, userResponseFormatter);
+  private final SearchResponseFormat searchResponseFormat = new SearchResponseFormat(durations, languages, textRangeResponseFormatter,
+    userResponseFormatter);
 
   private SearchResponseData searchResponseData;
   private IssueDto issueDto;
   private ComponentDto componentDto;
   private UserDto userDto;
 
-  @Before
-  public void setUp() {
+  @BeforeEach
+  void setUp() {
     searchResponseData = newSearchResponseDataMainBranch();
   }
 
   @Test
-  public void formatOperation_should_add_components_to_response() {
-    Operation result = searchResponseFormat.formatOperation(searchResponseData);
+  void formatOperation_should_add_components_to_response() {
+    Operation result = searchResponseFormat.formatOperation(searchResponseData, true);
 
     assertThat(result.getComponentsList()).hasSize(1);
     assertThat(result.getComponentsList().get(0).getKey()).isEqualTo(issueDto.getComponentKey());
   }
 
   @Test
-  public void formatOperation_should_add_rules_to_response() {
-    Operation result = searchResponseFormat.formatOperation(searchResponseData);
+  void formatOperation_should_add_rules_to_response() {
+    Operation result = searchResponseFormat.formatOperation(searchResponseData, true);
 
     assertThat(result.getRulesList()).hasSize(1);
     assertThat(result.getRulesList().get(0).getKey()).isEqualTo(issueDto.getRuleKey().toString());
   }
 
   @Test
-  public void formatOperation_should_add_users_to_response() {
-    Operation result = searchResponseFormat.formatOperation(searchResponseData);
+  void formatOperation_should_add_users_to_response() {
+    Operation result = searchResponseFormat.formatOperation(searchResponseData, true);
 
     assertThat(result.getUsersList()).hasSize(1);
     assertThat(result.getUsers(0)).isSameAs(user);
   }
 
   @Test
-  public void formatOperation_should_add_issue_to_response() {
-    Operation result = searchResponseFormat.formatOperation(searchResponseData);
+  void formatOperation_does_not_add_author_to_response_if_showAuthor_false() {
+    Operation result = searchResponseFormat.formatOperation(searchResponseData, false);
+
+    assertThat(result.getIssue().getAuthor()).isEmpty();
+  }
+
+  @Test
+  void formatOperation_should_add_issue_to_response() {
+    Operation result = searchResponseFormat.formatOperation(searchResponseData, true);
 
     assertIssueEqualsIssueDto(result.getIssue(), issueDto);
   }
@@ -155,10 +163,10 @@ public class SearchResponseFormatFormatOperationTest {
   }
 
   @Test
-  public void formatOperation_should_not_add_issue_when_several_issue() {
+  void formatOperation_should_not_add_issue_when_several_issue() {
     searchResponseData = new SearchResponseData(List.of(createIssue(), createIssue()));
 
-    Operation result = searchResponseFormat.formatOperation(searchResponseData);
+    Operation result = searchResponseFormat.formatOperation(searchResponseData, true);
 
     assertThat(result.getIssue()).isEqualTo(Issue.getDefaultInstance());
   }
@@ -172,86 +180,86 @@ public class SearchResponseFormatFormatOperationTest {
   }
 
   @Test
-  public void formatOperation_should_add_branch_on_issue() {
+  void formatOperation_should_add_branch_on_issue() {
     String branchName = randomAlphanumeric(5);
     searchResponseData = newSearchResponseDataBranch(branchName);
-    Operation result = searchResponseFormat.formatOperation(searchResponseData);
+    Operation result = searchResponseFormat.formatOperation(searchResponseData, true);
     assertThat(result.getIssue().getBranch()).isEqualTo(branchName);
   }
 
   @Test
-  public void formatOperation_should_add_pullrequest_on_issue() {
+  void formatOperation_should_add_pullrequest_on_issue() {
     searchResponseData = newSearchResponseDataPr("pr1");
-    Operation result = searchResponseFormat.formatOperation(searchResponseData);
+    Operation result = searchResponseFormat.formatOperation(searchResponseData, true);
     assertThat(result.getIssue().getPullRequest()).isEqualTo("pr1");
   }
 
   @Test
-  public void formatOperation_should_add_project_on_issue() {
+  void formatOperation_should_add_project_on_issue() {
     issueDto.setProjectUuid(componentDto.uuid());
 
-    Operation result = searchResponseFormat.formatOperation(searchResponseData);
+    Operation result = searchResponseFormat.formatOperation(searchResponseData, true);
 
     assertThat(result.getIssue().getProject()).isEqualTo(componentDto.getKey());
   }
 
   @Test
-  public void formatOperation_should_add_external_rule_engine_on_issue() {
+  void formatOperation_should_add_external_rule_engine_on_issue() {
     issueDto.setExternal(true);
     String expected = randomAlphanumeric(5);
     issueDto.setRuleKey(EXTERNAL_RULE_REPO_PREFIX + expected, randomAlphanumeric(5));
 
-    Operation result = searchResponseFormat.formatOperation(searchResponseData);
+    Operation result = searchResponseFormat.formatOperation(searchResponseData, true);
 
     assertThat(result.getIssue().getExternalRuleEngine()).isEqualTo(expected);
   }
 
   @Test
-  public void formatOperation_should_add_effort_and_debt_on_issue() {
+  void formatOperation_should_add_effort_and_debt_on_issue() {
     long effort = 60L;
     issueDto.setEffort(effort);
     String expected = durations.encode(Duration.create(effort));
 
-    Operation result = searchResponseFormat.formatOperation(searchResponseData);
+    Operation result = searchResponseFormat.formatOperation(searchResponseData, true);
 
     assertThat(result.getIssue().getEffort()).isEqualTo(expected);
     assertThat(result.getIssue().getDebt()).isEqualTo(expected);
   }
 
   @Test
-  public void formatOperation_should_add_scope_test_on_issue_when_unit_test_file() {
+  void formatOperation_should_add_scope_test_on_issue_when_unit_test_file() {
     componentDto.setQualifier(UNIT_TEST_FILE);
 
-    Operation result = searchResponseFormat.formatOperation(searchResponseData);
+    Operation result = searchResponseFormat.formatOperation(searchResponseData, true);
 
     assertThat(result.getIssue().getScope()).isEqualTo(TEST.name());
   }
 
   @Test
-  public void formatOperation_should_add_scope_main_on_issue_when_not_unit_test_file() {
+  void formatOperation_should_add_scope_main_on_issue_when_not_unit_test_file() {
     componentDto.setQualifier(randomAlphanumeric(5));
 
-    Operation result = searchResponseFormat.formatOperation(searchResponseData);
+    Operation result = searchResponseFormat.formatOperation(searchResponseData, true);
 
     assertThat(result.getIssue().getScope()).isEqualTo(MAIN.name());
   }
 
   @Test
-  public void formatOperation_should_add_actions_on_issues() {
+  void formatOperation_should_add_actions_on_issues() {
     Set<String> expectedActions = Set.of("actionA", "actionB");
     searchResponseData.addActions(issueDto.getKey(), expectedActions);
 
-    Operation result = searchResponseFormat.formatOperation(searchResponseData);
+    Operation result = searchResponseFormat.formatOperation(searchResponseData, true);
 
     assertThat(result.getIssue().getActions().getActionsList()).containsExactlyInAnyOrderElementsOf(expectedActions);
   }
 
   @Test
-  public void formatOperation_should_add_transitions_on_issues() {
+  void formatOperation_should_add_transitions_on_issues() {
     Set<String> expectedTransitions = Set.of("transitionone", "transitiontwo");
     searchResponseData.addTransitions(issueDto.getKey(), createFakeTransitions(expectedTransitions));
 
-    Operation result = searchResponseFormat.formatOperation(searchResponseData);
+    Operation result = searchResponseFormat.formatOperation(searchResponseData, true);
 
     assertThat(result.getIssue().getTransitions().getTransitionsList()).containsExactlyInAnyOrderElementsOf(expectedTransitions);
   }
@@ -263,30 +271,30 @@ public class SearchResponseFormatFormatOperationTest {
   }
 
   @Test
-  public void formatOperation_should_add_comments_on_issues() {
+  void formatOperation_should_add_comments_on_issues() {
     IssueChangeDto issueChangeDto = newIssueChangeDto(issueDto);
     searchResponseData.setComments(List.of(issueChangeDto));
 
-    Operation result = searchResponseFormat.formatOperation(searchResponseData);
+    Operation result = searchResponseFormat.formatOperation(searchResponseData, true);
 
     assertThat(result.getIssue().getComments().getCommentsList()).hasSize(1).extracting(Common.Comment::getKey).containsExactly(issueChangeDto.getKey());
   }
 
   @Test
-  public void formatOperation_should_not_set_severity_for_security_hotspot_issue() {
+  void formatOperation_should_not_set_severity_for_security_hotspot_issue() {
     issueDto.setType(SECURITY_HOTSPOT);
 
-    Operation result = searchResponseFormat.formatOperation(searchResponseData);
+    Operation result = searchResponseFormat.formatOperation(searchResponseData, true);
 
     assertThat(result.getIssue().hasSeverity()).isFalse();
   }
 
   @Test
-  public void formatOperation_shouldReturnExpectedIssueStatus() {
+  void formatOperation_shouldReturnExpectedIssueStatus() {
     issueDto.setStatus(org.sonar.api.issue.Issue.STATUS_RESOLVED);
     issueDto.setResolution(org.sonar.api.issue.Issue.RESOLUTION_WONT_FIX);
 
-    Operation result = searchResponseFormat.formatOperation(searchResponseData);
+    Operation result = searchResponseFormat.formatOperation(searchResponseData, true);
 
     assertThat(result.getIssue().getIssueStatus()).isEqualTo(IssueStatus.ACCEPTED.name());
   }