From 300b83c3db2eb56003c948aa41617b630642579e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinb=C3=B6lting?= Date: Fri, 15 Nov 2024 12:45:54 +0100 Subject: [PATCH 01/18] add properties to knora base and admin ontologies --- .../knora-ontologies/knora-admin.ttl | 18 ++++++++++----- .../resources/knora-ontologies/knora-base.ttl | 23 +++++++++++++++++-- .../main/scala/org/knora/webapi/package.scala | 2 +- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/webapi/src/main/resources/knora-ontologies/knora-admin.ttl b/webapi/src/main/resources/knora-ontologies/knora-admin.ttl index 5e291d0e58..5368c6e3f7 100644 --- a/webapi/src/main/resources/knora-ontologies/knora-admin.ttl +++ b/webapi/src/main/resources/knora-ontologies/knora-admin.ttl @@ -377,12 +377,18 @@ [ rdf:type owl:Restriction ; owl:onProperty :projectRestrictedViewWatermark ; owl:maxCardinality "1"^^xsd:nonNegativeInteger ], - [ rdf:type owl:Restriction ; - owl:onProperty :status ; - owl:cardinality "1"^^xsd:nonNegativeInteger ], - [ rdf:type owl:Restriction ; - owl:onProperty :hasSelfJoinEnabled ; - owl:cardinality "1"^^xsd:nonNegativeInteger ] ; + [ rdf:type owl:Restriction ; + owl:onProperty :status ; + owl:cardinality "1"^^xsd:nonNegativeInteger ], + [ rdf:type owl:Restriction ; + owl:onProperty :hasSelfJoinEnabled ; + owl:cardinality "1"^^xsd:nonNegativeInteger ], + [ rdf:type owl:Restriction ; + owl:onProperty knora-base:hasCopyrightAttribution ; + owl:maxCardinality "1"^^xsd:nonNegativeInteger ], + [ rdf:type owl:Restriction ; + owl:onProperty knora-base:hasLicense ; + owl:maxCardinality "1"^^xsd:nonNegativeInteger ]; rdfs:comment "Represents a project that uses Knora."@en . diff --git a/webapi/src/main/resources/knora-ontologies/knora-base.ttl b/webapi/src/main/resources/knora-ontologies/knora-base.ttl index ac026f6bf5..3e976e6513 100644 --- a/webapi/src/main/resources/knora-ontologies/knora-base.ttl +++ b/webapi/src/main/resources/knora-ontologies/knora-base.ttl @@ -20,7 +20,7 @@ rdf:type owl:Ontology ; rdfs:label "The Knora base ontology"@en ; :attachedToProject knora-admin:SystemProject ; - :ontologyVersion "knora-base v41" . + :ontologyVersion "knora-base v42" . ################################################################# @@ -527,6 +527,19 @@ :subjectClassConstraint :Resource ; :objectClassConstraint :Value . +### http://www.knora.org/ontology/knora-base#hasCopyrightAttribution + +:hasCopyrightAttribution + rdf:type owl:DatatypeProperty ; + rdfs:comment "The copyright statement that gives credit to the original author."@en ; + :objectDatatypeConstraint xsd:string . + +### http://www.knora.org/ontology/knora-base#hasLicense + +:hasLicense + rdf:type owl:DatatypeProperty ; + rdfs:comment "Specifies the terms under which a work can be used. This statement may be a reference to a well-known license, such as Creative Commons (e.g. 'CC BY-SA') or a custom license."@en ; + :objectDatatypeConstraint xsd:string . ### http://www.knora.org/ontology/knora-base#isAnnotationOf @@ -1479,7 +1492,13 @@ owl:maxCardinality "1"^^xsd:nonNegativeInteger ], [ rdf:type owl:Restriction ; owl:onProperty :originalMimeType ; - owl:maxCardinality "1"^^xsd:nonNegativeInteger ] . + owl:maxCardinality "1"^^xsd:nonNegativeInteger ], + [ rdf:type owl:Restriction ; + owl:onProperty :hasCopyrightAttribution ; + owl:maxCardinality "1"^^xsd:nonNegativeInteger ], + [ rdf:type owl:Restriction ; + owl:onProperty :hasLicense ; + owl:maxCardinality "1"^^xsd:nonNegativeInteger ]. ### http://www.knora.org/ontology/knora-base#DecimalBase diff --git a/webapi/src/main/scala/org/knora/webapi/package.scala b/webapi/src/main/scala/org/knora/webapi/package.scala index ebe9fca3d4..0e40b8f2d7 100644 --- a/webapi/src/main/scala/org/knora/webapi/package.scala +++ b/webapi/src/main/scala/org/knora/webapi/package.scala @@ -14,7 +14,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: Int = 41 + val KnoraBaseVersion: Int = 42 val KnoraBaseVersionString: String = s"$versionPrefix$KnoraBaseVersion" /** From 102cac0441d6d65d4ca0426e8100b3d7e6273b3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinb=C3=B6lting?= Date: Fri, 15 Nov 2024 12:50:14 +0100 Subject: [PATCH 02/18] sort lines --- ...aseToApiV2ComplexTransformationRules.scala | 102 +++++++++--------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/KnoraBaseToApiV2ComplexTransformationRules.scala b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/KnoraBaseToApiV2ComplexTransformationRules.scala index 0801f609e1..4987cdf5ee 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/KnoraBaseToApiV2ComplexTransformationRules.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/KnoraBaseToApiV2ComplexTransformationRules.scala @@ -625,70 +625,70 @@ object KnoraBaseToApiV2ComplexTransformationRules extends OntologyTransformation * See also [[OntologyConstants.CorrespondingIris]]. */ override val externalPropertiesToAdd: Map[SmartIri, ReadPropertyInfoV2] = Set( - Label, - Result, - MayHaveMoreResults, - Error, - CanDo, - UserHasPermission, - VersionDate, ArkUrl, - VersionArkUrl, Author, - IsShared, - IsBuiltIn, - IsResourceClass, - IsStandoffClass, - IsValueClass, - IsEditable, - IsLinkProperty, - IsLinkValueProperty, - IsInherited, - NewModificationDate, - OntologyName, - MappingHasName, - ValueAsString, - HasIncomingLinkValue, - SubjectType, - ObjectType, - TextValueHasMarkup, - TextValueHasStandoff, - TextValueHasMaxStandoffStartIndex, - NextStandoffStartIndex, - StandoffTagHasStartParentIndex, - StandoffTagHasEndParentIndex, - TextValueHasLanguage, - TextValueAsXml, - TextValueAsHtml, - TextValueHasMapping, - DateValueHasStartYear, - DateValueHasEndYear, - DateValueHasStartMonth, + BooleanValueAsBoolean, + CanDo, + ColorValueAsColor, + DateValueHasCalendar, + DateValueHasEndDay, + DateValueHasEndEra, DateValueHasEndMonth, + DateValueHasEndYear, DateValueHasStartDay, - DateValueHasEndDay, DateValueHasStartEra, - DateValueHasEndEra, - DateValueHasCalendar, - IntervalValueHasStart, + DateValueHasStartMonth, + DateValueHasStartYear, + DecimalValueAsDecimal, + Error, + FileValueAsUrl, + FileValueHasFilename, + GeometryValueAsGeometry, + GeonameValueAsGeonameCode, + HasIncomingLinkValue, + IntValueAsInt, IntervalValueHasEnd, + IntervalValueHasStart, + IsBuiltIn, + IsEditable, + IsInherited, + IsLinkProperty, + IsLinkValueProperty, + IsResourceClass, + IsShared, + IsStandoffClass, + IsValueClass, + Label, LinkValueHasSource, LinkValueHasSourceIri, LinkValueHasTarget, LinkValueHasTargetIri, - IntValueAsInt, - DecimalValueAsDecimal, - BooleanValueAsBoolean, - GeometryValueAsGeometry, ListValueAsListNode, - ColorValueAsColor, - UriValueAsUri, - GeonameValueAsGeonameCode, - FileValueAsUrl, - FileValueHasFilename, + MappingHasName, + MayHaveMoreResults, + NewModificationDate, + NextStandoffStartIndex, + ObjectType, + OntologyName, + Result, + StandoffTagHasEndParentIndex, + StandoffTagHasStartParentIndex, StillImageFileValueHasDimX, StillImageFileValueHasDimY, - StillImageFileValueHasIIIFBaseUrl, StillImageFileValueHasExternalUrl, + StillImageFileValueHasIIIFBaseUrl, + SubjectType, + TextValueAsHtml, + TextValueAsXml, + TextValueHasLanguage, + TextValueHasMapping, + TextValueHasMarkup, + TextValueHasMaxStandoffStartIndex, + TextValueHasStandoff, + UriValueAsUri, + UserHasPermission, + ValueAsString, + VersionArkUrl, + VersionDate, ).map(_.build()).map(info => info.entityInfoContent.propertyIri -> info).toMap } From fbd579e5dd918ab4283f62f7a550db16c040ec88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinb=C3=B6lting?= Date: Fri, 15 Nov 2024 13:06:59 +0100 Subject: [PATCH 03/18] add to knora-api v2 --- .../webapi/messages/OntologyConstants.scala | 38 ++++++++++--------- ...aseToApiV2ComplexTransformationRules.scala | 12 ++++++ 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/OntologyConstants.scala b/webapi/src/main/scala/org/knora/webapi/messages/OntologyConstants.scala index 37fa73df89..ed6fc1db1e 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/OntologyConstants.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/OntologyConstants.scala @@ -263,6 +263,8 @@ object OntologyConstants { val HasTextFileValue: IRI = KnoraBasePrefixExpansion + "hasTextFileValue" val HasDocumentFileValue: IRI = KnoraBasePrefixExpansion + "hasDocumentFileValue" val HasArchiveFileValue: IRI = KnoraBasePrefixExpansion + "hasArchiveFileValue" + val HasCopyrightAttribution: IRI = KnoraBasePrefixExpansion + "hasCopyrightAttribution" + val HasLicense: IRI = KnoraBasePrefixExpansion + "hasLicense" val ResourceIcon: IRI = KnoraBasePrefixExpansion + "resourceIcon" @@ -617,23 +619,25 @@ object OntologyConstants { val ValueHasComment: IRI = KnoraApiV2PrefixExpansion + "valueHasComment" val NewValueVersionIri: IRI = KnoraApiV2PrefixExpansion + "newValueVersionIri" - val User: IRI = KnoraApiV2PrefixExpansion + "User" - val AttachedToUser: IRI = KnoraApiV2PrefixExpansion + "attachedToUser" - val AttachedToProject: IRI = KnoraApiV2PrefixExpansion + "attachedToProject" - val HasStandoffLinkTo: IRI = KnoraApiV2PrefixExpansion + "hasStandoffLinkTo" - val HasStandoffLinkToValue: IRI = KnoraApiV2PrefixExpansion + "hasStandoffLinkToValue" - val HasPermissions: IRI = KnoraApiV2PrefixExpansion + "hasPermissions" - val UserHasPermission: String = KnoraApiV2PrefixExpansion + "userHasPermission" - val CreationDate: IRI = KnoraApiV2PrefixExpansion + "creationDate" - val LastModificationDate: IRI = KnoraApiV2PrefixExpansion + "lastModificationDate" - val VersionDate: IRI = KnoraApiV2PrefixExpansion + "versionDate" - val NewModificationDate: IRI = KnoraApiV2PrefixExpansion + "newModificationDate" - val IsDeleted: IRI = KnoraApiV2PrefixExpansion + "isDeleted" - val DeleteDate: IRI = KnoraApiV2PrefixExpansion + "deleteDate" - val DeleteComment: IRI = KnoraApiV2PrefixExpansion + "deleteComment" - val ArkUrl: IRI = KnoraApiV2PrefixExpansion + "arkUrl" - val VersionArkUrl: IRI = KnoraApiV2PrefixExpansion + "versionArkUrl" - val Author: IRI = KnoraApiV2PrefixExpansion + "author" + val User: IRI = KnoraApiV2PrefixExpansion + "User" + val AttachedToUser: IRI = KnoraApiV2PrefixExpansion + "attachedToUser" + val AttachedToProject: IRI = KnoraApiV2PrefixExpansion + "attachedToProject" + val HasStandoffLinkTo: IRI = KnoraApiV2PrefixExpansion + "hasStandoffLinkTo" + val HasStandoffLinkToValue: IRI = KnoraApiV2PrefixExpansion + "hasStandoffLinkToValue" + val HasPermissions: IRI = KnoraApiV2PrefixExpansion + "hasPermissions" + val HasCopyrightAttribution: IRI = KnoraApiV2PrefixExpansion + "hasCopyrightAttribution" + val HasLicense: IRI = KnoraApiV2PrefixExpansion + "hasLicense" + val UserHasPermission: String = KnoraApiV2PrefixExpansion + "userHasPermission" + val CreationDate: IRI = KnoraApiV2PrefixExpansion + "creationDate" + val LastModificationDate: IRI = KnoraApiV2PrefixExpansion + "lastModificationDate" + val VersionDate: IRI = KnoraApiV2PrefixExpansion + "versionDate" + val NewModificationDate: IRI = KnoraApiV2PrefixExpansion + "newModificationDate" + val IsDeleted: IRI = KnoraApiV2PrefixExpansion + "isDeleted" + val DeleteDate: IRI = KnoraApiV2PrefixExpansion + "deleteDate" + val DeleteComment: IRI = KnoraApiV2PrefixExpansion + "deleteComment" + val ArkUrl: IRI = KnoraApiV2PrefixExpansion + "arkUrl" + val VersionArkUrl: IRI = KnoraApiV2PrefixExpansion + "versionArkUrl" + val Author: IRI = KnoraApiV2PrefixExpansion + "author" val Resource: IRI = KnoraApiV2PrefixExpansion + "Resource" val DeletedResource: IRI = KnoraApiV2PrefixExpansion + "DeletedResource" diff --git a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/KnoraBaseToApiV2ComplexTransformationRules.scala b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/KnoraBaseToApiV2ComplexTransformationRules.scala index 4987cdf5ee..c28fa904fa 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/KnoraBaseToApiV2ComplexTransformationRules.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/KnoraBaseToApiV2ComplexTransformationRules.scala @@ -152,6 +152,16 @@ object KnoraBaseToApiV2ComplexTransformationRules extends OntologyTransformation .withIsResourceProp() .withIsLinkValueProp() + private val HasCopyrightAttribution = makeOwlDatatypeProperty(KA.HasCopyrightAttribution, XSD.STRING) + .withRdfLabelEn("has copyright attribution") + .withRdfCommentEn("The copyright statement that gives credit to the original author.") + + private val HasLicense = makeOwlDatatypeProperty(KA.HasLicense, XSD.STRING) + .withRdfLabelEn("has copyright attribution") + .withRdfCommentEn( + "Specifies the terms under which a work can be used. This statement may be a reference to a well-known license, such as Creative Commons (e.g. CC BY-SA) or a custom license.", + ) + private val ValueAsString = makeOwlDatatypeProperty(KA.ValueAsString, XSD.STRING) .withSubjectType(KA.Value) .withRdfCommentEn("A plain string representation of a value") @@ -645,7 +655,9 @@ object KnoraBaseToApiV2ComplexTransformationRules extends OntologyTransformation FileValueHasFilename, GeometryValueAsGeometry, GeonameValueAsGeonameCode, + HasCopyrightAttribution, HasIncomingLinkValue, + HasLicense, IntValueAsInt, IntervalValueHasEnd, IntervalValueHasStart, From d7e1ec18f9847ff70cea1cd06ae0b63d0cb47d96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinb=C3=B6lting?= Date: Fri, 15 Nov 2024 14:09:26 +0100 Subject: [PATCH 04/18] feat: Add copyright attribution and license to Project --- .../org/knora/webapi/ProjectEraseIT.scala | 2 ++ .../IntegrationTestAdminJsonProtocol.scala | 2 ++ .../admin/ProjectRestServiceSpec.scala | 15 ++++++++- .../sharedtestdata/SharedTestDataADM.scala | 20 ++++++++++++ .../webapi/slice/admin/api/Examples.scala | 2 ++ ...rojectsEndpointsRequestsAndResponses.scala | 2 ++ .../admin/api/model/ProjectsMessagesADM.scala | 2 ++ .../admin/domain/model/KnoraProject.scala | 2 ++ .../domain/service/KnoraProjectRepo.scala | 2 ++ .../domain/service/KnoraProjectService.scala | 2 ++ .../admin/domain/service/ProjectService.scala | 4 +++ .../repo/service/KnoraProjectRepoLive.scala | 32 +++++++++++++------ .../slice/common/repo/rdf/Vocabulary.scala | 2 ++ .../org/knora/webapi/TestDataFactory.scala | 2 ++ .../domain/service/ProjectServiceSpec.scala | 4 +++ .../service/KnoraProjectRepoLiveSpec.scala | 8 +++-- 16 files changed, 90 insertions(+), 13 deletions(-) diff --git a/integration/src/test/scala/org/knora/webapi/ProjectEraseIT.scala b/integration/src/test/scala/org/knora/webapi/ProjectEraseIT.scala index dfd542331a..aaee0bc1fd 100644 --- a/integration/src/test/scala/org/knora/webapi/ProjectEraseIT.scala +++ b/integration/src/test/scala/org/knora/webapi/ProjectEraseIT.scala @@ -83,6 +83,8 @@ object ProjectEraseIT extends E2EZSpec { None, KnoraProject.Status.Active, KnoraProject.SelfJoin.CanJoin, + None, + None, ), ), ).orDie diff --git a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala index fd36ebe999..c0efc1325f 100644 --- a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala +++ b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala @@ -189,6 +189,8 @@ object IntegrationTestAdminJsonProtocol extends TriplestoreJsonProtocol { "ontologies", "status", "selfjoin", + "copyrightAttribution", + "license", ), ) diff --git a/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala b/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala index 945c7126b4..b250f5f43d 100644 --- a/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala @@ -162,6 +162,8 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { logo = Some(Logo.unsafeFrom("/fu/bar/baz.jpg")), status = Status.Active, selfjoin = SelfJoin.CannotJoin, + copyrightAttribution = Some("2024, Example Project"), + license = Some("CC-BY-4.0"), ), SharedTestDataADM.rootUser, ), @@ -174,6 +176,8 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { received.project.description should be( Seq(StringLiteralV2.from(value = "project description", language = Some("en"))), ) + received.project.copyrightAttribution should be(Some("2024, Example Project")) + received.project.license should be(Some("CC-BY-4.0")) newProjectIri.set(received.project.id) @@ -257,6 +261,8 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { logo = Some(Logo.unsafeFrom("/fu/bar/baz.jpg")), status = Status.Active, selfjoin = SelfJoin.CannotJoin, + None, + None, ), SharedTestDataADM.rootUser, ), @@ -269,7 +275,8 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { received.project.description should be( Seq(StringLiteralV2.from(value = "project description", language = Some("en"))), ) - + received.project.copyrightAttribution should be(None) + received.project.license should be(None) } "CREATE a project that its info has special characters" in { @@ -292,6 +299,8 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { logo = Some(Logo.unsafeFrom("/fu/bar/baz.jpg")), status = Status.Active, selfjoin = SelfJoin.CannotJoin, + None, + None, ), SharedTestDataADM.rootUser, ), @@ -324,6 +333,8 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { logo = Some(Logo.unsafeFrom("/fu/bar/baz.jpg")), status = Status.Active, selfjoin = SelfJoin.CannotJoin, + copyrightAttribution = None, + license = None, ), SharedTestDataADM.rootUser, ), @@ -346,6 +357,8 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { logo = Some(Logo.unsafeFrom("/fu/bar/baz.jpg")), status = Status.Active, selfjoin = SelfJoin.CannotJoin, + copyrightAttribution = None, + license = None, ), SharedTestDataADM.rootUser, ), diff --git a/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala b/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala index f40a35403f..b4e11edcc4 100644 --- a/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala +++ b/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala @@ -169,6 +169,8 @@ object SharedTestDataADM { ), status = true, selfjoin = false, + copyrightAttribution = None, + license = None, ) /* represents the full ProjectADM of the default shared ontologies project */ @@ -183,6 +185,8 @@ object SharedTestDataADM { ontologies = Seq.empty[IRI], status = true, selfjoin = false, + copyrightAttribution = None, + license = None, ) /** @@ -295,6 +299,8 @@ object SharedTestDataADM { ontologies = Seq(SharedOntologyTestDataADM.IMAGES_ONTOLOGY_IRI), status = true, selfjoin = false, + copyrightAttribution = None, + license = None, ) /* represents the full ProjectADM of the images project in the external format */ @@ -309,6 +315,8 @@ object SharedTestDataADM { ontologies = Seq(SharedOntologyTestDataADM.IMAGES_ONTOLOGY_IRI_LocalHost), status = true, selfjoin = false, + copyrightAttribution = None, + license = None, ) /* represents the full GroupADM of the images ProjectAdmin group */ @@ -472,6 +480,8 @@ object SharedTestDataADM { ontologies = Seq(SharedOntologyTestDataADM.INCUNABULA_ONTOLOGY_IRI), status = true, selfjoin = false, + copyrightAttribution = None, + license = None, ) /* represents the ProjectADM of the incunabula project in the external format*/ @@ -507,6 +517,8 @@ object SharedTestDataADM { ontologies = Seq(SharedOntologyTestDataADM.INCUNABULA_ONTOLOGY_IRI_LocalHost), status = true, selfjoin = false, + copyrightAttribution = None, + license = None, ) /** @@ -619,6 +631,8 @@ object SharedTestDataADM { ontologies = Seq(SharedOntologyTestDataADM.ANYTHING_ONTOLOGY_IRI, SharedOntologyTestDataADM.SomethingOntologyIri), status = true, selfjoin = false, + copyrightAttribution = None, + license = None, ) def anythingProjectExternal: Project = Project( @@ -635,6 +649,8 @@ object SharedTestDataADM { ), status = true, selfjoin = false, + copyrightAttribution = None, + license = None, ) /* represents the full GroupADM of the Thing searcher group */ @@ -672,6 +688,8 @@ object SharedTestDataADM { ), status = true, selfjoin = false, + copyrightAttribution = None, + license = None, ) /* represents the user profile of 'superuser' as found in admin-data.ttl */ @@ -721,5 +739,7 @@ object SharedTestDataADM { ontologies = Seq("http://www.knora.org/ontology/0804/dokubib"), status = false, selfjoin = false, + copyrightAttribution = None, + license = None, ) } diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala index f669607840..45737e59cd 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala @@ -93,6 +93,8 @@ object Examples { status = true, ontologies = Seq.empty, selfjoin = false, + copyrightAttribution = Some("2024, Example Project"), + license = Some("CC-BY-4.0"), ) private val group = Group( diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsEndpointsRequestsAndResponses.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsEndpointsRequestsAndResponses.scala index 89b8bce775..ad9bca8bd8 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsEndpointsRequestsAndResponses.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsEndpointsRequestsAndResponses.scala @@ -27,6 +27,8 @@ object ProjectsEndpointsRequestsAndResponses { logo: Option[Logo] = None, status: Status, selfjoin: SelfJoin, + copyrightAttribution: Option[String], + license: Option[String], ) object ProjectCreateRequest { implicit val codec: JsonCodec[ProjectCreateRequest] = DeriveJsonCodec.gen[ProjectCreateRequest] diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala index dcb3b218f2..c2c4dcdfff 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala @@ -40,6 +40,8 @@ case class Project( ontologies: Seq[IRI], status: Boolean, selfjoin: Boolean, + copyrightAttribution: Option[String], + license: Option[String], ) extends Ordered[Project] { def projectIri: ProjectIri = ProjectIri.unsafeFrom(id) diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/model/KnoraProject.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/model/KnoraProject.scala index 42889abb00..e3771c5802 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/model/KnoraProject.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/model/KnoraProject.scala @@ -34,6 +34,8 @@ case class KnoraProject( status: Status, selfjoin: SelfJoin, restrictedView: RestrictedView, + copyrightAttribution: Option[String], + license: Option[String], ) extends EntityWithId[ProjectIri] object KnoraProject { diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraProjectRepo.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraProjectRepo.scala index 0e231dce98..2d82da3468 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraProjectRepo.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraProjectRepo.scala @@ -47,6 +47,8 @@ object KnoraProjectRepo { KnoraProject.Status.Active, KnoraProject.SelfJoin.CannotJoin, RestrictedView.default, + None, + None, ) val SystemProject: KnoraProject = makeBuiltIn( diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraProjectService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraProjectService.scala index 9c3837ecf5..9a05ca32c4 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraProjectService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraProjectService.scala @@ -52,6 +52,8 @@ final case class KnoraProjectService(knoraProjectRepo: KnoraProjectRepo, ontolog req.status, req.selfjoin, RestrictedView.default, + req.copyrightAttribution, + req.license, ) project <- knoraProjectRepo.save(project) } yield project diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala index 82a2db205a..e4af95ef9c 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala @@ -56,6 +56,8 @@ final case class ProjectService( ontologies, knoraProject.status.value, knoraProject.selfjoin.value, + knoraProject.copyrightAttribution, + knoraProject.license, ), ) @@ -73,6 +75,8 @@ final case class ProjectService( status = Status.from(project.status), selfjoin = SelfJoin.from(project.selfjoin), restrictedView, + project.copyrightAttribution, + project.license, ) def setProjectRestrictedView(project: Project, settings: RestrictedView): Task[RestrictedView] = diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/repo/service/KnoraProjectRepoLive.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/repo/service/KnoraProjectRepoLive.scala index 045cc486a4..8c9336c874 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/repo/service/KnoraProjectRepoLive.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/repo/service/KnoraProjectRepoLive.scala @@ -14,6 +14,8 @@ import zio.* import org.knora.webapi.messages.OntologyConstants.KnoraAdmin import org.knora.webapi.messages.OntologyConstants.KnoraAdmin.* +import org.knora.webapi.messages.OntologyConstants.KnoraBase.HasCopyrightAttribution +import org.knora.webapi.messages.OntologyConstants.KnoraBase.HasLicense import org.knora.webapi.slice.admin.domain.model.KnoraProject import org.knora.webapi.slice.admin.domain.model.KnoraProject.* import org.knora.webapi.slice.admin.domain.model.RestrictedView @@ -48,6 +50,8 @@ final case class KnoraProjectRepoLive( Vocabulary.KnoraAdmin.projectLongname, Vocabulary.KnoraAdmin.projectRestrictedViewSize, Vocabulary.KnoraAdmin.projectRestrictedViewWatermark, + Vocabulary.KnoraBase.hasCopyrightAttribution, + Vocabulary.KnoraBase.hasLicense, ), ) @@ -91,16 +95,18 @@ object KnoraProjectRepoLive { } yield size.orElse(watermark).getOrElse(RestrictedView.default) for { - iri <- resource.getSubjectIri - shortcode <- resource.getStringLiteralOrFail[Shortcode](ProjectShortcode) - shortname <- resource.getStringLiteralOrFail[Shortname](ProjectShortname) - longname <- resource.getStringLiteral[Longname](ProjectLongname) - description <- resource.getLangStringLiteralsOrFail[Description](ProjectDescription) - keywords <- resource.getStringLiterals[Keyword](ProjectKeyword) - logo <- resource.getStringLiteral[Logo](ProjectLogo) - status <- resource.getBooleanLiteralOrFail[Status](StatusProp) - selfjoin <- resource.getBooleanLiteralOrFail[SelfJoin](HasSelfJoinEnabled) - restrictedView <- getRestrictedView + iri <- resource.getSubjectIri + shortcode <- resource.getStringLiteralOrFail[Shortcode](ProjectShortcode) + shortname <- resource.getStringLiteralOrFail[Shortname](ProjectShortname) + longname <- resource.getStringLiteral[Longname](ProjectLongname) + description <- resource.getLangStringLiteralsOrFail[Description](ProjectDescription) + keywords <- resource.getStringLiterals[Keyword](ProjectKeyword) + logo <- resource.getStringLiteral[Logo](ProjectLogo) + status <- resource.getBooleanLiteralOrFail[Status](StatusProp) + selfjoin <- resource.getBooleanLiteralOrFail[SelfJoin](HasSelfJoinEnabled) + copyrightAttribution <- resource.getStringLiteral[String](HasCopyrightAttribution)(Right(_)) + license <- resource.getStringLiteral[String](HasLicense)(Right(_)) + restrictedView <- getRestrictedView } yield KnoraProject( id = ProjectIri.unsafeFrom(iri.value), shortcode = shortcode, @@ -112,6 +118,8 @@ object KnoraProjectRepoLive { status = status, selfjoin = selfjoin, restrictedView = restrictedView, + copyrightAttribution = copyrightAttribution, + license = license, ) } @@ -136,6 +144,10 @@ object KnoraProjectRepoLive { case RestrictedView.Watermark(watermark) => pattern.andHas(Vocabulary.KnoraAdmin.projectRestrictedViewWatermark, watermark) } + + project.copyrightAttribution.foreach(attr => pattern.andHas(Vocabulary.KnoraBase.hasCopyrightAttribution, attr)) + project.license.foreach(license => pattern.andHas(Vocabulary.KnoraBase.hasLicense, license)) + pattern } } diff --git a/webapi/src/main/scala/org/knora/webapi/slice/common/repo/rdf/Vocabulary.scala b/webapi/src/main/scala/org/knora/webapi/slice/common/repo/rdf/Vocabulary.scala index 0e6d2097bc..471e2710a0 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/common/repo/rdf/Vocabulary.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/common/repo/rdf/Vocabulary.scala @@ -108,6 +108,8 @@ object Vocabulary { val valueHasMapping: Iri = iri(kb + "valueHasMapping") val valueHasMaxStandoffStartIndex: Iri = iri(kb + "valueHasMaxStandoffStartIndex") val valueHasStandoff: Iri = iri(kb + "valueHasStandoff") + val hasCopyrightAttribution: Iri = iri(kb + "hasCopyrightAttribution") + val hasLicense: Iri = iri(kb + "hasLicense") val internalFilename: Iri = iri(kb + "internalFilename") val internalMimeType: Iri = iri(kb + "internalMimeType") diff --git a/webapi/src/test/scala/org/knora/webapi/TestDataFactory.scala b/webapi/src/test/scala/org/knora/webapi/TestDataFactory.scala index aa361d10d1..2a026dacfe 100644 --- a/webapi/src/test/scala/org/knora/webapi/TestDataFactory.scala +++ b/webapi/src/test/scala/org/knora/webapi/TestDataFactory.scala @@ -99,5 +99,7 @@ object TestDataFactory { Status.Active, SelfJoin.CannotJoin, RestrictedView.default, + Some("2024, Example Project"), + Some("CC-BY-4.0"), ) } diff --git a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala index 659c4433b8..e6f842faa6 100644 --- a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala @@ -35,6 +35,8 @@ object ProjectServiceSpec extends ZIOSpecDefault { ontologies = List.empty, status = true, selfjoin = true, + copyrightAttribution = None, + license = None, ) assertTrue( ProjectService.projectDataNamedGraphV2(p).value == s"http://www.knora.org/data/$shortcode/$shortname", @@ -55,6 +57,8 @@ object ProjectServiceSpec extends ZIOSpecDefault { status = Status.Active, selfjoin = SelfJoin.CanJoin, restrictedView = RestrictedView.default, + copyrightAttribution = None, + license = None, ) assertTrue( ProjectService diff --git a/webapi/src/test/scala/org/knora/webapi/slice/admin/repo/service/KnoraProjectRepoLiveSpec.scala b/webapi/src/test/scala/org/knora/webapi/slice/admin/repo/service/KnoraProjectRepoLiveSpec.scala index 0a4977a8fb..7168f0a2cd 100644 --- a/webapi/src/test/scala/org/knora/webapi/slice/admin/repo/service/KnoraProjectRepoLiveSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/slice/admin/repo/service/KnoraProjectRepoLiveSpec.scala @@ -45,6 +45,8 @@ object KnoraProjectRepoLiveSpec extends ZIOSpecDefault { Status.Active, SelfJoin.CannotJoin, RestrictedView.default, + Some("2024, Example Project"), + Some("Apache-2.0"), ) private val someProjectTrig = @@ -62,7 +64,9 @@ object KnoraProjectRepoLiveSpec extends ZIOSpecDefault { | knora-admin:projectLogo "logo.png" ; | knora-admin:status true ; | knora-admin:hasSelfJoinEnabled false ; - | knora-admin:projectRestrictedViewSize "!128,128" . + | knora-admin:projectRestrictedViewSize "!128,128" ; + | knora-base:hasCopyrightAttribution "2024, Example Project" ; + | knora-base:hasLicense "Apache-2.0" . |} |""".stripMargin @@ -106,7 +110,7 @@ object KnoraProjectRepoLiveSpec extends ZIOSpecDefault { for { _ <- TriplestoreServiceInMemory.setDataSetFromTriG(someProjectTrig) project <- KnoraProjectRepo(_.findById(ProjectIri.unsafeFrom("http://rdfh.ch/projects/1234"))) - } yield assertTrue(project.contains(someProject)) + } yield assertTrue(project == Some(someProject)) }, test("return None if project does not exist") { for { From 2f937305fe74f0827ccb64a85f3653b0d5625b17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinb=C3=B6lting?= Date: Fri, 15 Nov 2024 14:24:47 +0100 Subject: [PATCH 05/18] feat: Add copyright attribution and license to update Project --- ...rojectsEndpointsRequestsAndResponses.scala | 2 + .../domain/service/KnoraProjectService.scala | 2 + .../service/KnoraProjectServiceSpec.scala | 42 +++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/KnoraProjectServiceSpec.scala diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsEndpointsRequestsAndResponses.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsEndpointsRequestsAndResponses.scala index ad9bca8bd8..25623f24a9 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsEndpointsRequestsAndResponses.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsEndpointsRequestsAndResponses.scala @@ -42,6 +42,8 @@ object ProjectsEndpointsRequestsAndResponses { logo: Option[Logo] = None, status: Option[Status] = None, selfjoin: Option[SelfJoin] = None, + copyrightAttribution: Option[String] = None, + license: Option[String] = None, ) object ProjectUpdateRequest { implicit val codec: JsonCodec[ProjectUpdateRequest] = DeriveJsonCodec.gen[ProjectUpdateRequest] diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraProjectService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraProjectService.scala index 9a05ca32c4..3af6f33f00 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraProjectService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraProjectService.scala @@ -99,6 +99,8 @@ final case class KnoraProjectService(knoraProjectRepo: KnoraProjectRepo, ontolog logo = updateReq.logo.orElse(project.logo), status = updateReq.status.getOrElse(project.status), selfjoin = updateReq.selfjoin.getOrElse(project.selfjoin), + copyrightAttribution = updateReq.copyrightAttribution.orElse(project.copyrightAttribution), + license = updateReq.license.orElse(project.license), ), ) } yield updated diff --git a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/KnoraProjectServiceSpec.scala b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/KnoraProjectServiceSpec.scala new file mode 100644 index 0000000000..f8fb2cf9d4 --- /dev/null +++ b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/KnoraProjectServiceSpec.scala @@ -0,0 +1,42 @@ +/* + * 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.slice.admin.domain.service + +import zio.ZIO +import zio.test.* +import zio.test.Assertion.* + +import org.knora.webapi.TestDataFactory +import org.knora.webapi.messages.StringFormatter +import org.knora.webapi.slice.admin.api.model.ProjectsEndpointsRequestsAndResponses.ProjectUpdateRequest +import org.knora.webapi.slice.admin.domain.repo.KnoraProjectRepoInMemory +import org.knora.webapi.slice.ontology.repo.service.OntologyRepoInMemory +import org.knora.webapi.slice.resourceinfo.domain.IriConverter + +object KnoraProjectServiceSpec extends ZIOSpecDefault { + + private val projectService = ZIO.serviceWithZIO[KnoraProjectService] + private val repo = ZIO.serviceWithZIO[KnoraProjectRepoInMemory] + + private val updateSuite = suite("updateProject")( + test("should update the license and copyright attribution") { + val project = TestDataFactory.someProject + for { + _ <- repo(_.save(project)) + updateRequest = ProjectUpdateRequest(copyrightAttribution = Some("Foo"), license = Some("bar")) + actual <- projectService(_.updateProject(project, updateRequest)) + } yield assertTrue(actual == project.copy(copyrightAttribution = Some("Foo"), license = Some("bar"))) + }, + ) + val spec = suite("KnoraProjectService")(updateSuite) + .provide( + KnoraProjectService.layer, + KnoraProjectRepoInMemory.layer, + OntologyRepoInMemory.emptyLayer, + IriConverter.layer, + StringFormatter.test, + ) +} From f1389a8354fbe66f15f49e9e48090c86f8af9bc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinb=C3=B6lting?= Date: Fri, 15 Nov 2024 14:40:41 +0100 Subject: [PATCH 06/18] feat: Add copyright attribution and license to test data --- .../knoraApiOntologySimple.jsonld | 32 ++++ .../knoraApiOntologyWithValueObjects.jsonld | 176 ++++++++++++++++++ 2 files changed, 208 insertions(+) diff --git a/test_data/generated_test_data/ontologyR2RV2/knoraApiOntologySimple.jsonld b/test_data/generated_test_data/ontologyR2RV2/knoraApiOntologySimple.jsonld index 92990a3815..a012f6a442 100644 --- a/test_data/generated_test_data/ontologyR2RV2/knoraApiOntologySimple.jsonld +++ b/test_data/generated_test_data/ontologyR2RV2/knoraApiOntologySimple.jsonld @@ -902,6 +902,22 @@ { "@id": "knora-api:StillImageAbstractFileValue", "@type": "owl:Class", + "rdfs:subClassOf": [ + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasCopyrightAttribution" + }, + "owl:maxCardinality": 1 + }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasLicense" + }, + "owl:maxCardinality": 1 + } + ], "rdfs:comment": "A file containing a two-dimensional still image" }, { @@ -1267,6 +1283,14 @@ }, "@id": "knora-api:hasComment" }, + { + "@id": "knora-api:hasCopyrightAttribution", + "@type": "owl:DatatypeProperty", + "knora-api:objectType": { + "@id": "xsd:string" + }, + "rdfs:comment": "The copyright statement that gives credit to the original author." + }, { "rdfs:label": "has 3D-file", "rdfs:subPropertyOf": { @@ -1394,6 +1418,14 @@ }, "@id": "knora-api:hasKeyword" }, + { + "@id": "knora-api:hasLicense", + "@type": "owl:DatatypeProperty", + "knora-api:objectType": { + "@id": "xsd:string" + }, + "rdfs:comment": "Specifies the terms under which a work can be used. This statement may be a reference to a well-known license, such as Creative Commons (e.g. 'CC BY-SA') or a custom license." + }, { "rdfs:label": "has Link to", "rdfs:subPropertyOf": { diff --git a/test_data/generated_test_data/ontologyR2RV2/knoraApiOntologyWithValueObjects.jsonld b/test_data/generated_test_data/ontologyR2RV2/knoraApiOntologyWithValueObjects.jsonld index 39bd56e9b4..667d0eb6aa 100644 --- a/test_data/generated_test_data/ontologyR2RV2/knoraApiOntologyWithValueObjects.jsonld +++ b/test_data/generated_test_data/ontologyR2RV2/knoraApiOntologyWithValueObjects.jsonld @@ -234,6 +234,22 @@ "owl:cardinality": 1, "knora-api:isInherited": true }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasCopyrightAttribution" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasLicense" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, { "@type": "owl:Restriction", "owl:onProperty": { @@ -517,6 +533,22 @@ "owl:cardinality": 1, "knora-api:isInherited": true }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasCopyrightAttribution" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasLicense" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, { "@type": "owl:Restriction", "owl:onProperty": { @@ -1315,6 +1347,22 @@ "owl:cardinality": 1, "knora-api:isInherited": true }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasCopyrightAttribution" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasLicense" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, { "@type": "owl:Restriction", "owl:onProperty": { @@ -2270,6 +2318,22 @@ "owl:cardinality": 1, "knora-api:isInherited": true }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasCopyrightAttribution" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasLicense" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, { "@type": "owl:Restriction", "owl:onProperty": { @@ -2559,6 +2623,20 @@ }, "owl:cardinality": 1 }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasCopyrightAttribution" + }, + "owl:maxCardinality": 1 + }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasLicense" + }, + "owl:maxCardinality": 1 + }, { "@type": "owl:Restriction", "owl:onProperty": { @@ -3695,6 +3773,22 @@ "owl:cardinality": 1, "knora-api:isInherited": true }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasCopyrightAttribution" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasLicense" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, { "@type": "owl:Restriction", "owl:onProperty": { @@ -5925,6 +6019,22 @@ "owl:cardinality": 1, "knora-api:isInherited": true }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasCopyrightAttribution" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasLicense" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, { "@type": "owl:Restriction", "owl:onProperty": { @@ -6063,6 +6173,22 @@ "owl:cardinality": 1, "knora-api:isInherited": true }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasCopyrightAttribution" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasLicense" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, { "@type": "owl:Restriction", "owl:onProperty": { @@ -6208,6 +6334,22 @@ "owl:cardinality": 1, "knora-api:isInherited": true }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasCopyrightAttribution" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasLicense" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, { "@type": "owl:Restriction", "owl:onProperty": { @@ -6518,6 +6660,22 @@ "owl:cardinality": 1, "knora-api:isInherited": true }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasCopyrightAttribution" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasLicense" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, { "@type": "owl:Restriction", "owl:onProperty": { @@ -8129,6 +8287,15 @@ }, "rdfs:comment": "Represents a comment on a resource as a knora-base:TextValue" }, + { + "rdfs:label": "has copyright attribution", + "rdfs:comment": "The copyright statement that gives credit to the original author.", + "@type": "owl:DatatypeProperty", + "knora-api:objectType": { + "@id": "xsd:string" + }, + "@id": "knora-api:hasCopyrightAttribution" + }, { "rdfs:label": "has 3D-file", "rdfs:subPropertyOf": { @@ -8287,6 +8454,15 @@ }, "rdfs:comment": "Indicates a keyword of a resource" }, + { + "rdfs:label": "has copyright attribution", + "rdfs:comment": "Specifies the terms under which a work can be used. This statement may be a reference to a well-known license, such as Creative Commons (e.g. CC BY-SA) or a custom license.", + "@type": "owl:DatatypeProperty", + "knora-api:objectType": { + "@id": "xsd:string" + }, + "@id": "knora-api:hasLicense" + }, { "rdfs:label": "has Link to", "rdfs:subPropertyOf": { From 97b0377e24002c4fabf2dd66821a4c34bbc7698f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinb=C3=B6lting?= Date: Fri, 15 Nov 2024 15:47:37 +0100 Subject: [PATCH 07/18] feat: Introduce StringValues for copyright attribution and license --- .../IntegrationTestAdminJsonProtocol.scala | 20 +++++++++++++++- .../admin/ProjectRestServiceSpec.scala | 8 +++---- .../knora/webapi/slice/admin/api/Codecs.scala | 12 ++++++---- .../webapi/slice/admin/api/Examples.scala | 6 +++-- ...rojectsEndpointsRequestsAndResponses.scala | 8 +++---- .../admin/api/model/ProjectsMessagesADM.scala | 6 +++-- .../admin/domain/model/KnoraProject.scala | 23 +++++++++++++++++-- .../slice/admin/repo/rdf/RdfConversions.scala | 3 +++ .../repo/service/KnoraProjectRepoLive.scala | 10 ++++---- .../org/knora/webapi/TestDataFactory.scala | 4 ++-- .../service/KnoraProjectServiceSpec.scala | 18 +++++++++++---- .../service/KnoraProjectRepoLiveSpec.scala | 6 +++-- 12 files changed, 92 insertions(+), 32 deletions(-) diff --git a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala index c0efc1325f..e4382aa8f3 100644 --- a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala +++ b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala @@ -6,7 +6,6 @@ package org.knora.webapi.messages.admin.responder import spray.json.* - import org.knora.webapi.messages.admin.responder.groupsmessages.GroupGetResponseADM import org.knora.webapi.messages.admin.responder.groupsmessages.GroupsGetResponseADM import org.knora.webapi.messages.admin.responder.permissionsmessages.AdministrativePermissionADM @@ -45,7 +44,10 @@ import org.knora.webapi.slice.admin.api.model.ProjectAdminMembersGetResponseADM import org.knora.webapi.slice.admin.api.model.ProjectMembersGetResponseADM import org.knora.webapi.slice.admin.api.model.ProjectOperationResponseADM import org.knora.webapi.slice.admin.domain.model.Group +import org.knora.webapi.slice.admin.domain.model.KnoraProject.CopyrightAttribution +import org.knora.webapi.slice.admin.domain.model.KnoraProject.License import org.knora.webapi.slice.admin.domain.model.User +import org.knora.webapi.slice.common.Value.StringValue /** * A spray-json protocol for generating Knora API JSON providing data about projects. @@ -194,6 +196,22 @@ object IntegrationTestAdminJsonProtocol extends TriplestoreJsonProtocol { ), ) + trait StringValueFormat[T <: StringValue] extends JsonFormat[T] { self => + def from: String => Either[String, T] + override def write(v: T): JsValue = JsString(v.value) + override def read(json: JsValue): T = json match + case JsString(str) => self.from(str).fold(err => throw DeserializationException(err), identity) + case _ => throw DeserializationException("Must be a json String") + } + + implicit object CopyrightAttributionFormat extends StringValueFormat[CopyrightAttribution] { + override val from: String => Either[String, CopyrightAttribution] = CopyrightAttribution.from + } + + implicit object LicenseFormat extends StringValueFormat[License] { + override val from: String => Either[String, License] = License.from + } + implicit val groupFormat: JsonFormat[Group] = jsonFormat6(Group.apply) implicit val projectAdminMembersGetResponseADMFormat: RootJsonFormat[ProjectAdminMembersGetResponseADM] = rootFormat( diff --git a/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala b/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala index b250f5f43d..24db171d85 100644 --- a/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala @@ -162,8 +162,8 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { logo = Some(Logo.unsafeFrom("/fu/bar/baz.jpg")), status = Status.Active, selfjoin = SelfJoin.CannotJoin, - copyrightAttribution = Some("2024, Example Project"), - license = Some("CC-BY-4.0"), + copyrightAttribution = Some(CopyrightAttribution.unsafeFrom("2024, Example Project")), + license = Some(License.unsafeFrom("CC-BY-4.0")), ), SharedTestDataADM.rootUser, ), @@ -176,8 +176,8 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { received.project.description should be( Seq(StringLiteralV2.from(value = "project description", language = Some("en"))), ) - received.project.copyrightAttribution should be(Some("2024, Example Project")) - received.project.license should be(Some("CC-BY-4.0")) + received.project.copyrightAttribution should be(Some(CopyrightAttribution.unsafeFrom("2024, Example Project"))) + received.project.license should be(Some(License.unsafeFrom("CC-BY-4.0"))) newProjectIri.set(received.project.id) diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Codecs.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Codecs.scala index 7a92b5c308..d0486968d8 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Codecs.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Codecs.scala @@ -102,11 +102,13 @@ object Codecs { implicit val restrictedViewWatermark: StringCodec[RestrictedView.Watermark] = booleanCodec( RestrictedView.Watermark.from, ) - implicit val selfJoin: StringCodec[SelfJoin] = booleanCodec(SelfJoin.from) - implicit val shortcode: StringCodec[Shortcode] = stringCodec(Shortcode.from) - implicit val shortname: StringCodec[Shortname] = stringCodec(Shortname.from) - implicit val sparqlEncodedString: StringCodec[SparqlEncodedString] = stringCodec(SparqlEncodedString.from) - implicit val status: StringCodec[Status] = booleanCodec(Status.from) + implicit val selfJoin: StringCodec[SelfJoin] = booleanCodec(SelfJoin.from) + implicit val shortcode: StringCodec[Shortcode] = stringCodec(Shortcode.from) + implicit val shortname: StringCodec[Shortname] = stringCodec(Shortname.from) + implicit val sparqlEncodedString: StringCodec[SparqlEncodedString] = stringCodec(SparqlEncodedString.from) + implicit val status: StringCodec[Status] = booleanCodec(Status.from) + implicit val copyrightAttribution: StringCodec[CopyrightAttribution] = stringCodec(CopyrightAttribution.from) + implicit val license: StringCodec[License] = stringCodec(License.from) // user implicit val userIri: StringCodec[UserIri] = stringCodec(UserIri.from) diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala index 45737e59cd..c76501dd20 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala @@ -23,6 +23,8 @@ import org.knora.webapi.slice.admin.domain.model.GroupIri import org.knora.webapi.slice.admin.domain.model.GroupName import org.knora.webapi.slice.admin.domain.model.GroupSelfJoin import org.knora.webapi.slice.admin.domain.model.GroupStatus +import org.knora.webapi.slice.admin.domain.model.KnoraProject.CopyrightAttribution +import org.knora.webapi.slice.admin.domain.model.KnoraProject.License import org.knora.webapi.slice.admin.domain.model.KnoraProject.ProjectIri import org.knora.webapi.slice.admin.domain.model.User import org.knora.webapi.slice.admin.domain.model.UserIri @@ -93,8 +95,8 @@ object Examples { status = true, ontologies = Seq.empty, selfjoin = false, - copyrightAttribution = Some("2024, Example Project"), - license = Some("CC-BY-4.0"), + copyrightAttribution = Some(CopyrightAttribution.unsafeFrom("2024, Example Project")), + license = Some(License.unsafeFrom("CC-BY-4.0")), ) private val group = Group( diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsEndpointsRequestsAndResponses.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsEndpointsRequestsAndResponses.scala index 25623f24a9..109144d967 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsEndpointsRequestsAndResponses.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsEndpointsRequestsAndResponses.scala @@ -27,8 +27,8 @@ object ProjectsEndpointsRequestsAndResponses { logo: Option[Logo] = None, status: Status, selfjoin: SelfJoin, - copyrightAttribution: Option[String], - license: Option[String], + copyrightAttribution: Option[CopyrightAttribution], + license: Option[License], ) object ProjectCreateRequest { implicit val codec: JsonCodec[ProjectCreateRequest] = DeriveJsonCodec.gen[ProjectCreateRequest] @@ -42,8 +42,8 @@ object ProjectsEndpointsRequestsAndResponses { logo: Option[Logo] = None, status: Option[Status] = None, selfjoin: Option[SelfJoin] = None, - copyrightAttribution: Option[String] = None, - license: Option[String] = None, + copyrightAttribution: Option[CopyrightAttribution] = None, + license: Option[License] = None, ) object ProjectUpdateRequest { implicit val codec: JsonCodec[ProjectUpdateRequest] = DeriveJsonCodec.gen[ProjectUpdateRequest] diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala index c2c4dcdfff..dcab052e59 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala @@ -11,6 +11,8 @@ import zio.json.JsonCodec import org.knora.webapi.IRI import org.knora.webapi.messages.admin.responder.AdminKnoraResponseADM import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 +import org.knora.webapi.slice.admin.api.Codecs.ZioJsonCodec.copyrightAttribution +import org.knora.webapi.slice.admin.api.Codecs.ZioJsonCodec.license import org.knora.webapi.slice.admin.domain.model.KnoraProject.* import org.knora.webapi.slice.admin.domain.model.RestrictedView import org.knora.webapi.slice.admin.domain.model.User @@ -40,8 +42,8 @@ case class Project( ontologies: Seq[IRI], status: Boolean, selfjoin: Boolean, - copyrightAttribution: Option[String], - license: Option[String], + copyrightAttribution: Option[CopyrightAttribution], + license: Option[License], ) extends Ordered[Project] { def projectIri: ProjectIri = ProjectIri.unsafeFrom(id) diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/model/KnoraProject.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/model/KnoraProject.scala index e3771c5802..67ffcfef1e 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/model/KnoraProject.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/model/KnoraProject.scala @@ -34,8 +34,8 @@ case class KnoraProject( status: Status, selfjoin: SelfJoin, restrictedView: RestrictedView, - copyrightAttribution: Option[String], - license: Option[String], + copyrightAttribution: Option[CopyrightAttribution], + license: Option[License], ) extends EntityWithId[ProjectIri] object KnoraProject { @@ -175,4 +175,23 @@ object KnoraProject { def from(value: Boolean): SelfJoin = if (value) CanJoin else CannotJoin } + + final case class CopyrightAttribution private (override val value: String) extends StringValue + object CopyrightAttribution extends StringValueCompanion[CopyrightAttribution] { + private val maxLength = 1_000 + def from(str: String): Either[String, CopyrightAttribution] = + if (str.isEmpty) Left("Copyright attribution cannot be empty.") + else if (str.contains("\n")) Left("Copyright attribution may not contain line breaks.") + else if (str.length >= maxLength) Left(s"Copyright attribution may only be ${maxLength} characters long.") + else Right(CopyrightAttribution(str)) + } + + final case class License private (override val value: String) extends StringValue + object License extends StringValueCompanion[License] { + private val maxLength = 10_000 + def from(str: String): Either[String, License] = + if (str.isEmpty) Left("License cannot be empty.") + else if (str.length >= maxLength) Left(s"License may only be ${maxLength} characters long.") + else Right(License(str)) + } } diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/repo/rdf/RdfConversions.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/repo/rdf/RdfConversions.scala index 1b7c9264ab..1b04ab0b29 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/repo/rdf/RdfConversions.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/repo/rdf/RdfConversions.scala @@ -42,6 +42,9 @@ object RdfConversions { implicit val selfjoinConverter: Boolean => Either[String, SelfJoin] = value => Right(SelfJoin.from(value)) implicit val descriptionConverter: LangString => Either[String, Description] = langString => Description.from(StringLiteralV2.from(langString.value, langString.lang)) + implicit val copyrightAttributionConverter: String => Either[String, CopyrightAttribution] = value => + CopyrightAttribution.from(value) + implicit val licenseConverter: String => Either[String, License] = value => License.from(value) // User properties implicit val usernameConverter: String => Either[String, Username] = Username.from diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/repo/service/KnoraProjectRepoLive.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/repo/service/KnoraProjectRepoLive.scala index 8c9336c874..9268f786c1 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/repo/service/KnoraProjectRepoLive.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/repo/service/KnoraProjectRepoLive.scala @@ -104,8 +104,8 @@ object KnoraProjectRepoLive { logo <- resource.getStringLiteral[Logo](ProjectLogo) status <- resource.getBooleanLiteralOrFail[Status](StatusProp) selfjoin <- resource.getBooleanLiteralOrFail[SelfJoin](HasSelfJoinEnabled) - copyrightAttribution <- resource.getStringLiteral[String](HasCopyrightAttribution)(Right(_)) - license <- resource.getStringLiteral[String](HasLicense)(Right(_)) + copyrightAttribution <- resource.getStringLiteral[CopyrightAttribution](HasCopyrightAttribution) + license <- resource.getStringLiteral[License](HasLicense) restrictedView <- getRestrictedView } yield KnoraProject( id = ProjectIri.unsafeFrom(iri.value), @@ -145,8 +145,10 @@ object KnoraProjectRepoLive { pattern.andHas(Vocabulary.KnoraAdmin.projectRestrictedViewWatermark, watermark) } - project.copyrightAttribution.foreach(attr => pattern.andHas(Vocabulary.KnoraBase.hasCopyrightAttribution, attr)) - project.license.foreach(license => pattern.andHas(Vocabulary.KnoraBase.hasLicense, license)) + project.copyrightAttribution.foreach(attr => + pattern.andHas(Vocabulary.KnoraBase.hasCopyrightAttribution, attr.value), + ) + project.license.foreach(license => pattern.andHas(Vocabulary.KnoraBase.hasLicense, license.value)) pattern } diff --git a/webapi/src/test/scala/org/knora/webapi/TestDataFactory.scala b/webapi/src/test/scala/org/knora/webapi/TestDataFactory.scala index 2a026dacfe..982ff13950 100644 --- a/webapi/src/test/scala/org/knora/webapi/TestDataFactory.scala +++ b/webapi/src/test/scala/org/knora/webapi/TestDataFactory.scala @@ -99,7 +99,7 @@ object TestDataFactory { Status.Active, SelfJoin.CannotJoin, RestrictedView.default, - Some("2024, Example Project"), - Some("CC-BY-4.0"), + Some(CopyrightAttribution.unsafeFrom("2024, Example Project")), + Some(License.unsafeFrom("CC-BY-4.0")), ) } diff --git a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/KnoraProjectServiceSpec.scala b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/KnoraProjectServiceSpec.scala index f8fb2cf9d4..030da89ce6 100644 --- a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/KnoraProjectServiceSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/KnoraProjectServiceSpec.scala @@ -12,6 +12,8 @@ import zio.test.Assertion.* import org.knora.webapi.TestDataFactory import org.knora.webapi.messages.StringFormatter import org.knora.webapi.slice.admin.api.model.ProjectsEndpointsRequestsAndResponses.ProjectUpdateRequest +import org.knora.webapi.slice.admin.domain.model.KnoraProject.CopyrightAttribution +import org.knora.webapi.slice.admin.domain.model.KnoraProject.License import org.knora.webapi.slice.admin.domain.repo.KnoraProjectRepoInMemory import org.knora.webapi.slice.ontology.repo.service.OntologyRepoInMemory import org.knora.webapi.slice.resourceinfo.domain.IriConverter @@ -25,10 +27,18 @@ object KnoraProjectServiceSpec extends ZIOSpecDefault { test("should update the license and copyright attribution") { val project = TestDataFactory.someProject for { - _ <- repo(_.save(project)) - updateRequest = ProjectUpdateRequest(copyrightAttribution = Some("Foo"), license = Some("bar")) - actual <- projectService(_.updateProject(project, updateRequest)) - } yield assertTrue(actual == project.copy(copyrightAttribution = Some("Foo"), license = Some("bar"))) + _ <- repo(_.save(project)) + updateRequest = ProjectUpdateRequest( + copyrightAttribution = Some(CopyrightAttribution.unsafeFrom("Foo")), + license = Some(License.unsafeFrom("bar")), + ) + actual <- projectService(_.updateProject(project, updateRequest)) + } yield assertTrue( + actual == project.copy( + copyrightAttribution = Some(CopyrightAttribution.unsafeFrom("Foo")), + license = Some(License.unsafeFrom("bar")), + ), + ) }, ) val spec = suite("KnoraProjectService")(updateSuite) diff --git a/webapi/src/test/scala/org/knora/webapi/slice/admin/repo/service/KnoraProjectRepoLiveSpec.scala b/webapi/src/test/scala/org/knora/webapi/slice/admin/repo/service/KnoraProjectRepoLiveSpec.scala index 7168f0a2cd..1fd1ed296c 100644 --- a/webapi/src/test/scala/org/knora/webapi/slice/admin/repo/service/KnoraProjectRepoLiveSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/slice/admin/repo/service/KnoraProjectRepoLiveSpec.scala @@ -18,8 +18,10 @@ import zio.test.check import org.knora.webapi.messages.StringFormatter import org.knora.webapi.slice.admin.AdminConstants import org.knora.webapi.slice.admin.domain.model.KnoraProject +import org.knora.webapi.slice.admin.domain.model.KnoraProject.CopyrightAttribution import org.knora.webapi.slice.admin.domain.model.KnoraProject.Description import org.knora.webapi.slice.admin.domain.model.KnoraProject.Keyword +import org.knora.webapi.slice.admin.domain.model.KnoraProject.License import org.knora.webapi.slice.admin.domain.model.KnoraProject.Logo import org.knora.webapi.slice.admin.domain.model.KnoraProject.Longname import org.knora.webapi.slice.admin.domain.model.KnoraProject.ProjectIri @@ -45,8 +47,8 @@ object KnoraProjectRepoLiveSpec extends ZIOSpecDefault { Status.Active, SelfJoin.CannotJoin, RestrictedView.default, - Some("2024, Example Project"), - Some("Apache-2.0"), + Some(CopyrightAttribution.unsafeFrom("2024, Example Project")), + Some(License.unsafeFrom("Apache-2.0")), ) private val someProjectTrig = From aec743f00bcb8060fbfa3d29f7b89f3409e486be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinb=C3=B6lting?= Date: Fri, 15 Nov 2024 16:38:19 +0100 Subject: [PATCH 08/18] fmt --- .../admin/responder/IntegrationTestAdminJsonProtocol.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala index e4382aa8f3..3ce4d8d615 100644 --- a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala +++ b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala @@ -6,6 +6,7 @@ package org.knora.webapi.messages.admin.responder import spray.json.* + import org.knora.webapi.messages.admin.responder.groupsmessages.GroupGetResponseADM import org.knora.webapi.messages.admin.responder.groupsmessages.GroupsGetResponseADM import org.knora.webapi.messages.admin.responder.permissionsmessages.AdministrativePermissionADM From 7947c2dd7325b3f1bf3b63f15534c55f1a36b2a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinb=C3=B6lting?= Date: Fri, 15 Nov 2024 16:40:34 +0100 Subject: [PATCH 09/18] simplify --- .../knora/webapi/slice/admin/repo/rdf/RdfConversions.scala | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/repo/rdf/RdfConversions.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/repo/rdf/RdfConversions.scala index 1b04ab0b29..f01da22943 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/repo/rdf/RdfConversions.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/repo/rdf/RdfConversions.scala @@ -42,9 +42,8 @@ object RdfConversions { implicit val selfjoinConverter: Boolean => Either[String, SelfJoin] = value => Right(SelfJoin.from(value)) implicit val descriptionConverter: LangString => Either[String, Description] = langString => Description.from(StringLiteralV2.from(langString.value, langString.lang)) - implicit val copyrightAttributionConverter: String => Either[String, CopyrightAttribution] = value => - CopyrightAttribution.from(value) - implicit val licenseConverter: String => Either[String, License] = value => License.from(value) + implicit val copyrightAttributionConverter: String => Either[String, CopyrightAttribution] = CopyrightAttribution.from + implicit val licenseConverter: String => Either[String, License] = License.from // User properties implicit val usernameConverter: String => Either[String, Username] = Username.from From 64ce806fcf539b6eed58ede63a77c9d2ea4e807b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinb=C3=B6lting?= Date: Fri, 15 Nov 2024 17:37:52 +0100 Subject: [PATCH 10/18] refactor: Make Project.shortname typed --- .../IntegrationTestAdminJsonProtocol.scala | 5 +++++ .../admin/ProjectRestServiceSpec.scala | 8 +++---- .../webapi/sharedtestdata/ProjectInfo.scala | 22 +++++++++---------- .../sharedtestdata/SharedTestDataADM.scala | 21 +++++++++--------- .../webapi/slice/admin/api/Examples.scala | 3 ++- .../admin/api/model/ProjectsMessagesADM.scala | 4 ++-- .../admin/domain/service/ProjectService.scala | 7 +++--- .../domain/service/ProjectServiceSpec.scala | 4 ++-- 8 files changed, 40 insertions(+), 34 deletions(-) diff --git a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala index 3ce4d8d615..9294bdda50 100644 --- a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala +++ b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala @@ -47,6 +47,7 @@ import org.knora.webapi.slice.admin.api.model.ProjectOperationResponseADM import org.knora.webapi.slice.admin.domain.model.Group import org.knora.webapi.slice.admin.domain.model.KnoraProject.CopyrightAttribution import org.knora.webapi.slice.admin.domain.model.KnoraProject.License +import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortname import org.knora.webapi.slice.admin.domain.model.User import org.knora.webapi.slice.common.Value.StringValue @@ -213,6 +214,10 @@ object IntegrationTestAdminJsonProtocol extends TriplestoreJsonProtocol { override val from: String => Either[String, License] = License.from } + implicit object ShortnameFormat extends StringValueFormat[Shortname] { + override val from: String => Either[String, Shortname] = Shortname.from + } + implicit val groupFormat: JsonFormat[Group] = jsonFormat6(Group.apply) implicit val projectAdminMembersGetResponseADMFormat: RootJsonFormat[ProjectAdminMembersGetResponseADM] = rootFormat( diff --git a/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala b/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala index 24db171d85..a64bec8480 100644 --- a/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala @@ -66,7 +66,7 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { "return information about a project identified by shortname" in { val actual = UnsafeZioRun.runOrThrow( - ProjectRestService(_.findByShortname(SharedTestDataADM.incunabulaProject.getShortname)), + ProjectRestService(_.findByShortname(SharedTestDataADM.incunabulaProject.shortname)), ) assert(actual == ProjectGetResponse(toExternal(SharedTestDataADM.incunabulaProject))) } @@ -106,7 +106,7 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { "return restricted view settings using project SHORTNAME" in { val actual = UnsafeZioRun.runOrThrow( ProjectRestService( - _.getProjectRestrictedViewSettingsByShortname(SharedTestDataADM.imagesProject.getShortname), + _.getProjectRestrictedViewSettingsByShortname(SharedTestDataADM.imagesProject.shortname), ), ) actual shouldEqual expectedResult @@ -451,7 +451,7 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { "return all members of a project identified by shortname" in { val actual = UnsafeZioRun.runOrThrow( ProjectRestService( - _.getProjectMembersByShortname(SharedTestDataADM.rootUser, SharedTestDataADM.imagesProject.getShortname), + _.getProjectMembersByShortname(SharedTestDataADM.rootUser, SharedTestDataADM.imagesProject.shortname), ), ) @@ -527,7 +527,7 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { ProjectRestService( _.getProjectAdminMembersByShortname( SharedTestDataADM.rootUser, - SharedTestDataADM.imagesProject.getShortname, + SharedTestDataADM.imagesProject.shortname, ), ), ) diff --git a/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala b/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala index e52c52700f..49ea177cef 100644 --- a/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala +++ b/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala @@ -35,17 +35,17 @@ case class ProjectInfo( ) object ProjectInfo { - def from(projectADM: Project): ProjectInfo = + def from(project: Project): ProjectInfo = ProjectInfo( - id = projectADM.id, - shortname = projectADM.shortname, - shortcode = projectADM.shortcode, - longname = projectADM.longname, - description = projectADM.description.headOption.map(_.value), - keywords = projectADM.keywords.headOption.map(_ => projectADM.keywords.mkString(", ")), - logo = projectADM.logo, - ontologies = projectADM.ontologies, - status = projectADM.status, - selfjoin = projectADM.selfjoin, + id = project.id, + shortname = project.shortname.value, + shortcode = project.shortcode, + longname = project.longname, + description = project.description.headOption.map(_.value), + keywords = project.keywords.headOption.map(_ => project.keywords.mkString(", ")), + logo = project.logo, + ontologies = project.ontologies, + status = project.status, + selfjoin = project.selfjoin, ) } diff --git a/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala b/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala index b4e11edcc4..69711de82d 100644 --- a/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala +++ b/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala @@ -16,6 +16,7 @@ import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 import org.knora.webapi.messages.util.KnoraSystemInstances import org.knora.webapi.slice.admin.api.model.Project import org.knora.webapi.slice.admin.domain.model.Group +import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortname import org.knora.webapi.slice.admin.domain.model.Permission import org.knora.webapi.slice.admin.domain.model.User import org.knora.webapi.slice.admin.domain.service.KnoraGroupRepo @@ -155,7 +156,7 @@ object SharedTestDataADM { /* represents the full ProjectADM of the Knora System project */ def systemProject: Project = Project( id = KnoraProjectRepo.builtIn.SystemProject.id.value, - shortname = "SystemProject", + shortname = Shortname.unsafeFrom("SystemProject"), shortcode = "FFFF", longname = Some("Knora System Project"), description = Seq(StringLiteralV2.from(value = "Knora System Project", language = Some("en"))), @@ -176,7 +177,7 @@ object SharedTestDataADM { /* represents the full ProjectADM of the default shared ontologies project */ def defaultSharedOntologiesProject: Project = Project( id = OntologyConstants.KnoraAdmin.DefaultSharedOntologiesProject, - shortname = "DefaultSharedOntologiesProject", + shortname = Shortname.unsafeFrom("DefaultSharedOntologiesProject"), shortcode = "0000", longname = Some("Default Knora Shared Ontologies Project"), description = Seq(StringLiteralV2.from(value = "Default Knora Shared Ontologies Project", language = Some("en"))), @@ -290,7 +291,7 @@ object SharedTestDataADM { /* represents the full ProjectADM of the images project */ def imagesProject: Project = Project( id = imagesProjectIri, - shortname = "images", + shortname = Shortname.unsafeFrom("images"), shortcode = "00FF", longname = Some("Image Collection Demo"), description = Seq(StringLiteralV2.from(value = "A demo project of a collection of images", language = Some("en"))), @@ -306,7 +307,7 @@ object SharedTestDataADM { /* represents the full ProjectADM of the images project in the external format */ def imagesProjectExternal: Project = Project( id = imagesProjectIri, - shortname = "images", + shortname = Shortname.unsafeFrom("images"), shortcode = "00FF", longname = Some("Image Collection Demo"), description = Seq(StringLiteralV2.from(value = "A demo project of a collection of images", language = Some("en"))), @@ -450,7 +451,7 @@ object SharedTestDataADM { /* represents the ProjectADM of the incunabula project */ def incunabulaProject: Project = Project( id = incunabulaProjectIri, - shortname = "incunabula", + shortname = Shortname.unsafeFrom("incunabula"), shortcode = "0803", longname = Some("Bilderfolgen Basler Frühdrucke"), description = Seq( @@ -487,7 +488,7 @@ object SharedTestDataADM { /* represents the ProjectADM of the incunabula project in the external format*/ def incunabulaProjectExternal: Project = Project( id = incunabulaProjectIri, - shortname = "incunabula", + shortname = Shortname.unsafeFrom("incunabula"), shortcode = "0803", longname = Some("Bilderfolgen Basler Frühdrucke"), description = Seq( @@ -622,7 +623,7 @@ object SharedTestDataADM { def anythingProject: Project = Project( id = anythingProjectIri, - shortname = "anything", + shortname = Shortname.unsafeFrom("anything"), shortcode = "0001", longname = Some("Anything Project"), description = Seq(StringLiteralV2.from(value = "Anything Project", language = None)), @@ -637,7 +638,7 @@ object SharedTestDataADM { def anythingProjectExternal: Project = Project( id = anythingProjectIri, - shortname = "anything", + shortname = Shortname.unsafeFrom("anything"), shortcode = "0001", longname = Some("Anything Project"), description = Seq(StringLiteralV2.from(value = "Anything Project", language = None)), @@ -674,7 +675,7 @@ object SharedTestDataADM { def beolProject: Project = Project( id = beolProjectIri, - shortname = "beol", + shortname = Shortname.unsafeFrom("beol"), shortcode = "0801", longname = Some("Bernoulli-Euler Online"), description = Seq(StringLiteralV2.from(value = "Bernoulli-Euler Online", language = None)), @@ -730,7 +731,7 @@ object SharedTestDataADM { def dokubibProject: Project = Project( id = dokubibProjectIri, - shortname = "dokubib", + shortname = Shortname.unsafeFrom("dokubib"), shortcode = "0804", longname = Some("Dokubib"), description = Seq(StringLiteralV2.from(value = "Dokubib", language = None)), diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala index c76501dd20..10e9834c84 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala @@ -26,6 +26,7 @@ import org.knora.webapi.slice.admin.domain.model.GroupStatus import org.knora.webapi.slice.admin.domain.model.KnoraProject.CopyrightAttribution import org.knora.webapi.slice.admin.domain.model.KnoraProject.License import org.knora.webapi.slice.admin.domain.model.KnoraProject.ProjectIri +import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortname import org.knora.webapi.slice.admin.domain.model.User import org.knora.webapi.slice.admin.domain.model.UserIri import org.knora.webapi.slice.admin.domain.model.UserStatus @@ -86,7 +87,7 @@ object Examples { private val project: Project = Project( id = ProjectExample.projectIri.value, - shortname = "example", + shortname = Shortname.unsafeFrom("example"), shortcode = "0001", longname = Some("Example Project"), description = Seq(StringLiteralV2.from("An example project", Some("en"))), diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala index dcab052e59..69638938ae 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala @@ -13,6 +13,7 @@ import org.knora.webapi.messages.admin.responder.AdminKnoraResponseADM import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 import org.knora.webapi.slice.admin.api.Codecs.ZioJsonCodec.copyrightAttribution import org.knora.webapi.slice.admin.api.Codecs.ZioJsonCodec.license +import org.knora.webapi.slice.admin.api.Codecs.ZioJsonCodec.shortname import org.knora.webapi.slice.admin.domain.model.KnoraProject.* import org.knora.webapi.slice.admin.domain.model.RestrictedView import org.knora.webapi.slice.admin.domain.model.User @@ -33,7 +34,7 @@ import org.knora.webapi.slice.admin.domain.model.User */ case class Project( id: IRI, - shortname: String, + shortname: Shortname, shortcode: String, longname: Option[String], description: Seq[StringLiteralV2], @@ -48,7 +49,6 @@ case class Project( def projectIri: ProjectIri = ProjectIri.unsafeFrom(id) - def getShortname: Shortname = Shortname.unsafeFrom(shortname) def getShortcode: Shortcode = Shortcode.unsafeFrom(shortcode) /** diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala index e4af95ef9c..bc68cb1ce1 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala @@ -47,7 +47,7 @@ final case class ProjectService( .map(ontologies => Project( knoraProject.id.value, - knoraProject.shortname.value, + knoraProject.shortname, knoraProject.shortcode.value, knoraProject.longname.map(_.value), knoraProject.description.map(_.value), @@ -64,7 +64,7 @@ final case class ProjectService( private def toKnoraProject(project: Project, restrictedView: RestrictedView): KnoraProject = KnoraProject( id = ProjectIri.unsafeFrom(project.id), - shortname = Shortname.unsafeFrom(project.shortname), + shortname = project.shortname, shortcode = Shortcode.unsafeFrom(project.shortcode), longname = project.longname.map(Longname.unsafeFrom), description = NonEmptyChunk @@ -99,8 +99,7 @@ object ProjectService { */ def projectDataNamedGraphV2(project: Project): InternalIri = { val shortcode = Shortcode.unsafeFrom(project.shortcode) - val shortname = Shortname.unsafeFrom(project.shortname) - projectDataNamedGraphV2(shortcode, shortname) + projectDataNamedGraphV2(shortcode, project.shortname) } /** diff --git a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala index e6f842faa6..61be50aa39 100644 --- a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala @@ -22,7 +22,7 @@ object ProjectServiceSpec extends ZIOSpecDefault { val spec: Spec[Any, Nothing] = suite("projectDataNamedGraphV2 should return the data named graph of a project with shortcode for")( test("a ProjectADM") { - val shortname = "someProject" + val shortname = Shortname.unsafeFrom("someProject") val shortcode = "0001" val p = Project( id = IriTestConstants.Project.TestProject, @@ -39,7 +39,7 @@ object ProjectServiceSpec extends ZIOSpecDefault { license = None, ) assertTrue( - ProjectService.projectDataNamedGraphV2(p).value == s"http://www.knora.org/data/$shortcode/$shortname", + ProjectService.projectDataNamedGraphV2(p).value == s"http://www.knora.org/data/$shortcode/${shortname.value}", ) }, test("a KnoraProject") { From 0ddf7aaf601f326c9c7e3a16f803ffe19a8a5c84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinb=C3=B6lting?= Date: Fri, 15 Nov 2024 17:49:31 +0100 Subject: [PATCH 11/18] refactor: Make Project.shortcode typed --- .../IntegrationTestAdminJsonProtocol.scala | 6 ++- .../models/filemodels/FileModelsSpec.scala | 40 +++++++++---------- .../admin/ProjectRestServiceSpec.scala | 6 +-- .../webapi/sharedtestdata/ProjectInfo.scala | 2 +- .../sharedtestdata/SharedTestDataADM.scala | 22 +++++----- .../webapi/messages/StringFormatter.scala | 4 +- .../webapi/responders/v2/ResourceUtilV2.scala | 2 +- .../webapi/slice/admin/api/Examples.scala | 3 +- .../admin/api/model/ProjectsMessagesADM.scala | 5 +-- .../admin/domain/service/ProjectService.scala | 10 ++--- .../ApiComplexV2JsonLdRequestParser.scala | 4 +- .../domain/service/ProjectServiceSpec.scala | 8 ++-- 12 files changed, 58 insertions(+), 54 deletions(-) diff --git a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala index 9294bdda50..b95941ae5d 100644 --- a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala +++ b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala @@ -6,7 +6,6 @@ package org.knora.webapi.messages.admin.responder import spray.json.* - import org.knora.webapi.messages.admin.responder.groupsmessages.GroupGetResponseADM import org.knora.webapi.messages.admin.responder.groupsmessages.GroupsGetResponseADM import org.knora.webapi.messages.admin.responder.permissionsmessages.AdministrativePermissionADM @@ -47,6 +46,7 @@ import org.knora.webapi.slice.admin.api.model.ProjectOperationResponseADM import org.knora.webapi.slice.admin.domain.model.Group import org.knora.webapi.slice.admin.domain.model.KnoraProject.CopyrightAttribution import org.knora.webapi.slice.admin.domain.model.KnoraProject.License +import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortcode import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortname import org.knora.webapi.slice.admin.domain.model.User import org.knora.webapi.slice.common.Value.StringValue @@ -218,6 +218,10 @@ object IntegrationTestAdminJsonProtocol extends TriplestoreJsonProtocol { override val from: String => Either[String, Shortname] = Shortname.from } + implicit object ShortcodeFormat extends StringValueFormat[Shortcode] { + override val from: String => Either[String, Shortcode] = Shortcode.from + } + implicit val groupFormat: JsonFormat[Group] = jsonFormat6(Group.apply) implicit val projectAdminMembersGetResponseADMFormat: RootJsonFormat[ProjectAdminMembersGetResponseADM] = rootFormat( diff --git a/integration/src/test/scala/org/knora/webapi/models/filemodels/FileModelsSpec.scala b/integration/src/test/scala/org/knora/webapi/models/filemodels/FileModelsSpec.scala index a3424eeda3..5ac6b34b2b 100644 --- a/integration/src/test/scala/org/knora/webapi/models/filemodels/FileModelsSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/models/filemodels/FileModelsSpec.scala @@ -10,7 +10,6 @@ import spray.json.DefaultJsonProtocol.* import java.time.Instant import java.util.UUID - import dsp.errors.AssertionException import org.knora.webapi.ApiV2Complex import org.knora.webapi.CoreSpec @@ -20,6 +19,7 @@ import org.knora.webapi.messages.v2.responder.resourcemessages.CreateValueInNewR import org.knora.webapi.messages.v2.responder.valuemessages.DocumentFileValueContentV2 import org.knora.webapi.messages.v2.responder.valuemessages.FileValueV2 import org.knora.webapi.sharedtestdata.SharedTestDataADM +import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortcode class FileModelsSpec extends CoreSpec { implicit val stringFormatter: StringFormatter = StringFormatter.getGeneralInstance @@ -263,7 +263,7 @@ class FileModelsSpec extends CoreSpec { .toJsonLd( className = className, ontologyName = ontologyName, - shortcode = shortcode, + shortcode = shortcode.value, ontologyIRI = ontologyIRI, ) .parseJson @@ -408,8 +408,8 @@ class FileModelsSpec extends CoreSpec { "creating a ChangeFileRequest," should { "create a valid representation of a DocumentRepresentation with default values" in { - val resourceIRI = stringFormatter.makeRandomResourceIri("0000") - val valueIRI = stringFormatter.makeRandomResourceIri("0000") + val resourceIRI = stringFormatter.makeRandomResourceIri(Shortcode.unsafeFrom("0000")) + val valueIRI = stringFormatter.makeRandomResourceIri(Shortcode.unsafeFrom("0000")) val change = ChangeFileRequest.make( fileType = FileType.DocumentFile(), @@ -432,8 +432,8 @@ class FileModelsSpec extends CoreSpec { } "create a valid representation of a DocumentRepresentation with custom values" in { - val resourceIRI = stringFormatter.makeRandomResourceIri("0000") - val valueIRI = stringFormatter.makeRandomResourceIri("0000") + val resourceIRI = stringFormatter.makeRandomResourceIri(Shortcode.unsafeFrom("0000")) + val valueIRI = stringFormatter.makeRandomResourceIri(Shortcode.unsafeFrom("0000")) val pageCount = Some(33) val dimX = Some(44) val dimY = Some(55) @@ -467,8 +467,8 @@ class FileModelsSpec extends CoreSpec { } "create a valid representation of a StillImageRepresentation with default values" in { - val resourceIRI = stringFormatter.makeRandomResourceIri("0000") - val valueIRI = stringFormatter.makeRandomResourceIri("0000") + val resourceIRI = stringFormatter.makeRandomResourceIri(Shortcode.unsafeFrom("0000")) + val valueIRI = stringFormatter.makeRandomResourceIri(Shortcode.unsafeFrom("0000")) val change = ChangeFileRequest.make( fileType = FileType.StillImageFile(), @@ -490,8 +490,8 @@ class FileModelsSpec extends CoreSpec { } "create a valid representation of a MovingImageRepresentation with default values" in { - val resourceIRI = stringFormatter.makeRandomResourceIri("0000") - val valueIRI = stringFormatter.makeRandomResourceIri("0000") + val resourceIRI = stringFormatter.makeRandomResourceIri(Shortcode.unsafeFrom("0000")) + val valueIRI = stringFormatter.makeRandomResourceIri(Shortcode.unsafeFrom("0000")) val change = ChangeFileRequest.make( fileType = FileType.MovingImageFile(), @@ -513,8 +513,8 @@ class FileModelsSpec extends CoreSpec { } "create a valid representation of a AudioRepresentation with default values" in { - val resourceIRI = stringFormatter.makeRandomResourceIri("0000") - val valueIRI = stringFormatter.makeRandomResourceIri("0000") + val resourceIRI = stringFormatter.makeRandomResourceIri(Shortcode.unsafeFrom("0000")) + val valueIRI = stringFormatter.makeRandomResourceIri(Shortcode.unsafeFrom("0000")) val change = ChangeFileRequest.make( fileType = FileType.AudioFile, @@ -531,8 +531,8 @@ class FileModelsSpec extends CoreSpec { } "create a valid representation of a TextRepresentation with default values" in { - val resourceIRI = stringFormatter.makeRandomResourceIri("0000") - val valueIRI = stringFormatter.makeRandomResourceIri("0000") + val resourceIRI = stringFormatter.makeRandomResourceIri(Shortcode.unsafeFrom("0000")) + val valueIRI = stringFormatter.makeRandomResourceIri(Shortcode.unsafeFrom("0000")) val change = ChangeFileRequest.make( fileType = FileType.TextFile, @@ -549,8 +549,8 @@ class FileModelsSpec extends CoreSpec { } "create a valid representation of a ArchiveRepresentation with default values" in { - val resourceIRI = stringFormatter.makeRandomResourceIri("0000") - val valueIRI = stringFormatter.makeRandomResourceIri("0000") + val resourceIRI = stringFormatter.makeRandomResourceIri(Shortcode.unsafeFrom("0000")) + val valueIRI = stringFormatter.makeRandomResourceIri(Shortcode.unsafeFrom("0000")) val change = ChangeFileRequest.make( fileType = FileType.ArchiveFile, @@ -569,8 +569,8 @@ class FileModelsSpec extends CoreSpec { "generating a JSON-LD representation of a ChangeFileRequest," should { "correctly serialize a DocumentRepresentation with default values" in { - val resourceIRI = stringFormatter.makeRandomResourceIri("7777") - val valueIRI = stringFormatter.makeRandomResourceIri("7777") + val resourceIRI = stringFormatter.makeRandomResourceIri(Shortcode.unsafeFrom("7777")) + val valueIRI = stringFormatter.makeRandomResourceIri(Shortcode.unsafeFrom("7777")) val documentRepresentation = ChangeFileRequest.make( fileType = FileType.DocumentFile(), @@ -598,8 +598,8 @@ class FileModelsSpec extends CoreSpec { } "correctly serialize a DocumentRepresentation with custom values" in { - val resourceIRI = stringFormatter.makeRandomResourceIri("7777") - val valueIRI = stringFormatter.makeRandomResourceIri("7777") + val resourceIRI = stringFormatter.makeRandomResourceIri(Shortcode.unsafeFrom("7777")) + val valueIRI = stringFormatter.makeRandomResourceIri(Shortcode.unsafeFrom("7777")) val className = "CustomDocumentRepresentation" val prefix = "onto" diff --git a/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala b/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala index a64bec8480..f3d2e0101e 100644 --- a/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala @@ -115,7 +115,7 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { "return restricted view settings using project SHORTCODE" in { val actual = UnsafeZioRun.runOrThrow( ProjectRestService( - _.getProjectRestrictedViewSettingsByShortcode(SharedTestDataADM.imagesProject.getShortcode), + _.getProjectRestrictedViewSettingsByShortcode(SharedTestDataADM.imagesProject.shortcode), ), ) actual shouldEqual expectedResult @@ -468,7 +468,7 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { "return all members of a project identified by shortcode" in { val actual = UnsafeZioRun.runOrThrow( ProjectRestService( - _.getProjectMembersByShortcode(SharedTestDataADM.rootUser, SharedTestDataADM.imagesProject.getShortcode), + _.getProjectMembersByShortcode(SharedTestDataADM.rootUser, SharedTestDataADM.imagesProject.shortcode), ), ) @@ -545,7 +545,7 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { ProjectRestService( _.getProjectAdminMembersByShortcode( SharedTestDataADM.rootUser, - SharedTestDataADM.imagesProject.getShortcode, + SharedTestDataADM.imagesProject.shortcode, ), ), ) diff --git a/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala b/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala index 49ea177cef..e80630d15e 100644 --- a/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala +++ b/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala @@ -39,7 +39,7 @@ object ProjectInfo { ProjectInfo( id = project.id, shortname = project.shortname.value, - shortcode = project.shortcode, + shortcode = project.shortcode.value, longname = project.longname, description = project.description.headOption.map(_.value), keywords = project.keywords.headOption.map(_ => project.keywords.mkString(", ")), diff --git a/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala b/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala index 69711de82d..de70ae2409 100644 --- a/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala +++ b/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala @@ -6,7 +6,6 @@ package org.knora.webapi.sharedtestdata import java.time.Instant - import dsp.constants.SalsahGui import org.knora.webapi.IRI import org.knora.webapi.messages.OntologyConstants @@ -16,6 +15,7 @@ import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 import org.knora.webapi.messages.util.KnoraSystemInstances import org.knora.webapi.slice.admin.api.model.Project import org.knora.webapi.slice.admin.domain.model.Group +import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortcode import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortname import org.knora.webapi.slice.admin.domain.model.Permission import org.knora.webapi.slice.admin.domain.model.User @@ -157,7 +157,7 @@ object SharedTestDataADM { def systemProject: Project = Project( id = KnoraProjectRepo.builtIn.SystemProject.id.value, shortname = Shortname.unsafeFrom("SystemProject"), - shortcode = "FFFF", + shortcode = Shortcode.unsafeFrom("FFFF"), longname = Some("Knora System Project"), description = Seq(StringLiteralV2.from(value = "Knora System Project", language = Some("en"))), keywords = Seq.empty[String], @@ -178,7 +178,7 @@ object SharedTestDataADM { def defaultSharedOntologiesProject: Project = Project( id = OntologyConstants.KnoraAdmin.DefaultSharedOntologiesProject, shortname = Shortname.unsafeFrom("DefaultSharedOntologiesProject"), - shortcode = "0000", + shortcode = Shortcode.unsafeFrom("0000"), longname = Some("Default Knora Shared Ontologies Project"), description = Seq(StringLiteralV2.from(value = "Default Knora Shared Ontologies Project", language = Some("en"))), keywords = Seq.empty[String], @@ -292,7 +292,7 @@ object SharedTestDataADM { def imagesProject: Project = Project( id = imagesProjectIri, shortname = Shortname.unsafeFrom("images"), - shortcode = "00FF", + shortcode = Shortcode.unsafeFrom("00FF"), longname = Some("Image Collection Demo"), description = Seq(StringLiteralV2.from(value = "A demo project of a collection of images", language = Some("en"))), keywords = Seq("images", "collection").sorted, @@ -308,7 +308,7 @@ object SharedTestDataADM { def imagesProjectExternal: Project = Project( id = imagesProjectIri, shortname = Shortname.unsafeFrom("images"), - shortcode = "00FF", + shortcode = Shortcode.unsafeFrom("00FF"), longname = Some("Image Collection Demo"), description = Seq(StringLiteralV2.from(value = "A demo project of a collection of images", language = Some("en"))), keywords = Seq("images", "collection").sorted, @@ -452,7 +452,7 @@ object SharedTestDataADM { def incunabulaProject: Project = Project( id = incunabulaProjectIri, shortname = Shortname.unsafeFrom("incunabula"), - shortcode = "0803", + shortcode = Shortcode.unsafeFrom("0803"), longname = Some("Bilderfolgen Basler Frühdrucke"), description = Seq( StringLiteralV2.from( @@ -489,7 +489,7 @@ object SharedTestDataADM { def incunabulaProjectExternal: Project = Project( id = incunabulaProjectIri, shortname = Shortname.unsafeFrom("incunabula"), - shortcode = "0803", + shortcode = Shortcode.unsafeFrom("0803"), longname = Some("Bilderfolgen Basler Frühdrucke"), description = Seq( StringLiteralV2.from( @@ -624,7 +624,7 @@ object SharedTestDataADM { def anythingProject: Project = Project( id = anythingProjectIri, shortname = Shortname.unsafeFrom("anything"), - shortcode = "0001", + shortcode = Shortcode.unsafeFrom("0001"), longname = Some("Anything Project"), description = Seq(StringLiteralV2.from(value = "Anything Project", language = None)), keywords = Seq("things", "arbitrary test data").sorted, @@ -639,7 +639,7 @@ object SharedTestDataADM { def anythingProjectExternal: Project = Project( id = anythingProjectIri, shortname = Shortname.unsafeFrom("anything"), - shortcode = "0001", + shortcode = Shortcode.unsafeFrom("0001"), longname = Some("Anything Project"), description = Seq(StringLiteralV2.from(value = "Anything Project", language = None)), keywords = Seq("things", "arbitrary test data").sorted, @@ -676,7 +676,7 @@ object SharedTestDataADM { def beolProject: Project = Project( id = beolProjectIri, shortname = Shortname.unsafeFrom("beol"), - shortcode = "0801", + shortcode = Shortcode.unsafeFrom("0801"), longname = Some("Bernoulli-Euler Online"), description = Seq(StringLiteralV2.from(value = "Bernoulli-Euler Online", language = None)), keywords = Seq.empty[String], @@ -732,7 +732,7 @@ object SharedTestDataADM { def dokubibProject: Project = Project( id = dokubibProjectIri, shortname = Shortname.unsafeFrom("dokubib"), - shortcode = "0804", + shortcode = Shortcode.unsafeFrom("0804"), longname = Some("Dokubib"), description = Seq(StringLiteralV2.from(value = "Dokubib", language = None)), keywords = Seq.empty[String], diff --git a/webapi/src/main/scala/org/knora/webapi/messages/StringFormatter.scala b/webapi/src/main/scala/org/knora/webapi/messages/StringFormatter.scala index 45a29961ad..003d11740c 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/StringFormatter.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/StringFormatter.scala @@ -1589,9 +1589,9 @@ class StringFormatter private ( * @param projectShortcode the project's shortcode. * @return a new resource IRI. */ - def makeRandomResourceIri(projectShortcode: String): IRI = { + def makeRandomResourceIri(shortcode: Shortcode): IRI = { val knoraResourceID = UuidUtil.makeRandomBase64EncodedUuid - s"http://$IriDomain/$projectShortcode/$knoraResourceID" + s"http://$IriDomain/${shortcode.value}/$knoraResourceID" } /** diff --git a/webapi/src/main/scala/org/knora/webapi/responders/v2/ResourceUtilV2.scala b/webapi/src/main/scala/org/knora/webapi/responders/v2/ResourceUtilV2.scala index 039d676977..6f5053fc20 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/v2/ResourceUtilV2.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/v2/ResourceUtilV2.scala @@ -228,7 +228,7 @@ final case class ResourceUtilV2Live(triplestore: TriplestoreService, sipiService sipiService.moveTemporaryFileToPermanentStorage( MoveTemporaryFileToPermanentStorageRequest( file.fileValue.internalFilename, - updateInProject.projectADM.shortcode, + updateInProject.projectADM.shortcode.value, requestingUser, ), ) diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala index 10e9834c84..ffa82ece99 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala @@ -26,6 +26,7 @@ import org.knora.webapi.slice.admin.domain.model.GroupStatus import org.knora.webapi.slice.admin.domain.model.KnoraProject.CopyrightAttribution import org.knora.webapi.slice.admin.domain.model.KnoraProject.License import org.knora.webapi.slice.admin.domain.model.KnoraProject.ProjectIri +import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortcode import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortname import org.knora.webapi.slice.admin.domain.model.User import org.knora.webapi.slice.admin.domain.model.UserIri @@ -88,7 +89,7 @@ object Examples { private val project: Project = Project( id = ProjectExample.projectIri.value, shortname = Shortname.unsafeFrom("example"), - shortcode = "0001", + shortcode = Shortcode.unsafeFrom("0001"), longname = Some("Example Project"), description = Seq(StringLiteralV2.from("An example project", Some("en"))), keywords = Seq("example", "project"), diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala index 69638938ae..c57e811fde 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala @@ -14,6 +14,7 @@ import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 import org.knora.webapi.slice.admin.api.Codecs.ZioJsonCodec.copyrightAttribution import org.knora.webapi.slice.admin.api.Codecs.ZioJsonCodec.license import org.knora.webapi.slice.admin.api.Codecs.ZioJsonCodec.shortname +import org.knora.webapi.slice.admin.api.Codecs.ZioJsonCodec.shortcode import org.knora.webapi.slice.admin.domain.model.KnoraProject.* import org.knora.webapi.slice.admin.domain.model.RestrictedView import org.knora.webapi.slice.admin.domain.model.User @@ -35,7 +36,7 @@ import org.knora.webapi.slice.admin.domain.model.User case class Project( id: IRI, shortname: Shortname, - shortcode: String, + shortcode: Shortcode, longname: Option[String], description: Seq[StringLiteralV2], keywords: Seq[String], @@ -49,8 +50,6 @@ case class Project( def projectIri: ProjectIri = ProjectIri.unsafeFrom(id) - def getShortcode: Shortcode = Shortcode.unsafeFrom(shortcode) - /** * Allows to sort collections of ProjectADM. Sorting is done by the id. */ diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala index bc68cb1ce1..c38609a76d 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala @@ -48,7 +48,7 @@ final case class ProjectService( Project( knoraProject.id.value, knoraProject.shortname, - knoraProject.shortcode.value, + knoraProject.shortcode, knoraProject.longname.map(_.value), knoraProject.description.map(_.value), knoraProject.keywords.map(_.value), @@ -65,7 +65,7 @@ final case class ProjectService( KnoraProject( id = ProjectIri.unsafeFrom(project.id), shortname = project.shortname, - shortcode = Shortcode.unsafeFrom(project.shortcode), + shortcode = project.shortcode, longname = project.longname.map(Longname.unsafeFrom), description = NonEmptyChunk .fromIterable(project.description.head, project.description.tail) @@ -97,10 +97,8 @@ object ProjectService { * @param project A [[ProjectADM]]. * @return the [[InternalIri]] of the project's data named graph. */ - def projectDataNamedGraphV2(project: Project): InternalIri = { - val shortcode = Shortcode.unsafeFrom(project.shortcode) - projectDataNamedGraphV2(shortcode, project.shortname) - } + def projectDataNamedGraphV2(project: Project): InternalIri = + projectDataNamedGraphV2(project.shortcode, project.shortname) /** * Given the [[KnoraProject]] constructs the project's data named graph. diff --git a/webapi/src/main/scala/org/knora/webapi/slice/common/ApiComplexV2JsonLdRequestParser.scala b/webapi/src/main/scala/org/knora/webapi/slice/common/ApiComplexV2JsonLdRequestParser.scala index e1aec3eb14..23f7593ece 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/common/ApiComplexV2JsonLdRequestParser.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/common/ApiComplexV2JsonLdRequestParser.scala @@ -242,9 +242,9 @@ final case class ApiComplexV2JsonLdRequestParser( project <- attachedToProject(r.resource) _ <- ZIO .fail("Resource IRI and project IRI must reference the same project") - .when(r.resourceIri.exists(_.shortcode != project.getShortcode)) + .when(r.resourceIri.exists(_.shortcode != project.shortcode)) attachedToUser <- attachedToUser(r.resource, requestingUser, project.projectIri) - values <- extractValues(r.resource, project.getShortcode, ingestState) + values <- extractValues(r.resource, project.shortcode, ingestState) } yield CreateResourceRequestV2( CreateResourceV2( r.resourceIri.map(_.smartIri), diff --git a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala index 61be50aa39..c99ef6a836 100644 --- a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala @@ -20,10 +20,10 @@ import org.knora.webapi.slice.resourceinfo.domain.IriTestConstants object ProjectServiceSpec extends ZIOSpecDefault { val spec: Spec[Any, Nothing] = - suite("projectDataNamedGraphV2 should return the data named graph of a project with shortcode for")( + suite("projectDataNamedGraphV2 shouldshortcodefor")( test("a ProjectADM") { val shortname = Shortname.unsafeFrom("someProject") - val shortcode = "0001" + val shortcode = Shortcode.unsafeFrom("0001") val p = Project( id = IriTestConstants.Project.TestProject, shortname = shortname, @@ -39,7 +39,9 @@ object ProjectServiceSpec extends ZIOSpecDefault { license = None, ) assertTrue( - ProjectService.projectDataNamedGraphV2(p).value == s"http://www.knora.org/data/$shortcode/${shortname.value}", + ProjectService + .projectDataNamedGraphV2(p) + .value == s"http://www.knora.org/data/${shortcode.value}/${shortname.value}", ) }, test("a KnoraProject") { From 209af475a73fd49b093f97336f28f9b1955debd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinb=C3=B6lting?= Date: Fri, 15 Nov 2024 17:53:46 +0100 Subject: [PATCH 12/18] refactor: Make Project.longname typed --- .../IntegrationTestAdminJsonProtocol.scala | 5 +++++ .../webapi/sharedtestdata/ProjectInfo.scala | 2 +- .../sharedtestdata/SharedTestDataADM.scala | 21 ++++++++++--------- .../webapi/slice/admin/api/Examples.scala | 3 ++- .../admin/api/model/ProjectsMessagesADM.scala | 7 ++----- .../admin/domain/service/ProjectService.scala | 4 ++-- 6 files changed, 23 insertions(+), 19 deletions(-) diff --git a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala index b95941ae5d..928dbd7689 100644 --- a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala +++ b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala @@ -46,6 +46,7 @@ import org.knora.webapi.slice.admin.api.model.ProjectOperationResponseADM import org.knora.webapi.slice.admin.domain.model.Group import org.knora.webapi.slice.admin.domain.model.KnoraProject.CopyrightAttribution import org.knora.webapi.slice.admin.domain.model.KnoraProject.License +import org.knora.webapi.slice.admin.domain.model.KnoraProject.Longname import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortcode import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortname import org.knora.webapi.slice.admin.domain.model.User @@ -222,6 +223,10 @@ object IntegrationTestAdminJsonProtocol extends TriplestoreJsonProtocol { override val from: String => Either[String, Shortcode] = Shortcode.from } + implicit object LongnameFormat extends StringValueFormat[Longname] { + override val from: String => Either[String, Longname] = Longname.from + } + implicit val groupFormat: JsonFormat[Group] = jsonFormat6(Group.apply) implicit val projectAdminMembersGetResponseADMFormat: RootJsonFormat[ProjectAdminMembersGetResponseADM] = rootFormat( diff --git a/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala b/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala index e80630d15e..a9358038c5 100644 --- a/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala +++ b/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala @@ -40,7 +40,7 @@ object ProjectInfo { id = project.id, shortname = project.shortname.value, shortcode = project.shortcode.value, - longname = project.longname, + longname = project.longname.map(_.value), description = project.description.headOption.map(_.value), keywords = project.keywords.headOption.map(_ => project.keywords.mkString(", ")), logo = project.logo, diff --git a/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala b/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala index de70ae2409..62eb471830 100644 --- a/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala +++ b/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala @@ -15,6 +15,7 @@ import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 import org.knora.webapi.messages.util.KnoraSystemInstances import org.knora.webapi.slice.admin.api.model.Project import org.knora.webapi.slice.admin.domain.model.Group +import org.knora.webapi.slice.admin.domain.model.KnoraProject.Longname import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortcode import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortname import org.knora.webapi.slice.admin.domain.model.Permission @@ -158,7 +159,7 @@ object SharedTestDataADM { id = KnoraProjectRepo.builtIn.SystemProject.id.value, shortname = Shortname.unsafeFrom("SystemProject"), shortcode = Shortcode.unsafeFrom("FFFF"), - longname = Some("Knora System Project"), + longname = Some(Longname.unsafeFrom("Knora System Project")), description = Seq(StringLiteralV2.from(value = "Knora System Project", language = Some("en"))), keywords = Seq.empty[String], logo = None, @@ -179,7 +180,7 @@ object SharedTestDataADM { id = OntologyConstants.KnoraAdmin.DefaultSharedOntologiesProject, shortname = Shortname.unsafeFrom("DefaultSharedOntologiesProject"), shortcode = Shortcode.unsafeFrom("0000"), - longname = Some("Default Knora Shared Ontologies Project"), + longname = Some(Longname.unsafeFrom("Default Knora Shared Ontologies Project")), description = Seq(StringLiteralV2.from(value = "Default Knora Shared Ontologies Project", language = Some("en"))), keywords = Seq.empty[String], logo = None, @@ -293,7 +294,7 @@ object SharedTestDataADM { id = imagesProjectIri, shortname = Shortname.unsafeFrom("images"), shortcode = Shortcode.unsafeFrom("00FF"), - longname = Some("Image Collection Demo"), + longname = Some(Longname.unsafeFrom("Image Collection Demo")), description = Seq(StringLiteralV2.from(value = "A demo project of a collection of images", language = Some("en"))), keywords = Seq("images", "collection").sorted, logo = None, @@ -309,7 +310,7 @@ object SharedTestDataADM { id = imagesProjectIri, shortname = Shortname.unsafeFrom("images"), shortcode = Shortcode.unsafeFrom("00FF"), - longname = Some("Image Collection Demo"), + longname = Some(Longname.unsafeFrom("Image Collection Demo")), description = Seq(StringLiteralV2.from(value = "A demo project of a collection of images", language = Some("en"))), keywords = Seq("images", "collection").sorted, logo = None, @@ -453,7 +454,7 @@ object SharedTestDataADM { id = incunabulaProjectIri, shortname = Shortname.unsafeFrom("incunabula"), shortcode = Shortcode.unsafeFrom("0803"), - longname = Some("Bilderfolgen Basler Frühdrucke"), + longname = Some(Longname.unsafeFrom("Bilderfolgen Basler Frühdrucke")), description = Seq( StringLiteralV2.from( value = @@ -490,7 +491,7 @@ object SharedTestDataADM { id = incunabulaProjectIri, shortname = Shortname.unsafeFrom("incunabula"), shortcode = Shortcode.unsafeFrom("0803"), - longname = Some("Bilderfolgen Basler Frühdrucke"), + longname = Some(Longname.unsafeFrom("Bilderfolgen Basler Frühdrucke")), description = Seq( StringLiteralV2.from( value = @@ -625,7 +626,7 @@ object SharedTestDataADM { id = anythingProjectIri, shortname = Shortname.unsafeFrom("anything"), shortcode = Shortcode.unsafeFrom("0001"), - longname = Some("Anything Project"), + longname = Some(Longname.unsafeFrom("Anything Project")), description = Seq(StringLiteralV2.from(value = "Anything Project", language = None)), keywords = Seq("things", "arbitrary test data").sorted, logo = None, @@ -640,7 +641,7 @@ object SharedTestDataADM { id = anythingProjectIri, shortname = Shortname.unsafeFrom("anything"), shortcode = Shortcode.unsafeFrom("0001"), - longname = Some("Anything Project"), + longname = Some(Longname.unsafeFrom("Anything Project")), description = Seq(StringLiteralV2.from(value = "Anything Project", language = None)), keywords = Seq("things", "arbitrary test data").sorted, logo = None, @@ -677,7 +678,7 @@ object SharedTestDataADM { id = beolProjectIri, shortname = Shortname.unsafeFrom("beol"), shortcode = Shortcode.unsafeFrom("0801"), - longname = Some("Bernoulli-Euler Online"), + longname = Some(Longname.unsafeFrom("Bernoulli-Euler Online")), description = Seq(StringLiteralV2.from(value = "Bernoulli-Euler Online", language = None)), keywords = Seq.empty[String], logo = None, @@ -733,7 +734,7 @@ object SharedTestDataADM { id = dokubibProjectIri, shortname = Shortname.unsafeFrom("dokubib"), shortcode = Shortcode.unsafeFrom("0804"), - longname = Some("Dokubib"), + longname = Some(Longname.unsafeFrom("Dokubib")), description = Seq(StringLiteralV2.from(value = "Dokubib", language = None)), keywords = Seq.empty[String], logo = None, diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala index ffa82ece99..1cccf78209 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala @@ -25,6 +25,7 @@ import org.knora.webapi.slice.admin.domain.model.GroupSelfJoin import org.knora.webapi.slice.admin.domain.model.GroupStatus import org.knora.webapi.slice.admin.domain.model.KnoraProject.CopyrightAttribution import org.knora.webapi.slice.admin.domain.model.KnoraProject.License +import org.knora.webapi.slice.admin.domain.model.KnoraProject.Longname import org.knora.webapi.slice.admin.domain.model.KnoraProject.ProjectIri import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortcode import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortname @@ -90,7 +91,7 @@ object Examples { id = ProjectExample.projectIri.value, shortname = Shortname.unsafeFrom("example"), shortcode = Shortcode.unsafeFrom("0001"), - longname = Some("Example Project"), + longname = Some(Longname.unsafeFrom("Example Project")), description = Seq(StringLiteralV2.from("An example project", Some("en"))), keywords = Seq("example", "project"), logo = None, diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala index c57e811fde..b259dd1e4d 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala @@ -11,10 +11,7 @@ import zio.json.JsonCodec import org.knora.webapi.IRI import org.knora.webapi.messages.admin.responder.AdminKnoraResponseADM import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 -import org.knora.webapi.slice.admin.api.Codecs.ZioJsonCodec.copyrightAttribution -import org.knora.webapi.slice.admin.api.Codecs.ZioJsonCodec.license -import org.knora.webapi.slice.admin.api.Codecs.ZioJsonCodec.shortname -import org.knora.webapi.slice.admin.api.Codecs.ZioJsonCodec.shortcode +import org.knora.webapi.slice.admin.api.Codecs.ZioJsonCodec.* import org.knora.webapi.slice.admin.domain.model.KnoraProject.* import org.knora.webapi.slice.admin.domain.model.RestrictedView import org.knora.webapi.slice.admin.domain.model.User @@ -37,7 +34,7 @@ case class Project( id: IRI, shortname: Shortname, shortcode: Shortcode, - longname: Option[String], + longname: Option[Longname], description: Seq[StringLiteralV2], keywords: Seq[String], logo: Option[String], diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala index c38609a76d..da4183a29d 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala @@ -49,7 +49,7 @@ final case class ProjectService( knoraProject.id.value, knoraProject.shortname, knoraProject.shortcode, - knoraProject.longname.map(_.value), + knoraProject.longname, knoraProject.description.map(_.value), knoraProject.keywords.map(_.value), knoraProject.logo.map(_.value), @@ -66,7 +66,7 @@ final case class ProjectService( id = ProjectIri.unsafeFrom(project.id), shortname = project.shortname, shortcode = project.shortcode, - longname = project.longname.map(Longname.unsafeFrom), + longname = project.longname, description = NonEmptyChunk .fromIterable(project.description.head, project.description.tail) .map(Description.unsafeFrom), From 3fb6603c7a1c7707324d69f4311fde32a0f9d8aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinb=C3=B6lting?= Date: Fri, 15 Nov 2024 17:56:08 +0100 Subject: [PATCH 13/18] refactor: Make Project.logo typed --- .../admin/responder/IntegrationTestAdminJsonProtocol.scala | 5 +++++ .../scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala | 2 +- .../org/knora/webapi/sharedtestdata/SharedTestDataADM.scala | 5 +++-- .../webapi/slice/admin/api/model/ProjectsMessagesADM.scala | 2 +- .../webapi/slice/admin/domain/service/ProjectService.scala | 4 ++-- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala index 928dbd7689..b62cd3b10c 100644 --- a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala +++ b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala @@ -46,6 +46,7 @@ import org.knora.webapi.slice.admin.api.model.ProjectOperationResponseADM import org.knora.webapi.slice.admin.domain.model.Group import org.knora.webapi.slice.admin.domain.model.KnoraProject.CopyrightAttribution import org.knora.webapi.slice.admin.domain.model.KnoraProject.License +import org.knora.webapi.slice.admin.domain.model.KnoraProject.Logo import org.knora.webapi.slice.admin.domain.model.KnoraProject.Longname import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortcode import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortname @@ -227,6 +228,10 @@ object IntegrationTestAdminJsonProtocol extends TriplestoreJsonProtocol { override val from: String => Either[String, Longname] = Longname.from } + implicit object LogoFormat extends StringValueFormat[Logo] { + override val from: String => Either[String, Logo] = Logo.from + } + implicit val groupFormat: JsonFormat[Group] = jsonFormat6(Group.apply) implicit val projectAdminMembersGetResponseADMFormat: RootJsonFormat[ProjectAdminMembersGetResponseADM] = rootFormat( diff --git a/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala b/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala index a9358038c5..b3aff19c8e 100644 --- a/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala +++ b/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala @@ -43,7 +43,7 @@ object ProjectInfo { longname = project.longname.map(_.value), description = project.description.headOption.map(_.value), keywords = project.keywords.headOption.map(_ => project.keywords.mkString(", ")), - logo = project.logo, + logo = project.logo.map(_.value), ontologies = project.ontologies, status = project.status, selfjoin = project.selfjoin, diff --git a/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala b/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala index 62eb471830..1f0b5a036e 100644 --- a/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala +++ b/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala @@ -15,6 +15,7 @@ import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 import org.knora.webapi.messages.util.KnoraSystemInstances import org.knora.webapi.slice.admin.api.model.Project import org.knora.webapi.slice.admin.domain.model.Group +import org.knora.webapi.slice.admin.domain.model.KnoraProject.Logo import org.knora.webapi.slice.admin.domain.model.KnoraProject.Longname import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortcode import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortname @@ -478,7 +479,7 @@ object SharedTestDataADM { "Basel", "Contectualisation of images", ).sorted, - logo = Some("incunabula_logo.png"), + logo = Some(Logo.unsafeFrom("incunabula_logo.png")), ontologies = Seq(SharedOntologyTestDataADM.INCUNABULA_ONTOLOGY_IRI), status = true, selfjoin = false, @@ -515,7 +516,7 @@ object SharedTestDataADM { "Basel", "Contectualisation of images", ).sorted, - logo = Some("incunabula_logo.png"), + logo = Some(Logo.unsafeFrom("incunabula_logo.png")), ontologies = Seq(SharedOntologyTestDataADM.INCUNABULA_ONTOLOGY_IRI_LocalHost), status = true, selfjoin = false, diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala index b259dd1e4d..bc39ef8e28 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala @@ -37,7 +37,7 @@ case class Project( longname: Option[Longname], description: Seq[StringLiteralV2], keywords: Seq[String], - logo: Option[String], + logo: Option[Logo], ontologies: Seq[IRI], status: Boolean, selfjoin: Boolean, diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala index da4183a29d..f474b748d5 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala @@ -52,7 +52,7 @@ final case class ProjectService( knoraProject.longname, knoraProject.description.map(_.value), knoraProject.keywords.map(_.value), - knoraProject.logo.map(_.value), + knoraProject.logo, ontologies, knoraProject.status.value, knoraProject.selfjoin.value, @@ -71,7 +71,7 @@ final case class ProjectService( .fromIterable(project.description.head, project.description.tail) .map(Description.unsafeFrom), keywords = project.keywords.map(Keyword.unsafeFrom).toList, - logo = project.logo.map(Logo.unsafeFrom), + logo = project.logo, status = Status.from(project.status), selfjoin = SelfJoin.from(project.selfjoin), restrictedView, From 48f6180db20068d45b655ec4b0e55bca745887c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinb=C3=B6lting?= Date: Fri, 15 Nov 2024 18:04:23 +0100 Subject: [PATCH 14/18] refactor: Make Project.selfjoin typed --- .../webapi/e2e/admin/ProjectsADME2ESpec.scala | 6 ++-- .../IntegrationTestAdminJsonProtocol.scala | 14 +++++++++ .../admin/ProjectRestServiceSpec.scala | 2 +- .../webapi/sharedtestdata/ProjectInfo.scala | 2 +- .../sharedtestdata/SharedTestDataADM.scala | 29 ++++++++++--------- .../webapi/slice/admin/api/Examples.scala | 3 +- .../admin/api/model/ProjectsMessagesADM.scala | 2 +- .../admin/domain/service/ProjectService.scala | 4 +-- .../domain/service/ProjectServiceSpec.scala | 2 +- 9 files changed, 40 insertions(+), 24 deletions(-) diff --git a/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2ESpec.scala b/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2ESpec.scala index c651e0cff7..dd8db41e8f 100644 --- a/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2ESpec.scala +++ b/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2ESpec.scala @@ -19,7 +19,6 @@ import java.net.URLEncoder import scala.concurrent.Await import scala.concurrent.Future import scala.concurrent.duration.* - import org.knora.webapi.E2ESpec import org.knora.webapi.IRI import org.knora.webapi.messages.admin.responder.IntegrationTestAdminJsonProtocol.* @@ -29,6 +28,7 @@ import org.knora.webapi.messages.util.rdf.RdfModel import org.knora.webapi.sharedtestdata.SharedTestDataADM import org.knora.webapi.slice.admin.api.model.* import org.knora.webapi.slice.admin.api.model.ProjectMembersGetResponseADM +import org.knora.webapi.slice.admin.domain.model.KnoraProject.SelfJoin import org.knora.webapi.slice.admin.domain.model.User import org.knora.webapi.util.AkkaHttpUtils import org.knora.webapi.util.MutableTestIri @@ -236,7 +236,7 @@ class ProjectsADME2ESpec extends E2ESpec with SprayJsonSupport { result.keywords should be(Seq("keywords")) result.logo should be(Some("/fu/bar/baz.jpg")) result.status should be(true) - result.selfjoin should be(false) + result.selfjoin should be(SelfJoin.CannotJoin) newProjectIri.set(result.id) } @@ -363,7 +363,7 @@ class ProjectsADME2ESpec extends E2ESpec with SprayJsonSupport { result.keywords.sorted should be(Seq("updated", "keywords").sorted) result.logo should be(Some("/fu/bar/baz-updated.jpg")) result.status should be(true) - result.selfjoin should be(true) + result.selfjoin should be(SelfJoin.CanJoin) } "UPDATE a project with multi-language description" in { diff --git a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala index b62cd3b10c..991d7faeab 100644 --- a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala +++ b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala @@ -48,9 +48,11 @@ import org.knora.webapi.slice.admin.domain.model.KnoraProject.CopyrightAttributi import org.knora.webapi.slice.admin.domain.model.KnoraProject.License import org.knora.webapi.slice.admin.domain.model.KnoraProject.Logo import org.knora.webapi.slice.admin.domain.model.KnoraProject.Longname +import org.knora.webapi.slice.admin.domain.model.KnoraProject.SelfJoin import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortcode import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortname import org.knora.webapi.slice.admin.domain.model.User +import org.knora.webapi.slice.common.Value.BooleanValue import org.knora.webapi.slice.common.Value.StringValue /** @@ -232,6 +234,18 @@ object IntegrationTestAdminJsonProtocol extends TriplestoreJsonProtocol { override val from: String => Either[String, Logo] = Logo.from } + trait BooleanValueFormat[T <: BooleanValue] extends JsonFormat[T] { self => + def from: Boolean => Either[String, T] + override def write(v: T): JsValue = JsString(v.value.toString) + override def read(json: JsValue): T = json match + case JsBoolean(bool) => self.from(bool).fold(err => throw DeserializationException(err), identity) + case _ => throw DeserializationException("Must be a json Boolean") + } + + implicit object SelfJoinValueFormat extends BooleanValueFormat[SelfJoin] { + override val from: Boolean => Either[String, SelfJoin] = b => Right(SelfJoin.from(b)) + } + implicit val groupFormat: JsonFormat[Group] = jsonFormat6(Group.apply) implicit val projectAdminMembersGetResponseADMFormat: RootJsonFormat[ProjectAdminMembersGetResponseADM] = rootFormat( diff --git a/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala b/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala index f3d2e0101e..81664b9293 100644 --- a/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala @@ -411,7 +411,7 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { received.project.keywords.sorted should be(Seq("updated", "keywords").sorted) received.project.logo should be(Some("/fu/bar/baz-updated.jpg")) received.project.status should be(true) - received.project.selfjoin should be(true) + received.project.selfjoin should be(SelfJoin.CanJoin) } "return 'NotFound' if a not existing project IRI is submitted during update" in { diff --git a/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala b/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala index b3aff19c8e..26a92aa4de 100644 --- a/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala +++ b/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala @@ -46,6 +46,6 @@ object ProjectInfo { logo = project.logo.map(_.value), ontologies = project.ontologies, status = project.status, - selfjoin = project.selfjoin, + selfjoin = project.selfjoin.value, ) } diff --git a/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala b/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala index 1f0b5a036e..a4c47daf80 100644 --- a/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala +++ b/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala @@ -17,6 +17,7 @@ import org.knora.webapi.slice.admin.api.model.Project import org.knora.webapi.slice.admin.domain.model.Group import org.knora.webapi.slice.admin.domain.model.KnoraProject.Logo import org.knora.webapi.slice.admin.domain.model.KnoraProject.Longname +import org.knora.webapi.slice.admin.domain.model.KnoraProject.SelfJoin import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortcode import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortname import org.knora.webapi.slice.admin.domain.model.Permission @@ -171,7 +172,7 @@ object SharedTestDataADM { OntologyConstants.Standoff.StandoffOntologyIri, ), status = true, - selfjoin = false, + selfjoin = SelfJoin.CannotJoin, copyrightAttribution = None, license = None, ) @@ -187,7 +188,7 @@ object SharedTestDataADM { logo = None, ontologies = Seq.empty[IRI], status = true, - selfjoin = false, + selfjoin = SelfJoin.CannotJoin, copyrightAttribution = None, license = None, ) @@ -301,7 +302,7 @@ object SharedTestDataADM { logo = None, ontologies = Seq(SharedOntologyTestDataADM.IMAGES_ONTOLOGY_IRI), status = true, - selfjoin = false, + selfjoin = SelfJoin.CannotJoin, copyrightAttribution = None, license = None, ) @@ -317,7 +318,7 @@ object SharedTestDataADM { logo = None, ontologies = Seq(SharedOntologyTestDataADM.IMAGES_ONTOLOGY_IRI_LocalHost), status = true, - selfjoin = false, + selfjoin = SelfJoin.CannotJoin, copyrightAttribution = None, license = None, ) @@ -329,7 +330,7 @@ object SharedTestDataADM { descriptions = Seq(StringLiteralV2.from(value = "Default Project Admin Group", language = Some("en"))), project = Some(imagesProject), status = true, - selfjoin = false, + selfjoin = SelfJoin.CannotJoin, ) /* represents the full GroupADM of the images ProjectMember group */ @@ -339,7 +340,7 @@ object SharedTestDataADM { descriptions = Seq(StringLiteralV2.from(value = "Default Project Member Group", language = Some("en"))), project = Some(imagesProject), status = true, - selfjoin = false, + selfjoin = SelfJoin.CannotJoin, ) /* represents the full GroupADM of the images project reviewer group */ @@ -349,7 +350,7 @@ object SharedTestDataADM { descriptions = Seq(StringLiteralV2.from(value = "A group for image reviewers.", language = Some("en"))), project = Some(imagesProject), status = true, - selfjoin = false, + selfjoin = SelfJoin.CannotJoin, ) /* represents the full GroupADM of the images project reviewer group in the external format*/ @@ -359,7 +360,7 @@ object SharedTestDataADM { descriptions = Seq(StringLiteralV2.from(value = "A group for image reviewers.", language = Some("en"))), project = Some(imagesProjectExternal), status = true, - selfjoin = false, + selfjoin = SelfJoin.CannotJoin, ) /** @@ -482,7 +483,7 @@ object SharedTestDataADM { logo = Some(Logo.unsafeFrom("incunabula_logo.png")), ontologies = Seq(SharedOntologyTestDataADM.INCUNABULA_ONTOLOGY_IRI), status = true, - selfjoin = false, + selfjoin = SelfJoin.CannotJoin, copyrightAttribution = None, license = None, ) @@ -519,7 +520,7 @@ object SharedTestDataADM { logo = Some(Logo.unsafeFrom("incunabula_logo.png")), ontologies = Seq(SharedOntologyTestDataADM.INCUNABULA_ONTOLOGY_IRI_LocalHost), status = true, - selfjoin = false, + selfjoin = SelfJoin.CannotJoin, copyrightAttribution = None, license = None, ) @@ -633,7 +634,7 @@ object SharedTestDataADM { logo = None, ontologies = Seq(SharedOntologyTestDataADM.ANYTHING_ONTOLOGY_IRI, SharedOntologyTestDataADM.SomethingOntologyIri), status = true, - selfjoin = false, + selfjoin = SelfJoin.CannotJoin, copyrightAttribution = None, license = None, ) @@ -651,7 +652,7 @@ object SharedTestDataADM { SharedOntologyTestDataADM.SomethingOntologyIriLocalhost, ), status = true, - selfjoin = false, + selfjoin = SelfJoin.CannotJoin, copyrightAttribution = None, license = None, ) @@ -690,7 +691,7 @@ object SharedTestDataADM { "http://www.knora.org/ontology/0801/newton", ), status = true, - selfjoin = false, + selfjoin = SelfJoin.CannotJoin, copyrightAttribution = None, license = None, ) @@ -741,7 +742,7 @@ object SharedTestDataADM { logo = None, ontologies = Seq("http://www.knora.org/ontology/0804/dokubib"), status = false, - selfjoin = false, + selfjoin = SelfJoin.CannotJoin, copyrightAttribution = None, license = None, ) diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala index 1cccf78209..2ebf48cc4c 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala @@ -27,6 +27,7 @@ import org.knora.webapi.slice.admin.domain.model.KnoraProject.CopyrightAttributi import org.knora.webapi.slice.admin.domain.model.KnoraProject.License import org.knora.webapi.slice.admin.domain.model.KnoraProject.Longname import org.knora.webapi.slice.admin.domain.model.KnoraProject.ProjectIri +import org.knora.webapi.slice.admin.domain.model.KnoraProject.SelfJoin.CannotJoin import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortcode import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortname import org.knora.webapi.slice.admin.domain.model.User @@ -97,7 +98,7 @@ object Examples { logo = None, status = true, ontologies = Seq.empty, - selfjoin = false, + selfjoin = CannotJoin, copyrightAttribution = Some(CopyrightAttribution.unsafeFrom("2024, Example Project")), license = Some(License.unsafeFrom("CC-BY-4.0")), ) diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala index bc39ef8e28..e2cc59063e 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala @@ -40,7 +40,7 @@ case class Project( logo: Option[Logo], ontologies: Seq[IRI], status: Boolean, - selfjoin: Boolean, + selfjoin: SelfJoin, copyrightAttribution: Option[CopyrightAttribution], license: Option[License], ) extends Ordered[Project] { diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala index f474b748d5..2c1741d341 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala @@ -55,7 +55,7 @@ final case class ProjectService( knoraProject.logo, ontologies, knoraProject.status.value, - knoraProject.selfjoin.value, + knoraProject.selfjoin, knoraProject.copyrightAttribution, knoraProject.license, ), @@ -73,7 +73,7 @@ final case class ProjectService( keywords = project.keywords.map(Keyword.unsafeFrom).toList, logo = project.logo, status = Status.from(project.status), - selfjoin = SelfJoin.from(project.selfjoin), + selfjoin = project.selfjoin, restrictedView, project.copyrightAttribution, project.license, diff --git a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala index c99ef6a836..696586a958 100644 --- a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala @@ -34,7 +34,7 @@ object ProjectServiceSpec extends ZIOSpecDefault { logo = None, ontologies = List.empty, status = true, - selfjoin = true, + selfjoin = SelfJoin.CanJoin, copyrightAttribution = None, license = None, ) From c564346524afcd1f5e1922ec64702e1d566a2467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinb=C3=B6lting?= Date: Fri, 15 Nov 2024 18:11:33 +0100 Subject: [PATCH 15/18] refactor: Make Project.status typed --- .../webapi/e2e/admin/ProjectsADME2ESpec.scala | 10 +++---- .../IntegrationTestAdminJsonProtocol.scala | 11 +++++-- .../admin/ProjectRestServiceSpec.scala | 2 +- .../webapi/sharedtestdata/ProjectInfo.scala | 2 +- .../sharedtestdata/SharedTestDataADM.scala | 29 ++++++++++--------- .../webapi/slice/admin/api/Examples.scala | 3 +- .../admin/api/model/ProjectsMessagesADM.scala | 2 +- .../admin/domain/service/ProjectService.scala | 4 +-- .../domain/service/ProjectServiceSpec.scala | 2 +- 9 files changed, 36 insertions(+), 29 deletions(-) diff --git a/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2ESpec.scala b/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2ESpec.scala index dd8db41e8f..cc47c928cd 100644 --- a/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2ESpec.scala +++ b/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2ESpec.scala @@ -29,6 +29,7 @@ import org.knora.webapi.sharedtestdata.SharedTestDataADM import org.knora.webapi.slice.admin.api.model.* import org.knora.webapi.slice.admin.api.model.ProjectMembersGetResponseADM import org.knora.webapi.slice.admin.domain.model.KnoraProject.SelfJoin +import org.knora.webapi.slice.admin.domain.model.KnoraProject.Status import org.knora.webapi.slice.admin.domain.model.User import org.knora.webapi.util.AkkaHttpUtils import org.knora.webapi.util.MutableTestIri @@ -235,7 +236,7 @@ class ProjectsADME2ESpec extends E2ESpec with SprayJsonSupport { result.description should be(Seq(StringLiteralV2.from(value = "project description", language = Some("en")))) result.keywords should be(Seq("keywords")) result.logo should be(Some("/fu/bar/baz.jpg")) - result.status should be(true) + result.status should be(Status.Active) result.selfjoin should be(SelfJoin.CannotJoin) newProjectIri.set(result.id) @@ -362,7 +363,7 @@ class ProjectsADME2ESpec extends E2ESpec with SprayJsonSupport { ) result.keywords.sorted should be(Seq("updated", "keywords").sorted) result.logo should be(Some("/fu/bar/baz-updated.jpg")) - result.status should be(true) + result.status should be(Status.Active) result.selfjoin should be(SelfJoin.CanJoin) } @@ -398,7 +399,7 @@ class ProjectsADME2ESpec extends E2ESpec with SprayJsonSupport { response.status should be(StatusCodes.OK) val result: Project = AkkaHttpUtils.httpResponseToJson(response).fields("project").convertTo[Project] - result.status should be(false) + result.status should be(Status.Inactive) } } @@ -411,8 +412,7 @@ class ProjectsADME2ESpec extends E2ESpec with SprayJsonSupport { assert(response.status === StatusCodes.OK) val jsObject = AkkaHttpUtils.httpResponseToJson(response) val prjMembersResp = jsonReader[ProjectMembersGetResponseADM].read(jsObject) -// val prjMembersResp = jsObject.convertTo[ProjectMembersGetResponseADM] - val members = prjMembersResp.members + val members = prjMembersResp.members members.size should be(4) } diff --git a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala index 991d7faeab..0a99e53455 100644 --- a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala +++ b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala @@ -51,6 +51,7 @@ import org.knora.webapi.slice.admin.domain.model.KnoraProject.Longname import org.knora.webapi.slice.admin.domain.model.KnoraProject.SelfJoin import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortcode import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortname +import org.knora.webapi.slice.admin.domain.model.KnoraProject.Status import org.knora.webapi.slice.admin.domain.model.User import org.knora.webapi.slice.common.Value.BooleanValue import org.knora.webapi.slice.common.Value.StringValue @@ -235,15 +236,19 @@ object IntegrationTestAdminJsonProtocol extends TriplestoreJsonProtocol { } trait BooleanValueFormat[T <: BooleanValue] extends JsonFormat[T] { self => - def from: Boolean => Either[String, T] + def from: Boolean => T override def write(v: T): JsValue = JsString(v.value.toString) override def read(json: JsValue): T = json match - case JsBoolean(bool) => self.from(bool).fold(err => throw DeserializationException(err), identity) + case JsBoolean(bool) => self.from(bool) case _ => throw DeserializationException("Must be a json Boolean") } implicit object SelfJoinValueFormat extends BooleanValueFormat[SelfJoin] { - override val from: Boolean => Either[String, SelfJoin] = b => Right(SelfJoin.from(b)) + override val from: Boolean => SelfJoin = SelfJoin.from + } + + implicit object StatusFormat extends BooleanValueFormat[Status] { + override val from: Boolean => Status = Status.from } implicit val groupFormat: JsonFormat[Group] = jsonFormat6(Group.apply) diff --git a/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala b/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala index 81664b9293..4f4430d0c9 100644 --- a/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala @@ -410,7 +410,7 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { ) received.project.keywords.sorted should be(Seq("updated", "keywords").sorted) received.project.logo should be(Some("/fu/bar/baz-updated.jpg")) - received.project.status should be(true) + received.project.status should be(Status.Active) received.project.selfjoin should be(SelfJoin.CanJoin) } diff --git a/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala b/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala index 26a92aa4de..686a89a398 100644 --- a/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala +++ b/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala @@ -45,7 +45,7 @@ object ProjectInfo { keywords = project.keywords.headOption.map(_ => project.keywords.mkString(", ")), logo = project.logo.map(_.value), ontologies = project.ontologies, - status = project.status, + status = project.status.value, selfjoin = project.selfjoin.value, ) } diff --git a/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala b/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala index a4c47daf80..db866f5097 100644 --- a/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala +++ b/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala @@ -20,6 +20,7 @@ import org.knora.webapi.slice.admin.domain.model.KnoraProject.Longname import org.knora.webapi.slice.admin.domain.model.KnoraProject.SelfJoin import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortcode import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortname +import org.knora.webapi.slice.admin.domain.model.KnoraProject.Status import org.knora.webapi.slice.admin.domain.model.Permission import org.knora.webapi.slice.admin.domain.model.User import org.knora.webapi.slice.admin.domain.service.KnoraGroupRepo @@ -171,7 +172,7 @@ object SharedTestDataADM { SalsahGui.SalsahGuiOntologyIri, OntologyConstants.Standoff.StandoffOntologyIri, ), - status = true, + status = Status.Active, selfjoin = SelfJoin.CannotJoin, copyrightAttribution = None, license = None, @@ -187,7 +188,7 @@ object SharedTestDataADM { keywords = Seq.empty[String], logo = None, ontologies = Seq.empty[IRI], - status = true, + status = Status.Active, selfjoin = SelfJoin.CannotJoin, copyrightAttribution = None, license = None, @@ -301,7 +302,7 @@ object SharedTestDataADM { keywords = Seq("images", "collection").sorted, logo = None, ontologies = Seq(SharedOntologyTestDataADM.IMAGES_ONTOLOGY_IRI), - status = true, + status = Status.Active, selfjoin = SelfJoin.CannotJoin, copyrightAttribution = None, license = None, @@ -317,7 +318,7 @@ object SharedTestDataADM { keywords = Seq("images", "collection").sorted, logo = None, ontologies = Seq(SharedOntologyTestDataADM.IMAGES_ONTOLOGY_IRI_LocalHost), - status = true, + status = Status.Active, selfjoin = SelfJoin.CannotJoin, copyrightAttribution = None, license = None, @@ -330,7 +331,7 @@ object SharedTestDataADM { descriptions = Seq(StringLiteralV2.from(value = "Default Project Admin Group", language = Some("en"))), project = Some(imagesProject), status = true, - selfjoin = SelfJoin.CannotJoin, + selfjoin = false, ) /* represents the full GroupADM of the images ProjectMember group */ @@ -340,7 +341,7 @@ object SharedTestDataADM { descriptions = Seq(StringLiteralV2.from(value = "Default Project Member Group", language = Some("en"))), project = Some(imagesProject), status = true, - selfjoin = SelfJoin.CannotJoin, + selfjoin = false, ) /* represents the full GroupADM of the images project reviewer group */ @@ -350,7 +351,7 @@ object SharedTestDataADM { descriptions = Seq(StringLiteralV2.from(value = "A group for image reviewers.", language = Some("en"))), project = Some(imagesProject), status = true, - selfjoin = SelfJoin.CannotJoin, + selfjoin = false, ) /* represents the full GroupADM of the images project reviewer group in the external format*/ @@ -360,7 +361,7 @@ object SharedTestDataADM { descriptions = Seq(StringLiteralV2.from(value = "A group for image reviewers.", language = Some("en"))), project = Some(imagesProjectExternal), status = true, - selfjoin = SelfJoin.CannotJoin, + selfjoin = false, ) /** @@ -482,7 +483,7 @@ object SharedTestDataADM { ).sorted, logo = Some(Logo.unsafeFrom("incunabula_logo.png")), ontologies = Seq(SharedOntologyTestDataADM.INCUNABULA_ONTOLOGY_IRI), - status = true, + status = Status.Active, selfjoin = SelfJoin.CannotJoin, copyrightAttribution = None, license = None, @@ -519,7 +520,7 @@ object SharedTestDataADM { ).sorted, logo = Some(Logo.unsafeFrom("incunabula_logo.png")), ontologies = Seq(SharedOntologyTestDataADM.INCUNABULA_ONTOLOGY_IRI_LocalHost), - status = true, + status = Status.Active, selfjoin = SelfJoin.CannotJoin, copyrightAttribution = None, license = None, @@ -633,7 +634,7 @@ object SharedTestDataADM { keywords = Seq("things", "arbitrary test data").sorted, logo = None, ontologies = Seq(SharedOntologyTestDataADM.ANYTHING_ONTOLOGY_IRI, SharedOntologyTestDataADM.SomethingOntologyIri), - status = true, + status = Status.Active, selfjoin = SelfJoin.CannotJoin, copyrightAttribution = None, license = None, @@ -651,7 +652,7 @@ object SharedTestDataADM { SharedOntologyTestDataADM.ANYTHING_ONTOLOGY_IRI_LocalHost, SharedOntologyTestDataADM.SomethingOntologyIriLocalhost, ), - status = true, + status = Status.Active, selfjoin = SelfJoin.CannotJoin, copyrightAttribution = None, license = None, @@ -690,7 +691,7 @@ object SharedTestDataADM { "http://www.knora.org/ontology/0801/leibniz", "http://www.knora.org/ontology/0801/newton", ), - status = true, + status = Status.Active, selfjoin = SelfJoin.CannotJoin, copyrightAttribution = None, license = None, @@ -741,7 +742,7 @@ object SharedTestDataADM { keywords = Seq.empty[String], logo = None, ontologies = Seq("http://www.knora.org/ontology/0804/dokubib"), - status = false, + status = Status.Inactive, selfjoin = SelfJoin.CannotJoin, copyrightAttribution = None, license = None, diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala index 2ebf48cc4c..50ba4de1e7 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala @@ -30,6 +30,7 @@ import org.knora.webapi.slice.admin.domain.model.KnoraProject.ProjectIri import org.knora.webapi.slice.admin.domain.model.KnoraProject.SelfJoin.CannotJoin import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortcode import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortname +import org.knora.webapi.slice.admin.domain.model.KnoraProject.Status.Active import org.knora.webapi.slice.admin.domain.model.User import org.knora.webapi.slice.admin.domain.model.UserIri import org.knora.webapi.slice.admin.domain.model.UserStatus @@ -96,7 +97,7 @@ object Examples { description = Seq(StringLiteralV2.from("An example project", Some("en"))), keywords = Seq("example", "project"), logo = None, - status = true, + status = Active, ontologies = Seq.empty, selfjoin = CannotJoin, copyrightAttribution = Some(CopyrightAttribution.unsafeFrom("2024, Example Project")), diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala index e2cc59063e..feb3f52908 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala @@ -39,7 +39,7 @@ case class Project( keywords: Seq[String], logo: Option[Logo], ontologies: Seq[IRI], - status: Boolean, + status: Status, selfjoin: SelfJoin, copyrightAttribution: Option[CopyrightAttribution], license: Option[License], diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala index 2c1741d341..158a21a72a 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala @@ -54,7 +54,7 @@ final case class ProjectService( knoraProject.keywords.map(_.value), knoraProject.logo, ontologies, - knoraProject.status.value, + knoraProject.status, knoraProject.selfjoin, knoraProject.copyrightAttribution, knoraProject.license, @@ -72,7 +72,7 @@ final case class ProjectService( .map(Description.unsafeFrom), keywords = project.keywords.map(Keyword.unsafeFrom).toList, logo = project.logo, - status = Status.from(project.status), + status = project.status, selfjoin = project.selfjoin, restrictedView, project.copyrightAttribution, diff --git a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala index 696586a958..ef5f7d1b30 100644 --- a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala @@ -33,7 +33,7 @@ object ProjectServiceSpec extends ZIOSpecDefault { keywords = List.empty, logo = None, ontologies = List.empty, - status = true, + status = Status.Active, selfjoin = SelfJoin.CanJoin, copyrightAttribution = None, license = None, From d418c7bb84ae0a6df6825e984e68a56b02783d8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinb=C3=B6lting?= Date: Fri, 15 Nov 2024 19:27:12 +0100 Subject: [PATCH 16/18] refactor: Make Project.id typed --- .../webapi/e2e/admin/ProjectsADME2ESpec.scala | 17 ++-- .../webapi/e2e/admin/UsersADME2ESpec.scala | 2 +- .../e2e/v2/OntologyFormatsE2ESpec.scala | 5 +- .../e2e/v2/ResourcesRouteV2E2ESpec.scala | 2 +- .../IntegrationTestAdminJsonProtocol.scala | 6 ++ .../PermissionsMessagesADMSpec.scala | 18 ++--- .../models/filemodels/FileModelsSpec.scala | 1 + .../admin/GroupRestServiceSpec.scala | 5 +- .../admin/PermissionsResponderSpec.scala | 77 ++++++++----------- .../admin/ProjectRestServiceSpec.scala | 31 ++++---- .../admin/UserRestServiceSpec.scala | 40 +++++----- .../v2/OntologyResponderV2Spec.scala | 8 +- .../responders/v2/SearchResponderV2Spec.scala | 2 +- .../webapi/sharedtestdata/ProjectInfo.scala | 2 +- .../sharedtestdata/SharedTestDataADM.scala | 62 +++++++-------- .../webapi/sharedtestdata/UserProfile.scala | 2 +- .../KnoraUserToUserConverterSpec.scala | 4 +- .../webapi/messages/OntologyConstants.scala | 4 +- .../resourcemessages/ResourceMessagesV2.scala | 4 +- .../admin/PermissionsResponder.scala | 4 +- .../responders/v2/OntologyResponderV2.scala | 4 +- .../webapi/responders/v2/ResourceUtilV2.scala | 4 +- .../responders/v2/ResourcesResponderV2.scala | 2 +- .../responders/v2/ValuesResponderV2.scala | 4 +- .../ontology/OntologyTriplestoreHelpers.scala | 2 +- .../resources/CreateResourceV2Handler.scala | 24 +++--- .../webapi/slice/admin/api/Examples.scala | 2 +- .../admin/api/model/ProjectsMessagesADM.scala | 6 +- .../api/service/PermissionRestService.scala | 6 +- .../api/service/ProjectRestService.scala | 4 +- .../admin/domain/service/GroupService.scala | 2 +- .../domain/service/KnoraUserService.scala | 18 ++--- .../admin/domain/service/ProjectService.scala | 4 +- .../ApiComplexV2JsonLdRequestParser.scala | 2 +- .../domain/service/ProjectServiceSpec.scala | 2 +- .../RestCardinalityServiceLiveSpec.scala | 4 +- .../domain/IriTestConstants.scala | 3 +- 37 files changed, 192 insertions(+), 197 deletions(-) diff --git a/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2ESpec.scala b/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2ESpec.scala index cc47c928cd..7c87fee891 100644 --- a/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2ESpec.scala +++ b/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2ESpec.scala @@ -19,6 +19,7 @@ import java.net.URLEncoder import scala.concurrent.Await import scala.concurrent.Future import scala.concurrent.duration.* + import org.knora.webapi.E2ESpec import org.knora.webapi.IRI import org.knora.webapi.messages.admin.responder.IntegrationTestAdminJsonProtocol.* @@ -42,7 +43,7 @@ class ProjectsADME2ESpec extends E2ESpec with SprayJsonSupport { private val rootEmail = SharedTestDataADM.rootUser.email private val testPass = SharedTestDataADM.testPass private val projectIri = SharedTestDataADM.imagesProject.id - private val projectIriEnc = URLEncoder.encode(projectIri, "utf-8") + private val projectIriEnc = URLEncoder.encode(projectIri.value, "utf-8") private val projectShortname = SharedTestDataADM.imagesProject.shortname private val projectShortcode = SharedTestDataADM.imagesProject.shortcode @@ -239,7 +240,7 @@ class ProjectsADME2ESpec extends E2ESpec with SprayJsonSupport { result.status should be(Status.Active) result.selfjoin should be(SelfJoin.CannotJoin) - newProjectIri.set(result.id) + newProjectIri.set(result.id.value) } "return a 'BadRequest' if the supplied project shortname during creation is not unique" in { @@ -539,7 +540,7 @@ class ProjectsADME2ESpec extends E2ESpec with SprayJsonSupport { } "return all keywords for a single project" in { - val incunabulaIriEnc = URLEncoder.encode(SharedTestDataADM.incunabulaProject.id, "utf-8") + val incunabulaIriEnc = URLEncoder.encode(SharedTestDataADM.incunabulaProject.id.value, "utf-8") val request = Get(baseApiUrl + s"/admin/projects/iri/$incunabulaIriEnc/Keywords") ~> addCredentials( BasicHttpCredentials(rootEmail, testPass), ) @@ -551,7 +552,7 @@ class ProjectsADME2ESpec extends E2ESpec with SprayJsonSupport { } "return empty list for a project without keywords" in { - val dokubibIriEnc = URLEncoder.encode(SharedTestDataADM.dokubibProject.id, "utf-8") + val dokubibIriEnc = URLEncoder.encode(SharedTestDataADM.dokubibProject.id.value, "utf-8") val request = Get(baseApiUrl + s"/admin/projects/iri/$dokubibIriEnc/Keywords") ~> addCredentials( BasicHttpCredentials(rootEmail, testPass), ) @@ -574,7 +575,7 @@ class ProjectsADME2ESpec extends E2ESpec with SprayJsonSupport { "used to dump project data" should { "return a TriG file containing all data from a project" in { - val anythingProjectIriEnc = URLEncoder.encode(SharedTestDataADM.anythingProject.id, "utf-8") + val anythingProjectIriEnc = URLEncoder.encode(SharedTestDataADM.anythingProject.id.value, "utf-8") val request = Get(baseApiUrl + s"/admin/projects/iri/$anythingProjectIriEnc/AllData") ~> addCredentials( BasicHttpCredentials(SharedTestDataADM.anythingAdminUser.email, testPass), ) @@ -599,7 +600,7 @@ class ProjectsADME2ESpec extends E2ESpec with SprayJsonSupport { "used to set RestrictedViewSize by project IRI" should { "return requested value to be set with 200 Response Status" in { - val encodedIri = URLEncoder.encode(SharedTestDataADM.imagesProject.id, "utf-8") + val encodedIri = URLEncoder.encode(SharedTestDataADM.imagesProject.id.value, "utf-8") val payload = """{"size":"pct:1"}""" val request = Post( @@ -614,7 +615,7 @@ class ProjectsADME2ESpec extends E2ESpec with SprayJsonSupport { } "return the `BadRequest` if the size value is invalid" in { - val encodedIri = URLEncoder.encode(SharedTestDataADM.imagesProject.id, "utf-8") + val encodedIri = URLEncoder.encode(SharedTestDataADM.imagesProject.id.value, "utf-8") val payload = """{"size":"pct:0"}""" val request = Post( @@ -630,7 +631,7 @@ class ProjectsADME2ESpec extends E2ESpec with SprayJsonSupport { } "return `Forbidden` for the user who is not a system nor project admin" in { - val encodedIri = URLEncoder.encode(SharedTestDataADM.imagesProject.id, "utf-8") + val encodedIri = URLEncoder.encode(SharedTestDataADM.imagesProject.id.value, "utf-8") val payload = """{"size":"pct:1"}""" val request = Post( diff --git a/integration/src/test/scala/org/knora/webapi/e2e/admin/UsersADME2ESpec.scala b/integration/src/test/scala/org/knora/webapi/e2e/admin/UsersADME2ESpec.scala index 1d8565f428..a4ed15b696 100644 --- a/integration/src/test/scala/org/knora/webapi/e2e/admin/UsersADME2ESpec.scala +++ b/integration/src/test/scala/org/knora/webapi/e2e/admin/UsersADME2ESpec.scala @@ -50,7 +50,7 @@ class UsersADME2ESpec extends E2ESpec with SprayJsonSupport { private val multiUserIriEnc = java.net.URLEncoder.encode(multiUserIri, "utf-8") private val imagesProjectIri = SharedTestDataADM.imagesProject.id - private val imagesProjectIriEnc = java.net.URLEncoder.encode(imagesProjectIri, "utf-8") + private val imagesProjectIriEnc = java.net.URLEncoder.encode(imagesProjectIri.value, "utf-8") private val imagesReviewerGroupIri = SharedTestDataADM.imagesReviewerGroup.id private val imagesReviewerGroupIriEnc = java.net.URLEncoder.encode(imagesReviewerGroupIri, "utf-8") diff --git a/integration/src/test/scala/org/knora/webapi/e2e/v2/OntologyFormatsE2ESpec.scala b/integration/src/test/scala/org/knora/webapi/e2e/v2/OntologyFormatsE2ESpec.scala index 90acbae336..da0b296900 100644 --- a/integration/src/test/scala/org/knora/webapi/e2e/v2/OntologyFormatsE2ESpec.scala +++ b/integration/src/test/scala/org/knora/webapi/e2e/v2/OntologyFormatsE2ESpec.scala @@ -23,6 +23,7 @@ import org.knora.webapi.messages.util.rdf.RdfFormatUtil import org.knora.webapi.messages.util.rdf.Turtle import org.knora.webapi.sharedtestdata.SharedOntologyTestDataADM import org.knora.webapi.sharedtestdata.SharedTestDataADM +import org.knora.webapi.slice.common.Value.StringValue import org.knora.webapi.util.* class OntologyFormatsE2ESpec extends E2ESpec { @@ -73,8 +74,8 @@ class OntologyFormatsE2ESpec extends E2ESpec { } } - private def urlEncodeIri(iri: IRI): String = - URLEncoder.encode(iri, "UTF-8") + private def urlEncodeIri(iri: StringValue): String = URLEncoder.encode(iri.value, "UTF-8") + private def urlEncodeIri(iri: IRI): String = URLEncoder.encode(iri, "UTF-8") private def checkTestCase(httpGetTest: HttpGetTest) = { val responseJsonLd = getResponse(httpGetTest.urlPath, RdfMediaTypes.`application/ld+json`) diff --git a/integration/src/test/scala/org/knora/webapi/e2e/v2/ResourcesRouteV2E2ESpec.scala b/integration/src/test/scala/org/knora/webapi/e2e/v2/ResourcesRouteV2E2ESpec.scala index d3d49aebf2..5a645fc858 100644 --- a/integration/src/test/scala/org/knora/webapi/e2e/v2/ResourcesRouteV2E2ESpec.scala +++ b/integration/src/test/scala/org/knora/webapi/e2e/v2/ResourcesRouteV2E2ESpec.scala @@ -652,7 +652,7 @@ class ResourcesRouteV2E2ESpec extends E2ESpec { val orderByProperty = URLEncoder.encode("http://0.0.0.0:3333/ontology/0803/incunabula/v2#title", "UTF-8") val request = Get(s"$baseApiUrl/v2/resources?resourceClass=$resourceClass&orderByProperty=$orderByProperty&page=0") - .addHeader(new ProjectHeader(SharedTestDataADM.incunabulaProject.id)) ~> addCredentials( + .addHeader(new ProjectHeader(SharedTestDataADM.incunabulaProject.id.value)) ~> addCredentials( BasicHttpCredentials(SharedTestDataADM.incunabulaProjectAdminUser.email, password), ) val response: HttpResponse = singleAwaitingRequest(request) diff --git a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala index 0a99e53455..9d2d1385a8 100644 --- a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala +++ b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala @@ -6,6 +6,7 @@ package org.knora.webapi.messages.admin.responder import spray.json.* + import org.knora.webapi.messages.admin.responder.groupsmessages.GroupGetResponseADM import org.knora.webapi.messages.admin.responder.groupsmessages.GroupsGetResponseADM import org.knora.webapi.messages.admin.responder.permissionsmessages.AdministrativePermissionADM @@ -48,6 +49,7 @@ import org.knora.webapi.slice.admin.domain.model.KnoraProject.CopyrightAttributi import org.knora.webapi.slice.admin.domain.model.KnoraProject.License import org.knora.webapi.slice.admin.domain.model.KnoraProject.Logo import org.knora.webapi.slice.admin.domain.model.KnoraProject.Longname +import org.knora.webapi.slice.admin.domain.model.KnoraProject.ProjectIri import org.knora.webapi.slice.admin.domain.model.KnoraProject.SelfJoin import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortcode import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortname @@ -211,6 +213,10 @@ object IntegrationTestAdminJsonProtocol extends TriplestoreJsonProtocol { case _ => throw DeserializationException("Must be a json String") } + implicit object ProjectIriFormat extends StringValueFormat[ProjectIri] { + override val from: String => Either[String, ProjectIri] = ProjectIri.from + } + implicit object CopyrightAttributionFormat extends StringValueFormat[CopyrightAttribution] { override val from: String => Either[String, CopyrightAttribution] = CopyrightAttribution.from } diff --git a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/permissionsmessages/PermissionsMessagesADMSpec.scala b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/permissionsmessages/PermissionsMessagesADMSpec.scala index 8955d36a49..c127f2880c 100644 --- a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/permissionsmessages/PermissionsMessagesADMSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/permissionsmessages/PermissionsMessagesADMSpec.scala @@ -45,7 +45,7 @@ class PermissionsMessagesADMSpec extends CoreSpec { val exit = UnsafeZioRun.run( PermissionRestService.createAdministrativePermission( CreateAdministrativePermissionAPIRequestADM( - forProject = SharedTestDataADM.imagesProjectIri, + forProject = SharedTestDataADM.imagesProjectIri.value, forGroup = groupIri, hasPermissions = Set(PermissionADM.from(Permission.Administrative.ProjectAdminAll)), ), @@ -61,7 +61,7 @@ class PermissionsMessagesADMSpec extends CoreSpec { PermissionRestService.createAdministrativePermission( CreateAdministrativePermissionAPIRequestADM( id = Some(permissionIri), - forProject = SharedTestDataADM.imagesProjectIri, + forProject = SharedTestDataADM.imagesProjectIri.value, forGroup = KnoraGroupRepo.builtIn.ProjectMember.id.value, hasPermissions = Set(PermissionADM.from(Permission.Administrative.ProjectAdminAll)), ), @@ -83,7 +83,7 @@ class PermissionsMessagesADMSpec extends CoreSpec { val exit = UnsafeZioRun.run( PermissionRestService.createAdministrativePermission( CreateAdministrativePermissionAPIRequestADM( - forProject = SharedTestDataADM.imagesProjectIri, + forProject = SharedTestDataADM.imagesProjectIri.value, forGroup = KnoraGroupRepo.builtIn.ProjectMember.id.value, hasPermissions = hasPermissions, ), @@ -101,7 +101,7 @@ class PermissionsMessagesADMSpec extends CoreSpec { val exit = UnsafeZioRun.run( PermissionRestService.createAdministrativePermission( CreateAdministrativePermissionAPIRequestADM( - forProject = SharedTestDataADM.imagesProjectIri, + forProject = SharedTestDataADM.imagesProjectIri.value, forGroup = KnoraGroupRepo.builtIn.ProjectMember.id.value, hasPermissions = Set.empty[PermissionADM], ), @@ -115,7 +115,7 @@ class PermissionsMessagesADMSpec extends CoreSpec { val exit = UnsafeZioRun.run( PermissionRestService.createAdministrativePermission( CreateAdministrativePermissionAPIRequestADM( - forProject = SharedTestDataADM.imagesProjectIri, + forProject = SharedTestDataADM.imagesProjectIri.value, forGroup = KnoraGroupRepo.builtIn.ProjectMember.id.value, hasPermissions = Set(PermissionADM.from(Permission.Administrative.ProjectAdminAll)), ), @@ -153,7 +153,7 @@ class PermissionsMessagesADMSpec extends CoreSpec { val exit = UnsafeZioRun.run( PermissionRestService.createDefaultObjectAccessPermission( CreateDefaultObjectAccessPermissionAPIRequestADM( - forProject = SharedTestDataADM.imagesProjectIri, + forProject = SharedTestDataADM.imagesProjectIri.value, forGroup = Some(groupIri), hasPermissions = Set( PermissionADM.from(Permission.ObjectAccess.ChangeRights, KnoraGroupRepo.builtIn.ProjectMember.id.value), @@ -171,7 +171,7 @@ class PermissionsMessagesADMSpec extends CoreSpec { PermissionRestService.createDefaultObjectAccessPermission( CreateDefaultObjectAccessPermissionAPIRequestADM( id = Some(permissionIri), - forProject = SharedTestDataADM.imagesProjectIri, + forProject = SharedTestDataADM.imagesProjectIri.value, forGroup = Some(KnoraGroupRepo.builtIn.ProjectMember.id.value), hasPermissions = Set( PermissionADM.from(Permission.ObjectAccess.ChangeRights, KnoraGroupRepo.builtIn.ProjectMember.id.value), @@ -187,7 +187,7 @@ class PermissionsMessagesADMSpec extends CoreSpec { val exit = UnsafeZioRun.run( PermissionRestService.createDefaultObjectAccessPermission( CreateDefaultObjectAccessPermissionAPIRequestADM( - forProject = SharedTestDataADM.imagesProjectIri, + forProject = SharedTestDataADM.imagesProjectIri.value, forGroup = Some(SharedTestDataADM.thingSearcherGroup.id), hasPermissions = Set.empty[PermissionADM], ), @@ -289,7 +289,7 @@ class PermissionsMessagesADMSpec extends CoreSpec { val exit = UnsafeZioRun.run( PermissionRestService.createDefaultObjectAccessPermission( CreateDefaultObjectAccessPermissionAPIRequestADM( - forProject = SharedTestDataADM.anythingProjectIri, + forProject = SharedTestDataADM.anythingProjectIri.value, forGroup = Some(SharedTestDataADM.thingSearcherGroup.id), hasPermissions = Set(PermissionADM.from(Permission.ObjectAccess.RestrictedView, SharedTestDataADM.thingSearcherGroup.id)), diff --git a/integration/src/test/scala/org/knora/webapi/models/filemodels/FileModelsSpec.scala b/integration/src/test/scala/org/knora/webapi/models/filemodels/FileModelsSpec.scala index 5ac6b34b2b..7d275c06dd 100644 --- a/integration/src/test/scala/org/knora/webapi/models/filemodels/FileModelsSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/models/filemodels/FileModelsSpec.scala @@ -10,6 +10,7 @@ import spray.json.DefaultJsonProtocol.* import java.time.Instant import java.util.UUID + import dsp.errors.AssertionException import org.knora.webapi.ApiV2Complex import org.knora.webapi.CoreSpec diff --git a/integration/src/test/scala/org/knora/webapi/responders/admin/GroupRestServiceSpec.scala b/integration/src/test/scala/org/knora/webapi/responders/admin/GroupRestServiceSpec.scala index ac1bb8ed81..c36217ff24 100644 --- a/integration/src/test/scala/org/knora/webapi/responders/admin/GroupRestServiceSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/responders/admin/GroupRestServiceSpec.scala @@ -22,7 +22,6 @@ import org.knora.webapi.slice.admin.domain.model.GroupIri import org.knora.webapi.slice.admin.domain.model.GroupName import org.knora.webapi.slice.admin.domain.model.GroupSelfJoin import org.knora.webapi.slice.admin.domain.model.GroupStatus -import org.knora.webapi.slice.admin.domain.model.KnoraProject.ProjectIri import org.knora.webapi.slice.admin.domain.service.GroupService import org.knora.webapi.util.MutableTestIri import org.knora.webapi.util.ZioScalaTestUtil.assertFailsWithA @@ -74,7 +73,7 @@ class GroupRestServiceSpec extends CoreSpec { ), ), ), - project = ProjectIri.unsafeFrom(imagesProjectIri), + project = imagesProjectIri, status = GroupStatus.active, selfjoin = GroupSelfJoin.disabled, ), @@ -106,7 +105,7 @@ class GroupRestServiceSpec extends CoreSpec { name = groupName, descriptions = GroupDescriptions .unsafeFrom(Seq(StringLiteralV2.from(value = "NewGroupDescription", language = Some("en")))), - project = ProjectIri.unsafeFrom(imagesProjectIri), + project = imagesProjectIri, status = GroupStatus.active, selfjoin = GroupSelfJoin.disabled, ), diff --git a/integration/src/test/scala/org/knora/webapi/responders/admin/PermissionsResponderSpec.scala b/integration/src/test/scala/org/knora/webapi/responders/admin/PermissionsResponderSpec.scala index 2043a7cd65..b285b922ca 100644 --- a/integration/src/test/scala/org/knora/webapi/responders/admin/PermissionsResponderSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/responders/admin/PermissionsResponderSpec.scala @@ -33,7 +33,6 @@ import org.knora.webapi.sharedtestdata.SharedTestDataADM.normalUser import org.knora.webapi.sharedtestdata.SharedTestDataADM2 import org.knora.webapi.slice.admin.api.service.PermissionRestService import org.knora.webapi.slice.admin.domain.model.GroupIri -import org.knora.webapi.slice.admin.domain.model.KnoraProject.ProjectIri import org.knora.webapi.slice.admin.domain.model.Permission import org.knora.webapi.slice.admin.domain.model.PermissionIri import org.knora.webapi.slice.admin.domain.service.KnoraGroupRepo @@ -80,7 +79,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { val result = UnsafeZioRun.runOrThrow( permissionRestService( _.getPermissionsApByProjectAndGroupIri( - ProjectIri.unsafeFrom(imagesProjectIri), + imagesProjectIri, KnoraGroupRepo.builtIn.ProjectMember.id, rootUser, ), @@ -96,7 +95,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { permissionsResponder( _.createAdministrativePermission( CreateAdministrativePermissionAPIRequestADM( - forProject = imagesProjectIri, + forProject = imagesProjectIri.value, forGroup = KnoraGroupRepo.builtIn.ProjectMember.id.value, hasPermissions = Set(PermissionADM.from(Permission.Administrative.ProjectResourceCreateAll)), ), @@ -121,7 +120,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { _.createAdministrativePermission( CreateAdministrativePermissionAPIRequestADM( id = Some(customIri), - forProject = SharedTestDataADM.anythingProjectIri, + forProject = SharedTestDataADM.anythingProjectIri.value, forGroup = SharedTestDataADM.thingSearcherGroup.id, hasPermissions = Set(PermissionADM.from(Permission.Administrative.ProjectResourceCreateAll)), ), @@ -131,7 +130,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { ), ) assert(actual.administrativePermission.iri == customIri) - assert(actual.administrativePermission.forProject == SharedTestDataADM.anythingProjectIri) + assert(actual.administrativePermission.forProject == SharedTestDataADM.anythingProjectIri.value) assert(actual.administrativePermission.forGroup == SharedTestDataADM.thingSearcherGroup.id) } @@ -150,7 +149,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { _.createAdministrativePermission( CreateAdministrativePermissionAPIRequestADM( id = Some(customIri), - forProject = SharedTestDataADM.anythingProjectIri, + forProject = SharedTestDataADM.anythingProjectIri.value, forGroup = KnoraGroupRepo.builtIn.KnownUser.id.value, hasPermissions = hasPermissions, ), @@ -161,7 +160,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { ) assert(actual.administrativePermission.iri == customIri) assert(actual.administrativePermission.forGroup == KnoraGroupRepo.builtIn.KnownUser.id.value) - assert(actual.administrativePermission.forProject == SharedTestDataADM.anythingProjectIri) + assert(actual.administrativePermission.forProject == SharedTestDataADM.anythingProjectIri.value) assert(actual.administrativePermission.hasPermissions.equals(expectedHasPermissions)) } } @@ -169,13 +168,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { "ask to query about default object access permissions " should { "return all DefaultObjectAccessPermissions for project" in { - val actual = UnsafeZioRun.runOrThrow( - permissionsResponder( - _.getPermissionsDaopByProjectIri( - ProjectIri.unsafeFrom(imagesProjectIri), - ), - ), - ) + val actual = UnsafeZioRun.runOrThrow(permissionsResponder(_.getPermissionsDaopByProjectIri(imagesProjectIri))) actual shouldEqual DefaultObjectAccessPermissionsForProjectGetResponseADM( Seq(perm002_d2.p, perm0003_a4.p, perm002_d1.p), ) @@ -189,7 +182,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { permissionsResponder( _.createDefaultObjectAccessPermission( CreateDefaultObjectAccessPermissionAPIRequestADM( - forProject = SharedTestDataADM.anythingProjectIri, + forProject = SharedTestDataADM.anythingProjectIri.value, forGroup = Some(SharedTestDataADM.thingSearcherGroup.id), hasPermissions = Set( PermissionADM.from(Permission.ObjectAccess.RestrictedView, SharedTestDataADM.thingSearcherGroup.id), @@ -200,7 +193,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { ), ) - assert(actual.defaultObjectAccessPermission.forProject == SharedTestDataADM.anythingProjectIri) + assert(actual.defaultObjectAccessPermission.forProject == SharedTestDataADM.anythingProjectIri.value) assert(actual.defaultObjectAccessPermission.forGroup.contains(SharedTestDataADM.thingSearcherGroup.id)) assert( actual.defaultObjectAccessPermission.hasPermissions.contains( @@ -216,7 +209,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { _.createDefaultObjectAccessPermission( createRequest = CreateDefaultObjectAccessPermissionAPIRequestADM( id = Some(customIri), - forProject = SharedTestDataADM.anythingProjectIri, + forProject = SharedTestDataADM.anythingProjectIri.value, forGroup = Some(KnoraGroupRepo.builtIn.UnknownUser.id.value), hasPermissions = Set( PermissionADM @@ -229,7 +222,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { ) assert(received.defaultObjectAccessPermission.iri == customIri) assert(received.defaultObjectAccessPermission.forGroup.contains(KnoraGroupRepo.builtIn.UnknownUser.id.value)) - assert(received.defaultObjectAccessPermission.forProject == SharedTestDataADM.anythingProjectIri) + assert(received.defaultObjectAccessPermission.forProject == SharedTestDataADM.anythingProjectIri.value) assert( received.defaultObjectAccessPermission.hasPermissions .contains( @@ -243,7 +236,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { permissionsResponder( _.createDefaultObjectAccessPermission( CreateDefaultObjectAccessPermissionAPIRequestADM( - forProject = imagesProjectIri, + forProject = imagesProjectIri.value, forResourceClass = Some(SharedOntologyTestDataADM.IMAGES_BILD_RESOURCE_CLASS), hasPermissions = Set(PermissionADM.from(Permission.ObjectAccess.Modify, KnoraGroupRepo.builtIn.KnownUser.id.value)), @@ -252,7 +245,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { ), ), ) - assert(actual.defaultObjectAccessPermission.forProject == imagesProjectIri) + assert(actual.defaultObjectAccessPermission.forProject == imagesProjectIri.value) assert( actual.defaultObjectAccessPermission.forResourceClass .contains(SharedOntologyTestDataADM.IMAGES_BILD_RESOURCE_CLASS), @@ -268,7 +261,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { permissionsResponder( _.createDefaultObjectAccessPermission( CreateDefaultObjectAccessPermissionAPIRequestADM( - forProject = imagesProjectIri, + forProject = imagesProjectIri.value, forProperty = Some(SharedOntologyTestDataADM.IMAGES_TITEL_PROPERTY), hasPermissions = Set( PermissionADM.from(Permission.ObjectAccess.ChangeRights, KnoraGroupRepo.builtIn.Creator.id.value), @@ -278,7 +271,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { ), ), ) - assert(actual.defaultObjectAccessPermission.forProject == imagesProjectIri) + assert(actual.defaultObjectAccessPermission.forProject == imagesProjectIri.value) assert( actual.defaultObjectAccessPermission.forProperty .contains(SharedOntologyTestDataADM.IMAGES_TITEL_PROPERTY), @@ -406,7 +399,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { permissionsResponder( _.createDefaultObjectAccessPermission( CreateDefaultObjectAccessPermissionAPIRequestADM( - forProject = imagesProjectIri, + forProject = imagesProjectIri.value, forGroup = Some(KnoraGroupRepo.builtIn.UnknownUser.id.value), hasPermissions = hasPermissions, ), @@ -414,7 +407,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { ), ), ) - assert(actual.defaultObjectAccessPermission.forProject == imagesProjectIri) + assert(actual.defaultObjectAccessPermission.forProject == imagesProjectIri.value) assert(actual.defaultObjectAccessPermission.forGroup.contains(KnoraGroupRepo.builtIn.UnknownUser.id.value)) assert( actual.defaultObjectAccessPermission.hasPermissions.contains( @@ -442,7 +435,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { permissionsResponder( _.createDefaultObjectAccessPermission( CreateDefaultObjectAccessPermissionAPIRequestADM( - forProject = imagesProjectIri, + forProject = imagesProjectIri.value, forGroup = Some(KnoraGroupRepo.builtIn.ProjectAdmin.id.value), hasPermissions = hasPermissions, ), @@ -450,7 +443,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { ), ), ) - assert(actual.defaultObjectAccessPermission.forProject == imagesProjectIri) + assert(actual.defaultObjectAccessPermission.forProject == imagesProjectIri.value) assert(actual.defaultObjectAccessPermission.forGroup.contains(KnoraGroupRepo.builtIn.ProjectAdmin.id.value)) assert(actual.defaultObjectAccessPermission.hasPermissions.equals(expectedPermissions)) } @@ -459,21 +452,13 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { "ask to get all permissions" should { "return all permissions for 'image' project" in { - val actual = UnsafeZioRun.runOrThrow( - permissionsResponder( - _.getPermissionsByProjectIri(ProjectIri.unsafeFrom(imagesProjectIri)), - ), - ) + val actual = UnsafeZioRun.runOrThrow(permissionsResponder(_.getPermissionsByProjectIri(imagesProjectIri))) actual.permissions.size should be(10) } "return all permissions for 'incunabula' project" in { val actual = UnsafeZioRun.runOrThrow( - permissionsResponder( - _.getPermissionsByProjectIri( - ProjectIri.unsafeFrom(SharedTestDataADM.incunabulaProjectIri), - ), - ), + permissionsResponder(_.getPermissionsByProjectIri(SharedTestDataADM.incunabulaProjectIri)), ) actual shouldEqual PermissionsForProjectGetResponseADM(permissions = @@ -517,7 +502,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { val actual = UnsafeZioRun.runOrThrow( permissionsResponder( _.newResourceDefaultObjectAccessPermissions( - ProjectIri.unsafeFrom(SharedTestDataADM.incunabulaProjectIri), + SharedTestDataADM.incunabulaProjectIri, SharedOntologyTestDataADM.INCUNABULA_BOOK_RESOURCE_CLASS.toSmartIri, SharedTestDataADM.incunabulaProjectAdminUser, ), @@ -534,7 +519,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { val actual = UnsafeZioRun.runOrThrow( permissionsResponder( _.newResourceDefaultObjectAccessPermissions( - ProjectIri.unsafeFrom(SharedTestDataADM.incunabulaProjectIri), + SharedTestDataADM.incunabulaProjectIri, SharedOntologyTestDataADM.INCUNABULA_PAGE_RESOURCE_CLASS.toSmartIri, SharedTestDataADM.incunabulaProjectAdminUser, ), @@ -551,7 +536,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { val actual = UnsafeZioRun.runOrThrow( permissionsResponder( _.newValueDefaultObjectAccessPermissions( - ProjectIri.unsafeFrom(SharedTestDataADM.anythingProjectIri), + SharedTestDataADM.anythingProjectIri, stringFormatter.toSmartIri("http://www.knora.org/ontology/0001/anything#Thing"), stringFormatter.toSmartIri("http://www.knora.org/ontology/0001/anything#hasInterval"), SharedTestDataADM.anythingUser2, @@ -570,7 +555,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { val actual = UnsafeZioRun.runOrThrow( permissionsResponder( _.newResourceDefaultObjectAccessPermissions( - ProjectIri.unsafeFrom(SharedTestDataADM.anythingProjectIri), + SharedTestDataADM.anythingProjectIri, "http://www.knora.org/ontology/0001/anything#Thing".toSmartIri, SharedTestDataADM.anythingUser2, ), @@ -588,7 +573,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { .runOrThrow( permissionsResponder( _.newValueDefaultObjectAccessPermissions( - projectIri = ProjectIri.unsafeFrom(SharedTestDataADM.anythingProjectIri), + projectIri = SharedTestDataADM.anythingProjectIri, resourceClassIri = stringFormatter.toSmartIri("http://www.knora.org/ontology/0001/anything#Thing"), propertyIri = stringFormatter.toSmartIri("http://www.knora.org/ontology/0001/anything#hasText"), targetUser = SharedTestDataADM.anythingUser1, @@ -603,7 +588,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { .runOrThrow( permissionsResponder( _.newValueDefaultObjectAccessPermissions( - ProjectIri.unsafeFrom(SharedTestDataADM.anythingProjectIri), + SharedTestDataADM.anythingProjectIri, stringFormatter.toSmartIri(s"${SharedOntologyTestDataADM.IMAGES_ONTOLOGY_IRI}#bild"), stringFormatter.toSmartIri("http://www.knora.org/ontology/0001/anything#hasText"), SharedTestDataADM.anythingUser2, @@ -623,7 +608,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { .run( permissionsResponder( _.newValueDefaultObjectAccessPermissions( - ProjectIri.unsafeFrom(SharedTestDataADM.imagesProjectIri), + SharedTestDataADM.imagesProjectIri, stringFormatter.toSmartIri(SharedTestDataADM.customResourceIRI), stringFormatter.toSmartIri(SharedOntologyTestDataADM.IMAGES_TITEL_PROPERTY), SharedTestDataADM.imagesReviewerUser, @@ -640,7 +625,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { val exit = UnsafeZioRun.run( permissionsResponder( _.newValueDefaultObjectAccessPermissions( - ProjectIri.unsafeFrom(SharedTestDataADM.imagesProjectIri), + SharedTestDataADM.imagesProjectIri, stringFormatter.toSmartIri(SharedOntologyTestDataADM.IMAGES_BILD_RESOURCE_CLASS), stringFormatter.toSmartIri(SharedTestDataADM.customValueIRI), SharedTestDataADM.imagesReviewerUser, @@ -654,7 +639,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { val exit = UnsafeZioRun.run( permissionsResponder( _.newValueDefaultObjectAccessPermissions( - ProjectIri.unsafeFrom(SharedTestDataADM.imagesProjectIri), + SharedTestDataADM.imagesProjectIri, stringFormatter.toSmartIri(SharedOntologyTestDataADM.IMAGES_BILD_RESOURCE_CLASS), stringFormatter.toSmartIri(SharedOntologyTestDataADM.IMAGES_TITEL_PROPERTY), SharedTestDataADM.anonymousUser, @@ -668,7 +653,7 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { val actual = UnsafeZioRun.runOrThrow( permissionsResponder( _.newResourceDefaultObjectAccessPermissions( - ProjectIri.unsafeFrom(SharedTestDataADM.anythingProjectIri), + SharedTestDataADM.anythingProjectIri, "http://www.knora.org/ontology/0001/anything#Thing".toSmartIri, SharedTestDataADM.rootUser, ), diff --git a/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala b/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala index 4f4430d0c9..38b3268a04 100644 --- a/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala @@ -59,7 +59,7 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { "return information about a project identified by IRI" in { val actual = UnsafeZioRun.runOrThrow( - ProjectRestService(_.findById(SharedTestDataADM.incunabulaProject.projectIri)), + ProjectRestService(_.findById(SharedTestDataADM.incunabulaProject.id)), ) assert(actual == ProjectGetResponse(toExternal(SharedTestDataADM.incunabulaProject))) } @@ -97,7 +97,7 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { "return restricted view settings using project IRI" in { val actual = UnsafeZioRun.runOrThrow( ProjectRestService( - _.getProjectRestrictedViewSettingsById(SharedTestDataADM.imagesProject.projectIri), + _.getProjectRestrictedViewSettingsById(SharedTestDataADM.imagesProject.id), ), ) actual shouldEqual expectedResult @@ -179,17 +179,16 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { received.project.copyrightAttribution should be(Some(CopyrightAttribution.unsafeFrom("2024, Example Project"))) received.project.license should be(Some(License.unsafeFrom("CC-BY-4.0"))) - newProjectIri.set(received.project.id) + newProjectIri.set(received.project.id.value) // Check Administrative Permissions - val receivedApAdmin = - UnsafeZioRun.runOrThrow( - ZIO.serviceWithZIO[PermissionsResponder](_.getPermissionsApByProjectIri(received.project.id)), - ) + val receivedApAdmin = UnsafeZioRun.runOrThrow( + ZIO.serviceWithZIO[PermissionsResponder](_.getPermissionsApByProjectIri(received.project.id)), + ) val hasAPForProjectAdmin = receivedApAdmin.administrativePermissions.filter { (ap: AdministrativePermissionADM) => - ap.forProject == received.project.id && ap.forGroup == KnoraGroupRepo.builtIn.ProjectAdmin.id.value && + ap.forProject == received.project.id.value && ap.forGroup == KnoraGroupRepo.builtIn.ProjectAdmin.id.value && ap.hasPermissions.equals( Set( PermissionADM.from(Permission.Administrative.ProjectAdminAll), @@ -203,7 +202,7 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { // Check Administrative Permission of ProjectMember val hasAPForProjectMember = receivedApAdmin.administrativePermissions.filter { (ap: AdministrativePermissionADM) => - ap.forProject == received.project.id && ap.forGroup == KnoraGroupRepo.builtIn.ProjectMember.id.value && + ap.forProject == received.project.id.value && ap.forGroup == KnoraGroupRepo.builtIn.ProjectMember.id.value && ap.hasPermissions.equals(Set(PermissionADM.from(Permission.Administrative.ProjectResourceCreateAll))) } hasAPForProjectMember.size shouldBe 1 @@ -211,14 +210,14 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { // Check Default Object Access permissions val receivedDoaps = UnsafeZioRun.runOrThrow( ZIO.serviceWithZIO[PermissionsResponder]( - _.getPermissionsDaopByProjectIri(ProjectIri.unsafeFrom(received.project.id)), + _.getPermissionsDaopByProjectIri(received.project.id), ), ) // Check Default Object Access permission of ProjectAdmin val hasDOAPForProjectAdmin = receivedDoaps.defaultObjectAccessPermissions.filter { (doap: DefaultObjectAccessPermissionADM) => - doap.forProject == received.project.id && doap.forGroup.contains( + doap.forProject == received.project.id.value && doap.forGroup.contains( KnoraGroupRepo.builtIn.ProjectAdmin.id.value, ) && doap.hasPermissions.equals( @@ -233,7 +232,7 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { // Check Default Object Access permission of ProjectMember val hasDOAPForProjectMember = receivedDoaps.defaultObjectAccessPermissions.filter { (doap: DefaultObjectAccessPermissionADM) => - doap.forProject == received.project.id && doap.forGroup.contains( + doap.forProject == received.project.id.value && doap.forGroup.contains( KnoraGroupRepo.builtIn.ProjectMember.id.value, ) && doap.hasPermissions.equals( @@ -434,7 +433,7 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { "return all members of a project identified by IRI" in { val actual = UnsafeZioRun.runOrThrow( ProjectRestService( - _.getProjectMembersById(SharedTestDataADM.rootUser, SharedTestDataADM.imagesProject.projectIri), + _.getProjectMembersById(SharedTestDataADM.rootUser, SharedTestDataADM.imagesProject.id), ), ) @@ -510,7 +509,7 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { "return all project admin members of a project identified by IRI" in { val received = UnsafeZioRun.runOrThrow( ProjectRestService( - _.getProjectAdminMembersById(SharedTestDataADM.rootUser, SharedTestDataADM.imagesProject.projectIri), + _.getProjectAdminMembersById(SharedTestDataADM.rootUser, SharedTestDataADM.imagesProject.id), ), ) @@ -593,7 +592,7 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { "return all keywords for a single project" in { val received = UnsafeZioRun.runOrThrow( ProjectRestService( - _.getKeywordsByProjectIri(SharedTestDataADM.incunabulaProject.projectIri), + _.getKeywordsByProjectIri(SharedTestDataADM.incunabulaProject.id), ), ) received.keywords should be(SharedTestDataADM.incunabulaProject.keywords) @@ -601,7 +600,7 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { "return empty list for a project without keywords" in { val received = UnsafeZioRun.runOrThrow( - ProjectRestService(_.getKeywordsByProjectIri(SharedTestDataADM.dokubibProject.projectIri)), + ProjectRestService(_.getKeywordsByProjectIri(SharedTestDataADM.dokubibProject.id)), ) received.keywords should be(Seq.empty[String]) } diff --git a/integration/src/test/scala/org/knora/webapi/responders/admin/UserRestServiceSpec.scala b/integration/src/test/scala/org/knora/webapi/responders/admin/UserRestServiceSpec.scala index 437284f63c..e130cfef1d 100644 --- a/integration/src/test/scala/org/knora/webapi/responders/admin/UserRestServiceSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/responders/admin/UserRestServiceSpec.scala @@ -366,7 +366,7 @@ class UserRestServiceSpec extends CoreSpec with ImplicitSender { // add user to images project (00FF) UnsafeZioRun.runOrThrow( - userRestService(_.addUserToProject(rootUser, normalUser.userIri, imagesProject.projectIri)), + userRestService(_.addUserToProject(rootUser, normalUser.userIri, imagesProject.id)), ) val membershipsAfterUpdate = @@ -375,7 +375,7 @@ class UserRestServiceSpec extends CoreSpec with ImplicitSender { val received = UnsafeZioRun.runOrThrow( projectRestService( - _.getProjectMembersById(KnoraSystemInstances.Users.SystemUser, imagesProject.projectIri), + _.getProjectMembersById(KnoraSystemInstances.Users.SystemUser, imagesProject.id), ), ) received.members.map(_.id) should contain(normalUser.id) @@ -385,22 +385,22 @@ class UserRestServiceSpec extends CoreSpec with ImplicitSender { // get current project memberships val membershipsBeforeUpdate = UnsafeZioRun.runOrThrow(userRestService(_.getProjectMemberShipsByUserIri(normalUser.userIri))) - membershipsBeforeUpdate.projects.map(_.id).sorted should equal(Seq(imagesProject.id).sorted) + membershipsBeforeUpdate.projects.map(_.id).sortBy(_.value) should equal(Seq(imagesProject.id).sortBy(_.value)) // add user to images project (00FF) UnsafeZioRun.runOrThrow( - userRestService(_.addUserToProject(rootUser, normalUser.userIri, incunabulaProject.projectIri)), + userRestService(_.addUserToProject(rootUser, normalUser.userIri, incunabulaProject.id)), ) val membershipsAfterUpdate = UnsafeZioRun.runOrThrow(userRestService(_.getProjectMemberShipsByUserIri(normalUser.userIri))) - membershipsAfterUpdate.projects.map(_.id).sorted should equal( - Seq(imagesProject.id, incunabulaProject.id).sorted, + membershipsAfterUpdate.projects.map(_.id).sortBy(_.value) should equal( + Seq(imagesProject.id, incunabulaProject.id).sortBy(_.value), ) val received = UnsafeZioRun.runOrThrow( projectRestService( - _.getProjectMembersById(KnoraSystemInstances.Users.SystemUser, incunabulaProject.projectIri), + _.getProjectMembersById(KnoraSystemInstances.Users.SystemUser, incunabulaProject.id), ), ) received.members.map(_.id) should contain(normalUser.id) @@ -410,23 +410,25 @@ class UserRestServiceSpec extends CoreSpec with ImplicitSender { // check project memberships (user should be member of images and incunabula projects) val membershipsBeforeUpdate = UnsafeZioRun.runOrThrow(userRestService(_.getProjectMemberShipsByUserIri(normalUser.userIri))) - membershipsBeforeUpdate.projects.map(_.id).sorted should equal( - Seq(imagesProject.id, incunabulaProject.id).sorted, + membershipsBeforeUpdate.projects.map(_.id).sortBy(_.value) should equal( + Seq(imagesProject.id, incunabulaProject.id).sortBy(_.value), ) // add user as project admin to images project UnsafeZioRun.runOrThrow( - userRestService(_.addUserToProjectAsAdmin(rootUser, normalUser.userIri, imagesProject.projectIri)), + userRestService(_.addUserToProjectAsAdmin(rootUser, normalUser.userIri, imagesProject.id)), ) // verify that the user has been added as project admin to the images project val projectAdminMembershipsBeforeUpdate = UnsafeZioRun.runOrThrow(userRestService(_.getProjectAdminMemberShipsByUserIri(normalUser.userIri))) - projectAdminMembershipsBeforeUpdate.projects.map(_.id).sorted should equal(Seq(imagesProject.id).sorted) + projectAdminMembershipsBeforeUpdate.projects.map(_.id).sortBy(_.value) should equal( + Seq(imagesProject.id).sortBy(_.value), + ) // remove the user as member of the images project UnsafeZioRun.runOrThrow( - userRestService(_.removeUserFromProject(rootUser, normalUser.userIri, imagesProject.projectIri)), + userRestService(_.removeUserFromProject(rootUser, normalUser.userIri, imagesProject.id)), ) // verify that the user has been removed as project member of the images project @@ -441,7 +443,7 @@ class UserRestServiceSpec extends CoreSpec with ImplicitSender { // also check that the user has been removed from the project's list of users val received = UnsafeZioRun.runOrThrow( - projectRestService(_.getProjectMembersById(rootUser, imagesProject.projectIri)), + projectRestService(_.getProjectMembersById(rootUser, imagesProject.id)), ) received.members should not contain normalUser.ofType(UserInformationType.Restricted) } @@ -456,7 +458,7 @@ class UserRestServiceSpec extends CoreSpec with ImplicitSender { // try to add user as project admin to images project (expected to fail because he is not a member of the project) val exit = UnsafeZioRun.run( - userRestService(_.addUserToProjectAsAdmin(rootUser, normalUser.userIri, imagesProject.projectIri)), + userRestService(_.addUserToProjectAsAdmin(rootUser, normalUser.userIri, imagesProject.id)), ) assertFailsWithA[BadRequestException]( exit, @@ -472,12 +474,12 @@ class UserRestServiceSpec extends CoreSpec with ImplicitSender { // add user as project member to images project UnsafeZioRun.runOrThrow( - userRestService(_.addUserToProject(rootUser, normalUser.userIri, imagesProject.projectIri)), + userRestService(_.addUserToProject(rootUser, normalUser.userIri, imagesProject.id)), ) // add user as project admin to images project UnsafeZioRun.runOrThrow( - userRestService(_.addUserToProjectAsAdmin(rootUser, normalUser.userIri, imagesProject.projectIri)), + userRestService(_.addUserToProjectAsAdmin(rootUser, normalUser.userIri, imagesProject.id)), ) // get the updated project admin memberships (should contain images project) @@ -487,7 +489,7 @@ class UserRestServiceSpec extends CoreSpec with ImplicitSender { // get project admins for images project (should contain normal user) val received = UnsafeZioRun.runOrThrow( - projectRestService(_.getProjectAdminMembersById(rootUser, imagesProject.projectIri)), + projectRestService(_.getProjectAdminMembersById(rootUser, imagesProject.id)), ) received.members.map(_.id) should contain(normalUser.id) } @@ -498,7 +500,7 @@ class UserRestServiceSpec extends CoreSpec with ImplicitSender { membershipsBeforeUpdate.projects.map(_.id) should equal(Seq(imagesProject.id)) UnsafeZioRun.runOrThrow( - userRestService(_.removeUserFromProjectAsAdmin(rootUser, normalUser.userIri, imagesProject.projectIri)), + userRestService(_.removeUserFromProjectAsAdmin(rootUser, normalUser.userIri, imagesProject.id)), ) val membershipsAfterUpdate = @@ -506,7 +508,7 @@ class UserRestServiceSpec extends CoreSpec with ImplicitSender { membershipsAfterUpdate.projects should equal(Seq()) val received = UnsafeZioRun.runOrThrow( - projectRestService(_.getProjectAdminMembersById(rootUser, imagesProject.projectIri)), + projectRestService(_.getProjectAdminMembersById(rootUser, imagesProject.id)), ) received.members should not contain normalUser.ofType(UserInformationType.Restricted) } diff --git a/integration/src/test/scala/org/knora/webapi/responders/v2/OntologyResponderV2Spec.scala b/integration/src/test/scala/org/knora/webapi/responders/v2/OntologyResponderV2Spec.scala index 0b454597e4..0b214b4ab1 100644 --- a/integration/src/test/scala/org/knora/webapi/responders/v2/OntologyResponderV2Spec.scala +++ b/integration/src/test/scala/org/knora/webapi/responders/v2/OntologyResponderV2Spec.scala @@ -51,10 +51,10 @@ class OntologyResponderV2Spec extends CoreSpec with ImplicitSender { private implicit val stringFormatter: StringFormatter = StringFormatter.getGeneralInstance private val imagesUser = SharedTestDataADM.imagesUser01 - private val imagesProjectIri = SharedTestDataADM.imagesProjectIri.toSmartIri + private val imagesProjectIri = SharedTestDataADM.imagesProjectIri.value.toSmartIri private val anythingAdminUser = SharedTestDataADM.anythingAdminUser private val anythingNonAdminUser = SharedTestDataADM.anythingUser1 - private val anythingProjectIri = SharedTestDataADM.anythingProjectIri.toSmartIri + private val anythingProjectIri = SharedTestDataADM.anythingProjectIri.value.toSmartIri private val ontologyResponder = ZIO.serviceWithZIO[OntologyResponderV2] private val triplestoreService = ZIO.serviceWithZIO[TriplestoreService] @@ -636,7 +636,7 @@ class OntologyResponderV2Spec extends CoreSpec with ImplicitSender { "not create a non-shared ontology in the shared ontologies project" in { appActor ! CreateOntologyRequestV2( ontologyName = "misplaced", - projectIri = OntologyConstants.KnoraAdmin.DefaultSharedOntologiesProject.toSmartIri, + projectIri = OntologyConstants.KnoraAdmin.DefaultSharedOntologiesProject.value.toSmartIri, label = "The invalid non-shared ontology", apiRequestID = UUID.randomUUID, requestingUser = SharedTestDataADM.superUser, @@ -650,7 +650,7 @@ class OntologyResponderV2Spec extends CoreSpec with ImplicitSender { "create a shared ontology" in { appActor ! CreateOntologyRequestV2( ontologyName = "chair", - projectIri = OntologyConstants.KnoraAdmin.DefaultSharedOntologiesProject.toSmartIri, + projectIri = OntologyConstants.KnoraAdmin.DefaultSharedOntologiesProject.value.toSmartIri, isShared = true, label = "a chaired ontology", apiRequestID = UUID.randomUUID, diff --git a/integration/src/test/scala/org/knora/webapi/responders/v2/SearchResponderV2Spec.scala b/integration/src/test/scala/org/knora/webapi/responders/v2/SearchResponderV2Spec.scala index b8fa79b87b..aaca388590 100644 --- a/integration/src/test/scala/org/knora/webapi/responders/v2/SearchResponderV2Spec.scala +++ b/integration/src/test/scala/org/knora/webapi/responders/v2/SearchResponderV2Spec.scala @@ -303,7 +303,7 @@ class SearchResponderV2Spec extends CoreSpec { "search by project and resource class" in { val result = UnsafeZioRun.runOrThrow( searchResourcesByProjectAndClassV2( - projectIri = SharedTestDataADM.incunabulaProject.id.toSmartIri, + projectIri = SharedTestDataADM.incunabulaProject.id.value.toSmartIri, resourceClass = "http://0.0.0.0:3333/ontology/0803/incunabula/v2#book".toSmartIri, orderByProperty = Some("http://0.0.0.0:3333/ontology/0803/incunabula/v2#title".toSmartIri), page = 0, diff --git a/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala b/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala index 686a89a398..466f842d84 100644 --- a/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala +++ b/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala @@ -37,7 +37,7 @@ case class ProjectInfo( object ProjectInfo { def from(project: Project): ProjectInfo = ProjectInfo( - id = project.id, + id = project.id.value, shortname = project.shortname.value, shortcode = project.shortcode.value, longname = project.longname.map(_.value), diff --git a/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala b/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala index db866f5097..797c38886d 100644 --- a/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala +++ b/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala @@ -6,6 +6,7 @@ package org.knora.webapi.sharedtestdata import java.time.Instant + import dsp.constants.SalsahGui import org.knora.webapi.IRI import org.knora.webapi.messages.OntologyConstants @@ -17,6 +18,7 @@ import org.knora.webapi.slice.admin.api.model.Project import org.knora.webapi.slice.admin.domain.model.Group import org.knora.webapi.slice.admin.domain.model.KnoraProject.Logo import org.knora.webapi.slice.admin.domain.model.KnoraProject.Longname +import org.knora.webapi.slice.admin.domain.model.KnoraProject.ProjectIri import org.knora.webapi.slice.admin.domain.model.KnoraProject.SelfJoin import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortcode import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortname @@ -134,22 +136,22 @@ object SharedTestDataADM { projects = Seq(incunabulaProject, imagesProject), permissions = PermissionsDataADM( groupsPerProject = Map( - incunabulaProjectIri -> List( + incunabulaProjectIri.value -> List( KnoraGroupRepo.builtIn.ProjectMember.id.value, KnoraGroupRepo.builtIn.ProjectAdmin.id.value, ), - imagesProjectIri -> List( + imagesProjectIri.value -> List( "http://rdfh.ch/groups/00FF/images-reviewer", KnoraGroupRepo.builtIn.ProjectMember.id.value, KnoraGroupRepo.builtIn.ProjectAdmin.id.value, ), ), administrativePermissionsPerProject = Map( - incunabulaProjectIri -> Set( + incunabulaProjectIri.value -> Set( PermissionADM.from(Permission.Administrative.ProjectAdminAll), PermissionADM.from(Permission.Administrative.ProjectResourceCreateAll), ), - imagesProjectIri -> Set( + imagesProjectIri.value -> Set( PermissionADM.from(Permission.Administrative.ProjectAdminAll), PermissionADM.from(Permission.Administrative.ProjectResourceCreateAll), ), @@ -159,7 +161,7 @@ object SharedTestDataADM { /* represents the full ProjectADM of the Knora System project */ def systemProject: Project = Project( - id = KnoraProjectRepo.builtIn.SystemProject.id.value, + id = KnoraProjectRepo.builtIn.SystemProject.id, shortname = Shortname.unsafeFrom("SystemProject"), shortcode = Shortcode.unsafeFrom("FFFF"), longname = Some(Longname.unsafeFrom("Knora System Project")), @@ -201,7 +203,7 @@ object SharedTestDataADM { /** * ********************************** */ - val imagesProjectIri = "http://rdfh.ch/projects/00FF" + val imagesProjectIri: ProjectIri = ProjectIri.unsafeFrom("http://rdfh.ch/projects/00FF") /* represents 'user01' as found in admin-data.ttl */ def imagesUser01: User = @@ -218,13 +220,13 @@ object SharedTestDataADM { projects = Seq(imagesProject), permissions = PermissionsDataADM( groupsPerProject = Map( - imagesProjectIri -> List( + imagesProjectIri.value -> List( KnoraGroupRepo.builtIn.ProjectMember.id.value, KnoraGroupRepo.builtIn.ProjectAdmin.id.value, ), ), administrativePermissionsPerProject = Map( - imagesProjectIri -> Set( + imagesProjectIri.value -> Set( PermissionADM.from(Permission.Administrative.ProjectAdminAll), PermissionADM.from(Permission.Administrative.ProjectResourceCreateAll), ), @@ -247,10 +249,10 @@ object SharedTestDataADM { projects = Seq(imagesProject), permissions = PermissionsDataADM( groupsPerProject = Map( - imagesProjectIri -> List(KnoraGroupRepo.builtIn.ProjectMember.id.value), + imagesProjectIri.value -> List(KnoraGroupRepo.builtIn.ProjectMember.id.value), ), administrativePermissionsPerProject = Map( - imagesProjectIri -> Set( + imagesProjectIri.value -> Set( PermissionADM.from(Permission.Administrative.ProjectResourceCreateAll), ), ), @@ -272,13 +274,13 @@ object SharedTestDataADM { projects = Seq(imagesProject), permissions = PermissionsDataADM( groupsPerProject = Map( - imagesProjectIri -> List( + imagesProjectIri.value -> List( "http://rdfh.ch/groups/00FF/images-reviewer", KnoraGroupRepo.builtIn.ProjectMember.id.value, ), ), administrativePermissionsPerProject = Map( - imagesProjectIri -> Set( + imagesProjectIri.value -> Set( PermissionADM.from( Permission.Administrative.ProjectResourceCreateRestricted, s"${SharedOntologyTestDataADM.IMAGES_ONTOLOGY_IRI}#bild", @@ -371,7 +373,7 @@ object SharedTestDataADM { /** * ********************************** */ - val incunabulaProjectIri = "http://rdfh.ch/projects/0803" + val incunabulaProjectIri: ProjectIri = ProjectIri.unsafeFrom("http://rdfh.ch/projects/0803") /* represents 'testuser' (Incunabula ProjectAdmin) as found in admin-data.ttl */ def incunabulaProjectAdminUser: User = @@ -388,13 +390,13 @@ object SharedTestDataADM { projects = Seq(incunabulaProject), permissions = PermissionsDataADM( groupsPerProject = Map( - incunabulaProjectIri -> List( + incunabulaProjectIri.value -> List( KnoraGroupRepo.builtIn.ProjectMember.id.value, KnoraGroupRepo.builtIn.ProjectAdmin.id.value, ), ), administrativePermissionsPerProject = Map( - incunabulaProjectIri -> Set( + incunabulaProjectIri.value -> Set( PermissionADM.from(Permission.Administrative.ProjectAdminAll), PermissionADM.from(Permission.Administrative.ProjectResourceCreateAll), ), @@ -417,10 +419,10 @@ object SharedTestDataADM { projects = Seq(incunabulaProject), permissions = PermissionsDataADM( groupsPerProject = Map( - incunabulaProjectIri -> List(KnoraGroupRepo.builtIn.ProjectMember.id.value), + incunabulaProjectIri.value -> List(KnoraGroupRepo.builtIn.ProjectMember.id.value), ), administrativePermissionsPerProject = Map( - incunabulaProjectIri -> Set( + incunabulaProjectIri.value -> Set( PermissionADM.from(Permission.Administrative.ProjectResourceCreateAll), ), ), @@ -442,10 +444,10 @@ object SharedTestDataADM { projects = Seq(incunabulaProject), permissions = PermissionsDataADM( groupsPerProject = Map( - incunabulaProjectIri -> List(KnoraGroupRepo.builtIn.ProjectMember.id.value), + incunabulaProjectIri.value -> List(KnoraGroupRepo.builtIn.ProjectMember.id.value), ), administrativePermissionsPerProject = Map( - incunabulaProjectIri -> Set( + incunabulaProjectIri.value -> Set( PermissionADM.from(Permission.Administrative.ProjectResourceCreateAll), ), ), @@ -533,7 +535,7 @@ object SharedTestDataADM { /** * ********************************* */ - val anythingProjectIri = "http://rdfh.ch/projects/0001" + val anythingProjectIri: ProjectIri = ProjectIri.unsafeFrom("http://rdfh.ch/projects/0001") val customResourceIRI: IRI = "http://rdfh.ch/0001/rYAMw7wSTbGw3boYHefByg" val customResourceIRI_resourceWithValues: IRI = "http://rdfh.ch/0001/4PnSvolsTEa86KJ2EG76SQ" @@ -560,13 +562,13 @@ object SharedTestDataADM { projects = Seq(anythingProject), permissions = PermissionsDataADM( groupsPerProject = Map( - anythingProjectIri -> List( + anythingProjectIri.value -> List( KnoraGroupRepo.builtIn.ProjectMember.id.value, KnoraGroupRepo.builtIn.ProjectAdmin.id.value, ), ), administrativePermissionsPerProject = Map( - anythingProjectIri -> Set( + anythingProjectIri.value -> Set( PermissionADM.from(Permission.Administrative.ProjectAdminAll), PermissionADM.from(Permission.Administrative.ProjectResourceCreateAll), ), @@ -588,13 +590,13 @@ object SharedTestDataADM { projects = Seq(anythingProject), permissions = PermissionsDataADM( groupsPerProject = Map( - anythingProjectIri -> List( + anythingProjectIri.value -> List( KnoraGroupRepo.builtIn.ProjectMember.id.value, "http://rdfh.ch/groups/0001/thing-searcher", ), ), administrativePermissionsPerProject = Map( - anythingProjectIri -> Set( + anythingProjectIri.value -> Set( PermissionADM.from(Permission.Administrative.ProjectResourceCreateAll), ), ), @@ -615,10 +617,10 @@ object SharedTestDataADM { projects = Seq(anythingProject), permissions = PermissionsDataADM( groupsPerProject = Map( - anythingProjectIri -> List(KnoraGroupRepo.builtIn.ProjectMember.id.value), + anythingProjectIri.value -> List(KnoraGroupRepo.builtIn.ProjectMember.id.value), ), administrativePermissionsPerProject = Map( - anythingProjectIri -> Set( + anythingProjectIri.value -> Set( PermissionADM.from(Permission.Administrative.ProjectResourceCreateAll), ), ), @@ -675,7 +677,7 @@ object SharedTestDataADM { /** * ********************************* */ - val beolProjectIri = "http://rdfh.ch/projects/yTerZGyxjZVqFMNNKXCDPF" + val beolProjectIri: ProjectIri = ProjectIri.unsafeFrom("http://rdfh.ch/projects/yTerZGyxjZVqFMNNKXCDPF") def beolProject: Project = Project( id = beolProjectIri, @@ -711,13 +713,13 @@ object SharedTestDataADM { projects = Seq(beolProject), permissions = PermissionsDataADM( groupsPerProject = Map( - beolProjectIri -> List( + beolProjectIri.value -> List( KnoraGroupRepo.builtIn.ProjectMember.id.value, KnoraGroupRepo.builtIn.ProjectAdmin.id.value, ), ), administrativePermissionsPerProject = Map( - beolProjectIri -> Set( + beolProjectIri.value -> Set( PermissionADM.from(Permission.Administrative.ProjectAdminAll), ), ), @@ -731,7 +733,7 @@ object SharedTestDataADM { /** * ********************************* */ - val dokubibProjectIri = "http://rdfh.ch/projects/0804" + val dokubibProjectIri: ProjectIri = ProjectIri.unsafeFrom("http://rdfh.ch/projects/0804") def dokubibProject: Project = Project( id = dokubibProjectIri, diff --git a/integration/src/test/scala/org/knora/webapi/sharedtestdata/UserProfile.scala b/integration/src/test/scala/org/knora/webapi/sharedtestdata/UserProfile.scala index ca663afa12..34dba78e98 100644 --- a/integration/src/test/scala/org/knora/webapi/sharedtestdata/UserProfile.scala +++ b/integration/src/test/scala/org/knora/webapi/sharedtestdata/UserProfile.scala @@ -35,7 +35,7 @@ object UserProfile { val v1Groups: Seq[IRI] = userADM.groups.map(_.id) val projectsWithoutBuiltinProjects = userADM.projects - .filter(_.id != KnoraProjectRepo.builtIn.SystemProject.id.value) + .filter(_.id != KnoraProjectRepo.builtIn.SystemProject.id) .filter(_.id != OntologyConstants.KnoraAdmin.DefaultSharedOntologiesProject) val projectInfosV1 = projectsWithoutBuiltinProjects.map(ProjectInfo.from) val projects_info_v1: Map[IRI, ProjectInfo] = diff --git a/integration/src/test/scala/org/knora/webapi/slice/admin/domain/service/KnoraUserToUserConverterSpec.scala b/integration/src/test/scala/org/knora/webapi/slice/admin/domain/service/KnoraUserToUserConverterSpec.scala index a6c10f6623..6e6d1e3cfa 100644 --- a/integration/src/test/scala/org/knora/webapi/slice/admin/domain/service/KnoraUserToUserConverterSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/slice/admin/domain/service/KnoraUserToUserConverterSpec.scala @@ -34,7 +34,7 @@ object KnoraUserToUserConverterSpec extends E2EZSpec { isInProject: Iterable[IRI], isInGroup: Iterable[IRI], systemAdmin: SystemAdmin, - isInProjectAdminGroup: Iterable[IRI], + isInProjectAdminGroup: Iterable[ProjectIri], ) = KnoraUser( UserIri.unsafeFrom("http://rdfh.ch/users/dummy"), Username.unsafeFrom("dummy"), @@ -47,7 +47,7 @@ object KnoraUserToUserConverterSpec extends E2EZSpec { isInProject.map(ProjectIri.unsafeFrom).toChunk, isInGroup.map(GroupIri.unsafeFrom).toChunk, systemAdmin, - isInProjectAdminGroup.map(ProjectIri.unsafeFrom).toChunk, + isInProjectAdminGroup.toChunk, ) private val knoraUserToUserConverter = ZIO.serviceWithZIO[KnoraUserToUserConverter] diff --git a/webapi/src/main/scala/org/knora/webapi/messages/OntologyConstants.scala b/webapi/src/main/scala/org/knora/webapi/messages/OntologyConstants.scala index ed6fc1db1e..b94d6a91c7 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/OntologyConstants.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/OntologyConstants.scala @@ -7,6 +7,7 @@ package org.knora.webapi package messages import dsp.constants.SalsahGui +import org.knora.webapi.slice.admin.domain.model.KnoraProject.ProjectIri /** * Contains string constants for IRIs from ontologies used by the application. @@ -495,7 +496,8 @@ object OntologyConstants { HasDefaultChangeRightsPermission, ) - val DefaultSharedOntologiesProject: IRI = KnoraAdminPrefixExpansion + "DefaultSharedOntologiesProject" + val DefaultSharedOntologiesProject: ProjectIri = + ProjectIri.unsafeFrom(KnoraAdminPrefixExpansion + "DefaultSharedOntologiesProject") } object Standoff { diff --git a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/resourcemessages/ResourceMessagesV2.scala b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/resourcemessages/ResourceMessagesV2.scala index 43a2623aed..950bd172e6 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/resourcemessages/ResourceMessagesV2.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/resourcemessages/ResourceMessagesV2.scala @@ -435,7 +435,7 @@ case class ReadResourceV2( val metadataForComplexSchema: Map[IRI, JsonLDValue] = if (targetSchema == ApiV2Complex) { val requiredMetadataForComplexSchema: Map[IRI, JsonLDValue] = Map( KnoraApiV2Complex.AttachedToUser -> JsonLDUtil.iriToJsonLDObject(attachedToUser), - KnoraApiV2Complex.AttachedToProject -> JsonLDUtil.iriToJsonLDObject(projectADM.id), + KnoraApiV2Complex.AttachedToProject -> JsonLDUtil.iriToJsonLDObject(projectADM.id.value), KnoraApiV2Complex.HasPermissions -> JsonLDString(permissions), KnoraApiV2Complex.UserHasPermission -> JsonLDString(userPermission.toString), KnoraApiV2Complex.CreationDate -> JsonLDUtil.datatypeValueToJsonLDObject( @@ -1193,7 +1193,7 @@ case class ResourceEventBody( Map( KnoraApiV2Complex.ResourceIri -> JsonLDString(resourceIri), KnoraApiV2Complex.ResourceClassIri -> JsonLDString(resourceClassIri.toString), - KnoraApiV2Complex.AttachedToProject -> JsonLDUtil.iriToJsonLDObject(projectADM.id), + KnoraApiV2Complex.AttachedToProject -> JsonLDUtil.iriToJsonLDObject(projectADM.id.value), ) ++ resourceLabel ++ creationDateAsJsonLD ++ propertiesAndValuesAsJsonLD ++ lastModificationDateAsJsonLD ++ deletionInfoAsJsonLD ++ permissionAsJsonLD, ) diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/PermissionsResponder.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/PermissionsResponder.scala index e9b7e8adf4..c71bc1eafe 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/PermissionsResponder.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/PermissionsResponder.scala @@ -75,11 +75,11 @@ final case class PermissionsResponder( case Property } - def getPermissionsApByProjectIri(projectIRI: IRI): Task[AdministrativePermissionsForProjectGetResponseADM] = + def getPermissionsApByProjectIri(projectIri: ProjectIri): Task[AdministrativePermissionsForProjectGetResponseADM] = for { permissionsQueryResponseRows <- triplestore - .query(Select(sparql.admin.txt.getAdministrativePermissionsForProject(projectIRI))) + .query(Select(sparql.admin.txt.getAdministrativePermissionsForProject(projectIri.value))) .map(_.results.bindings) permissionsWithProperties = diff --git a/webapi/src/main/scala/org/knora/webapi/responders/v2/OntologyResponderV2.scala b/webapi/src/main/scala/org/knora/webapi/responders/v2/OntologyResponderV2.scala index f0917addd3..325dc8e3e7 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/v2/OntologyResponderV2.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/v2/OntologyResponderV2.scala @@ -436,7 +436,7 @@ final case class OntologyResponderV2( // If this is a shared ontology, make sure it's in the default shared ontologies project. _ <- ZIO.when( - createOntologyRequest.isShared && createOntologyRequest.projectIri.toString != OntologyConstants.KnoraAdmin.DefaultSharedOntologiesProject, + createOntologyRequest.isShared && createOntologyRequest.projectIri.toString != OntologyConstants.KnoraAdmin.DefaultSharedOntologiesProject.value, ) { val msg = s"Shared ontologies must be created in project <${OntologyConstants.KnoraAdmin.DefaultSharedOntologiesProject}>" @@ -446,7 +446,7 @@ final case class OntologyResponderV2( // If it's in the default shared ontologies project, make sure it's a shared ontology. _ <- ZIO.when( - createOntologyRequest.projectIri.toString == OntologyConstants.KnoraAdmin.DefaultSharedOntologiesProject && !createOntologyRequest.isShared, + createOntologyRequest.projectIri.toString == OntologyConstants.KnoraAdmin.DefaultSharedOntologiesProject.value && !createOntologyRequest.isShared, ) { val msg = s"Ontologies created in project <${OntologyConstants.KnoraAdmin.DefaultSharedOntologiesProject}> must be shared" diff --git a/webapi/src/main/scala/org/knora/webapi/responders/v2/ResourceUtilV2.scala b/webapi/src/main/scala/org/knora/webapi/responders/v2/ResourceUtilV2.scala index 6f5053fc20..9e439d5149 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/v2/ResourceUtilV2.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/v2/ResourceUtilV2.scala @@ -122,7 +122,7 @@ final case class ResourceUtilV2Live(triplestore: TriplestoreService, sipiService ): IO[ForbiddenException, Unit] = { val maybeUserPermission: Option[Permission.ObjectAccess] = PermissionUtilADM.getUserPermissionADM( entityCreator = resourceInfo.attachedToUser, - entityProject = resourceInfo.projectADM.id, + entityProject = resourceInfo.projectADM.id.value, entityPermissionLiteral = resourceInfo.permissions, requestingUser = requestingUser, ) @@ -155,7 +155,7 @@ final case class ResourceUtilV2Live(triplestore: TriplestoreService, sipiService ): IO[ForbiddenException, Unit] = { val maybeUserPermission: Option[Permission.ObjectAccess] = PermissionUtilADM.getUserPermissionADM( entityCreator = valueInfo.attachedToUser, - entityProject = resourceInfo.projectADM.id, + entityProject = resourceInfo.projectADM.id.value, entityPermissionLiteral = valueInfo.permissions, requestingUser = requestingUser, ) diff --git a/webapi/src/main/scala/org/knora/webapi/responders/v2/ResourcesResponderV2.scala b/webapi/src/main/scala/org/knora/webapi/responders/v2/ResourcesResponderV2.scala index e3ae11382c..e46ae77cfd 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/v2/ResourcesResponderV2.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/v2/ResourcesResponderV2.scala @@ -455,7 +455,7 @@ final case class ResourcesResponderV2( // Ensure that the requesting user is a system admin, or an admin of this project. _ <- ZIO.when( - !(eraseResourceV2.requestingUser.permissions.isProjectAdmin(resource.projectADM.id) || + !(eraseResourceV2.requestingUser.permissions.isProjectAdmin(resource.projectADM.id.value) || eraseResourceV2.requestingUser.permissions.isSystemAdmin), ) { ZIO.fail(ForbiddenException(s"Only a system admin or project admin can erase a resource")) diff --git a/webapi/src/main/scala/org/knora/webapi/responders/v2/ValuesResponderV2.scala b/webapi/src/main/scala/org/knora/webapi/responders/v2/ValuesResponderV2.scala index e2895a263b..833e4b4eef 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/v2/ValuesResponderV2.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/v2/ValuesResponderV2.scala @@ -241,7 +241,7 @@ final case class ValuesResponderV2( // Get the default permissions for the new value. defaultValuePermissions <- permissionsResponder.newValueDefaultObjectAccessPermissions( - resourceInfo.projectADM.projectIri, + resourceInfo.projectADM.id, resourceInfo.resourceClassIri, submittedInternalPropertyIri, requestingUser, @@ -262,7 +262,7 @@ final case class ValuesResponderV2( // No. Make sure they don't give themselves higher permissions than they would get from the default permissions. val permissionComparisonResult: PermissionComparisonResult = PermissionUtilADM.comparePermissionsADM( - entityProject = resourceInfo.projectADM.id, + entityProject = resourceInfo.projectADM.id.value, permissionLiteralA = validatedCustomPermissions, permissionLiteralB = defaultValuePermissions.permissionLiteral, requestingUser = requestingUser, diff --git a/webapi/src/main/scala/org/knora/webapi/responders/v2/ontology/OntologyTriplestoreHelpers.scala b/webapi/src/main/scala/org/knora/webapi/responders/v2/ontology/OntologyTriplestoreHelpers.scala index 5661b16475..d6d3f383f3 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/v2/ontology/OntologyTriplestoreHelpers.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/v2/ontology/OntologyTriplestoreHelpers.scala @@ -152,7 +152,7 @@ final case class OntologyTriplestoreHelpersLive( } if ( - internalOntologyIri.isKnoraSharedDefinitionIri && projectIri.toString != OntologyConstants.KnoraAdmin.DefaultSharedOntologiesProject + internalOntologyIri.isKnoraSharedDefinitionIri && projectIri != OntologyConstants.KnoraAdmin.DefaultSharedOntologiesProject ) { throw InconsistentRepositoryDataException( s"Shared ontology $internalOntologyIri must be in project ${OntologyConstants.KnoraAdmin.DefaultSharedOntologiesProject}", diff --git a/webapi/src/main/scala/org/knora/webapi/responders/v2/resources/CreateResourceV2Handler.scala b/webapi/src/main/scala/org/knora/webapi/responders/v2/resources/CreateResourceV2Handler.scala index 66f509f084..e2a64a6c20 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/v2/resources/CreateResourceV2Handler.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/v2/resources/CreateResourceV2Handler.scala @@ -96,7 +96,7 @@ final case class CreateResourceV2Handler( for { _ <- ensureNotAnonymousUser(createResourceRequestV2.requestingUser) _ <- ensureClassBelongsToProjectOntology(createResourceRequestV2) - projectIri = createResourceRequestV2.createResource.projectADM.id + projectIri = createResourceRequestV2.createResource.projectADM.id.value _ <- ensureUserHasPermission(createResourceRequestV2, projectIri) resourceIri <- @@ -119,10 +119,10 @@ final case class CreateResourceV2Handler( private def ensureClassBelongsToProjectOntology(createResourceRequestV2: CreateResourceRequestV2): Task[Unit] = for { projectIri <- ZIO.succeed(createResourceRequestV2.createResource.projectADM.id) isSystemOrSharedProject = - projectIri == KnoraProjectRepo.builtIn.SystemProject.id.value || + projectIri == KnoraProjectRepo.builtIn.SystemProject.id || projectIri == OntologyConstants.KnoraAdmin.DefaultSharedOntologiesProject _ <- ZIO.when(isSystemOrSharedProject)( - ZIO.fail(BadRequestException(s"Resources cannot be created in project <$projectIri>")), + ZIO.fail(BadRequestException(s"Resources cannot be created in project <${projectIri.value}>")), ) resourceClassOntologyIri = @@ -136,11 +136,11 @@ final case class CreateResourceV2Handler( ZIO .fail( BadRequestException( - s"Cannot create a resource in project <$projectIri> with resource class <${createResourceRequestV2.createResource.resourceClassIri}>, which is defined in a non-shared ontology in another project", + s"Cannot create a resource in project <${projectIri.value}> with resource class <${createResourceRequestV2.createResource.resourceClassIri}>, which is defined in a non-shared ontology in another project", ), ) .unless( - projectIri == resourceClassProjectIri || OntologyServiceLive.isBuiltInOrSharedOntology( + projectIri.value == resourceClassProjectIri || OntologyServiceLive.isBuiltInOrSharedOntology( resourceClassOntologyIri, ), ) @@ -221,14 +221,14 @@ final case class CreateResourceV2Handler( // Get the default permissions of the resource class. defaultResourcePermissions <- permissionsResponder.newResourceDefaultObjectAccessPermissions( - createResourceRequestV2.createResource.projectADM.projectIri, + createResourceRequestV2.createResource.projectADM.id, internalCreateResource.resourceClassIri, createResourceRequestV2.requestingUser, ) // Get the default permissions of each property used. defaultPropertyPermissionsMap <- permissionsResponder.newValueDefaultObjectAccessPermissions( - createResourceRequestV2.createResource.projectADM.projectIri, + createResourceRequestV2.createResource.projectADM.id, internalCreateResource.resourceClassIri, internalCreateResource.values.keySet, createResourceRequestV2.requestingUser, @@ -254,7 +254,7 @@ final case class CreateResourceV2Handler( _ <- resourcesRepo.createNewResource( dataGraphIri = dataNamedGraph, resource = resourceReadyToCreate, - projectIri = InternalIri(createResourceRequestV2.createResource.projectADM.id), + projectIri = InternalIri(createResourceRequestV2.createResource.projectADM.id.value), userIri = InternalIri(createResourceRequestV2.requestingUser.id), ) @@ -382,13 +382,13 @@ final case class CreateResourceV2Handler( validatedCustomPermissions <- permissionUtilADM.validatePermissions(permissionStr) _ <- ZIO.when { - !(requestingUser.permissions.isProjectAdmin(internalCreateResource.projectADM.id) && + !(requestingUser.permissions.isProjectAdmin(internalCreateResource.projectADM.id.value) && !requestingUser.permissions.isSystemAdmin) } { // Make sure they don't give themselves higher permissions than they would get from the default permissions. val permissionComparisonResult: PermissionComparisonResult = PermissionUtilADM.comparePermissionsADM( - internalCreateResource.projectADM.id, + internalCreateResource.projectADM.id.value, validatedCustomPermissions, defaultResourcePermissions, requestingUser, @@ -844,14 +844,14 @@ final case class CreateResourceV2Handler( // Is the requesting user a system admin, or an admin of this project? _ <- ZIO.when( !(requestingUser.permissions - .isProjectAdmin(project.id) || requestingUser.permissions.isSystemAdmin), + .isProjectAdmin(project.id.value) || requestingUser.permissions.isSystemAdmin), ) { // No. Make sure they don't give themselves higher permissions than they would get from the default permissions. val permissionComparisonResult: PermissionComparisonResult = PermissionUtilADM.comparePermissionsADM( - entityProject = project.id, + entityProject = project.id.value, permissionLiteralA = validatedCustomPermissions, permissionLiteralB = defaultPropertyPermissions(propertyIri), requestingUser = requestingUser, diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala index 50ba4de1e7..2d3895e0d9 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala @@ -90,7 +90,7 @@ object Examples { ) private val project: Project = Project( - id = ProjectExample.projectIri.value, + id = ProjectExample.projectIri, shortname = Shortname.unsafeFrom("example"), shortcode = Shortcode.unsafeFrom("0001"), longname = Some(Longname.unsafeFrom("Example Project")), diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala index feb3f52908..65692df527 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala @@ -31,7 +31,7 @@ import org.knora.webapi.slice.admin.domain.model.User * @param selfjoin The project's self-join status. */ case class Project( - id: IRI, + id: ProjectIri, shortname: Shortname, shortcode: Shortcode, longname: Option[Longname], @@ -45,12 +45,10 @@ case class Project( license: Option[License], ) extends Ordered[Project] { - def projectIri: ProjectIri = ProjectIri.unsafeFrom(id) - /** * Allows to sort collections of ProjectADM. Sorting is done by the id. */ - def compare(that: Project): Int = this.id.compareTo(that.id) + def compare(that: Project): Int = this.id.value.compareTo(that.id.value) } object Project { implicit val projectCodec: JsonCodec[Project] = DeriveJsonCodec.gen[Project] diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/PermissionRestService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/PermissionRestService.scala index c08c31cd16..5a253d9b73 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/PermissionRestService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/PermissionRestService.scala @@ -70,12 +70,12 @@ final case class PermissionRestService( .tap(auth.ensureSystemAdminOrProjectAdmin(user, _)) def getPermissionsApByProjectIri( - value: ProjectIri, + projectIri: ProjectIri, user: User, ): Task[AdministrativePermissionsForProjectGetResponseADM] = for { - _ <- ensureProjectIriExistsAndUserHasAccess(value, user) - result <- responder.getPermissionsApByProjectIri(value.value) + _ <- ensureProjectIriExistsAndUserHasAccess(projectIri, user) + result <- responder.getPermissionsApByProjectIri(projectIri) ext <- format.toExternal(result) } yield ext diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectRestService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectRestService.scala index a95e882321..227143f2ab 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectRestService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectRestService.scala @@ -62,7 +62,7 @@ final case class ProjectRestService( */ def listAllProjects(): Task[ProjectsGetResponse] = for { internal <- projectService.findAllRegularProjects - projects = internal.filter(_.projectIri.isRegularProjectIri) + projects = internal.filter(_.id.isRegularProjectIri) external <- format.toExternal(ProjectsGetResponse(projects)) } yield external @@ -107,7 +107,7 @@ final case class ProjectRestService( }, ) internal <- projectService.createProject(createReq).map(ProjectOperationResponseADM.apply) - _ <- permissionResponder.createPermissionsForAdminsAndMembersOfNewProject(internal.project.projectIri) + _ <- permissionResponder.createPermissionsForAdminsAndMembersOfNewProject(internal.project.id) external <- format.toExternal(internal) } yield external diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/GroupService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/GroupService.scala index 1266efa4b9..9b1103a512 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/GroupService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/GroupService.scala @@ -51,7 +51,7 @@ final case class GroupService( groupName = GroupName.unsafeFrom(group.name), groupDescriptions = GroupDescriptions.unsafeFrom(group.descriptions), status = GroupStatus.from(group.status), - belongsToProject = group.project.map(it => ProjectIri.unsafeFrom(it.id)), + belongsToProject = group.project.map(_.id), hasSelfJoinEnabled = GroupSelfJoin.from(group.selfjoin), ) diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraUserService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraUserService.scala index 2f4b7af7ba..e370cd54c3 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraUserService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraUserService.scala @@ -161,8 +161,8 @@ case class KnoraUserService( userRepo.save(user.copy(isInGroup = user.isInGroup.filterNot(_ == groupIri))).orDie def addUserToProject(user: KnoraUser, project: Project): IO[IsProjectMember, KnoraUser] = for { - _ <- ZIO.fail(IsProjectMember(user.id, project.projectIri)).when(user.isInProject.contains(project.projectIri)) - user <- addUserToProject(user, project.projectIri) + _ <- ZIO.fail(IsProjectMember(user.id, project.id)).when(user.isInProject.contains(project.id)) + user <- addUserToProject(user, project.id) } yield user def addUserToProject(user: KnoraUser, project: KnoraProject): UIO[KnoraUser] = addUserToProject(user, project.id) @@ -179,7 +179,7 @@ case class KnoraUserService( * @return The updated user. If the user is not a member of the project, an error is returned. */ def removeUserFromProject(user: KnoraUser, project: Project): IO[NotProjectMember, KnoraUser] = - removeUserFromProject(user, project.projectIri) + removeUserFromProject(user, project.id) def removeUsersFromProject(users: Seq[KnoraUser], project: KnoraProject): UIO[Unit] = ZIO.foreachDiscard(users)(removeUserFromProject(_, project.id).ignore) @@ -203,14 +203,12 @@ case class KnoraUserService( def addUserToProjectAsAdmin( user: KnoraUser, project: Project, - ): IO[IsProjectAdminMember | NotProjectMember, KnoraUser] = { - val projectIri = project.projectIri + ): IO[IsProjectAdminMember | NotProjectMember, KnoraUser] = for { - _ <- ZIO.fail(IsProjectAdminMember(user.id, projectIri)).when(user.isInProjectAdminGroup.contains(projectIri)) - _ <- ZIO.fail(NotProjectMember(user.id, projectIri)).unless(user.isInProject.contains(projectIri)) - _ <- addUserToProjectAsAdmin(user, projectIri) + _ <- ZIO.fail(IsProjectAdminMember(user.id, project.id)).when(user.isInProjectAdminGroup.contains(project.id)) + _ <- ZIO.fail(NotProjectMember(user.id, project.id)).unless(user.isInProject.contains(project.id)) + _ <- addUserToProjectAsAdmin(user, project.id) } yield user - } def addUserToProjectAsAdmin(user: KnoraUser, project: KnoraProject): UIO[KnoraUser] = addUserToProjectAsAdmin(user, project.id) @@ -227,7 +225,7 @@ case class KnoraUserService( * @return The updated user. If the user is not an admin member of the project, an error is returned. */ def removeUserFromProjectAsAdmin(user: KnoraUser, project: Project): IO[NotProjectAdminMember, KnoraUser] = - removeUserFromProjectIriAsAdmin(user, project.projectIri) + removeUserFromProjectIriAsAdmin(user, project.id) def removeUsersFromProjectAsAdmin(users: Seq[KnoraUser], project: KnoraProject): IO[NotProjectAdminMember, Unit] = ZIO.foreachDiscard(users)(removeUserFromProjectIriAsAdmin(_, project.id)) diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala index 158a21a72a..46f18ea4b9 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala @@ -46,7 +46,7 @@ final case class ProjectService( .map(_.map(_.ontologyMetadata.ontologyIri.toIri)) .map(ontologies => Project( - knoraProject.id.value, + knoraProject.id, knoraProject.shortname, knoraProject.shortcode, knoraProject.longname, @@ -63,7 +63,7 @@ final case class ProjectService( private def toKnoraProject(project: Project, restrictedView: RestrictedView): KnoraProject = KnoraProject( - id = ProjectIri.unsafeFrom(project.id), + id = project.id, shortname = project.shortname, shortcode = project.shortcode, longname = project.longname, diff --git a/webapi/src/main/scala/org/knora/webapi/slice/common/ApiComplexV2JsonLdRequestParser.scala b/webapi/src/main/scala/org/knora/webapi/slice/common/ApiComplexV2JsonLdRequestParser.scala index 23f7593ece..d009a2b412 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/common/ApiComplexV2JsonLdRequestParser.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/common/ApiComplexV2JsonLdRequestParser.scala @@ -243,7 +243,7 @@ final case class ApiComplexV2JsonLdRequestParser( _ <- ZIO .fail("Resource IRI and project IRI must reference the same project") .when(r.resourceIri.exists(_.shortcode != project.shortcode)) - attachedToUser <- attachedToUser(r.resource, requestingUser, project.projectIri) + attachedToUser <- attachedToUser(r.resource, requestingUser, project.id) values <- extractValues(r.resource, project.shortcode, ingestState) } yield CreateResourceRequestV2( CreateResourceV2( diff --git a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala index ef5f7d1b30..f7badf15e1 100644 --- a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala @@ -48,7 +48,7 @@ object ProjectServiceSpec extends ZIOSpecDefault { val shortcode = "0002" val shortname = "someOtherProject" val p: KnoraProject = KnoraProject( - id = ProjectIri.unsafeFrom(IriTestConstants.Project.TestProject), + id = IriTestConstants.Project.TestProject, shortname = Shortname.unsafeFrom(shortname), shortcode = Shortcode.unsafeFrom(shortcode), longname = None, diff --git a/webapi/src/test/scala/org/knora/webapi/slice/ontology/api/service/RestCardinalityServiceLiveSpec.scala b/webapi/src/test/scala/org/knora/webapi/slice/ontology/api/service/RestCardinalityServiceLiveSpec.scala index f8cafb8dc1..16f2c919e0 100644 --- a/webapi/src/test/scala/org/knora/webapi/slice/ontology/api/service/RestCardinalityServiceLiveSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/slice/ontology/api/service/RestCardinalityServiceLiveSpec.scala @@ -36,10 +36,10 @@ object RestCardinalityServiceLiveSpec extends ZIOSpecDefault { .addOntology( ReadOntologyV2Builder .builder(IriTestConstants.Biblio.Ontology) - .assignToProject(IriTestConstants.Project.TestProject), + .assignToProject(IriTestConstants.Project.TestProject.value), ) .build - private val projectIri: IRI = IriTestConstants.Project.TestProject + private val projectIri: IRI = IriTestConstants.Project.TestProject.value private val classIri: IRI = IriTestConstants.Biblio.Class.Article.value private val propertyIri: IRI = IriTestConstants.Biblio.Property.hasTitle.value private val userWithAccess: User = diff --git a/webapi/src/test/scala/org/knora/webapi/slice/resourceinfo/domain/IriTestConstants.scala b/webapi/src/test/scala/org/knora/webapi/slice/resourceinfo/domain/IriTestConstants.scala index 26feb8a413..38e9d9e5e7 100644 --- a/webapi/src/test/scala/org/knora/webapi/slice/resourceinfo/domain/IriTestConstants.scala +++ b/webapi/src/test/scala/org/knora/webapi/slice/resourceinfo/domain/IriTestConstants.scala @@ -5,10 +5,11 @@ package org.knora.webapi.slice.resourceinfo.domain import org.knora.webapi.IRI +import org.knora.webapi.slice.admin.domain.model.KnoraProject.ProjectIri object IriTestConstants { object Project { - val TestProject: IRI = "http://rdfh.ch/projects/0000" + val TestProject: ProjectIri = ProjectIri.unsafeFrom("http://rdfh.ch/projects/0000") } private def makeEntity(ontologyIri: InternalIri, entityName: String) = InternalIri(s"${ontologyIri.value}#$entityName") From 804e35a22f91d7754b9cff564efc4730a14aee23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinb=C3=B6lting?= Date: Fri, 15 Nov 2024 19:35:26 +0100 Subject: [PATCH 17/18] refactor: Make Project.keywords typed --- .../webapi/e2e/admin/ProjectsADME2ESpec.scala | 2 +- .../IntegrationTestAdminJsonProtocol.scala | 5 ++++ .../admin/ProjectRestServiceSpec.scala | 2 +- .../sharedtestdata/SharedTestDataADM.scala | 25 ++++++++++--------- .../webapi/slice/admin/api/Examples.scala | 3 ++- .../admin/api/model/ProjectsMessagesADM.scala | 2 +- .../admin/domain/service/ProjectService.scala | 4 +-- 7 files changed, 25 insertions(+), 18 deletions(-) diff --git a/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2ESpec.scala b/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2ESpec.scala index 7c87fee891..e3794abe63 100644 --- a/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2ESpec.scala +++ b/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2ESpec.scala @@ -362,7 +362,7 @@ class ProjectsADME2ESpec extends E2ESpec with SprayJsonSupport { result.description should be( Seq(StringLiteralV2.from(value = "updated project description", language = Some("en"))), ) - result.keywords.sorted should be(Seq("updated", "keywords").sorted) + result.keywords.map(_.value).sorted should be(Seq("updated", "keywords").sorted) result.logo should be(Some("/fu/bar/baz-updated.jpg")) result.status should be(Status.Active) result.selfjoin should be(SelfJoin.CanJoin) diff --git a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala index 9d2d1385a8..da2ff2d18a 100644 --- a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala +++ b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala @@ -46,6 +46,7 @@ import org.knora.webapi.slice.admin.api.model.ProjectMembersGetResponseADM import org.knora.webapi.slice.admin.api.model.ProjectOperationResponseADM import org.knora.webapi.slice.admin.domain.model.Group import org.knora.webapi.slice.admin.domain.model.KnoraProject.CopyrightAttribution +import org.knora.webapi.slice.admin.domain.model.KnoraProject.Keyword import org.knora.webapi.slice.admin.domain.model.KnoraProject.License import org.knora.webapi.slice.admin.domain.model.KnoraProject.Logo import org.knora.webapi.slice.admin.domain.model.KnoraProject.Longname @@ -241,6 +242,10 @@ object IntegrationTestAdminJsonProtocol extends TriplestoreJsonProtocol { override val from: String => Either[String, Logo] = Logo.from } + implicit object KeywordFormat extends StringValueFormat[Keyword] { + override val from: String => Either[String, Keyword] = Keyword.from + } + trait BooleanValueFormat[T <: BooleanValue] extends JsonFormat[T] { self => def from: Boolean => T override def write(v: T): JsValue = JsString(v.value.toString) diff --git a/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala b/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala index 38b3268a04..a8c9a827f0 100644 --- a/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectRestServiceSpec.scala @@ -407,7 +407,7 @@ class ProjectRestServiceSpec extends CoreSpec with ImplicitSender { ), ), ) - received.project.keywords.sorted should be(Seq("updated", "keywords").sorted) + received.project.keywords.map(_.value).sorted should be(List("updated", "keywords").sorted) received.project.logo should be(Some("/fu/bar/baz-updated.jpg")) received.project.status should be(Status.Active) received.project.selfjoin should be(SelfJoin.CanJoin) diff --git a/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala b/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala index 797c38886d..aef55eb351 100644 --- a/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala +++ b/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala @@ -16,6 +16,7 @@ import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 import org.knora.webapi.messages.util.KnoraSystemInstances import org.knora.webapi.slice.admin.api.model.Project import org.knora.webapi.slice.admin.domain.model.Group +import org.knora.webapi.slice.admin.domain.model.KnoraProject.Keyword import org.knora.webapi.slice.admin.domain.model.KnoraProject.Logo import org.knora.webapi.slice.admin.domain.model.KnoraProject.Longname import org.knora.webapi.slice.admin.domain.model.KnoraProject.ProjectIri @@ -166,7 +167,7 @@ object SharedTestDataADM { shortcode = Shortcode.unsafeFrom("FFFF"), longname = Some(Longname.unsafeFrom("Knora System Project")), description = Seq(StringLiteralV2.from(value = "Knora System Project", language = Some("en"))), - keywords = Seq.empty[String], + keywords = List.empty, logo = None, ontologies = Seq( OntologyConstants.KnoraBase.KnoraBaseOntologyIri, @@ -187,7 +188,7 @@ object SharedTestDataADM { shortcode = Shortcode.unsafeFrom("0000"), longname = Some(Longname.unsafeFrom("Default Knora Shared Ontologies Project")), description = Seq(StringLiteralV2.from(value = "Default Knora Shared Ontologies Project", language = Some("en"))), - keywords = Seq.empty[String], + keywords = List.empty, logo = None, ontologies = Seq.empty[IRI], status = Status.Active, @@ -301,7 +302,7 @@ object SharedTestDataADM { shortcode = Shortcode.unsafeFrom("00FF"), longname = Some(Longname.unsafeFrom("Image Collection Demo")), description = Seq(StringLiteralV2.from(value = "A demo project of a collection of images", language = Some("en"))), - keywords = Seq("images", "collection").sorted, + keywords = List("images", "collection").map(Keyword.unsafeFrom), logo = None, ontologies = Seq(SharedOntologyTestDataADM.IMAGES_ONTOLOGY_IRI), status = Status.Active, @@ -317,7 +318,7 @@ object SharedTestDataADM { shortcode = Shortcode.unsafeFrom("00FF"), longname = Some(Longname.unsafeFrom("Image Collection Demo")), description = Seq(StringLiteralV2.from(value = "A demo project of a collection of images", language = Some("en"))), - keywords = Seq("images", "collection").sorted, + keywords = List("images", "collection").map(Keyword.unsafeFrom), logo = None, ontologies = Seq(SharedOntologyTestDataADM.IMAGES_ONTOLOGY_IRI_LocalHost), status = Status.Active, @@ -467,7 +468,7 @@ object SharedTestDataADM { language = None, ), ), - keywords = Seq( + keywords = List( "Basler Frühdrucke", "Inkunabel", "Narrenschiff", @@ -482,7 +483,7 @@ object SharedTestDataADM { "Letterpress Printing", "Basel", "Contectualisation of images", - ).sorted, + ).map(Keyword.unsafeFrom), logo = Some(Logo.unsafeFrom("incunabula_logo.png")), ontologies = Seq(SharedOntologyTestDataADM.INCUNABULA_ONTOLOGY_IRI), status = Status.Active, @@ -504,7 +505,7 @@ object SharedTestDataADM { language = None, ), ), - keywords = Seq( + keywords = List( "Basler Frühdrucke", "Inkunabel", "Narrenschiff", @@ -519,7 +520,7 @@ object SharedTestDataADM { "Letterpress Printing", "Basel", "Contectualisation of images", - ).sorted, + ).map(Keyword.unsafeFrom), logo = Some(Logo.unsafeFrom("incunabula_logo.png")), ontologies = Seq(SharedOntologyTestDataADM.INCUNABULA_ONTOLOGY_IRI_LocalHost), status = Status.Active, @@ -633,7 +634,7 @@ object SharedTestDataADM { shortcode = Shortcode.unsafeFrom("0001"), longname = Some(Longname.unsafeFrom("Anything Project")), description = Seq(StringLiteralV2.from(value = "Anything Project", language = None)), - keywords = Seq("things", "arbitrary test data").sorted, + keywords = List("things", "arbitrary test data").map(Keyword.unsafeFrom), logo = None, ontologies = Seq(SharedOntologyTestDataADM.ANYTHING_ONTOLOGY_IRI, SharedOntologyTestDataADM.SomethingOntologyIri), status = Status.Active, @@ -648,7 +649,7 @@ object SharedTestDataADM { shortcode = Shortcode.unsafeFrom("0001"), longname = Some(Longname.unsafeFrom("Anything Project")), description = Seq(StringLiteralV2.from(value = "Anything Project", language = None)), - keywords = Seq("things", "arbitrary test data").sorted, + keywords = List("things", "arbitrary test data").map(Keyword.unsafeFrom), logo = None, ontologies = Seq( SharedOntologyTestDataADM.ANYTHING_ONTOLOGY_IRI_LocalHost, @@ -685,7 +686,7 @@ object SharedTestDataADM { shortcode = Shortcode.unsafeFrom("0801"), longname = Some(Longname.unsafeFrom("Bernoulli-Euler Online")), description = Seq(StringLiteralV2.from(value = "Bernoulli-Euler Online", language = None)), - keywords = Seq.empty[String], + keywords = List.empty, logo = None, ontologies = Seq( "http://www.knora.org/ontology/0801/beol", @@ -741,7 +742,7 @@ object SharedTestDataADM { shortcode = Shortcode.unsafeFrom("0804"), longname = Some(Longname.unsafeFrom("Dokubib")), description = Seq(StringLiteralV2.from(value = "Dokubib", language = None)), - keywords = Seq.empty[String], + keywords = List.empty, logo = None, ontologies = Seq("http://www.knora.org/ontology/0804/dokubib"), status = Status.Inactive, diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala index 2d3895e0d9..0abc38efac 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala @@ -24,6 +24,7 @@ import org.knora.webapi.slice.admin.domain.model.GroupName import org.knora.webapi.slice.admin.domain.model.GroupSelfJoin import org.knora.webapi.slice.admin.domain.model.GroupStatus import org.knora.webapi.slice.admin.domain.model.KnoraProject.CopyrightAttribution +import org.knora.webapi.slice.admin.domain.model.KnoraProject.Keyword import org.knora.webapi.slice.admin.domain.model.KnoraProject.License import org.knora.webapi.slice.admin.domain.model.KnoraProject.Longname import org.knora.webapi.slice.admin.domain.model.KnoraProject.ProjectIri @@ -95,7 +96,7 @@ object Examples { shortcode = Shortcode.unsafeFrom("0001"), longname = Some(Longname.unsafeFrom("Example Project")), description = Seq(StringLiteralV2.from("An example project", Some("en"))), - keywords = Seq("example", "project"), + keywords = List("example", "project").map(Keyword.unsafeFrom), logo = None, status = Active, ontologies = Seq.empty, diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala index 65692df527..ba5dc64f96 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala @@ -36,7 +36,7 @@ case class Project( shortcode: Shortcode, longname: Option[Longname], description: Seq[StringLiteralV2], - keywords: Seq[String], + keywords: List[Keyword], logo: Option[Logo], ontologies: Seq[IRI], status: Status, diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala index 46f18ea4b9..84922ee815 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala @@ -51,7 +51,7 @@ final case class ProjectService( knoraProject.shortcode, knoraProject.longname, knoraProject.description.map(_.value), - knoraProject.keywords.map(_.value), + knoraProject.keywords, knoraProject.logo, ontologies, knoraProject.status, @@ -70,7 +70,7 @@ final case class ProjectService( description = NonEmptyChunk .fromIterable(project.description.head, project.description.tail) .map(Description.unsafeFrom), - keywords = project.keywords.map(Keyword.unsafeFrom).toList, + keywords = project.keywords, logo = project.logo, status = project.status, selfjoin = project.selfjoin, From 02f828c5b5248c0860e44a937c96cad58bff4f1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinb=C3=B6lting?= Date: Fri, 15 Nov 2024 19:48:54 +0100 Subject: [PATCH 18/18] refactor: Make Project.description typed --- .../IntegrationTestAdminJsonProtocol.scala | 9 ++++++ .../webapi/sharedtestdata/ProjectInfo.scala | 2 +- .../sharedtestdata/SharedTestDataADM.scala | 30 +++++++++++-------- .../webapi/slice/admin/api/Examples.scala | 3 +- .../admin/api/model/ProjectsMessagesADM.scala | 3 +- .../admin/domain/service/ProjectService.scala | 6 ++-- .../domain/service/ProjectServiceSpec.scala | 2 +- 7 files changed, 34 insertions(+), 21 deletions(-) diff --git a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala index da2ff2d18a..b98d07e61e 100644 --- a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala +++ b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala @@ -39,6 +39,7 @@ import org.knora.webapi.messages.admin.responder.usersmessages.UserProjectAdminM import org.knora.webapi.messages.admin.responder.usersmessages.UserProjectMembershipsGetResponseADM import org.knora.webapi.messages.admin.responder.usersmessages.UserResponseADM import org.knora.webapi.messages.admin.responder.usersmessages.UsersGetResponseADM +import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 import org.knora.webapi.messages.store.triplestoremessages.TriplestoreJsonProtocol import org.knora.webapi.slice.admin.api.model.Project import org.knora.webapi.slice.admin.api.model.ProjectAdminMembersGetResponseADM @@ -46,6 +47,7 @@ import org.knora.webapi.slice.admin.api.model.ProjectMembersGetResponseADM import org.knora.webapi.slice.admin.api.model.ProjectOperationResponseADM import org.knora.webapi.slice.admin.domain.model.Group import org.knora.webapi.slice.admin.domain.model.KnoraProject.CopyrightAttribution +import org.knora.webapi.slice.admin.domain.model.KnoraProject.Description import org.knora.webapi.slice.admin.domain.model.KnoraProject.Keyword import org.knora.webapi.slice.admin.domain.model.KnoraProject.License import org.knora.webapi.slice.admin.domain.model.KnoraProject.Logo @@ -206,6 +208,13 @@ object IntegrationTestAdminJsonProtocol extends TriplestoreJsonProtocol { ), ) + implicit object DescriptionFormat extends JsonFormat[Description] with TriplestoreJsonProtocol { + val lit = implicitly[JsonFormat[StringLiteralV2]] + override def write(obj: Description): JsValue = lit.write(obj.value) + override def read(json: JsValue): Description = Description + .from(lit.read(json)) + .fold(err => throw DeserializationException(err), identity) + } trait StringValueFormat[T <: StringValue] extends JsonFormat[T] { self => def from: String => Either[String, T] override def write(v: T): JsValue = JsString(v.value) diff --git a/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala b/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala index 466f842d84..bc3b5ba924 100644 --- a/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala +++ b/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala @@ -41,7 +41,7 @@ object ProjectInfo { shortname = project.shortname.value, shortcode = project.shortcode.value, longname = project.longname.map(_.value), - description = project.description.headOption.map(_.value), + description = project.description.map(_.value).headOption.map(_.value), keywords = project.keywords.headOption.map(_ => project.keywords.mkString(", ")), logo = project.logo.map(_.value), ontologies = project.ontologies, diff --git a/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala b/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala index aef55eb351..ef5cee5ee3 100644 --- a/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala +++ b/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala @@ -16,6 +16,7 @@ import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 import org.knora.webapi.messages.util.KnoraSystemInstances import org.knora.webapi.slice.admin.api.model.Project import org.knora.webapi.slice.admin.domain.model.Group +import org.knora.webapi.slice.admin.domain.model.KnoraProject.Description import org.knora.webapi.slice.admin.domain.model.KnoraProject.Keyword import org.knora.webapi.slice.admin.domain.model.KnoraProject.Logo import org.knora.webapi.slice.admin.domain.model.KnoraProject.Longname @@ -166,7 +167,8 @@ object SharedTestDataADM { shortname = Shortname.unsafeFrom("SystemProject"), shortcode = Shortcode.unsafeFrom("FFFF"), longname = Some(Longname.unsafeFrom("Knora System Project")), - description = Seq(StringLiteralV2.from(value = "Knora System Project", language = Some("en"))), + description = + List(StringLiteralV2.from(value = "Knora System Project", language = Some("en"))).map(Description.unsafeFrom), keywords = List.empty, logo = None, ontologies = Seq( @@ -187,7 +189,8 @@ object SharedTestDataADM { shortname = Shortname.unsafeFrom("DefaultSharedOntologiesProject"), shortcode = Shortcode.unsafeFrom("0000"), longname = Some(Longname.unsafeFrom("Default Knora Shared Ontologies Project")), - description = Seq(StringLiteralV2.from(value = "Default Knora Shared Ontologies Project", language = Some("en"))), + description = List(StringLiteralV2.from(value = "Default Knora Shared Ontologies Project", language = Some("en"))) + .map(Description.unsafeFrom), keywords = List.empty, logo = None, ontologies = Seq.empty[IRI], @@ -301,7 +304,8 @@ object SharedTestDataADM { shortname = Shortname.unsafeFrom("images"), shortcode = Shortcode.unsafeFrom("00FF"), longname = Some(Longname.unsafeFrom("Image Collection Demo")), - description = Seq(StringLiteralV2.from(value = "A demo project of a collection of images", language = Some("en"))), + description = List(StringLiteralV2.from(value = "A demo project of a collection of images", language = Some("en"))) + .map(Description.unsafeFrom), keywords = List("images", "collection").map(Keyword.unsafeFrom), logo = None, ontologies = Seq(SharedOntologyTestDataADM.IMAGES_ONTOLOGY_IRI), @@ -317,7 +321,8 @@ object SharedTestDataADM { shortname = Shortname.unsafeFrom("images"), shortcode = Shortcode.unsafeFrom("00FF"), longname = Some(Longname.unsafeFrom("Image Collection Demo")), - description = Seq(StringLiteralV2.from(value = "A demo project of a collection of images", language = Some("en"))), + description = List(StringLiteralV2.from(value = "A demo project of a collection of images", language = Some("en"))) + .map(Description.unsafeFrom), keywords = List("images", "collection").map(Keyword.unsafeFrom), logo = None, ontologies = Seq(SharedOntologyTestDataADM.IMAGES_ONTOLOGY_IRI_LocalHost), @@ -461,13 +466,13 @@ object SharedTestDataADM { shortname = Shortname.unsafeFrom("incunabula"), shortcode = Shortcode.unsafeFrom("0803"), longname = Some(Longname.unsafeFrom("Bilderfolgen Basler Frühdrucke")), - description = Seq( + description = List( StringLiteralV2.from( value = "

