} | } | ||||
public static HotspotRuleDescription from(RuleDefinitionDto dto) { | public static HotspotRuleDescription from(RuleDefinitionDto dto) { | ||||
String description = dto.getDescription(); | |||||
String description = dto.isCustomRule() ? RuleDescriptionFormatter.getDescriptionAsHtml(dto) : dto.getDescription(); | |||||
return from(description); | return from(description); | ||||
} | } | ||||
if (endIndex == -1) { | if (endIndex == -1) { | ||||
endIndex = description.length(); | endIndex = description.length(); | ||||
} | } | ||||
return new String[] { | |||||
return new String[]{ | |||||
description.substring(0, beginningIndex) + description.substring(endIndex), | description.substring(0, beginningIndex) + description.substring(endIndex), | ||||
description.substring(beginningIndex, endIndex) | description.substring(beginningIndex, endIndex) | ||||
}; | }; | ||||
} else { | } else { | ||||
return new String[] {description, ""}; | |||||
return new String[]{description, ""}; | |||||
} | } | ||||
} | } |
import org.junit.Test; | import org.junit.Test; | ||||
import org.junit.runner.RunWith; | import org.junit.runner.RunWith; | ||||
import org.sonar.db.rule.RuleDefinitionDto; | import org.sonar.db.rule.RuleDefinitionDto; | ||||
import org.sonar.db.rule.RuleDto; | |||||
import org.sonar.db.rule.RuleTesting; | import org.sonar.db.rule.RuleTesting; | ||||
import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; | import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; | ||||
assertThat(result.getFixIt().get()).isEqualTo(RECOMMENTEDCODINGPRACTICE + SEE); | assertThat(result.getFixIt().get()).isEqualTo(RECOMMENTEDCODINGPRACTICE + SEE); | ||||
} | } | ||||
@Test | |||||
public void parse_custom_rule_description() { | |||||
String ruleDescription = "This is the custom rule description"; | |||||
String exceptionsContent = "This the exceptions section content"; | |||||
String askContent = "This is the ask section content"; | |||||
String recommendedContent = "This is the recommended section content"; | |||||
RuleDefinitionDto dto = RuleTesting.newRule() | |||||
.setTemplateUuid("123") | |||||
.setDescriptionFormat(RuleDto.Format.MARKDOWN) | |||||
.setDescription( | |||||
ruleDescription + "\n" | |||||
+ "== Exceptions" + "\n" | |||||
+ exceptionsContent + "\n" | |||||
+ "== Ask Yourself Whether" + "\n" | |||||
+ askContent + "\n" | |||||
+ "== Recommended Secure Coding Practices" + "\n" | |||||
+ recommendedContent + "\n" | |||||
); | |||||
HotspotRuleDescription result = HotspotRuleDescription.from(dto); | |||||
assertThat(result.getRisk().get()).hasToString( | |||||
ruleDescription + "<br/>" | |||||
+ "<h2>Exceptions</h2>" | |||||
+ exceptionsContent + "<br/>" | |||||
); | |||||
assertThat(result.getVulnerable().get()).hasToString( | |||||
"<h2>Ask Yourself Whether</h2>" | |||||
+ askContent + "<br/>" | |||||
); | |||||
assertThat(result.getFixIt().get()).hasToString( | |||||
"<h2>Recommended Secure Coding Practices</h2>" | |||||
+ recommendedContent + "<br/>" | |||||
); | |||||
} | |||||
/* | /* | ||||
* Bunch of static constant to create rule description. | * Bunch of static constant to create rule description. | ||||
*/ | */ |
import org.sonar.server.issue.TextRangeResponseFormatter; | import org.sonar.server.issue.TextRangeResponseFormatter; | ||||
import org.sonar.server.issue.ws.UserResponseFormatter; | import org.sonar.server.issue.ws.UserResponseFormatter; | ||||
import org.sonar.server.rule.HotspotRuleDescription; | import org.sonar.server.rule.HotspotRuleDescription; | ||||
import org.sonar.server.rule.RuleDescriptionFormatter; | |||||
import org.sonar.server.security.SecurityStandards; | import org.sonar.server.security.SecurityStandards; | ||||
import org.sonar.server.text.MacroInterpreter; | import org.sonar.server.text.MacroInterpreter; | ||||
import org.sonarqube.ws.Common; | import org.sonarqube.ws.Common; | ||||
.setSecurityCategory(sqCategory.getKey()) | .setSecurityCategory(sqCategory.getKey()) | ||||
.setVulnerabilityProbability(sqCategory.getVulnerability().name()); | .setVulnerabilityProbability(sqCategory.getVulnerability().name()); | ||||
if (ruleDefinitionDto.isCustomRule()) { | |||||
String htmlDescription = RuleDescriptionFormatter.getDescriptionAsHtml(ruleDefinitionDto); | |||||
if (htmlDescription != null) { | |||||
ruleBuilder.setRiskDescription(macroInterpreter.interpret(htmlDescription)); | |||||
} | |||||
} else { | |||||
HotspotRuleDescription hotspotRuleDescription = HotspotRuleDescription.from(ruleDefinitionDto); | |||||
hotspotRuleDescription.getVulnerable().ifPresent(ruleBuilder::setVulnerabilityDescription); | |||||
hotspotRuleDescription.getRisk().ifPresent(ruleBuilder::setRiskDescription); | |||||
hotspotRuleDescription.getFixIt().ifPresent(ruleBuilder::setFixRecommendations); | |||||
} | |||||
HotspotRuleDescription hotspotRuleDescription = HotspotRuleDescription.from(ruleDefinitionDto); | |||||
hotspotRuleDescription.getVulnerable().ifPresent(ruleBuilder::setVulnerabilityDescription); | |||||
hotspotRuleDescription.getRisk().ifPresent(ruleBuilder::setRiskDescription); | |||||
hotspotRuleDescription.getFixIt().ifPresent(ruleBuilder::setFixRecommendations); | |||||
responseBuilder.setRule(ruleBuilder.build()); | responseBuilder.setRule(ruleBuilder.build()); | ||||
} | } | ||||
boolean hotspotOnProject = Objects.equals(project.uuid(), componentUuid); | boolean hotspotOnProject = Objects.equals(project.uuid(), componentUuid); | ||||
ComponentDto component = hotspotOnProject ? project | ComponentDto component = hotspotOnProject ? project | ||||
: dbClient.componentDao().selectByUuid(dbSession, componentUuid) | : dbClient.componentDao().selectByUuid(dbSession, componentUuid) | ||||
.orElseThrow(() -> new NotFoundException(format("Component with uuid '%s' does not exist", componentUuid))); | |||||
.orElseThrow(() -> new NotFoundException(format("Component with uuid '%s' does not exist", componentUuid))); | |||||
return new Components(project, component); | return new Components(project, component); | ||||
} | } |
userSessionRule.logIn().addProjectPermission(UserRole.USER, project); | userSessionRule.logIn().addProjectPermission(UserRole.USER, project); | ||||
ComponentDto file = dbTester.components().insertComponent(newFileDto(project)); | ComponentDto file = dbTester.components().insertComponent(newFileDto(project)); | ||||
String description = "<div>line1\nline2</div>"; | |||||
String parsedDescription = "<div>line1<br/>line2</div>"; | |||||
String resultingDescription = "!" + parsedDescription + "!"; | |||||
String description = "== Title\n<div>line1\nline2</div>"; | |||||
RuleDefinitionDto rule = newRule(SECURITY_HOTSPOT, | RuleDefinitionDto rule = newRule(SECURITY_HOTSPOT, | ||||
r -> r.setTemplateUuid("123") | r -> r.setTemplateUuid("123") | ||||
.setDescription(description) | .setDescription(description) | ||||
.setDescriptionFormat(MARKDOWN)); | .setDescriptionFormat(MARKDOWN)); | ||||
doReturn(resultingDescription).when(macroInterpreter).interpret(parsedDescription); | |||||
IssueDto hotspot = dbTester.issues().insertHotspot(rule, project, file); | IssueDto hotspot = dbTester.issues().insertHotspot(rule, project, file); | ||||
mockChangelogAndCommentsFormattingContext(); | mockChangelogAndCommentsFormattingContext(); | ||||
Hotspots.ShowWsResponse response = newRequest(hotspot) | Hotspots.ShowWsResponse response = newRequest(hotspot) | ||||
.executeProtobuf(Hotspots.ShowWsResponse.class); | .executeProtobuf(Hotspots.ShowWsResponse.class); | ||||
assertThat(response.getRule().getRiskDescription()).isEqualTo(resultingDescription); | |||||
assertThat(response.getRule().getRiskDescription()).isEqualTo("<h2>Title</h2><div>line1<br/>line2</div>"); | |||||
} | } | ||||
@Test | @Test |
CharSequence headingText = token.subSequence(index, token.length()); | CharSequence headingText = token.subSequence(index, token.length()); | ||||
output.append("<h" + headingLevel + ">"); | output.append("<h" + headingLevel + ">"); | ||||
output.append(headingText); | |||||
output.append(headingText.toString().trim()); | |||||
output.append("</h" + headingLevel + ">"); | output.append("</h" + headingLevel + ">"); | ||||
} | } | ||||
} | } |
@Test | @Test | ||||
public void shouldDecorateHeadings() { | public void shouldDecorateHeadings() { | ||||
assertThat(Markdown.convertToHtml(" = Top\r== Sub\r\n=== Subsub\n ==== \n 1.five")) | |||||
.isEqualTo("<h1>Top\r</h1><h2>Sub\r\n</h2><h3>Subsub\n</h3><h4></h4> 1.five"); | |||||
assertThat(Markdown.convertToHtml(" = Top\r== Sub\r\n=== Sub sub\n ==== \n 1.five")) | |||||
.isEqualTo("<h1>Top</h1><h2>Sub</h2><h3>Sub sub</h3><h4></h4> 1.five"); | |||||
} | } | ||||
@Test | @Test |