diff --git a/article-api/src/main/scala/no/ndla/articleapi/validation/ContentValidator.scala b/article-api/src/main/scala/no/ndla/articleapi/validation/ContentValidator.scala index 4b556f08d..90fc36721 100644 --- a/article-api/src/main/scala/no/ndla/articleapi/validation/ContentValidator.scala +++ b/article-api/src/main/scala/no/ndla/articleapi/validation/ContentValidator.scala @@ -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) ++ @@ -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()) diff --git a/article-api/src/test/scala/no/ndla/articleapi/validation/ContentValidatorTest.scala b/article-api/src/test/scala/no/ndla/articleapi/validation/ContentValidatorTest.scala index c4f191bed..f8b4a626b 100644 --- a/article-api/src/test/scala/no/ndla/articleapi/validation/ContentValidatorTest.scala +++ b/article-api/src/test/scala/no/ndla/articleapi/validation/ContentValidatorTest.scala @@ -15,6 +15,7 @@ import no.ndla.common.model.domain.{ ArticleMetaImage, Author, Description, + Disclaimer, Introduction, RequiredLibrary, Tag, @@ -30,6 +31,8 @@ class ContentValidatorTest extends UnitSuite with TestEnvironment { val validDocument = """

heisann

heia

""" val validIntroduction = """

heisann heia

hopp

""" val invalidDocument = """
""" + val validDisclaimer = + """

hallo!test

""" test("validateArticle does not throw an exception on a valid document") { val article = TestData.sampleArticleWithByNcSa.copy(content = Seq(ArticleContent(validDocument, "nb"))) @@ -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("

hei

", "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")), diff --git a/draft-api/src/main/scala/no/ndla/draftapi/validation/ContentValidator.scala b/draft-api/src/main/scala/no/ndla/draftapi/validation/ContentValidator.scala index d1bd62e04..c9ff0c12b 100644 --- a/draft-api/src/main/scala/no/ndla/draftapi/validation/ContentValidator.scala +++ b/draft-api/src/main/scala/no/ndla/draftapi/validation/ContentValidator.scala @@ -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 ++ @@ -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()) diff --git a/draft-api/src/test/scala/no/ndla/draftapi/validation/ContentValidatorTest.scala b/draft-api/src/test/scala/no/ndla/draftapi/validation/ContentValidatorTest.scala index 9d626f17c..413498b69 100644 --- a/draft-api/src/test/scala/no/ndla/draftapi/validation/ContentValidatorTest.scala +++ b/draft-api/src/test/scala/no/ndla/draftapi/validation/ContentValidatorTest.scala @@ -21,6 +21,8 @@ class ContentValidatorTest extends UnitSuite with TestEnvironment { override val converterService: ConverterService = new ConverterService val validDocument = """

heisann

heia

""" val invalidDocument = """
""" + val validDisclaimer = + """

hallo!test

""" val articleToValidate: Draft = TestData.sampleArticleWithByNcSa.copy(responsible = Some(Responsible("hei", TestData.today))) @@ -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("

hei

", "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"))