Das interdisziplinäre Forschungsprojekt \"Die Bilderfolgen der Basler Frühdrucke: Spätmittelalterliche Didaxe als Bild-Text-Lektüre\" verbindet eine umfassende kunstwissenschaftliche Analyse der Bezüge zwischen den Bildern und Texten in den illustrierten Basler Inkunabeln mit der Digitalisierung der Bestände der Universitätsbibliothek und der Entwicklung einer elektronischen Edition in der Form einer neuartigen Web-0.2-Applikation.\n

\n

Das Projekt wird durchgeführt vom Kunsthistorischen Seminar der Universität Basel (Prof. B. Schellewald) und dem Digital Humanities Lab der Universität Basel (PD Dr. L. Rosenthaler).\n

\n

\nDas Kernstück der digitalen Edition besteht aus rund zwanzig reich bebilderten Frühdrucken aus vier verschiedenen Basler Offizinen. Viele davon sind bereits vor 1500 in mehreren Ausgaben erschienen, einige fast gleichzeitig auf Deutsch und Lateinisch. Es handelt sich um eine ausserordentlich vielfältige Produktion; neben dem Heilsspiegel finden sich ein Roman, die Melusine, die Reisebeschreibungen des Jean de Mandeville, einige Gebets- und Erbauungsbüchlein, theologische Schriften, Fastenpredigten, die Leben der Heiligen Fridolin und Meinrad, das berühmte Narrenschiff sowie die Exempelsammlung des Ritters vom Thurn.\n

