You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SearchActionIT.java 89KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2023 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. package org.sonar.server.issue.ws;
  21. import com.google.common.collect.Sets;
  22. import com.google.gson.JsonElement;
  23. import com.google.gson.JsonParser;
  24. import java.time.Clock;
  25. import java.util.Arrays;
  26. import java.util.Collections;
  27. import java.util.List;
  28. import java.util.Random;
  29. import java.util.Set;
  30. import java.util.function.Consumer;
  31. import java.util.stream.Collectors;
  32. import java.util.stream.IntStream;
  33. import java.util.stream.Stream;
  34. import org.junit.Before;
  35. import org.junit.Rule;
  36. import org.junit.Test;
  37. import org.sonar.api.resources.Languages;
  38. import org.sonar.api.rule.RuleStatus;
  39. import org.sonar.api.rules.RuleType;
  40. import org.sonar.api.server.ws.WebService;
  41. import org.sonar.api.utils.Durations;
  42. import org.sonar.api.utils.System2;
  43. import org.sonar.api.web.UserRole;
  44. import org.sonar.core.util.UuidFactoryFast;
  45. import org.sonar.core.util.Uuids;
  46. import org.sonar.db.DbClient;
  47. import org.sonar.db.DbSession;
  48. import org.sonar.db.DbTester;
  49. import org.sonar.db.component.BranchType;
  50. import org.sonar.db.component.ComponentDto;
  51. import org.sonar.db.component.ProjectData;
  52. import org.sonar.db.component.SnapshotDto;
  53. import org.sonar.db.issue.IssueChangeDto;
  54. import org.sonar.db.issue.IssueDto;
  55. import org.sonar.db.permission.GroupPermissionDto;
  56. import org.sonar.db.project.ProjectDto;
  57. import org.sonar.db.protobuf.DbCommons;
  58. import org.sonar.db.protobuf.DbIssues;
  59. import org.sonar.db.rule.RuleDto;
  60. import org.sonar.db.rule.RuleTesting;
  61. import org.sonar.db.user.UserDto;
  62. import org.sonar.server.es.EsTester;
  63. import org.sonar.server.es.SearchOptions;
  64. import org.sonar.server.common.avatar.AvatarResolverImpl;
  65. import org.sonar.server.issue.IssueFieldsSetter;
  66. import org.sonar.server.issue.TextRangeResponseFormatter;
  67. import org.sonar.server.issue.TransitionService;
  68. import org.sonar.server.issue.index.IssueIndex;
  69. import org.sonar.server.issue.index.IssueIndexSyncProgressChecker;
  70. import org.sonar.server.issue.index.IssueIndexer;
  71. import org.sonar.server.issue.index.IssueIteratorFactory;
  72. import org.sonar.server.issue.index.IssueQuery;
  73. import org.sonar.server.issue.index.IssueQueryFactory;
  74. import org.sonar.server.issue.workflow.FunctionExecutor;
  75. import org.sonar.server.issue.workflow.IssueWorkflow;
  76. import org.sonar.server.permission.index.PermissionIndexer;
  77. import org.sonar.server.permission.index.WebAuthorizationTypeSupport;
  78. import org.sonar.server.tester.UserSessionRule;
  79. import org.sonar.server.ws.MessageFormattingUtils;
  80. import org.sonar.server.ws.TestRequest;
  81. import org.sonar.server.ws.TestResponse;
  82. import org.sonar.server.ws.WsActionTester;
  83. import org.sonarqube.ws.Common;
  84. import org.sonarqube.ws.Common.Severity;
  85. import org.sonarqube.ws.Issues.Issue;
  86. import org.sonarqube.ws.Issues.SearchWsResponse;
  87. import static java.util.Arrays.asList;
  88. import static java.util.Collections.singletonList;
  89. import static org.apache.commons.lang.StringUtils.EMPTY;
  90. import static org.assertj.core.api.Assertions.assertThat;
  91. import static org.assertj.core.api.Assertions.assertThatThrownBy;
  92. import static org.assertj.core.groups.Tuple.tuple;
  93. import static org.sonar.api.issue.Issue.RESOLUTION_FIXED;
  94. import static org.sonar.api.issue.Issue.STATUS_OPEN;
  95. import static org.sonar.api.issue.Issue.STATUS_RESOLVED;
  96. import static org.sonar.api.resources.Qualifiers.UNIT_TEST_FILE;
  97. import static org.sonar.api.rules.RuleType.CODE_SMELL;
  98. import static org.sonar.api.server.ws.WebService.Param.FACETS;
  99. import static org.sonar.api.utils.DateUtils.formatDateTime;
  100. import static org.sonar.api.utils.DateUtils.parseDate;
  101. import static org.sonar.api.utils.DateUtils.parseDateTime;
  102. import static org.sonar.api.web.UserRole.ISSUE_ADMIN;
  103. import static org.sonar.db.component.ComponentTesting.newFileDto;
  104. import static org.sonar.db.issue.IssueTesting.newIssue;
  105. import static org.sonar.db.protobuf.DbIssues.MessageFormattingType.CODE;
  106. import static org.sonar.db.rule.RuleDescriptionSectionDto.createDefaultRuleDescriptionSection;
  107. import static org.sonar.db.rule.RuleTesting.XOO_X1;
  108. import static org.sonar.db.rule.RuleTesting.XOO_X2;
  109. import static org.sonar.db.rule.RuleTesting.newRule;
  110. import static org.sonar.server.issue.CommentAction.COMMENT_KEY;
  111. import static org.sonar.server.tester.UserSessionRule.standalone;
  112. import static org.sonarqube.ws.Common.RuleType.BUG;
  113. import static org.sonarqube.ws.Common.RuleType.SECURITY_HOTSPOT_VALUE;
  114. import static org.sonarqube.ws.Common.RuleType.VULNERABILITY;
  115. import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_BRANCH;
  116. import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_ASSIGN;
  117. import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_SET_TAGS;
  118. import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ADDITIONAL_FIELDS;
  119. import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ASSIGNEES;
  120. import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CODE_VARIANTS;
  121. import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENTS;
  122. import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CREATED_AFTER;
  123. import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_HIDE_COMMENTS;
  124. import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_IN_NEW_CODE_PERIOD;
  125. import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PULL_REQUEST;
  126. import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_RULES;
  127. import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_STATUSES;
  128. public class SearchActionIT {
  129. public static final DbIssues.MessageFormatting MESSAGE_FORMATTING = DbIssues.MessageFormatting.newBuilder()
  130. .setStart(0).setEnd(11).setType(CODE).build();
  131. private final UuidFactoryFast uuidFactory = UuidFactoryFast.getInstance();
  132. @Rule
  133. public UserSessionRule userSession = standalone();
  134. @Rule
  135. public DbTester db = DbTester.create();
  136. @Rule
  137. public EsTester es = EsTester.create();
  138. private final DbClient dbClient = db.getDbClient();
  139. private final DbSession session = db.getSession();
  140. private final IssueIndex issueIndex = new IssueIndex(es.client(), System2.INSTANCE, userSession, new WebAuthorizationTypeSupport(userSession));
  141. private final IssueIndexer issueIndexer = new IssueIndexer(es.client(), dbClient, new IssueIteratorFactory(dbClient), null);
  142. private final IssueQueryFactory issueQueryFactory = new IssueQueryFactory(dbClient, Clock.systemUTC(), userSession);
  143. private final IssueFieldsSetter issueFieldsSetter = new IssueFieldsSetter();
  144. private final IssueWorkflow issueWorkflow = new IssueWorkflow(new FunctionExecutor(issueFieldsSetter), issueFieldsSetter);
  145. private final SearchResponseLoader searchResponseLoader = new SearchResponseLoader(userSession, dbClient, new TransitionService(userSession, issueWorkflow));
  146. private final Languages languages = new Languages();
  147. private final UserResponseFormatter userFormatter = new UserResponseFormatter(new AvatarResolverImpl());
  148. private final SearchResponseFormat searchResponseFormat = new SearchResponseFormat(new Durations(), languages, new TextRangeResponseFormatter(), userFormatter);
  149. private final IssueIndexSyncProgressChecker issueIndexSyncProgressChecker = new IssueIndexSyncProgressChecker(dbClient);
  150. private final WsActionTester ws = new WsActionTester(
  151. new SearchAction(userSession, issueIndex, issueQueryFactory, issueIndexSyncProgressChecker, searchResponseLoader, searchResponseFormat, System2.INSTANCE, dbClient));
  152. private final PermissionIndexer permissionIndexer = new PermissionIndexer(dbClient, es.client(), issueIndexer);
  153. @Before
  154. public void setUp() {
  155. issueWorkflow.start();
  156. }
  157. @Test
  158. public void givenPrivateProject_responseContainsAllFieldsExceptAdditionalFields() {
  159. UserDto user = db.users().insertUser();
  160. userSession.logIn(user);
  161. ProjectData projectData = db.components().insertPrivateProject();
  162. ProjectDto projectDto = projectData.getProjectDto();
  163. db.users().insertProjectPermissionOnUser(user, UserRole.USER, projectDto);
  164. ComponentDto project = projectData.getMainBranchComponent();
  165. ComponentDto file = db.components().insertComponent(newFileDto(project));
  166. UserDto simon = db.users().insertUser();
  167. RuleDto rule = newIssueRule();
  168. IssueDto issue = db.issues().insertIssue(rule, project, file, i -> i
  169. .setEffort(10L)
  170. .setLine(42)
  171. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  172. .setMessage("the message")
  173. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  174. .setStatus(STATUS_RESOLVED)
  175. .setResolution(RESOLUTION_FIXED)
  176. .setSeverity("MAJOR")
  177. .setAuthorLogin("John")
  178. .setAssigneeUuid(simon.getUuid())
  179. .setTags(asList("bug", "owasp"))
  180. .setIssueCreationDate(parseDate("2014-09-03"))
  181. .setIssueUpdateDate(parseDate("2017-12-04"))
  182. .setCodeVariants(List.of("variant1", "variant2")));
  183. indexPermissionsAndIssues();
  184. SearchWsResponse response = ws.newRequest()
  185. .executeProtobuf(SearchWsResponse.class);
  186. assertThat(response.getIssuesList())
  187. .extracting(
  188. Issue::getKey, Issue::getRule, Issue::getSeverity, Issue::getComponent, Issue::getResolution, Issue::getStatus, Issue::getMessage, Issue::getMessageFormattingsList,
  189. Issue::getEffort, Issue::getAssignee, Issue::getAuthor, Issue::getLine, Issue::getHash, Issue::getTagsList, Issue::getCreationDate, Issue::getUpdateDate,
  190. Issue::getQuickFixAvailable, Issue::getCodeVariantsList)
  191. .containsExactlyInAnyOrder(
  192. tuple(issue.getKey(), rule.getKey().toString(), Severity.MAJOR, file.getKey(), RESOLUTION_FIXED, STATUS_RESOLVED, "the message",
  193. MessageFormattingUtils.dbMessageFormattingListToWs(List.of(MESSAGE_FORMATTING)), "10min",
  194. simon.getLogin(), "John", 42, "a227e508d6646b55a086ee11d63b21e9", asList("bug", "owasp"), formatDateTime(issue.getIssueCreationDate()),
  195. formatDateTime(issue.getIssueUpdateDate()), false, List.of("variant1", "variant2")));
  196. }
  197. @Test
  198. public void response_contains_correct_actions() {
  199. UserDto user = db.users().insertUser();
  200. userSession.logIn(user);
  201. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  202. ComponentDto file = db.components().insertComponent(newFileDto(project));
  203. RuleDto rule = newIssueRule();
  204. db.issues().insertIssue(rule, project, file, i -> i.setStatus(STATUS_OPEN));
  205. db.issues().insertIssue(rule, project, file, i -> i.setStatus(STATUS_RESOLVED).setResolution(RESOLUTION_FIXED));
  206. indexPermissionsAndIssues();
  207. SearchWsResponse response = ws.newRequest()
  208. .setParam(PARAM_ADDITIONAL_FIELDS, "actions")
  209. .setParam(PARAM_STATUSES, STATUS_OPEN)
  210. .executeProtobuf(SearchWsResponse.class);
  211. assertThat(
  212. response
  213. .getIssuesList()
  214. .get(0)
  215. .getActions()
  216. .getActionsList()).isEqualTo(asList(ACTION_SET_TAGS, COMMENT_KEY, ACTION_ASSIGN));
  217. response = ws.newRequest()
  218. .setParam(PARAM_ADDITIONAL_FIELDS, "actions")
  219. .setParam(PARAM_STATUSES, STATUS_RESOLVED)
  220. .executeProtobuf(SearchWsResponse.class);
  221. assertThat(
  222. response
  223. .getIssuesList()
  224. .get(0)
  225. .getActions()
  226. .getActionsList()).isEqualTo(asList(ACTION_SET_TAGS, COMMENT_KEY));
  227. }
  228. @Test
  229. public void issue_on_external_rule() {
  230. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  231. ComponentDto file = db.components().insertComponent(newFileDto(project));
  232. RuleDto rule = db.rules().insertIssueRule(RuleTesting.EXTERNAL_XOO, r -> r.setIsExternal(true).setLanguage("xoo"));
  233. IssueDto issue = db.issues().insertIssue(rule, project, file);
  234. indexPermissionsAndIssues();
  235. SearchWsResponse response = ws.newRequest()
  236. .executeProtobuf(SearchWsResponse.class);
  237. assertThat(response.getIssuesList())
  238. .extracting(Issue::getKey, Issue::getRule, Issue::getExternalRuleEngine)
  239. .containsExactlyInAnyOrder(tuple(issue.getKey(), rule.getKey().toString(), "xoo"));
  240. }
  241. @Test
  242. public void issue_on_external_adhoc_rule_without_metadata() {
  243. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  244. indexPermissions();
  245. ComponentDto file = db.components().insertComponent(newFileDto(project));
  246. RuleDto rule = db.rules().insertIssueRule(RuleTesting.EXTERNAL_XOO, r -> r.setIsExternal(true)
  247. .setName("xoo:x1:name")
  248. .setAdHocName(null)
  249. .setLanguage("xoo")
  250. .setIsAdHoc(true));
  251. IssueDto issue = db.issues().insertIssue(rule, project, file);
  252. indexIssues();
  253. SearchWsResponse response = ws.newRequest()
  254. .setParam("additionalFields", "rules")
  255. .executeProtobuf(SearchWsResponse.class);
  256. assertThat(response.getIssuesList())
  257. .extracting(Issue::getKey, Issue::getRule, Issue::getExternalRuleEngine)
  258. .containsExactlyInAnyOrder(tuple(issue.getKey(), rule.getKey().toString(), "xoo"));
  259. assertThat((response.getRules().getRulesList()))
  260. .extracting(Common.Rule::getKey, Common.Rule::getName)
  261. .containsExactlyInAnyOrder(tuple(rule.getKey().toString(), rule.getName()));
  262. }
  263. @Test
  264. public void issue_on_external_adhoc_rule_with_metadata() {
  265. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  266. indexPermissions();
  267. ComponentDto file = db.components().insertComponent(newFileDto(project));
  268. RuleDto rule = db.rules().insertIssueRule(RuleTesting.EXTERNAL_XOO,
  269. r -> r
  270. .setIsExternal(true)
  271. .setLanguage("xoo")
  272. .setIsAdHoc(true)
  273. .setAdHocName("different_rule_name"));
  274. IssueDto issue = db.issues().insertIssue(rule, project, file);
  275. indexIssues();
  276. SearchWsResponse response = ws.newRequest()
  277. .setParam("additionalFields", "rules")
  278. .executeProtobuf(SearchWsResponse.class);
  279. assertThat(response.getIssuesList())
  280. .extracting(Issue::getKey, Issue::getRule, Issue::getExternalRuleEngine)
  281. .containsExactlyInAnyOrder(tuple(issue.getKey(), rule.getKey().toString(), "xoo"));
  282. assertThat(response.getRules().getRulesList())
  283. .extracting(Common.Rule::getKey, Common.Rule::getName)
  284. .containsExactlyInAnyOrder(tuple(rule.getKey().toString(), rule.getAdHocName()));
  285. }
  286. @Test
  287. public void issue_with_cross_file_locations() {
  288. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  289. indexPermissions();
  290. ComponentDto file = db.components().insertComponent(newFileDto(project));
  291. ComponentDto anotherFile = db.components().insertComponent(newFileDto(project));
  292. DbIssues.Locations.Builder locations = DbIssues.Locations.newBuilder().addFlow(DbIssues.Flow.newBuilder().addAllLocation(Arrays.asList(
  293. DbIssues.Location.newBuilder()
  294. .setComponentId(file.uuid())
  295. .setMsg("FLOW MESSAGE")
  296. .setTextRange(DbCommons.TextRange.newBuilder()
  297. .setStartLine(1)
  298. .setEndLine(1)
  299. .setStartOffset(0)
  300. .setEndOffset(12)
  301. .build())
  302. .build(),
  303. DbIssues.Location.newBuilder()
  304. .setComponentId(anotherFile.uuid())
  305. .setMsg("ANOTHER FLOW MESSAGE")
  306. .addMsgFormatting(DbIssues.MessageFormatting.newBuilder().setStart(0).setEnd(20).setType(CODE).build())
  307. .setTextRange(DbCommons.TextRange.newBuilder()
  308. .setStartLine(1)
  309. .setEndLine(1)
  310. .setStartOffset(0)
  311. .setEndOffset(12)
  312. .build())
  313. .build(),
  314. DbIssues.Location.newBuilder()
  315. // .setComponentId(no component id set)
  316. .setMsg("FLOW MESSAGE WITHOUT FILE UUID")
  317. .setTextRange(DbCommons.TextRange.newBuilder()
  318. .setStartLine(1)
  319. .setEndLine(1)
  320. .setStartOffset(0)
  321. .setEndOffset(12)
  322. .build())
  323. .build())));
  324. RuleDto rule = newIssueRule();
  325. db.issues().insertIssue(rule, project, file, i -> i.setLocations(locations.build()));
  326. indexIssues();
  327. SearchWsResponse result = ws.newRequest().executeProtobuf(SearchWsResponse.class);
  328. assertThat(result.getIssuesCount()).isOne();
  329. assertThat(result.getIssues(0).getFlows(0).getLocationsList()).extracting(Common.Location::getComponent, Common.Location::getMsg, Common.Location::getMsgFormattingsList)
  330. .containsExactlyInAnyOrder(
  331. tuple(file.getKey(), "FLOW MESSAGE", List.of()),
  332. tuple(anotherFile.getKey(), "ANOTHER FLOW MESSAGE", List.of(Common.MessageFormatting.newBuilder()
  333. .setStart(0).setEnd(20).setType(Common.MessageFormattingType.CODE).build())),
  334. tuple(file.getKey(), "FLOW MESSAGE WITHOUT FILE UUID", List.of()));
  335. }
  336. @Test
  337. public void issue_with_comments() {
  338. UserDto john = db.users().insertUser(u -> u.setLogin("john").setName("John"));
  339. UserDto fabrice = db.users().insertUser(u -> u.setLogin("fabrice").setName("Fabrice").setEmail("fabrice@email.com"));
  340. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  341. indexPermissions();
  342. ComponentDto file = db.components().insertComponent(newFileDto(project));
  343. RuleDto rule = newIssueRule();
  344. IssueDto issue = db.issues().insertIssue(rule, project, file, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
  345. dbClient.issueChangeDao().insert(session,
  346. new IssueChangeDto()
  347. .setUuid(Uuids.createFast())
  348. .setIssueKey(issue.getKey())
  349. .setKey("COMMENT-ABCD")
  350. .setChangeData("*My comment*")
  351. .setChangeType(IssueChangeDto.TYPE_COMMENT)
  352. .setUserUuid(john.getUuid())
  353. .setProjectUuid(project.branchUuid())
  354. .setIssueChangeCreationDate(parseDateTime("2014-09-09T12:00:00+0000").getTime()));
  355. dbClient.issueChangeDao().insert(session,
  356. new IssueChangeDto()
  357. .setUuid(Uuids.createFast())
  358. .setIssueKey(issue.getKey())
  359. .setKey("COMMENT-ABCE")
  360. .setChangeData("Another comment")
  361. .setChangeType(IssueChangeDto.TYPE_COMMENT)
  362. .setUserUuid(fabrice.getUuid())
  363. .setProjectUuid(project.branchUuid())
  364. .setIssueChangeCreationDate(parseDateTime("2014-09-10T12:00:00+0000").getTime()));
  365. dbClient.issueChangeDao().insert(session,
  366. new IssueChangeDto()
  367. .setUuid(Uuids.createFast())
  368. .setIssueKey(issue.getKey())
  369. .setKey("COMMENT-NO-USER")
  370. .setChangeData("Another comment without user")
  371. .setChangeType(IssueChangeDto.TYPE_COMMENT)
  372. .setProjectUuid(project.branchUuid())
  373. .setIssueChangeCreationDate(parseDateTime("2022-09-10T12:00:00+0000").getTime()));
  374. session.commit();
  375. indexIssues();
  376. userSession.logIn(john);
  377. ws.newRequest()
  378. .setParam("additionalFields", "comments,users")
  379. .execute()
  380. .assertJson(this.getClass(), "issue_with_comments.json");
  381. }
  382. @Test
  383. public void issue_with_comment_hidden() {
  384. UserDto john = db.users().insertUser(u -> u.setLogin("john").setName("John").setEmail("john@email.com"));
  385. UserDto fabrice = db.users().insertUser(u -> u.setLogin("fabrice").setName("Fabrice").setEmail("fabrice@email.com"));
  386. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  387. indexPermissions();
  388. ComponentDto file = db.components().insertComponent(newFileDto(project));
  389. RuleDto rule = newIssueRule();
  390. IssueDto issue = db.issues().insertIssue(rule, project, file, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
  391. dbClient.issueChangeDao().insert(session,
  392. new IssueChangeDto()
  393. .setUuid(Uuids.createFast())
  394. .setIssueKey(issue.getKey())
  395. .setKey("COMMENT-ABCD")
  396. .setChangeData("*My comment*")
  397. .setChangeType(IssueChangeDto.TYPE_COMMENT)
  398. .setUserUuid(john.getUuid())
  399. .setProjectUuid(project.branchUuid())
  400. .setCreatedAt(parseDateTime("2014-09-09T12:00:00+0000").getTime()));
  401. dbClient.issueChangeDao().insert(session,
  402. new IssueChangeDto()
  403. .setUuid(Uuids.createFast())
  404. .setIssueKey(issue.getKey())
  405. .setKey("COMMENT-ABCE")
  406. .setChangeData("Another comment")
  407. .setChangeType(IssueChangeDto.TYPE_COMMENT)
  408. .setUserUuid(fabrice.getUuid())
  409. .setProjectUuid(project.branchUuid())
  410. .setCreatedAt(parseDateTime("2014-09-10T19:10:03+0000").getTime()));
  411. session.commit();
  412. indexIssues();
  413. userSession.logIn(john);
  414. SearchWsResponse response = ws.newRequest()
  415. .setParam(PARAM_HIDE_COMMENTS, "true")
  416. .executeProtobuf(SearchWsResponse.class);
  417. assertThat(response.getIssuesList())
  418. .extracting(Issue::getKey, i -> i.getComments().getCommentsList())
  419. .containsExactlyInAnyOrder(tuple(issue.getKey(), Collections.emptyList()));
  420. }
  421. @Test
  422. public void load_additional_fields() {
  423. UserDto simon = db.users().insertUser(u -> u.setLogin("simon").setName("Simon").setEmail("simon@email.com"));
  424. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  425. indexPermissions();
  426. ComponentDto file = db.components().insertComponent(newFileDto(project));
  427. RuleDto rule = newIssueRule();
  428. db.issues().insertIssue(rule, project, file, i -> i.setAssigneeUuid(simon.getUuid()).setType(CODE_SMELL));
  429. indexIssues();
  430. userSession.logIn("john");
  431. ws.newRequest()
  432. .setParam("additionalFields", "_all").execute()
  433. .assertJson(this.getClass(), "load_additional_fields.json");
  434. }
  435. @Test
  436. public void load_additional_fields_with_issue_admin_permission() {
  437. UserDto simon = db.users().insertUser(u -> u.setLogin("simon").setName("Simon").setEmail("simon@email.com"));
  438. UserDto fabrice = db.users().insertUser(u -> u.setLogin("fabrice").setName("Fabrice").setEmail("fabrice@email.com"));
  439. ProjectData project = db.components().insertPublicProject("PROJECT_ID",
  440. c -> c.setKey("PROJECT_KEY").setName("NAME_PROJECT_ID").setLongName("LONG_NAME_PROJECT_ID").setLanguage("java"));
  441. grantPermissionToAnyone(project.getProjectDto(), ISSUE_ADMIN);
  442. indexPermissions();
  443. ComponentDto file = db.components().insertComponent(newFileDto(project.getMainBranchComponent(), null, "FILE_ID").setKey("FILE_KEY").setLanguage("js"));
  444. IssueDto issue = newIssue(newIssueRule(), project.getMainBranchComponent(), file)
  445. .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
  446. .setAuthorLogin(fabrice.getLogin())
  447. .setAssigneeUuid(simon.getUuid());
  448. dbClient.issueDao().insert(session, issue);
  449. session.commit();
  450. indexIssues();
  451. userSession.logIn("john")
  452. .addProjectPermission(ISSUE_ADMIN, project.getMainBranchComponent()); // granted by Anyone
  453. ws.newRequest()
  454. .setParam("additionalFields", "_all").execute()
  455. .assertJson(this.getClass(), "load_additional_fields_with_issue_admin_permission.json");
  456. }
  457. @Test
  458. public void search_by_rule_key() {
  459. RuleDto rule = newIssueRule();
  460. ComponentDto project = db.components().insertPublicProject("PROJECT_ID",
  461. c -> c.setKey("PROJECT_KEY").setName("NAME_PROJECT_ID").setLongName("LONG_NAME_PROJECT_ID").setLanguage("java")).getMainBranchComponent();
  462. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setKey("FILE_KEY").setLanguage("java"));
  463. db.issues().insertIssue(rule, project, file);
  464. session.commit();
  465. indexIssues();
  466. userSession.logIn("john")
  467. .addProjectPermission(ISSUE_ADMIN, project); // granted by Anyone
  468. indexPermissions();
  469. TestResponse execute = ws.newRequest()
  470. .setParam(PARAM_RULES, rule.getKey().toString())
  471. .setParam("additionalFields", "_all")
  472. .execute();
  473. execute.assertJson(this.getClass(), "result_for_rule_search.json");
  474. }
  475. @Test
  476. public void search_adhoc_issue_by_rule_key_returns_correct_rule_name() {
  477. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  478. ComponentDto file = db.components().insertComponent(newFileDto(project));
  479. RuleDto rule = db.rules().insertIssueRule(RuleTesting.EXTERNAL_XOO, r -> r.setIsExternal(true)
  480. .setIsAdHoc(true)
  481. .setLanguage("xoo")
  482. .setName(RuleTesting.EXTERNAL_XOO.toString())
  483. .setAdHocName("adHocRuleName"));
  484. db.issues().insertIssue(rule, project, file);
  485. indexPermissionsAndIssues();
  486. SearchWsResponse response = ws.newRequest()
  487. .setParam(PARAM_RULES, rule.getKey().toString())
  488. .setParam("additionalFields", "_all")
  489. .executeProtobuf(SearchWsResponse.class);
  490. assertThat(response.getRules().getRulesList())
  491. .extracting(Common.Rule::getKey, Common.Rule::getName)
  492. .containsExactlyInAnyOrder(tuple(rule.getKey().toString(), rule.getAdHocName()));
  493. }
  494. @Test
  495. public void search_by_non_existing_rule_key() {
  496. RuleDto rule = newIssueRule();
  497. ComponentDto project = db.components().insertPublicProject("PROJECT_ID",
  498. c -> c.setKey("PROJECT_KEY").setName("NAME_PROJECT_ID").setLongName("LONG_NAME_PROJECT_ID").setLanguage("java")).getMainBranchComponent();
  499. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setKey("FILE_KEY").setLanguage("java"));
  500. db.issues().insertIssue(rule, project, file);
  501. session.commit();
  502. indexIssues();
  503. userSession.logIn("john")
  504. .addProjectPermission(ISSUE_ADMIN, project); // granted by Anyone
  505. indexPermissions();
  506. TestResponse execute = ws.newRequest()
  507. .setParam(PARAM_RULES, "nonexisting:rulekey")
  508. .setParam("additionalFields", "_all")
  509. .execute();
  510. execute.assertJson(this.getClass(), "no_issue.json");
  511. }
  512. @Test
  513. public void search_by_variants_with_facets() {
  514. RuleDto rule = newIssueRule();
  515. ComponentDto project = db.components().insertPublicProject("PROJECT_ID",
  516. c -> c.setKey("PROJECT_KEY").setName("NAME_PROJECT_ID").setLongName("LONG_NAME_PROJECT_ID").setLanguage("java")).getMainBranchComponent();
  517. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setKey("FILE_KEY").setLanguage("java"));
  518. db.issues().insertIssue(rule, project, file, i -> i.setCodeVariants(List.of("variant1")));
  519. db.issues().insertIssue(rule, project, file, i -> i.setCodeVariants(List.of("variant2")));
  520. db.issues().insertIssue(rule, project, file, i -> i.setCodeVariants(List.of("variant1", "variant2")));
  521. db.issues().insertIssue(rule, project, file, i -> i.setCodeVariants(List.of("variant2", "variant3")));
  522. indexPermissionsAndIssues();
  523. ws.newRequest()
  524. .setParam(PARAM_CODE_VARIANTS, "variant2,variant3")
  525. .setParam(FACETS, PARAM_CODE_VARIANTS)
  526. .execute()
  527. .assertJson(this.getClass(), "search_by_variants_with_facets.json");
  528. }
  529. @Test
  530. public void issue_on_removed_file() {
  531. RuleDto rule = newIssueRule();
  532. ComponentDto project = db.components().insertPublicProject("PROJECT_ID", c -> c.setKey("PROJECT_KEY").setKey("PROJECT_KEY")).getMainBranchComponent();
  533. indexPermissions();
  534. ComponentDto removedFile = db.components().insertComponent(newFileDto(project).setUuid("REMOVED_FILE_ID")
  535. .setKey("REMOVED_FILE_KEY")
  536. .setEnabled(false));
  537. IssueDto issue = newIssue(rule, project, removedFile)
  538. .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
  539. .setComponent(removedFile)
  540. .setStatus("OPEN").setResolution("OPEN")
  541. .setSeverity("MAJOR")
  542. .setIssueCreationDate(parseDateTime("2014-09-04T00:00:00+0100"))
  543. .setIssueUpdateDate(parseDateTime("2017-12-04T00:00:00+0100"));
  544. dbClient.issueDao().insert(session, issue);
  545. session.commit();
  546. indexIssues();
  547. ws.newRequest()
  548. .execute()
  549. .assertJson(this.getClass(), "issue_on_removed_file.json");
  550. }
  551. @Test
  552. public void apply_paging_with_one_component() {
  553. RuleDto rule = newIssueRule();
  554. ComponentDto project = db.components().insertPublicProject("PROJECT_ID", c -> c.setKey("PROJECT_KEY").setKey("PROJECT_KEY")).getMainBranchComponent();
  555. indexPermissions();
  556. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setKey("FILE_KEY"));
  557. for (int i = 0; i < SearchOptions.MAX_PAGE_SIZE + 1; i++) {
  558. IssueDto issue = newIssue(rule, project, file).setAssigneeUuid(null).setChecksum(null);
  559. dbClient.issueDao().insert(session, issue);
  560. }
  561. session.commit();
  562. indexIssues();
  563. ws.newRequest().setParam(PARAM_COMPONENTS, file.getKey()).execute()
  564. .assertJson(this.getClass(), "apply_paging_with_one_component.json");
  565. }
  566. @Test
  567. public void filter_by_assigned_to_me() {
  568. UserDto alice = db.users().insertUser(u -> u.setLogin("alice").setName("Alice").setEmail("alice@email.com"));
  569. UserDto john = db.users().insertUser(u -> u.setLogin("john").setName("John").setEmail("john@email.com"));
  570. ComponentDto project = db.components().insertPublicProject(c -> c.setUuid("PROJECT_ID").setKey("PROJECT_KEY").setBranchUuid("PROJECT_ID")).getMainBranchComponent();
  571. indexPermissions();
  572. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setKey("FILE_KEY"));
  573. RuleDto rule = newIssueRule();
  574. IssueDto issue1 = newIssue(rule, project, file)
  575. .setIssueCreationDate(parseDate("2014-09-04"))
  576. .setIssueUpdateDate(parseDate("2017-12-04"))
  577. .setEffort(10L)
  578. .setStatus("OPEN")
  579. .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
  580. .setSeverity("MAJOR")
  581. .setAssigneeUuid(john.getUuid());
  582. IssueDto issue2 = newIssue(rule, project, file)
  583. .setIssueCreationDate(parseDate("2014-09-04"))
  584. .setIssueUpdateDate(parseDate("2017-12-04"))
  585. .setEffort(10L)
  586. .setStatus("OPEN")
  587. .setKee("7b112bd4-b650-4037-80bc-82fd47d4eac2")
  588. .setSeverity("MAJOR")
  589. .setAssigneeUuid(alice.getUuid());
  590. IssueDto issue3 = newIssue(rule, project, file)
  591. .setIssueCreationDate(parseDate("2014-09-04"))
  592. .setIssueUpdateDate(parseDate("2017-12-04"))
  593. .setEffort(10L)
  594. .setStatus("OPEN")
  595. .setKee("82fd47d4-4037-b650-80bc-7b112bd4eac2")
  596. .setSeverity("MAJOR")
  597. .setAssigneeUuid(null);
  598. dbClient.issueDao().insert(session, issue1, issue2, issue3);
  599. session.commit();
  600. indexIssues();
  601. userSession.logIn(john);
  602. ws.newRequest()
  603. .setParam("resolved", "false")
  604. .setParam("assignees", "__me__")
  605. .setParam(FACETS, "assignees,assigned_to_me")
  606. .execute()
  607. .assertJson(this.getClass(), "filter_by_assigned_to_me.json");
  608. }
  609. @Test
  610. public void filter_by_new_code_period() {
  611. UserDto john = db.users().insertUser(u -> u.setLogin("john").setName("John").setEmail("john@email.com"));
  612. UserDto alice = db.users().insertUser(u -> u.setLogin("alice").setName("Alice").setEmail("alice@email.com"));
  613. ComponentDto project = db.components().insertPublicProject("PROJECT_ID",
  614. c -> c.setKey("PROJECT_KEY").setName("NAME_PROJECT_ID").setLongName("LONG_NAME_PROJECT_ID")).getMainBranchComponent();
  615. SnapshotDto snapshotDto = db.components().insertSnapshot(project, s -> s.setLast(true).setPeriodDate(parseDateTime("2014-09-05T00:00:00+0100").getTime()));
  616. indexPermissions();
  617. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setKey("FILE_KEY"));
  618. RuleDto rule = newIssueRule();
  619. IssueDto issue1 = newIssue(rule, project, file)
  620. .setIssueCreationDate(parseDateTime("2014-09-04T00:00:00+0100"))
  621. .setIssueUpdateDate(parseDateTime("2017-12-04T00:00:00+0100"))
  622. .setEffort(10L)
  623. .setStatus("OPEN")
  624. .setMessage(null)
  625. .setTags(null)
  626. .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
  627. .setSeverity("MAJOR")
  628. .setChecksum(null)
  629. .setAssigneeUuid(john.getUuid());
  630. IssueDto issue2 = newIssue(rule, project, file)
  631. .setIssueCreationDate(parseDateTime("2014-09-06T00:00:00+0100"))
  632. .setIssueUpdateDate(parseDateTime("2017-12-04T00:00:00+0100"))
  633. .setEffort(10L)
  634. .setStatus("OPEN")
  635. .setMessage(null)
  636. .setTags(null)
  637. .setKee("7b112bd4-b650-4037-80bc-82fd47d4eac2")
  638. .setSeverity("MAJOR")
  639. .setChecksum(null)
  640. .setAssigneeUuid(alice.getUuid());
  641. dbClient.issueDao().insert(session, issue1, issue2);
  642. session.commit();
  643. indexIssues();
  644. userSession.logIn(john);
  645. ws.newRequest()
  646. .setParam(PARAM_IN_NEW_CODE_PERIOD, "true")
  647. .setParam(PARAM_COMPONENTS, "PROJECT_KEY")
  648. .execute()
  649. .assertJson(this.getClass(), "filter_by_leak_period.json");
  650. }
  651. @Test
  652. public void explicit_false_value_for_new_code_period_parameters_has_no_effect() {
  653. ws.newRequest()
  654. .setParam(PARAM_IN_NEW_CODE_PERIOD, "false")
  655. .execute()
  656. .assertJson(this.getClass(), "default_page_size_is_100.json");
  657. }
  658. @Test
  659. public void filter_by_leak_period_without_a_period() {
  660. UserDto john = db.users().insertUser(u -> u.setLogin("john").setName("John").setEmail("john@email.com"));
  661. UserDto alice = db.users().insertUser(u -> u.setLogin("alice").setName("Alice").setEmail("alice@email.com"));
  662. ComponentDto project = db.components().insertPublicProject("PROJECT_ID", c -> c.setKey("PROJECT_KEY")).getMainBranchComponent();
  663. SnapshotDto snapshotDto = db.components().insertSnapshot(project);
  664. indexPermissions();
  665. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setKey("FILE_KEY"));
  666. RuleDto rule = newIssueRule();
  667. IssueDto issue1 = newIssue(rule, project, file)
  668. .setIssueCreationDate(parseDateTime("2014-09-04T00:00:00+0100"))
  669. .setIssueUpdateDate(parseDateTime("2017-12-04T00:00:00+0100"))
  670. .setEffort(10L)
  671. .setStatus("OPEN")
  672. .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
  673. .setSeverity("MAJOR")
  674. .setChecksum(null)
  675. .setAssigneeUuid(john.getUuid());
  676. IssueDto issue2 = newIssue(rule, project, file)
  677. .setIssueCreationDate(parseDateTime("2014-09-04T00:00:00+0100"))
  678. .setIssueUpdateDate(parseDateTime("2017-12-04T00:00:00+0100"))
  679. .setEffort(10L)
  680. .setStatus("OPEN")
  681. .setKee("7b112bd4-b650-4037-80bc-82fd47d4eac2")
  682. .setSeverity("MAJOR")
  683. .setChecksum(null)
  684. .setAssigneeUuid(alice.getUuid());
  685. dbClient.issueDao().insert(session, issue1, issue2);
  686. session.commit();
  687. indexIssues();
  688. userSession.logIn(john);
  689. ws.newRequest()
  690. .setParam(PARAM_COMPONENTS, "PROJECT_KEY")
  691. .setParam(PARAM_IN_NEW_CODE_PERIOD, "true")
  692. .execute()
  693. .assertJson(this.getClass(), "empty_result.json");
  694. }
  695. @Test
  696. public void filter_by_leak_period_has_no_effect_on_prs() {
  697. UserDto john = db.users().insertUser(u -> u.setLogin("john").setName("John").setEmail("john@email.com"));
  698. UserDto alice = db.users().insertUser(u -> u.setLogin("alice").setName("Alice").setEmail("alice@email.com"));
  699. ComponentDto project = db.components().insertPublicProject("PROJECT_ID", c -> c.setKey("PROJECT_KEY")).getMainBranchComponent();
  700. ComponentDto pr = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.PULL_REQUEST).setKey("pr"));
  701. SnapshotDto snapshotDto = db.components().insertSnapshot(pr);
  702. indexPermissions();
  703. ComponentDto file = db.components().insertComponent(newFileDto(pr, null, "FILE_ID", project.uuid()).setKey("FILE_KEY"));
  704. RuleDto rule = newIssueRule();
  705. IssueDto issue1 = newIssue(rule, pr, file)
  706. .setIssueCreationDate(parseDateTime("2014-09-04T00:00:00+0100"))
  707. .setIssueUpdateDate(parseDateTime("2017-12-04T00:00:00+0100"))
  708. .setEffort(10L)
  709. .setTags(null)
  710. .setMessage(null)
  711. .setStatus("OPEN")
  712. .setAuthorLogin("john")
  713. .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
  714. .setSeverity("MAJOR")
  715. .setAssigneeUuid(john.getUuid());
  716. IssueDto issue2 = newIssue(rule, pr, file)
  717. .setIssueCreationDate(parseDateTime("2014-09-04T00:00:00+0100"))
  718. .setIssueUpdateDate(parseDateTime("2017-12-04T00:00:00+0100"))
  719. .setEffort(10L)
  720. .setTags(null)
  721. .setMessage(null)
  722. .setStatus("OPEN")
  723. .setAuthorLogin("john")
  724. .setKee("7b112bd4-b650-4037-80bc-82fd47d4eac2")
  725. .setSeverity("MAJOR")
  726. .setAssigneeUuid(alice.getUuid());
  727. dbClient.issueDao().insert(session, issue1, issue2);
  728. session.commit();
  729. indexIssues();
  730. userSession.logIn(john);
  731. ws.newRequest()
  732. .setParam(PARAM_COMPONENTS, "PROJECT_KEY")
  733. .setParam(PARAM_PULL_REQUEST, "pr")
  734. .setParam(PARAM_IN_NEW_CODE_PERIOD, "true")
  735. .execute()
  736. .assertJson(this.getClass(), "filter_by_leak_period_has_no_effect_on_prs.json");
  737. }
  738. @Test
  739. public void return_empty_when_login_is_unknown() {
  740. UserDto john = db.users().insertUser(u -> u.setLogin("john").setName("John").setEmail("john@email.com"));
  741. UserDto alice = db.users().insertUser(u -> u.setLogin("alice").setName("Alice").setEmail("alice@email.com"));
  742. ComponentDto project = db.components().insertPublicProject("PROJECT_ID", c -> c.setKey("PROJECT_KEY")).getMainBranchComponent();
  743. indexPermissions();
  744. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setKey("FILE_KEY"));
  745. RuleDto rule = newIssueRule();
  746. IssueDto issue1 = newIssue(rule, project, file)
  747. .setIssueCreationDate(parseDate("2014-09-04"))
  748. .setIssueUpdateDate(parseDate("2017-12-04"))
  749. .setEffort(10L)
  750. .setStatus("OPEN")
  751. .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
  752. .setSeverity("MAJOR")
  753. .setAssigneeUuid(john.getUuid());
  754. IssueDto issue2 = newIssue(rule, project, file)
  755. .setIssueCreationDate(parseDate("2014-09-04"))
  756. .setIssueUpdateDate(parseDate("2017-12-04"))
  757. .setEffort(10L)
  758. .setStatus("OPEN")
  759. .setKee("7b112bd4-b650-4037-80bc-82fd47d4eac2")
  760. .setSeverity("MAJOR")
  761. .setAssigneeUuid(alice.getUuid());
  762. IssueDto issue3 = newIssue(rule, project, file)
  763. .setIssueCreationDate(parseDate("2014-09-04"))
  764. .setIssueUpdateDate(parseDate("2017-12-04"))
  765. .setEffort(10L)
  766. .setStatus("OPEN")
  767. .setKee("82fd47d4-4037-b650-80bc-7b112bd4eac2")
  768. .setSeverity("MAJOR")
  769. .setAssigneeUuid(null);
  770. dbClient.issueDao().insert(session, issue1, issue2, issue3);
  771. session.commit();
  772. indexIssues();
  773. userSession.logIn(john);
  774. SearchWsResponse response = ws.newRequest()
  775. .setParam("resolved", "false")
  776. .setParam("assignees", "unknown")
  777. .setParam(FACETS, "assignees")
  778. .executeProtobuf(SearchWsResponse.class);
  779. assertThat(response.getIssuesList()).isEmpty();
  780. }
  781. @Test
  782. public void filter_by_assigned_to_me_when_not_authenticate() {
  783. UserDto alice = db.users().insertUser(u -> u.setLogin("alice").setName("Alice").setEmail("alice@email.com"));
  784. UserDto john = db.users().insertUser(u -> u.setLogin("john").setName("John").setEmail("john@email.com"));
  785. UserDto poy = db.users().insertUser(u -> u.setLogin("poy").setName("poypoy").setEmail("poypoy@email.com"));
  786. userSession.logIn(poy);
  787. ComponentDto project = db.components().insertPublicProject("PROJECT_ID", c -> c.setKey("PROJECT_KEY")).getMainBranchComponent();
  788. indexPermissions();
  789. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setKey("FILE_KEY"));
  790. RuleDto rule = newIssueRule();
  791. IssueDto issue1 = newIssue(rule, project, file)
  792. .setStatus("OPEN")
  793. .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
  794. .setAssigneeUuid(john.getUuid());
  795. IssueDto issue2 = newIssue(rule, project, file)
  796. .setStatus("OPEN")
  797. .setKee("7b112bd4-b650-4037-80bc-82fd47d4eac2")
  798. .setAssigneeUuid(alice.getUuid());
  799. IssueDto issue3 = newIssue(rule, project, file)
  800. .setStatus("OPEN")
  801. .setKee("82fd47d4-4037-b650-80bc-7b112bd4eac2")
  802. .setAssigneeUuid(null);
  803. dbClient.issueDao().insert(session, issue1, issue2, issue3);
  804. session.commit();
  805. indexIssues();
  806. ws.newRequest()
  807. .setParam("resolved", "false")
  808. .setParam("assignees", "__me__")
  809. .execute()
  810. .assertJson(this.getClass(), "empty_result.json");
  811. }
  812. @Test
  813. public void search_by_author() {
  814. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  815. ComponentDto file = db.components().insertComponent(newFileDto(project));
  816. RuleDto rule = db.rules().insertIssueRule();
  817. IssueDto issue1 = db.issues().insertIssue(rule, project, file, i -> i.setAuthorLogin("leia"));
  818. IssueDto issue2 = db.issues().insertIssue(rule, project, file, i -> i.setAuthorLogin("luke"));
  819. IssueDto issue3 = db.issues().insertIssue(rule, project, file, i -> i.setAuthorLogin("han, solo"));
  820. indexPermissionsAndIssues();
  821. SearchWsResponse response = ws.newRequest()
  822. .setMultiParam("author", asList("leia", "han, solo"))
  823. .setParam(FACETS, "author")
  824. .executeProtobuf(SearchWsResponse.class);
  825. assertThat(response.getIssuesList())
  826. .extracting(Issue::getKey)
  827. .containsExactlyInAnyOrder(issue1.getKey(), issue3.getKey());
  828. Common.Facet facet = response.getFacets().getFacetsList().get(0);
  829. assertThat(facet.getProperty()).isEqualTo("author");
  830. assertThat(facet.getValuesList())
  831. .extracting(Common.FacetValue::getVal, Common.FacetValue::getCount)
  832. .containsExactlyInAnyOrder(
  833. tuple("leia", 1L),
  834. tuple("luke", 1L),
  835. tuple("han, solo", 1L));
  836. assertThat(ws.newRequest()
  837. .setMultiParam("author", singletonList("unknown"))
  838. .executeProtobuf(SearchWsResponse.class).getIssuesList())
  839. .isEmpty();
  840. }
  841. @Test
  842. public void filter_by_test_scope() {
  843. ProjectData projectData = db.components().insertPublicProject("PROJECT_ID",
  844. c -> c.setKey("PROJECT_KEY").setName("NAME_PROJECT_ID").setLongName("LONG_NAME_PROJECT_ID"));
  845. ComponentDto project = projectData.getMainBranchComponent();
  846. indexPermissions();
  847. ComponentDto mainCodeFile = db.components().insertComponent(
  848. newFileDto(project, null, "FILE_ID").setKey("FILE_KEY"));
  849. ComponentDto testCodeFile = db.components().insertComponent(
  850. newFileDto(project, null, "ANOTHER_FILE_ID").setKey("ANOTHER_FILE_KEY").setQualifier(UNIT_TEST_FILE));
  851. RuleDto rule = newIssueRule();
  852. IssueDto issue1 = newIssue(rule, project, mainCodeFile)
  853. .setIssueCreationDate(parseDate("2014-09-04"))
  854. .setIssueUpdateDate(parseDate("2017-12-04"))
  855. .setEffort(10L)
  856. .setStatus("OPEN")
  857. .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
  858. .setSeverity("MAJOR");
  859. IssueDto issue2 = newIssue(rule, project, mainCodeFile)
  860. .setIssueCreationDate(parseDate("2014-09-04"))
  861. .setIssueUpdateDate(parseDate("2017-12-04"))
  862. .setEffort(10L)
  863. .setStatus("OPEN")
  864. .setKee("7b112bd4-b650-4037-80bc-82fd47d4eac2")
  865. .setSeverity("MAJOR");
  866. IssueDto issue3 = newIssue(rule, project, testCodeFile)
  867. .setIssueCreationDate(parseDate("2014-09-04"))
  868. .setIssueUpdateDate(parseDate("2017-12-04"))
  869. .setEffort(10L)
  870. .setStatus("OPEN")
  871. .setKee("82fd47d4-4037-b650-80bc-7b112bd4eac2")
  872. .setSeverity("MAJOR");
  873. dbClient.issueDao().insert(session, issue1, issue2, issue3);
  874. session.commit();
  875. indexIssues();
  876. ws.newRequest()
  877. .setParam("scopes", "TEST")
  878. .setParam(FACETS, "scopes")
  879. .execute()
  880. .assertJson(this.getClass(), "filter_by_test_scope.json");
  881. }
  882. @Test
  883. public void filter_by_main_scope() {
  884. ComponentDto project = db.components().insertPublicProject("PROJECT_ID",
  885. c -> c.setKey("PROJECT_KEY").setName("NAME_PROJECT_ID").setLongName("LONG_NAME_PROJECT_ID")).getMainBranchComponent();
  886. indexPermissions();
  887. ComponentDto mainCodeFile = db.components().insertComponent(
  888. newFileDto(project, null, "FILE_ID").setKey("FILE_KEY"));
  889. ComponentDto testCodeFile = db.components().insertComponent(
  890. newFileDto(project, null, "ANOTHER_FILE_ID").setKey("ANOTHER_FILE_KEY").setQualifier(UNIT_TEST_FILE));
  891. RuleDto rule = newIssueRule();
  892. IssueDto issue1 = newIssue(rule, project, mainCodeFile)
  893. .setIssueCreationDate(parseDate("2014-09-04"))
  894. .setIssueUpdateDate(parseDate("2017-12-04"))
  895. .setEffort(10L)
  896. .setStatus("OPEN")
  897. .setKee("83ec1d05-9397-4137-9978-85368bcc3b90")
  898. .setSeverity("MAJOR");
  899. IssueDto issue2 = newIssue(rule, project, mainCodeFile)
  900. .setIssueCreationDate(parseDate("2014-09-04"))
  901. .setIssueUpdateDate(parseDate("2017-12-04"))
  902. .setEffort(10L)
  903. .setStatus("OPEN")
  904. .setKee("7b112bd4-b650-4037-80bc-82fd47d4eac2")
  905. .setSeverity("MAJOR");
  906. IssueDto issue3 = newIssue(rule, project, testCodeFile)
  907. .setIssueCreationDate(parseDate("2014-09-04"))
  908. .setIssueUpdateDate(parseDate("2017-12-04"))
  909. .setEffort(10L)
  910. .setStatus("OPEN")
  911. .setKee("82fd47d4-4037-b650-80bc-7b112bd4eac2")
  912. .setSeverity("MAJOR");
  913. dbClient.issueDao().insert(session, issue1, issue2, issue3);
  914. session.commit();
  915. indexIssues();
  916. ws.newRequest()
  917. .setParam("scopes", "MAIN")
  918. .setParam(FACETS, "scopes")
  919. .execute()
  920. .assertJson(this.getClass(), "filter_by_main_scope.json");
  921. }
  922. @Test
  923. public void filter_by_scope_always_returns_all_scope_facet_values() {
  924. ComponentDto project = db.components().insertPublicProject("PROJECT_ID",
  925. c -> c.setKey("PROJECT_KEY").setName("NAME_PROJECT_ID").setLongName("LONG_NAME_PROJECT_ID")).getMainBranchComponent();
  926. indexPermissions();
  927. ComponentDto mainCodeFile = db.components().insertComponent(
  928. newFileDto(project, null, "FILE_ID").setKey("FILE_KEY"));
  929. RuleDto rule = newIssueRule();
  930. IssueDto issue1 = newIssue(rule, project, mainCodeFile)
  931. .setIssueCreationDate(parseDate("2014-09-04"))
  932. .setIssueUpdateDate(parseDate("2017-12-04"))
  933. .setEffort(10L)
  934. .setStatus("OPEN")
  935. .setKee("83ec1d05-9397-4137-9978-85368bcc3b90")
  936. .setSeverity("MAJOR");
  937. IssueDto issue2 = newIssue(rule, project, mainCodeFile)
  938. .setIssueCreationDate(parseDate("2014-09-04"))
  939. .setIssueUpdateDate(parseDate("2017-12-04"))
  940. .setEffort(10L)
  941. .setStatus("OPEN")
  942. .setKee("7b112bd4-b650-4037-80bc-82fd47d4eac2")
  943. .setSeverity("MAJOR");
  944. dbClient.issueDao().insert(session, issue1, issue2);
  945. session.commit();
  946. indexIssues();
  947. ws.newRequest()
  948. .setParam("scopes", "MAIN")
  949. .setParam(FACETS, "scopes")
  950. .execute()
  951. .assertJson(this.getClass(), "filter_by_main_scope_2.json");
  952. }
  953. @Test
  954. public void sort_by_updated_at() {
  955. RuleDto rule = newIssueRule();
  956. ComponentDto project = db.components().insertPublicProject("PROJECT_ID",
  957. c -> c.setKey("PROJECT_KEY").setName("NAME_PROJECT_ID").setLongName("LONG_NAME_PROJECT_ID")).getMainBranchComponent();
  958. indexPermissions();
  959. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setKey("FILE_KEY"));
  960. dbClient.issueDao().insert(session, newIssue(rule, project, file)
  961. .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac1")
  962. .setIssueUpdateDate(parseDateTime("2014-11-02T00:00:00+0100")));
  963. dbClient.issueDao().insert(session, newIssue(rule, project, file)
  964. .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
  965. .setIssueUpdateDate(parseDateTime("2014-11-01T00:00:00+0100")));
  966. dbClient.issueDao().insert(session, newIssue(rule, project, file)
  967. .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac3")
  968. .setIssueUpdateDate(parseDateTime("2014-11-03T00:00:00+0100")));
  969. session.commit();
  970. indexIssues();
  971. TestResponse response = ws.newRequest()
  972. .setParam("s", IssueQuery.SORT_BY_UPDATE_DATE)
  973. .setParam("asc", "false")
  974. .execute();
  975. JsonElement parse = new JsonParser().parse(response.getInput());
  976. assertThat(parse.getAsJsonObject().get("issues").getAsJsonArray())
  977. .extracting(o -> o.getAsJsonObject().get("key").getAsString())
  978. .containsExactly("82fd47d4-b650-4037-80bc-7b112bd4eac3", "82fd47d4-b650-4037-80bc-7b112bd4eac1", "82fd47d4-b650-4037-80bc-7b112bd4eac2");
  979. }
  980. @Test
  981. public void only_vulnerabilities_are_returned_by_owaspAsvs40() {
  982. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  983. ComponentDto file = db.components().insertComponent(newFileDto(project));
  984. Consumer<RuleDto> ruleConsumer = ruleDefinitionDto -> ruleDefinitionDto
  985. .setSecurityStandards(Sets.newHashSet("cwe:20", "owaspTop10:a1", "pciDss-3.2:6.5.3", "owaspAsvs-4.0:12.3.1"))
  986. .setSystemTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  987. Consumer<IssueDto> issueConsumer = issueDto -> issueDto.setTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  988. RuleDto hotspotRule = db.rules().insertHotspotRule(ruleConsumer);
  989. db.issues().insertHotspot(hotspotRule, project, file, issueConsumer);
  990. RuleDto issueRule = db.rules().insertIssueRule(ruleConsumer);
  991. IssueDto issueDto1 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  992. IssueDto issueDto2 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  993. IssueDto issueDto3 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(CODE_SMELL));
  994. indexPermissionsAndIssues();
  995. SearchWsResponse result = ws.newRequest()
  996. .setParam("owaspAsvs-4.0", "12.3.1")
  997. .executeProtobuf(SearchWsResponse.class);
  998. assertThat(result.getIssuesList())
  999. .extracting(Issue::getKey)
  1000. .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto2.getKey());
  1001. result = ws.newRequest()
  1002. .setParam("owaspAsvs-4.0", "12")
  1003. .executeProtobuf(SearchWsResponse.class);
  1004. assertThat(result.getIssuesList())
  1005. .extracting(Issue::getKey)
  1006. .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto2.getKey());
  1007. }
  1008. @Test
  1009. public void only_vulnerabilities_are_returned_by_owaspAsvs40_with_level() {
  1010. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  1011. ComponentDto file = db.components().insertComponent(newFileDto(project));
  1012. Consumer<IssueDto> issueConsumer = issueDto -> issueDto.setTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1013. RuleDto issueRule1 = db.rules().insertIssueRule(r -> r.setSecurityStandards(Set.of("owaspAsvs-4.0:1.7.2", "owaspAsvs-4.0:12.3.1")));
  1014. RuleDto issueRule2 = db.rules().insertIssueRule(r -> r.setSecurityStandards(Set.of("owaspAsvs-4.0:2.2.5")));
  1015. RuleDto issueRule3 = db.rules().insertIssueRule(r -> r.setSecurityStandards(Set.of("owaspAsvs-4.0:2.2.5", "owaspAsvs-4.0:12.1.3")));
  1016. IssueDto issueDto1 = db.issues().insertIssue(issueRule1, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1017. IssueDto issueDto2 = db.issues().insertIssue(issueRule2, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1018. IssueDto issueDto3 = db.issues().insertIssue(issueRule3, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1019. indexPermissionsAndIssues();
  1020. SearchWsResponse result = ws.newRequest()
  1021. .setParam("owaspAsvs-4.0", "1")
  1022. .setParam("owaspAsvsLevel", "1")
  1023. .executeProtobuf(SearchWsResponse.class);
  1024. assertThat(result.getIssuesList()).isEmpty();
  1025. result = ws.newRequest()
  1026. .setParam("owaspAsvs-4.0", "1")
  1027. .setParam("owaspAsvsLevel", "2")
  1028. .executeProtobuf(SearchWsResponse.class);
  1029. assertThat(result.getIssuesList())
  1030. .extracting(Issue::getKey)
  1031. .containsExactlyInAnyOrder(issueDto1.getKey());
  1032. result = ws.newRequest()
  1033. .setParam("owaspAsvs-4.0", "12")
  1034. .setParam("owaspAsvsLevel", "1")
  1035. .executeProtobuf(SearchWsResponse.class);
  1036. assertThat(result.getIssuesList())
  1037. .extracting(Issue::getKey)
  1038. .containsExactlyInAnyOrder(issueDto1.getKey());
  1039. result = ws.newRequest()
  1040. .setParam("owaspAsvs-4.0", "12")
  1041. .setParam("owaspAsvsLevel", "2")
  1042. .executeProtobuf(SearchWsResponse.class);
  1043. assertThat(result.getIssuesList())
  1044. .extracting(Issue::getKey)
  1045. .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto3.getKey());
  1046. }
  1047. @Test
  1048. public void only_vulnerabilities_are_returned_by_pciDss32() {
  1049. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  1050. ComponentDto file = db.components().insertComponent(newFileDto(project));
  1051. Consumer<RuleDto> ruleConsumer = ruleDefinitionDto -> ruleDefinitionDto
  1052. .setSecurityStandards(Sets.newHashSet("cwe:20", "owaspTop10:a1", "pciDss-3.2:6.5.3", "pciDss-3.2:10.1"))
  1053. .setSystemTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1054. Consumer<IssueDto> issueConsumer = issueDto -> issueDto.setTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1055. RuleDto hotspotRule = db.rules().insertHotspotRule(ruleConsumer);
  1056. db.issues().insertHotspot(hotspotRule, project, file, issueConsumer);
  1057. RuleDto issueRule = db.rules().insertIssueRule(ruleConsumer);
  1058. IssueDto issueDto1 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1059. IssueDto issueDto2 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1060. IssueDto issueDto3 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(CODE_SMELL));
  1061. indexPermissionsAndIssues();
  1062. SearchWsResponse result = ws.newRequest()
  1063. .setParam("pciDss-3.2", "10")
  1064. .executeProtobuf(SearchWsResponse.class);
  1065. assertThat(result.getIssuesList())
  1066. .extracting(Issue::getKey)
  1067. .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto2.getKey());
  1068. result = ws.newRequest()
  1069. .setParam("pciDss-3.2", "10.1")
  1070. .executeProtobuf(SearchWsResponse.class);
  1071. assertThat(result.getIssuesList())
  1072. .extracting(Issue::getKey)
  1073. .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto2.getKey());
  1074. }
  1075. @Test
  1076. public void multiple_categories_pciDss32() {
  1077. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  1078. ComponentDto file = db.components().insertComponent(newFileDto(project));
  1079. // Rule 1
  1080. Consumer<RuleDto> ruleConsumer = ruleDefinitionDto -> ruleDefinitionDto
  1081. .setSecurityStandards(Sets.newHashSet("cwe:20", "owaspTop10:a1", "pciDss-3.2:6.5.3", "pciDss-3.2:10.1"))
  1082. .setSystemTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1083. Consumer<IssueDto> issueConsumer = issueDto -> issueDto.setTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1084. RuleDto hotspotRule = db.rules().insertHotspotRule(ruleConsumer);
  1085. db.issues().insertHotspot(hotspotRule, project, file, issueConsumer);
  1086. RuleDto issueRule = db.rules().insertIssueRule(ruleConsumer);
  1087. IssueDto issueDto1 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1088. IssueDto issueDto2 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1089. // Rule 2
  1090. ruleConsumer = ruleDefinitionDto -> ruleDefinitionDto
  1091. .setSecurityStandards(Sets.newHashSet("pciDss-4.0:6.5.3", "pciDss-3.2:1.1"))
  1092. .setSystemTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1093. issueConsumer = issueDto -> issueDto.setTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1094. hotspotRule = db.rules().insertHotspotRule(ruleConsumer);
  1095. db.issues().insertHotspot(hotspotRule, project, file, issueConsumer);
  1096. issueRule = db.rules().insertIssueRule(ruleConsumer);
  1097. IssueDto issueDto3 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1098. IssueDto issueDto4 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1099. // Rule 3
  1100. ruleConsumer = ruleDefinitionDto -> ruleDefinitionDto
  1101. .setSecurityStandards(Sets.newHashSet("pciDss-4.0:6.5.3", "pciDss-3.2:2.3", "pciDss-3.2:10.1.2"))
  1102. .setSystemTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1103. issueConsumer = issueDto -> issueDto.setTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1104. hotspotRule = db.rules().insertHotspotRule(ruleConsumer);
  1105. db.issues().insertHotspot(hotspotRule, project, file, issueConsumer);
  1106. issueRule = db.rules().insertIssueRule(ruleConsumer);
  1107. IssueDto issueDto5 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1108. IssueDto issueDto6 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1109. indexPermissionsAndIssues();
  1110. SearchWsResponse result = ws.newRequest()
  1111. .setParam("pciDss-3.2", "1,10")
  1112. .executeProtobuf(SearchWsResponse.class);
  1113. assertThat(result.getIssuesList())
  1114. .extracting(Issue::getKey)
  1115. .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto2.getKey(), issueDto3.getKey(), issueDto4.getKey(), issueDto5.getKey(), issueDto6.getKey());
  1116. result = ws.newRequest()
  1117. .setParam("pciDss-3.2", "1")
  1118. .executeProtobuf(SearchWsResponse.class);
  1119. assertThat(result.getIssuesList())
  1120. .extracting(Issue::getKey)
  1121. .containsExactlyInAnyOrder(issueDto3.getKey(), issueDto4.getKey());
  1122. result = ws.newRequest()
  1123. .setParam("pciDss-3.2", "1,10,4")
  1124. .executeProtobuf(SearchWsResponse.class);
  1125. assertThat(result.getIssuesList())
  1126. .extracting(Issue::getKey)
  1127. .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto2.getKey(), issueDto3.getKey(), issueDto4.getKey(), issueDto5.getKey(), issueDto6.getKey());
  1128. result = ws.newRequest()
  1129. .setParam("pciDss-3.2", "4")
  1130. .executeProtobuf(SearchWsResponse.class);
  1131. assertThat(result.getIssuesList()).isEmpty();
  1132. result = ws.newRequest()
  1133. .setParam("pciDss-3.2", "4,7,12")
  1134. .executeProtobuf(SearchWsResponse.class);
  1135. assertThat(result.getIssuesList()).isEmpty();
  1136. result = ws.newRequest()
  1137. .setParam("pciDss-3.2", "10.1")
  1138. .executeProtobuf(SearchWsResponse.class);
  1139. assertThat(result.getIssuesList())
  1140. .extracting(Issue::getKey)
  1141. .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto2.getKey());
  1142. }
  1143. @Test
  1144. public void only_vulnerabilities_are_returned_by_pciDss40() {
  1145. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  1146. ComponentDto file = db.components().insertComponent(newFileDto(project));
  1147. Consumer<RuleDto> ruleConsumer = ruleDefinitionDto -> ruleDefinitionDto
  1148. .setSecurityStandards(Sets.newHashSet("cwe:20", "owaspTop10:a1", "pciDss-4.0:6.5.3", "pciDss-4.0:10.1"))
  1149. .setSystemTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1150. Consumer<IssueDto> issueConsumer = issueDto -> issueDto.setTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1151. RuleDto hotspotRule = db.rules().insertHotspotRule(ruleConsumer);
  1152. db.issues().insertHotspot(hotspotRule, project, file, issueConsumer);
  1153. RuleDto issueRule = db.rules().insertIssueRule(ruleConsumer);
  1154. IssueDto issueDto1 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1155. IssueDto issueDto2 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1156. IssueDto issueDto3 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(CODE_SMELL));
  1157. indexPermissionsAndIssues();
  1158. SearchWsResponse result = ws.newRequest()
  1159. .setParam("pciDss-4.0", "10,6,5")
  1160. .executeProtobuf(SearchWsResponse.class);
  1161. assertThat(result.getIssuesList())
  1162. .extracting(Issue::getKey)
  1163. .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto2.getKey());
  1164. result = ws.newRequest()
  1165. .setParam("pciDss-4.0", "10.1,6.5,5.5")
  1166. .executeProtobuf(SearchWsResponse.class);
  1167. assertThat(result.getIssuesList())
  1168. .extracting(Issue::getKey)
  1169. .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto2.getKey());
  1170. }
  1171. @Test
  1172. public void multiple_categories_pciDss40() {
  1173. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  1174. ComponentDto file = db.components().insertComponent(newFileDto(project));
  1175. // Rule 1
  1176. Consumer<RuleDto> ruleConsumer = ruleDefinitionDto -> ruleDefinitionDto
  1177. .setSecurityStandards(Sets.newHashSet("cwe:20", "owaspTop10:a1", "pciDss-4.0:6.5.3", "pciDss-4.0:10.1"))
  1178. .setSystemTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1179. Consumer<IssueDto> issueConsumer = issueDto -> issueDto.setTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1180. RuleDto hotspotRule = db.rules().insertHotspotRule(ruleConsumer);
  1181. db.issues().insertHotspot(hotspotRule, project, file, issueConsumer);
  1182. RuleDto issueRule = db.rules().insertIssueRule(ruleConsumer);
  1183. IssueDto issueDto1 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1184. IssueDto issueDto2 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1185. // Rule 2
  1186. ruleConsumer = ruleDefinitionDto -> ruleDefinitionDto
  1187. .setSecurityStandards(Sets.newHashSet("pciDss-4.0:6.5.3", "pciDss-4.0:1.1"))
  1188. .setSystemTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1189. issueConsumer = issueDto -> issueDto.setTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1190. hotspotRule = db.rules().insertHotspotRule(ruleConsumer);
  1191. db.issues().insertHotspot(hotspotRule, project, file, issueConsumer);
  1192. issueRule = db.rules().insertIssueRule(ruleConsumer);
  1193. IssueDto issueDto3 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1194. IssueDto issueDto4 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1195. // Rule 3
  1196. ruleConsumer = ruleDefinitionDto -> ruleDefinitionDto
  1197. .setSecurityStandards(Sets.newHashSet("pciDss-3.2:6.5.3", "pciDss-4.0:2.3"))
  1198. .setSystemTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1199. issueConsumer = issueDto -> issueDto.setTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1200. hotspotRule = db.rules().insertHotspotRule(ruleConsumer);
  1201. db.issues().insertHotspot(hotspotRule, project, file, issueConsumer);
  1202. issueRule = db.rules().insertIssueRule(ruleConsumer);
  1203. IssueDto issueDto5 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1204. IssueDto issueDto6 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1205. indexPermissionsAndIssues();
  1206. SearchWsResponse result = ws.newRequest()
  1207. .setParam("pciDss-4.0", "1,10")
  1208. .executeProtobuf(SearchWsResponse.class);
  1209. assertThat(result.getIssuesList())
  1210. .extracting(Issue::getKey)
  1211. .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto2.getKey(), issueDto3.getKey(), issueDto4.getKey());
  1212. result = ws.newRequest()
  1213. .setParam("pciDss-4.0", "1")
  1214. .executeProtobuf(SearchWsResponse.class);
  1215. assertThat(result.getIssuesList())
  1216. .extracting(Issue::getKey)
  1217. .containsExactlyInAnyOrder(issueDto3.getKey(), issueDto4.getKey());
  1218. result = ws.newRequest()
  1219. .setParam("pciDss-4.0", "1,10,4")
  1220. .executeProtobuf(SearchWsResponse.class);
  1221. assertThat(result.getIssuesList())
  1222. .extracting(Issue::getKey)
  1223. .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto2.getKey(), issueDto3.getKey(), issueDto4.getKey());
  1224. result = ws.newRequest()
  1225. .setParam("pciDss-4.0", "4")
  1226. .executeProtobuf(SearchWsResponse.class);
  1227. assertThat(result.getIssuesList()).isEmpty();
  1228. result = ws.newRequest()
  1229. .setParam("pciDss-4.0", "4,7,12")
  1230. .executeProtobuf(SearchWsResponse.class);
  1231. assertThat(result.getIssuesList()).isEmpty();
  1232. }
  1233. @Test
  1234. public void only_vulnerabilities_are_returned_by_cwe() {
  1235. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  1236. ComponentDto file = db.components().insertComponent(newFileDto(project));
  1237. Consumer<RuleDto> ruleConsumer = ruleDefinitionDto -> ruleDefinitionDto
  1238. .setSecurityStandards(Sets.newHashSet("cwe:20", "cwe:564", "cwe:89", "cwe:943", "owaspTop10:a1"))
  1239. .setSystemTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1240. Consumer<IssueDto> issueConsumer = issueDto -> issueDto.setTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1241. RuleDto hotspotRule = db.rules().insertHotspotRule(ruleConsumer);
  1242. db.issues().insertHotspot(hotspotRule, project, file, issueConsumer);
  1243. RuleDto issueRule = db.rules().insertIssueRule(ruleConsumer);
  1244. IssueDto issueDto1 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1245. IssueDto issueDto2 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1246. IssueDto issueDto3 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(CODE_SMELL));
  1247. indexPermissionsAndIssues();
  1248. SearchWsResponse result = ws.newRequest()
  1249. .setParam("cwe", "20")
  1250. .executeProtobuf(SearchWsResponse.class);
  1251. assertThat(result.getIssuesList())
  1252. .extracting(Issue::getKey)
  1253. .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto2.getKey());
  1254. }
  1255. @Test
  1256. public void only_vulnerabilities_are_returned_by_owasp() {
  1257. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  1258. ComponentDto file = db.components().insertComponent(newFileDto(project));
  1259. Consumer<RuleDto> ruleConsumer = ruleDefinitionDto -> ruleDefinitionDto
  1260. .setSecurityStandards(Sets.newHashSet("cwe:20", "cwe:564", "cwe:89", "cwe:943", "owaspTop10:a1", "owaspTop10-2021:a2"))
  1261. .setSystemTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1262. Consumer<IssueDto> issueConsumer = issueDto -> issueDto.setTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1263. RuleDto hotspotRule = db.rules().insertHotspotRule(ruleConsumer);
  1264. db.issues().insertHotspot(hotspotRule, project, file, issueConsumer);
  1265. RuleDto issueRule = db.rules().insertIssueRule(ruleConsumer);
  1266. IssueDto issueDto1 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1267. IssueDto issueDto2 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1268. IssueDto issueDto3 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(CODE_SMELL));
  1269. indexPermissionsAndIssues();
  1270. SearchWsResponse result = ws.newRequest()
  1271. .setParam("owaspTop10", "a1")
  1272. .executeProtobuf(SearchWsResponse.class);
  1273. assertThat(result.getIssuesList())
  1274. .extracting(Issue::getKey)
  1275. .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto2.getKey());
  1276. }
  1277. @Test
  1278. public void only_vulnerabilities_are_returned_by_owasp_2021() {
  1279. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  1280. ComponentDto file = db.components().insertComponent(newFileDto(project));
  1281. Consumer<RuleDto> ruleConsumer = ruleDefinitionDto -> ruleDefinitionDto
  1282. .setSecurityStandards(Sets.newHashSet("cwe:20", "cwe:564", "cwe:89", "cwe:943", "owaspTop10:a1", "owaspTop10-2021:a2"))
  1283. .setSystemTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1284. Consumer<IssueDto> issueConsumer = issueDto -> issueDto.setTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1285. RuleDto hotspotRule = db.rules().insertHotspotRule(ruleConsumer);
  1286. db.issues().insertHotspot(hotspotRule, project, file, issueConsumer);
  1287. RuleDto issueRule = db.rules().insertIssueRule(ruleConsumer);
  1288. IssueDto issueDto1 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1289. IssueDto issueDto2 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1290. IssueDto issueDto3 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(CODE_SMELL));
  1291. indexPermissionsAndIssues();
  1292. SearchWsResponse result = ws.newRequest()
  1293. .setParam("owaspTop10-2021", "a2")
  1294. .executeProtobuf(SearchWsResponse.class);
  1295. assertThat(result.getIssuesList())
  1296. .extracting(Issue::getKey)
  1297. .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto2.getKey());
  1298. }
  1299. @Test
  1300. public void only_vulnerabilities_are_returned_by_sansTop25() {
  1301. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  1302. ComponentDto file = db.components().insertComponent(newFileDto(project));
  1303. Consumer<RuleDto> ruleConsumer = ruleDefinitionDto -> ruleDefinitionDto
  1304. .setSecurityStandards(Sets.newHashSet("cwe:266", "cwe:732", "owaspTop10:a5"))
  1305. .setSystemTags(Sets.newHashSet("cert", "cwe", "owasp-a5", "sans-top25-porous"));
  1306. Consumer<IssueDto> issueConsumer = issueDto -> issueDto.setTags(Sets.newHashSet("cert", "cwe", "owasp-a5", "sans-top25-porous"));
  1307. RuleDto hotspotRule = db.rules().insertHotspotRule(ruleConsumer);
  1308. db.issues().insertHotspot(hotspotRule, project, file, issueConsumer);
  1309. RuleDto issueRule = db.rules().insertIssueRule(ruleConsumer);
  1310. IssueDto issueDto1 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1311. IssueDto issueDto2 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1312. IssueDto issueDto3 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(CODE_SMELL));
  1313. indexPermissionsAndIssues();
  1314. SearchWsResponse result = ws.newRequest()
  1315. .setParam("sansTop25", "porous-defenses")
  1316. .executeProtobuf(SearchWsResponse.class);
  1317. assertThat(result.getIssuesList())
  1318. .extracting(Issue::getKey)
  1319. .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto2.getKey());
  1320. }
  1321. @Test
  1322. public void only_vulnerabilities_are_returned_by_sonarsource_security() {
  1323. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  1324. ComponentDto file = db.components().insertComponent(newFileDto(project));
  1325. Consumer<RuleDto> ruleConsumer = ruleDefinitionDto -> ruleDefinitionDto
  1326. .setSecurityStandards(Sets.newHashSet("cwe:20", "cwe:564", "cwe:89", "cwe:943", "owaspTop10:a1"))
  1327. .setSystemTags(Sets.newHashSet("cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1328. Consumer<IssueDto> issueConsumer = issueDto -> issueDto.setTags(Sets.newHashSet("cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1329. RuleDto hotspotRule = db.rules().insertHotspotRule(ruleConsumer);
  1330. db.issues().insertHotspot(hotspotRule, project, file, issueConsumer);
  1331. RuleDto issueRule = db.rules().insertIssueRule(ruleConsumer);
  1332. IssueDto issueDto1 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1333. IssueDto issueDto2 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1334. IssueDto issueDto3 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(CODE_SMELL));
  1335. indexPermissionsAndIssues();
  1336. SearchWsResponse result = ws.newRequest()
  1337. .setParam("sonarsourceSecurity", "sql-injection")
  1338. .executeProtobuf(SearchWsResponse.class);
  1339. assertThat(result.getIssuesList())
  1340. .extracting(Issue::getKey)
  1341. .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto2.getKey());
  1342. }
  1343. @Test
  1344. public void security_hotspots_are_not_returned_by_default() {
  1345. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  1346. ComponentDto file = db.components().insertComponent(newFileDto(project));
  1347. RuleDto rule = db.rules().insertIssueRule();
  1348. db.issues().insertIssue(rule, project, file, i -> i.setType(RuleType.BUG));
  1349. db.issues().insertIssue(rule, project, file, i -> i.setType(RuleType.VULNERABILITY));
  1350. db.issues().insertIssue(rule, project, file, i -> i.setType(CODE_SMELL));
  1351. db.issues().insertHotspot(project, file);
  1352. indexPermissionsAndIssues();
  1353. SearchWsResponse result = ws.newRequest().executeProtobuf(SearchWsResponse.class);
  1354. assertThat(result.getIssuesList())
  1355. .extracting(Issue::getType)
  1356. .containsExactlyInAnyOrder(BUG, VULNERABILITY, Common.RuleType.CODE_SMELL);
  1357. }
  1358. @Test
  1359. public void security_hotspots_are_not_returned_by_issues_param() {
  1360. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  1361. ComponentDto file = db.components().insertComponent(newFileDto(project));
  1362. RuleDto issueRule = db.rules().insertIssueRule();
  1363. IssueDto bugIssue = db.issues().insertIssue(issueRule, project, file, i -> i.setType(RuleType.BUG));
  1364. IssueDto vulnerabilityIssue = db.issues().insertIssue(issueRule, project, file, i -> i.setType(RuleType.VULNERABILITY));
  1365. IssueDto codeSmellIssue = db.issues().insertIssue(issueRule, project, file, i -> i.setType(CODE_SMELL));
  1366. RuleDto hotspotRule = db.rules().insertHotspotRule();
  1367. IssueDto hotspot = db.issues().insertHotspot(hotspotRule, project, file);
  1368. indexPermissionsAndIssues();
  1369. SearchWsResponse result = ws.newRequest()
  1370. .setParam("issues", Stream.of(bugIssue, vulnerabilityIssue, codeSmellIssue, hotspot).map(IssueDto::getKey).collect(Collectors.joining(",")))
  1371. .executeProtobuf(SearchWsResponse.class);
  1372. assertThat(result.getIssuesList())
  1373. .extracting(Issue::getType)
  1374. .containsExactlyInAnyOrder(BUG, VULNERABILITY, Common.RuleType.CODE_SMELL);
  1375. }
  1376. @Test
  1377. public void security_hotspots_are_not_returned_by_cwe() {
  1378. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  1379. ComponentDto file = db.components().insertComponent(newFileDto(project));
  1380. Consumer<RuleDto> ruleConsumer = ruleDefinitionDto -> ruleDefinitionDto
  1381. .setSecurityStandards(Sets.newHashSet("cwe:20", "cwe:564", "cwe:89", "cwe:943", "owaspTop10:a1"))
  1382. .setSystemTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1383. Consumer<IssueDto> issueConsumer = issueDto -> issueDto.setTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  1384. RuleDto hotspotRule = db.rules().insertHotspotRule(ruleConsumer);
  1385. db.issues().insertHotspot(hotspotRule, project, file, issueConsumer);
  1386. RuleDto issueRule = db.rules().insertIssueRule(ruleConsumer);
  1387. IssueDto issueDto1 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1388. IssueDto issueDto2 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1389. indexPermissions();
  1390. indexIssues();
  1391. SearchWsResponse result = ws.newRequest()
  1392. .setParam("cwe", "20")
  1393. .executeProtobuf(SearchWsResponse.class);
  1394. assertThat(result.getIssuesList())
  1395. .extracting(Issue::getKey)
  1396. .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto2.getKey());
  1397. }
  1398. @Test
  1399. public void security_hotspots_are_not_returned_by_assignees() {
  1400. UserDto user = db.users().insertUser();
  1401. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  1402. ComponentDto file = db.components().insertComponent(newFileDto(project));
  1403. RuleDto hotspotRule = db.rules().insertHotspotRule();
  1404. db.issues().insertHotspot(hotspotRule, project, file, issueDto -> issueDto.setAssigneeUuid(user.getUuid()));
  1405. RuleDto issueRule = db.rules().insertIssueRule();
  1406. IssueDto issueDto1 = db.issues().insertIssue(issueRule, project, file, issueDto -> issueDto.setAssigneeUuid(user.getUuid()));
  1407. IssueDto issueDto2 = db.issues().insertIssue(issueRule, project, file, issueDto -> issueDto.setAssigneeUuid(user.getUuid()));
  1408. IssueDto issueDto3 = db.issues().insertIssue(issueRule, project, file, issueDto -> issueDto.setAssigneeUuid(user.getUuid()));
  1409. IssueDto issueDto4 = db.issues().insertIssue(issueRule, project, file, issueDto -> issueDto.setAssigneeUuid(user.getUuid()));
  1410. indexPermissionsAndIssues();
  1411. SearchWsResponse result = ws.newRequest()
  1412. .setParam(PARAM_ASSIGNEES, user.getLogin())
  1413. .executeProtobuf(SearchWsResponse.class);
  1414. assertThat(result.getIssuesList())
  1415. .extracting(Issue::getKey)
  1416. .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto2.getKey(), issueDto3.getKey(), issueDto4.getKey());
  1417. }
  1418. @Test
  1419. public void security_hotspots_are_not_returned_by_rule() {
  1420. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  1421. ComponentDto file = db.components().insertComponent(newFileDto(project));
  1422. RuleDto hotspotRule = db.rules().insertHotspotRule();
  1423. db.issues().insertHotspot(hotspotRule, project, file);
  1424. indexPermissionsAndIssues();
  1425. SearchWsResponse result = ws.newRequest()
  1426. .setParam("rules", hotspotRule.getKey().toString())
  1427. .executeProtobuf(SearchWsResponse.class);
  1428. assertThat(result.getIssuesList()).isEmpty();
  1429. }
  1430. @Test
  1431. public void security_hotspots_are_not_returned_by_issues_param_only() {
  1432. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  1433. ComponentDto file = db.components().insertComponent(newFileDto(project));
  1434. RuleDto rule = db.rules().insertHotspotRule();
  1435. List<IssueDto> hotspots = IntStream.range(1, 2 + new Random().nextInt(10))
  1436. .mapToObj(value -> db.issues().insertHotspot(rule, project, file))
  1437. .toList();
  1438. indexPermissions();
  1439. indexIssues();
  1440. SearchWsResponse result = ws.newRequest()
  1441. .setParam("issues", hotspots.stream().map(IssueDto::getKey).collect(Collectors.joining(",")))
  1442. .executeProtobuf(SearchWsResponse.class);
  1443. assertThat(result.getIssuesList())
  1444. .isEmpty();
  1445. }
  1446. @Test
  1447. public void fail_if_trying_to_filter_issues_by_hotspots() {
  1448. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  1449. ComponentDto file = db.components().insertComponent(newFileDto(project));
  1450. RuleDto hotspotRule = newHotspotRule();
  1451. db.issues().insertHotspot(hotspotRule, project, file);
  1452. insertIssues(i -> i.setType(RuleType.BUG), i -> i.setType(RuleType.VULNERABILITY),
  1453. i -> i.setType(RuleType.CODE_SMELL));
  1454. indexPermissionsAndIssues();
  1455. TestRequest request = ws.newRequest()
  1456. .setParam("types", RuleType.SECURITY_HOTSPOT.toString());
  1457. assertThatThrownBy(request::execute)
  1458. .isInstanceOf(IllegalArgumentException.class)
  1459. .hasMessage("Value of parameter 'types' (SECURITY_HOTSPOT) must be one of: [CODE_SMELL, BUG, VULNERABILITY]");
  1460. }
  1461. @Test
  1462. public void security_hotspot_are_ignored_when_filtering_by_severities() {
  1463. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  1464. ComponentDto file = db.components().insertComponent(newFileDto(project));
  1465. RuleDto issueRule = db.rules().insertIssueRule();
  1466. IssueDto bugIssue = db.issues().insertIssue(issueRule, project, file, i -> i.setType(RuleType.BUG).setSeverity(Severity.MAJOR.name()));
  1467. IssueDto vulnerabilityIssue = db.issues().insertIssue(issueRule, project, file, i -> i.setType(RuleType.VULNERABILITY).setSeverity(Severity.MAJOR.name()));
  1468. IssueDto codeSmellIssue = db.issues().insertIssue(issueRule, project, file, i -> i.setType(CODE_SMELL).setSeverity(Severity.MAJOR.name()));
  1469. RuleDto hotspotRule = db.rules().insertHotspotRule();
  1470. db.issues().insertHotspot(hotspotRule, project, file, i -> i.setSeverity(Severity.MAJOR.name()));
  1471. indexPermissions();
  1472. indexIssues();
  1473. SearchWsResponse result = ws.newRequest()
  1474. .setParam("severities", Severity.MAJOR.name())
  1475. .setParam(FACETS, "severities")
  1476. .executeProtobuf(SearchWsResponse.class);
  1477. assertThat(result.getIssuesList())
  1478. .extracting(Issue::getKey, Issue::getType)
  1479. .containsExactlyInAnyOrder(
  1480. tuple(bugIssue.getKey(), BUG),
  1481. tuple(vulnerabilityIssue.getKey(), VULNERABILITY),
  1482. tuple(codeSmellIssue.getKey(), Common.RuleType.CODE_SMELL));
  1483. assertThat(result.getFacets().getFacets(0).getValuesList())
  1484. .extracting(Common.FacetValue::getVal, Common.FacetValue::getCount)
  1485. .containsExactlyInAnyOrder(tuple("MAJOR", 3L), tuple("INFO", 0L), tuple("MINOR", 0L), tuple("CRITICAL", 0L), tuple("BLOCKER", 0L));
  1486. }
  1487. @Test
  1488. public void return_total_effort() {
  1489. insertIssues(i -> i.setEffort(10L), i -> i.setEffort(15L));
  1490. indexPermissionsAndIssues();
  1491. SearchWsResponse response = ws.newRequest().executeProtobuf(SearchWsResponse.class);
  1492. assertThat(response.getEffortTotal()).isEqualTo(25L);
  1493. }
  1494. @Test
  1495. public void givenNotQuickFixableIssue_returnIssueIsNotQuickFixable() {
  1496. insertIssues(i -> i.setQuickFixAvailable(false));
  1497. indexPermissionsAndIssues();
  1498. SearchWsResponse response = ws.newRequest().executeProtobuf(SearchWsResponse.class);
  1499. assertThat(response.getIssuesList()).hasSize(1);
  1500. assertThat(response.getIssuesList().get(0).getQuickFixAvailable()).isFalse();
  1501. }
  1502. @Test
  1503. public void givenQuickFixableIssue_returnIssueIsQuickFixable() {
  1504. insertIssues(i -> i.setQuickFixAvailable(true));
  1505. indexPermissionsAndIssues();
  1506. SearchWsResponse response = ws.newRequest().executeProtobuf(SearchWsResponse.class);
  1507. assertThat(response.getIssuesList()).hasSize(1);
  1508. assertThat(response.getIssuesList().get(0).getQuickFixAvailable()).isTrue();
  1509. }
  1510. @Test
  1511. public void paging() {
  1512. RuleDto rule = newIssueRule();
  1513. ComponentDto project = db.components().insertPublicProject("PROJECT_ID", c -> c.setKey("PROJECT_KEY")).getMainBranchComponent();
  1514. indexPermissions();
  1515. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setKey("FILE_KEY"));
  1516. for (int i = 0; i < 12; i++) {
  1517. IssueDto issue = newIssue(rule, project, file).setChecksum(null);
  1518. dbClient.issueDao().insert(session, issue);
  1519. }
  1520. session.commit();
  1521. indexIssues();
  1522. ws.newRequest()
  1523. .setParam(WebService.Param.PAGE, "2")
  1524. .setParam(WebService.Param.PAGE_SIZE, "9")
  1525. .execute()
  1526. .assertJson(this.getClass(), "paging.json");
  1527. }
  1528. @Test
  1529. public void paging_with_page_size_to_minus_one() {
  1530. TestRequest requestWithNegativePageSize = ws.newRequest()
  1531. .setParam(WebService.Param.PAGE, "1")
  1532. .setParam(WebService.Param.PAGE_SIZE, "-1");
  1533. assertThatThrownBy(requestWithNegativePageSize::execute)
  1534. .isInstanceOf(IllegalArgumentException.class)
  1535. .hasMessage("Page size must be between 1 and 500 (got -1)");
  1536. }
  1537. @Test
  1538. public void default_page_size_is_100() {
  1539. ws.newRequest()
  1540. .execute()
  1541. .assertJson(this.getClass(), "default_page_size_is_100.json");
  1542. }
  1543. // SONAR-10217
  1544. @Test
  1545. public void empty_search_with_unknown_branch() {
  1546. SearchWsResponse response = ws.newRequest()
  1547. .setParam("onComponentOnly", "true")
  1548. .setParam("components", "foo")
  1549. .setParam("branch", "bar")
  1550. .executeProtobuf(SearchWsResponse.class);
  1551. assertThat(response)
  1552. .extracting(SearchWsResponse::getIssuesList, r -> r.getPaging().getTotal())
  1553. .containsExactlyInAnyOrder(Collections.emptyList(), 0);
  1554. }
  1555. @Test
  1556. public void empty_search() {
  1557. SearchWsResponse response = ws.newRequest().executeProtobuf(SearchWsResponse.class);
  1558. assertThat(response)
  1559. .extracting(SearchWsResponse::getIssuesList, r -> r.getPaging().getTotal())
  1560. .containsExactlyInAnyOrder(Collections.emptyList(), 0);
  1561. }
  1562. @Test
  1563. public void fail_when_invalid_format() {
  1564. TestRequest invalidFormatRequest = ws.newRequest()
  1565. .setParam(PARAM_CREATED_AFTER, "wrong-date-input");
  1566. assertThatThrownBy(invalidFormatRequest::execute)
  1567. .isInstanceOf(IllegalArgumentException.class)
  1568. .hasMessage("Date 'wrong-date-input' cannot be parsed as either a date or date+time");
  1569. }
  1570. @Test
  1571. public void test_definition() {
  1572. WebService.Action def = ws.getDef();
  1573. assertThat(def.key()).isEqualTo("search");
  1574. assertThat(def.isInternal()).isFalse();
  1575. assertThat(def.isPost()).isFalse();
  1576. assertThat(def.since()).isEqualTo("3.6");
  1577. assertThat(def.responseExampleAsString()).isNotEmpty();
  1578. assertThat(def.params()).extracting("key").containsExactlyInAnyOrder(
  1579. "additionalFields", "asc", "assigned", "assignees", "author", "components", "branch", "pullRequest", "createdAfter", "createdAt",
  1580. "createdBefore", "createdInLast", "directories", "facets", "files", "issues", "scopes", "languages", "onComponentOnly",
  1581. "p", "projects", "ps", "resolutions", "resolved", "rules", "s", "severities", "statuses", "tags", "types", "pciDss-3.2", "pciDss-4.0", "owaspAsvs-4.0",
  1582. "owaspAsvsLevel", "owaspTop10",
  1583. "owaspTop10-2021", "sansTop25", "cwe", "sonarsourceSecurity", "timeZone", "inNewCodePeriod", "codeVariants");
  1584. WebService.Param branch = def.param(PARAM_BRANCH);
  1585. assertThat(branch.isInternal()).isFalse();
  1586. assertThat(branch.isRequired()).isFalse();
  1587. assertThat(branch.since()).isEqualTo("6.6");
  1588. WebService.Param projectUuids = def.param("projects");
  1589. assertThat(projectUuids.description()).isEqualTo("To retrieve issues associated to a specific list of projects (comma-separated list of project keys). " +
  1590. "This parameter is mostly used by the Issues page, please prefer usage of the componentKeys parameter. If this parameter is set, projectUuids must not be set.");
  1591. }
  1592. @Test
  1593. public void search_when_additional_field_set_return_context_key() {
  1594. insertIssues(issue -> issue.setRuleDescriptionContextKey("spring"));
  1595. indexPermissionsAndIssues();
  1596. SearchWsResponse response = ws.newRequest()
  1597. .setParam("additionalFields", "ruleDescriptionContextKey")
  1598. .executeProtobuf(SearchWsResponse.class);
  1599. assertThat(response.getIssuesList()).isNotEmpty()
  1600. .extracting(Issue::getRuleDescriptionContextKey).containsExactly("spring");
  1601. }
  1602. @Test
  1603. public void search_when_no_additional_field_return_empty_context_key() {
  1604. insertIssues(issue -> issue.setRuleDescriptionContextKey("spring"));
  1605. indexPermissionsAndIssues();
  1606. SearchWsResponse response = ws.newRequest()
  1607. .executeProtobuf(SearchWsResponse.class);
  1608. assertThat(response.getIssuesList()).isNotEmpty()
  1609. .extracting(Issue::getRuleDescriptionContextKey).containsExactly(EMPTY);
  1610. }
  1611. @Test
  1612. public void search_when_additional_field_but_no_context_key_return_empty_context_key() {
  1613. insertIssues(issue -> issue.setRuleDescriptionContextKey(null));
  1614. indexPermissionsAndIssues();
  1615. SearchWsResponse response = ws.newRequest()
  1616. .setParam("additionalFields", "ruleDescriptionContextKey")
  1617. .executeProtobuf(SearchWsResponse.class);
  1618. assertThat(response.getIssuesList()).isNotEmpty()
  1619. .extracting(Issue::getRuleDescriptionContextKey).containsExactly(EMPTY);
  1620. }
  1621. @Test
  1622. public void search_when_additional_field_set_to_all_return_context_key() {
  1623. insertIssues(issue -> issue.setRuleDescriptionContextKey("spring"));
  1624. indexPermissionsAndIssues();
  1625. SearchWsResponse response = ws.newRequest()
  1626. .setParam("additionalFields", "_all")
  1627. .executeProtobuf(SearchWsResponse.class);
  1628. assertThat(response.getIssuesList()).isNotEmpty()
  1629. .extracting(Issue::getRuleDescriptionContextKey).containsExactly("spring");
  1630. }
  1631. private RuleDto newIssueRule() {
  1632. RuleDto rule = newRule(XOO_X1, createDefaultRuleDescriptionSection(uuidFactory.create(), "Rule desc"))
  1633. .setLanguage("xoo")
  1634. .setName("Rule name")
  1635. .setStatus(RuleStatus.READY);
  1636. db.rules().insert(rule);
  1637. return rule;
  1638. }
  1639. private RuleDto newHotspotRule() {
  1640. RuleDto rule = newRule(XOO_X2, createDefaultRuleDescriptionSection(uuidFactory.create(), "Rule desc"))
  1641. .setLanguage("xoo")
  1642. .setName("Rule name")
  1643. .setStatus(RuleStatus.READY)
  1644. .setType(SECURITY_HOTSPOT_VALUE);
  1645. db.rules().insert(rule);
  1646. return rule;
  1647. }
  1648. private void indexPermissions() {
  1649. permissionIndexer.indexAll(permissionIndexer.getIndexTypes());
  1650. }
  1651. private void indexIssues() {
  1652. issueIndexer.indexAllIssues();
  1653. }
  1654. private void grantPermissionToAnyone(ProjectDto project, String permission) {
  1655. dbClient.groupPermissionDao().insert(session,
  1656. new GroupPermissionDto()
  1657. .setUuid(Uuids.createFast())
  1658. .setGroupUuid(null)
  1659. .setEntityUuid(project.getUuid())
  1660. .setEntityName(project.getName())
  1661. .setRole(permission),
  1662. project, null);
  1663. session.commit();
  1664. userSession.logIn().addProjectPermission(permission, project);
  1665. }
  1666. private void insertIssues(Consumer<IssueDto>... populators) {
  1667. UserDto john = db.users().insertUser();
  1668. userSession.logIn(john);
  1669. RuleDto rule = db.rules().insertIssueRule();
  1670. ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
  1671. ComponentDto file = db.components().insertComponent(newFileDto(project));
  1672. for (Consumer<IssueDto> populator : populators) {
  1673. db.issues().insertIssue(rule, project, file, populator);
  1674. }
  1675. }
  1676. private void indexPermissionsAndIssues() {
  1677. indexPermissions();
  1678. indexIssues();
  1679. }
  1680. }