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 107KB

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