\nDie Internetpublikation macht das digitalisierte Korpus dieser Frühdrucke durch die Möglichkeiten nichtlinearer Verknüpfung und Kommentierung der Bilder und Texte, für die wissenschaftliche Edition sowie für die Erforschung der Bilder und Texte nutzbar machen. Auch können bereits bestehende und entstehende Online-Editionen damit verknüpft werden , wodurch die Nutzung von Datenbanken anderer Institutionen im Hinblick auf unser Corpus optimiert wird.\n

", language = None, ), - ), + ).map(Description.unsafeFrom), keywords = List( "Basler Frühdrucke", "Inkunabel", @@ -498,13 +503,13 @@ object SharedTestDataADM { shortname = Shortname.unsafeFrom("incunabula"), shortcode = Shortcode.unsafeFrom("0803"), longname = Some(Longname.unsafeFrom("Bilderfolgen Basler Frühdrucke")), - description = Seq( + description = List( StringLiteralV2.from( value = "

Das interdisziplinäre Forschungsprojekt \"Die Bilderfolgen der Basler Frühdrucke: Spätmittelalterliche Didaxe als Bild-Text-Lektüre\" verbindet eine umfassende kunstwissenschaftliche Analyse der Bezüge zwischen den Bildern und Texten in den illustrierten Basler Inkunabeln mit der Digitalisierung der Bestände der Universitätsbibliothek und der Entwicklung einer elektronischen Edition in der Form einer neuartigen Web-0.2-Applikation.\n

