From 477d50e5ee00065f5ecd7c9f143a0fb42bb31b47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinb=C3=B6lting?= Date: Mon, 18 Mar 2024 11:04:42 +0100 Subject: [PATCH] fix: Add upgrade plugin which ensures all projects have valid RestrictedView settings persisted --- project/LocalSettings.scala | 2 +- .../resources/knora-ontologies/knora-base.ttl | 2 +- .../main/scala/org/knora/webapi/package.scala | 2 +- .../upgrade/RepositoryUpdatePlan.scala | 3 +- .../upgrade/plugins/UpgradePluginPR3112.scala | 80 ++++++++++++ .../plugins/UpgradePluginPR3111Spec.scala | 2 + .../plugins/UpgradePluginPR3112Spec.scala | 114 ++++++++++++++++++ 7 files changed, 200 insertions(+), 5 deletions(-) create mode 100644 webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR3112.scala create mode 100644 webapi/src/test/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR3112Spec.scala diff --git a/project/LocalSettings.scala b/project/LocalSettings.scala index de132b5689..c7e174fec5 100644 --- a/project/LocalSettings.scala +++ b/project/LocalSettings.scala @@ -8,6 +8,6 @@ import Keys.* object LocalSettings { val localScalacOptions: Seq[SettingsDefinition] = Seq( - // scalacOptions -= "-Xfatal-warnings" + scalacOptions -= "-Xfatal-warnings", ) } diff --git a/webapi/src/main/resources/knora-ontologies/knora-base.ttl b/webapi/src/main/resources/knora-ontologies/knora-base.ttl index 910c3492c6..2f44bac9c1 100644 --- a/webapi/src/main/resources/knora-ontologies/knora-base.ttl +++ b/webapi/src/main/resources/knora-ontologies/knora-base.ttl @@ -19,7 +19,7 @@ rdf:type owl:Ontology ; rdfs:label "The Knora base ontology"@en ; :attachedToProject knora-admin:SystemProject ; - :ontologyVersion "knora-base v30" . + :ontologyVersion "knora-base v31" . ################################################################# diff --git a/webapi/src/main/scala/org/knora/webapi/package.scala b/webapi/src/main/scala/org/knora/webapi/package.scala index 3c51e25537..7d3ef66965 100644 --- a/webapi/src/main/scala/org/knora/webapi/package.scala +++ b/webapi/src/main/scala/org/knora/webapi/package.scala @@ -11,7 +11,7 @@ package object webapi { * The version of `knora-base` and of the other built-in ontologies that this version of Knora requires. * Must be the same as the object of `knora-base:ontologyVersion` in the `knora-base` ontology being used. */ - val KnoraBaseVersion: String = "knora-base v30" + val KnoraBaseVersion: String = "knora-base v31" /** * `IRI` is a synonym for `String`, used to improve code readability. diff --git a/webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/RepositoryUpdatePlan.scala b/webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/RepositoryUpdatePlan.scala index 58e5669af4..33f265c53d 100644 --- a/webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/RepositoryUpdatePlan.scala +++ b/webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/RepositoryUpdatePlan.scala @@ -8,7 +8,6 @@ package org.knora.webapi.store.triplestore.upgrade import com.typesafe.scalalogging.Logger import org.knora.webapi.messages.store.triplestoremessages.RdfDataObject -import org.knora.webapi.store.triplestore.upgrade.plugins.UpgradePluginPR3110 import org.knora.webapi.store.triplestore.upgrade.plugins.* /** @@ -47,7 +46,7 @@ object RepositoryUpdatePlan { PluginForKnoraBaseVersion(versionNumber = 28, plugin = new MigrateOnlyBuiltInGraphs), // PR 3038 PluginForKnoraBaseVersion(versionNumber = 29, plugin = new UpgradePluginPR3110()), PluginForKnoraBaseVersion(versionNumber = 30, plugin = new UpgradePluginPR3111()), - // KEEP IT ON THE BOTTOM + PluginForKnoraBaseVersion(versionNumber = 31, plugin = new UpgradePluginPR3112()), ) /** diff --git a/webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR3112.scala b/webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR3112.scala new file mode 100644 index 0000000000..28c7467d41 --- /dev/null +++ b/webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR3112.scala @@ -0,0 +1,80 @@ +/* + * Copyright © 2021 - 2024 Swiss National Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.knora.webapi.store.triplestore.upgrade.plugins + +import org.eclipse.rdf4j.sparqlbuilder.core.SparqlBuilder.`var` as variable +import org.eclipse.rdf4j.sparqlbuilder.core.query.ModifyQuery +import org.eclipse.rdf4j.sparqlbuilder.core.query.* +import org.eclipse.rdf4j.sparqlbuilder.rdf.Rdf + +import org.knora.webapi.slice.admin.AdminConstants +import org.knora.webapi.slice.admin.domain.model.RestrictedView.Size +import org.knora.webapi.slice.admin.repo.rdf.Vocabulary +import org.knora.webapi.store.triplestore.upgrade.GraphsForMigration +import org.knora.webapi.store.triplestore.upgrade.MigrateSpecificGraphs + +/** + * Certain restricted views have a watermark that is not a boolean. This plugin removes the invalid watermark triples. + */ +class UpgradePluginPR3112 extends AbstractSparqlUpdatePlugin { + + override def graphsForMigration: GraphsForMigration = + MigrateSpecificGraphs.from(AdminConstants.adminDataNamedGraph) + + private val removeWatermarkIfBothSet: ModifyQuery = { + val (project, prevWatermark, prevSize) = (variable("project"), variable("prevWatermark"), variable("prevSize")) + Queries + .MODIFY() + .prefix(Vocabulary.KnoraAdmin.NS) + .delete(project.has(Vocabulary.KnoraAdmin.projectRestrictedViewWatermark, prevWatermark)) + .from(Vocabulary.NamedGraphs.knoraAdminIri) + .where( + project + .isA(Vocabulary.KnoraAdmin.KnoraProject) + .andHas(Vocabulary.KnoraAdmin.projectRestrictedViewWatermark, prevWatermark) + .andHas(Vocabulary.KnoraAdmin.projectRestrictedViewSize, prevSize) + .from(Vocabulary.NamedGraphs.knoraAdminIri), + ) + } + + private val addDefaultRestrictedViewSizeToProjectsWithout = { + val project = variable("project") + Queries + .MODIFY() + .prefix(Vocabulary.KnoraAdmin.NS) + .`with`(Vocabulary.NamedGraphs.knoraAdminIri) + .insert(project.has(Vocabulary.KnoraAdmin.projectRestrictedViewSize, Rdf.literalOf(Size.default.value))) + .where( + project + .isA(Vocabulary.KnoraAdmin.KnoraProject) + .filterNotExists(project.has(Vocabulary.KnoraAdmin.projectRestrictedViewSize, variable("size"))) + .filterNotExists(project.has(Vocabulary.KnoraAdmin.projectRestrictedViewWatermark, variable("watermark"))) + .from(Vocabulary.NamedGraphs.knoraAdminIri), + ) + } + + private val replaceWatermarkFalseWithDefaultRestrictedViewSize = { + val project = variable("project") + Queries + .MODIFY() + .prefix(Vocabulary.KnoraAdmin.NS) + .`with`(Vocabulary.NamedGraphs.knoraAdminIri) + .insert(project.has(Vocabulary.KnoraAdmin.projectRestrictedViewSize, Rdf.literalOf(Size.default.value))) + .where( + project + .isA(Vocabulary.KnoraAdmin.KnoraProject) + .andHas(Vocabulary.KnoraAdmin.projectRestrictedViewWatermark, Rdf.literalOf(false)) + .filterNotExists(project.has(Vocabulary.KnoraAdmin.projectRestrictedViewSize, variable("size"))) + .from(Vocabulary.NamedGraphs.knoraAdminIri), + ) + } + + override def getQueries: List[ModifyQuery] = List( + removeWatermarkIfBothSet, + addDefaultRestrictedViewSizeToProjectsWithout, + replaceWatermarkFalseWithDefaultRestrictedViewSize, + ) +} diff --git a/webapi/src/test/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR3111Spec.scala b/webapi/src/test/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR3111Spec.scala index ae5daa0e41..685d231a4f 100644 --- a/webapi/src/test/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR3111Spec.scala +++ b/webapi/src/test/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR3111Spec.scala @@ -34,7 +34,9 @@ object UpgradePluginPR3111Spec extends ZIOSpecDefault with UpgradePluginTestOps val model = createJenaModelFromTriG(triG) // when + printModel(model) plugin.transform(model) + printModel(model) // then val doProjectsStillExist = diff --git a/webapi/src/test/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR3112Spec.scala b/webapi/src/test/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR3112Spec.scala new file mode 100644 index 0000000000..d4c74b4969 --- /dev/null +++ b/webapi/src/test/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR3112Spec.scala @@ -0,0 +1,114 @@ +package org.knora.webapi.store.triplestore.upgrade.plugins + +import zio.test.Spec +import zio.test.ZIOSpecDefault +import zio.test.assertTrue + +object UpgradePluginPR3112Spec extends ZIOSpecDefault with UpgradePluginTestOps { + + val spec: Spec[Any, Nothing] = suite("UpgradePluginPR3111")( + test( + "given project with invalid RestrictedView settings, " + + "when the plugin is run, " + + "then the size is retained or a default size is set.", + ) { + // given + val plugin = new UpgradePluginPR3112() + val triG = + s""" + |@prefix knora-admin: . + |@prefix xsd: . + | + |GRAPH { + | a knora-admin:knoraProject ; + | knora-admin:projectRestrictedViewWatermark true ; + | knora-admin:projectRestrictedViewSize "!512,512"^^xsd:string . + | + | a knora-admin:knoraProject . + | + | a knora-admin:knoraProject ; + | knora-admin:projectRestrictedViewWatermark false. + | + | a knora-admin:knoraProject ; + | knora-admin:projectRestrictedViewWatermark true. + | + | a knora-admin:knoraProject ; + | knora-admin:projectRestrictedViewSize "!555,555"^^xsd:string . + |} + |""".stripMargin + val model = createJenaModelFromTriG(triG) + + // when + printModel(model) + plugin.transform(model) + printModel(model) + + // then + val project0001HasOnlyViewSize = + """ + |PREFIX knora-admin: + |PREFIX xsd: + | + |ASK { + | GRAPH { + | a knora-admin:knoraProject ; + | knora-admin:projectRestrictedViewSize "!512,512"^^xsd:string . + | FILTER NOT EXISTS { knora-admin:projectRestrictedViewWatermark ?any . } + | } + |} + |""".stripMargin + + val project0002HasDefaultRestrictedViewSize = + """ + |PREFIX knora-admin: + |PREFIX xsd: + | + |ASK { + | GRAPH { + | a knora-admin:knoraProject ; + | knora-admin:projectRestrictedViewSize "!128,128"^^xsd:string . + | FILTER NOT EXISTS { knora-admin:projectRestrictedViewWatermark ?any . } + | } + |} + |""".stripMargin + + val watermarkFalseIsReplacedByDefaultRestrictedViewSize = + """ + |PREFIX knora-admin: + |PREFIX xsd: + | + |ASK { + | GRAPH { + | a knora-admin:knoraProject ; + | knora-admin:projectRestrictedViewSize "!128,128"^^xsd:string . + | FILTER NOT EXISTS { knora-admin:projectRestrictedViewWatermark ?any . } + | } + |} + |""".stripMargin + + val validProjectsRemainUntouched = + """ + |PREFIX knora-admin: + |PREFIX xsd: + | + |ASK { + | GRAPH { + | + | a knora-admin:knoraProject ; + | knora-admin:projectRestrictedViewWatermark true. + | + | a knora-admin:knoraProject ; + | knora-admin:projectRestrictedViewSize "!555,555"^^xsd:string . + | } + |} + |""".stripMargin + + assertTrue( + queryAsk(project0001HasOnlyViewSize, model), + queryAsk(project0002HasDefaultRestrictedViewSize, model), + queryAsk(watermarkFalseIsReplacedByDefaultRestrictedViewSize, model), + queryAsk(validProjectsRemainUntouched, model), + ) + }, + ) +}