aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java3
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchResponseFormat.java81
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/ws/WsResponseCommonFormat.java8
-rw-r--r--server/sonar-server/src/main/resources/org/sonar/server/issue/ws/search-example.json2
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/issue_with_comments.json3
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/load_additional_fields.json3
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/load_additional_fields_with_issue_admin_permission.json5
-rw-r--r--sonar-ws/src/main/protobuf/ws-commons.proto11
-rw-r--r--sonar-ws/src/main/protobuf/ws-issues.proto15
9 files changed, 74 insertions, 57 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java
index 06cce4c77bf..1b6c6e43a3b 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java
@@ -126,7 +126,8 @@ public class SearchAction implements IssuesWsAction {
"At most one of the following parameters can be provided at the same time: %s, %s, %s, %s, %s<br>" +
"Since 5.5, response field 'debt' has been renamed to 'effort'.<br>" +
"Since 5.5, response field 'actionPlan' has been removed.<br>" +
- "Since 5.5, response field 'reporter' has been removed, as manual issue feature has been dropped.",
+ "Since 5.5, response field 'reporter' has been removed, as manual issue feature has been dropped." +
+ "Since 6.3, response field 'email' has been replaced by 'avatar'",
PARAM_COMPONENT_KEYS, PARAM_COMPONENT_UUIDS, PARAM_COMPONENTS, PARAM_COMPONENT_ROOT_UUIDS, PARAM_COMPONENT_ROOTS)
.setSince("3.6")
.setResponseExample(getClass().getResource("search-example.json"));
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchResponseFormat.java b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchResponseFormat.java
index bfb2d239718..f6cb0bdbe65 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchResponseFormat.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchResponseFormat.java
@@ -20,6 +20,7 @@
package org.sonar.server.issue.ws;
import com.google.common.base.Strings;
+import com.google.common.hash.Hashing;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -51,7 +52,20 @@ import org.sonarqube.ws.Issues;
import static com.google.common.base.Strings.emptyToNull;
import static com.google.common.base.Strings.nullToEmpty;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.util.Locale.ENGLISH;
import static org.sonar.core.util.Protobuf.setNullable;
+import static org.sonarqube.ws.Issues.Actions;
+import static org.sonarqube.ws.Issues.Comment;
+import static org.sonarqube.ws.Issues.Comments;
+import static org.sonarqube.ws.Issues.Component;
+import static org.sonarqube.ws.Issues.Flow;
+import static org.sonarqube.ws.Issues.Issue;
+import static org.sonarqube.ws.Issues.Location;
+import static org.sonarqube.ws.Issues.Operation;
+import static org.sonarqube.ws.Issues.SearchWsResponse;
+import static org.sonarqube.ws.Issues.Transitions;
+import static org.sonarqube.ws.Issues.Users;
public class SearchResponseFormat {
@@ -65,9 +79,9 @@ public class SearchResponseFormat {
this.languages = languages;
}
- public Issues.SearchWsResponse formatSearch(Set<SearchAdditionalField> fields, SearchResponseData data,
+ public SearchWsResponse formatSearch(Set<SearchAdditionalField> fields, SearchResponseData data,
Paging paging, @Nullable Facets facets) {
- Issues.SearchWsResponse.Builder response = Issues.SearchWsResponse.newBuilder();
+ SearchWsResponse.Builder response = SearchWsResponse.newBuilder();
formatPaging(paging, response);
formatEffortTotal(data, response);
@@ -88,11 +102,11 @@ public class SearchResponseFormat {
return response.build();
}
- public Issues.Operation formatOperation(SearchResponseData data) {
- Issues.Operation.Builder response = Issues.Operation.newBuilder();
+ public Operation formatOperation(SearchResponseData data) {
+ Operation.Builder response = Operation.newBuilder();
if (data.getIssues().size() == 1) {
- Issues.Issue.Builder issueBuilder = Issues.Issue.newBuilder();
+ Issue.Builder issueBuilder = Issue.newBuilder();
IssueDto dto = data.getIssues().get(0);
formatIssue(issueBuilder, dto, data);
formatIssueActions(data, issueBuilder, dto);
@@ -106,7 +120,7 @@ public class SearchResponseFormat {
return response.build();
}
- private void formatEffortTotal(SearchResponseData data, Issues.SearchWsResponse.Builder response) {
+ private void formatEffortTotal(SearchResponseData data, SearchWsResponse.Builder response) {
Long effort = data.getEffortTotal();
if (effort != null) {
response.setDebtTotal(effort);
@@ -114,7 +128,7 @@ public class SearchResponseFormat {
}
}
- private void formatPaging(Paging paging, Issues.SearchWsResponse.Builder response) {
+ private void formatPaging(Paging paging, SearchWsResponse.Builder response) {
response.setP(paging.pageIndex());
response.setPs(paging.pageSize());
response.setTotal(paging.total());
@@ -123,8 +137,8 @@ public class SearchResponseFormat {
private List<Issues.Issue> formatIssues(Set<SearchAdditionalField> fields, SearchResponseData data) {
List<Issues.Issue> result = new ArrayList<>();
- Issues.Issue.Builder issueBuilder = Issues.Issue.newBuilder();
- for (IssueDto dto : data.getIssues()) {
+ Issue.Builder issueBuilder = Issue.newBuilder();
+ data.getIssues().forEach(dto -> {
issueBuilder.clear();
formatIssue(issueBuilder, dto, data);
if (fields.contains(SearchAdditionalField.ACTIONS)) {
@@ -137,11 +151,11 @@ public class SearchResponseFormat {
formatIssueComments(data, issueBuilder, dto);
}
result.add(issueBuilder.build());
- }
+ });
return result;
}
- private void formatIssue(Issues.Issue.Builder issueBuilder, IssueDto dto, SearchResponseData data) {
+ private void formatIssue(Issue.Builder issueBuilder, IssueDto dto, SearchResponseData data) {
issueBuilder.setKey(dto.getKey());
setNullable(dto.getType(), issueBuilder::setType, Common.RuleType::valueOf);
@@ -179,7 +193,7 @@ public class SearchResponseFormat {
setNullable(dto.getIssueCloseDate(), issueBuilder::setCloseDate, DateUtils::formatDateTime);
}
- private void completeIssueLocations(IssueDto dto, Issues.Issue.Builder issueBuilder) {
+ private void completeIssueLocations(IssueDto dto, Issue.Builder issueBuilder) {
DbIssues.Locations locations = dto.parseLocations();
if (locations == null) {
return;
@@ -189,7 +203,7 @@ public class SearchResponseFormat {
issueBuilder.setTextRange(convertTextRange(textRange));
}
for (DbIssues.Flow flow : locations.getFlowList()) {
- Issues.Flow.Builder targetFlow = Issues.Flow.newBuilder();
+ Flow.Builder targetFlow = Flow.newBuilder();
for (DbIssues.Location flowLocation : flow.getLocationList()) {
targetFlow.addLocations(convertLocation(flowLocation));
}
@@ -197,8 +211,8 @@ public class SearchResponseFormat {
}
}
- private static Issues.Location convertLocation(DbIssues.Location source) {
- Issues.Location.Builder target = Issues.Location.newBuilder();
+ private static Location convertLocation(DbIssues.Location source) {
+ Location.Builder target = Location.newBuilder();
if (source.hasComponentId()) {
target.setComponentId(source.getComponentId());
}
@@ -230,8 +244,8 @@ public class SearchResponseFormat {
return targetRange;
}
- private static void formatIssueTransitions(SearchResponseData data, Issues.Issue.Builder wsIssue, IssueDto dto) {
- Issues.Transitions.Builder wsTransitions = Issues.Transitions.newBuilder();
+ private static void formatIssueTransitions(SearchResponseData data, Issue.Builder wsIssue, IssueDto dto) {
+ Transitions.Builder wsTransitions = Transitions.newBuilder();
List<Transition> transitions = data.getTransitionsForIssueKey(dto.getKey());
if (transitions != null) {
for (Transition transition : transitions) {
@@ -241,8 +255,8 @@ public class SearchResponseFormat {
wsIssue.setTransitions(wsTransitions);
}
- private static void formatIssueActions(SearchResponseData data, Issues.Issue.Builder wsIssue, IssueDto dto) {
- Issues.Actions.Builder wsActions = Issues.Actions.newBuilder();
+ private static void formatIssueActions(SearchResponseData data, Issue.Builder wsIssue, IssueDto dto) {
+ Actions.Builder wsActions = Actions.newBuilder();
List<String> actions = data.getActionsForIssueKey(dto.getKey());
if (actions != null) {
wsActions.addAllActions(actions);
@@ -250,11 +264,11 @@ public class SearchResponseFormat {
wsIssue.setActions(wsActions);
}
- private static void formatIssueComments(SearchResponseData data, Issues.Issue.Builder wsIssue, IssueDto dto) {
- Issues.Comments.Builder wsComments = Issues.Comments.newBuilder();
+ private static void formatIssueComments(SearchResponseData data, Issue.Builder wsIssue, IssueDto dto) {
+ Comments.Builder wsComments = Comments.newBuilder();
List<IssueChangeDto> comments = data.getCommentsForIssueKey(dto.getKey());
if (comments != null) {
- Issues.Comment.Builder wsComment = Issues.Comment.newBuilder();
+ Comment.Builder wsComment = Comment.newBuilder();
for (IssueChangeDto comment : comments) {
String markdown = comment.getChangeData();
wsComment
@@ -293,7 +307,7 @@ public class SearchResponseFormat {
List<Issues.Component> result = new ArrayList<>();
for (ComponentDto dto : components) {
String uuid = dto.uuid();
- Issues.Component.Builder builder = Issues.Component.newBuilder()
+ Component.Builder builder = Component.newBuilder()
.setOrganization(data.getOrganizationKey(dto.getOrganizationUuid()))
.setId(dto.getId())
.setKey(dto.key())
@@ -322,17 +336,30 @@ public class SearchResponseFormat {
return result;
}
- private Common.Users.Builder formatUsers(SearchResponseData data) {
- Common.Users.Builder wsUsers = Common.Users.newBuilder();
+ private Users.Builder formatUsers(SearchResponseData data) {
+ Users.Builder wsUsers = Users.newBuilder();
List<UserDto> users = data.getUsers();
if (users != null) {
for (UserDto user : users) {
- wsUsers.addUsers(commonFormat.formatUser(user));
+ wsUsers.addUsers(formatUser(user));
}
}
return wsUsers;
}
+ public Users.User.Builder formatUser(UserDto user) {
+ Users.User.Builder builder = Users.User.newBuilder()
+ .setLogin(user.getLogin())
+ .setName(nullToEmpty(user.getName()))
+ .setActive(user.isActive());
+ setNullable(user.getEmail(), text -> builder.setAvatar(hash(text)));
+ return builder;
+ }
+
+ private static String hash(String text) {
+ return Hashing.md5().hashString(text.toLowerCase(ENGLISH), UTF_8).toString();
+ }
+
private Issues.Languages.Builder formatLanguages() {
Issues.Languages.Builder wsLangs = Issues.Languages.newBuilder();
Issues.Language.Builder wsLang = Issues.Language.newBuilder();
@@ -346,7 +373,7 @@ public class SearchResponseFormat {
return wsLangs;
}
- private void formatFacets(Facets facets, Issues.SearchWsResponse.Builder wsSearch) {
+ private void formatFacets(Facets facets, SearchWsResponse.Builder wsSearch) {
Common.Facets.Builder wsFacets = Common.Facets.newBuilder();
Common.Facet.Builder wsFacet = Common.Facet.newBuilder();
for (Map.Entry<String, LinkedHashMap<String, Long>> facet : facets.getAll().entrySet()) {
diff --git a/server/sonar-server/src/main/java/org/sonar/server/ws/WsResponseCommonFormat.java b/server/sonar-server/src/main/java/org/sonar/server/ws/WsResponseCommonFormat.java
index d30eaa5d823..b2333685896 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/ws/WsResponseCommonFormat.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/ws/WsResponseCommonFormat.java
@@ -23,7 +23,6 @@ import org.sonar.api.resources.Language;
import org.sonar.api.resources.Languages;
import org.sonar.api.utils.Paging;
import org.sonar.db.rule.RuleDto;
-import org.sonar.db.user.UserDto;
import org.sonarqube.ws.Common;
import static com.google.common.base.Strings.nullToEmpty;
@@ -57,11 +56,4 @@ public class WsResponseCommonFormat {
return builder;
}
- public Common.User.Builder formatUser(UserDto user) {
- return Common.User.newBuilder()
- .setLogin(user.getLogin())
- .setName(nullToEmpty(user.getName()))
- .setEmail(nullToEmpty(user.getEmail()))
- .setActive(user.isActive());
- }
}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/issue/ws/search-example.json b/server/sonar-server/src/main/resources/org/sonar/server/issue/ws/search-example.json
index 2bb9d5fc008..f14ef06f785 100644
--- a/server/sonar-server/src/main/resources/org/sonar/server/issue/ws/search-example.json
+++ b/server/sonar-server/src/main/resources/org/sonar/server/issue/ws/search-example.json
@@ -81,7 +81,7 @@
"login": "admin",
"name": "Administrator",
"active": true,
- "email": "admin@sonarqube.org"
+ "avatar": "ab0ec6adc38ad44a15105f207394946f"
}
]
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/issue_with_comments.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/issue_with_comments.json
index ccbba305815..0c6e1982ca7 100644
--- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/issue_with_comments.json
+++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/issue_with_comments.json
@@ -29,13 +29,12 @@
{
"login": "fabrice",
"name": "Fabrice",
- "email": "fabrice@email.com",
+ "avatar": "1c7a5823d4ad91e32a88f91242d2c9c2",
"active": true
},
{
"login": "john",
"name": "John",
- "email": "",
"active": true
}
]
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/load_additional_fields.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/load_additional_fields.json
index abaebf76bb6..f5510c017e5 100644
--- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/load_additional_fields.json
+++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/load_additional_fields.json
@@ -20,13 +20,12 @@
{
"login": "simon",
"name": "Simon",
- "email": "simon@email.com",
+ "avatar": "ab0ec6adc38ad44a15105f207394946f",
"active": true
},
{
"login": "admin",
"name": "Administrator",
- "email": "",
"active": true
}
]
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/load_additional_fields_with_issue_admin_permission.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/load_additional_fields_with_issue_admin_permission.json
index a25410deaca..745ffde8fa5 100644
--- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/load_additional_fields_with_issue_admin_permission.json
+++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/load_additional_fields_with_issue_admin_permission.json
@@ -17,20 +17,19 @@
"resolve",
"falsepositive",
"wontfix"
- ],
+ ]
}
],
"users": [
{
"login": "simon",
"name": "Simon",
- "email": "simon@email.com",
+ "avatar": "ab0ec6adc38ad44a15105f207394946f",
"active": true
},
{
"login": "admin",
"name": "Administrator",
- "email": "",
"active": true
}
]
diff --git a/sonar-ws/src/main/protobuf/ws-commons.proto b/sonar-ws/src/main/protobuf/ws-commons.proto
index 6f9c6805103..50a4fa4268c 100644
--- a/sonar-ws/src/main/protobuf/ws-commons.proto
+++ b/sonar-ws/src/main/protobuf/ws-commons.proto
@@ -72,17 +72,6 @@ enum RuleStatus {
REMOVED = 3;
}
-message User {
- optional string login = 1;
- optional string name = 2;
- optional string email = 3;
- optional bool active = 4;
-}
-
-message Users {
- repeated User users = 1;
-}
-
// Lines start at 1 and line offsets start at 0
message TextRange {
// Start line. Should never be absent
diff --git a/sonar-ws/src/main/protobuf/ws-issues.proto b/sonar-ws/src/main/protobuf/ws-issues.proto
index a2d1aa67a2f..361efbd4a92 100644
--- a/sonar-ws/src/main/protobuf/ws-issues.proto
+++ b/sonar-ws/src/main/protobuf/ws-issues.proto
@@ -41,7 +41,7 @@ message SearchWsResponse {
repeated Issue issues = 6;
repeated Component components = 7;
optional sonarqube.ws.commons.Rules rules = 8;
- optional sonarqube.ws.commons.Users users = 9;
+ optional Users users = 9;
// Deprecated since 5.5, action plan has been removed
optional ActionPlans unusedActionPlans = 10;
@@ -54,7 +54,7 @@ message Operation {
optional Issue issue = 1;
repeated Component components = 2;
repeated sonarqube.ws.commons.Rule rules = 3;
- repeated sonarqube.ws.commons.User users = 4;
+ repeated Users.User users = 4;
// Deprecated since 5.5, action plan has been removed
repeated ActionPlan actiunusedActionPlansonPlans = 5;
}
@@ -211,5 +211,16 @@ message BulkChangeWsResponse {
optional int64 failures = 4;
}
+message Users {
+ repeated User users = 1;
+
+ message User {
+ optional string login = 1;
+ optional string name = 2;
+ optional string avatar = 3;
+ optional bool active = 4;
+ }
+}
+