\n

Das Projekt wird durchgeführt vom Kunsthistorischen Seminar der Universität Basel (Prof. B. Schellewald) und dem Digital Humanities Lab der Universität Basel (PD Dr. L. Rosenthaler).\n

\n

\nDas Kernstück der digitalen Edition besteht aus rund zwanzig reich bebilderten Frühdrucken aus vier verschiedenen Basler Offizinen. Viele davon sind bereits vor 1500 in mehreren Ausgaben erschienen, einige fast gleichzeitig auf Deutsch und Lateinisch. Es handelt sich um eine ausserordentlich vielfältige Produktion; neben dem Heilsspiegel finden sich ein Roman, die Melusine, die Reisebeschreibungen des Jean de Mandeville, einige Gebets- und Erbauungsbüchlein, theologische Schriften, Fastenpredigten, die Leben der Heiligen Fridolin und Meinrad, das berühmte Narrenschiff sowie die Exempelsammlung des Ritters vom Thurn.\n

\nDie Internetpublikation macht das digitalisierte Korpus dieser Frühdrucke durch die Möglichkeiten nichtlinearer Verknüpfung und Kommentierung der Bilder und Texte, für die wissenschaftliche Edition sowie für die Erforschung der Bilder und Texte nutzbar machen. Auch können bereits bestehende und entstehende Online-Editionen damit verknüpft werden , wodurch die Nutzung von Datenbanken anderer Institutionen im Hinblick auf unser Corpus optimiert wird.\n

