From f1808a92c75c308b877ab230f2bfafc810542dc7 Mon Sep 17 00:00:00 2001 From: Gunnar Velle Date: Tue, 19 Nov 2024 12:09:05 +0100 Subject: [PATCH 1/2] Add created field for learningpaths --- .../domain/learningpath/LearningPath.scala | 1 + .../V38__AddCreatedToLearningpath.sql | 6 +++ .../model/api/LearningPathSummaryV2.scala | 1 + .../model/api/LearningPathV2.scala | 1 + .../model/search/SearchableLearningPath.scala | 1 + .../LearningPathRepositoryComponent.scala | 2 +- .../service/ConverterService.scala | 5 +- .../service/UpdateService.scala | 15 ++---- .../SearchConverterServiceComponent.scala | 8 +-- .../service/search/SearchIndexService.scala | 9 ++-- .../service/search/SearchService.scala | 8 +-- .../validation/DurationValidator.scala | 4 +- .../validation/LanguageValidator.scala | 8 +-- .../validation/LearningPathValidator.scala | 8 +-- .../validation/LearningStepValidator.scala | 49 ++++++++++--------- .../validation/StatusValidator.scala | 16 +++--- .../validation/TextValidator.scala | 34 ++++++------- .../validation/TitleValidator.scala | 4 +- .../validation/UrlValidator.scala | 6 +-- .../no/ndla/learningpathapi/TestData.scala | 1 + .../controller/InternControllerTest.scala | 20 ++++---- .../LearningpathControllerV2Test.scala | 1 + .../controller/StatsControllerTest.scala | 2 +- ...thRepositoryComponentIntegrationTest.scala | 1 + .../service/ConverterServiceTest.scala | 7 ++- .../service/ReadServiceTest.scala | 2 + .../service/UpdateServiceTest.scala | 5 ++ .../service/search/SearchServiceTest.scala | 9 +++- .../LearningPathValidatorTest.scala | 3 +- 29 files changed, 132 insertions(+), 105 deletions(-) create mode 100644 learningpath-api/src/main/resources/no/ndla/learningpathapi/db/migration/V38__AddCreatedToLearningpath.sql diff --git a/common/src/main/scala/no/ndla/common/model/domain/learningpath/LearningPath.scala b/common/src/main/scala/no/ndla/common/model/domain/learningpath/LearningPath.scala index 6cc404c81c..4d1fef9b6c 100644 --- a/common/src/main/scala/no/ndla/common/model/domain/learningpath/LearningPath.scala +++ b/common/src/main/scala/no/ndla/common/model/domain/learningpath/LearningPath.scala @@ -25,6 +25,7 @@ case class LearningPath( duration: Option[Int], status: LearningPathStatus, verificationStatus: LearningPathVerificationStatus, + created: NDLADate, lastUpdated: NDLADate, tags: Seq[Tag], owner: String, diff --git a/learningpath-api/src/main/resources/no/ndla/learningpathapi/db/migration/V38__AddCreatedToLearningpath.sql b/learningpath-api/src/main/resources/no/ndla/learningpathapi/db/migration/V38__AddCreatedToLearningpath.sql new file mode 100644 index 0000000000..6c2a71e49d --- /dev/null +++ b/learningpath-api/src/main/resources/no/ndla/learningpathapi/db/migration/V38__AddCreatedToLearningpath.sql @@ -0,0 +1,6 @@ +UPDATE learningpaths lp +SET document=( + SELECT document || jsonb_build_object('created', document ->> 'lastUpdated') + FROM learningpaths lp2 + WHERE lp.id = lp2.id +) diff --git a/learningpath-api/src/main/scala/no/ndla/learningpathapi/model/api/LearningPathSummaryV2.scala b/learningpath-api/src/main/scala/no/ndla/learningpathapi/model/api/LearningPathSummaryV2.scala index 92543e2a63..75b622dfa5 100644 --- a/learningpath-api/src/main/scala/no/ndla/learningpathapi/model/api/LearningPathSummaryV2.scala +++ b/learningpath-api/src/main/scala/no/ndla/learningpathapi/model/api/LearningPathSummaryV2.scala @@ -25,6 +25,7 @@ case class LearningPathSummaryV2( @description("Url to where a cover photo can be found") coverPhotoUrl: Option[String], @description("The duration of the learningpath in minutes") duration: Option[Int], @description("The publishing status of the learningpath.") status: String, + @description("The date when this learningpath was created.") created: NDLADate, @description("The date when this learningpath was last updated.") lastUpdated: NDLADate, @description("Searchable tags for the learningpath") tags: LearningPathTags, @description("The contributors of this learningpath") copyright: Copyright, diff --git a/learningpath-api/src/main/scala/no/ndla/learningpathapi/model/api/LearningPathV2.scala b/learningpath-api/src/main/scala/no/ndla/learningpathapi/model/api/LearningPathV2.scala index 5ef5a30759..0a3f73b4b8 100644 --- a/learningpath-api/src/main/scala/no/ndla/learningpathapi/model/api/LearningPathV2.scala +++ b/learningpath-api/src/main/scala/no/ndla/learningpathapi/model/api/LearningPathV2.scala @@ -28,6 +28,7 @@ case class LearningPathV2( @description("The duration of the learningpath in minutes") duration: Option[Int], @description("The publishing status of the learningpath") status: String, @description("Verification status") verificationStatus: String, + @description("The date when this learningpath was created.") created: NDLADate, @description("The date when this learningpath was last updated.") lastUpdated: NDLADate, @description("Searchable tags for the learningpath") tags: LearningPathTags, @description("Describes the copyright information for the learningpath") copyright: Copyright, diff --git a/learningpath-api/src/main/scala/no/ndla/learningpathapi/model/search/SearchableLearningPath.scala b/learningpath-api/src/main/scala/no/ndla/learningpathapi/model/search/SearchableLearningPath.scala index 9414559602..36c5033d90 100644 --- a/learningpath-api/src/main/scala/no/ndla/learningpathapi/model/search/SearchableLearningPath.scala +++ b/learningpath-api/src/main/scala/no/ndla/learningpathapi/model/search/SearchableLearningPath.scala @@ -22,6 +22,7 @@ case class SearchableLearningPath( duration: Option[Int], status: String, verificationStatus: String, + created: NDLADate, lastUpdated: NDLADate, defaultTitle: Option[String], tags: SearchableLanguageList, diff --git a/learningpath-api/src/main/scala/no/ndla/learningpathapi/repository/LearningPathRepositoryComponent.scala b/learningpath-api/src/main/scala/no/ndla/learningpathapi/repository/LearningPathRepositoryComponent.scala index 65e2b36954..b9fb064fc1 100644 --- a/learningpath-api/src/main/scala/no/ndla/learningpathapi/repository/LearningPathRepositoryComponent.scala +++ b/learningpath-api/src/main/scala/no/ndla/learningpathapi/repository/LearningPathRepositoryComponent.scala @@ -28,7 +28,7 @@ import java.util.UUID import scala.util.Try trait LearningPathRepositoryComponent extends StrictLogging { - this: DataSource with Props => + this: DataSource & Props => val learningPathRepository: LearningPathRepository def inTransaction[A](work: DBSession => A)(implicit session: DBSession = null): A = { diff --git a/learningpath-api/src/main/scala/no/ndla/learningpathapi/service/ConverterService.scala b/learningpath-api/src/main/scala/no/ndla/learningpathapi/service/ConverterService.scala index 191603db46..02689a68fc 100644 --- a/learningpath-api/src/main/scala/no/ndla/learningpathapi/service/ConverterService.scala +++ b/learningpath-api/src/main/scala/no/ndla/learningpathapi/service/ConverterService.scala @@ -48,7 +48,7 @@ trait ConverterService { val converterService: ConverterService class ConverterService { - import props._ + import props.* def asEmbedUrlV2(embedUrl: api.EmbedUrlV2, language: String): EmbedUrl = { learningpath.EmbedUrl(embedUrl.url, language, EmbedType.valueOfOrError(embedUrl.embedType)) @@ -145,6 +145,7 @@ trait ConverterService { lp.duration, lp.status.toString, lp.verificationStatus.toString, + lp.created, lp.lastUpdated, tags, asApiCopyright(lp.copyright), @@ -408,6 +409,7 @@ trait ConverterService { learningpath.LearningPathStatus.PRIVATE, getVerificationStatus(user), clock.now(), + clock.now(), domainTags, ownerId, converterService.asCopyright(newLearningPath.copyright), @@ -460,6 +462,7 @@ trait ConverterService { learningpath.coverPhotoId.flatMap(asCoverPhoto).map(_.url), learningpath.duration, learningpath.status.toString, + learningpath.created, learningpath.lastUpdated, tags, asApiCopyright(learningpath.copyright), diff --git a/learningpath-api/src/main/scala/no/ndla/learningpathapi/service/UpdateService.scala b/learningpath-api/src/main/scala/no/ndla/learningpathapi/service/UpdateService.scala index ab101124b8..e790501da2 100644 --- a/learningpath-api/src/main/scala/no/ndla/learningpathapi/service/UpdateService.scala +++ b/learningpath-api/src/main/scala/no/ndla/learningpathapi/service/UpdateService.scala @@ -30,18 +30,9 @@ import scala.annotation.tailrec import scala.util.{Failure, Success, Try} trait UpdateService { - this: LearningPathRepositoryComponent - with ReadService - with ConverterService - with SearchIndexService - with Clock - with LearningStepValidator - with LearningPathValidator - with TaxonomyApiClient - with FeideApiClient - with SearchApiClient - with Props - with RedisClient => + this: LearningPathRepositoryComponent & ReadService & ConverterService & SearchIndexService & Clock & + LearningStepValidator & LearningPathValidator & TaxonomyApiClient & FeideApiClient & SearchApiClient & Props & + RedisClient => val updateService: UpdateService class UpdateService { diff --git a/learningpath-api/src/main/scala/no/ndla/learningpathapi/service/search/SearchConverterServiceComponent.scala b/learningpath-api/src/main/scala/no/ndla/learningpathapi/service/search/SearchConverterServiceComponent.scala index 3f416aa74a..b0b4878f41 100644 --- a/learningpath-api/src/main/scala/no/ndla/learningpathapi/service/search/SearchConverterServiceComponent.scala +++ b/learningpath-api/src/main/scala/no/ndla/learningpathapi/service/search/SearchConverterServiceComponent.scala @@ -23,7 +23,7 @@ import no.ndla.search.SearchLanguage import no.ndla.search.model.{LanguageValue, SearchableLanguageList, SearchableLanguageValues} trait SearchConverterServiceComponent { - this: ConverterService with Props => + this: ConverterService & Props => val searchConverterService: SearchConverterService class SearchConverterService { @@ -57,6 +57,7 @@ trait SearchConverterServiceComponent { searchableLearningPath.coverPhotoUrl, searchableLearningPath.duration, searchableLearningPath.status, + searchableLearningPath.created, searchableLearningPath.lastUpdated, findByLanguageOrBestEffort(tags, language) .getOrElse(api.LearningPathTags(Seq(), DefaultLanguage)), @@ -86,6 +87,7 @@ trait SearchConverterServiceComponent { learningPath.duration, learningPath.status.toString, learningPath.verificationStatus.toString, + learningPath.created, learningPath.lastUpdated, defaultTitle.map(_.title), SearchableLanguageList(learningPath.tags.map(tags => LanguageValue(tags.language, tags.tags))), @@ -95,7 +97,7 @@ trait SearchConverterServiceComponent { ) } - def asSearchableLearningStep(learningStep: LearningStep): SearchableLearningStep = { + private def asSearchableLearningStep(learningStep: LearningStep): SearchableLearningStep = { SearchableLearningStep( learningStep.`type`.toString, learningStep.embedUrl.map(_.url).toList, @@ -125,7 +127,7 @@ trait SearchConverterServiceComponent { .lastOption } - val highlightKeys: Option[Map[String, _]] = Option(result.highlight) + val highlightKeys: Option[Map[String, ?]] = Option(result.highlight) val matchLanguage = keyToLanguage(highlightKeys.getOrElse(Map()).keys) matchLanguage match { diff --git a/learningpath-api/src/main/scala/no/ndla/learningpathapi/service/search/SearchIndexService.scala b/learningpath-api/src/main/scala/no/ndla/learningpathapi/service/search/SearchIndexService.scala index f2d888f409..683a5b9286 100644 --- a/learningpath-api/src/main/scala/no/ndla/learningpathapi/service/search/SearchIndexService.scala +++ b/learningpath-api/src/main/scala/no/ndla/learningpathapi/service/search/SearchIndexService.scala @@ -29,12 +29,8 @@ import no.ndla.common.model.domain.learningpath.LearningPath import no.ndla.network.tapir.auth.TokenUser trait SearchIndexService { - this: Elastic4sClient - with SearchConverterServiceComponent - with LearningPathRepositoryComponent - with SearchApiClient - with BaseIndexService - with Props => + this: Elastic4sClient & SearchConverterServiceComponent & LearningPathRepositoryComponent & SearchApiClient & + BaseIndexService & Props => val searchIndexService: SearchIndexService class SearchIndexService extends BaseIndexService with StrictLogging { @@ -165,6 +161,7 @@ trait SearchIndexService { intField("duration"), keywordField("status"), keywordField("verificationStatus"), + dateField("created"), dateField("lastUpdated"), keywordField("defaultTitle"), textField("author"), diff --git a/learningpath-api/src/main/scala/no/ndla/learningpathapi/service/search/SearchService.scala b/learningpath-api/src/main/scala/no/ndla/learningpathapi/service/search/SearchService.scala index af3af43082..617c8b8e1a 100644 --- a/learningpath-api/src/main/scala/no/ndla/learningpathapi/service/search/SearchService.scala +++ b/learningpath-api/src/main/scala/no/ndla/learningpathapi/service/search/SearchService.scala @@ -31,7 +31,7 @@ import scala.concurrent.{ExecutionContext, ExecutionContextExecutorService, Futu import scala.util.{Failure, Success, Try} trait SearchService extends StrictLogging { - this: SearchIndexService with Elastic4sClient with SearchConverterServiceComponent with Props with ErrorHandling => + this: SearchIndexService & Elastic4sClient & SearchConverterServiceComponent & Props & ErrorHandling => val searchService: SearchService class SearchService { @@ -55,7 +55,7 @@ trait SearchService extends StrictLogging { ) }) - def getHitsV2(response: SearchResponse, language: String): Seq[LearningPathSummaryV2] = { + private def getHitsV2(response: SearchResponse, language: String): Seq[LearningPathSummaryV2] = { response.totalHits match { case count if count > 0 => val resultArray = response.hits.hits.toList @@ -75,7 +75,7 @@ trait SearchService extends StrictLogging { } } - def hitAsLearningPathSummaryV2(hitString: String, language: String): LearningPathSummaryV2 = { + private def hitAsLearningPathSummaryV2(hitString: String, language: String): LearningPathSummaryV2 = { val searchable = CirceUtil.unsafeParseAs[SearchableLearningPath](hitString) searchConverterService.asApiLearningPathSummaryV2(searchable, language) } @@ -220,7 +220,7 @@ trait SearchService extends StrictLogging { } } - def pathsFilterQuery(paths: List[String]): Option[NestedQuery] = { + private def pathsFilterQuery(paths: List[String]): Option[NestedQuery] = { if (paths.isEmpty) None else { Some( diff --git a/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/DurationValidator.scala b/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/DurationValidator.scala index 4f1efc15f1..7a31e2e7be 100644 --- a/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/DurationValidator.scala +++ b/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/DurationValidator.scala @@ -11,8 +11,8 @@ package no.ndla.learningpathapi.validation import no.ndla.common.errors.ValidationMessage class DurationValidator { - val DURATION_INVALID = "Required value duration must be greater than 0." - val DURATION_REQUIRED = "Required value is empty." + private val DURATION_INVALID = "Required value duration must be greater than 0." + private val DURATION_REQUIRED = "Required value is empty." def validateRequired(durationOpt: Option[Int]): Option[ValidationMessage] = { durationOpt match { diff --git a/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/LanguageValidator.scala b/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/LanguageValidator.scala index ca6e646c0b..e8f6029663 100644 --- a/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/LanguageValidator.scala +++ b/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/LanguageValidator.scala @@ -24,10 +24,10 @@ trait LanguageValidator { } def validate(fieldPath: String, languageCode: String, allowUnknownLanguage: Boolean): Option[ValidationMessage] = { - languageCode.nonEmpty && languageCodeSupported6391(languageCode, allowUnknownLanguage) match { - case true => None - case false => - Some(ValidationMessage(fieldPath, s"Language '$languageCode' is not a supported value.")) + if (languageCode.nonEmpty && languageCodeSupported6391(languageCode, allowUnknownLanguage)) { + None + } else { + Some(ValidationMessage(fieldPath, s"Language '$languageCode' is not a supported value.")) } } diff --git a/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/LearningPathValidator.scala b/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/LearningPathValidator.scala index 0d6f5c5161..dbba12248f 100644 --- a/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/LearningPathValidator.scala +++ b/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/LearningPathValidator.scala @@ -21,13 +21,13 @@ trait LearningPathValidator { class LearningPathValidator(descriptionRequired: Boolean = true) { - val MISSING_DESCRIPTION = "At least one description is required." + private val MISSING_DESCRIPTION = "At least one description is required." - val INVALID_COVER_PHOTO = + private val INVALID_COVER_PHOTO = "The url to the coverPhoto must point to an image in NDLA Image API." - val noHtmlTextValidator = new TextValidator(allowHtml = false) - val durationValidator = new DurationValidator + val noHtmlTextValidator = new TextValidator(allowHtml = false) + private val durationValidator = new DurationValidator def validate(newLearningPath: LearningPath, allowUnknownLanguage: Boolean = false): Unit = { validateLearningPath(newLearningPath, allowUnknownLanguage) match { diff --git a/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/LearningStepValidator.scala b/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/LearningStepValidator.scala index c073051790..23e31e2023 100644 --- a/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/LearningStepValidator.scala +++ b/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/LearningStepValidator.scala @@ -14,15 +14,15 @@ import no.ndla.common.model.domain.learningpath.{Description, EmbedUrl, Learning import scala.util.{Failure, Success, Try} trait LearningStepValidator { - this: TitleValidator with LanguageValidator with TextValidator with UrlValidator => + this: TitleValidator & LanguageValidator & TextValidator & UrlValidator => val learningStepValidator: LearningStepValidator class LearningStepValidator { - val noHtmlTextValidator = new TextValidator(allowHtml = false) - val basicHtmlTextValidator = new TextValidator(allowHtml = true) - val urlValidator = new UrlValidator() + val noHtmlTextValidator = new TextValidator(allowHtml = false) + private val basicHtmlTextValidator = new TextValidator(allowHtml = true) + private val urlValidator = new UrlValidator() - val MISSING_DESCRIPTION_OR_EMBED_URL = + private val MISSING_DESCRIPTION_OR_EMBED_URL = "A learningstep is required to have either a description, embedUrl or both." def validate(newLearningStep: LearningStep, allowUnknownLanguage: Boolean = false): Try[LearningStep] = { @@ -41,21 +41,21 @@ trait LearningStepValidator { } def validateDescription(descriptions: Seq[Description], allowUnknownLanguage: Boolean): Seq[ValidationMessage] = { - descriptions.isEmpty match { - case true => List() - case false => - descriptions.flatMap(description => { - basicHtmlTextValidator - .validate("description", description.description) - .toList ::: - languageValidator - .validate("language", description.language, allowUnknownLanguage) - .toList - }) + if (descriptions.isEmpty) { + List() + } else { + descriptions.flatMap(description => { + basicHtmlTextValidator + .validate("description", description.description) + .toList ::: + languageValidator + .validate("language", description.language, allowUnknownLanguage) + .toList + }) } } - def validateEmbedUrl(embedUrls: Seq[EmbedUrl], allowUnknownLanguage: Boolean): Seq[ValidationMessage] = { + private def validateEmbedUrl(embedUrls: Seq[EmbedUrl], allowUnknownLanguage: Boolean): Seq[ValidationMessage] = { embedUrls.flatMap(embedUrl => { urlValidator.validate("embedUrl.url", embedUrl.url).toList ::: languageValidator @@ -67,17 +67,18 @@ trait LearningStepValidator { def validateLicense(licenseOpt: Option[String]): Option[ValidationMessage] = { licenseOpt match { case None => None - case Some(license) => { + case Some(license) => noHtmlTextValidator.validate("license", license) - } } } - def validateThatDescriptionOrEmbedUrlOrBothIsDefined(newLearningStep: LearningStep): Option[ValidationMessage] = { - newLearningStep.description.isEmpty && newLearningStep.embedUrl.isEmpty match { - case true => - Some(ValidationMessage("description|embedUrl", MISSING_DESCRIPTION_OR_EMBED_URL)) - case false => None + private def validateThatDescriptionOrEmbedUrlOrBothIsDefined( + newLearningStep: LearningStep + ): Option[ValidationMessage] = { + if (newLearningStep.description.isEmpty && newLearningStep.embedUrl.isEmpty) { + Some(ValidationMessage("description|embedUrl", MISSING_DESCRIPTION_OR_EMBED_URL)) + } else { + None } } } diff --git a/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/StatusValidator.scala b/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/StatusValidator.scala index c1c676bf12..c4fe9393bc 100644 --- a/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/StatusValidator.scala +++ b/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/StatusValidator.scala @@ -14,18 +14,18 @@ import no.ndla.common.model.domain.learningpath.{LearningPathStatus, StepStatus} class StatusValidator { def validateLearningStepStatus(status: String): Option[ValidationMessage] = { - StepStatus.valueOf(status).isEmpty match { - case true => - Some(ValidationMessage("status", s"'$status' is not a valid status.")) - case false => None + if (StepStatus.valueOf(status).isEmpty) { + Some(ValidationMessage("status", s"'$status' is not a valid status.")) + } else { + None } } def validateLearningPathStatus(status: String): Option[ValidationMessage] = { - LearningPathStatus.valueOf(status).isEmpty match { - case true => - Some(ValidationMessage("status", s"'$status' is not a valid publishingstatus.")) - case false => None + if (LearningPathStatus.valueOf(status).isEmpty) { + Some(ValidationMessage("status", s"'$status' is not a valid publishingstatus.")) + } else { + None } } } diff --git a/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/TextValidator.scala b/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/TextValidator.scala index 0848c30dcd..0c4f4dd060 100644 --- a/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/TextValidator.scala +++ b/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/TextValidator.scala @@ -17,40 +17,40 @@ trait TextValidator { this: Props => class TextValidator(allowHtml: Boolean) { - import props._ + import props.* val IllegalContentInBasicText: String = s"The content contains illegal html-characters. Allowed characters are ${BasicHtmlTags.mkString(", ")}" val IllegalContentInPlainText = "The content contains illegal html-characters. No HTML is allowed." - val FieldEmpty = "Required field is empty." + private val FieldEmpty = "Required field is empty." def validate(fieldPath: String, text: String): Option[ValidationMessage] = { - allowHtml match { - case true => validateOnlyBasicHtmlTags(fieldPath, text) - case false => validateNoHtmlTags(fieldPath, text) + if (allowHtml) { + validateOnlyBasicHtmlTags(fieldPath, text) + } else { + validateNoHtmlTags(fieldPath, text) } } private def validateOnlyBasicHtmlTags(fieldPath: String, text: String): Option[ValidationMessage] = { - text.isEmpty match { - case true => Some(ValidationMessage(fieldPath, FieldEmpty)) - case false => { - Jsoup.isValid(text, new Safelist().addTags(BasicHtmlTags: _*)) match { - case true => None - case false => - Some(ValidationMessage(fieldPath, IllegalContentInBasicText)) - } + if (text.isEmpty) { + Some(ValidationMessage(fieldPath, FieldEmpty)) + } else { + if (Jsoup.isValid(text, new Safelist().addTags(BasicHtmlTags*))) { + None + } else { + Some(ValidationMessage(fieldPath, IllegalContentInBasicText)) } } } private def validateNoHtmlTags(fieldPath: String, text: String): Option[ValidationMessage] = { - Jsoup.isValid(text, Safelist.none()) match { - case true => None - case false => - Some(ValidationMessage(fieldPath, IllegalContentInPlainText)) + if (Jsoup.isValid(text, Safelist.none())) { + None + } else { + Some(ValidationMessage(fieldPath, IllegalContentInPlainText)) } } } diff --git a/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/TitleValidator.scala b/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/TitleValidator.scala index 37ccfa39cb..4d31cb15a8 100644 --- a/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/TitleValidator.scala +++ b/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/TitleValidator.scala @@ -12,11 +12,11 @@ import no.ndla.common.errors.ValidationMessage import no.ndla.common.model.domain.Title trait TitleValidator { - this: LanguageValidator with TextValidator => + this: LanguageValidator & TextValidator => val titleValidator: TitleValidator class TitleValidator(titleRequired: Boolean = true) { - val MISSING_TITLE = "At least one title is required." + private val MISSING_TITLE = "At least one title is required." val noHtmlTextValidator = new TextValidator(allowHtml = false) diff --git a/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/UrlValidator.scala b/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/UrlValidator.scala index 9fda5c3daf..4f1d37d003 100644 --- a/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/UrlValidator.scala +++ b/learningpath-api/src/main/scala/no/ndla/learningpathapi/validation/UrlValidator.scala @@ -8,14 +8,14 @@ package no.ndla.learningpathapi.validation -import io.lemonlabs.uri.typesafe.dsl._ +import io.lemonlabs.uri.typesafe.dsl.* import no.ndla.common.errors.ValidationMessage import no.ndla.learningpathapi.Props trait UrlValidator { - this: Props with TextValidator => + this: Props & TextValidator => - class UrlValidator() { + class UrlValidator { val noHtmlTextValidator = new TextValidator(allowHtml = false) def validate(fieldPath: String, url: String): Seq[ValidationMessage] = { diff --git a/learningpath-api/src/test/scala/no/ndla/learningpathapi/TestData.scala b/learningpath-api/src/test/scala/no/ndla/learningpathapi/TestData.scala index a5fabea4a5..0fa66c9d1b 100644 --- a/learningpath-api/src/test/scala/no/ndla/learningpathapi/TestData.scala +++ b/learningpath-api/src/test/scala/no/ndla/learningpathapi/TestData.scala @@ -80,6 +80,7 @@ object TestData { LearningPathStatus.PUBLISHED, LearningPathVerificationStatus.CREATED_BY_NDLA, today, + today, List(common.Tag(List("tag"), DefaultLanguage)), "me", LearningpathCopyright(CC_BY.toString, List.empty), diff --git a/learningpath-api/src/test/scala/no/ndla/learningpathapi/controller/InternControllerTest.scala b/learningpath-api/src/test/scala/no/ndla/learningpathapi/controller/InternControllerTest.scala index 721686813f..85bfa76eb6 100644 --- a/learningpath-api/src/test/scala/no/ndla/learningpathapi/controller/InternControllerTest.scala +++ b/learningpath-api/src/test/scala/no/ndla/learningpathapi/controller/InternControllerTest.scala @@ -34,9 +34,9 @@ class InternControllerTest extends UnitSuite with TestEnvironment with TapirCont test("That DELETE /index removes all indexes") { reset(searchIndexService) when(searchIndexService.findAllIndexes(any[String])).thenReturn(Success(List("index1", "index2", "index3"))) - doReturn(Success(""), Nil: _*).when(searchIndexService).deleteIndexWithName(Some("index1")) - doReturn(Success(""), Nil: _*).when(searchIndexService).deleteIndexWithName(Some("index2")) - doReturn(Success(""), Nil: _*).when(searchIndexService).deleteIndexWithName(Some("index3")) + doReturn(Success(""), Nil*).when(searchIndexService).deleteIndexWithName(Some("index1")) + doReturn(Success(""), Nil*).when(searchIndexService).deleteIndexWithName(Some("index2")) + doReturn(Success(""), Nil*).when(searchIndexService).deleteIndexWithName(Some("index3")) val res = simpleHttpClient.send( quickRequest.delete(uri"http://localhost:$serverPort/intern/index") @@ -52,12 +52,12 @@ class InternControllerTest extends UnitSuite with TestEnvironment with TapirCont test("That DELETE /index fails if at least one index isn't found, and no indexes are deleted") { reset(searchIndexService) - doReturn(Failure(new RuntimeException("Failed to find indexes")), Nil: _*) + doReturn(Failure(new RuntimeException("Failed to find indexes")), Nil*) .when(searchIndexService) .findAllIndexes(props.SearchIndex) - doReturn(Success(""), Nil: _*).when(searchIndexService).deleteIndexWithName(Some("index1")) - doReturn(Success(""), Nil: _*).when(searchIndexService).deleteIndexWithName(Some("index2")) - doReturn(Success(""), Nil: _*).when(searchIndexService).deleteIndexWithName(Some("index3")) + doReturn(Success(""), Nil*).when(searchIndexService).deleteIndexWithName(Some("index1")) + doReturn(Success(""), Nil*).when(searchIndexService).deleteIndexWithName(Some("index2")) + doReturn(Success(""), Nil*).when(searchIndexService).deleteIndexWithName(Some("index3")) val res = simpleHttpClient.send( quickRequest.delete(uri"http://localhost:$serverPort/intern/index") ) @@ -71,11 +71,11 @@ class InternControllerTest extends UnitSuite with TestEnvironment with TapirCont ) { reset(searchIndexService) when(searchIndexService.findAllIndexes(any[String])).thenReturn(Success(List("index1", "index2", "index3"))) - doReturn(Success(""), Nil: _*).when(searchIndexService).deleteIndexWithName(Some("index1")) - doReturn(Failure(new RuntimeException("No index with name 'index2' exists")), Nil: _*) + doReturn(Success(""), Nil*).when(searchIndexService).deleteIndexWithName(Some("index1")) + doReturn(Failure(new RuntimeException("No index with name 'index2' exists")), Nil*) .when(searchIndexService) .deleteIndexWithName(Some("index2")) - doReturn(Success(""), Nil: _*).when(searchIndexService).deleteIndexWithName(Some("index3")) + doReturn(Success(""), Nil*).when(searchIndexService).deleteIndexWithName(Some("index3")) val res = simpleHttpClient.send( quickRequest.delete(uri"http://localhost:$serverPort/intern/index") ) diff --git a/learningpath-api/src/test/scala/no/ndla/learningpathapi/controller/LearningpathControllerV2Test.scala b/learningpath-api/src/test/scala/no/ndla/learningpathapi/controller/LearningpathControllerV2Test.scala index 8032fb7ce3..d6cd4cb404 100644 --- a/learningpath-api/src/test/scala/no/ndla/learningpathapi/controller/LearningpathControllerV2Test.scala +++ b/learningpath-api/src/test/scala/no/ndla/learningpathapi/controller/LearningpathControllerV2Test.scala @@ -49,6 +49,7 @@ class LearningpathControllerV2Test extends UnitSuite with TestEnvironment with T None, "", NDLADate.now(), + NDLADate.now(), api.LearningPathTags(Seq(), "nb"), copyright, List("nb"), diff --git a/learningpath-api/src/test/scala/no/ndla/learningpathapi/controller/StatsControllerTest.scala b/learningpath-api/src/test/scala/no/ndla/learningpathapi/controller/StatsControllerTest.scala index 3f0fc1d4ef..a2ecfa91b6 100644 --- a/learningpath-api/src/test/scala/no/ndla/learningpathapi/controller/StatsControllerTest.scala +++ b/learningpath-api/src/test/scala/no/ndla/learningpathapi/controller/StatsControllerTest.scala @@ -9,7 +9,7 @@ package no.ndla.learningpathapi.controller import no.ndla.learningpathapi.{TestEnvironment, UnitSuite} import no.ndla.tapirtesting.TapirControllerTest -import sttp.client3.quick._ +import sttp.client3.quick.* class StatsControllerTest extends UnitSuite with TestEnvironment with TapirControllerTest { diff --git a/learningpath-api/src/test/scala/no/ndla/learningpathapi/repository/LearningPathRepositoryComponentIntegrationTest.scala b/learningpath-api/src/test/scala/no/ndla/learningpathapi/repository/LearningPathRepositoryComponentIntegrationTest.scala index 4c6334a311..7c15c4f585 100644 --- a/learningpath-api/src/test/scala/no/ndla/learningpathapi/repository/LearningPathRepositoryComponentIntegrationTest.scala +++ b/learningpath-api/src/test/scala/no/ndla/learningpathapi/repository/LearningPathRepositoryComponentIntegrationTest.scala @@ -58,6 +58,7 @@ class LearningPathRepositoryComponentIntegrationTest LearningPathStatus.PRIVATE, LearningPathVerificationStatus.EXTERNAL, NDLADate.now().withNano(0), + NDLADate.now().withNano(0), List(), "UNIT-TEST", copyright diff --git a/learningpath-api/src/test/scala/no/ndla/learningpathapi/service/ConverterServiceTest.scala b/learningpath-api/src/test/scala/no/ndla/learningpathapi/service/ConverterServiceTest.scala index 6498e84964..bef96ac75a 100644 --- a/learningpath-api/src/test/scala/no/ndla/learningpathapi/service/ConverterServiceTest.scala +++ b/learningpath-api/src/test/scala/no/ndla/learningpathapi/service/ConverterServiceTest.scala @@ -57,6 +57,7 @@ class ConverterServiceTest extends UnitSuite with UnitTestEnvironment { "PRIVATE", "CREATED_BY_NDLA", NDLADate.now(), + NDLADate.now(), api.LearningPathTags(List(), "nb"), copyright, true, @@ -96,6 +97,7 @@ class ConverterServiceTest extends UnitSuite with UnitTestEnvironment { LearningPathStatus.PRIVATE, LearningPathVerificationStatus.CREATED_BY_NDLA, randomDate, + randomDate, List(Tag(List("tag"), DefaultLanguage)), "me", LearningpathCopyright(CC_BY.toString, List.empty), @@ -122,6 +124,7 @@ class ConverterServiceTest extends UnitSuite with UnitTestEnvironment { LearningPathStatus.PRIVATE.toString, LearningPathVerificationStatus.CREATED_BY_NDLA.toString, randomDate, + randomDate, api.LearningPathTags(Seq("tag"), DefaultLanguage), api.Copyright( commonApi.License( @@ -172,6 +175,7 @@ class ConverterServiceTest extends UnitSuite with UnitTestEnvironment { LearningPathStatus.PRIVATE.toString, LearningPathVerificationStatus.CREATED_BY_NDLA.toString, randomDate, + randomDate, api.LearningPathTags(Seq("tag"), DefaultLanguage), api.Copyright( commonApi.License( @@ -208,6 +212,7 @@ class ConverterServiceTest extends UnitSuite with UnitTestEnvironment { Some(60), LearningPathStatus.PRIVATE.toString, randomDate, + randomDate, api.LearningPathTags(Seq("tag"), DefaultLanguage), api.Copyright( commonApi.License( @@ -414,7 +419,7 @@ class ConverterServiceTest extends UnitSuite with UnitTestEnvironment { assertResult("Validation Error") { intercept[ValidationException] { service.asEmbedUrlV2(api.EmbedUrlV2("http://test.no/2/oembed/", "test"), "nb") - }.getMessage() + }.getMessage } } diff --git a/learningpath-api/src/test/scala/no/ndla/learningpathapi/service/ReadServiceTest.scala b/learningpath-api/src/test/scala/no/ndla/learningpathapi/service/ReadServiceTest.scala index 44b6578048..3fb3a84ed6 100644 --- a/learningpath-api/src/test/scala/no/ndla/learningpathapi/service/ReadServiceTest.scala +++ b/learningpath-api/src/test/scala/no/ndla/learningpathapi/service/ReadServiceTest.scala @@ -53,6 +53,7 @@ class ReadServiceTest extends UnitSuite with UnitTestEnvironment { LearningPathStatus.PUBLISHED, LearningPathVerificationStatus.EXTERNAL, NDLADate.now(), + NDLADate.now(), List(), PUBLISHED_OWNER.id, copyright @@ -70,6 +71,7 @@ class ReadServiceTest extends UnitSuite with UnitTestEnvironment { LearningPathStatus.PRIVATE, LearningPathVerificationStatus.EXTERNAL, NDLADate.now(), + NDLADate.now(), List(), PRIVATE_OWNER.id, copyright diff --git a/learningpath-api/src/test/scala/no/ndla/learningpathapi/service/UpdateServiceTest.scala b/learningpath-api/src/test/scala/no/ndla/learningpathapi/service/UpdateServiceTest.scala index 8e6cb5de44..a76a191b00 100644 --- a/learningpath-api/src/test/scala/no/ndla/learningpathapi/service/UpdateServiceTest.scala +++ b/learningpath-api/src/test/scala/no/ndla/learningpathapi/service/UpdateServiceTest.scala @@ -167,6 +167,7 @@ class UpdateServiceTest extends UnitSuite with UnitTestEnvironment { LearningPathStatus.PUBLISHED, LearningPathVerificationStatus.EXTERNAL, NDLADate.now(), + NDLADate.now(), List(), PUBLISHED_OWNER.id, copyright, @@ -185,6 +186,7 @@ class UpdateServiceTest extends UnitSuite with UnitTestEnvironment { learningpath.LearningPathStatus.PUBLISHED, LearningPathVerificationStatus.EXTERNAL, NDLADate.now(), + NDLADate.now(), List(), PUBLISHED_OWNER.id, copyright, @@ -203,6 +205,7 @@ class UpdateServiceTest extends UnitSuite with UnitTestEnvironment { learningpath.LearningPathStatus.PRIVATE, LearningPathVerificationStatus.EXTERNAL, NDLADate.now(), + NDLADate.now(), List(), PRIVATE_OWNER.id, copyright, @@ -221,6 +224,7 @@ class UpdateServiceTest extends UnitSuite with UnitTestEnvironment { learningpath.LearningPathStatus.PRIVATE, LearningPathVerificationStatus.EXTERNAL, NDLADate.now(), + NDLADate.now(), List(), PRIVATE_OWNER.id, copyright, @@ -239,6 +243,7 @@ class UpdateServiceTest extends UnitSuite with UnitTestEnvironment { learningpath.LearningPathStatus.DELETED, LearningPathVerificationStatus.EXTERNAL, NDLADate.now(), + NDLADate.now(), List(), PRIVATE_OWNER.id, copyright, diff --git a/learningpath-api/src/test/scala/no/ndla/learningpathapi/service/search/SearchServiceTest.scala b/learningpath-api/src/test/scala/no/ndla/learningpathapi/service/search/SearchServiceTest.scala index 492ae33f07..0ebba9dec6 100644 --- a/learningpath-api/src/test/scala/no/ndla/learningpathapi/service/search/SearchServiceTest.scala +++ b/learningpath-api/src/test/scala/no/ndla/learningpathapi/service/search/SearchServiceTest.scala @@ -59,6 +59,7 @@ class SearchServiceTest duration = Some(0), status = LearningPathStatus.PUBLISHED, verificationStatus = LearningPathVerificationStatus.EXTERNAL, + created = clock.now(), lastUpdated = clock.now(), tags = List(), owner = "owner", @@ -91,7 +92,7 @@ class SearchServiceTest if (elasticSearchContainer.isSuccess) { searchIndexService.createIndexAndAlias().get - doReturn(commonApi.Author("Forfatter", "En eier"), Nil: _*).when(converterService).asAuthor(any[NdlaUserName]) + doReturn(commonApi.Author("Forfatter", "En eier"), Nil*).when(converterService).asAuthor(any[NdlaUserName]) val today = NDLADate.now() val yesterday = NDLADate.now().minusDays(1) @@ -119,6 +120,7 @@ class SearchServiceTest title = List(Title("Pingvinen er en kjeltring", "nb")), description = List(Description("Dette handler om fugler", "nb")), duration = Some(1), + created = yesterday, lastUpdated = yesterday, tags = List(Tag(Seq("superhelt", "kanikkefly"), "nb")), learningsteps = Some(List(activeStep)) @@ -129,6 +131,7 @@ class SearchServiceTest title = List(Title("Batman er en tøff og morsom helt", "nb"), Title("Batman is a tough guy", "en")), description = List(Description("Dette handler om flaggermus, som kan ligne litt på en fugl", "nb")), duration = Some(2), + created = yesterday, lastUpdated = today, tags = List(Tag(Seq("superhelt", "kanfly"), "nb")), learningsteps = Some(List(activeStep, deletedStep)) @@ -139,6 +142,7 @@ class SearchServiceTest title = List(Title("Donald er en tøff, rar og morsom and", "nb"), Title("Donald is a weird duck", "en")), description = List(Description("Dette handler om en and, som også minner om både flaggermus og fugler.", "nb")), duration = Some(3), + created = yesterday, lastUpdated = tomorrow, tags = List(Tag(Seq("disney", "kanfly"), "nb")), learningsteps = Some(List(deletedStep)), @@ -150,6 +154,7 @@ class SearchServiceTest title = List(Title("Unrelated", "en"), Title("Urelatert", "nb")), description = List(Description("This is unrelated", "en"), Description("Dette er en urelatert", "nb")), duration = Some(4), + created = yesterday, lastUpdated = tomorrowp1, tags = List() ) @@ -159,6 +164,7 @@ class SearchServiceTest title = List(Title("Englando", "en"), Title("Djinba", "djb")), description = List(Description("This is a englando learningpath", "en"), Description("This is djinba", "djb")), duration = Some(5), + created = yesterday, lastUpdated = tomorrowp2, tags = List() ) @@ -168,6 +174,7 @@ class SearchServiceTest title = List(Title("Brumle", "nb")), description = List(Description("Dette er brumle", "nb")), duration = Some(5), + created = yesterday, lastUpdated = tomorrowp2, tags = List(), status = LearningPathStatus.UNLISTED diff --git a/learningpath-api/src/test/scala/no/ndla/learningpathapi/validation/LearningPathValidatorTest.scala b/learningpath-api/src/test/scala/no/ndla/learningpathapi/validation/LearningPathValidatorTest.scala index a8793fc1b3..f0469e9252 100644 --- a/learningpath-api/src/test/scala/no/ndla/learningpathapi/validation/LearningPathValidatorTest.scala +++ b/learningpath-api/src/test/scala/no/ndla/learningpathapi/validation/LearningPathValidatorTest.scala @@ -34,7 +34,7 @@ class LearningPathValidatorTest extends UnitSuite with TestEnvironment { } val trump: Author = Author("author", "Donald Drumpf") - val license = PublicDomain.toString + val license: String = PublicDomain.toString val copyright: LearningpathCopyright = LearningpathCopyright(license, List(trump)) val ValidLearningPath: LearningPath = LearningPath( @@ -49,6 +49,7 @@ class LearningPathValidatorTest extends UnitSuite with TestEnvironment { isBasedOn = None, status = LearningPathStatus.PRIVATE, verificationStatus = LearningPathVerificationStatus.EXTERNAL, + created = clock.now(), lastUpdated = clock.now(), owner = "", copyright = copyright From 27760d4ad79822cd370da16bbf75d21651d11ea7 Mon Sep 17 00:00:00 2001 From: Gunnar Velle Date: Tue, 19 Nov 2024 12:21:20 +0100 Subject: [PATCH 2/2] Fix test in search-api --- search-api/src/test/scala/no/ndla/searchapi/TestData.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/search-api/src/test/scala/no/ndla/searchapi/TestData.scala b/search-api/src/test/scala/no/ndla/searchapi/TestData.scala index 12831629a8..774642ab3e 100644 --- a/search-api/src/test/scala/no/ndla/searchapi/TestData.scala +++ b/search-api/src/test/scala/no/ndla/searchapi/TestData.scala @@ -933,6 +933,7 @@ object TestData { duration = Some(0), status = LearningPathStatus.PUBLISHED, verificationStatus = LearningPathVerificationStatus.EXTERNAL, + created = today, lastUpdated = today, tags = List(), owner = "owner",