Skip to content

Commit

Permalink
Add content validation for disclaimer
Browse files Browse the repository at this point in the history
  • Loading branch information
katrinewi committed Dec 16, 2024
1 parent d3c8a06 commit d754dc5
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ trait ContentValidator {
def validateArticle(article: Article, isImported: Boolean): Try[Article] = {
val validationErrors = validateArticleContent(article.content) ++
article.introduction.flatMap(i => validateIntroduction(i)) ++
validateArticleDisclaimer(article.disclaimer.getOrElse(Seq.empty)) ++
validateMetaDescription(article.metaDescription, isImported) ++
validateTitle(article.title) ++
validateCopyright(article.copyright) ++
Expand Down Expand Up @@ -89,6 +90,14 @@ trait ContentValidator {
}) ++ validateNonEmpty("content", contents)
}

private def validateArticleDisclaimer(disclaimers: Seq[Disclaimer]): Seq[ValidationMessage] = {
disclaimers.flatMap(disclaimer => {
val field = s"disclaimer.${disclaimer.language}"
TextValidator.validate(field, disclaimer.disclaimer, allLegalTags).toList ++
validateLanguage("content.language", disclaimer.language)
})
}

private def rootElementContainsOnlySectionBlocks(field: String, html: String): Option[ValidationMessage] = {
val legalTopLevelTag = "section"
val topLevelTags = stringToJsoupDocument(html).children().asScala.map(_.tagName())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import no.ndla.common.model.domain.{
ArticleMetaImage,
Author,
Description,
Disclaimer,
Introduction,
RequiredLibrary,
Tag,
Expand All @@ -30,6 +31,8 @@ class ContentValidatorTest extends UnitSuite with TestEnvironment {
val validDocument = """<section><h1>heisann</h1><h2>heia</h2></section>"""
val validIntroduction = """<p>heisann <span lang="en">heia</span></p><p>hopp</p>"""
val invalidDocument = """<section><invalid></invalid></section>"""
val validDisclaimer =
"""<p><strong>hallo!</strong><ndlaembed data-content-id="123" data-open-in="current-context" data-resource="content-link" data-content-type="article">test</ndlaembed></p>"""

test("validateArticle does not throw an exception on a valid document") {
val article = TestData.sampleArticleWithByNcSa.copy(content = Seq(ArticleContent(validDocument, "nb")))
Expand Down Expand Up @@ -77,6 +80,41 @@ class ContentValidatorTest extends UnitSuite with TestEnvironment {
contentValidator.validateArticle(article, false).isSuccess should be(true)
}

test("validateArticle should throw an error if disclaimer contains illegal HTML tags") {
val article = TestData.sampleArticleWithByNcSa.copy(
content = Seq(ArticleContent(validDocument, "nb")),
disclaimer = Some(Seq(Disclaimer("<p><hallo>hei</hallo></p>", "nb")))
)
val result = contentValidator.validateArticle(article, false)
result.failed.get.asInstanceOf[ValidationException].errors.length should be(1)
result.failed.get.asInstanceOf[ValidationException].errors.head.message should be(
"The content contains illegal tags and/or attributes. Allowed HTML tags are: h3, msgroup, a, article, sub, sup, mtext, msrow, tbody, mtd, pre, thead, figcaption, mover, msup, semantics, ol, span, mroot, munder, h4, mscarries, dt, nav, mtr, ndlaembed, li, br, mrow, merror, mphantom, u, audio, ul, maligngroup, mfenced, annotation, div, strong, section, i, mspace, malignmark, mfrac, code, h2, td, aside, em, mstack, button, dl, th, tfoot, math, tr, b, blockquote, msline, col, annotation-xml, mstyle, caption, mpadded, mo, mlongdiv, msubsup, p, munderover, maction, menclose, h1, details, mmultiscripts, msqrt, mscarry, mstac, mi, mglyph, mlabeledtr, mtable, mprescripts, summary, mn, msub, ms, table, colgroup, dd"
)
}

test("validateArticle should not throw an error if disclaimer contains legal HTML tags") {
val article = TestData.sampleArticleWithByNcSa.copy(
content = Seq(ArticleContent(validDocument, "nb")),
disclaimer = Some(
Seq(
Disclaimer(
validDisclaimer,
"nb"
)
)
)
)
contentValidator.validateArticle(article, false).isSuccess should be(true)
}

test("validateArticle should not throw an error if disclaimer contains plain text") {
val article = TestData.sampleArticleWithByNcSa.copy(
content = Seq(ArticleContent(validDocument, "nb")),
disclaimer = Some(Seq(Disclaimer("disclaimer", "nb")))
)
contentValidator.validateArticle(article, false).isSuccess should be(true)
}

test("validateArticle should throw an error if metaDescription contains HTML tags") {
val article = TestData.sampleArticleWithByNcSa.copy(
content = Seq(ArticleContent(validDocument, "nb")),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ trait ContentValidator {
if (shouldValidateEntireArticle)
article.content.flatMap(c => validateArticleContent(c)) ++
article.introduction.flatMap(i => validateIntroduction(i)) ++
validateArticleDisclaimer(article.disclaimer.getOrElse(Seq.empty)) ++
article.metaDescription.flatMap(m => validateMetaDescription(m)) ++
validateTitles(article.title) ++
article.copyright.map(x => validateCopyright(x)).toSeq.flatten ++
Expand Down Expand Up @@ -164,6 +165,13 @@ trait ContentValidator {
validateLanguage("content.language", content.language)
}

private def validateArticleDisclaimer(disclaimers: Seq[Disclaimer]): Seq[ValidationMessage] = {
disclaimers.flatMap(disclaimer => {
TextValidator.validate("disclaimer", disclaimer.disclaimer, allLegalTags).toList ++
validateLanguage("disclaimer.language", disclaimer.language)
})
}

private def rootElementContainsOnlySectionBlocks(field: String, html: String): Option[ValidationMessage] = {
val legalTopLevelTag = "section"
val topLevelTags = stringToJsoupDocument(html).children().asScala.map(_.tagName())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ class ContentValidatorTest extends UnitSuite with TestEnvironment {
override val converterService: ConverterService = new ConverterService
val validDocument = """<section><h1>heisann</h1><h2>heia</h2></section>"""
val invalidDocument = """<section><invalid></invalid></section>"""
val validDisclaimer =
"""<p><strong>hallo!</strong><ndlaembed data-content-id="123" data-open-in="current-context" data-resource="content-link" data-content-type="article">test</ndlaembed></p>"""

val articleToValidate: Draft =
TestData.sampleArticleWithByNcSa.copy(responsible = Some(Responsible("hei", TestData.today)))
Expand Down Expand Up @@ -58,7 +60,36 @@ class ContentValidatorTest extends UnitSuite with TestEnvironment {
contentValidator.validateArticle(article).isSuccess should be(true)
}

test("validateArticle should throw an error if disclaimer contains illegal HTML tags") {
val article = articleToValidate.copy(
content = Seq(ArticleContent(validDocument, "nb")),
disclaimer = Some(Seq(Disclaimer("<p><hallo>hei</hallo></p>", "nb")))
)
val result = contentValidator.validateArticle(article)
result.failed.get.asInstanceOf[ValidationException].errors.length should be(1)
result.failed.get.asInstanceOf[ValidationException].errors.head.message should be(
"The content contains illegal tags and/or attributes. Allowed HTML tags are: h3, msgroup, a, article, sub, sup, mtext, msrow, tbody, mtd, pre, thead, figcaption, mover, msup, semantics, ol, span, mroot, munder, h4, mscarries, dt, nav, mtr, ndlaembed, li, br, mrow, merror, mphantom, u, audio, ul, maligngroup, mfenced, annotation, div, strong, section, i, mspace, malignmark, mfrac, code, h2, td, aside, em, mstack, button, dl, th, tfoot, math, tr, b, blockquote, msline, col, annotation-xml, mstyle, caption, mpadded, mo, mlongdiv, msubsup, p, munderover, maction, menclose, h1, details, mmultiscripts, msqrt, mscarry, mstac, mi, mglyph, mlabeledtr, mtable, mprescripts, summary, mn, msub, ms, table, colgroup, dd"
)
}

test("validateArticle should not throw an error if disclaimer contains legal HTML tags") {
val article = articleToValidate.copy(
content = Seq(ArticleContent(validDocument, "nb")),
disclaimer = Some(Seq(Disclaimer(validDisclaimer, "nb")))
)
contentValidator.validateArticle(article).isSuccess should be(true)

}

test("validateArticle should throw an error if metaDescription contains HTML tags") {
val article = articleToValidate.copy(
content = Seq(ArticleContent(validDocument, "nb")),
metaDescription = Seq(Description(validDisclaimer, "nb"))
)
contentValidator.validateArticle(article).isFailure should be(true)
}

test("validateArticle should throw an error if metaDescription contains plain text") {
val article = articleToValidate.copy(
content = Seq(ArticleContent(validDocument, "nb")),
metaDescription = Seq(Description(validDocument, "nb"))
Expand Down

0 comments on commit d754dc5

Please sign in to comment.