", language = None, ), - ), + ).map(Description.unsafeFrom), keywords = List( "Basler Frühdrucke", "Inkunabel", @@ -633,7 +638,7 @@ object SharedTestDataADM { shortname = Shortname.unsafeFrom("anything"), shortcode = Shortcode.unsafeFrom("0001"), longname = Some(Longname.unsafeFrom("Anything Project")), - description = Seq(StringLiteralV2.from(value = "Anything Project", language = None)), + description = List(StringLiteralV2.from(value = "Anything Project", language = None)).map(Description.unsafeFrom), keywords = List("things", "arbitrary test data").map(Keyword.unsafeFrom), logo = None, ontologies = Seq(SharedOntologyTestDataADM.ANYTHING_ONTOLOGY_IRI, SharedOntologyTestDataADM.SomethingOntologyIri), @@ -648,7 +653,7 @@ object SharedTestDataADM { shortname = Shortname.unsafeFrom("anything"), shortcode = Shortcode.unsafeFrom("0001"), longname = Some(Longname.unsafeFrom("Anything Project")), - description = Seq(StringLiteralV2.from(value = "Anything Project", language = None)), + description = List(StringLiteralV2.from(value = "Anything Project", language = None)).map(Description.unsafeFrom), keywords = List("things", "arbitrary test data").map(Keyword.unsafeFrom), logo = None, ontologies = Seq( @@ -685,7 +690,8 @@ object SharedTestDataADM { shortname = Shortname.unsafeFrom("beol"), shortcode = Shortcode.unsafeFrom("0801"), longname = Some(Longname.unsafeFrom("Bernoulli-Euler Online")), - description = Seq(StringLiteralV2.from(value = "Bernoulli-Euler Online", language = None)), + description = + List(StringLiteralV2.from(value = "Bernoulli-Euler Online", language = None)).map(Description.unsafeFrom), keywords = List.empty, logo = None, ontologies = Seq( @@ -741,7 +747,7 @@ object SharedTestDataADM { shortname = Shortname.unsafeFrom("dokubib"), shortcode = Shortcode.unsafeFrom("0804"), longname = Some(Longname.unsafeFrom("Dokubib")), - description = Seq(StringLiteralV2.from(value = "Dokubib", language = None)), + description = List(StringLiteralV2.from(value = "Dokubib", language = None)).map(Description.unsafeFrom), keywords = List.empty, logo = None, ontologies = Seq("http://www.knora.org/ontology/0804/dokubib"), diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala index 0abc38efac..fc0135555e 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala @@ -24,6 +24,7 @@ import org.knora.webapi.slice.admin.domain.model.GroupName import org.knora.webapi.slice.admin.domain.model.GroupSelfJoin import org.knora.webapi.slice.admin.domain.model.GroupStatus import org.knora.webapi.slice.admin.domain.model.KnoraProject.CopyrightAttribution +import org.knora.webapi.slice.admin.domain.model.KnoraProject.Description import org.knora.webapi.slice.admin.domain.model.KnoraProject.Keyword import org.knora.webapi.slice.admin.domain.model.KnoraProject.License import org.knora.webapi.slice.admin.domain.model.KnoraProject.Longname @@ -95,7 +96,7 @@ object Examples { shortname = Shortname.unsafeFrom("example"), shortcode = Shortcode.unsafeFrom("0001"), longname = Some(Longname.unsafeFrom("Example Project")), - description = Seq(StringLiteralV2.from("An example project", Some("en"))), + description = List(StringLiteralV2.from("An example project", Some("en"))).map(Description.unsafeFrom), keywords = List("example", "project").map(Keyword.unsafeFrom), logo = None, status = Active, diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala index ba5dc64f96..f7f3d60535 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala @@ -10,7 +10,6 @@ import zio.json.JsonCodec import org.knora.webapi.IRI import org.knora.webapi.messages.admin.responder.AdminKnoraResponseADM -import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 import org.knora.webapi.slice.admin.api.Codecs.ZioJsonCodec.* import org.knora.webapi.slice.admin.domain.model.KnoraProject.* import org.knora.webapi.slice.admin.domain.model.RestrictedView @@ -35,7 +34,7 @@ case class Project( shortname: Shortname, shortcode: Shortcode, longname: Option[Longname], - description: Seq[StringLiteralV2], + description: List[Description], keywords: List[Keyword], logo: Option[Logo], ontologies: Seq[IRI], diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala index 84922ee815..142b0b73eb 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala @@ -50,7 +50,7 @@ final case class ProjectService( knoraProject.shortname, knoraProject.shortcode, knoraProject.longname, - knoraProject.description.map(_.value), + knoraProject.description.toList, knoraProject.keywords, knoraProject.logo, ontologies, @@ -67,9 +67,7 @@ final case class ProjectService( shortname = project.shortname, shortcode = project.shortcode, longname = project.longname, - description = NonEmptyChunk - .fromIterable(project.description.head, project.description.tail) - .map(Description.unsafeFrom), + description = NonEmptyChunk.fromIterable(project.description.head, project.description.tail), keywords = project.keywords, logo = project.logo, status = project.status, diff --git a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala index f7badf15e1..325f7e58a4 100644 --- a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala @@ -29,7 +29,7 @@ object ProjectServiceSpec extends ZIOSpecDefault { shortname = shortname, shortcode = shortcode, longname = None, - description = List(StringLiteralV2.from("description not used in test", None)), + description = List(StringLiteralV2.from("description not used in test", None)).map(Description.unsafeFrom), keywords = List.empty, logo = None, ontologies = List.empty,