compile 'com.google.guava:guava'
compile 'commons-io:commons-io'
compile 'commons-lang:commons-lang'
+ compile 'org.apache.commons:commons-csv'
compileOnly 'com.google.code.findbugs:jsr305'
runtime project(path: ':sonar-plugin-api', configuration: 'shadow')
compileOnly project(path: ':sonar-plugin-api')
import com.google.common.annotations.VisibleForTesting;
import java.io.File;
+import java.io.FileReader;
import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
import java.util.Date;
import java.util.List;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang.StringUtils;
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVParser;
+import org.apache.commons.csv.CSVRecord;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.scm.BlameCommand;
import org.sonar.api.batch.scm.BlameLine;
import org.sonar.api.utils.DateUtils;
+import static com.google.common.base.Preconditions.checkState;
+import static java.util.stream.Collectors.toList;
+import static org.apache.commons.lang.StringUtils.trimToNull;
+
public class XooBlameCommand extends BlameCommand {
private static final String SCM_EXTENSION = ".scm";
@VisibleForTesting
protected void processFile(InputFile inputFile, BlameOutput result) {
File ioFile = inputFile.file();
- File scmDataFile = new java.io.File(ioFile.getParentFile(), ioFile.getName() + SCM_EXTENSION);
+ File scmDataFile = new File(ioFile.getParentFile(), ioFile.getName() + SCM_EXTENSION);
if (!scmDataFile.exists()) {
return;
}
try {
- List<String> lines = FileUtils.readLines(scmDataFile, StandardCharsets.UTF_8);
- List<BlameLine> blame = new ArrayList<>(lines.size());
- int lineNumber = 0;
- for (String line : lines) {
- lineNumber++;
- if (StringUtils.isNotBlank(line)) {
- // revision,author,dateTime
- String[] fields = StringUtils.splitPreserveAllTokens(line, ',');
- if (fields.length < 3) {
- throw new IllegalStateException("Not enough fields on line " + lineNumber);
- }
- String revision = StringUtils.trimToNull(fields[0]);
- String author = StringUtils.trimToNull(fields[1]);
- BlameLine blameLine = new BlameLine().revision(revision).author(author);
- String dateStr = StringUtils.trimToNull(fields[2]);
- if (dateStr != null) {
- Date dateTime = DateUtils.parseDateTimeQuietly(dateStr);
- if (dateTime != null) {
- blameLine.date(dateTime);
- } else {
- // Will throw an exception, when date is not in format "yyyy-MM-dd"
- blameLine.date(DateUtils.parseDate(dateStr));
- }
- }
- blame.add(blameLine);
- }
- }
+ List<BlameLine> blame = readFile(scmDataFile);
result.blameResult(inputFile, blame);
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
+
+ private static List<BlameLine> readFile(File inputStream) throws IOException {
+ try (CSVParser csvParser = CSVFormat.RFC4180
+ .withIgnoreEmptyLines()
+ .withIgnoreSurroundingSpaces()
+ .parse(new FileReader(inputStream))) {
+ List<CSVRecord> records = csvParser.getRecords();
+ return records.stream()
+ .map(XooBlameCommand::convertToBlameLine)
+ .collect(toList());
+ }
+ }
+
+ private static BlameLine convertToBlameLine(CSVRecord csvRecord) {
+ checkState(csvRecord.size() == 3, "Not enough fields on line %s", csvRecord);
+ String revision = trimToNull(csvRecord.get(0));
+ String author = trimToNull(csvRecord.get(1));
+ BlameLine blameLine = new BlameLine().revision(revision).author(author);
+ String dateStr = trimToNull(csvRecord.get(2));
+ if (dateStr != null) {
+ Date dateTime = DateUtils.parseDateTimeQuietly(dateStr);
+ if (dateTime != null) {
+ blameLine.date(dateTime);
+ } else {
+ // Will throw an exception, when date is not in format "yyyy-MM-dd"
+ blameLine.date(DateUtils.parseDate(dateStr));
+ }
+ }
+ return blameLine;
+ }
}
*/
package org.sonar.xoo.scm;
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
import org.apache.commons.io.FileUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
import org.sonar.api.utils.DateUtils;
import org.sonar.xoo.Xoo;
-import java.io.File;
-import java.io.IOException;
-import java.util.Arrays;
-
+import static java.util.Collections.singletonList;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
.setModuleBaseDir(baseDir.toPath())
.build();
fs.add(inputFile);
-
BlameOutput result = mock(BlameOutput.class);
when(input.filesToBlame()).thenReturn(Arrays.asList(inputFile));
+
new XooBlameCommand().blame(input, result);
+
verify(result).blameResult(inputFile, Arrays.asList(
new BlameLine().revision("123").author("julien").date(DateUtils.parseDate("2014-12-12")),
new BlameLine().revision("234").author("julien").date(DateUtils.parseDate("2014-12-24"))));
}
+
+ @Test
+ public void blame_containing_author_with_comma() throws IOException {
+ File source = new File(baseDir, "src/foo.xoo");
+ FileUtils.write(source, "sample content");
+ File scm = new File(baseDir, "src/foo.xoo.scm");
+ FileUtils.write(scm, "\"123\",\"john,doe\",\"2019-01-22\"");
+ DefaultInputFile inputFile = new TestInputFileBuilder("foo", "src/foo.xoo")
+ .setLanguage(Xoo.KEY)
+ .setModuleBaseDir(baseDir.toPath())
+ .build();
+ fs.add(inputFile);
+ BlameOutput result = mock(BlameOutput.class);
+ when(input.filesToBlame()).thenReturn(Arrays.asList(inputFile));
+
+ new XooBlameCommand().blame(input, result);
+
+ verify(result).blameResult(inputFile, singletonList(
+ new BlameLine().revision("123").author("john,doe").date(DateUtils.parseDate("2019-01-22"))));
+ }
}
import static org.sonar.server.es.EsUtils.escapeSpecialRegexChars;
import static org.sonar.server.issue.index.IssueIndex.Facet.ASSIGNED_TO_ME;
import static org.sonar.server.issue.index.IssueIndex.Facet.ASSIGNEES;
+import static org.sonar.server.issue.index.IssueIndex.Facet.AUTHOR;
import static org.sonar.server.issue.index.IssueIndex.Facet.AUTHORS;
import static org.sonar.server.issue.index.IssueIndex.Facet.CREATED_AT;
import static org.sonar.server.issue.index.IssueIndex.Facet.CWE;
import static org.sonar.server.issue.index.SecurityStandardHelper.SANS_TOP_25_POROUS_DEFENSES;
import static org.sonar.server.issue.index.SecurityStandardHelper.SANS_TOP_25_RISKY_RESOURCE;
import static org.sonar.server.issue.index.SecurityStandardHelper.UNKNOWN_STANDARD;
+import static org.sonarqube.ws.client.issue.IssuesWsParameters.DEPRECATED_PARAM_AUTHORS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.FACET_MODE_EFFORT;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ASSIGNEES;
-import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_AUTHORS;
+import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_AUTHOR;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CREATED_AT;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CWE;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_DIRECTORIES;
LANGUAGES(PARAM_LANGUAGES, FIELD_ISSUE_LANGUAGE, MAX_FACET_SIZE),
RULES(PARAM_RULES, FIELD_ISSUE_RULE_ID, MAX_FACET_SIZE),
TAGS(PARAM_TAGS, FIELD_ISSUE_TAGS, MAX_FACET_SIZE),
- AUTHORS(PARAM_AUTHORS, FIELD_ISSUE_AUTHOR_LOGIN, MAX_FACET_SIZE),
+ AUTHORS(DEPRECATED_PARAM_AUTHORS, FIELD_ISSUE_AUTHOR_LOGIN, MAX_FACET_SIZE),
+ AUTHOR(PARAM_AUTHOR, FIELD_ISSUE_AUTHOR_LOGIN, MAX_FACET_SIZE),
PROJECT_UUIDS(FACET_PROJECTS, FIELD_ISSUE_PROJECT_UUID, MAX_FACET_SIZE),
MODULE_UUIDS(PARAM_MODULE_UUIDS, FIELD_ISSUE_MODULE_UUID, MAX_FACET_SIZE),
FILE_UUIDS(PARAM_FILE_UUIDS, FIELD_ISSUE_COMPONENT_UUID, MAX_FACET_SIZE),
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, LANGUAGES, query.languages().toArray());
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, RULES, query.rules().stream().map(RuleDefinitionDto::getId).toArray());
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, AUTHORS, query.authors().toArray());
+ addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, AUTHOR, query.authors().toArray());
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, TAGS, query.tags().toArray());
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, TYPES, query.types().toArray());
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, OWASP_TOP_10, query.owaspTop10().toArray());
if (Double.isInfinite(actualValue)) {
return OptionalLong.empty();
}
- return OptionalLong.of((long)actualValue);
+ return OptionalLong.of((long) actualValue);
}
private void addAssignedToMeFacetIfNeeded(SearchRequestBuilder builder, SearchOptions options, IssueQuery query, Map<String, QueryBuilder> filters, QueryBuilder queryBuilder) {
import static java.util.Collections.singletonList;
import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.toList;
+import static org.sonar.api.server.ws.WebService.Param.FACETS;
import static org.sonar.api.utils.Paging.forPageIndex;
import static org.sonar.core.util.stream.MoreCollectors.toSet;
import static org.sonar.process.ProcessProperties.Property.SONARCLOUD_ENABLED;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_SEARCH;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.DEPRECATED_PARAM_ACTION_PLANS;
+import static org.sonarqube.ws.client.issue.IssuesWsParameters.DEPRECATED_PARAM_AUTHORS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.FACET_MODE;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.FACET_MODE_COUNT;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.FACET_MODE_EFFORT;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ASC;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ASSIGNED;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ASSIGNEES;
-import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_AUTHORS;
+import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_AUTHOR;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_BRANCH;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENTS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_KEYS;
PARAM_RULES,
PARAM_ASSIGNEES,
PARAM_REPORTERS,
- PARAM_AUTHORS,
+ DEPRECATED_PARAM_AUTHORS,
+ PARAM_AUTHOR,
PARAM_DIRECTORIES,
PARAM_LANGUAGES,
PARAM_TAGS,
PARAM_COMPONENT_KEYS, PARAM_COMPONENT_UUIDS, PARAM_COMPONENTS, PARAM_COMPONENT_ROOT_UUIDS, PARAM_COMPONENT_ROOTS)
.setSince("3.6")
.setChangelog(
- new Change("7.6", String.format("The use of module keys in parameter '%s' is deprecated", PARAM_COMPONENT_KEYS)),
+ new Change("7.7", format("Value '%s' in parameter '%s' is deprecated, please use '%s' instead", DEPRECATED_PARAM_AUTHORS, FACETS, PARAM_AUTHOR)),
+ new Change("7.6", format("The use of module keys in parameter '%s' is deprecated", PARAM_COMPONENT_KEYS)),
new Change("7.4", "The facet 'projectUuids' is dropped in favour of the new facet 'projects'. " +
"Note that they are not strictly identical, the latter returns the project keys."),
new Change("7.4", format("Parameter '%s' does not accept anymore deprecated value 'debt'", FACET_MODE)),
.setResponseExample(getClass().getResource("search-example.json"));
action.addPagingParams(100, MAX_LIMIT);
- action.createParam(Param.FACETS)
+ action.createParam(FACETS)
.setDescription("Comma-separated list of the facets to be computed. No facet is computed by default.")
.setPossibleValues(SUPPORTED_FACETS);
action.createParam(FACET_MODE)
action.createParam(PARAM_CWE)
.setDescription("Comma-separated list of CWE identifiers. Use '" + UNKNOWN_STANDARD + "' to select issues not associated to any CWE.")
.setExampleValue("12,125," + UNKNOWN_STANDARD);
- action.createParam(PARAM_AUTHORS)
- .setDescription("Comma-separated list of SCM accounts")
+ action.createParam(DEPRECATED_PARAM_AUTHORS)
+ .setDeprecatedSince("7.7")
+ .setDescription("This parameter is deprecated, please use '%s' instead", PARAM_AUTHOR)
.setExampleValue("torvalds@linux-foundation.org");
+ action.createParam(PARAM_AUTHOR)
+ .setDescription("SCM accounts. To set several values, the parameter must be called once for each value.")
+ .setExampleValue("author=torvalds@linux-foundation.org&author=linux@fondation.org");
action.createParam(PARAM_ASSIGNEES)
.setDescription("Comma-separated list of assignee logins. The value '__me__' can be used as a placeholder for user who performs the request")
.setExampleValue("admin,usera,__me__");
if (!organizationDto.isPresent() || !userSession.hasMembership(organizationDto.get())) {
// In order to display the authors facet, the organization parameter must be set and the user
// must be member of this organization
- requestedFacets.remove(PARAM_AUTHORS);
+ requestedFacets.remove(PARAM_AUTHOR);
+ requestedFacets.remove(DEPRECATED_PARAM_AUTHORS);
}
}
.setAsc(request.mandatoryParamAsBoolean(PARAM_ASC))
.setAssigned(request.paramAsBoolean(PARAM_ASSIGNED))
.setAssigneesUuid(getLogins(dbSession, request.paramAsStrings(PARAM_ASSIGNEES)))
- .setAuthors(request.paramAsStrings(PARAM_AUTHORS))
+ .setAuthors(request.hasParam(PARAM_AUTHOR) ? request.multiParam(PARAM_AUTHOR) : request.paramAsStrings(DEPRECATED_PARAM_AUTHORS))
.setComponentKeys(request.paramAsStrings(PARAM_COMPONENT_KEYS))
.setComponentRootUuids(request.paramAsStrings(PARAM_COMPONENT_ROOT_UUIDS))
.setComponentRoots(request.paramAsStrings(PARAM_COMPONENT_ROOTS))
.setCreatedInLast(request.param(PARAM_CREATED_IN_LAST))
.setDirectories(request.paramAsStrings(PARAM_DIRECTORIES))
.setFacetMode(request.mandatoryParam(FACET_MODE))
- .setFacets(request.paramAsStrings(Param.FACETS))
+ .setFacets(request.paramAsStrings(FACETS))
.setFileUuids(request.paramAsStrings(PARAM_FILE_UUIDS))
.setIssues(request.paramAsStrings(PARAM_ISSUES))
.setLanguages(request.paramAsStrings(PARAM_LANGUAGES))
}
@Test
- public void facets_on_authors() {
+ public void facets_on_author() {
+ ComponentDto project = newPrivateProjectDto(newOrganizationDto());
+ ComponentDto file = newFileDto(project, null);
+
+ indexIssues(
+ newDoc("I1", file).setAuthorLogin("steph"),
+ newDoc("I2", file).setAuthorLogin("marcel"),
+ newDoc("I3", file).setAuthorLogin("marcel"),
+ newDoc("I4", file).setAuthorLogin(null));
+
+ assertThatFacetHasOnly(IssueQuery.builder(), "author", entry("steph", 1L), entry("marcel", 2L));
+ }
+
+ @Test
+ public void facets_on_deprecated_authors() {
ComponentDto project = newPrivateProjectDto(newOrganizationDto());
ComponentDto file = newFileDto(project, null);
import org.sonar.api.resources.Languages;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.rule.RuleKey;
-import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.Durations;
import org.sonar.api.utils.System2;
import org.sonar.db.DbClient;
import org.sonar.db.issue.IssueDto;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.rule.RuleDefinitionDto;
-import org.sonar.db.user.UserDto;
import org.sonar.server.es.EsTester;
import org.sonar.server.issue.IssueFieldsSetter;
import org.sonar.server.issue.TransitionService;
import static org.sonar.db.component.ComponentTesting.newView;
import static org.sonar.db.issue.IssueTesting.newIssue;
import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_BRANCH;
-import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_AUTHORS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENTS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_KEYS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_UUIDS;
.assertJson(this.getClass(), "no_issue.json");
}
- @Test
- public void search_by_author() {
- ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
- ComponentDto file = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1"));
- RuleDefinitionDto rule = db.rules().insert(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
- db.issues().insert(rule, project, file, i -> i.setAuthorLogin("leia").setKee("2bd4eac2-b650-4037-80bc-7b112bd4eac2"));
- db.issues().insert(rule, project, file, i -> i.setAuthorLogin("luke@skywalker.name").setKee("82fd47d4-b650-4037-80bc-7b1182fd47d4"));
- allowAnyoneOnProjects(project);
- indexIssues();
-
- UserDto user = db.users().insertUser();
- db.organizations().addMember(db.getDefaultOrganization(), user);
- userSession.logIn(user).addMembership(db.getDefaultOrganization());
-
- ws.newRequest()
- .setParam(PARAM_AUTHORS, "leia")
- .setParam(WebService.Param.FACETS, "authors")
- .execute()
- .assertJson(this.getClass(), "search_by_authors.json");
-
- ws.newRequest()
- .setParam(PARAM_AUTHORS, "unknown")
- .execute()
- .assertJson(this.getClass(), "no_issue.json");
- }
-
@Test
public void search_by_application_key() {
ComponentDto application = db.components().insertPrivateApplication(db.getDefaultOrganization());
import org.sonarqube.ws.Issues.SearchWsResponse;
import static java.util.Arrays.asList;
+import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.groups.Tuple.tuple;
import static org.junit.rules.ExpectedException.none;
Issue::getAssignee, Issue::getAuthor, Issue::getLine, Issue::getHash, Issue::getTagsList, Issue::getCreationDate, Issue::getUpdateDate)
.containsExactlyInAnyOrder(
tuple(organization.getKey(), issue.getKey(), rule.getKey().toString(), Severity.MAJOR, file.getKey(), RESOLUTION_FIXED, STATUS_RESOLVED, "the message", "10min",
- simon.getLogin(), "John", 42, "a227e508d6646b55a086ee11d63b21e9", asList("bug", "owasp"), formatDateTime(issue.getIssueCreationDate()), formatDateTime(issue.getIssueUpdateDate())));
+ simon.getLogin(), "John", 42, "a227e508d6646b55a086ee11d63b21e9", asList("bug", "owasp"), formatDateTime(issue.getIssueCreationDate()),
+ formatDateTime(issue.getIssueUpdateDate())));
}
@Test
.assertJson(this.getClass(), "empty_result.json");
}
+ @Test
+ public void search_by_author() {
+ ComponentDto project = db.components().insertPublicProject();
+ ComponentDto file = db.components().insertComponent(newFileDto(project, null));
+ RuleDefinitionDto rule = db.rules().insert();
+ IssueDto issue1 = db.issues().insert(rule, project, file, i -> i.setAuthorLogin("leia"));
+ IssueDto issue2 = db.issues().insert(rule, project, file, i -> i.setAuthorLogin("luke"));
+ IssueDto issue3 = db.issues().insert(rule, project, file, i -> i.setAuthorLogin("han, solo"));
+ indexPermissions();
+ indexIssues();
+
+ SearchWsResponse response = ws.newRequest()
+ .setMultiParam("author", asList("leia", "han, solo"))
+ .setParam(FACETS, "author")
+ .executeProtobuf(SearchWsResponse.class);
+ assertThat(response.getIssuesList())
+ .extracting(Issue::getKey)
+ .containsExactlyInAnyOrder(issue1.getKey(), issue3.getKey());
+ Common.Facet facet = response.getFacets().getFacetsList().get(0);
+ assertThat(facet.getProperty()).isEqualTo("author");
+ assertThat(facet.getValuesList())
+ .extracting(Common.FacetValue::getVal, Common.FacetValue::getCount)
+ .containsExactlyInAnyOrder(
+ tuple("leia", 1L),
+ tuple("luke", 1L),
+ tuple("han, solo", 1L));
+
+ assertThat(ws.newRequest()
+ .setMultiParam("author", singletonList("unknown"))
+ .executeProtobuf(SearchWsResponse.class).getIssuesList())
+ .isEmpty();
+ }
+
+ @Test
+ public void search_by_deprecated_authors_parameter() {
+ ComponentDto project = db.components().insertPublicProject();
+ ComponentDto file = db.components().insertComponent(newFileDto(project, null));
+ RuleDefinitionDto rule = db.rules().insert();
+ IssueDto issue1 = db.issues().insert(rule, project, file, i -> i.setAuthorLogin("leia"));
+ IssueDto issue2 = db.issues().insert(rule, project, file, i -> i.setAuthorLogin("luke"));
+ indexPermissions();
+ indexIssues();
+
+ SearchWsResponse response = ws.newRequest()
+ .setParam("authors", "leia")
+ .setParam(FACETS, "authors")
+ .executeProtobuf(SearchWsResponse.class);
+ assertThat(response.getIssuesList()).extracting(Issue::getKey).containsExactlyInAnyOrder(issue1.getKey());
+ Common.Facet facet = response.getFacets().getFacetsList().get(0);
+ assertThat(facet.getProperty()).isEqualTo("authors");
+ assertThat(facet.getValuesList())
+ .extracting(Common.FacetValue::getVal, Common.FacetValue::getCount)
+ .containsExactlyInAnyOrder(
+ tuple("leia", 1L),
+ tuple("luke", 1L));
+
+ // Deprecated parameter 'authors' will be ignored if new parameter 'author' is set
+ assertThat(ws.newRequest()
+ .setMultiParam("author", singletonList("luke"))
+ // This parameter will be ignored
+ .setParam("authors", "leia")
+ .executeProtobuf(SearchWsResponse.class).getIssuesList())
+ .extracting(Issue::getKey)
+ .containsExactlyInAnyOrder(issue2.getKey());
+ }
+
@Test
public void sort_by_updated_at() {
RuleDto rule = newRule();
assertThat(def.responseExampleAsString()).isNotEmpty();
assertThat(def.params()).extracting("key").containsExactlyInAnyOrder(
- "additionalFields", "asc", "assigned", "assignees", "authors", "componentKeys", "componentRootUuids", "componentRoots", "componentUuids", "components", "branch",
+ "additionalFields", "asc", "assigned", "assignees", "authors", "author", "componentKeys", "componentRootUuids", "componentRoots", "componentUuids", "components", "branch",
"pullRequest", "organization",
"createdAfter", "createdAt", "createdBefore", "createdInLast", "directories", "facetMode", "facets", "fileUuids", "issues", "languages", "moduleUuids", "onComponentOnly",
"p", "projects", "ps", "resolutions", "resolved", "rules", "s", "severities", "sinceLeakPeriod",
+++ /dev/null
-{
- "total": 1,
- "p": 1,
- "issues": [
- {
- "key": "2bd4eac2-b650-4037-80bc-7b112bd4eac2",
- "component": "FK1",
- "project": "PK1",
- "rule": "xoo:x1",
- "author": "leia"
- }
- ],
- "facets": [
- {
- "property": "authors",
- "values": [
- {
- "val": "leia",
- "count": 1
- },
- {
- "val": "luke@skywalker.name",
- "count": 1
- }
- ]
- }
- ]
-}
@Deprecated
public static final String PARAM_REPORTERS = "reporters";
public static final String PARAM_ASSIGNEES = "assignees";
- public static final String PARAM_AUTHORS = "authors";
+
+ /**
+ * @deprecated since 7.7, please use 'author' instead
+ */
+ @Deprecated
+ public static final String DEPRECATED_PARAM_AUTHORS = "authors";
+
+ public static final String PARAM_AUTHOR = "author";
public static final String PARAM_LANGUAGES = "languages";
public static final String PARAM_TAGS = "tags";
public static final String PARAM_TYPES = "types";
.setParam("componentUuid", request.getComponentUuid())
.setParam("createdAfter", request.getCreatedAfter())
.setParam("ps", request.getPs())
- .setMediaType(MediaTypes.JSON)).content();
+ .setMediaType(MediaTypes.JSON)
+ ).content();
}
/**
new PostRequest(path("edit_comment"))
.setParam("comment", request.getComment())
.setParam("text", request.getText())
- .setMediaType(MediaTypes.JSON)).content();
+ .setMediaType(MediaTypes.JSON)
+ ).content();
}
/**
.setParam("asc", request.getAsc())
.setParam("assigned", request.getAssigned())
.setParam("assignees", request.getAssignees() == null ? null : request.getAssignees().stream().collect(Collectors.joining(",")))
+ .setParam("author", request.getAuthor())
.setParam("authors", request.getAuthors() == null ? null : request.getAuthors().stream().collect(Collectors.joining(",")))
.setParam("branch", request.getBranch())
.setParam("componentKeys", request.getComponentKeys() == null ? null : request.getComponentKeys().stream().collect(Collectors.joining(",")))
.setParam("createdAt", request.getCreatedAt())
.setParam("createdBefore", request.getCreatedBefore())
.setParam("createdInLast", request.getCreatedInLast())
+ .setParam("cwe", request.getCwe() == null ? null : request.getCwe().stream().collect(Collectors.joining(",")))
.setParam("directories", request.getDirectories() == null ? null : request.getDirectories().stream().collect(Collectors.joining(",")))
.setParam("facetMode", request.getFacetMode())
.setParam("facets", request.getFacets() == null ? null : request.getFacets().stream().collect(Collectors.joining(",")))
.setParam("moduleUuids", request.getModuleUuids() == null ? null : request.getModuleUuids().stream().collect(Collectors.joining(",")))
.setParam("onComponentOnly", request.getOnComponentOnly())
.setParam("organization", request.getOrganization())
+ .setParam("owaspTop10", request.getOwaspTop10() == null ? null : request.getOwaspTop10().stream().collect(Collectors.joining(",")))
.setParam("p", request.getP())
.setParam("projects", request.getProjects() == null ? null : request.getProjects().stream().collect(Collectors.joining(",")))
.setParam("ps", request.getPs())
.setParam("resolved", request.getResolved())
.setParam("rules", request.getRules() == null ? null : request.getRules().stream().collect(Collectors.joining(",")))
.setParam("s", request.getS())
+ .setParam("sansTop25", request.getSansTop25() == null ? null : request.getSansTop25().stream().collect(Collectors.joining(",")))
.setParam("severities", request.getSeverities() == null ? null : request.getSeverities().stream().collect(Collectors.joining(",")))
.setParam("sinceLeakPeriod", request.getSinceLeakPeriod())
.setParam("statuses", request.getStatuses() == null ? null : request.getStatuses().stream().collect(Collectors.joining(",")))
.setParam("tags", request.getTags() == null ? null : request.getTags().stream().collect(Collectors.joining(",")))
- .setParam("types", request.getTypes() == null ? null : request.getTypes().stream().collect(Collectors.joining(",")))
- .setParam("owaspTop10", request.getOwaspTop10() == null ? null : request.getOwaspTop10().stream().collect(Collectors.joining(",")))
- .setParam("sansTop25", request.getSansTop25() == null ? null : request.getSansTop25().stream().collect(Collectors.joining(",")))
- .setParam("cwe", request.getCwe() == null ? null : request.getCwe().stream().collect(Collectors.joining(","))),
+ .setParam("types", request.getTypes() == null ? null : request.getTypes().stream().collect(Collectors.joining(","))),
SearchWsResponse.parser());
}
private String asc;
private String assigned;
private List<String> assignees;
+ private List<String> author;
private List<String> authors;
private String branch;
private List<String> componentKeys;
return assignees;
}
+ /**
+ * Example value: "author=torvalds@linux-foundation.org&author=linux@fondation.org"
+ */
+ public SearchRequest setAuthor(List<String> author) {
+ this.author = author;
+ return this;
+ }
+
+ public List<String> getAuthor() {
+ return author;
+ }
+
/**
* Example value: "torvalds@linux-foundation.org"
+ * @deprecated since 7.7
*/
+ @Deprecated
public SearchRequest setAuthors(List<String> authors) {
this.authors = authors;
return this;
* <ul>
* <li>"count"</li>
* <li>"effort"</li>
- * <li>"debt"</li>
* </ul>
*/
public SearchRequest setFacetMode(String facetMode) {
/**
* Possible values:
* <ul>
+ * <li>"projects"</li>
+ * <li>"moduleUuids"</li>
+ * <li>"fileUuids"</li>
+ * <li>"assigned_to_me"</li>
* <li>"severities"</li>
* <li>"statuses"</li>
* <li>"resolutions"</li>
* <li>"actionPlans"</li>
- * <li>"projectUuids"</li>
* <li>"rules"</li>
* <li>"assignees"</li>
- * <li>"assigned_to_me"</li>
* <li>"reporters"</li>
* <li>"authors"</li>
- * <li>"moduleUuids"</li>
- * <li>"fileUuids"</li>
+ * <li>"author"</li>
* <li>"directories"</li>
* <li>"languages"</li>
* <li>"tags"</li>
/**
* This is part of the internal API.
* Example value: "7d8749e8-3070-4903-9188-bdd82933bb92"
+ * @deprecated since 7.6
*/
+ @Deprecated
public SearchRequest setModuleUuids(List<String> moduleUuids) {
this.moduleUuids = moduleUuids;
return this;