From 552664e097adf1694ca7eba87ee5de2cb59c868d Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Tue, 15 Aug 2023 10:31:34 +0200 Subject: [PATCH 01/51] add SPARQL query --- ...setProjectRestrictedViewSettings.scala.txt | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/setProjectRestrictedViewSettings.scala.txt diff --git a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/setProjectRestrictedViewSettings.scala.txt b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/setProjectRestrictedViewSettings.scala.txt new file mode 100644 index 0000000000..f1c8bbf1cc --- /dev/null +++ b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/setProjectRestrictedViewSettings.scala.txt @@ -0,0 +1,32 @@ +@* + * Copyright © 2021 - 2023 Swiss National Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. + * SPDX-License-Identifier: Apache-2.0 + *@ + +@import org.knora.webapi.IRI + +@* + * Sets project restricted view settings. + * + * @param size project's restricted view size. + * @param watermark project's watermark. + * @param projectIri project's IRI. + * + *@ +@(size: Option[String], + watermark: Option[String] = None, + projectIri: IRI) + +PREFIX rdf: +PREFIX xsd: +PREFIX knora-admin: + +INSERT DATA { + GRAPH { + @projectIri knora-admin:projectRestrictedViewSize """@size"""^^xsd:string . + + @if(watermark.noneEmpty) { + @projectIri knora-admin:projectRestrictedViewWatermark """@watermark"""^^xsd:string . + } + } +} From 0092974ae05bc32e8fad2afe5ea5796205088303 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Tue, 15 Aug 2023 15:02:04 +0200 Subject: [PATCH 02/51] add view settings functionality --- .../ProjectsMessagesADM.scala | 11 +++++++ .../admin/ProjectsResponderADM.scala | 32 +++++++++++++++++-- .../api/service/ProjectsADMRestService.scala | 12 +++++++ ...setProjectRestrictedViewSettings.scala.txt | 14 ++++---- .../admin/ProjectADMRestServiceMock.scala | 6 ++++ .../admin/ProjectsResponderADMMock.scala | 11 +++++++ 6 files changed, 77 insertions(+), 9 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala index c6cf1f9d8a..4fdabb2113 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala @@ -245,6 +245,17 @@ case class ProjectRestrictedViewSettingsGetRequestADM( identifier: ProjectIdentifierADM ) extends ProjectsResponderRequestADM +/** + * Return project's RestrictedView settings. + * + * @param identifier the identifier of the project. + */ +case class ProjectRestrictedViewSettingsSetRequestADM( + identifier: Iri.ProjectIri, + size: Option[String], + watermark: Option[String] +) extends ProjectsResponderRequestADM + /** * Requests the creation of a new project. * diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala index 5b11dcd7e3..c05e109ffe 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala @@ -110,7 +110,7 @@ trait ProjectsResponderADM { /** * Get project's restricted view settings. * - * @param id the project's identifier (IRI / shortcode / shortname / UUID) + * @param id the project's identifier (IRI / shortcode / shortname) * @return [[ProjectRestrictedViewSettingsADM]] */ def projectRestrictedViewSettingsGetADM(id: ProjectIdentifierADM): Task[Option[ProjectRestrictedViewSettingsADM]] @@ -118,13 +118,24 @@ trait ProjectsResponderADM { /** * Get project's restricted view settings. * - * @param id the project's identifier (IRI / shortcode / shortname / UUID) + * @param id the project's identifier (IRI / shortcode / shortname) * @return [[ProjectRestrictedViewSettingsGetResponseADM]] */ def projectRestrictedViewSettingsGetRequestADM( id: ProjectIdentifierADM ): Task[ProjectRestrictedViewSettingsGetResponseADM] + /** + * Sets project's restricted view settings. + * + * @param id the project's identifier (IRI / shortcode / shortname) + */ + def setProjectRestrictedViewSettings( + id: Iri.ProjectIri, + size: Option[String], + watermark: Option[String] + ): Task[Unit] + /** * Creates a project. * @@ -200,6 +211,8 @@ final case class ProjectsResponderADMLive( projectRestrictedViewSettingsGetADM(identifier) case ProjectRestrictedViewSettingsGetRequestADM(identifier) => projectRestrictedViewSettingsGetRequestADM(identifier) + case ProjectRestrictedViewSettingsSetRequestADM(identifier, size, watermark) => + setProjectRestrictedViewSettings(identifier, size, watermark) case ProjectCreateRequestADM(createRequest, requestingUser, apiRequestID) => projectCreateRequestADM(createRequest, requestingUser, apiRequestID) case ProjectChangeRequestADM( @@ -448,6 +461,20 @@ final case class ProjectsResponderADMLive( ProjectRestrictedViewSettingsGetResponseADM ) + override def setProjectRestrictedViewSettings( + iri: Iri.ProjectIri, + size: Option[String] = None, + watermark: Option[String] = None + ): Task[Unit] = { + val defaultViewSetting: String = size.getOrElse("pc:1") + val query = twirl.queries.sparql.admin.txt + .setProjectRestrictedViewSettings(iri.value, defaultViewSetting, watermark) + + for { + _ <- triplestoreService.sparqlHttpUpdate(query.toString) + } yield () + } + /** * Update project's basic information. * @@ -826,6 +853,7 @@ final case class ProjectsResponderADMLive( ) // create permissions for admins and members of the new group _ <- createPermissionsForAdminsAndMembersOfNewProject(newProjectIRI) + _ <- setProjectRestrictedViewSettings(id.value) } yield ProjectOperationResponseADM(project = newProjectADM.unescape) diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala index ec048d3d5c..c43c003cbf 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala @@ -10,6 +10,7 @@ import zio.macros.accessible import dsp.errors.BadRequestException import dsp.errors.NotFoundException +import dsp.valueobjects.Iri import dsp.valueobjects.Iri.ProjectIri import dsp.valueobjects.Project import dsp.valueobjects.Project.Shortcode @@ -62,6 +63,11 @@ trait ProjectADMRestService { def getProjectRestrictedViewSettings( identifier: ProjectIdentifierADM ): Task[ProjectRestrictedViewSettingsGetResponseADM] + def setProjectRestrictedViewSettings( + id: Iri.ProjectIri, + size: Option[String], + watermark: Option[String] + ): Task[Unit] } final case class ProjectsADMRestServiceLive( @@ -268,6 +274,12 @@ final case class ProjectsADMRestServiceLive( _ <- permissionService.ensureSystemAdmin(requestingUser) exports <- projectExportService.listExports().map(_.map(ProjectExportInfoResponse(_))) } yield exports + + override def setProjectRestrictedViewSettings( + id: Iri.ProjectIri, + size: Option[String], + watermark: Option[String] + ): Task[Unit] = responder.setProjectRestrictedViewSettings(id, size, watermark) } object ProjectsADMRestServiceLive { diff --git a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/setProjectRestrictedViewSettings.scala.txt b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/setProjectRestrictedViewSettings.scala.txt index f1c8bbf1cc..ebf2795fc0 100644 --- a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/setProjectRestrictedViewSettings.scala.txt +++ b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/setProjectRestrictedViewSettings.scala.txt @@ -8,14 +8,14 @@ @* * Sets project restricted view settings. * + * @param iri project's IRI. * @param size project's restricted view size. * @param watermark project's watermark. - * @param projectIri project's IRI. * *@ -@(size: Option[String], - watermark: Option[String] = None, - projectIri: IRI) +@(iri: IRI, + size: String, + watermark: Option[String]) PREFIX rdf: PREFIX xsd: @@ -23,10 +23,10 @@ PREFIX knora-admin: INSERT DATA { GRAPH { - @projectIri knora-admin:projectRestrictedViewSize """@size"""^^xsd:string . + <@iri> knora-admin:projectRestrictedViewSize "@size"^^xsd:string . - @if(watermark.noneEmpty) { - @projectIri knora-admin:projectRestrictedViewWatermark """@watermark"""^^xsd:string . + @if(watermark.nonEmpty) { + <@iri> knora-admin:projectRestrictedViewWatermark "@watermark"^^xsd:string . } } } diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala index 6ba1e27760..25721af026 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala @@ -97,6 +97,12 @@ object ProjectADMRestServiceMock extends Mock[ProjectADMRestService] { override def importProject(projectIri: IRI, requestingUser: UserADM): Task[ProjectImportResponse] = ??? override def listExports(requestingUser: UserADM): Task[Chunk[ProjectExportInfoResponse]] = ??? + + override def setProjectRestrictedViewSettings( + id: ProjectIri, + size: Option[IRI], + watermark: Option[IRI] + ): Task[Unit] = ??? } } } diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala index 818c909a4f..e89249f3af 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala @@ -97,6 +97,17 @@ object ProjectsResponderADMMock extends Mock[ProjectsResponderADM] { apiRequestID: UUID ): Task[ProjectOperationResponseADM] = proxy(ChangeBasicInformationRequestADM, (projectIri, updatePayload, user, apiRequestID)) + + /** + * Sets project's restricted view settings. + * + * @param id the project's identifier (IRI / shortcode / shortname) + */ + override def setProjectRestrictedViewSettings( + id: Iri.ProjectIri, + size: Option[String], + watermark: Option[String] + ): Task[Unit] = ??? } } } From 1c7fb7aa407b8cf07493ec600350eafff984e728 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Tue, 15 Aug 2023 15:02:35 +0200 Subject: [PATCH 03/51] add route --- .../ProjectsPayloadsADM.scala | 10 ++++++++ .../webapi/routing/admin/ProjectsRouteZ.scala | 24 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsPayloadsADM.scala index 84f33c9c6c..0f9575a4fc 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsPayloadsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsPayloadsADM.scala @@ -79,3 +79,13 @@ object ProjectUpdatePayloadADM { ) } } + +final case class ProjectSetRestrictedViewSettingsPayload( + size: Option[String], + watermark: Option[String] +) + +object ProjectSetRestrictedViewSettingsPayload { + implicit val codec: JsonCodec[ProjectSetRestrictedViewSettingsPayload] = + DeriveJsonCodec.gen[ProjectSetRestrictedViewSettingsPayload] +} diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala index e154b4cbf0..5a8136c6ea 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala @@ -14,12 +14,14 @@ import zio.stream.ZStream import java.nio.file.Files import dsp.errors.BadRequestException +import dsp.errors.ForbiddenException import dsp.valueobjects.Iri._ import org.knora.webapi.config.AppConfig import org.knora.webapi.http.handler.ExceptionHandlerZ import org.knora.webapi.http.middleware.AuthenticationMiddleware import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectCreatePayloadADM import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM._ +import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectSetRestrictedViewSettingsPayload import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectUpdatePayloadADM import org.knora.webapi.messages.admin.responder.usersmessages.UserADM import org.knora.webapi.routing.RouteUtilZ @@ -84,6 +86,11 @@ final case class ProjectsRouteZ( getRestrictedViewSettingsByShortname(shortname) case (Method.GET -> !! / "admin" / "projects" / "shortcode" / shortcode / "RestrictedViewSettings", _) => getRestrictedViewSettingsByShortcode(shortcode) + case ( + request @ Method.POST -> !! / "admin" / "projects" / "iri" / iri / "RestrictedViewSettings", + requestingUser + ) => + setProjectRestrictedViewSettings(iri, request.body, requestingUser) } .catchAll(ExceptionHandlerZ.exceptionToJsonHttpResponseZ(_, appConfig)) @@ -234,6 +241,23 @@ final case class ProjectsRouteZ( r <- projectsService.getProjectRestrictedViewSettings(shortcodeIdentifier) } yield Response.json(r.toJsValue.toString) + private def setProjectRestrictedViewSettings( + iri: String, + body: Body, + user: UserADM + ): Task[Response] = + for { + iriDecoded <- RouteUtilZ.urlDecode(iri, s"Failed to URL decode IRI parameter $iri.") + isSystemAdmin <- ZIO.succeed(user.permissions.isSystemAdmin) + isProjectAdmin <- ZIO.succeed(user.permissions.isProjectAdmin(iri)) + _ <- ZIO.fail(ForbiddenException("User is not system or project admin.")).when(!isSystemAdmin && !isProjectAdmin) + id <- IriIdentifier.fromString(iriDecoded).toZIO.mapError(e => BadRequestException(e.msg)) + body <- body.asString + payload <- + ZIO.fromEither(body.fromJson[ProjectSetRestrictedViewSettingsPayload]).mapError(e => BadRequestException(e)) + _ <- projectsService.setProjectRestrictedViewSettings(id.value, payload.size, payload.watermark) + } yield Response.status(Status.Ok) + } object ProjectsRouteZ { From 4e83dbaa326c56519ee4bedca61a9b2baff69fc2 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Tue, 15 Aug 2023 15:52:55 +0200 Subject: [PATCH 04/51] improve query --- ...setProjectRestrictedViewSettings.scala.txt | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/setProjectRestrictedViewSettings.scala.txt b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/setProjectRestrictedViewSettings.scala.txt index ebf2795fc0..2e136e6cb1 100644 --- a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/setProjectRestrictedViewSettings.scala.txt +++ b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/setProjectRestrictedViewSettings.scala.txt @@ -21,12 +21,28 @@ PREFIX rdf: PREFIX xsd: PREFIX knora-admin: -INSERT DATA { - GRAPH { - <@iri> knora-admin:projectRestrictedViewSize "@size"^^xsd:string . +WITH +DELETE { + <@iri> knora-admin:projectRestrictedViewSize ?prevSize . - @if(watermark.nonEmpty) { - <@iri> knora-admin:projectRestrictedViewWatermark "@watermark"^^xsd:string . - } - } + @if(watermark.nonEmpty) { + <@iri> knora-admin:projectRestrictedViewWatermark ?prevWatermark . + } +} +INSERT { + <@iri> knora-admin:projectRestrictedViewSize "@size"^^xsd:string . + + @if(watermark.nonEmpty) { + <@iri> knora-admin:projectRestrictedViewWatermark "@watermark"^^xsd:string . + } +} +WHERE { + <@iri> a knora-admin:knoraProject . + OPTIONAL { + <@iri> knora-admin:projectRestrictedViewSize ?prevSize . + + @if(watermark.nonEmpty) { + <@iri> knora-admin:projectRestrictedViewWatermark ?prevWatermark . + } + } } From e95d8d892a75d16cbc1e2f640908cc5cfbf7e806 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Mon, 28 Aug 2023 10:59:02 +0200 Subject: [PATCH 05/51] remove watermark field --- .../projectsmessages/ProjectsMessagesADM.scala | 3 +-- .../responders/admin/ProjectsResponderADM.scala | 15 +++++---------- .../webapi/routing/admin/ProjectsRouteZ.scala | 2 +- .../api/service/ProjectsADMRestService.scala | 8 +++----- .../admin/ProjectADMRestServiceMock.scala | 3 +-- .../admin/ProjectsResponderADMMock.scala | 3 +-- 6 files changed, 12 insertions(+), 22 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala index 4fdabb2113..8dbbca73fc 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala @@ -252,8 +252,7 @@ case class ProjectRestrictedViewSettingsGetRequestADM( */ case class ProjectRestrictedViewSettingsSetRequestADM( identifier: Iri.ProjectIri, - size: Option[String], - watermark: Option[String] + size: Option[String] ) extends ProjectsResponderRequestADM /** diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala index c05e109ffe..a5a7169bcb 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala @@ -130,11 +130,7 @@ trait ProjectsResponderADM { * * @param id the project's identifier (IRI / shortcode / shortname) */ - def setProjectRestrictedViewSettings( - id: Iri.ProjectIri, - size: Option[String], - watermark: Option[String] - ): Task[Unit] + def setProjectRestrictedViewSettings(id: Iri.ProjectIri, size: Option[String]): Task[Unit] /** * Creates a project. @@ -211,8 +207,8 @@ final case class ProjectsResponderADMLive( projectRestrictedViewSettingsGetADM(identifier) case ProjectRestrictedViewSettingsGetRequestADM(identifier) => projectRestrictedViewSettingsGetRequestADM(identifier) - case ProjectRestrictedViewSettingsSetRequestADM(identifier, size, watermark) => - setProjectRestrictedViewSettings(identifier, size, watermark) + case ProjectRestrictedViewSettingsSetRequestADM(identifier, size) => + setProjectRestrictedViewSettings(identifier, size) case ProjectCreateRequestADM(createRequest, requestingUser, apiRequestID) => projectCreateRequestADM(createRequest, requestingUser, apiRequestID) case ProjectChangeRequestADM( @@ -463,12 +459,11 @@ final case class ProjectsResponderADMLive( override def setProjectRestrictedViewSettings( iri: Iri.ProjectIri, - size: Option[String] = None, - watermark: Option[String] = None + size: Option[String] = None ): Task[Unit] = { val defaultViewSetting: String = size.getOrElse("pc:1") val query = twirl.queries.sparql.admin.txt - .setProjectRestrictedViewSettings(iri.value, defaultViewSetting, watermark) + .setProjectRestrictedViewSettings(iri.value, defaultViewSetting, None) for { _ <- triplestoreService.sparqlHttpUpdate(query.toString) diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala index 5a8136c6ea..ee14e6efb1 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala @@ -255,7 +255,7 @@ final case class ProjectsRouteZ( body <- body.asString payload <- ZIO.fromEither(body.fromJson[ProjectSetRestrictedViewSettingsPayload]).mapError(e => BadRequestException(e)) - _ <- projectsService.setProjectRestrictedViewSettings(id.value, payload.size, payload.watermark) + _ <- projectsService.setProjectRestrictedViewSettings(id.value, payload.size) } yield Response.status(Status.Ok) } diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala index c43c003cbf..8ed73ca0bc 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala @@ -65,8 +65,7 @@ trait ProjectADMRestService { ): Task[ProjectRestrictedViewSettingsGetResponseADM] def setProjectRestrictedViewSettings( id: Iri.ProjectIri, - size: Option[String], - watermark: Option[String] + size: Option[String] ): Task[Unit] } @@ -277,9 +276,8 @@ final case class ProjectsADMRestServiceLive( override def setProjectRestrictedViewSettings( id: Iri.ProjectIri, - size: Option[String], - watermark: Option[String] - ): Task[Unit] = responder.setProjectRestrictedViewSettings(id, size, watermark) + size: Option[String] + ): Task[Unit] = responder.setProjectRestrictedViewSettings(id, size) } object ProjectsADMRestServiceLive { diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala index 25721af026..1970e95547 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala @@ -100,8 +100,7 @@ object ProjectADMRestServiceMock extends Mock[ProjectADMRestService] { override def setProjectRestrictedViewSettings( id: ProjectIri, - size: Option[IRI], - watermark: Option[IRI] + size: Option[IRI] ): Task[Unit] = ??? } } diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala index e89249f3af..e47f78558b 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala @@ -105,8 +105,7 @@ object ProjectsResponderADMMock extends Mock[ProjectsResponderADM] { */ override def setProjectRestrictedViewSettings( id: Iri.ProjectIri, - size: Option[String], - watermark: Option[String] + size: Option[String] ): Task[Unit] = ??? } } From fc17ec3d77fdd02c1b1bcf971ba274c9417477f1 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Mon, 28 Aug 2023 15:20:22 +0200 Subject: [PATCH 06/51] add checking if project exists --- .../responders/admin/ProjectsResponderADM.scala | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala index a5a7169bcb..d766557c05 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala @@ -461,11 +461,17 @@ final case class ProjectsResponderADMLive( iri: Iri.ProjectIri, size: Option[String] = None ): Task[Unit] = { - val defaultViewSetting: String = size.getOrElse("pc:1") - val query = twirl.queries.sparql.admin.txt - .setProjectRestrictedViewSettings(iri.value, defaultViewSetting, None) - + val id = ProjectIdentifierADM.IriIdentifier(iri) for { + _ <- getProjectFromCacheOrTriplestore(id) + .flatMap(ZIO.fromOption(_)) + .orElseFail(NotFoundException(s"Project '${getId(id)}' not found.")) + + defaultViewSetting = size.getOrElse("pc:1") + + query = twirl.queries.sparql.admin.txt + .setProjectRestrictedViewSettings(iri.value, defaultViewSetting, None) + _ <- triplestoreService.sparqlHttpUpdate(query.toString) } yield () } From e153722bd42b92f4ad06452b4cf982997262efbb Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Mon, 28 Aug 2023 16:59:43 +0200 Subject: [PATCH 07/51] add response --- .../responders/admin/ProjectsResponderADM.scala | 13 +++++++++---- .../knora/webapi/routing/admin/ProjectsRouteZ.scala | 10 +++++----- .../admin/api/service/ProjectsADMRestService.scala | 4 ++-- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala index d766557c05..684c21271d 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala @@ -130,7 +130,10 @@ trait ProjectsResponderADM { * * @param id the project's identifier (IRI / shortcode / shortname) */ - def setProjectRestrictedViewSettings(id: Iri.ProjectIri, size: Option[String]): Task[Unit] + def setProjectRestrictedViewSettings( + id: Iri.ProjectIri, + size: Option[String] + ): Task[ProjectRestrictedViewSettingsGetResponseADM] /** * Creates a project. @@ -460,7 +463,7 @@ final case class ProjectsResponderADMLive( override def setProjectRestrictedViewSettings( iri: Iri.ProjectIri, size: Option[String] = None - ): Task[Unit] = { + ): Task[ProjectRestrictedViewSettingsGetResponseADM] = { val id = ProjectIdentifierADM.IriIdentifier(iri) for { _ <- getProjectFromCacheOrTriplestore(id) @@ -472,8 +475,10 @@ final case class ProjectsResponderADMLive( query = twirl.queries.sparql.admin.txt .setProjectRestrictedViewSettings(iri.value, defaultViewSetting, None) - _ <- triplestoreService.sparqlHttpUpdate(query.toString) - } yield () + response <- triplestoreService.sparqlHttpUpdate(query.toString) + _ = println(777, response) + settings = ProjectRestrictedViewSettingsADM(size) + } yield ProjectRestrictedViewSettingsGetResponseADM(settings) } /** diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala index ee14e6efb1..58b9174c85 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala @@ -250,13 +250,13 @@ final case class ProjectsRouteZ( iriDecoded <- RouteUtilZ.urlDecode(iri, s"Failed to URL decode IRI parameter $iri.") isSystemAdmin <- ZIO.succeed(user.permissions.isSystemAdmin) isProjectAdmin <- ZIO.succeed(user.permissions.isProjectAdmin(iri)) - _ <- ZIO.fail(ForbiddenException("User is not system or project admin.")).when(!isSystemAdmin && !isProjectAdmin) - id <- IriIdentifier.fromString(iriDecoded).toZIO.mapError(e => BadRequestException(e.msg)) - body <- body.asString +// _ <- ZIO.fail(ForbiddenException("User is not system or project admin.")).when(!isSystemAdmin && !isProjectAdmin) + id <- IriIdentifier.fromString(iriDecoded).toZIO.mapError(e => BadRequestException(e.msg)) + body <- body.asString payload <- ZIO.fromEither(body.fromJson[ProjectSetRestrictedViewSettingsPayload]).mapError(e => BadRequestException(e)) - _ <- projectsService.setProjectRestrictedViewSettings(id.value, payload.size) - } yield Response.status(Status.Ok) + response <- projectsService.setProjectRestrictedViewSettings(id.value, payload.size) + } yield Response.json(response.toJsValue.toString) } diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala index 8ed73ca0bc..b02926aefa 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala @@ -66,7 +66,7 @@ trait ProjectADMRestService { def setProjectRestrictedViewSettings( id: Iri.ProjectIri, size: Option[String] - ): Task[Unit] + ): Task[ProjectRestrictedViewSettingsGetResponseADM] } final case class ProjectsADMRestServiceLive( @@ -277,7 +277,7 @@ final case class ProjectsADMRestServiceLive( override def setProjectRestrictedViewSettings( id: Iri.ProjectIri, size: Option[String] - ): Task[Unit] = responder.setProjectRestrictedViewSettings(id, size) + ): Task[ProjectRestrictedViewSettingsGetResponseADM] = responder.setProjectRestrictedViewSettings(id, size) } object ProjectsADMRestServiceLive { From 4df4c17047247396036f2d8e7e88ecf53fa71bc2 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Mon, 28 Aug 2023 17:04:32 +0200 Subject: [PATCH 08/51] reuse respone for get and set --- .../projectsmessages/ProjectsMessagesADM.scala | 8 ++++---- .../responders/admin/ProjectsResponderADM.scala | 16 ++++++++-------- .../api/service/ProjectsADMRestService.scala | 10 +++++----- .../admin/ProjectADMRestServiceMock.scala | 4 ++-- .../admin/ProjectsResponderADMMock.scala | 6 +++--- .../admin/ProjectsServiceLiveSpec.scala | 6 +++--- .../routing/admin/ProjectsRouteZSpec.scala | 12 ++++++------ 7 files changed, 31 insertions(+), 31 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala index 8dbbca73fc..cdcf010b08 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala @@ -237,7 +237,7 @@ case class ProjectRestrictedViewSettingsGetADM( ) extends ProjectsResponderRequestADM /** - * Return project's RestrictedView settings. A successful response will be a [[ProjectRestrictedViewSettingsGetResponseADM]]. + * Return project's RestrictedView settings. A successful response will be a [[ProjectRestrictedViewSettingsResponseADM]]. * * @param identifier the identifier of the project. */ @@ -348,7 +348,7 @@ case class ProjectKeywordsGetResponseADM(keywords: Seq[String]) extends KnoraRes * * @param settings the restricted view settings. */ -case class ProjectRestrictedViewSettingsGetResponseADM(settings: ProjectRestrictedViewSettingsADM) +case class ProjectRestrictedViewSettingsResponseADM(settings: ProjectRestrictedViewSettingsADM) extends KnoraResponseADM with ProjectsADMJsonProtocol { def toJsValue: JsValue = projectRestrictedViewGetResponseADMFormat.write(this) @@ -612,8 +612,8 @@ trait ProjectsADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol jsonFormat(ProjectsKeywordsGetResponseADM, "keywords") implicit val projectKeywordsGetResponseADMFormat: RootJsonFormat[ProjectKeywordsGetResponseADM] = jsonFormat(ProjectKeywordsGetResponseADM, "keywords") - implicit val projectRestrictedViewGetResponseADMFormat: RootJsonFormat[ProjectRestrictedViewSettingsGetResponseADM] = - jsonFormat(ProjectRestrictedViewSettingsGetResponseADM, "settings") + implicit val projectRestrictedViewGetResponseADMFormat: RootJsonFormat[ProjectRestrictedViewSettingsResponseADM] = + jsonFormat(ProjectRestrictedViewSettingsResponseADM, "settings") implicit val projectOperationResponseADMFormat: RootJsonFormat[ProjectOperationResponseADM] = rootFormat( lazyFormat(jsonFormat(ProjectOperationResponseADM, "project")) diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala index 684c21271d..2bf414d430 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala @@ -119,11 +119,11 @@ trait ProjectsResponderADM { * Get project's restricted view settings. * * @param id the project's identifier (IRI / shortcode / shortname) - * @return [[ProjectRestrictedViewSettingsGetResponseADM]] + * @return [[ProjectRestrictedViewSettingsResponseADM]] */ def projectRestrictedViewSettingsGetRequestADM( id: ProjectIdentifierADM - ): Task[ProjectRestrictedViewSettingsGetResponseADM] + ): Task[ProjectRestrictedViewSettingsResponseADM] /** * Sets project's restricted view settings. @@ -133,7 +133,7 @@ trait ProjectsResponderADM { def setProjectRestrictedViewSettings( id: Iri.ProjectIri, size: Option[String] - ): Task[ProjectRestrictedViewSettingsGetResponseADM] + ): Task[ProjectRestrictedViewSettingsResponseADM] /** * Creates a project. @@ -448,22 +448,22 @@ final case class ProjectsResponderADMLive( * * @param id the project's identifier (IRI / shortcode / shortname / UUID) * - * @return [[ProjectRestrictedViewSettingsGetResponseADM]] + * @return [[ProjectRestrictedViewSettingsResponseADM]] */ override def projectRestrictedViewSettingsGetRequestADM( id: ProjectIdentifierADM - ): Task[ProjectRestrictedViewSettingsGetResponseADM] = + ): Task[ProjectRestrictedViewSettingsResponseADM] = projectRestrictedViewSettingsGetADM(id) .flatMap(ZIO.fromOption(_)) .mapBoth( _ => NotFoundException(s"Project '${getId(id)}' not found."), - ProjectRestrictedViewSettingsGetResponseADM + ProjectRestrictedViewSettingsResponseADM ) override def setProjectRestrictedViewSettings( iri: Iri.ProjectIri, size: Option[String] = None - ): Task[ProjectRestrictedViewSettingsGetResponseADM] = { + ): Task[ProjectRestrictedViewSettingsResponseADM] = { val id = ProjectIdentifierADM.IriIdentifier(iri) for { _ <- getProjectFromCacheOrTriplestore(id) @@ -478,7 +478,7 @@ final case class ProjectsResponderADMLive( response <- triplestoreService.sparqlHttpUpdate(query.toString) _ = println(777, response) settings = ProjectRestrictedViewSettingsADM(size) - } yield ProjectRestrictedViewSettingsGetResponseADM(settings) + } yield ProjectRestrictedViewSettingsResponseADM(settings) } /** diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala index b02926aefa..39715f648e 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala @@ -62,11 +62,11 @@ trait ProjectADMRestService { ): Task[ProjectKeywordsGetResponseADM] def getProjectRestrictedViewSettings( identifier: ProjectIdentifierADM - ): Task[ProjectRestrictedViewSettingsGetResponseADM] + ): Task[ProjectRestrictedViewSettingsResponseADM] def setProjectRestrictedViewSettings( id: Iri.ProjectIri, size: Option[String] - ): Task[ProjectRestrictedViewSettingsGetResponseADM] + ): Task[ProjectRestrictedViewSettingsResponseADM] } final case class ProjectsADMRestServiceLive( @@ -237,11 +237,11 @@ final case class ProjectsADMRestServiceLive( * * @param id the [[ProjectIdentifierADM]] of the project * @return - * '''success''': the restricted view settings as [[ProjectRestrictedViewSettingsGetResponseADM]] + * '''success''': the restricted view settings as [[ProjectRestrictedViewSettingsResponseADM]] * * '''failure''': [[dsp.errors.NotFoundException]] when no project for the given [[ProjectIri]] can be found */ - def getProjectRestrictedViewSettings(id: ProjectIdentifierADM): Task[ProjectRestrictedViewSettingsGetResponseADM] = + def getProjectRestrictedViewSettings(id: ProjectIdentifierADM): Task[ProjectRestrictedViewSettingsResponseADM] = responder.projectRestrictedViewSettingsGetRequestADM(id) override def exportProject(shortcodeStr: String, requestingUser: UserADM): Task[Unit] = for { @@ -277,7 +277,7 @@ final case class ProjectsADMRestServiceLive( override def setProjectRestrictedViewSettings( id: Iri.ProjectIri, size: Option[String] - ): Task[ProjectRestrictedViewSettingsGetResponseADM] = responder.setProjectRestrictedViewSettings(id, size) + ): Task[ProjectRestrictedViewSettingsResponseADM] = responder.setProjectRestrictedViewSettings(id, size) } object ProjectsADMRestServiceLive { diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala index 1970e95547..918d2f0780 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala @@ -31,7 +31,7 @@ object ProjectADMRestServiceMock extends Mock[ProjectADMRestService] { object GetKeywords extends Effect[Unit, Throwable, ProjectsKeywordsGetResponseADM] object GetKeywordsByProjectIri extends Effect[ProjectIri, Throwable, ProjectKeywordsGetResponseADM] object GetRestrictedViewSettings - extends Effect[ProjectIdentifierADM, Throwable, ProjectRestrictedViewSettingsGetResponseADM] + extends Effect[ProjectIdentifierADM, Throwable, ProjectRestrictedViewSettingsResponseADM] override val compose: URLayer[Proxy, ProjectADMRestService] = ZLayer { @@ -89,7 +89,7 @@ object ProjectADMRestServiceMock extends Mock[ProjectADMRestService] { def getProjectRestrictedViewSettings( identifier: ProjectIdentifierADM - ): Task[ProjectRestrictedViewSettingsGetResponseADM] = + ): Task[ProjectRestrictedViewSettingsResponseADM] = proxy(GetRestrictedViewSettings, identifier) override def exportProject(projectIri: IRI, requestingUser: UserADM): Task[Unit] = ??? diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala index e47f78558b..04071c3fdb 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala @@ -25,7 +25,7 @@ import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectKeyword import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectMembersGetResponseADM import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectOperationResponseADM import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectRestrictedViewSettingsADM -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectRestrictedViewSettingsGetResponseADM +import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectRestrictedViewSettingsResponseADM import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectUpdatePayloadADM import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectsGetResponseADM import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectsKeywordsGetResponseADM @@ -45,7 +45,7 @@ object ProjectsResponderADMMock extends Mock[ProjectsResponderADM] { object ProjectRestrictedViewSettingsGetADM extends Effect[ProjectIdentifierADM, Throwable, Option[ProjectRestrictedViewSettingsADM]] object ProjectRestrictedViewSettingsGetRequestADM - extends Effect[ProjectIdentifierADM, Throwable, ProjectRestrictedViewSettingsGetResponseADM] + extends Effect[ProjectIdentifierADM, Throwable, ProjectRestrictedViewSettingsResponseADM] object ProjectCreateRequestADM extends Effect[(ProjectCreatePayloadADM, UserADM, UUID), Throwable, ProjectOperationResponseADM] object ChangeBasicInformationRequestADM @@ -82,7 +82,7 @@ object ProjectsResponderADMMock extends Mock[ProjectsResponderADM] { proxy(ProjectRestrictedViewSettingsGetADM, id) override def projectRestrictedViewSettingsGetRequestADM( id: ProjectIdentifierADM - ): Task[ProjectRestrictedViewSettingsGetResponseADM] = + ): Task[ProjectRestrictedViewSettingsResponseADM] = proxy(ProjectRestrictedViewSettingsGetRequestADM, id) override def projectCreateRequestADM( createPayload: ProjectCreatePayloadADM, diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsServiceLiveSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsServiceLiveSpec.scala index 45a40aa1c3..a504e5e06a 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsServiceLiveSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsServiceLiveSpec.scala @@ -297,7 +297,7 @@ object ProjectsServiceLiveSpec extends ZIOSpecDefault { val settings = ProjectRestrictedViewSettingsADM(Some("!512,512"), Some("path_to_image")) val mockResponder = ProjectsResponderADMMock.ProjectRestrictedViewSettingsGetRequestADM( assertion = Assertion.equalTo(identifier), - result = Expectation.value(ProjectRestrictedViewSettingsGetResponseADM(settings)) + result = Expectation.value(ProjectRestrictedViewSettingsResponseADM(settings)) ) for { _ <- ProjectADMRestService @@ -311,7 +311,7 @@ object ProjectsServiceLiveSpec extends ZIOSpecDefault { val settings = ProjectRestrictedViewSettingsADM(Some("!512,512"), Some("path_to_image")) val mockResponder = ProjectsResponderADMMock.ProjectRestrictedViewSettingsGetRequestADM( assertion = Assertion.equalTo(identifier), - result = Expectation.value(ProjectRestrictedViewSettingsGetResponseADM(settings)) + result = Expectation.value(ProjectRestrictedViewSettingsResponseADM(settings)) ) for { _ <- ProjectADMRestService @@ -325,7 +325,7 @@ object ProjectsServiceLiveSpec extends ZIOSpecDefault { val settings = ProjectRestrictedViewSettingsADM(Some("!512,512"), Some("path_to_image")) val mockResponder = ProjectsResponderADMMock.ProjectRestrictedViewSettingsGetRequestADM( assertion = Assertion.equalTo(identifier), - result = Expectation.value(ProjectRestrictedViewSettingsGetResponseADM(settings)) + result = Expectation.value(ProjectRestrictedViewSettingsResponseADM(settings)) ) for { _ <- ProjectADMRestService diff --git a/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala b/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala index afbb23442a..017a6d76cd 100644 --- a/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala @@ -660,8 +660,8 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { val mockService: ULayer[ProjectADMRestService] = ProjectADMRestServiceMock .GetRestrictedViewSettings( assertion = Assertion.equalTo(identifier), - result = Expectation.valueF[ProjectIdentifierADM, ProjectRestrictedViewSettingsGetResponseADM](id => - ProjectRestrictedViewSettingsGetResponseADM(settings) + result = Expectation.valueF[ProjectIdentifierADM, ProjectRestrictedViewSettingsResponseADM](id => + ProjectRestrictedViewSettingsResponseADM(settings) ) ) .toLayer @@ -689,8 +689,8 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { val mockService: ULayer[ProjectADMRestService] = ProjectADMRestServiceMock .GetRestrictedViewSettings( assertion = Assertion.equalTo(identifier), - result = Expectation.valueF[ProjectIdentifierADM, ProjectRestrictedViewSettingsGetResponseADM](id => - ProjectRestrictedViewSettingsGetResponseADM(settings) + result = Expectation.valueF[ProjectIdentifierADM, ProjectRestrictedViewSettingsResponseADM](id => + ProjectRestrictedViewSettingsResponseADM(settings) ) ) .toLayer @@ -718,8 +718,8 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { val mockService: ULayer[ProjectADMRestService] = ProjectADMRestServiceMock .GetRestrictedViewSettings( assertion = Assertion.equalTo(identifier), - result = Expectation.valueF[ProjectIdentifierADM, ProjectRestrictedViewSettingsGetResponseADM](id => - ProjectRestrictedViewSettingsGetResponseADM(settings) + result = Expectation.valueF[ProjectIdentifierADM, ProjectRestrictedViewSettingsResponseADM](id => + ProjectRestrictedViewSettingsResponseADM(settings) ) ) .toLayer From d4ae04b143db4509c91ef0907b7f780ce7fd3def Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Tue, 29 Aug 2023 16:44:01 +0200 Subject: [PATCH 09/51] add mocks and service test --- .../ProjectsPayloadsADM.scala | 3 +- .../webapi/routing/admin/ProjectsRouteZ.scala | 2 +- .../api/service/ProjectsADMRestService.scala | 10 +++---- .../admin/ProjectADMRestServiceMock.scala | 18 ++++++++---- .../admin/ProjectsResponderADMMock.scala | 17 +++++------ .../routing/admin/ProjectsRouteZSpec.scala | 29 ++++++++++++++++++- 6 files changed, 54 insertions(+), 25 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsPayloadsADM.scala index 0f9575a4fc..7632daa9da 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsPayloadsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsPayloadsADM.scala @@ -81,8 +81,7 @@ object ProjectUpdatePayloadADM { } final case class ProjectSetRestrictedViewSettingsPayload( - size: Option[String], - watermark: Option[String] + size: Option[String] ) object ProjectSetRestrictedViewSettingsPayload { diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala index 58b9174c85..b47491713e 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala @@ -250,7 +250,7 @@ final case class ProjectsRouteZ( iriDecoded <- RouteUtilZ.urlDecode(iri, s"Failed to URL decode IRI parameter $iri.") isSystemAdmin <- ZIO.succeed(user.permissions.isSystemAdmin) isProjectAdmin <- ZIO.succeed(user.permissions.isProjectAdmin(iri)) -// _ <- ZIO.fail(ForbiddenException("User is not system or project admin.")).when(!isSystemAdmin && !isProjectAdmin) +// _ <- ZIO.fail(ForbiddenException("User is neither system nor project admin.")).when(!isSystemAdmin && !isProjectAdmin) id <- IriIdentifier.fromString(iriDecoded).toZIO.mapError(e => BadRequestException(e.msg)) body <- body.asString payload <- diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala index 39715f648e..36dc6c8754 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala @@ -244,6 +244,11 @@ final case class ProjectsADMRestServiceLive( def getProjectRestrictedViewSettings(id: ProjectIdentifierADM): Task[ProjectRestrictedViewSettingsResponseADM] = responder.projectRestrictedViewSettingsGetRequestADM(id) + override def setProjectRestrictedViewSettings( + id: Iri.ProjectIri, + size: Option[String] + ): Task[ProjectRestrictedViewSettingsResponseADM] = responder.setProjectRestrictedViewSettings(id, size) + override def exportProject(shortcodeStr: String, requestingUser: UserADM): Task[Unit] = for { _ <- permissionService.ensureSystemAdmin(requestingUser) shortcode <- convertStringToShortcode(shortcodeStr) @@ -273,11 +278,6 @@ final case class ProjectsADMRestServiceLive( _ <- permissionService.ensureSystemAdmin(requestingUser) exports <- projectExportService.listExports().map(_.map(ProjectExportInfoResponse(_))) } yield exports - - override def setProjectRestrictedViewSettings( - id: Iri.ProjectIri, - size: Option[String] - ): Task[ProjectRestrictedViewSettingsResponseADM] = responder.setProjectRestrictedViewSettings(id, size) } object ProjectsADMRestServiceLive { diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala index 918d2f0780..5cfd1cb70a 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala @@ -8,7 +8,6 @@ package org.knora.webapi.responders.admin import zio.URLayer import zio._ import zio.mock._ - import dsp.valueobjects.Iri._ import org.knora.webapi.messages.admin.responder.projectsmessages._ import org.knora.webapi.messages.admin.responder.usersmessages.UserADM @@ -32,6 +31,12 @@ object ProjectADMRestServiceMock extends Mock[ProjectADMRestService] { object GetKeywordsByProjectIri extends Effect[ProjectIri, Throwable, ProjectKeywordsGetResponseADM] object GetRestrictedViewSettings extends Effect[ProjectIdentifierADM, Throwable, ProjectRestrictedViewSettingsResponseADM] + object SetRestrictedViewSettings + extends Effect[ + (ProjectIri, Option[String]), + Throwable, + ProjectRestrictedViewSettingsResponseADM + ] override val compose: URLayer[Proxy, ProjectADMRestService] = ZLayer { @@ -92,16 +97,17 @@ object ProjectADMRestServiceMock extends Mock[ProjectADMRestService] { ): Task[ProjectRestrictedViewSettingsResponseADM] = proxy(GetRestrictedViewSettings, identifier) + def setProjectRestrictedViewSettings( + iri: ProjectIri, + size: Option[String] + ): Task[ProjectRestrictedViewSettingsResponseADM] = + proxy(SetRestrictedViewSettings, (iri, size)) + override def exportProject(projectIri: IRI, requestingUser: UserADM): Task[Unit] = ??? override def importProject(projectIri: IRI, requestingUser: UserADM): Task[ProjectImportResponse] = ??? override def listExports(requestingUser: UserADM): Task[Chunk[ProjectExportInfoResponse]] = ??? - - override def setProjectRestrictedViewSettings( - id: ProjectIri, - size: Option[IRI] - ): Task[Unit] = ??? } } } diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala index 04071c3fdb..e5745753f8 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala @@ -46,6 +46,8 @@ object ProjectsResponderADMMock extends Mock[ProjectsResponderADM] { extends Effect[ProjectIdentifierADM, Throwable, Option[ProjectRestrictedViewSettingsADM]] object ProjectRestrictedViewSettingsGetRequestADM extends Effect[ProjectIdentifierADM, Throwable, ProjectRestrictedViewSettingsResponseADM] + object ProjectRestrictedViewSettingSetRequestADM + extends Effect[(Iri.ProjectIri, Option[String]), Throwable, ProjectRestrictedViewSettingsResponseADM] object ProjectCreateRequestADM extends Effect[(ProjectCreatePayloadADM, UserADM, UUID), Throwable, ProjectOperationResponseADM] object ChangeBasicInformationRequestADM @@ -84,6 +86,11 @@ object ProjectsResponderADMMock extends Mock[ProjectsResponderADM] { id: ProjectIdentifierADM ): Task[ProjectRestrictedViewSettingsResponseADM] = proxy(ProjectRestrictedViewSettingsGetRequestADM, id) + override def setProjectRestrictedViewSettings( + id: Iri.ProjectIri, + size: Option[String] + ): Task[ProjectRestrictedViewSettingsResponseADM] = + proxy(ProjectRestrictedViewSettingSetRequestADM, (id, size)) override def projectCreateRequestADM( createPayload: ProjectCreatePayloadADM, requestingUser: UserADM, @@ -97,16 +104,6 @@ object ProjectsResponderADMMock extends Mock[ProjectsResponderADM] { apiRequestID: UUID ): Task[ProjectOperationResponseADM] = proxy(ChangeBasicInformationRequestADM, (projectIri, updatePayload, user, apiRequestID)) - - /** - * Sets project's restricted view settings. - * - * @param id the project's identifier (IRI / shortcode / shortname) - */ - override def setProjectRestrictedViewSettings( - id: Iri.ProjectIri, - size: Option[String] - ): Task[Unit] = ??? } } } diff --git a/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala b/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala index 017a6d76cd..8ee9512492 100644 --- a/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala @@ -83,7 +83,8 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { getProjectAdminsSpec, getKeywordsSpec, getKeywordsByProjectSpec, - getProjectRestrictedViewSettings + getProjectRestrictedViewSettings, + setProjectRestrictedViewSettingsSpec ) val getProjectsSpec: Spec[Any, Serializable] = test("get all projects") { @@ -650,6 +651,32 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { } ) + val setProjectRestrictedViewSettingsSpec: Spec[Any, Serializable] = suite("set project restricted view settings")( + test("successfully set project restricted view") { + val iri = "http://rdfh.ch/projects/0001" + val id = TestDataFactory.projectIri(iri) + val payload = """{"size":"pct:1"}""" + val body = Body.fromString(payload) + val request = Request.post(body, URL(basePathProjectsIri / encode(iri) / "RestrictedViewSettings")) + val settings = ProjectRestrictedViewSettingsADM(Some("pct:1"), Some("null")) + + val expectedResult = + Expectation.value[ProjectRestrictedViewSettingsResponseADM](ProjectRestrictedViewSettingsResponseADM(settings)) + + val mockService = ProjectADMRestServiceMock + .SetRestrictedViewSettings( + assertion = Assertion.equalTo((id, Some("pct:1"))), + result = expectedResult + ) + .toLayer + for { + response <- applyRoutes(request).provide(mockService) + body <- response.body.asString + } yield assertTrue(body.contains("pct:1")) + } + // test("don't set project restricted view if user is not at least project admin") + ) + val getProjectRestrictedViewSettings: Spec[Any, Serializable] = suite("get the restricted view settings of a project by project identifier")( test("successfully get the settings by project IRI") { From 85d266cf32d4c00498af0ac0cfe2b93619076d8d Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Wed, 30 Aug 2023 14:50:57 +0200 Subject: [PATCH 10/51] move user check to responder --- .../projectsmessages/ProjectsMessagesADM.scala | 1 + .../responders/admin/ProjectsResponderADM.scala | 13 +++++++++---- .../knora/webapi/routing/admin/ProjectsRouteZ.scala | 11 ++++------- .../admin/api/service/ProjectsADMRestService.scala | 4 +++- .../admin/ProjectADMRestServiceMock.scala | 5 +++-- .../responders/admin/ProjectsResponderADMMock.scala | 5 +++-- .../webapi/routing/admin/ProjectsRouteZSpec.scala | 3 ++- 7 files changed, 25 insertions(+), 17 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala index cdcf010b08..fe1f1131b9 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala @@ -252,6 +252,7 @@ case class ProjectRestrictedViewSettingsGetRequestADM( */ case class ProjectRestrictedViewSettingsSetRequestADM( identifier: Iri.ProjectIri, + user: UserADM, size: Option[String] ) extends ProjectsResponderRequestADM diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala index 2bf414d430..6e0c1ee12c 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala @@ -132,6 +132,7 @@ trait ProjectsResponderADM { */ def setProjectRestrictedViewSettings( id: Iri.ProjectIri, + user: UserADM, size: Option[String] ): Task[ProjectRestrictedViewSettingsResponseADM] @@ -210,8 +211,8 @@ final case class ProjectsResponderADMLive( projectRestrictedViewSettingsGetADM(identifier) case ProjectRestrictedViewSettingsGetRequestADM(identifier) => projectRestrictedViewSettingsGetRequestADM(identifier) - case ProjectRestrictedViewSettingsSetRequestADM(identifier, size) => - setProjectRestrictedViewSettings(identifier, size) + case ProjectRestrictedViewSettingsSetRequestADM(identifier, user, size) => + setProjectRestrictedViewSettings(identifier, user, size) case ProjectCreateRequestADM(createRequest, requestingUser, apiRequestID) => projectCreateRequestADM(createRequest, requestingUser, apiRequestID) case ProjectChangeRequestADM( @@ -462,6 +463,7 @@ final case class ProjectsResponderADMLive( override def setProjectRestrictedViewSettings( iri: Iri.ProjectIri, + user: UserADM, size: Option[String] = None ): Task[ProjectRestrictedViewSettingsResponseADM] = { val id = ProjectIdentifierADM.IriIdentifier(iri) @@ -469,8 +471,11 @@ final case class ProjectsResponderADMLive( _ <- getProjectFromCacheOrTriplestore(id) .flatMap(ZIO.fromOption(_)) .orElseFail(NotFoundException(s"Project '${getId(id)}' not found.")) + _ <- ZIO + .fail(ForbiddenException("User is neither system nor project admin.")) + .when(!user.permissions.isSystemAdmin && !user.permissions.isProjectAdmin(iri.value)) - defaultViewSetting = size.getOrElse("pc:1") + defaultViewSetting = size.getOrElse("pct:1") query = twirl.queries.sparql.admin.txt .setProjectRestrictedViewSettings(iri.value, defaultViewSetting, None) @@ -859,7 +864,7 @@ final case class ProjectsResponderADMLive( ) // create permissions for admins and members of the new group _ <- createPermissionsForAdminsAndMembersOfNewProject(newProjectIRI) - _ <- setProjectRestrictedViewSettings(id.value) + _ <- setProjectRestrictedViewSettings(id.value, requestingUser) } yield ProjectOperationResponseADM(project = newProjectADM.unescape) diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala index b47491713e..057c0fd927 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala @@ -247,15 +247,12 @@ final case class ProjectsRouteZ( user: UserADM ): Task[Response] = for { - iriDecoded <- RouteUtilZ.urlDecode(iri, s"Failed to URL decode IRI parameter $iri.") - isSystemAdmin <- ZIO.succeed(user.permissions.isSystemAdmin) - isProjectAdmin <- ZIO.succeed(user.permissions.isProjectAdmin(iri)) -// _ <- ZIO.fail(ForbiddenException("User is neither system nor project admin.")).when(!isSystemAdmin && !isProjectAdmin) - id <- IriIdentifier.fromString(iriDecoded).toZIO.mapError(e => BadRequestException(e.msg)) - body <- body.asString + iriDecoded <- RouteUtilZ.urlDecode(iri, s"Failed to URL decode IRI parameter $iri.") + id <- IriIdentifier.fromString(iriDecoded).toZIO.mapError(e => BadRequestException(e.msg)) + body <- body.asString payload <- ZIO.fromEither(body.fromJson[ProjectSetRestrictedViewSettingsPayload]).mapError(e => BadRequestException(e)) - response <- projectsService.setProjectRestrictedViewSettings(id.value, payload.size) + response <- projectsService.setProjectRestrictedViewSettings(id.value, user, payload.size) } yield Response.json(response.toJsValue.toString) } diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala index 36dc6c8754..8460ce519d 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala @@ -65,6 +65,7 @@ trait ProjectADMRestService { ): Task[ProjectRestrictedViewSettingsResponseADM] def setProjectRestrictedViewSettings( id: Iri.ProjectIri, + user: UserADM, size: Option[String] ): Task[ProjectRestrictedViewSettingsResponseADM] } @@ -246,8 +247,9 @@ final case class ProjectsADMRestServiceLive( override def setProjectRestrictedViewSettings( id: Iri.ProjectIri, + user: UserADM, size: Option[String] - ): Task[ProjectRestrictedViewSettingsResponseADM] = responder.setProjectRestrictedViewSettings(id, size) + ): Task[ProjectRestrictedViewSettingsResponseADM] = responder.setProjectRestrictedViewSettings(id, user, size) override def exportProject(shortcodeStr: String, requestingUser: UserADM): Task[Unit] = for { _ <- permissionService.ensureSystemAdmin(requestingUser) diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala index 5cfd1cb70a..304df42b53 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala @@ -33,7 +33,7 @@ object ProjectADMRestServiceMock extends Mock[ProjectADMRestService] { extends Effect[ProjectIdentifierADM, Throwable, ProjectRestrictedViewSettingsResponseADM] object SetRestrictedViewSettings extends Effect[ - (ProjectIri, Option[String]), + (ProjectIri, UserADM, Option[String]), Throwable, ProjectRestrictedViewSettingsResponseADM ] @@ -99,9 +99,10 @@ object ProjectADMRestServiceMock extends Mock[ProjectADMRestService] { def setProjectRestrictedViewSettings( iri: ProjectIri, + user: UserADM, size: Option[String] ): Task[ProjectRestrictedViewSettingsResponseADM] = - proxy(SetRestrictedViewSettings, (iri, size)) + proxy(SetRestrictedViewSettings, (iri, user, size)) override def exportProject(projectIri: IRI, requestingUser: UserADM): Task[Unit] = ??? diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala index e5745753f8..1e1626d71b 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala @@ -47,7 +47,7 @@ object ProjectsResponderADMMock extends Mock[ProjectsResponderADM] { object ProjectRestrictedViewSettingsGetRequestADM extends Effect[ProjectIdentifierADM, Throwable, ProjectRestrictedViewSettingsResponseADM] object ProjectRestrictedViewSettingSetRequestADM - extends Effect[(Iri.ProjectIri, Option[String]), Throwable, ProjectRestrictedViewSettingsResponseADM] + extends Effect[(Iri.ProjectIri, UserADM, Option[String]), Throwable, ProjectRestrictedViewSettingsResponseADM] object ProjectCreateRequestADM extends Effect[(ProjectCreatePayloadADM, UserADM, UUID), Throwable, ProjectOperationResponseADM] object ChangeBasicInformationRequestADM @@ -88,9 +88,10 @@ object ProjectsResponderADMMock extends Mock[ProjectsResponderADM] { proxy(ProjectRestrictedViewSettingsGetRequestADM, id) override def setProjectRestrictedViewSettings( id: Iri.ProjectIri, + user: UserADM, size: Option[String] ): Task[ProjectRestrictedViewSettingsResponseADM] = - proxy(ProjectRestrictedViewSettingSetRequestADM, (id, size)) + proxy(ProjectRestrictedViewSettingSetRequestADM, (id, user, size)) override def projectCreateRequestADM( createPayload: ProjectCreatePayloadADM, requestingUser: UserADM, diff --git a/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala b/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala index 8ee9512492..ced435f219 100644 --- a/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala @@ -654,6 +654,7 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { val setProjectRestrictedViewSettingsSpec: Spec[Any, Serializable] = suite("set project restricted view settings")( test("successfully set project restricted view") { val iri = "http://rdfh.ch/projects/0001" + val user = KnoraSystemInstances.Users.SystemUser val id = TestDataFactory.projectIri(iri) val payload = """{"size":"pct:1"}""" val body = Body.fromString(payload) @@ -665,7 +666,7 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { val mockService = ProjectADMRestServiceMock .SetRestrictedViewSettings( - assertion = Assertion.equalTo((id, Some("pct:1"))), + assertion = Assertion.equalTo((id, user, Some("pct:1"))), result = expectedResult ) .toLayer From 2b71493cdf51a9219968b30db6826fa78751e23a Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Wed, 30 Aug 2023 15:15:57 +0200 Subject: [PATCH 11/51] add code documentation --- .../projectsmessages/ProjectsMessagesADM.scala | 6 ++++-- .../responders/admin/ProjectsResponderADM.scala | 17 ++++++++++++----- .../webapi/routing/admin/ProjectsRouteZ.scala | 1 - .../api/service/ProjectsADMRestService.scala | 14 +++++++++++--- .../routing/admin/ProjectsRouteZSpec.scala | 1 - 5 files changed, 27 insertions(+), 12 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala index fe1f1131b9..df3f839596 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala @@ -248,10 +248,12 @@ case class ProjectRestrictedViewSettingsGetRequestADM( /** * Return project's RestrictedView settings. * - * @param identifier the identifier of the project. + * @param iri the identifier of the project. + * @param user requesting user. + * @param size size value to be applied. */ case class ProjectRestrictedViewSettingsSetRequestADM( - identifier: Iri.ProjectIri, + iri: Iri.ProjectIri, user: UserADM, size: Option[String] ) extends ProjectsResponderRequestADM diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala index 6e0c1ee12c..2f18c0e3a5 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala @@ -211,8 +211,8 @@ final case class ProjectsResponderADMLive( projectRestrictedViewSettingsGetADM(identifier) case ProjectRestrictedViewSettingsGetRequestADM(identifier) => projectRestrictedViewSettingsGetRequestADM(identifier) - case ProjectRestrictedViewSettingsSetRequestADM(identifier, user, size) => - setProjectRestrictedViewSettings(identifier, user, size) + case ProjectRestrictedViewSettingsSetRequestADM(iri, user, size) => + setProjectRestrictedViewSettings(iri, user, size) case ProjectCreateRequestADM(createRequest, requestingUser, apiRequestID) => projectCreateRequestADM(createRequest, requestingUser, apiRequestID) case ProjectChangeRequestADM( @@ -461,6 +461,14 @@ final case class ProjectsResponderADMLive( ProjectRestrictedViewSettingsResponseADM ) + /** + * Sets project's restricted view settings. + * + * @param iri the project's iri, + * @param user requesting user, + * @param size value to be set, + * @return [[ProjectRestrictedViewSettingsResponseADM]]. + */ override def setProjectRestrictedViewSettings( iri: Iri.ProjectIri, user: UserADM, @@ -480,9 +488,8 @@ final case class ProjectsResponderADMLive( query = twirl.queries.sparql.admin.txt .setProjectRestrictedViewSettings(iri.value, defaultViewSetting, None) - response <- triplestoreService.sparqlHttpUpdate(query.toString) - _ = println(777, response) - settings = ProjectRestrictedViewSettingsADM(size) + _ <- triplestoreService.sparqlHttpUpdate(query.toString) + settings = ProjectRestrictedViewSettingsADM(size) } yield ProjectRestrictedViewSettingsResponseADM(settings) } diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala index 057c0fd927..3435cb9575 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala @@ -254,7 +254,6 @@ final case class ProjectsRouteZ( ZIO.fromEither(body.fromJson[ProjectSetRestrictedViewSettingsPayload]).mapError(e => BadRequestException(e)) response <- projectsService.setProjectRestrictedViewSettings(id.value, user, payload.size) } yield Response.json(response.toJsValue.toString) - } object ProjectsRouteZ { diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala index 8460ce519d..11e3c13f46 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala @@ -64,7 +64,7 @@ trait ProjectADMRestService { identifier: ProjectIdentifierADM ): Task[ProjectRestrictedViewSettingsResponseADM] def setProjectRestrictedViewSettings( - id: Iri.ProjectIri, + iri: Iri.ProjectIri, user: UserADM, size: Option[String] ): Task[ProjectRestrictedViewSettingsResponseADM] @@ -245,11 +245,19 @@ final case class ProjectsADMRestServiceLive( def getProjectRestrictedViewSettings(id: ProjectIdentifierADM): Task[ProjectRestrictedViewSettingsResponseADM] = responder.projectRestrictedViewSettingsGetRequestADM(id) + /** + * Sets project's restricted view settings. + * + * @param iri the project's IRI, + * @param user requesting user, + * @param size value to be set, + * @return [[ProjectRestrictedViewSettingsResponseADM]]. + */ override def setProjectRestrictedViewSettings( - id: Iri.ProjectIri, + iri: Iri.ProjectIri, user: UserADM, size: Option[String] - ): Task[ProjectRestrictedViewSettingsResponseADM] = responder.setProjectRestrictedViewSettings(id, user, size) + ): Task[ProjectRestrictedViewSettingsResponseADM] = responder.setProjectRestrictedViewSettings(iri, user, size) override def exportProject(shortcodeStr: String, requestingUser: UserADM): Task[Unit] = for { _ <- permissionService.ensureSystemAdmin(requestingUser) diff --git a/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala b/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala index ced435f219..b854e371ed 100644 --- a/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala @@ -675,7 +675,6 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { body <- response.body.asString } yield assertTrue(body.contains("pct:1")) } - // test("don't set project restricted view if user is not at least project admin") ) val getProjectRestrictedViewSettings: Spec[Any, Serializable] = From b19ce9f1a29ad74bae269fe69879f8ae2b62f20a Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Thu, 31 Aug 2023 13:26:59 +0200 Subject: [PATCH 12/51] tests cleanup --- .../webapi/routing/admin/ProjectsRouteZ.scala | 1 - .../admin/ProjectADMRestServiceMock.scala | 1 + .../routing/admin/ProjectsRouteZSpec.scala | 144 ++++++++++-------- 3 files changed, 79 insertions(+), 67 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala index 3435cb9575..0827016c39 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala @@ -14,7 +14,6 @@ import zio.stream.ZStream import java.nio.file.Files import dsp.errors.BadRequestException -import dsp.errors.ForbiddenException import dsp.valueobjects.Iri._ import org.knora.webapi.config.AppConfig import org.knora.webapi.http.handler.ExceptionHandlerZ diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala index 304df42b53..1d401edec6 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala @@ -8,6 +8,7 @@ package org.knora.webapi.responders.admin import zio.URLayer import zio._ import zio.mock._ + import dsp.valueobjects.Iri._ import org.knora.webapi.messages.admin.responder.projectsmessages._ import org.knora.webapi.messages.admin.responder.usersmessages.UserADM diff --git a/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala b/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala index b854e371ed..7a115f9b9c 100644 --- a/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala @@ -93,7 +93,7 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { val mockService = ProjectADMRestServiceMock.GetProjects(expectedResult).toLayer for { response <- applyRoutes(request).provide(mockService) - body <- response.body.asString + _ <- response.body.asString } yield assertTrue(true) } @@ -117,14 +117,15 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { }, test("return a BadRequest Exception if project IRI is invalid") { val iri = "http://rdfh.ch/project/0001" - val user = KnoraSystemInstances.Users.SystemUser val request = Request.get(url = URL(basePathProjectsIri / encode(iri))) for { response <- applyRoutes(request).provide(ProjectADMRestServiceMock.empty) bodyAsString <- response.body.asString - } yield assertTrue(response.status == Status.BadRequest) && - assertTrue(bodyAsString == """{"error":"dsp.errors.BadRequestException: Project IRI is invalid."}""") + } yield assertTrue( + response.status == Status.BadRequest, + bodyAsString == """{"error":"dsp.errors.BadRequestException: Project IRI is invalid."}""" + ) }, test("get a project by shortname") { val shortname = "someProject" @@ -145,14 +146,15 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { }, test("return a BadRequest Exception if shortname is invalid") { val shortname = "short name" - val user = KnoraSystemInstances.Users.SystemUser val request = Request.get(url = URL(basePathProjectsShortname / shortname)) for { response <- applyRoutes(request).provide(ProjectADMRestServiceMock.empty) bodyAsString <- response.body.asString - } yield assertTrue(response.status == Status.BadRequest) && - assertTrue(bodyAsString == """{"error":"dsp.errors.BadRequestException: Shortname is invalid: short name"}""") + } yield assertTrue( + response.status == Status.BadRequest, + bodyAsString == """{"error":"dsp.errors.BadRequestException: Shortname is invalid: short name"}""" + ) }, test("get a project by shortcode") { val shortcode = "0001" @@ -173,14 +175,15 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { }, test("return a BadRequest Exception if shortcode is invalid") { val shortcode = "XY" - val user = KnoraSystemInstances.Users.SystemUser val request = Request.get(url = URL(basePathProjectsShortcode / shortcode)) for { response <- applyRoutes(request).provide(ProjectADMRestServiceMock.empty) bodyAsString <- response.body.asString - } yield assertTrue(response.status == Status.BadRequest) && - assertTrue(bodyAsString == """{"error":"dsp.errors.BadRequestException: Shortcode is invalid: XY"}""") + } yield assertTrue( + response.status == Status.BadRequest, + bodyAsString == """{"error":"dsp.errors.BadRequestException: Shortcode is invalid: XY"}""" + ) } ) @@ -246,14 +249,13 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { |""".stripMargin val body = Body.fromString(projectCreatePayloadString) val request = Request.post(url = URL(basePathProjects), body = body) - val user = KnoraSystemInstances.Users.SystemUser for { response <- applyRoutes(request).provide(ProjectADMRestServiceMock.empty) bodyAsString <- response.body.asString - } yield assertTrue(response.status == Status.BadRequest) && - assertTrue( - bodyAsString == """{"error":"dsp.errors.BadRequestException: .shortname(Shortname is invalid: new project)"}""" - ) + } yield assertTrue( + response.status == Status.BadRequest, + bodyAsString == """{"error":"dsp.errors.BadRequestException: .shortname(Shortname is invalid: new project)"}""" + ) }, test("return a BadRequest Exception if input (syntax) is invalid") { val projectCreatePayloadString = @@ -269,7 +271,6 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { |""".stripMargin val body = Body.fromString(projectCreatePayloadString) val request = Request.post(url = URL(basePathProjects), body = body) - val user = KnoraSystemInstances.Users.SystemUser for { response <- applyRoutes(request).provide(ProjectADMRestServiceMock.empty) } yield assertTrue(response.status == Status.BadRequest) @@ -295,14 +296,15 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { }, test("return a BadRequest Exception if project IRI is invalid") { val iri = "http://rdfh.ch/project/0001" - val user = KnoraSystemInstances.Users.SystemUser val request = Request.delete(url = URL(basePathProjectsIri / encode(iri))) for { response <- applyRoutes(request).provide(ProjectADMRestServiceMock.empty) bodyAsString <- response.body.asString - } yield assertTrue(response.status == Status.BadRequest) && - assertTrue(bodyAsString == """{"error":"dsp.errors.BadRequestException: Project IRI is invalid."}""") + } yield assertTrue( + response.status == Status.BadRequest, + bodyAsString == """{"error":"dsp.errors.BadRequestException: Project IRI is invalid."}""" + ) } ) @@ -359,22 +361,20 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { val projectUpdatePayloadString = """{"shortname": "invalid shortname"}""".stripMargin val body = Body.fromString(projectUpdatePayloadString) val request = Request.put(url = URL(basePathProjectsIri / encode(projectIri)), body = body) - val user = KnoraSystemInstances.Users.SystemUser for { response <- applyRoutes(request).provide(ProjectADMRestServiceMock.empty) bodyAsString <- response.body.asString - } yield assertTrue(response.status == Status.BadRequest) && - assertTrue( - bodyAsString == """{"error":"dsp.errors.BadRequestException: .shortname(Shortname is invalid: invalid shortname)"}""" - ) + } yield assertTrue( + response.status == Status.BadRequest, + bodyAsString == """{"error":"dsp.errors.BadRequestException: .shortname(Shortname is invalid: invalid shortname)"}""" + ) }, test("return a BadRequest Exception if input (syntax) is invalid") { val projectIri = "http://rdfh.ch/projects/0001" val projectUpdatePayloadString = """{"shortname":"usn" "longname":"updated longname"}""".stripMargin val body = Body.fromString(projectUpdatePayloadString) val request = Request.put(url = URL(basePathProjectsIri / encode(projectIri)), body = body) - val user = KnoraSystemInstances.Users.SystemUser for { response <- applyRoutes(request).provide(ProjectADMRestServiceMock.empty) @@ -385,13 +385,14 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { val projectUpdatePayloadString = """{"shortname":"usn"}""".stripMargin val body = Body.fromString(projectUpdatePayloadString) val request = Request.put(url = URL(basePathProjectsIri / encode(projectIri)), body = body) - val user = KnoraSystemInstances.Users.SystemUser for { response <- applyRoutes(request).provide(ProjectADMRestServiceMock.empty) bodyAsString <- response.body.asString - } yield assertTrue(response.status == Status.BadRequest) && - assertTrue(bodyAsString == """{"error":"dsp.errors.BadRequestException: Project IRI is invalid."}""") + } yield assertTrue( + response.status == Status.BadRequest, + bodyAsString == """{"error":"dsp.errors.BadRequestException: Project IRI is invalid."}""" + ) } ) @@ -413,20 +414,20 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { .toLayer for { response <- applyRoutes(request).provide(mockService) - body <- response.body.asString + _ <- response.body.asString } yield assertTrue(true) }, test("return a BadRequest Exception if project IRI is invalid") { val iri = "http://rdfh.ch/project/0001" - val user = KnoraSystemInstances.Users.SystemUser val request = Request.get(url = URL(basePathProjectsIri / encode(iri) / "AllData")) - val path = file.Paths.get("...") for { response <- applyRoutes(request).provide(ProjectADMRestServiceMock.empty) bodyAsString <- response.body.asString - } yield assertTrue(response.status == Status.BadRequest) && - assertTrue(bodyAsString == """{"error":"dsp.errors.BadRequestException: Project IRI is invalid."}""") + } yield assertTrue( + response.status == Status.BadRequest, + bodyAsString == """{"error":"dsp.errors.BadRequestException: Project IRI is invalid."}""" + ) } ) @@ -451,14 +452,15 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { }, test("return a BadRequest Exception if project IRI is invalid") { val iri = "http://rdfh.ch/project/0001" - val user = KnoraSystemInstances.Users.SystemUser val request = Request.get(url = URL(basePathProjectsIri / encode(iri) / "members")) for { response <- applyRoutes(request).provide(ProjectADMRestServiceMock.empty) bodyAsString <- response.body.asString - } yield assertTrue(response.status == Status.BadRequest) && - assertTrue(bodyAsString == """{"error":"dsp.errors.BadRequestException: Project IRI is invalid."}""") + } yield assertTrue( + response.status == Status.BadRequest, + bodyAsString == """{"error":"dsp.errors.BadRequestException: Project IRI is invalid."}""" + ) }, test("get all members by project shortcode") { val shortcode = "0001" @@ -480,14 +482,15 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { }, test("return a BadRequest Exception if shortcode is invalid") { val shortcode = "XY" - val user = KnoraSystemInstances.Users.SystemUser val request = Request.get(url = URL(basePathProjectsShortcode / shortcode / "members")) for { response <- applyRoutes(request).provide(ProjectADMRestServiceMock.empty) bodyAsString <- response.body.asString - } yield assertTrue(response.status == Status.BadRequest) && - assertTrue(bodyAsString == """{"error":"dsp.errors.BadRequestException: Shortcode is invalid: XY"}""") + } yield assertTrue( + response.status == Status.BadRequest, + bodyAsString == """{"error":"dsp.errors.BadRequestException: Shortcode is invalid: XY"}""" + ) }, test("get all members by project shortname") { val shortname = "someProject" @@ -509,14 +512,15 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { }, test("return a BadRequest Exception if shortname is invalid") { val shortname = "short name" - val user = KnoraSystemInstances.Users.SystemUser val request = Request.get(url = URL(basePathProjectsShortname / shortname / "members")) for { response <- applyRoutes(request).provide(ProjectADMRestServiceMock.empty) bodyAsString <- response.body.asString - } yield assertTrue(response.status == Status.BadRequest) && - assertTrue(bodyAsString == """{"error":"dsp.errors.BadRequestException: Shortname is invalid: short name"}""") + } yield assertTrue( + response.status == Status.BadRequest, + bodyAsString == """{"error":"dsp.errors.BadRequestException: Shortname is invalid: short name"}""" + ) } ) @@ -541,14 +545,15 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { }, test("return a BadRequest Exception if project IRI is invalid") { val iri = "http://rdfh.ch/project/0001" - val user = KnoraSystemInstances.Users.SystemUser val request = Request.get(url = URL(basePathProjectsIri / encode(iri) / "admin-members")) for { response <- applyRoutes(request).provide(ProjectADMRestServiceMock.empty) bodyAsString <- response.body.asString - } yield assertTrue(response.status == Status.BadRequest) && - assertTrue(bodyAsString == """{"error":"dsp.errors.BadRequestException: Project IRI is invalid."}""") + } yield assertTrue( + response.status == Status.BadRequest, + bodyAsString == """{"error":"dsp.errors.BadRequestException: Project IRI is invalid."}""" + ) }, test("get all project admins by project shortcode") { val shortcode = "0001" @@ -570,14 +575,15 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { }, test("return a BadRequest Exception if shortcode is invalid") { val shortcode = "XY" - val user = KnoraSystemInstances.Users.SystemUser val request = Request.get(url = URL(basePathProjectsShortcode / shortcode / "admin-members")) for { response <- applyRoutes(request).provide(ProjectADMRestServiceMock.empty) bodyAsString <- response.body.asString - } yield assertTrue(response.status == Status.BadRequest) && - assertTrue(bodyAsString == """{"error":"dsp.errors.BadRequestException: Shortcode is invalid: XY"}""") + } yield assertTrue( + response.status == Status.BadRequest, + bodyAsString == """{"error":"dsp.errors.BadRequestException: Shortcode is invalid: XY"}""" + ) }, test("get all project admins by project shortname") { val shortname = "someProject" @@ -599,14 +605,15 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { }, test("return a BadRequest Exception if shortname is invalid") { val shortname = "short name" - val user = KnoraSystemInstances.Users.SystemUser val request = Request.get(url = URL(basePathProjectsShortname / shortname / "admin-members")) for { response <- applyRoutes(request).provide(ProjectADMRestServiceMock.empty) bodyAsString <- response.body.asString - } yield assertTrue(response.status == Status.BadRequest) && - assertTrue(bodyAsString == """{"error":"dsp.errors.BadRequestException: Shortname is invalid: short name"}""") + } yield assertTrue( + response.status == Status.BadRequest, + bodyAsString == """{"error":"dsp.errors.BadRequestException: Shortname is invalid: short name"}""" + ) } ) @@ -617,7 +624,7 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { val mockService = ProjectADMRestServiceMock.GetKeywords(expectedResult).toLayer for { response <- applyRoutes(request).provide(mockService) - body <- response.body.asString + _ <- response.body.asString } yield assertCompletes } @@ -646,8 +653,10 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { for { response <- applyRoutes(request).provide(ProjectADMRestServiceMock.empty) bodyAsString <- response.body.asString - } yield assertTrue(response.status == Status.BadRequest) && - assertTrue(bodyAsString == """{"error":"dsp.errors.BadRequestException: Project IRI is invalid."}""") + } yield assertTrue( + response.status == Status.BadRequest, + bodyAsString == """{"error":"dsp.errors.BadRequestException: Project IRI is invalid."}""" + ) } ) @@ -687,7 +696,7 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { val mockService: ULayer[ProjectADMRestService] = ProjectADMRestServiceMock .GetRestrictedViewSettings( assertion = Assertion.equalTo(identifier), - result = Expectation.valueF[ProjectIdentifierADM, ProjectRestrictedViewSettingsResponseADM](id => + result = Expectation.valueF[ProjectIdentifierADM, ProjectRestrictedViewSettingsResponseADM](_ => ProjectRestrictedViewSettingsResponseADM(settings) ) ) @@ -699,14 +708,15 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { }, test("return a BadRequest Exception if project IRI is invalid") { val iri = "http://rdfh.ch/project/0001" - val user = KnoraSystemInstances.Users.SystemUser val request = Request.get(url = URL(basePathProjectsIri / encode(iri) / "RestrictedViewSettings")) for { response <- applyRoutes(request).provide(ProjectADMRestServiceMock.empty) bodyAsString <- response.body.asString - } yield assertTrue(response.status == Status.BadRequest) && - assertTrue(bodyAsString == """{"error":"dsp.errors.BadRequestException: Project IRI is invalid."}""") + } yield assertTrue( + response.status == Status.BadRequest, + bodyAsString == """{"error":"dsp.errors.BadRequestException: Project IRI is invalid."}""" + ) }, test("successfully get the settings by shortname") { val shortname = "someProject" @@ -716,7 +726,7 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { val mockService: ULayer[ProjectADMRestService] = ProjectADMRestServiceMock .GetRestrictedViewSettings( assertion = Assertion.equalTo(identifier), - result = Expectation.valueF[ProjectIdentifierADM, ProjectRestrictedViewSettingsResponseADM](id => + result = Expectation.valueF[ProjectIdentifierADM, ProjectRestrictedViewSettingsResponseADM](_ => ProjectRestrictedViewSettingsResponseADM(settings) ) ) @@ -728,14 +738,15 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { }, test("return a BadRequest Exception if shortname is invalid") { val shortname = "short name" - val user = KnoraSystemInstances.Users.SystemUser val request = Request.get(url = URL(basePathProjectsShortname / shortname / "RestrictedViewSettings")) for { response <- applyRoutes(request).provide(ProjectADMRestServiceMock.empty) bodyAsString <- response.body.asString - } yield assertTrue(response.status == Status.BadRequest) && - assertTrue(bodyAsString == """{"error":"dsp.errors.BadRequestException: Shortname is invalid: short name"}""") + } yield assertTrue( + response.status == Status.BadRequest, + bodyAsString == """{"error":"dsp.errors.BadRequestException: Shortname is invalid: short name"}""" + ) }, test("successfully get the settings by shortcode") { val shortcode = "0001" @@ -745,7 +756,7 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { val mockService: ULayer[ProjectADMRestService] = ProjectADMRestServiceMock .GetRestrictedViewSettings( assertion = Assertion.equalTo(identifier), - result = Expectation.valueF[ProjectIdentifierADM, ProjectRestrictedViewSettingsResponseADM](id => + result = Expectation.valueF[ProjectIdentifierADM, ProjectRestrictedViewSettingsResponseADM](_ => ProjectRestrictedViewSettingsResponseADM(settings) ) ) @@ -757,14 +768,15 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { }, test("return a BadRequest Exception if shortcode is invalid") { val shortcode = "XY" - val user = KnoraSystemInstances.Users.SystemUser val request = Request.get(url = URL(basePathProjectsShortcode / shortcode / "RestrictedViewSettings")) for { response <- applyRoutes(request).provide(ProjectADMRestServiceMock.empty) bodyAsString <- response.body.asString - } yield assertTrue(response.status == Status.BadRequest) && - assertTrue(bodyAsString == """{"error":"dsp.errors.BadRequestException: Shortcode is invalid: XY"}""") + } yield assertTrue( + response.status == Status.BadRequest, + bodyAsString == """{"error":"dsp.errors.BadRequestException: Shortcode is invalid: XY"}""" + ) } ) } From fa73a5564e16f16dbd46bd5ac5bd9a389e8bb822 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Thu, 31 Aug 2023 15:38:48 +0200 Subject: [PATCH 13/51] fix docs --- .../webapi/responders/admin/ProjectsResponderADM.scala | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala index 2f18c0e3a5..ca74dcdae2 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala @@ -128,10 +128,13 @@ trait ProjectsResponderADM { /** * Sets project's restricted view settings. * - * @param id the project's identifier (IRI / shortcode / shortname) + * @param iri the project's iri, + * @param user requesting user, + * @param size value to be set, + * @return [[ProjectRestrictedViewSettingsResponseADM]]. */ def setProjectRestrictedViewSettings( - id: Iri.ProjectIri, + iri: Iri.ProjectIri, user: UserADM, size: Option[String] ): Task[ProjectRestrictedViewSettingsResponseADM] From 6b0b2ac893f355d518e8796040e6f366b298807a Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Thu, 31 Aug 2023 17:01:40 +0200 Subject: [PATCH 14/51] add route documentation + fix user permission logic --- docs/03-endpoints/api-admin/projects.md | 35 +++++++++++++++++-- .../admin/ProjectsResponderADM.scala | 2 +- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/docs/03-endpoints/api-admin/projects.md b/docs/03-endpoints/api-admin/projects.md index a4aab2b4e2..30c0aa62b9 100644 --- a/docs/03-endpoints/api-admin/projects.md +++ b/docs/03-endpoints/api-admin/projects.md @@ -774,7 +774,7 @@ Example response: ``` -### Restricted View Settings +### Get Restricted View Settings Permissions: ProjectAdmin @@ -798,7 +798,7 @@ curl --request GET 'http://0.0.0.0:3333/admin/projects/shortname/anything/Restri ``` ```bash -curl --request GET 'http://0.0.0.0:3333/admin/projects/iri/http%3A%2F%2Frdfh.ch%2Fprojects%2F0001/RestrictedViewSettings' +curl --request GET 'http://0.0.0.0:3333/admin/projects/iri/http%3A%2F%2Frdfh.ch%2Fprojects%2F0001/RestrictedViewSettings' \ --header 'Authorization: Basic cm9vdEBleGFtcGxlLmNvbTp0ZXN0' ``` @@ -813,6 +813,37 @@ Example response: } ``` +### Set Restricted View Settings + +Permissions: ProjectAdmin/SystemAdmin + +Request definition: +- `POST /admin/projects/iri/{iri}/RestrictedViewSettings` + +Description: Set the project's restricted view + +Required payload: +- `size` + +Example request: + +```bash +curl --request GET 'http://0.0.0.0:3333/admin/projects/iri/http%3A%2F%2Frdfh.ch%2Fprojects%2F0001/RestrictedViewSettings' \ +--header 'Authorization: Basic cm9vdEBleGFtcGxlLmNvbTp0ZXN0' \ +--data '{"size": "222"} +``` + +Example response: + +```jsonc +{ + "settings": { + "size": "!512,512", + "watermark": "path_to_image" + } +} +``` + Operates on the following properties: - `knora-admin:projectRestrictedViewSize`: the IIIF size value - `knora-admin:projectRestrictedViewWatermark`: the path to the watermark image. **Currently not used!** diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala index ca74dcdae2..cec6d37dc9 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala @@ -484,7 +484,7 @@ final case class ProjectsResponderADMLive( .orElseFail(NotFoundException(s"Project '${getId(id)}' not found.")) _ <- ZIO .fail(ForbiddenException("User is neither system nor project admin.")) - .when(!user.permissions.isSystemAdmin && !user.permissions.isProjectAdmin(iri.value)) + .unless(user.permissions.isSystemAdmin || user.permissions.isProjectAdmin(iri.value)) defaultViewSetting = size.getOrElse("pct:1") From 4971df0c444e66c49b155912201a9e73dd53475e Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Tue, 5 Sep 2023 12:42:24 +0200 Subject: [PATCH 15/51] make size required and temp. remove default --- .../projectsmessages/ProjectsMessagesADM.scala | 2 +- .../projectsmessages/ProjectsPayloadsADM.scala | 4 +--- .../responders/admin/ProjectsResponderADM.scala | 14 +++++++------- .../admin/api/service/ProjectsADMRestService.scala | 7 ++++--- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala index df3f839596..571088d3e8 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala @@ -255,7 +255,7 @@ case class ProjectRestrictedViewSettingsGetRequestADM( case class ProjectRestrictedViewSettingsSetRequestADM( iri: Iri.ProjectIri, user: UserADM, - size: Option[String] + size: String ) extends ProjectsResponderRequestADM /** diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsPayloadsADM.scala index 7632daa9da..ef3a807b01 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsPayloadsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsPayloadsADM.scala @@ -80,9 +80,7 @@ object ProjectUpdatePayloadADM { } } -final case class ProjectSetRestrictedViewSettingsPayload( - size: Option[String] -) +final case class ProjectSetRestrictedViewSettingsPayload(size: String) object ProjectSetRestrictedViewSettingsPayload { implicit val codec: JsonCodec[ProjectSetRestrictedViewSettingsPayload] = diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala index cec6d37dc9..4d56b599dc 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala @@ -136,7 +136,7 @@ trait ProjectsResponderADM { def setProjectRestrictedViewSettings( iri: Iri.ProjectIri, user: UserADM, - size: Option[String] + size: String ): Task[ProjectRestrictedViewSettingsResponseADM] /** @@ -475,7 +475,7 @@ final case class ProjectsResponderADMLive( override def setProjectRestrictedViewSettings( iri: Iri.ProjectIri, user: UserADM, - size: Option[String] = None + size: String ): Task[ProjectRestrictedViewSettingsResponseADM] = { val id = ProjectIdentifierADM.IriIdentifier(iri) for { @@ -486,13 +486,11 @@ final case class ProjectsResponderADMLive( .fail(ForbiddenException("User is neither system nor project admin.")) .unless(user.permissions.isSystemAdmin || user.permissions.isProjectAdmin(iri.value)) - defaultViewSetting = size.getOrElse("pct:1") - query = twirl.queries.sparql.admin.txt - .setProjectRestrictedViewSettings(iri.value, defaultViewSetting, None) + .setProjectRestrictedViewSettings(iri.value, size, None) _ <- triplestoreService.sparqlHttpUpdate(query.toString) - settings = ProjectRestrictedViewSettingsADM(size) + settings = ProjectRestrictedViewSettingsADM(Some(size)) } yield ProjectRestrictedViewSettingsResponseADM(settings) } @@ -874,7 +872,9 @@ final case class ProjectsResponderADMLive( ) // create permissions for admins and members of the new group _ <- createPermissionsForAdminsAndMembersOfNewProject(newProjectIRI) - _ <- setProjectRestrictedViewSettings(id.value, requestingUser) +// TODO: DEV-2626 add default value here +// defaultSize = "" +// _ <- setProjectRestrictedViewSettings(id.value, requestingUser, defaultSize) } yield ProjectOperationResponseADM(project = newProjectADM.unescape) diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala index 11e3c13f46..d2bfacfeb1 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala @@ -66,7 +66,7 @@ trait ProjectADMRestService { def setProjectRestrictedViewSettings( iri: Iri.ProjectIri, user: UserADM, - size: Option[String] + size: String ): Task[ProjectRestrictedViewSettingsResponseADM] } @@ -256,8 +256,9 @@ final case class ProjectsADMRestServiceLive( override def setProjectRestrictedViewSettings( iri: Iri.ProjectIri, user: UserADM, - size: Option[String] - ): Task[ProjectRestrictedViewSettingsResponseADM] = responder.setProjectRestrictedViewSettings(iri, user, size) + size: String + ): Task[ProjectRestrictedViewSettingsResponseADM] = + responder.setProjectRestrictedViewSettings(iri, user, size) override def exportProject(shortcodeStr: String, requestingUser: UserADM): Task[Unit] = for { _ <- permissionService.ensureSystemAdmin(requestingUser) From 6487d6cf63571af389f8c9298726e739ef260605 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Tue, 5 Sep 2023 12:45:46 +0200 Subject: [PATCH 16/51] fix test --- .../webapi/responders/admin/ProjectADMRestServiceMock.scala | 4 ++-- .../webapi/responders/admin/ProjectsResponderADMMock.scala | 4 ++-- .../org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala index 1d401edec6..d821716a58 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala @@ -34,7 +34,7 @@ object ProjectADMRestServiceMock extends Mock[ProjectADMRestService] { extends Effect[ProjectIdentifierADM, Throwable, ProjectRestrictedViewSettingsResponseADM] object SetRestrictedViewSettings extends Effect[ - (ProjectIri, UserADM, Option[String]), + (ProjectIri, UserADM, String), Throwable, ProjectRestrictedViewSettingsResponseADM ] @@ -101,7 +101,7 @@ object ProjectADMRestServiceMock extends Mock[ProjectADMRestService] { def setProjectRestrictedViewSettings( iri: ProjectIri, user: UserADM, - size: Option[String] + size: String ): Task[ProjectRestrictedViewSettingsResponseADM] = proxy(SetRestrictedViewSettings, (iri, user, size)) diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala index 1e1626d71b..1ff179e95e 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala @@ -47,7 +47,7 @@ object ProjectsResponderADMMock extends Mock[ProjectsResponderADM] { object ProjectRestrictedViewSettingsGetRequestADM extends Effect[ProjectIdentifierADM, Throwable, ProjectRestrictedViewSettingsResponseADM] object ProjectRestrictedViewSettingSetRequestADM - extends Effect[(Iri.ProjectIri, UserADM, Option[String]), Throwable, ProjectRestrictedViewSettingsResponseADM] + extends Effect[(Iri.ProjectIri, UserADM, String), Throwable, ProjectRestrictedViewSettingsResponseADM] object ProjectCreateRequestADM extends Effect[(ProjectCreatePayloadADM, UserADM, UUID), Throwable, ProjectOperationResponseADM] object ChangeBasicInformationRequestADM @@ -89,7 +89,7 @@ object ProjectsResponderADMMock extends Mock[ProjectsResponderADM] { override def setProjectRestrictedViewSettings( id: Iri.ProjectIri, user: UserADM, - size: Option[String] + size: String ): Task[ProjectRestrictedViewSettingsResponseADM] = proxy(ProjectRestrictedViewSettingSetRequestADM, (id, user, size)) override def projectCreateRequestADM( diff --git a/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala b/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala index 7a115f9b9c..0ce734bc1c 100644 --- a/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala @@ -675,7 +675,7 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { val mockService = ProjectADMRestServiceMock .SetRestrictedViewSettings( - assertion = Assertion.equalTo((id, user, Some("pct:1"))), + assertion = Assertion.equalTo((id, user, "pct:1")), result = expectedResult ) .toLayer From 2c8f16e6e490161468f7acd2ebb832fbf8cbd283 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Mon, 11 Sep 2023 16:41:44 +0200 Subject: [PATCH 17/51] introduce RestrictedViewSize value object --- .../dsp/valueobjects/RestrictedViewSize.scala | 28 +++++++++++++++++ .../ProjectsMessagesADM.scala | 31 +++++++++++++++---- .../admin/ProjectsResponderADM.scala | 18 +++++------ .../webapi/routing/admin/ProjectsRouteZ.scala | 5 +-- .../api/service/ProjectsADMRestService.scala | 12 +++---- ...setProjectRestrictedViewSettings.scala.txt | 3 +- 6 files changed, 71 insertions(+), 26 deletions(-) create mode 100644 webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala diff --git a/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala b/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala new file mode 100644 index 0000000000..f00032a98b --- /dev/null +++ b/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala @@ -0,0 +1,28 @@ +/* + * Copyright © 2021 - 2023 Swiss National Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. + * SPDX-License-Identifier: Apache-2.0 + */ + +package dsp.valueobjects + +import dsp.errors.BadRequestException +import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectsADMJsonProtocol +import zio.prelude.Validation + +case class RestrictedViewSize(value: String) extends ProjectsADMJsonProtocol + +object RestrictedViewSize { + def make(value: String): Validation[Throwable, RestrictedViewSize] = + if (value.toString.isEmpty) Validation.fail(BadRequestException(ErrorMessages.RestrictedViewSizeMissing)) + else Validation.succeed(new RestrictedViewSize(s"!$value,$value") {}) +// value match { +// case v if v == 0 => Validation.fail(BadRequestException(ErrorMessages.RestrictedViewSizeInvalid)) +// case v if v > 1 && v < 100 => Validation.succeed(new RestrictedViewSize(s"pct:$v") {}) +// case v if v > 100 => Validation.succeed(new RestrictedViewSize(s"!$v,$v") {}) +// } +} + +object ErrorMessages { + val RestrictedViewSizeMissing = "RestrictedViewSize cannot be empty." + val RestrictedViewSizeInvalid = "RestrictedViewSize is invalid." +} diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala index 571088d3e8..57e2f507df 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala @@ -14,14 +14,12 @@ import spray.json.RootJsonFormat import zio.prelude.Validation import java.util.UUID - import dsp.errors.BadRequestException import dsp.errors.OntologyConstraintException import dsp.errors.ValidationException -import dsp.valueobjects.Iri +import dsp.valueobjects.{Iri, RestrictedViewSize, V2} import dsp.valueobjects.Iri.ProjectIri import dsp.valueobjects.Project._ -import dsp.valueobjects.V2 import org.knora.webapi.IRI import org.knora.webapi.core.RelayedMessage import org.knora.webapi.messages.ResponderRequest.KnoraRequestADM @@ -255,7 +253,7 @@ case class ProjectRestrictedViewSettingsGetRequestADM( case class ProjectRestrictedViewSettingsSetRequestADM( iri: Iri.ProjectIri, user: UserADM, - size: String + size: RestrictedViewSize ) extends ProjectsResponderRequestADM /** @@ -357,6 +355,23 @@ case class ProjectRestrictedViewSettingsResponseADM(settings: ProjectRestrictedV def toJsValue: JsValue = projectRestrictedViewGetResponseADMFormat.write(this) } +///** +// * Represents a response to a request for the project's restricted view settings. +// * +// * @param settings the restricted view size. +// */ +//case class ProjectRestrictedViewSizeResponseADM(settings: ProjectRestrictedViewSizeADM) +// extends KnoraResponseADM +// with ProjectsADMJsonProtocol { +// def toJsValue: JsValue = projectRestrictedViewSetResponseADMFormat.write(this) +//} + +case class ProjectRestrictedViewSizeResponseADM(size: RestrictedViewSize) + extends KnoraResponseADM + with ProjectsADMJsonProtocol { + def toJsValue: JsValue = projectRestrictedViewSizeResponseADMFormat.write(this) +} + /** * Represents an answer to a project creating/modifying operation. * @@ -551,6 +566,8 @@ trait ProjectsADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol import org.knora.webapi.messages.admin.responder.usersmessages.UsersADMJsonProtocol._ + implicit val restrictedViewSize: RootJsonFormat[RestrictedViewSize] = jsonFormat1(RestrictedViewSize.apply + ) implicit val projectADMFormat: JsonFormat[ProjectADM] = lazyFormat( jsonFormat( ProjectADM, @@ -574,7 +591,8 @@ trait ProjectsADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol ) implicit val projectRestrictedViewSettingsADMFormat: RootJsonFormat[ProjectRestrictedViewSettingsADM] = jsonFormat(ProjectRestrictedViewSettingsADM, "size", "watermark") - +// implicit val projectRestrictedViewSizeADMFormat: RootJsonFormat[ProjectRestrictedViewSizeADM] = +// jsonFormat(ProjectRestrictedViewSizeADM, "size") implicit val projectAdminMembersGetResponseADMFormat: RootJsonFormat[ProjectAdminMembersGetResponseADM] = rootFormat( lazyFormat(jsonFormat(ProjectAdminMembersGetResponseADM, "members")) ) @@ -617,7 +635,8 @@ trait ProjectsADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol jsonFormat(ProjectKeywordsGetResponseADM, "keywords") implicit val projectRestrictedViewGetResponseADMFormat: RootJsonFormat[ProjectRestrictedViewSettingsResponseADM] = jsonFormat(ProjectRestrictedViewSettingsResponseADM, "settings") - + implicit val projectRestrictedViewSizeResponseADMFormat: JsonFormat[ProjectRestrictedViewSizeResponseADM] = + lazyFormat(jsonFormat(ProjectRestrictedViewSizeResponseADM, "size")) implicit val projectOperationResponseADMFormat: RootJsonFormat[ProjectOperationResponseADM] = rootFormat( lazyFormat(jsonFormat(ProjectOperationResponseADM, "project")) ) diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala index 4d56b599dc..63fca80954 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala @@ -8,10 +8,8 @@ import com.typesafe.scalalogging.LazyLogging import zio._ import java.util.UUID - import dsp.errors._ -import dsp.valueobjects.Iri -import dsp.valueobjects.V2 +import dsp.valueobjects.{Iri, RestrictedViewSize, V2} import org.knora.webapi._ import org.knora.webapi.config.AppConfig import org.knora.webapi.core.MessageHandler @@ -136,8 +134,8 @@ trait ProjectsResponderADM { def setProjectRestrictedViewSettings( iri: Iri.ProjectIri, user: UserADM, - size: String - ): Task[ProjectRestrictedViewSettingsResponseADM] + size: RestrictedViewSize + ): Task[ProjectRestrictedViewSizeResponseADM] /** * Creates a project. @@ -475,8 +473,8 @@ final case class ProjectsResponderADMLive( override def setProjectRestrictedViewSettings( iri: Iri.ProjectIri, user: UserADM, - size: String - ): Task[ProjectRestrictedViewSettingsResponseADM] = { + size: RestrictedViewSize + ): Task[ProjectRestrictedViewSizeResponseADM] = { val id = ProjectIdentifierADM.IriIdentifier(iri) for { _ <- getProjectFromCacheOrTriplestore(id) @@ -489,9 +487,9 @@ final case class ProjectsResponderADMLive( query = twirl.queries.sparql.admin.txt .setProjectRestrictedViewSettings(iri.value, size, None) - _ <- triplestoreService.sparqlHttpUpdate(query.toString) - settings = ProjectRestrictedViewSettingsADM(Some(size)) - } yield ProjectRestrictedViewSettingsResponseADM(settings) + _ <- triplestoreService.sparqlHttpUpdate(query.toString) +// settings = ProjectRestrictedViewSettingsSetADM(size) + } yield ProjectRestrictedViewSizeResponseADM(size) } /** diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala index 0827016c39..9a773ff21b 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala @@ -12,9 +12,9 @@ import zio.json._ import zio.stream.ZStream import java.nio.file.Files - import dsp.errors.BadRequestException import dsp.valueobjects.Iri._ +import dsp.valueobjects.RestrictedViewSize import org.knora.webapi.config.AppConfig import org.knora.webapi.http.handler.ExceptionHandlerZ import org.knora.webapi.http.middleware.AuthenticationMiddleware @@ -251,7 +251,8 @@ final case class ProjectsRouteZ( body <- body.asString payload <- ZIO.fromEither(body.fromJson[ProjectSetRestrictedViewSettingsPayload]).mapError(e => BadRequestException(e)) - response <- projectsService.setProjectRestrictedViewSettings(id.value, user, payload.size) + size <- RestrictedViewSize.make(payload.size).toZIO + response <- projectsService.setProjectRestrictedViewSettings(id.value, user, size) } yield Response.json(response.toJsValue.toString) } diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala index d2bfacfeb1..5f24fe8a5e 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala @@ -7,12 +7,10 @@ package org.knora.webapi.slice.admin.api.service import zio._ import zio.macros.accessible - import dsp.errors.BadRequestException import dsp.errors.NotFoundException -import dsp.valueobjects.Iri +import dsp.valueobjects.{Iri, Project, RestrictedViewSize} import dsp.valueobjects.Iri.ProjectIri -import dsp.valueobjects.Project import dsp.valueobjects.Project.Shortcode import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM._ import org.knora.webapi.messages.admin.responder.projectsmessages._ @@ -66,8 +64,8 @@ trait ProjectADMRestService { def setProjectRestrictedViewSettings( iri: Iri.ProjectIri, user: UserADM, - size: String - ): Task[ProjectRestrictedViewSettingsResponseADM] + size: RestrictedViewSize + ): Task[ProjectRestrictedViewSizeResponseADM] } final case class ProjectsADMRestServiceLive( @@ -256,8 +254,8 @@ final case class ProjectsADMRestServiceLive( override def setProjectRestrictedViewSettings( iri: Iri.ProjectIri, user: UserADM, - size: String - ): Task[ProjectRestrictedViewSettingsResponseADM] = + size: RestrictedViewSize + ): Task[ProjectRestrictedViewSizeResponseADM] = responder.setProjectRestrictedViewSettings(iri, user, size) override def exportProject(shortcodeStr: String, requestingUser: UserADM): Task[Unit] = for { diff --git a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/setProjectRestrictedViewSettings.scala.txt b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/setProjectRestrictedViewSettings.scala.txt index 2e136e6cb1..97486f5229 100644 --- a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/setProjectRestrictedViewSettings.scala.txt +++ b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/setProjectRestrictedViewSettings.scala.txt @@ -4,6 +4,7 @@ *@ @import org.knora.webapi.IRI +@import dsp.valueobjects.RestrictedViewSize @* * Sets project restricted view settings. @@ -14,7 +15,7 @@ * *@ @(iri: IRI, - size: String, + size: RestrictedViewSize, watermark: Option[String]) PREFIX rdf: From c2be8a4c3c32952c995f81c4c99efcf4105f03d7 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Tue, 12 Sep 2023 11:55:46 +0200 Subject: [PATCH 18/51] fix value object --- .../dsp/valueobjects/RestrictedViewSize.scala | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala b/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala index f00032a98b..4273191a68 100644 --- a/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala +++ b/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala @@ -9,17 +9,28 @@ import dsp.errors.BadRequestException import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectsADMJsonProtocol import zio.prelude.Validation +import scala.util.matching.Regex + case class RestrictedViewSize(value: String) extends ProjectsADMJsonProtocol object RestrictedViewSize { - def make(value: String): Validation[Throwable, RestrictedViewSize] = - if (value.toString.isEmpty) Validation.fail(BadRequestException(ErrorMessages.RestrictedViewSizeMissing)) - else Validation.succeed(new RestrictedViewSize(s"!$value,$value") {}) -// value match { -// case v if v == 0 => Validation.fail(BadRequestException(ErrorMessages.RestrictedViewSizeInvalid)) -// case v if v > 1 && v < 100 => Validation.succeed(new RestrictedViewSize(s"pct:$v") {}) -// case v if v > 100 => Validation.succeed(new RestrictedViewSize(s"!$v,$v") {}) -// } + def make(value: String): Validation[Throwable, RestrictedViewSize] = { + // matches strings "pct:1-100" + val pctPattern: Regex = "pct:[1-9][0-9]?0?$".r + // matches strings "!x,x" where x is a number of pixels + val pixelPattern: Regex = "!\\d+,\\d+$".r + def isSquare(value: String): Boolean = { + val substr = value.substring(1).split(",").toSeq + substr.head == substr.last + } + + if (value.isEmpty) Validation.fail(BadRequestException(ErrorMessages.RestrictedViewSizeMissing)) + else if (!pctPattern.matches(value) || !pixelPattern.matches(value)) + Validation.fail(BadRequestException(ErrorMessages.RestrictedViewSizeInvalid)) + else if (pixelPattern.matches(value) && !isSquare(value)) + Validation.fail(BadRequestException(ErrorMessages.RestrictedViewSizeInvalid)) + else Validation.succeed(new RestrictedViewSize(value) {}) + } } object ErrorMessages { From f1fee5138d1d2f20a468cf5ed5f91d693232788e Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Tue, 12 Sep 2023 13:13:55 +0200 Subject: [PATCH 19/51] clean mocks and remove test --- .../dsp/valueobjects/RestrictedViewSize.scala | 5 ++-- .../ProjectsMessagesADM.scala | 8 +++-- .../admin/ProjectsResponderADM.scala | 5 +++- .../webapi/routing/admin/ProjectsRouteZ.scala | 1 + .../api/service/ProjectsADMRestService.scala | 5 +++- .../admin/ProjectADMRestServiceMock.scala | 20 +++++-------- .../admin/ProjectsResponderADMMock.scala | 28 +++++------------- .../routing/admin/ProjectsRouteZSpec.scala | 29 +------------------ 8 files changed, 32 insertions(+), 69 deletions(-) diff --git a/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala b/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala index 4273191a68..b12b5c3546 100644 --- a/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala +++ b/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala @@ -5,12 +5,13 @@ package dsp.valueobjects -import dsp.errors.BadRequestException -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectsADMJsonProtocol import zio.prelude.Validation import scala.util.matching.Regex +import dsp.errors.BadRequestException +import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectsADMJsonProtocol + case class RestrictedViewSize(value: String) extends ProjectsADMJsonProtocol object RestrictedViewSize { diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala index 57e2f507df..86e6918c00 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala @@ -14,12 +14,15 @@ import spray.json.RootJsonFormat import zio.prelude.Validation import java.util.UUID + import dsp.errors.BadRequestException import dsp.errors.OntologyConstraintException import dsp.errors.ValidationException -import dsp.valueobjects.{Iri, RestrictedViewSize, V2} +import dsp.valueobjects.Iri import dsp.valueobjects.Iri.ProjectIri import dsp.valueobjects.Project._ +import dsp.valueobjects.RestrictedViewSize +import dsp.valueobjects.V2 import org.knora.webapi.IRI import org.knora.webapi.core.RelayedMessage import org.knora.webapi.messages.ResponderRequest.KnoraRequestADM @@ -566,8 +569,7 @@ trait ProjectsADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol import org.knora.webapi.messages.admin.responder.usersmessages.UsersADMJsonProtocol._ - implicit val restrictedViewSize: RootJsonFormat[RestrictedViewSize] = jsonFormat1(RestrictedViewSize.apply - ) + implicit val restrictedViewSize: RootJsonFormat[RestrictedViewSize] = jsonFormat1(RestrictedViewSize.apply) implicit val projectADMFormat: JsonFormat[ProjectADM] = lazyFormat( jsonFormat( ProjectADM, diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala index 63fca80954..542127f8fc 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala @@ -8,8 +8,11 @@ import com.typesafe.scalalogging.LazyLogging import zio._ import java.util.UUID + import dsp.errors._ -import dsp.valueobjects.{Iri, RestrictedViewSize, V2} +import dsp.valueobjects.Iri +import dsp.valueobjects.RestrictedViewSize +import dsp.valueobjects.V2 import org.knora.webapi._ import org.knora.webapi.config.AppConfig import org.knora.webapi.core.MessageHandler diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala index 9a773ff21b..faf349c1ab 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala @@ -12,6 +12,7 @@ import zio.json._ import zio.stream.ZStream import java.nio.file.Files + import dsp.errors.BadRequestException import dsp.valueobjects.Iri._ import dsp.valueobjects.RestrictedViewSize diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala index 5f24fe8a5e..77961f6426 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala @@ -7,11 +7,14 @@ package org.knora.webapi.slice.admin.api.service import zio._ import zio.macros.accessible + import dsp.errors.BadRequestException import dsp.errors.NotFoundException -import dsp.valueobjects.{Iri, Project, RestrictedViewSize} +import dsp.valueobjects.Iri import dsp.valueobjects.Iri.ProjectIri +import dsp.valueobjects.Project import dsp.valueobjects.Project.Shortcode +import dsp.valueobjects.RestrictedViewSize import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM._ import org.knora.webapi.messages.admin.responder.projectsmessages._ import org.knora.webapi.messages.admin.responder.usersmessages.UserADM diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala index d821716a58..4b8ac630bd 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala @@ -10,6 +10,7 @@ import zio._ import zio.mock._ import dsp.valueobjects.Iri._ +import dsp.valueobjects.RestrictedViewSize import org.knora.webapi.messages.admin.responder.projectsmessages._ import org.knora.webapi.messages.admin.responder.usersmessages.UserADM import org.knora.webapi.slice.admin.api.model.ProjectDataGetResponseADM @@ -32,12 +33,6 @@ object ProjectADMRestServiceMock extends Mock[ProjectADMRestService] { object GetKeywordsByProjectIri extends Effect[ProjectIri, Throwable, ProjectKeywordsGetResponseADM] object GetRestrictedViewSettings extends Effect[ProjectIdentifierADM, Throwable, ProjectRestrictedViewSettingsResponseADM] - object SetRestrictedViewSettings - extends Effect[ - (ProjectIri, UserADM, String), - Throwable, - ProjectRestrictedViewSettingsResponseADM - ] override val compose: URLayer[Proxy, ProjectADMRestService] = ZLayer { @@ -98,18 +93,17 @@ object ProjectADMRestServiceMock extends Mock[ProjectADMRestService] { ): Task[ProjectRestrictedViewSettingsResponseADM] = proxy(GetRestrictedViewSettings, identifier) - def setProjectRestrictedViewSettings( - iri: ProjectIri, - user: UserADM, - size: String - ): Task[ProjectRestrictedViewSettingsResponseADM] = - proxy(SetRestrictedViewSettings, (iri, user, size)) - override def exportProject(projectIri: IRI, requestingUser: UserADM): Task[Unit] = ??? override def importProject(projectIri: IRI, requestingUser: UserADM): Task[ProjectImportResponse] = ??? override def listExports(requestingUser: UserADM): Task[Chunk[ProjectExportInfoResponse]] = ??? + + override def setProjectRestrictedViewSettings( + iri: ProjectIri, + user: UserADM, + size: RestrictedViewSize + ): Task[ProjectRestrictedViewSizeResponseADM] = ??? } } } diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala index 1ff179e95e..4447290db0 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala @@ -16,19 +16,8 @@ import zio.mock.Proxy import java.util.UUID import dsp.valueobjects.Iri -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectADM -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectAdminMembersGetResponseADM -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectCreatePayloadADM -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectGetResponseADM -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectKeywordsGetResponseADM -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectMembersGetResponseADM -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectOperationResponseADM -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectRestrictedViewSettingsADM -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectRestrictedViewSettingsResponseADM -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectUpdatePayloadADM -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectsGetResponseADM -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectsKeywordsGetResponseADM +import dsp.valueobjects.RestrictedViewSize +import org.knora.webapi.messages.admin.responder.projectsmessages._ import org.knora.webapi.messages.admin.responder.usersmessages.UserADM object ProjectsResponderADMMock extends Mock[ProjectsResponderADM] { @@ -46,8 +35,6 @@ object ProjectsResponderADMMock extends Mock[ProjectsResponderADM] { extends Effect[ProjectIdentifierADM, Throwable, Option[ProjectRestrictedViewSettingsADM]] object ProjectRestrictedViewSettingsGetRequestADM extends Effect[ProjectIdentifierADM, Throwable, ProjectRestrictedViewSettingsResponseADM] - object ProjectRestrictedViewSettingSetRequestADM - extends Effect[(Iri.ProjectIri, UserADM, String), Throwable, ProjectRestrictedViewSettingsResponseADM] object ProjectCreateRequestADM extends Effect[(ProjectCreatePayloadADM, UserADM, UUID), Throwable, ProjectOperationResponseADM] object ChangeBasicInformationRequestADM @@ -86,12 +73,6 @@ object ProjectsResponderADMMock extends Mock[ProjectsResponderADM] { id: ProjectIdentifierADM ): Task[ProjectRestrictedViewSettingsResponseADM] = proxy(ProjectRestrictedViewSettingsGetRequestADM, id) - override def setProjectRestrictedViewSettings( - id: Iri.ProjectIri, - user: UserADM, - size: String - ): Task[ProjectRestrictedViewSettingsResponseADM] = - proxy(ProjectRestrictedViewSettingSetRequestADM, (id, user, size)) override def projectCreateRequestADM( createPayload: ProjectCreatePayloadADM, requestingUser: UserADM, @@ -105,6 +86,11 @@ object ProjectsResponderADMMock extends Mock[ProjectsResponderADM] { apiRequestID: UUID ): Task[ProjectOperationResponseADM] = proxy(ChangeBasicInformationRequestADM, (projectIri, updatePayload, user, apiRequestID)) + override def setProjectRestrictedViewSettings( + iri: Iri.ProjectIri, + user: UserADM, + size: RestrictedViewSize + ): Task[ProjectRestrictedViewSizeResponseADM] = ??? } } } diff --git a/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala b/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala index 0ce734bc1c..0cee41b7d2 100644 --- a/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala @@ -83,8 +83,7 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { getProjectAdminsSpec, getKeywordsSpec, getKeywordsByProjectSpec, - getProjectRestrictedViewSettings, - setProjectRestrictedViewSettingsSpec + getProjectRestrictedViewSettings ) val getProjectsSpec: Spec[Any, Serializable] = test("get all projects") { @@ -660,32 +659,6 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { } ) - val setProjectRestrictedViewSettingsSpec: Spec[Any, Serializable] = suite("set project restricted view settings")( - test("successfully set project restricted view") { - val iri = "http://rdfh.ch/projects/0001" - val user = KnoraSystemInstances.Users.SystemUser - val id = TestDataFactory.projectIri(iri) - val payload = """{"size":"pct:1"}""" - val body = Body.fromString(payload) - val request = Request.post(body, URL(basePathProjectsIri / encode(iri) / "RestrictedViewSettings")) - val settings = ProjectRestrictedViewSettingsADM(Some("pct:1"), Some("null")) - - val expectedResult = - Expectation.value[ProjectRestrictedViewSettingsResponseADM](ProjectRestrictedViewSettingsResponseADM(settings)) - - val mockService = ProjectADMRestServiceMock - .SetRestrictedViewSettings( - assertion = Assertion.equalTo((id, user, "pct:1")), - result = expectedResult - ) - .toLayer - for { - response <- applyRoutes(request).provide(mockService) - body <- response.body.asString - } yield assertTrue(body.contains("pct:1")) - } - ) - val getProjectRestrictedViewSettings: Spec[Any, Serializable] = suite("get the restricted view settings of a project by project identifier")( test("successfully get the settings by project IRI") { From ca5bbc7dec69820ceeba8f944797ceb58283c799 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Wed, 13 Sep 2023 09:24:50 +0200 Subject: [PATCH 20/51] fix'jsonFormat overload --- webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala | 2 +- .../admin/responder/projectsmessages/ProjectsMessagesADM.scala | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala b/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala index b12b5c3546..e000d6a52a 100644 --- a/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala +++ b/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala @@ -12,7 +12,7 @@ import scala.util.matching.Regex import dsp.errors.BadRequestException import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectsADMJsonProtocol -case class RestrictedViewSize(value: String) extends ProjectsADMJsonProtocol +case class RestrictedViewSize(value: String) object RestrictedViewSize { def make(value: String): Validation[Throwable, RestrictedViewSize] = { diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala index 86e6918c00..9a46a65871 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala @@ -642,5 +642,4 @@ trait ProjectsADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol implicit val projectOperationResponseADMFormat: RootJsonFormat[ProjectOperationResponseADM] = rootFormat( lazyFormat(jsonFormat(ProjectOperationResponseADM, "project")) ) - } From 8c3664b3d9ca8c97a63e52afe0a5ab94f6907fc2 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Thu, 14 Sep 2023 13:09:38 +0200 Subject: [PATCH 21/51] add improvements and tests --- .../dsp/valueobjects/RestrictedViewSize.scala | 18 ++++----- .../valueobjects/RestrictedViewSizeSpec.scala | 40 +++++++++++++++++++ 2 files changed, 49 insertions(+), 9 deletions(-) create mode 100644 webapi/src/test/scala/dsp/valueobjects/RestrictedViewSizeSpec.scala diff --git a/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala b/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala index e000d6a52a..cfad30a392 100644 --- a/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala +++ b/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala @@ -10,27 +10,27 @@ import zio.prelude.Validation import scala.util.matching.Regex import dsp.errors.BadRequestException -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectsADMJsonProtocol case class RestrictedViewSize(value: String) object RestrictedViewSize { def make(value: String): Validation[Throwable, RestrictedViewSize] = { + val trimmed = value.trim // matches strings "pct:1-100" - val pctPattern: Regex = "pct:[1-9][0-9]?0?$".r + val percentagePattern: Regex = "pct:[1-9][0-9]?0?$".r // matches strings "!x,x" where x is a number of pixels - val pixelPattern: Regex = "!\\d+,\\d+$".r + val dimensionsPattern: Regex = "!\\d+,\\d+$".r def isSquare(value: String): Boolean = { - val substr = value.substring(1).split(",").toSeq + val substr = trimmed.substring(1).split(",").toSeq substr.head == substr.last } + println(111, value, percentagePattern.matches(value), dimensionsPattern.matches(value), isSquare(value)) if (value.isEmpty) Validation.fail(BadRequestException(ErrorMessages.RestrictedViewSizeMissing)) - else if (!pctPattern.matches(value) || !pixelPattern.matches(value)) - Validation.fail(BadRequestException(ErrorMessages.RestrictedViewSizeInvalid)) - else if (pixelPattern.matches(value) && !isSquare(value)) - Validation.fail(BadRequestException(ErrorMessages.RestrictedViewSizeInvalid)) - else Validation.succeed(new RestrictedViewSize(value) {}) + else if (percentagePattern.matches(trimmed)) Validation.succeed(new RestrictedViewSize(trimmed) {}) + else if (dimensionsPattern.matches(trimmed) && isSquare(value)) + Validation.succeed(new RestrictedViewSize(trimmed) {}) + else Validation.fail(BadRequestException(ErrorMessages.RestrictedViewSizeInvalid)) } } diff --git a/webapi/src/test/scala/dsp/valueobjects/RestrictedViewSizeSpec.scala b/webapi/src/test/scala/dsp/valueobjects/RestrictedViewSizeSpec.scala new file mode 100644 index 0000000000..916b0e0b56 --- /dev/null +++ b/webapi/src/test/scala/dsp/valueobjects/RestrictedViewSizeSpec.scala @@ -0,0 +1,40 @@ +/* + * Copyright © 2021 - 2023 Swiss National Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. + * SPDX-License-Identifier: Apache-2.0 + */ + +package dsp.valueobjects + +import zio.prelude.Validation +import zio.test._ + +import dsp.errors.BadRequestException + +/** + * This spec is used to test the [[dsp.valueobjects.RestrictedViewSize]] value object creation. + */ +object RestrictedViewSizeSpec extends ZIOSpecDefault { + + def spec = suite("Size")( + test("pass correct percentage value") { + assertTrue(RestrictedViewSize.make("pct:1").toOption.get.value == "pct:1") + }, + test("pass correct dimension value") { + assertTrue(RestrictedViewSize.make("!512,512").toOption.get.value == "!512,512") + }, + test("fail on passing incorrect values") { + assertTrue( + RestrictedViewSize.make("!512,100") == Validation.fail( + BadRequestException(ErrorMessages.RestrictedViewSizeInvalid) + ), + RestrictedViewSize.make("pct:0") == Validation.fail( + BadRequestException(ErrorMessages.RestrictedViewSizeInvalid) + ), + RestrictedViewSize.make("pct:101") == Validation.fail( + BadRequestException(ErrorMessages.RestrictedViewSizeInvalid) + ) +// RestrictedViewSize.make("") == Validation.fail(BadRequestException(ErrorMessages.RestrictedViewSizeMissing)) + ) + } + ) +} From 2c52c2c24a9ae10939788a0c43e3285382a0113e Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Thu, 14 Sep 2023 16:46:23 +0200 Subject: [PATCH 22/51] add custom JsonFormat + value object fixes --- .../dsp/valueobjects/RestrictedViewSize.scala | 14 ++++++------ .../ProjectsMessagesADM.scala | 22 +++++++++++++++++-- .../admin/ProjectsResponderADM.scala | 4 +++- ...setProjectRestrictedViewSettings.scala.txt | 2 +- 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala b/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala index cfad30a392..e1f93cf283 100644 --- a/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala +++ b/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala @@ -8,28 +8,28 @@ package dsp.valueobjects import zio.prelude.Validation import scala.util.matching.Regex - import dsp.errors.BadRequestException -case class RestrictedViewSize(value: String) +/** + * RestrictedViewSize value object. + */ +sealed abstract case class RestrictedViewSize private (value: String) object RestrictedViewSize { def make(value: String): Validation[Throwable, RestrictedViewSize] = { - val trimmed = value.trim + val trimmed: String = value.trim // matches strings "pct:1-100" val percentagePattern: Regex = "pct:[1-9][0-9]?0?$".r // matches strings "!x,x" where x is a number of pixels val dimensionsPattern: Regex = "!\\d+,\\d+$".r - def isSquare(value: String): Boolean = { + def isSquare: Boolean = { val substr = trimmed.substring(1).split(",").toSeq substr.head == substr.last } - println(111, value, percentagePattern.matches(value), dimensionsPattern.matches(value), isSquare(value)) if (value.isEmpty) Validation.fail(BadRequestException(ErrorMessages.RestrictedViewSizeMissing)) else if (percentagePattern.matches(trimmed)) Validation.succeed(new RestrictedViewSize(trimmed) {}) - else if (dimensionsPattern.matches(trimmed) && isSquare(value)) - Validation.succeed(new RestrictedViewSize(trimmed) {}) + else if (dimensionsPattern.matches(trimmed) && isSquare) Validation.succeed(new RestrictedViewSize(trimmed) {}) else Validation.fail(BadRequestException(ErrorMessages.RestrictedViewSizeInvalid)) } } diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala index 9a46a65871..908e297f54 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala @@ -8,12 +8,17 @@ package org.knora.webapi.messages.admin.responder.projectsmessages import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport import org.apache.commons.lang3.builder.HashCodeBuilder import spray.json.DefaultJsonProtocol +import spray.json.JsString import spray.json.JsValue import spray.json.JsonFormat import spray.json.RootJsonFormat +import spray.json.deserializationError import zio.prelude.Validation import java.util.UUID +import scala.util.Failure +import scala.util.Success +import scala.util.Try import dsp.errors.BadRequestException import dsp.errors.OntologyConstraintException @@ -569,7 +574,20 @@ trait ProjectsADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol import org.knora.webapi.messages.admin.responder.usersmessages.UsersADMJsonProtocol._ - implicit val restrictedViewSize: RootJsonFormat[RestrictedViewSize] = jsonFormat1(RestrictedViewSize.apply) + implicit val restrictedViewSizeFormat: JsonFormat[RestrictedViewSize] = + new JsonFormat[RestrictedViewSize] { + override def read(json: JsValue): RestrictedViewSize = json match { + case JsString(str) => + Try(RestrictedViewSize.make(str)) match { + case Success(result) => result.asInstanceOf[RestrictedViewSize] + case Failure(exception) => deserializationError(s"Could not parse $str", exception) + } + case other => deserializationError(s"Expected a String but got a $other") + } + + override def write(obj: RestrictedViewSize): JsValue = JsString(obj.value) + } + implicit val projectADMFormat: JsonFormat[ProjectADM] = lazyFormat( jsonFormat( ProjectADM, @@ -638,7 +656,7 @@ trait ProjectsADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol implicit val projectRestrictedViewGetResponseADMFormat: RootJsonFormat[ProjectRestrictedViewSettingsResponseADM] = jsonFormat(ProjectRestrictedViewSettingsResponseADM, "settings") implicit val projectRestrictedViewSizeResponseADMFormat: JsonFormat[ProjectRestrictedViewSizeResponseADM] = - lazyFormat(jsonFormat(ProjectRestrictedViewSizeResponseADM, "size")) + jsonFormat(ProjectRestrictedViewSizeResponseADM, "size") implicit val projectOperationResponseADMFormat: RootJsonFormat[ProjectOperationResponseADM] = rootFormat( lazyFormat(jsonFormat(ProjectOperationResponseADM, "project")) ) diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala index 542127f8fc..a386f9bc3b 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala @@ -487,8 +487,10 @@ final case class ProjectsResponderADMLive( .fail(ForbiddenException("User is neither system nor project admin.")) .unless(user.permissions.isSystemAdmin || user.permissions.isProjectAdmin(iri.value)) + _ = println(888, size) + query = twirl.queries.sparql.admin.txt - .setProjectRestrictedViewSettings(iri.value, size, None) + .setProjectRestrictedViewSettings(iri.value, size.value, None) _ <- triplestoreService.sparqlHttpUpdate(query.toString) // settings = ProjectRestrictedViewSettingsSetADM(size) diff --git a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/setProjectRestrictedViewSettings.scala.txt b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/setProjectRestrictedViewSettings.scala.txt index 97486f5229..4b122da5d9 100644 --- a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/setProjectRestrictedViewSettings.scala.txt +++ b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/setProjectRestrictedViewSettings.scala.txt @@ -15,7 +15,7 @@ * *@ @(iri: IRI, - size: RestrictedViewSize, + size: String, watermark: Option[String]) PREFIX rdf: From 80bc159cae79c2eab244b1059b31635ce8c9960a Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Mon, 18 Sep 2023 08:59:14 +0200 Subject: [PATCH 23/51] cleanup --- .../projectsmessages/ProjectsMessagesADM.scala | 14 +------------- .../responders/admin/ProjectsResponderADM.scala | 1 - .../dsp/valueobjects/RestrictedViewSizeSpec.scala | 4 ++-- 3 files changed, 3 insertions(+), 16 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala index 908e297f54..85c25a40fa 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala @@ -363,17 +363,6 @@ case class ProjectRestrictedViewSettingsResponseADM(settings: ProjectRestrictedV def toJsValue: JsValue = projectRestrictedViewGetResponseADMFormat.write(this) } -///** -// * Represents a response to a request for the project's restricted view settings. -// * -// * @param settings the restricted view size. -// */ -//case class ProjectRestrictedViewSizeResponseADM(settings: ProjectRestrictedViewSizeADM) -// extends KnoraResponseADM -// with ProjectsADMJsonProtocol { -// def toJsValue: JsValue = projectRestrictedViewSetResponseADMFormat.write(this) -//} - case class ProjectRestrictedViewSizeResponseADM(size: RestrictedViewSize) extends KnoraResponseADM with ProjectsADMJsonProtocol { @@ -611,8 +600,7 @@ trait ProjectsADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol ) implicit val projectRestrictedViewSettingsADMFormat: RootJsonFormat[ProjectRestrictedViewSettingsADM] = jsonFormat(ProjectRestrictedViewSettingsADM, "size", "watermark") -// implicit val projectRestrictedViewSizeADMFormat: RootJsonFormat[ProjectRestrictedViewSizeADM] = -// jsonFormat(ProjectRestrictedViewSizeADM, "size") + implicit val projectAdminMembersGetResponseADMFormat: RootJsonFormat[ProjectAdminMembersGetResponseADM] = rootFormat( lazyFormat(jsonFormat(ProjectAdminMembersGetResponseADM, "members")) ) diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala index a386f9bc3b..5153b5ba6d 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala @@ -493,7 +493,6 @@ final case class ProjectsResponderADMLive( .setProjectRestrictedViewSettings(iri.value, size.value, None) _ <- triplestoreService.sparqlHttpUpdate(query.toString) -// settings = ProjectRestrictedViewSettingsSetADM(size) } yield ProjectRestrictedViewSizeResponseADM(size) } diff --git a/webapi/src/test/scala/dsp/valueobjects/RestrictedViewSizeSpec.scala b/webapi/src/test/scala/dsp/valueobjects/RestrictedViewSizeSpec.scala index 916b0e0b56..468ef609d2 100644 --- a/webapi/src/test/scala/dsp/valueobjects/RestrictedViewSizeSpec.scala +++ b/webapi/src/test/scala/dsp/valueobjects/RestrictedViewSizeSpec.scala @@ -32,8 +32,8 @@ object RestrictedViewSizeSpec extends ZIOSpecDefault { ), RestrictedViewSize.make("pct:101") == Validation.fail( BadRequestException(ErrorMessages.RestrictedViewSizeInvalid) - ) -// RestrictedViewSize.make("") == Validation.fail(BadRequestException(ErrorMessages.RestrictedViewSizeMissing)) + ), + RestrictedViewSize.make("") == Validation.fail(BadRequestException(ErrorMessages.RestrictedViewSizeMissing)) ) } ) From 20dec4dc757b415038d9f3cf687039d251bc11c7 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Mon, 18 Sep 2023 12:14:46 +0200 Subject: [PATCH 24/51] update docs --- docs/03-endpoints/api-admin/projects.md | 15 ++++++++++----- .../dsp/valueobjects/RestrictedViewSize.scala | 1 + .../responders/admin/ProjectsResponderADM.scala | 2 -- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/docs/03-endpoints/api-admin/projects.md b/docs/03-endpoints/api-admin/projects.md index 30c0aa62b9..17e9fa8914 100644 --- a/docs/03-endpoints/api-admin/projects.md +++ b/docs/03-endpoints/api-admin/projects.md @@ -815,6 +815,14 @@ Example response: ### Set Restricted View Settings +The route takes String parameter which sets restricted view size in on of two formats: as an image dimensions or a +percentage. The dimensions pattern looks like: `!X,X`, where X is the number representing scaled image dimensions in +a square, so that the width and height of the returned image are not greater than the requested value. +Example: `!512,512` means the image's bigger side will be set to 512 pixels, setting the other side respectively to +image aspect ratio. +The percentage pattern looks like: `pct:X`, where X is the number between 1-100 representing the percentage the image +will be scaled to. Example: `pct:1` means the image will be scaled to 1% of the original image size. + Permissions: ProjectAdmin/SystemAdmin Request definition: @@ -830,17 +838,14 @@ Example request: ```bash curl --request GET 'http://0.0.0.0:3333/admin/projects/iri/http%3A%2F%2Frdfh.ch%2Fprojects%2F0001/RestrictedViewSettings' \ --header 'Authorization: Basic cm9vdEBleGFtcGxlLmNvbTp0ZXN0' \ ---data '{"size": "222"} +--data '{"size": "!512,512"} ``` Example response: ```jsonc { - "settings": { - "size": "!512,512", - "watermark": "path_to_image" - } + "size": "!512,512" } ``` diff --git a/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala b/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala index e1f93cf283..2c141e06ef 100644 --- a/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala +++ b/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala @@ -8,6 +8,7 @@ package dsp.valueobjects import zio.prelude.Validation import scala.util.matching.Regex + import dsp.errors.BadRequestException /** diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala index 5153b5ba6d..e7b9a4e113 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala @@ -487,8 +487,6 @@ final case class ProjectsResponderADMLive( .fail(ForbiddenException("User is neither system nor project admin.")) .unless(user.permissions.isSystemAdmin || user.permissions.isProjectAdmin(iri.value)) - _ = println(888, size) - query = twirl.queries.sparql.admin.txt .setProjectRestrictedViewSettings(iri.value, size.value, None) From a4eba54a82348846d1b05aa475dc1c03abe3c862 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Mon, 18 Sep 2023 14:30:02 +0200 Subject: [PATCH 25/51] update query handling --- .../knora/webapi/responders/admin/ProjectsResponderADM.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala index eca52ffdf6..80d951cebd 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala @@ -492,7 +492,7 @@ final case class ProjectsResponderADMLive( query = twirl.queries.sparql.admin.txt .setProjectRestrictedViewSettings(iri.value, size.value, None) - _ <- triplestoreService.sparqlHttpUpdate(query.toString) + _ = Update(query.toString) } yield ProjectRestrictedViewSizeResponseADM(size) } From 95cdeac29d1653daf69e9923f1146f2c3722f93b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinb=C3=B6lting?= Date: Mon, 18 Sep 2023 15:30:44 +0200 Subject: [PATCH 26/51] Remove spray json and replace with zio-json --- .../dsp/valueobjects/RestrictedViewSize.scala | 7 +++++- .../ProjectsMessagesADM.scala | 24 ++++--------------- .../webapi/routing/admin/ProjectsRouteZ.scala | 2 +- 3 files changed, 11 insertions(+), 22 deletions(-) diff --git a/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala b/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala index 2c141e06ef..9befc8e2e2 100644 --- a/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala +++ b/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala @@ -8,8 +8,8 @@ package dsp.valueobjects import zio.prelude.Validation import scala.util.matching.Regex - import dsp.errors.BadRequestException +import zio.json.JsonCodec /** * RestrictedViewSize value object. @@ -33,6 +33,11 @@ object RestrictedViewSize { else if (dimensionsPattern.matches(trimmed) && isSquare) Validation.succeed(new RestrictedViewSize(trimmed) {}) else Validation.fail(BadRequestException(ErrorMessages.RestrictedViewSizeInvalid)) } + + implicit val codec: JsonCodec[RestrictedViewSize] = JsonCodec[String].transformOrFail( + str => RestrictedViewSize.make(str).toEither.left.map(err => err.map(_.getMessage).mkString(", ")), + value => value.value + ) } object ErrorMessages { diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala index 85c25a40fa..b3985ab6b3 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala @@ -19,7 +19,6 @@ import java.util.UUID import scala.util.Failure import scala.util.Success import scala.util.Try - import dsp.errors.BadRequestException import dsp.errors.OntologyConstraintException import dsp.errors.ValidationException @@ -36,6 +35,7 @@ import org.knora.webapi.messages.admin.responder.KnoraResponseADM import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM._ import org.knora.webapi.messages.admin.responder.usersmessages.UserADM import org.knora.webapi.messages.store.triplestoremessages.TriplestoreJsonProtocol +import zio.json.{DeriveJsonCodec, JsonCodec} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // API requests @@ -364,9 +364,9 @@ case class ProjectRestrictedViewSettingsResponseADM(settings: ProjectRestrictedV } case class ProjectRestrictedViewSizeResponseADM(size: RestrictedViewSize) - extends KnoraResponseADM - with ProjectsADMJsonProtocol { - def toJsValue: JsValue = projectRestrictedViewSizeResponseADMFormat.write(this) +object ProjectRestrictedViewSizeResponseADM { + implicit val codec: JsonCodec[ProjectRestrictedViewSizeResponseADM] = + DeriveJsonCodec.gen[ProjectRestrictedViewSizeResponseADM] } /** @@ -563,20 +563,6 @@ trait ProjectsADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol import org.knora.webapi.messages.admin.responder.usersmessages.UsersADMJsonProtocol._ - implicit val restrictedViewSizeFormat: JsonFormat[RestrictedViewSize] = - new JsonFormat[RestrictedViewSize] { - override def read(json: JsValue): RestrictedViewSize = json match { - case JsString(str) => - Try(RestrictedViewSize.make(str)) match { - case Success(result) => result.asInstanceOf[RestrictedViewSize] - case Failure(exception) => deserializationError(s"Could not parse $str", exception) - } - case other => deserializationError(s"Expected a String but got a $other") - } - - override def write(obj: RestrictedViewSize): JsValue = JsString(obj.value) - } - implicit val projectADMFormat: JsonFormat[ProjectADM] = lazyFormat( jsonFormat( ProjectADM, @@ -643,8 +629,6 @@ trait ProjectsADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol jsonFormat(ProjectKeywordsGetResponseADM, "keywords") implicit val projectRestrictedViewGetResponseADMFormat: RootJsonFormat[ProjectRestrictedViewSettingsResponseADM] = jsonFormat(ProjectRestrictedViewSettingsResponseADM, "settings") - implicit val projectRestrictedViewSizeResponseADMFormat: JsonFormat[ProjectRestrictedViewSizeResponseADM] = - jsonFormat(ProjectRestrictedViewSizeResponseADM, "size") implicit val projectOperationResponseADMFormat: RootJsonFormat[ProjectOperationResponseADM] = rootFormat( lazyFormat(jsonFormat(ProjectOperationResponseADM, "project")) ) diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala index faf349c1ab..10fd0b3bfc 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala @@ -254,7 +254,7 @@ final case class ProjectsRouteZ( ZIO.fromEither(body.fromJson[ProjectSetRestrictedViewSettingsPayload]).mapError(e => BadRequestException(e)) size <- RestrictedViewSize.make(payload.size).toZIO response <- projectsService.setProjectRestrictedViewSettings(id.value, user, size) - } yield Response.json(response.toJsValue.toString) + } yield Response.json(response.toJson) } object ProjectsRouteZ { From ad85c7c79546e73f0375bdbb0124b3009ae0adff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinb=C3=B6lting?= Date: Mon, 18 Sep 2023 16:01:31 +0200 Subject: [PATCH 27/51] Replace Validation with Either and add tests --- .../dsp/valueobjects/RestrictedViewSize.scala | 20 +++++----- .../webapi/routing/admin/ProjectsRouteZ.scala | 7 ++-- .../valueobjects/RestrictedViewSizeSpec.scala | 39 ++++++++++--------- 3 files changed, 34 insertions(+), 32 deletions(-) diff --git a/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala b/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala index 9befc8e2e2..22e5efa7ff 100644 --- a/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala +++ b/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala @@ -8,7 +8,6 @@ package dsp.valueobjects import zio.prelude.Validation import scala.util.matching.Regex -import dsp.errors.BadRequestException import zio.json.JsonCodec /** @@ -17,7 +16,7 @@ import zio.json.JsonCodec sealed abstract case class RestrictedViewSize private (value: String) object RestrictedViewSize { - def make(value: String): Validation[Throwable, RestrictedViewSize] = { + def make(value: String): Either[String, RestrictedViewSize] = { val trimmed: String = value.trim // matches strings "pct:1-100" val percentagePattern: Regex = "pct:[1-9][0-9]?0?$".r @@ -28,16 +27,17 @@ object RestrictedViewSize { substr.head == substr.last } - if (value.isEmpty) Validation.fail(BadRequestException(ErrorMessages.RestrictedViewSizeMissing)) - else if (percentagePattern.matches(trimmed)) Validation.succeed(new RestrictedViewSize(trimmed) {}) - else if (dimensionsPattern.matches(trimmed) && isSquare) Validation.succeed(new RestrictedViewSize(trimmed) {}) - else Validation.fail(BadRequestException(ErrorMessages.RestrictedViewSizeInvalid)) + if (value.isEmpty) Left(ErrorMessages.RestrictedViewSizeMissing) + else if (percentagePattern.matches(trimmed)) Right(new RestrictedViewSize(trimmed) {}) + else if (dimensionsPattern.matches(trimmed) && isSquare) Right(new RestrictedViewSize(trimmed) {}) + else Left(ErrorMessages.RestrictedViewSizeInvalid) } - implicit val codec: JsonCodec[RestrictedViewSize] = JsonCodec[String].transformOrFail( - str => RestrictedViewSize.make(str).toEither.left.map(err => err.map(_.getMessage).mkString(", ")), - value => value.value - ) + def unsafeFrom(value: String): RestrictedViewSize = + make(value).fold(s => throw new IllegalArgumentException(s), identity) + + implicit val codec: JsonCodec[RestrictedViewSize] = + JsonCodec[String].transformOrFail(RestrictedViewSize.make, _.value) } object ErrorMessages { diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala index 10fd0b3bfc..7942eef347 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala @@ -250,10 +250,9 @@ final case class ProjectsRouteZ( iriDecoded <- RouteUtilZ.urlDecode(iri, s"Failed to URL decode IRI parameter $iri.") id <- IriIdentifier.fromString(iriDecoded).toZIO.mapError(e => BadRequestException(e.msg)) body <- body.asString - payload <- - ZIO.fromEither(body.fromJson[ProjectSetRestrictedViewSettingsPayload]).mapError(e => BadRequestException(e)) - size <- RestrictedViewSize.make(payload.size).toZIO - response <- projectsService.setProjectRestrictedViewSettings(id.value, user, size) + payload <- ZIO.fromEither(body.fromJson[ProjectSetRestrictedViewSettingsPayload]).mapError(BadRequestException(_)) + size <- ZIO.fromEither(RestrictedViewSize.make(payload.size)).mapError(BadRequestException(_)) + response <- projectsService.setProjectRestrictedViewSettings(id.value, user, size) } yield Response.json(response.toJson) } diff --git a/webapi/src/test/scala/dsp/valueobjects/RestrictedViewSizeSpec.scala b/webapi/src/test/scala/dsp/valueobjects/RestrictedViewSizeSpec.scala index 468ef609d2..fedd3d1721 100644 --- a/webapi/src/test/scala/dsp/valueobjects/RestrictedViewSizeSpec.scala +++ b/webapi/src/test/scala/dsp/valueobjects/RestrictedViewSizeSpec.scala @@ -5,11 +5,8 @@ package dsp.valueobjects -import zio.prelude.Validation import zio.test._ -import dsp.errors.BadRequestException - /** * This spec is used to test the [[dsp.valueobjects.RestrictedViewSize]] value object creation. */ @@ -17,24 +14,30 @@ object RestrictedViewSizeSpec extends ZIOSpecDefault { def spec = suite("Size")( test("pass correct percentage value") { - assertTrue(RestrictedViewSize.make("pct:1").toOption.get.value == "pct:1") + assertTrue(RestrictedViewSize.make("pct:1").map(_.value) == Right("pct:1")) + }, + test("should succeed on passing same x y dimensions") { + val gen = Gen.int(1, 1000) + check(gen) { integer => + val param = s"!$integer,$integer" + assertTrue(RestrictedViewSize.make(param).map(_.value) == Right(param)) + } }, - test("pass correct dimension value") { - assertTrue(RestrictedViewSize.make("!512,512").toOption.get.value == "!512,512") + test("should fail on passing negative x y dimensions") { + val gen = Gen.int(-1000, -1) + check(gen) { integer => + val param = s"!$integer,$integer" + assertTrue(RestrictedViewSize.make(param).map(_.value) == Left(ErrorMessages.RestrictedViewSizeInvalid)) + } }, test("fail on passing incorrect values") { - assertTrue( - RestrictedViewSize.make("!512,100") == Validation.fail( - BadRequestException(ErrorMessages.RestrictedViewSizeInvalid) - ), - RestrictedViewSize.make("pct:0") == Validation.fail( - BadRequestException(ErrorMessages.RestrictedViewSizeInvalid) - ), - RestrictedViewSize.make("pct:101") == Validation.fail( - BadRequestException(ErrorMessages.RestrictedViewSizeInvalid) - ), - RestrictedViewSize.make("") == Validation.fail(BadRequestException(ErrorMessages.RestrictedViewSizeMissing)) - ) + val gen = Gen.fromIterable(Seq("!512,100", "pct:0", "pct:101")) + check(gen) { param => + assertTrue(RestrictedViewSize.make(param) == Left(ErrorMessages.RestrictedViewSizeInvalid)) + } + }, + test("fail on passing empty value") { + assertTrue(RestrictedViewSize.make("") == Left(ErrorMessages.RestrictedViewSizeMissing)) } ) } From c53c2798bdb7ffffee7d953c87df466c19a6d31c Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Mon, 18 Sep 2023 16:24:43 +0200 Subject: [PATCH 28/51] fix Update usage and tests --- .../responders/admin/ProjectsResponderADM.scala | 2 +- .../valueobjects/RestrictedViewSizeSpec.scala | 16 ++++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala index 80d951cebd..94ede0bd46 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala @@ -492,7 +492,7 @@ final case class ProjectsResponderADMLive( query = twirl.queries.sparql.admin.txt .setProjectRestrictedViewSettings(iri.value, size.value, None) - _ = Update(query.toString) + _ <- triplestore.query(Update(query.toString)) } yield ProjectRestrictedViewSizeResponseADM(size) } diff --git a/webapi/src/test/scala/dsp/valueobjects/RestrictedViewSizeSpec.scala b/webapi/src/test/scala/dsp/valueobjects/RestrictedViewSizeSpec.scala index fedd3d1721..0a4baaa80d 100644 --- a/webapi/src/test/scala/dsp/valueobjects/RestrictedViewSizeSpec.scala +++ b/webapi/src/test/scala/dsp/valueobjects/RestrictedViewSizeSpec.scala @@ -13,10 +13,14 @@ import zio.test._ object RestrictedViewSizeSpec extends ZIOSpecDefault { def spec = suite("Size")( - test("pass correct percentage value") { - assertTrue(RestrictedViewSize.make("pct:1").map(_.value) == Right("pct:1")) + test("should succeed on passing percentage values") { + val gen = Gen.int(1,100) + check(gen) { int => + val param = s"pct:$int" + assertTrue(RestrictedViewSize.make(param).map(_.value) == Right(param)) + } }, - test("should succeed on passing same x y dimensions") { + test("should succeed on passing the same x y dimensions") { val gen = Gen.int(1, 1000) check(gen) { integer => val param = s"!$integer,$integer" @@ -30,13 +34,13 @@ object RestrictedViewSizeSpec extends ZIOSpecDefault { assertTrue(RestrictedViewSize.make(param).map(_.value) == Left(ErrorMessages.RestrictedViewSizeInvalid)) } }, - test("fail on passing incorrect values") { - val gen = Gen.fromIterable(Seq("!512,100", "pct:0", "pct:101")) + test("should fail on passing incorrect values") { + val gen = Gen.fromIterable(Seq("!512,100", "pct:-1", "pct:0", "pct:101")) check(gen) { param => assertTrue(RestrictedViewSize.make(param) == Left(ErrorMessages.RestrictedViewSizeInvalid)) } }, - test("fail on passing empty value") { + test("should fail on passing empty value") { assertTrue(RestrictedViewSize.make("") == Left(ErrorMessages.RestrictedViewSizeMissing)) } ) From b34c791403e5d540f858f6b890d4c06828892401 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Mon, 18 Sep 2023 16:38:56 +0200 Subject: [PATCH 29/51] fmt --- .../main/scala/dsp/valueobjects/RestrictedViewSize.scala | 3 +-- .../responder/projectsmessages/ProjectsMessagesADM.scala | 9 +++------ .../scala/dsp/valueobjects/RestrictedViewSizeSpec.scala | 2 +- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala b/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala index 22e5efa7ff..678016436b 100644 --- a/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala +++ b/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala @@ -5,10 +5,9 @@ package dsp.valueobjects -import zio.prelude.Validation +import zio.json.JsonCodec import scala.util.matching.Regex -import zio.json.JsonCodec /** * RestrictedViewSize value object. diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala index b3985ab6b3..2da1c23693 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala @@ -8,17 +8,15 @@ package org.knora.webapi.messages.admin.responder.projectsmessages import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport import org.apache.commons.lang3.builder.HashCodeBuilder import spray.json.DefaultJsonProtocol -import spray.json.JsString import spray.json.JsValue import spray.json.JsonFormat import spray.json.RootJsonFormat -import spray.json.deserializationError +import zio.json.DeriveJsonCodec +import zio.json.JsonCodec import zio.prelude.Validation import java.util.UUID -import scala.util.Failure -import scala.util.Success -import scala.util.Try + import dsp.errors.BadRequestException import dsp.errors.OntologyConstraintException import dsp.errors.ValidationException @@ -35,7 +33,6 @@ import org.knora.webapi.messages.admin.responder.KnoraResponseADM import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM._ import org.knora.webapi.messages.admin.responder.usersmessages.UserADM import org.knora.webapi.messages.store.triplestoremessages.TriplestoreJsonProtocol -import zio.json.{DeriveJsonCodec, JsonCodec} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // API requests diff --git a/webapi/src/test/scala/dsp/valueobjects/RestrictedViewSizeSpec.scala b/webapi/src/test/scala/dsp/valueobjects/RestrictedViewSizeSpec.scala index 0a4baaa80d..ee191494ba 100644 --- a/webapi/src/test/scala/dsp/valueobjects/RestrictedViewSizeSpec.scala +++ b/webapi/src/test/scala/dsp/valueobjects/RestrictedViewSizeSpec.scala @@ -14,7 +14,7 @@ object RestrictedViewSizeSpec extends ZIOSpecDefault { def spec = suite("Size")( test("should succeed on passing percentage values") { - val gen = Gen.int(1,100) + val gen = Gen.int(1, 100) check(gen) { int => val param = s"pct:$int" assertTrue(RestrictedViewSize.make(param).map(_.value) == Right(param)) From e56b9999e605e3c48e1552531c1bdd1d57cf3165 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Tue, 19 Sep 2023 11:07:06 +0200 Subject: [PATCH 30/51] remove ProjectRestrictedViewSettingsSetRequestADM --- .../projectsmessages/ProjectsMessagesADM.scala | 13 ------------- .../responders/admin/ProjectsResponderADM.scala | 2 -- 2 files changed, 15 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala index 2da1c23693..d8f331e3e5 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala @@ -248,19 +248,6 @@ case class ProjectRestrictedViewSettingsGetRequestADM( identifier: ProjectIdentifierADM ) extends ProjectsResponderRequestADM -/** - * Return project's RestrictedView settings. - * - * @param iri the identifier of the project. - * @param user requesting user. - * @param size size value to be applied. - */ -case class ProjectRestrictedViewSettingsSetRequestADM( - iri: Iri.ProjectIri, - user: UserADM, - size: RestrictedViewSize -) extends ProjectsResponderRequestADM - /** * Requests the creation of a new project. * diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala index 94ede0bd46..8ce7f386c8 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala @@ -219,8 +219,6 @@ final case class ProjectsResponderADMLive( projectRestrictedViewSettingsGetADM(identifier) case ProjectRestrictedViewSettingsGetRequestADM(identifier) => projectRestrictedViewSettingsGetRequestADM(identifier) - case ProjectRestrictedViewSettingsSetRequestADM(iri, user, size) => - setProjectRestrictedViewSettings(iri, user, size) case ProjectCreateRequestADM(createRequest, requestingUser, apiRequestID) => projectCreateRequestADM(createRequest, requestingUser, apiRequestID) case ProjectChangeRequestADM( From a0a1b57ed76cf4979934c192159f9a8302e1c126 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Tue, 19 Sep 2023 13:02:45 +0200 Subject: [PATCH 31/51] replace ProjectIri with ProjectIdentifierADM --- .../responders/admin/ProjectsResponderADM.scala | 17 ++++++++--------- .../webapi/routing/admin/ProjectsRouteZ.scala | 2 +- .../api/service/ProjectsADMRestService.scala | 5 ++--- .../admin/ProjectADMRestServiceMock.scala | 2 +- .../admin/ProjectsResponderADMMock.scala | 2 +- 5 files changed, 13 insertions(+), 15 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala index 8ce7f386c8..cc9d801834 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala @@ -139,7 +139,7 @@ trait ProjectsResponderADM { * @return [[ProjectRestrictedViewSettingsResponseADM]]. */ def setProjectRestrictedViewSettings( - iri: Iri.ProjectIri, + iri: ProjectIdentifierADM, user: UserADM, size: RestrictedViewSize ): Task[ProjectRestrictedViewSizeResponseADM] @@ -474,25 +474,24 @@ final case class ProjectsResponderADMLive( * @return [[ProjectRestrictedViewSettingsResponseADM]]. */ override def setProjectRestrictedViewSettings( - iri: Iri.ProjectIri, + iri: ProjectIdentifierADM, user: UserADM, size: RestrictedViewSize - ): Task[ProjectRestrictedViewSizeResponseADM] = { - val id = ProjectIdentifierADM.IriIdentifier(iri) + ): Task[ProjectRestrictedViewSizeResponseADM] = +// val id = ProjectIdentifierADM.IriIdentifier(iri) for { - _ <- getProjectFromCacheOrTriplestore(id) + _ <- getProjectFromCacheOrTriplestore(iri) .flatMap(ZIO.fromOption(_)) - .orElseFail(NotFoundException(s"Project '${getId(id)}' not found.")) + .orElseFail(NotFoundException(s"Project '${getId(iri)}' not found.")) _ <- ZIO .fail(ForbiddenException("User is neither system nor project admin.")) - .unless(user.permissions.isSystemAdmin || user.permissions.isProjectAdmin(iri.value)) + .unless(user.permissions.isSystemAdmin || user.permissions.isProjectAdmin(getId(iri))) query = twirl.queries.sparql.admin.txt - .setProjectRestrictedViewSettings(iri.value, size.value, None) + .setProjectRestrictedViewSettings(getId(iri), size.value, None) _ <- triplestore.query(Update(query.toString)) } yield ProjectRestrictedViewSizeResponseADM(size) - } /** * Update project's basic information. diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala index 7942eef347..5a659858b5 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala @@ -252,7 +252,7 @@ final case class ProjectsRouteZ( body <- body.asString payload <- ZIO.fromEither(body.fromJson[ProjectSetRestrictedViewSettingsPayload]).mapError(BadRequestException(_)) size <- ZIO.fromEither(RestrictedViewSize.make(payload.size)).mapError(BadRequestException(_)) - response <- projectsService.setProjectRestrictedViewSettings(id.value, user, size) + response <- projectsService.setProjectRestrictedViewSettings(id, user, size) } yield Response.json(response.toJson) } diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala index 77961f6426..59fdeeab7a 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala @@ -10,7 +10,6 @@ import zio.macros.accessible import dsp.errors.BadRequestException import dsp.errors.NotFoundException -import dsp.valueobjects.Iri import dsp.valueobjects.Iri.ProjectIri import dsp.valueobjects.Project import dsp.valueobjects.Project.Shortcode @@ -65,7 +64,7 @@ trait ProjectADMRestService { identifier: ProjectIdentifierADM ): Task[ProjectRestrictedViewSettingsResponseADM] def setProjectRestrictedViewSettings( - iri: Iri.ProjectIri, + iri: ProjectIdentifierADM, user: UserADM, size: RestrictedViewSize ): Task[ProjectRestrictedViewSizeResponseADM] @@ -255,7 +254,7 @@ final case class ProjectsADMRestServiceLive( * @return [[ProjectRestrictedViewSettingsResponseADM]]. */ override def setProjectRestrictedViewSettings( - iri: Iri.ProjectIri, + iri: ProjectIdentifierADM, user: UserADM, size: RestrictedViewSize ): Task[ProjectRestrictedViewSizeResponseADM] = diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala index 4b8ac630bd..21ad5858e4 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala @@ -100,7 +100,7 @@ object ProjectADMRestServiceMock extends Mock[ProjectADMRestService] { override def listExports(requestingUser: UserADM): Task[Chunk[ProjectExportInfoResponse]] = ??? override def setProjectRestrictedViewSettings( - iri: ProjectIri, + iri: ProjectIdentifierADM, user: UserADM, size: RestrictedViewSize ): Task[ProjectRestrictedViewSizeResponseADM] = ??? diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala index 4447290db0..704228cb16 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala @@ -87,7 +87,7 @@ object ProjectsResponderADMMock extends Mock[ProjectsResponderADM] { ): Task[ProjectOperationResponseADM] = proxy(ChangeBasicInformationRequestADM, (projectIri, updatePayload, user, apiRequestID)) override def setProjectRestrictedViewSettings( - iri: Iri.ProjectIri, + iri: ProjectIdentifierADM, user: UserADM, size: RestrictedViewSize ): Task[ProjectRestrictedViewSizeResponseADM] = ??? From d68efa1c69d947b718d9168333e2a327353001c1 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Tue, 19 Sep 2023 17:00:13 +0200 Subject: [PATCH 32/51] move all setProjectRestrictedViewSettings functionality to rest service --- .../admin/ProjectsResponderADM.scala | 43 ------------------- .../api/service/ProjectsADMRestService.scala | 13 +++++- .../admin/ProjectsResponderADMMock.scala | 6 --- .../admin/ProjectsServiceLiveSpec.scala | 3 ++ 4 files changed, 15 insertions(+), 50 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala index cc9d801834..35e86509e1 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala @@ -11,7 +11,6 @@ import java.util.UUID import dsp.errors._ import dsp.valueobjects.Iri -import dsp.valueobjects.RestrictedViewSize import dsp.valueobjects.V2 import org.knora.webapi._ import org.knora.webapi.config.AppConfig @@ -130,20 +129,6 @@ trait ProjectsResponderADM { id: ProjectIdentifierADM ): Task[ProjectRestrictedViewSettingsResponseADM] - /** - * Sets project's restricted view settings. - * - * @param iri the project's iri, - * @param user requesting user, - * @param size value to be set, - * @return [[ProjectRestrictedViewSettingsResponseADM]]. - */ - def setProjectRestrictedViewSettings( - iri: ProjectIdentifierADM, - user: UserADM, - size: RestrictedViewSize - ): Task[ProjectRestrictedViewSizeResponseADM] - /** * Creates a project. * @@ -465,34 +450,6 @@ final case class ProjectsResponderADMLive( ProjectRestrictedViewSettingsResponseADM ) - /** - * Sets project's restricted view settings. - * - * @param iri the project's iri, - * @param user requesting user, - * @param size value to be set, - * @return [[ProjectRestrictedViewSettingsResponseADM]]. - */ - override def setProjectRestrictedViewSettings( - iri: ProjectIdentifierADM, - user: UserADM, - size: RestrictedViewSize - ): Task[ProjectRestrictedViewSizeResponseADM] = -// val id = ProjectIdentifierADM.IriIdentifier(iri) - for { - _ <- getProjectFromCacheOrTriplestore(iri) - .flatMap(ZIO.fromOption(_)) - .orElseFail(NotFoundException(s"Project '${getId(iri)}' not found.")) - _ <- ZIO - .fail(ForbiddenException("User is neither system nor project admin.")) - .unless(user.permissions.isSystemAdmin || user.permissions.isProjectAdmin(getId(iri))) - - query = twirl.queries.sparql.admin.txt - .setProjectRestrictedViewSettings(getId(iri), size.value, None) - - _ <- triplestore.query(Update(query.toString)) - } yield ProjectRestrictedViewSizeResponseADM(size) - /** * Update project's basic information. * diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala index 59fdeeab7a..5750de8399 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala @@ -17,6 +17,7 @@ import dsp.valueobjects.RestrictedViewSize import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM._ import org.knora.webapi.messages.admin.responder.projectsmessages._ import org.knora.webapi.messages.admin.responder.usersmessages.UserADM +import org.knora.webapi.messages.twirl.queries.sparql import org.knora.webapi.responders.admin.ProjectsResponderADM import org.knora.webapi.slice.admin.api.model.ProjectDataGetResponseADM import org.knora.webapi.slice.admin.api.model.ProjectExportInfoResponse @@ -25,6 +26,8 @@ import org.knora.webapi.slice.admin.domain.service.KnoraProjectRepo import org.knora.webapi.slice.admin.domain.service.ProjectExportService import org.knora.webapi.slice.admin.domain.service.ProjectImportService import org.knora.webapi.slice.common.api.RestPermissionService +import org.knora.webapi.store.triplestore.api.TriplestoreService +import org.knora.webapi.store.triplestore.api.TriplestoreService.Queries.Update @accessible trait ProjectADMRestService { @@ -71,6 +74,7 @@ trait ProjectADMRestService { } final case class ProjectsADMRestServiceLive( + triplestore: TriplestoreService, responder: ProjectsResponderADM, projectRepo: KnoraProjectRepo, projectExportService: ProjectExportService, @@ -258,7 +262,13 @@ final case class ProjectsADMRestServiceLive( user: UserADM, size: RestrictedViewSize ): Task[ProjectRestrictedViewSizeResponseADM] = - responder.setProjectRestrictedViewSettings(iri, user, size) + for { + project <- projectRepo.findById(iri).someOrFail(NotFoundException(s"Project '${getId(iri)}' not found.")) + _ <- permissionService.ensureSystemOrProjectAdmin(user, project) + query = sparql.admin.txt + .setProjectRestrictedViewSettings(getId(iri), size.value, None) + _ <- triplestore.query(Update(query.toString)) + } yield ProjectRestrictedViewSizeResponseADM(size) override def exportProject(shortcodeStr: String, requestingUser: UserADM): Task[Unit] = for { _ <- permissionService.ensureSystemAdmin(requestingUser) @@ -294,6 +304,7 @@ final case class ProjectsADMRestServiceLive( object ProjectsADMRestServiceLive { val layer: URLayer[ ProjectsResponderADM + with TriplestoreService with KnoraProjectRepo with ProjectExportService with ProjectImportService diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala index 704228cb16..d7c29edd4e 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala @@ -16,7 +16,6 @@ import zio.mock.Proxy import java.util.UUID import dsp.valueobjects.Iri -import dsp.valueobjects.RestrictedViewSize import org.knora.webapi.messages.admin.responder.projectsmessages._ import org.knora.webapi.messages.admin.responder.usersmessages.UserADM @@ -86,11 +85,6 @@ object ProjectsResponderADMMock extends Mock[ProjectsResponderADM] { apiRequestID: UUID ): Task[ProjectOperationResponseADM] = proxy(ChangeBasicInformationRequestADM, (projectIri, updatePayload, user, apiRequestID)) - override def setProjectRestrictedViewSettings( - iri: ProjectIdentifierADM, - user: UserADM, - size: RestrictedViewSize - ): Task[ProjectRestrictedViewSizeResponseADM] = ??? } } } diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsServiceLiveSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsServiceLiveSpec.scala index a504e5e06a..57397fa48c 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsServiceLiveSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsServiceLiveSpec.scala @@ -22,6 +22,7 @@ import org.knora.webapi.slice.admin.domain.service.DspIngestClientMock import org.knora.webapi.slice.admin.domain.service.ProjectExportServiceStub import org.knora.webapi.slice.admin.domain.service.ProjectExportStorageServiceLive import org.knora.webapi.slice.admin.domain.service.ProjectImportServiceLive +import org.knora.webapi.store.triplestore.impl.TriplestoreServiceLive object ProjectsServiceLiveSpec extends ZIOSpecDefault { @@ -58,6 +59,8 @@ object ProjectsServiceLiveSpec extends ZIOSpecDefault { private def projectServiceLayer(exp: Expectation[ProjectsResponderADM]): ULayer[ProjectADMRestService] = ZLayer.make[ProjectADMRestService]( + TriplestoreServiceLive.layer, + StringFormatter.test, ProjectsADMRestServiceLive.layer, exp.toLayer, org.knora.webapi.slice.common.api.RestPermissionServiceLive.layer, From fd48160411650ac047258686e5c64b0988bce815 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Wed, 20 Sep 2023 09:38:38 +0200 Subject: [PATCH 33/51] names refactoring --- .../projectsmessages/ProjectsPayloadsADM.scala | 8 ++++---- .../knora/webapi/routing/admin/ProjectsRouteZ.scala | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsPayloadsADM.scala index ef3a807b01..132026f947 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsPayloadsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsPayloadsADM.scala @@ -80,9 +80,9 @@ object ProjectUpdatePayloadADM { } } -final case class ProjectSetRestrictedViewSettingsPayload(size: String) +final case class ProjectSetRestrictedViewSizePayload(size: String) -object ProjectSetRestrictedViewSettingsPayload { - implicit val codec: JsonCodec[ProjectSetRestrictedViewSettingsPayload] = - DeriveJsonCodec.gen[ProjectSetRestrictedViewSettingsPayload] +object ProjectSetRestrictedViewSizePayload { + implicit val codec: JsonCodec[ProjectSetRestrictedViewSizePayload] = + DeriveJsonCodec.gen[ProjectSetRestrictedViewSizePayload] } diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala index 5a659858b5..70f5b9f98c 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala @@ -12,7 +12,6 @@ import zio.json._ import zio.stream.ZStream import java.nio.file.Files - import dsp.errors.BadRequestException import dsp.valueobjects.Iri._ import dsp.valueobjects.RestrictedViewSize @@ -21,10 +20,11 @@ import org.knora.webapi.http.handler.ExceptionHandlerZ import org.knora.webapi.http.middleware.AuthenticationMiddleware import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectCreatePayloadADM import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM._ -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectSetRestrictedViewSettingsPayload +import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectSetRestrictedViewSizePayload import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectUpdatePayloadADM import org.knora.webapi.messages.admin.responder.usersmessages.UserADM import org.knora.webapi.routing.RouteUtilZ +import org.knora.webapi.routing.admin.ProjectsRouteZ.layer import org.knora.webapi.slice.admin.api.service.ProjectADMRestService final case class ProjectsRouteZ( @@ -90,7 +90,7 @@ final case class ProjectsRouteZ( request @ Method.POST -> !! / "admin" / "projects" / "iri" / iri / "RestrictedViewSettings", requestingUser ) => - setProjectRestrictedViewSettings(iri, request.body, requestingUser) + setProjectRestrictedViewSizeByIri(iri, request.body, requestingUser) } .catchAll(ExceptionHandlerZ.exceptionToJsonHttpResponseZ(_, appConfig)) @@ -241,7 +241,7 @@ final case class ProjectsRouteZ( r <- projectsService.getProjectRestrictedViewSettings(shortcodeIdentifier) } yield Response.json(r.toJsValue.toString) - private def setProjectRestrictedViewSettings( + private def setProjectRestrictedViewSizeByIri( iri: String, body: Body, user: UserADM @@ -250,7 +250,7 @@ final case class ProjectsRouteZ( iriDecoded <- RouteUtilZ.urlDecode(iri, s"Failed to URL decode IRI parameter $iri.") id <- IriIdentifier.fromString(iriDecoded).toZIO.mapError(e => BadRequestException(e.msg)) body <- body.asString - payload <- ZIO.fromEither(body.fromJson[ProjectSetRestrictedViewSettingsPayload]).mapError(BadRequestException(_)) + payload <- ZIO.fromEither(body.fromJson[ProjectSetRestrictedViewSizePayload]).mapError(BadRequestException(_)) size <- ZIO.fromEither(RestrictedViewSize.make(payload.size)).mapError(BadRequestException(_)) response <- projectsService.setProjectRestrictedViewSettings(id, user, size) } yield Response.json(response.toJson) From a25a0b1e5803f04478904eb7b240199857246ff4 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Wed, 20 Sep 2023 13:12:16 +0200 Subject: [PATCH 34/51] add ByShortcode route version --- .../webapi/routing/admin/ProjectsRouteZ.scala | 17 +++++++++++++++++ .../api/service/ProjectsADMRestService.scala | 12 +++++++----- .../admin/ProjectADMRestServiceMock.scala | 2 +- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala index 70f5b9f98c..8ac2e1bdbd 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala @@ -91,6 +91,11 @@ final case class ProjectsRouteZ( requestingUser ) => setProjectRestrictedViewSizeByIri(iri, request.body, requestingUser) + case ( + request @ Method.POST -> !! / "admin" / "projects" / "shortcode" / shortcode / "RestrictedViewSettings", + requstingUser + ) => + setProjectRestrictedViewSizeByShortcode(shortcode, request.body, requstingUser) } .catchAll(ExceptionHandlerZ.exceptionToJsonHttpResponseZ(_, appConfig)) @@ -254,6 +259,18 @@ final case class ProjectsRouteZ( size <- ZIO.fromEither(RestrictedViewSize.make(payload.size)).mapError(BadRequestException(_)) response <- projectsService.setProjectRestrictedViewSettings(id, user, size) } yield Response.json(response.toJson) + + private def setProjectRestrictedViewSizeByShortcode( + shortcode: String, + body: Body, + user: UserADM + ): Task[Response] = for { + id <- ShortcodeIdentifier.fromString(shortcode).toZIO.mapError(e => BadRequestException(e.msg)) + body <- body.asString + payload <- ZIO.fromEither(body.fromJson[ProjectSetRestrictedViewSizePayload]).mapError(BadRequestException(_)) + size <- ZIO.fromEither(RestrictedViewSize.make(payload.size)).mapError(BadRequestException(_)) + response <- projectsService.setProjectRestrictedViewSettings(id, user, size) + } yield Response.json(response.toJson) } object ProjectsRouteZ { diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala index 5750de8399..9956984b06 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala @@ -67,7 +67,7 @@ trait ProjectADMRestService { identifier: ProjectIdentifierADM ): Task[ProjectRestrictedViewSettingsResponseADM] def setProjectRestrictedViewSettings( - iri: ProjectIdentifierADM, + id: ProjectIdentifierADM, user: UserADM, size: RestrictedViewSize ): Task[ProjectRestrictedViewSizeResponseADM] @@ -252,21 +252,23 @@ final case class ProjectsADMRestServiceLive( /** * Sets project's restricted view settings. * - * @param iri the project's IRI, + * @param id the project's id represented by iri, shortocde or shortname, * @param user requesting user, * @param size value to be set, * @return [[ProjectRestrictedViewSettingsResponseADM]]. */ override def setProjectRestrictedViewSettings( - iri: ProjectIdentifierADM, + id: ProjectIdentifierADM, user: UserADM, size: RestrictedViewSize ): Task[ProjectRestrictedViewSizeResponseADM] = for { - project <- projectRepo.findById(iri).someOrFail(NotFoundException(s"Project '${getId(iri)}' not found.")) + project <- projectRepo.findById(id).someOrFail(NotFoundException(s"Project '${getId(id)}' not found.")) _ <- permissionService.ensureSystemOrProjectAdmin(user, project) query = sparql.admin.txt - .setProjectRestrictedViewSettings(getId(iri), size.value, None) + .setProjectRestrictedViewSettings(project.id.value, size.value, None) + + _ = println(777, getId(id), project) _ <- triplestore.query(Update(query.toString)) } yield ProjectRestrictedViewSizeResponseADM(size) diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala index 21ad5858e4..9ac618a5c0 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala @@ -100,7 +100,7 @@ object ProjectADMRestServiceMock extends Mock[ProjectADMRestService] { override def listExports(requestingUser: UserADM): Task[Chunk[ProjectExportInfoResponse]] = ??? override def setProjectRestrictedViewSettings( - iri: ProjectIdentifierADM, + id: ProjectIdentifierADM, user: UserADM, size: RestrictedViewSize ): Task[ProjectRestrictedViewSizeResponseADM] = ??? From 5bc2c695c1b1fc916f8ce223d719696b4c406299 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Thu, 21 Sep 2023 11:13:12 +0200 Subject: [PATCH 35/51] update docs --- docs/03-endpoints/api-admin/projects.md | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/docs/03-endpoints/api-admin/projects.md b/docs/03-endpoints/api-admin/projects.md index 17e9fa8914..4135d7b1ae 100644 --- a/docs/03-endpoints/api-admin/projects.md +++ b/docs/03-endpoints/api-admin/projects.md @@ -6,7 +6,7 @@ # Projects Endpoint | Scope | Route | Operations | Explanation | -| --------------- | -------------------------------------------------------------- | ---------- | ----------------------------------------------------------------------- | +| --------------- | -------------------------------------------------------------- |------------|-------------------------------------------------------------------------| | projects | `/admin/projects` | `GET` | [get all projects](#get-all-projects) | | projects | `/admin/projects` | `POST` | [create a project](#create-a-new-project) | | projects | `/admin/projects/shortname/{shortname}` | `GET` | [get a single project](#get-project-by-id) | @@ -26,7 +26,8 @@ | view settings | `/admin/projects/shortname/{shortname}/RestrictedViewSettings` | `GET` | [get restricted view settings for a project](#restricted-view-settings) | | view settings | `/admin/projects/shortcode/{shortcode}/RestrictedViewSettings` | `GET` | [get restricted view settings for a project](#restricted-view-settings) | | view settings | `/admin/projects/iri/{iri}/RestrictedViewSettings` | `GET` | [get restricted view settings for a project](#restricted-view-settings) | - +| view settings | `/admin/projects/iri/{iri}/RestrictedViewSettings` | `POST` | [set restricted view settings for a project](#restricted-view-settings) | +| view settings | `/admin/projects/shortcode/{shortcode}/RestrictedViewSettings` | `POST` | [set restricted view settings for a project](#restricted-view-settings) | ## Project Operations @@ -815,18 +816,19 @@ Example response: ### Set Restricted View Settings -The route takes String parameter which sets restricted view size in on of two formats: as an image dimensions or a +Both routes take String parameter which sets restricted view size in one of two formats: as an image dimensions or a percentage. The dimensions pattern looks like: `!X,X`, where X is the number representing scaled image dimensions in a square, so that the width and height of the returned image are not greater than the requested value. Example: `!512,512` means the image's bigger side will be set to 512 pixels, setting the other side respectively to -image aspect ratio. -The percentage pattern looks like: `pct:X`, where X is the number between 1-100 representing the percentage the image -will be scaled to. Example: `pct:1` means the image will be scaled to 1% of the original image size. +image aspect ratio. The percentage pattern looks like: `pct:X`, where X is the number between 1-100 representing the +percentage the image will be scaled to. Example: `pct:1` means the image will be scaled to 1% of the original image +size. **Both routes are implemented only in `ZIO-HTTP`, thus can be reached under port `5555`.** Permissions: ProjectAdmin/SystemAdmin Request definition: - `POST /admin/projects/iri/{iri}/RestrictedViewSettings` +- `POST /admin/projects/shortcode/{shortcode}/RestrictedViewSettings` Description: Set the project's restricted view @@ -836,7 +838,13 @@ Required payload: Example request: ```bash -curl --request GET 'http://0.0.0.0:3333/admin/projects/iri/http%3A%2F%2Frdfh.ch%2Fprojects%2F0001/RestrictedViewSettings' \ +curl --request POST 'http://0.0.0.0:5555/admin/projects/iri/http%3A%2F%2Frdfh.ch%2Fprojects%2F0001/RestrictedViewSettings' \ +--header 'Authorization: Basic cm9vdEBleGFtcGxlLmNvbTp0ZXN0' \ +--data '{"size": "!512,512"} +``` + +```bash +curl --request POST 'http://0.0.0.0:5555/admin/projects/shortcode/0001/RestrictedViewSettings' \ --header 'Authorization: Basic cm9vdEBleGFtcGxlLmNvbTp0ZXN0' \ --data '{"size": "!512,512"} ``` From 43b5a0e6183ef96b19eb588dd825f693f2f113e3 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Thu, 21 Sep 2023 20:45:17 +0200 Subject: [PATCH 36/51] reorder implementation --- docs/03-endpoints/api-admin/projects.md | 2 +- .../responders/admin/ProjectsResponderADM.scala | 1 - .../knora/webapi/routing/admin/ProjectsRouteZ.scala | 2 +- .../admin/api/service/ProjectsADMRestService.scala | 8 +------- .../admin/domain/service/KnoraProjectRepo.scala | 2 ++ .../admin/domain/service/ProjectADMService.scala | 11 ++++++----- .../admin/repo/service/KnoraProjectRepoLive.scala | 13 +++++++++++++ .../repo/service/KnoraProjectRepoInMemory.scala | 3 +++ .../domain/service/KnoraProjectRepoInMemory.scala | 3 +++ 9 files changed, 30 insertions(+), 15 deletions(-) diff --git a/docs/03-endpoints/api-admin/projects.md b/docs/03-endpoints/api-admin/projects.md index 4135d7b1ae..1a0d957020 100644 --- a/docs/03-endpoints/api-admin/projects.md +++ b/docs/03-endpoints/api-admin/projects.md @@ -822,7 +822,7 @@ a square, so that the width and height of the returned image are not greater tha Example: `!512,512` means the image's bigger side will be set to 512 pixels, setting the other side respectively to image aspect ratio. The percentage pattern looks like: `pct:X`, where X is the number between 1-100 representing the percentage the image will be scaled to. Example: `pct:1` means the image will be scaled to 1% of the original image -size. **Both routes are implemented only in `ZIO-HTTP`, thus can be reached under port `5555`.** +size. **Both routes are implemented in `ZIO-HTTP`, thus can be reached only under port `5555`.** Permissions: ProjectAdmin/SystemAdmin diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala index 35e86509e1..f3f87fc843 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala @@ -646,7 +646,6 @@ final case class ProjectsResponderADMLive( ) ) } - } /** diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala index 8ac2e1bdbd..ef71baf157 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala @@ -12,6 +12,7 @@ import zio.json._ import zio.stream.ZStream import java.nio.file.Files + import dsp.errors.BadRequestException import dsp.valueobjects.Iri._ import dsp.valueobjects.RestrictedViewSize @@ -24,7 +25,6 @@ import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectSetRest import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectUpdatePayloadADM import org.knora.webapi.messages.admin.responder.usersmessages.UserADM import org.knora.webapi.routing.RouteUtilZ -import org.knora.webapi.routing.admin.ProjectsRouteZ.layer import org.knora.webapi.slice.admin.api.service.ProjectADMRestService final case class ProjectsRouteZ( diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala index 9956984b06..bac551fbe4 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala @@ -17,7 +17,6 @@ import dsp.valueobjects.RestrictedViewSize import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM._ import org.knora.webapi.messages.admin.responder.projectsmessages._ import org.knora.webapi.messages.admin.responder.usersmessages.UserADM -import org.knora.webapi.messages.twirl.queries.sparql import org.knora.webapi.responders.admin.ProjectsResponderADM import org.knora.webapi.slice.admin.api.model.ProjectDataGetResponseADM import org.knora.webapi.slice.admin.api.model.ProjectExportInfoResponse @@ -27,7 +26,6 @@ import org.knora.webapi.slice.admin.domain.service.ProjectExportService import org.knora.webapi.slice.admin.domain.service.ProjectImportService import org.knora.webapi.slice.common.api.RestPermissionService import org.knora.webapi.store.triplestore.api.TriplestoreService -import org.knora.webapi.store.triplestore.api.TriplestoreService.Queries.Update @accessible trait ProjectADMRestService { @@ -265,11 +263,7 @@ final case class ProjectsADMRestServiceLive( for { project <- projectRepo.findById(id).someOrFail(NotFoundException(s"Project '${getId(id)}' not found.")) _ <- permissionService.ensureSystemOrProjectAdmin(user, project) - query = sparql.admin.txt - .setProjectRestrictedViewSettings(project.id.value, size.value, None) - - _ = println(777, getId(id), project) - _ <- triplestore.query(Update(query.toString)) + _ <- projectRepo.setProjectRestrictedViewSize(project, size) } yield ProjectRestrictedViewSizeResponseADM(size) override def exportProject(shortcodeStr: String, requestingUser: UserADM): Task[Unit] = for { 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 6e93af9483..499f465a5b 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 @@ -7,6 +7,7 @@ package org.knora.webapi.slice.admin.domain.service import zio.Task import dsp.valueobjects.Project.Shortcode +import dsp.valueobjects.RestrictedViewSize import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM.ShortcodeIdentifier import org.knora.webapi.slice.admin.domain.model.KnoraProject @@ -17,4 +18,5 @@ trait KnoraProjectRepo extends Repository[KnoraProject, InternalIri] { def findById(id: ProjectIdentifierADM): Task[Option[KnoraProject]] def findByShortcode(shortcode: Shortcode): Task[Option[KnoraProject]] = findById(ShortcodeIdentifier(shortcode)) def findOntologies(project: KnoraProject): Task[List[InternalIri]] + def setProjectRestrictedViewSize(project: KnoraProject, size: RestrictedViewSize): Task[Unit] } diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectADMService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectADMService.scala index 6bbe24c6b4..d54c66d4d4 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectADMService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectADMService.scala @@ -6,13 +6,14 @@ package org.knora.webapi.slice.admin.domain.service import zio._ - import dsp.valueobjects.Project.Shortcode import org.knora.webapi.messages.OntologyConstants -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectADM -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectKeywordsGetResponseADM -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectsKeywordsGetResponseADM +import org.knora.webapi.messages.admin.responder.projectsmessages.{ + ProjectADM, + ProjectIdentifierADM, + ProjectKeywordsGetResponseADM, + ProjectsKeywordsGetResponseADM +} import org.knora.webapi.slice.admin.domain.model.KnoraProject import org.knora.webapi.slice.ontology.domain.service.OntologyRepo import org.knora.webapi.slice.resourceinfo.domain.InternalIri 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 fb8f5746d5..bf227ede52 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 @@ -9,6 +9,7 @@ import play.twirl.api.TxtFormat import zio._ import dsp.valueobjects.Project +import dsp.valueobjects.RestrictedViewSize import dsp.valueobjects.V2 import org.knora.webapi.messages.OntologyConstants.KnoraAdmin.HasSelfJoinEnabled import org.knora.webapi.messages.OntologyConstants.KnoraAdmin.ProjectDescription @@ -33,6 +34,7 @@ import org.knora.webapi.slice.resourceinfo.domain.InternalIri import org.knora.webapi.store.triplestore.api.TriplestoreService import org.knora.webapi.store.triplestore.api.TriplestoreService.Queries.Construct import org.knora.webapi.store.triplestore.api.TriplestoreService.Queries.Select +import org.knora.webapi.store.triplestore.api.TriplestoreService.Queries.Update final case class KnoraProjectRepoLive( private val triplestore: TriplestoreService, @@ -104,6 +106,17 @@ final case class KnoraProjectRepoLive( .query(Select(query)) .map(_.results.bindings.flatMap(_.rowMap.get("ontologyIri")).map(InternalIri).toList) } + + override def setProjectRestrictedViewSize( + project: KnoraProject, + size: RestrictedViewSize + ): Task[Unit] = { + val query = sparql.admin.txt + .setProjectRestrictedViewSettings(project.id.value, size.value, None) + for { + _ <- triplestore.query(Update(query.toString)) + } yield () + } } object KnoraProjectRepoLive { diff --git a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/repo/service/KnoraProjectRepoInMemory.scala b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/repo/service/KnoraProjectRepoInMemory.scala index e234aefed1..d9a9de8455 100644 --- a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/repo/service/KnoraProjectRepoInMemory.scala +++ b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/repo/service/KnoraProjectRepoInMemory.scala @@ -10,6 +10,7 @@ import zio.Task import zio.ULayer import zio.ZLayer +import dsp.valueobjects.RestrictedViewSize import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM import org.knora.webapi.slice.admin.domain.model.KnoraProject import org.knora.webapi.slice.admin.domain.service.KnoraProjectRepo @@ -32,6 +33,8 @@ final case class KnoraProjectRepoInMemory(projects: Ref[List[KnoraProject]]) override def findOntologies(project: KnoraProject): Task[List[InternalIri]] = throw new UnsupportedOperationException("not implemented (yet)") + + override def setProjectRestrictedViewSize(project: KnoraProject, size: RestrictedViewSize): Task[Unit] = ??? } object KnoraProjectRepoInMemory { diff --git a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/KnoraProjectRepoInMemory.scala b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/KnoraProjectRepoInMemory.scala index 479a6c4abc..8e7e45cfc7 100644 --- a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/KnoraProjectRepoInMemory.scala +++ b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/KnoraProjectRepoInMemory.scala @@ -10,6 +10,7 @@ import zio.Task import zio.ULayer import zio.ZLayer +import dsp.valueobjects.RestrictedViewSize import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM.IriIdentifier import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM.ShortcodeIdentifier @@ -32,6 +33,8 @@ final case class KnoraProjectRepoInMemory(projects: Ref[List[KnoraProject]]) override def findOntologies(project: KnoraProject): Task[List[InternalIri]] = throw new UnsupportedOperationException("not yet implemented") + + override def setProjectRestrictedViewSize(project: KnoraProject, size: RestrictedViewSize): Task[Unit] = ??? } object KnoraProjectRepoInMemory { From 8fcaed2407f26292362fff337e69ea4a886d119e Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Thu, 21 Sep 2023 21:01:09 +0200 Subject: [PATCH 37/51] fmt Signed-off-by: Marcin Procyk --- .../admin/domain/service/ProjectADMService.scala | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectADMService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectADMService.scala index d54c66d4d4..6bbe24c6b4 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectADMService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectADMService.scala @@ -6,14 +6,13 @@ package org.knora.webapi.slice.admin.domain.service import zio._ + import dsp.valueobjects.Project.Shortcode import org.knora.webapi.messages.OntologyConstants -import org.knora.webapi.messages.admin.responder.projectsmessages.{ - ProjectADM, - ProjectIdentifierADM, - ProjectKeywordsGetResponseADM, - ProjectsKeywordsGetResponseADM -} +import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectADM +import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM +import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectKeywordsGetResponseADM +import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectsKeywordsGetResponseADM import org.knora.webapi.slice.admin.domain.model.KnoraProject import org.knora.webapi.slice.ontology.domain.service.OntologyRepo import org.knora.webapi.slice.resourceinfo.domain.InternalIri From 2bdcaa1f61e8fc42deada9e4f993887196a1b359 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Tue, 26 Sep 2023 11:13:12 +0200 Subject: [PATCH 38/51] add e2e tests --- .../e2e/admin/ProjectsADME2EZioHttpSpec.scala | 93 ++++++++++++++++++- .../dsp/valueobjects/RestrictedViewSize.scala | 4 +- .../repo/service/KnoraProjectRepoLive.scala | 4 +- .../valueobjects/RestrictedViewSizeSpec.scala | 4 +- 4 files changed, 93 insertions(+), 12 deletions(-) diff --git a/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala b/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala index 9525d66cde..2ed2496bd7 100644 --- a/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala @@ -5,10 +5,7 @@ package org.knora.webapi.e2e.admin -import akka.http.scaladsl.model.ContentTypes -import akka.http.scaladsl.model.HttpEntity -import akka.http.scaladsl.model.HttpResponse -import akka.http.scaladsl.model.StatusCodes +import akka.http.scaladsl.model.{ContentTypes, HttpEntity, HttpRequest, HttpResponse, StatusCodes} import akka.http.scaladsl.model.headers.BasicHttpCredentials import akka.http.scaladsl.unmarshalling.Unmarshal import akka.util.Timeout @@ -17,7 +14,6 @@ import java.net.URLEncoder import scala.concurrent.Await import scala.concurrent.Future import scala.concurrent.duration._ - import dsp.valueobjects.V2 import org.knora.webapi.E2ESpec import org.knora.webapi.IRI @@ -774,5 +770,92 @@ class ProjectsADME2EZioHttpSpec extends E2ESpec with ProjectsADMJsonProtocol wit ) } } + + "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 payload = """{"size":"pct:1"}""" + val request = + Post(s"http://0.0.0.0:5555/admin/projects/iri/$encodedIri/RestrictedViewSettings", payload) ~> addCredentials( + BasicHttpCredentials(rootEmail, testPass) + ) + val response: HttpResponse = singleAwaitingRequest(request) + val result: String = responseToString(response) + assert(response.status === StatusCodes.OK) + assert(payload === result) + } + + "return the `BadRequest` if the size value is invalid" in { + val encodedIri = URLEncoder.encode(SharedTestDataADM.imagesProject.id, "utf-8") + val payload = """{"size":"pct:0"}""" + val request = + Post(s"http://0.0.0.0:5555/admin/projects/iri/$encodedIri/RestrictedViewSettings", payload) ~> addCredentials( + BasicHttpCredentials(rootEmail, testPass) + ) + val response: HttpResponse = singleAwaitingRequest(request) + val result: String = responseToString(response) + assert(response.status === StatusCodes.BadRequest) + assert(result.contains("Invalid RestrictedViewSize: pct:0")) + } + + "return `Forbidden` for the user who is not a system nor project admin" in { + val encodedIri = URLEncoder.encode(SharedTestDataADM.imagesProject.id, "utf-8") + val payload = """{"size":"pct:1"}""" + val request = + Post(s"http://0.0.0.0:5555/admin/projects/iri/$encodedIri/RestrictedViewSettings", payload) ~> addCredentials( + BasicHttpCredentials(SharedTestDataADM.imagesUser02.email, testPass) + ) + val response: HttpResponse = singleAwaitingRequest(request) + assert(response.status === StatusCodes.Forbidden) + } + } + + "used to set RestrictedViewSize by project Shortcode" should { + "return requested value to be set with 200 Response Status" in { + val shortcode = SharedTestDataADM.imagesProject.shortcode + val payload = """{"size":"pct:1"}""" + val request = + Post( + s"http://0.0.0.0:5555/admin/projects/shortcode/$shortcode/RestrictedViewSettings", + payload + ) ~> addCredentials( + BasicHttpCredentials(rootEmail, testPass) + ) + val response: HttpResponse = singleAwaitingRequest(request) + val result: String = responseToString(response) + assert(response.status === StatusCodes.OK) + assert(payload === result) + } + + "return the `BadRequest` if the size value is invalid" in { + val shortcode = SharedTestDataADM.imagesProject.shortcode + val payload = """{"size":"pct:0"}""" + val request = + Post( + s"http://0.0.0.0:5555/admin/projects/shortcode/$shortcode/RestrictedViewSettings", + payload + ) ~> addCredentials( + BasicHttpCredentials(rootEmail, testPass) + ) + val response: HttpResponse = singleAwaitingRequest(request) + val result: String = responseToString(response) + assert(response.status === StatusCodes.BadRequest) + assert(result.contains("Invalid RestrictedViewSize: pct:0")) + } + + "return `Forbidden` for the user who is not a system nor project admin" in { + val shortcode = SharedTestDataADM.imagesProject.shortcode + val payload = """{"size":"pct:1"}""" + val request = + Post( + s"http://0.0.0.0:5555/admin/projects/shortcode/$shortcode/RestrictedViewSettings", + payload + ) ~> addCredentials( + BasicHttpCredentials(SharedTestDataADM.imagesUser02.email, testPass) + ) + val response: HttpResponse = singleAwaitingRequest(request) + assert(response.status === StatusCodes.Forbidden) + } + } } } diff --git a/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala b/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala index 678016436b..2fb747171b 100644 --- a/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala +++ b/webapi/src/main/scala/dsp/valueobjects/RestrictedViewSize.scala @@ -29,7 +29,7 @@ object RestrictedViewSize { if (value.isEmpty) Left(ErrorMessages.RestrictedViewSizeMissing) else if (percentagePattern.matches(trimmed)) Right(new RestrictedViewSize(trimmed) {}) else if (dimensionsPattern.matches(trimmed) && isSquare) Right(new RestrictedViewSize(trimmed) {}) - else Left(ErrorMessages.RestrictedViewSizeInvalid) + else Left(ErrorMessages.RestrictedViewSizeInvalid(value)) } def unsafeFrom(value: String): RestrictedViewSize = @@ -41,5 +41,5 @@ object RestrictedViewSize { object ErrorMessages { val RestrictedViewSizeMissing = "RestrictedViewSize cannot be empty." - val RestrictedViewSizeInvalid = "RestrictedViewSize is invalid." + val RestrictedViewSizeInvalid = (v: String) => s"Invalid RestrictedViewSize: $v" } 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 bf227ede52..ca786565fd 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 @@ -113,9 +113,7 @@ final case class KnoraProjectRepoLive( ): Task[Unit] = { val query = sparql.admin.txt .setProjectRestrictedViewSettings(project.id.value, size.value, None) - for { - _ <- triplestore.query(Update(query.toString)) - } yield () + triplestore.query(Update(query.toString)) } } diff --git a/webapi/src/test/scala/dsp/valueobjects/RestrictedViewSizeSpec.scala b/webapi/src/test/scala/dsp/valueobjects/RestrictedViewSizeSpec.scala index ee191494ba..3a84a27064 100644 --- a/webapi/src/test/scala/dsp/valueobjects/RestrictedViewSizeSpec.scala +++ b/webapi/src/test/scala/dsp/valueobjects/RestrictedViewSizeSpec.scala @@ -31,13 +31,13 @@ object RestrictedViewSizeSpec extends ZIOSpecDefault { val gen = Gen.int(-1000, -1) check(gen) { integer => val param = s"!$integer,$integer" - assertTrue(RestrictedViewSize.make(param).map(_.value) == Left(ErrorMessages.RestrictedViewSizeInvalid)) + assertTrue(RestrictedViewSize.make(param).map(_.value) == Left(ErrorMessages.RestrictedViewSizeInvalid(param))) } }, test("should fail on passing incorrect values") { val gen = Gen.fromIterable(Seq("!512,100", "pct:-1", "pct:0", "pct:101")) check(gen) { param => - assertTrue(RestrictedViewSize.make(param) == Left(ErrorMessages.RestrictedViewSizeInvalid)) + assertTrue(RestrictedViewSize.make(param) == Left(ErrorMessages.RestrictedViewSizeInvalid(param))) } }, test("should fail on passing empty value") { From c5243ad94a7f95652a266496a4d8a2fa160f0020 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Tue, 26 Sep 2023 11:55:19 +0200 Subject: [PATCH 39/51] fmt --- .../knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala b/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala index 2ed2496bd7..7aeed0a474 100644 --- a/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala @@ -5,7 +5,10 @@ package org.knora.webapi.e2e.admin -import akka.http.scaladsl.model.{ContentTypes, HttpEntity, HttpRequest, HttpResponse, StatusCodes} +import akka.http.scaladsl.model.ContentTypes +import akka.http.scaladsl.model.HttpEntity +import akka.http.scaladsl.model.HttpResponse +import akka.http.scaladsl.model.StatusCodes import akka.http.scaladsl.model.headers.BasicHttpCredentials import akka.http.scaladsl.unmarshalling.Unmarshal import akka.util.Timeout @@ -14,6 +17,7 @@ import java.net.URLEncoder import scala.concurrent.Await import scala.concurrent.Future import scala.concurrent.duration._ + import dsp.valueobjects.V2 import org.knora.webapi.E2ESpec import org.knora.webapi.IRI From b00ada288df5c72eb4a17cc70c0189080a1c819c Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Wed, 27 Sep 2023 09:23:45 +0200 Subject: [PATCH 40/51] place e2e test to separate file --- .../e2e/admin/ProjectsADME2EZioHttpSpec.scala | 87 ------------- .../e2e/admin/RestrictedViewSizeE2ESpec.scala | 114 ++++++++++++++++++ 2 files changed, 114 insertions(+), 87 deletions(-) create mode 100644 integration/src/test/scala/org/knora/webapi/e2e/admin/RestrictedViewSizeE2ESpec.scala diff --git a/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala b/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala index 7aeed0a474..9525d66cde 100644 --- a/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala @@ -774,92 +774,5 @@ class ProjectsADME2EZioHttpSpec extends E2ESpec with ProjectsADMJsonProtocol wit ) } } - - "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 payload = """{"size":"pct:1"}""" - val request = - Post(s"http://0.0.0.0:5555/admin/projects/iri/$encodedIri/RestrictedViewSettings", payload) ~> addCredentials( - BasicHttpCredentials(rootEmail, testPass) - ) - val response: HttpResponse = singleAwaitingRequest(request) - val result: String = responseToString(response) - assert(response.status === StatusCodes.OK) - assert(payload === result) - } - - "return the `BadRequest` if the size value is invalid" in { - val encodedIri = URLEncoder.encode(SharedTestDataADM.imagesProject.id, "utf-8") - val payload = """{"size":"pct:0"}""" - val request = - Post(s"http://0.0.0.0:5555/admin/projects/iri/$encodedIri/RestrictedViewSettings", payload) ~> addCredentials( - BasicHttpCredentials(rootEmail, testPass) - ) - val response: HttpResponse = singleAwaitingRequest(request) - val result: String = responseToString(response) - assert(response.status === StatusCodes.BadRequest) - assert(result.contains("Invalid RestrictedViewSize: pct:0")) - } - - "return `Forbidden` for the user who is not a system nor project admin" in { - val encodedIri = URLEncoder.encode(SharedTestDataADM.imagesProject.id, "utf-8") - val payload = """{"size":"pct:1"}""" - val request = - Post(s"http://0.0.0.0:5555/admin/projects/iri/$encodedIri/RestrictedViewSettings", payload) ~> addCredentials( - BasicHttpCredentials(SharedTestDataADM.imagesUser02.email, testPass) - ) - val response: HttpResponse = singleAwaitingRequest(request) - assert(response.status === StatusCodes.Forbidden) - } - } - - "used to set RestrictedViewSize by project Shortcode" should { - "return requested value to be set with 200 Response Status" in { - val shortcode = SharedTestDataADM.imagesProject.shortcode - val payload = """{"size":"pct:1"}""" - val request = - Post( - s"http://0.0.0.0:5555/admin/projects/shortcode/$shortcode/RestrictedViewSettings", - payload - ) ~> addCredentials( - BasicHttpCredentials(rootEmail, testPass) - ) - val response: HttpResponse = singleAwaitingRequest(request) - val result: String = responseToString(response) - assert(response.status === StatusCodes.OK) - assert(payload === result) - } - - "return the `BadRequest` if the size value is invalid" in { - val shortcode = SharedTestDataADM.imagesProject.shortcode - val payload = """{"size":"pct:0"}""" - val request = - Post( - s"http://0.0.0.0:5555/admin/projects/shortcode/$shortcode/RestrictedViewSettings", - payload - ) ~> addCredentials( - BasicHttpCredentials(rootEmail, testPass) - ) - val response: HttpResponse = singleAwaitingRequest(request) - val result: String = responseToString(response) - assert(response.status === StatusCodes.BadRequest) - assert(result.contains("Invalid RestrictedViewSize: pct:0")) - } - - "return `Forbidden` for the user who is not a system nor project admin" in { - val shortcode = SharedTestDataADM.imagesProject.shortcode - val payload = """{"size":"pct:1"}""" - val request = - Post( - s"http://0.0.0.0:5555/admin/projects/shortcode/$shortcode/RestrictedViewSettings", - payload - ) ~> addCredentials( - BasicHttpCredentials(SharedTestDataADM.imagesUser02.email, testPass) - ) - val response: HttpResponse = singleAwaitingRequest(request) - assert(response.status === StatusCodes.Forbidden) - } - } } } diff --git a/integration/src/test/scala/org/knora/webapi/e2e/admin/RestrictedViewSizeE2ESpec.scala b/integration/src/test/scala/org/knora/webapi/e2e/admin/RestrictedViewSizeE2ESpec.scala new file mode 100644 index 0000000000..da2a4b2c44 --- /dev/null +++ b/integration/src/test/scala/org/knora/webapi/e2e/admin/RestrictedViewSizeE2ESpec.scala @@ -0,0 +1,114 @@ +/* + * Copyright © 2021 - 2023 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.e2e.admin + +import akka.http.scaladsl.model.HttpResponse +import akka.http.scaladsl.model.StatusCodes +import akka.http.scaladsl.model.headers.BasicHttpCredentials + +import java.net.URLEncoder + +import org.knora.webapi.E2ESpec +import org.knora.webapi.sharedtestdata.SharedTestDataADM + +/** + * End-to-End (E2E) test specification for testing groups endpoint. + */ +class RestrictedViewSizeE2ESpec extends E2ESpec { + + private val rootEmail = SharedTestDataADM.rootUser.email + private val testPass = SharedTestDataADM.testPass + + s"The Projects Route 'admin/projects'" when { + + "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 payload = """{"size":"pct:1"}""" + val request = + Post(s"http://0.0.0.0:5555/admin/projects/iri/$encodedIri/RestrictedViewSettings", payload) ~> addCredentials( + BasicHttpCredentials(rootEmail, testPass) + ) + val response: HttpResponse = singleAwaitingRequest(request) + val result: String = responseToString(response) + assert(response.status === StatusCodes.OK) + assert(payload === result) + } + + "return the `BadRequest` if the size value is invalid" in { + val encodedIri = URLEncoder.encode(SharedTestDataADM.imagesProject.id, "utf-8") + val payload = """{"size":"pct:0"}""" + val request = + Post(s"http://0.0.0.0:5555/admin/projects/iri/$encodedIri/RestrictedViewSettings", payload) ~> addCredentials( + BasicHttpCredentials(rootEmail, testPass) + ) + val response: HttpResponse = singleAwaitingRequest(request) + val result: String = responseToString(response) + assert(response.status === StatusCodes.BadRequest) + assert(result.contains("Invalid RestrictedViewSize: pct:0")) + } + + "return `Forbidden` for the user who is not a system nor project admin" in { + val encodedIri = URLEncoder.encode(SharedTestDataADM.imagesProject.id, "utf-8") + val payload = """{"size":"pct:1"}""" + val request = + Post(s"http://0.0.0.0:5555/admin/projects/iri/$encodedIri/RestrictedViewSettings", payload) ~> addCredentials( + BasicHttpCredentials(SharedTestDataADM.imagesUser02.email, testPass) + ) + val response: HttpResponse = singleAwaitingRequest(request) + assert(response.status === StatusCodes.Forbidden) + } + } + + "used to set RestrictedViewSize by project Shortcode" should { + "return requested value to be set with 200 Response Status" in { + val shortcode = SharedTestDataADM.imagesProject.shortcode + val payload = """{"size":"pct:1"}""" + val request = + Post( + s"http://0.0.0.0:5555/admin/projects/shortcode/$shortcode/RestrictedViewSettings", + payload + ) ~> addCredentials( + BasicHttpCredentials(rootEmail, testPass) + ) + val response: HttpResponse = singleAwaitingRequest(request) + val result: String = responseToString(response) + assert(response.status === StatusCodes.OK) + assert(payload === result) + } + + "return the `BadRequest` if the size value is invalid" in { + val shortcode = SharedTestDataADM.imagesProject.shortcode + val payload = """{"size":"pct:0"}""" + val request = + Post( + s"http://0.0.0.0:5555/admin/projects/shortcode/$shortcode/RestrictedViewSettings", + payload + ) ~> addCredentials( + BasicHttpCredentials(rootEmail, testPass) + ) + val response: HttpResponse = singleAwaitingRequest(request) + val result: String = responseToString(response) + assert(response.status === StatusCodes.BadRequest) + assert(result.contains("Invalid RestrictedViewSize: pct:0")) + } + + "return `Forbidden` for the user who is not a system nor project admin" in { + val shortcode = SharedTestDataADM.imagesProject.shortcode + val payload = """{"size":"pct:1"}""" + val request = + Post( + s"http://0.0.0.0:5555/admin/projects/shortcode/$shortcode/RestrictedViewSettings", + payload + ) ~> addCredentials( + BasicHttpCredentials(SharedTestDataADM.imagesUser02.email, testPass) + ) + val response: HttpResponse = singleAwaitingRequest(request) + assert(response.status === StatusCodes.Forbidden) + } + } + } +} From 66c291529e9acf1ff6ee704e070b8d61c13aa7e7 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Wed, 27 Sep 2023 10:04:09 +0200 Subject: [PATCH 41/51] extend with ProjectsADMJsonProtocol --- .../knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala | 2 +- .../knora/webapi/e2e/admin/RestrictedViewSizeE2ESpec.scala | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala b/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala index 9525d66cde..9c9eb160e3 100644 --- a/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala @@ -37,7 +37,7 @@ import org.knora.webapi.util.MutableTestIri /** * End-to-End (E2E) test specification for testing groups endpoint. */ -class ProjectsADME2EZioHttpSpec extends E2ESpec with ProjectsADMJsonProtocol with TriplestoreJsonProtocol { +class ProjectsADME2EZioHttpSpec extends E2ESpec with ProjectsADMJsonProtocol { private val rootEmail = SharedTestDataADM.rootUser.email private val testPass = SharedTestDataADM.testPass diff --git a/integration/src/test/scala/org/knora/webapi/e2e/admin/RestrictedViewSizeE2ESpec.scala b/integration/src/test/scala/org/knora/webapi/e2e/admin/RestrictedViewSizeE2ESpec.scala index da2a4b2c44..37200e307c 100644 --- a/integration/src/test/scala/org/knora/webapi/e2e/admin/RestrictedViewSizeE2ESpec.scala +++ b/integration/src/test/scala/org/knora/webapi/e2e/admin/RestrictedViewSizeE2ESpec.scala @@ -10,14 +10,14 @@ import akka.http.scaladsl.model.StatusCodes import akka.http.scaladsl.model.headers.BasicHttpCredentials import java.net.URLEncoder - import org.knora.webapi.E2ESpec +import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectsADMJsonProtocol import org.knora.webapi.sharedtestdata.SharedTestDataADM /** * End-to-End (E2E) test specification for testing groups endpoint. */ -class RestrictedViewSizeE2ESpec extends E2ESpec { +class RestrictedViewSizeE2ESpec extends E2ESpec with ProjectsADMJsonProtocol { private val rootEmail = SharedTestDataADM.rootUser.email private val testPass = SharedTestDataADM.testPass From 362c9e576f62e488db5df04a571e4c42d7706083 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Wed, 27 Sep 2023 10:33:36 +0200 Subject: [PATCH 42/51] add HttpEntity to the requests --- .../e2e/admin/ProjectsADME2EZioHttpSpec.scala | 1 - .../e2e/admin/RestrictedViewSizeE2ESpec.scala | 25 +++++++++++++------ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala b/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala index 9c9eb160e3..f532a69d7d 100644 --- a/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala @@ -28,7 +28,6 @@ import org.knora.webapi.messages.admin.responder.projectsmessages._ import org.knora.webapi.messages.admin.responder.usersmessages.UserADM import org.knora.webapi.messages.admin.responder.usersmessages.UsersADMJsonProtocol._ import org.knora.webapi.messages.store.triplestoremessages.RdfDataObject -import org.knora.webapi.messages.store.triplestoremessages.TriplestoreJsonProtocol import org.knora.webapi.messages.util.rdf.RdfModel import org.knora.webapi.sharedtestdata.SharedTestDataADM import org.knora.webapi.util.AkkaHttpUtils diff --git a/integration/src/test/scala/org/knora/webapi/e2e/admin/RestrictedViewSizeE2ESpec.scala b/integration/src/test/scala/org/knora/webapi/e2e/admin/RestrictedViewSizeE2ESpec.scala index 37200e307c..1fd1dcb8a0 100644 --- a/integration/src/test/scala/org/knora/webapi/e2e/admin/RestrictedViewSizeE2ESpec.scala +++ b/integration/src/test/scala/org/knora/webapi/e2e/admin/RestrictedViewSizeE2ESpec.scala @@ -5,11 +5,14 @@ package org.knora.webapi.e2e.admin +import akka.http.scaladsl.model.ContentTypes +import akka.http.scaladsl.model.HttpEntity import akka.http.scaladsl.model.HttpResponse import akka.http.scaladsl.model.StatusCodes import akka.http.scaladsl.model.headers.BasicHttpCredentials import java.net.URLEncoder + import org.knora.webapi.E2ESpec import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectsADMJsonProtocol import org.knora.webapi.sharedtestdata.SharedTestDataADM @@ -23,13 +26,15 @@ class RestrictedViewSizeE2ESpec extends E2ESpec with ProjectsADMJsonProtocol { private val testPass = SharedTestDataADM.testPass s"The Projects Route 'admin/projects'" when { - "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 payload = """{"size":"pct:1"}""" val request = - Post(s"http://0.0.0.0:5555/admin/projects/iri/$encodedIri/RestrictedViewSettings", payload) ~> addCredentials( + Post( + s"http://0.0.0.0:5555/admin/projects/iri/$encodedIri/RestrictedViewSettings", + HttpEntity(ContentTypes.`application/json`, payload) + ) ~> addCredentials( BasicHttpCredentials(rootEmail, testPass) ) val response: HttpResponse = singleAwaitingRequest(request) @@ -42,7 +47,10 @@ class RestrictedViewSizeE2ESpec extends E2ESpec with ProjectsADMJsonProtocol { val encodedIri = URLEncoder.encode(SharedTestDataADM.imagesProject.id, "utf-8") val payload = """{"size":"pct:0"}""" val request = - Post(s"http://0.0.0.0:5555/admin/projects/iri/$encodedIri/RestrictedViewSettings", payload) ~> addCredentials( + Post( + s"http://0.0.0.0:5555/admin/projects/iri/$encodedIri/RestrictedViewSettings", + HttpEntity(ContentTypes.`application/json`, payload) + ) ~> addCredentials( BasicHttpCredentials(rootEmail, testPass) ) val response: HttpResponse = singleAwaitingRequest(request) @@ -55,7 +63,10 @@ class RestrictedViewSizeE2ESpec extends E2ESpec with ProjectsADMJsonProtocol { val encodedIri = URLEncoder.encode(SharedTestDataADM.imagesProject.id, "utf-8") val payload = """{"size":"pct:1"}""" val request = - Post(s"http://0.0.0.0:5555/admin/projects/iri/$encodedIri/RestrictedViewSettings", payload) ~> addCredentials( + Post( + s"http://0.0.0.0:5555/admin/projects/iri/$encodedIri/RestrictedViewSettings", + HttpEntity(ContentTypes.`application/json`, payload) + ) ~> addCredentials( BasicHttpCredentials(SharedTestDataADM.imagesUser02.email, testPass) ) val response: HttpResponse = singleAwaitingRequest(request) @@ -70,7 +81,7 @@ class RestrictedViewSizeE2ESpec extends E2ESpec with ProjectsADMJsonProtocol { val request = Post( s"http://0.0.0.0:5555/admin/projects/shortcode/$shortcode/RestrictedViewSettings", - payload + HttpEntity(ContentTypes.`application/json`, payload) ) ~> addCredentials( BasicHttpCredentials(rootEmail, testPass) ) @@ -86,7 +97,7 @@ class RestrictedViewSizeE2ESpec extends E2ESpec with ProjectsADMJsonProtocol { val request = Post( s"http://0.0.0.0:5555/admin/projects/shortcode/$shortcode/RestrictedViewSettings", - payload + HttpEntity(ContentTypes.`application/json`, payload) ) ~> addCredentials( BasicHttpCredentials(rootEmail, testPass) ) @@ -102,7 +113,7 @@ class RestrictedViewSizeE2ESpec extends E2ESpec with ProjectsADMJsonProtocol { val request = Post( s"http://0.0.0.0:5555/admin/projects/shortcode/$shortcode/RestrictedViewSettings", - payload + HttpEntity(ContentTypes.`application/json`, payload) ) ~> addCredentials( BasicHttpCredentials(SharedTestDataADM.imagesUser02.email, testPass) ) From d976806b6baa38aac6b314959431c8cbe8117e4a Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Wed, 27 Sep 2023 13:32:09 +0200 Subject: [PATCH 43/51] add condition on tests --- .../e2e/admin/ProjectsADME2EZioHttpSpec.scala | 98 ++++++++++++++ .../e2e/admin/RestrictedViewSizeE2ESpec.scala | 125 ------------------ 2 files changed, 98 insertions(+), 125 deletions(-) delete mode 100644 integration/src/test/scala/org/knora/webapi/e2e/admin/RestrictedViewSizeE2ESpec.scala diff --git a/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala b/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala index f532a69d7d..78ddf26a84 100644 --- a/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2EZioHttpSpec.scala @@ -773,5 +773,103 @@ class ProjectsADME2EZioHttpSpec extends E2ESpec with ProjectsADMJsonProtocol { ) } } + + if (baseApiUrl.contains("5555")) "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 payload = """{"size":"pct:1"}""" + val request = + Post( + baseApiUrl + s"/admin/projects/iri/$encodedIri/RestrictedViewSettings", + HttpEntity(ContentTypes.`application/json`, payload) + ) ~> addCredentials( + BasicHttpCredentials(rootEmail, testPass) + ) + val response: HttpResponse = singleAwaitingRequest(request) + val result: String = responseToString(response) + assert(response.status === StatusCodes.OK) + assert(payload === result) + } + + "return the `BadRequest` if the size value is invalid" in { + val encodedIri = URLEncoder.encode(SharedTestDataADM.imagesProject.id, "utf-8") + val payload = """{"size":"pct:0"}""" + val request = + Post( + baseApiUrl + s"/admin/projects/iri/$encodedIri/RestrictedViewSettings", + HttpEntity(ContentTypes.`application/json`, payload) + ) ~> addCredentials( + BasicHttpCredentials(rootEmail, testPass) + ) + val response: HttpResponse = singleAwaitingRequest(request) + val result: String = responseToString(response) + assert(response.status === StatusCodes.BadRequest) + assert(result.contains("Invalid RestrictedViewSize: pct:0")) + } + + "return `Forbidden` for the user who is not a system nor project admin" in { + val encodedIri = URLEncoder.encode(SharedTestDataADM.imagesProject.id, "utf-8") + val payload = """{"size":"pct:1"}""" + val request = + Post( + baseApiUrl + s"/admin/projects/iri/$encodedIri/RestrictedViewSettings", + HttpEntity(ContentTypes.`application/json`, payload) + ) ~> addCredentials( + BasicHttpCredentials(SharedTestDataADM.imagesUser02.email, testPass) + ) + val response: HttpResponse = singleAwaitingRequest(request) + assert(response.status === StatusCodes.Forbidden) + } + } + else "used to set RestrictedViewSize by project IRI" ignore () + + if (baseApiUrl.contains("5555")) "used to set RestrictedViewSize by project Shortcode" should { + "return requested value to be set with 200 Response Status" in { + val shortcode = SharedTestDataADM.imagesProject.shortcode + val payload = """{"size":"pct:1"}""" + val request = + Post( + baseApiUrl + s"/admin/projects/shortcode/$shortcode/RestrictedViewSettings", + HttpEntity(ContentTypes.`application/json`, payload) + ) ~> addCredentials( + BasicHttpCredentials(rootEmail, testPass) + ) + val response: HttpResponse = singleAwaitingRequest(request) + val result: String = responseToString(response) + assert(response.status === StatusCodes.OK) + assert(payload === result) + } + + "return the `BadRequest` if the size value is invalid" in { + val shortcode = SharedTestDataADM.imagesProject.shortcode + val payload = """{"size":"pct:0"}""" + val request = + Post( + baseApiUrl + s"/admin/projects/shortcode/$shortcode/RestrictedViewSettings", + HttpEntity(ContentTypes.`application/json`, payload) + ) ~> addCredentials( + BasicHttpCredentials(rootEmail, testPass) + ) + val response: HttpResponse = singleAwaitingRequest(request) + val result: String = responseToString(response) + assert(response.status === StatusCodes.BadRequest) + assert(result.contains("Invalid RestrictedViewSize: pct:0")) + } + + "return `Forbidden` for the user who is not a system nor project admin" in { + val shortcode = SharedTestDataADM.imagesProject.shortcode + val payload = """{"size":"pct:1"}""" + val request = + Post( + baseApiUrl + s"/admin/projects/shortcode/$shortcode/RestrictedViewSettings", + HttpEntity(ContentTypes.`application/json`, payload) + ) ~> addCredentials( + BasicHttpCredentials(SharedTestDataADM.imagesUser02.email, testPass) + ) + val response: HttpResponse = singleAwaitingRequest(request) + assert(response.status === StatusCodes.Forbidden) + } + } + else "used to set RestrictedViewSize by project Shortcode" ignore () } } diff --git a/integration/src/test/scala/org/knora/webapi/e2e/admin/RestrictedViewSizeE2ESpec.scala b/integration/src/test/scala/org/knora/webapi/e2e/admin/RestrictedViewSizeE2ESpec.scala deleted file mode 100644 index 1fd1dcb8a0..0000000000 --- a/integration/src/test/scala/org/knora/webapi/e2e/admin/RestrictedViewSizeE2ESpec.scala +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright © 2021 - 2023 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.e2e.admin - -import akka.http.scaladsl.model.ContentTypes -import akka.http.scaladsl.model.HttpEntity -import akka.http.scaladsl.model.HttpResponse -import akka.http.scaladsl.model.StatusCodes -import akka.http.scaladsl.model.headers.BasicHttpCredentials - -import java.net.URLEncoder - -import org.knora.webapi.E2ESpec -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectsADMJsonProtocol -import org.knora.webapi.sharedtestdata.SharedTestDataADM - -/** - * End-to-End (E2E) test specification for testing groups endpoint. - */ -class RestrictedViewSizeE2ESpec extends E2ESpec with ProjectsADMJsonProtocol { - - private val rootEmail = SharedTestDataADM.rootUser.email - private val testPass = SharedTestDataADM.testPass - - s"The Projects Route 'admin/projects'" when { - "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 payload = """{"size":"pct:1"}""" - val request = - Post( - s"http://0.0.0.0:5555/admin/projects/iri/$encodedIri/RestrictedViewSettings", - HttpEntity(ContentTypes.`application/json`, payload) - ) ~> addCredentials( - BasicHttpCredentials(rootEmail, testPass) - ) - val response: HttpResponse = singleAwaitingRequest(request) - val result: String = responseToString(response) - assert(response.status === StatusCodes.OK) - assert(payload === result) - } - - "return the `BadRequest` if the size value is invalid" in { - val encodedIri = URLEncoder.encode(SharedTestDataADM.imagesProject.id, "utf-8") - val payload = """{"size":"pct:0"}""" - val request = - Post( - s"http://0.0.0.0:5555/admin/projects/iri/$encodedIri/RestrictedViewSettings", - HttpEntity(ContentTypes.`application/json`, payload) - ) ~> addCredentials( - BasicHttpCredentials(rootEmail, testPass) - ) - val response: HttpResponse = singleAwaitingRequest(request) - val result: String = responseToString(response) - assert(response.status === StatusCodes.BadRequest) - assert(result.contains("Invalid RestrictedViewSize: pct:0")) - } - - "return `Forbidden` for the user who is not a system nor project admin" in { - val encodedIri = URLEncoder.encode(SharedTestDataADM.imagesProject.id, "utf-8") - val payload = """{"size":"pct:1"}""" - val request = - Post( - s"http://0.0.0.0:5555/admin/projects/iri/$encodedIri/RestrictedViewSettings", - HttpEntity(ContentTypes.`application/json`, payload) - ) ~> addCredentials( - BasicHttpCredentials(SharedTestDataADM.imagesUser02.email, testPass) - ) - val response: HttpResponse = singleAwaitingRequest(request) - assert(response.status === StatusCodes.Forbidden) - } - } - - "used to set RestrictedViewSize by project Shortcode" should { - "return requested value to be set with 200 Response Status" in { - val shortcode = SharedTestDataADM.imagesProject.shortcode - val payload = """{"size":"pct:1"}""" - val request = - Post( - s"http://0.0.0.0:5555/admin/projects/shortcode/$shortcode/RestrictedViewSettings", - HttpEntity(ContentTypes.`application/json`, payload) - ) ~> addCredentials( - BasicHttpCredentials(rootEmail, testPass) - ) - val response: HttpResponse = singleAwaitingRequest(request) - val result: String = responseToString(response) - assert(response.status === StatusCodes.OK) - assert(payload === result) - } - - "return the `BadRequest` if the size value is invalid" in { - val shortcode = SharedTestDataADM.imagesProject.shortcode - val payload = """{"size":"pct:0"}""" - val request = - Post( - s"http://0.0.0.0:5555/admin/projects/shortcode/$shortcode/RestrictedViewSettings", - HttpEntity(ContentTypes.`application/json`, payload) - ) ~> addCredentials( - BasicHttpCredentials(rootEmail, testPass) - ) - val response: HttpResponse = singleAwaitingRequest(request) - val result: String = responseToString(response) - assert(response.status === StatusCodes.BadRequest) - assert(result.contains("Invalid RestrictedViewSize: pct:0")) - } - - "return `Forbidden` for the user who is not a system nor project admin" in { - val shortcode = SharedTestDataADM.imagesProject.shortcode - val payload = """{"size":"pct:1"}""" - val request = - Post( - s"http://0.0.0.0:5555/admin/projects/shortcode/$shortcode/RestrictedViewSettings", - HttpEntity(ContentTypes.`application/json`, payload) - ) ~> addCredentials( - BasicHttpCredentials(SharedTestDataADM.imagesUser02.email, testPass) - ) - val response: HttpResponse = singleAwaitingRequest(request) - assert(response.status === StatusCodes.Forbidden) - } - } - } -} From c2de3fb3f0340e387bced7411dc644c08bee2fd2 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Thu, 28 Sep 2023 10:06:22 +0200 Subject: [PATCH 44/51] jsonc tpo json --- docs/03-endpoints/api-admin/projects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/03-endpoints/api-admin/projects.md b/docs/03-endpoints/api-admin/projects.md index d03f61ead0..d0ab0867e0 100644 --- a/docs/03-endpoints/api-admin/projects.md +++ b/docs/03-endpoints/api-admin/projects.md @@ -852,7 +852,7 @@ curl --request POST 'http://0.0.0.0:5555/admin/projects/shortcode/0001/Restricte Example response: -```jsonc +```json { "size": "!512,512" } From b95d3c70976b1c3d3fddb1424dba5cf7eef7bac2 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Thu, 28 Sep 2023 10:12:16 +0200 Subject: [PATCH 45/51] bring back ProjectRestrictedViewSettingsGetResponseADM name --- .../projectsmessages/ProjectsMessagesADM.scala | 8 ++++---- .../responders/admin/ProjectsResponderADM.scala | 10 +++++----- .../admin/api/service/ProjectsADMRestService.scala | 8 ++++---- .../responders/admin/ProjectADMRestServiceMock.scala | 4 ++-- .../responders/admin/ProjectsResponderADMMock.scala | 4 ++-- .../responders/admin/ProjectsServiceLiveSpec.scala | 6 +++--- .../webapi/routing/admin/ProjectsRouteZSpec.scala | 12 ++++++------ 7 files changed, 26 insertions(+), 26 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala index d8f331e3e5..91fdf72e5a 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala @@ -240,7 +240,7 @@ case class ProjectRestrictedViewSettingsGetADM( ) extends ProjectsResponderRequestADM /** - * Return project's RestrictedView settings. A successful response will be a [[ProjectRestrictedViewSettingsResponseADM]]. + * Return project's RestrictedView settings. A successful response will be a [[ProjectRestrictedViewSettingsGetResponseADM]]. * * @param identifier the identifier of the project. */ @@ -341,7 +341,7 @@ case class ProjectKeywordsGetResponseADM(keywords: Seq[String]) extends KnoraRes * * @param settings the restricted view settings. */ -case class ProjectRestrictedViewSettingsResponseADM(settings: ProjectRestrictedViewSettingsADM) +case class ProjectRestrictedViewSettingsGetResponseADM(settings: ProjectRestrictedViewSettingsADM) extends KnoraResponseADM with ProjectsADMJsonProtocol { def toJsValue: JsValue = projectRestrictedViewGetResponseADMFormat.write(this) @@ -611,8 +611,8 @@ trait ProjectsADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol jsonFormat(ProjectsKeywordsGetResponseADM, "keywords") implicit val projectKeywordsGetResponseADMFormat: RootJsonFormat[ProjectKeywordsGetResponseADM] = jsonFormat(ProjectKeywordsGetResponseADM, "keywords") - implicit val projectRestrictedViewGetResponseADMFormat: RootJsonFormat[ProjectRestrictedViewSettingsResponseADM] = - jsonFormat(ProjectRestrictedViewSettingsResponseADM, "settings") + implicit val projectRestrictedViewGetResponseADMFormat: RootJsonFormat[ProjectRestrictedViewSettingsGetResponseADM] = + jsonFormat(ProjectRestrictedViewSettingsGetResponseADM, "settings") implicit val projectOperationResponseADMFormat: RootJsonFormat[ProjectOperationResponseADM] = rootFormat( lazyFormat(jsonFormat(ProjectOperationResponseADM, "project")) ) diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala index f3f87fc843..0abfaf1121 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala @@ -123,11 +123,11 @@ trait ProjectsResponderADM { * Get project's restricted view settings. * * @param id the project's identifier (IRI / shortcode / shortname) - * @return [[ProjectRestrictedViewSettingsResponseADM]] + * @return [[ProjectRestrictedViewSettingsGetResponseADM]] */ def projectRestrictedViewSettingsGetRequestADM( id: ProjectIdentifierADM - ): Task[ProjectRestrictedViewSettingsResponseADM] + ): Task[ProjectRestrictedViewSettingsGetResponseADM] /** * Creates a project. @@ -438,16 +438,16 @@ final case class ProjectsResponderADMLive( * * @param id the project's identifier (IRI / shortcode / shortname / UUID) * - * @return [[ProjectRestrictedViewSettingsResponseADM]] + * @return [[ProjectRestrictedViewSettingsGetResponseADM]] */ override def projectRestrictedViewSettingsGetRequestADM( id: ProjectIdentifierADM - ): Task[ProjectRestrictedViewSettingsResponseADM] = + ): Task[ProjectRestrictedViewSettingsGetResponseADM] = projectRestrictedViewSettingsGetADM(id) .flatMap(ZIO.fromOption(_)) .mapBoth( _ => NotFoundException(s"Project '${getId(id)}' not found."), - ProjectRestrictedViewSettingsResponseADM + ProjectRestrictedViewSettingsGetResponseADM ) /** diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala index bac551fbe4..a8405ff8f2 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala @@ -63,7 +63,7 @@ trait ProjectADMRestService { ): Task[ProjectKeywordsGetResponseADM] def getProjectRestrictedViewSettings( identifier: ProjectIdentifierADM - ): Task[ProjectRestrictedViewSettingsResponseADM] + ): Task[ProjectRestrictedViewSettingsGetResponseADM] def setProjectRestrictedViewSettings( id: ProjectIdentifierADM, user: UserADM, @@ -240,11 +240,11 @@ final case class ProjectsADMRestServiceLive( * * @param id the [[ProjectIdentifierADM]] of the project * @return - * '''success''': the restricted view settings as [[ProjectRestrictedViewSettingsResponseADM]] + * '''success''': the restricted view settings as [[ProjectRestrictedViewSettingsGetResponseADM]] * * '''failure''': [[dsp.errors.NotFoundException]] when no project for the given [[ProjectIri]] can be found */ - def getProjectRestrictedViewSettings(id: ProjectIdentifierADM): Task[ProjectRestrictedViewSettingsResponseADM] = + def getProjectRestrictedViewSettings(id: ProjectIdentifierADM): Task[ProjectRestrictedViewSettingsGetResponseADM] = responder.projectRestrictedViewSettingsGetRequestADM(id) /** @@ -253,7 +253,7 @@ final case class ProjectsADMRestServiceLive( * @param id the project's id represented by iri, shortocde or shortname, * @param user requesting user, * @param size value to be set, - * @return [[ProjectRestrictedViewSettingsResponseADM]]. + * @return [[ProjectRestrictedViewSizeResponseADM]]. */ override def setProjectRestrictedViewSettings( id: ProjectIdentifierADM, diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala index 9ac618a5c0..2a202abc02 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectADMRestServiceMock.scala @@ -32,7 +32,7 @@ object ProjectADMRestServiceMock extends Mock[ProjectADMRestService] { object GetKeywords extends Effect[Unit, Throwable, ProjectsKeywordsGetResponseADM] object GetKeywordsByProjectIri extends Effect[ProjectIri, Throwable, ProjectKeywordsGetResponseADM] object GetRestrictedViewSettings - extends Effect[ProjectIdentifierADM, Throwable, ProjectRestrictedViewSettingsResponseADM] + extends Effect[ProjectIdentifierADM, Throwable, ProjectRestrictedViewSettingsGetResponseADM] override val compose: URLayer[Proxy, ProjectADMRestService] = ZLayer { @@ -90,7 +90,7 @@ object ProjectADMRestServiceMock extends Mock[ProjectADMRestService] { def getProjectRestrictedViewSettings( identifier: ProjectIdentifierADM - ): Task[ProjectRestrictedViewSettingsResponseADM] = + ): Task[ProjectRestrictedViewSettingsGetResponseADM] = proxy(GetRestrictedViewSettings, identifier) override def exportProject(projectIri: IRI, requestingUser: UserADM): Task[Unit] = ??? diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala index d7c29edd4e..b425279898 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMMock.scala @@ -33,7 +33,7 @@ object ProjectsResponderADMMock extends Mock[ProjectsResponderADM] { object ProjectRestrictedViewSettingsGetADM extends Effect[ProjectIdentifierADM, Throwable, Option[ProjectRestrictedViewSettingsADM]] object ProjectRestrictedViewSettingsGetRequestADM - extends Effect[ProjectIdentifierADM, Throwable, ProjectRestrictedViewSettingsResponseADM] + extends Effect[ProjectIdentifierADM, Throwable, ProjectRestrictedViewSettingsGetResponseADM] object ProjectCreateRequestADM extends Effect[(ProjectCreatePayloadADM, UserADM, UUID), Throwable, ProjectOperationResponseADM] object ChangeBasicInformationRequestADM @@ -70,7 +70,7 @@ object ProjectsResponderADMMock extends Mock[ProjectsResponderADM] { proxy(ProjectRestrictedViewSettingsGetADM, id) override def projectRestrictedViewSettingsGetRequestADM( id: ProjectIdentifierADM - ): Task[ProjectRestrictedViewSettingsResponseADM] = + ): Task[ProjectRestrictedViewSettingsGetResponseADM] = proxy(ProjectRestrictedViewSettingsGetRequestADM, id) override def projectCreateRequestADM( createPayload: ProjectCreatePayloadADM, diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsServiceLiveSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsServiceLiveSpec.scala index 57397fa48c..c2ae32e209 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsServiceLiveSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsServiceLiveSpec.scala @@ -300,7 +300,7 @@ object ProjectsServiceLiveSpec extends ZIOSpecDefault { val settings = ProjectRestrictedViewSettingsADM(Some("!512,512"), Some("path_to_image")) val mockResponder = ProjectsResponderADMMock.ProjectRestrictedViewSettingsGetRequestADM( assertion = Assertion.equalTo(identifier), - result = Expectation.value(ProjectRestrictedViewSettingsResponseADM(settings)) + result = Expectation.value(ProjectRestrictedViewSettingsGetResponseADM(settings)) ) for { _ <- ProjectADMRestService @@ -314,7 +314,7 @@ object ProjectsServiceLiveSpec extends ZIOSpecDefault { val settings = ProjectRestrictedViewSettingsADM(Some("!512,512"), Some("path_to_image")) val mockResponder = ProjectsResponderADMMock.ProjectRestrictedViewSettingsGetRequestADM( assertion = Assertion.equalTo(identifier), - result = Expectation.value(ProjectRestrictedViewSettingsResponseADM(settings)) + result = Expectation.value(ProjectRestrictedViewSettingsGetResponseADM(settings)) ) for { _ <- ProjectADMRestService @@ -328,7 +328,7 @@ object ProjectsServiceLiveSpec extends ZIOSpecDefault { val settings = ProjectRestrictedViewSettingsADM(Some("!512,512"), Some("path_to_image")) val mockResponder = ProjectsResponderADMMock.ProjectRestrictedViewSettingsGetRequestADM( assertion = Assertion.equalTo(identifier), - result = Expectation.value(ProjectRestrictedViewSettingsResponseADM(settings)) + result = Expectation.value(ProjectRestrictedViewSettingsGetResponseADM(settings)) ) for { _ <- ProjectADMRestService diff --git a/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala b/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala index 0cee41b7d2..162ee80bc2 100644 --- a/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/routing/admin/ProjectsRouteZSpec.scala @@ -669,8 +669,8 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { val mockService: ULayer[ProjectADMRestService] = ProjectADMRestServiceMock .GetRestrictedViewSettings( assertion = Assertion.equalTo(identifier), - result = Expectation.valueF[ProjectIdentifierADM, ProjectRestrictedViewSettingsResponseADM](_ => - ProjectRestrictedViewSettingsResponseADM(settings) + result = Expectation.valueF[ProjectIdentifierADM, ProjectRestrictedViewSettingsGetResponseADM](_ => + ProjectRestrictedViewSettingsGetResponseADM(settings) ) ) .toLayer @@ -699,8 +699,8 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { val mockService: ULayer[ProjectADMRestService] = ProjectADMRestServiceMock .GetRestrictedViewSettings( assertion = Assertion.equalTo(identifier), - result = Expectation.valueF[ProjectIdentifierADM, ProjectRestrictedViewSettingsResponseADM](_ => - ProjectRestrictedViewSettingsResponseADM(settings) + result = Expectation.valueF[ProjectIdentifierADM, ProjectRestrictedViewSettingsGetResponseADM](_ => + ProjectRestrictedViewSettingsGetResponseADM(settings) ) ) .toLayer @@ -729,8 +729,8 @@ object ProjectsRouteZSpec extends ZIOSpecDefault { val mockService: ULayer[ProjectADMRestService] = ProjectADMRestServiceMock .GetRestrictedViewSettings( assertion = Assertion.equalTo(identifier), - result = Expectation.valueF[ProjectIdentifierADM, ProjectRestrictedViewSettingsResponseADM](_ => - ProjectRestrictedViewSettingsResponseADM(settings) + result = Expectation.valueF[ProjectIdentifierADM, ProjectRestrictedViewSettingsGetResponseADM](_ => + ProjectRestrictedViewSettingsGetResponseADM(settings) ) ) .toLayer From f373059e993dae71f357e3bb3411bb4e08533627 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Thu, 28 Sep 2023 10:13:21 +0200 Subject: [PATCH 46/51] remove unused dependency --- .../slice/admin/api/service/ProjectsADMRestService.scala | 3 --- 1 file changed, 3 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala index a8405ff8f2..d19769cf5d 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/ProjectsADMRestService.scala @@ -25,7 +25,6 @@ import org.knora.webapi.slice.admin.domain.service.KnoraProjectRepo import org.knora.webapi.slice.admin.domain.service.ProjectExportService import org.knora.webapi.slice.admin.domain.service.ProjectImportService import org.knora.webapi.slice.common.api.RestPermissionService -import org.knora.webapi.store.triplestore.api.TriplestoreService @accessible trait ProjectADMRestService { @@ -72,7 +71,6 @@ trait ProjectADMRestService { } final case class ProjectsADMRestServiceLive( - triplestore: TriplestoreService, responder: ProjectsResponderADM, projectRepo: KnoraProjectRepo, projectExportService: ProjectExportService, @@ -300,7 +298,6 @@ final case class ProjectsADMRestServiceLive( object ProjectsADMRestServiceLive { val layer: URLayer[ ProjectsResponderADM - with TriplestoreService with KnoraProjectRepo with ProjectExportService with ProjectImportService From 79bb03164b85c504078bda7a5a9938efaadc40c9 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Thu, 28 Sep 2023 10:53:16 +0200 Subject: [PATCH 47/51] extract route method --- .../webapi/routing/admin/ProjectsRouteZ.scala | 36 ++++++++----------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala index ef71baf157..14b90ded4b 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala @@ -246,31 +246,23 @@ final case class ProjectsRouteZ( r <- projectsService.getProjectRestrictedViewSettings(shortcodeIdentifier) } yield Response.json(r.toJsValue.toString) - private def setProjectRestrictedViewSizeByIri( - iri: String, - body: Body, - user: UserADM - ): Task[Response] = + private def setProjectRestrictedViewSizeByIri(iri: IRI, body: Body, user: UserADM): Task[Response] = for { iriDecoded <- RouteUtilZ.urlDecode(iri, s"Failed to URL decode IRI parameter $iri.") - id <- IriIdentifier.fromString(iriDecoded).toZIO.mapError(e => BadRequestException(e.msg)) - body <- body.asString - payload <- ZIO.fromEither(body.fromJson[ProjectSetRestrictedViewSizePayload]).mapError(BadRequestException(_)) - size <- ZIO.fromEither(RestrictedViewSize.make(payload.size)).mapError(BadRequestException(_)) - response <- projectsService.setProjectRestrictedViewSettings(id, user, size) - } yield Response.json(response.toJson) + result <- handleRestrictedViewSizeRequest(iriDecoded, body, user) + } yield result + + private def setProjectRestrictedViewSizeByShortcode(shortcode: String, body: Body, user: UserADM): Task[Response] = + handleRestrictedViewSizeRequest(shortcode, body, user) - private def setProjectRestrictedViewSizeByShortcode( - shortcode: String, - body: Body, - user: UserADM - ): Task[Response] = for { - id <- ShortcodeIdentifier.fromString(shortcode).toZIO.mapError(e => BadRequestException(e.msg)) - body <- body.asString - payload <- ZIO.fromEither(body.fromJson[ProjectSetRestrictedViewSizePayload]).mapError(BadRequestException(_)) - size <- ZIO.fromEither(RestrictedViewSize.make(payload.size)).mapError(BadRequestException(_)) - response <- projectsService.setProjectRestrictedViewSettings(id, user, size) - } yield Response.json(response.toJson) + private def handleRestrictedViewSizeRequest(shortcode: String, body: Body, user: UserADM) = + for { + id <- ShortcodeIdentifier.fromString(shortcode).toZIO.mapError(e => BadRequestException(e.msg)) + body <- body.asString + payload <- ZIO.fromEither(body.fromJson[ProjectSetRestrictedViewSizePayload]).mapError(BadRequestException(_)) + size <- ZIO.fromEither(RestrictedViewSize.make(payload.size)).mapError(BadRequestException(_)) + response <- projectsService.setProjectRestrictedViewSettings(id, user, size) + } yield Response.json(response.toJson) } object ProjectsRouteZ { From b57e6e814f99af16ebd057e65bb0630404578797 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Thu, 28 Sep 2023 11:59:16 +0200 Subject: [PATCH 48/51] fix extracted method --- .../webapi/routing/admin/ProjectsRouteZ.scala | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala index 14b90ded4b..615e305974 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala @@ -12,17 +12,19 @@ import zio.json._ import zio.stream.ZStream import java.nio.file.Files - import dsp.errors.BadRequestException import dsp.valueobjects.Iri._ import dsp.valueobjects.RestrictedViewSize import org.knora.webapi.config.AppConfig import org.knora.webapi.http.handler.ExceptionHandlerZ import org.knora.webapi.http.middleware.AuthenticationMiddleware -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectCreatePayloadADM +import org.knora.webapi.messages.admin.responder.projectsmessages.{ + ProjectCreatePayloadADM, + ProjectIdentifierADM, + ProjectSetRestrictedViewSizePayload, + ProjectUpdatePayloadADM +} import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM._ -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectSetRestrictedViewSizePayload -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectUpdatePayloadADM import org.knora.webapi.messages.admin.responder.usersmessages.UserADM import org.knora.webapi.routing.RouteUtilZ import org.knora.webapi.slice.admin.api.service.ProjectADMRestService @@ -249,15 +251,18 @@ final case class ProjectsRouteZ( private def setProjectRestrictedViewSizeByIri(iri: IRI, body: Body, user: UserADM): Task[Response] = for { iriDecoded <- RouteUtilZ.urlDecode(iri, s"Failed to URL decode IRI parameter $iri.") - result <- handleRestrictedViewSizeRequest(iriDecoded, body, user) + id <- IriIdentifier.fromString(iriDecoded).toZIO.mapError(e => BadRequestException(e.msg)) + result <- handleRestrictedViewSizeRequest(id, body, user) } yield result private def setProjectRestrictedViewSizeByShortcode(shortcode: String, body: Body, user: UserADM): Task[Response] = - handleRestrictedViewSizeRequest(shortcode, body, user) + for { + id <- ShortcodeIdentifier.fromString(shortcode).toZIO.mapError(e => BadRequestException(e.msg)) + result <- handleRestrictedViewSizeRequest(id, body, user) + } yield result - private def handleRestrictedViewSizeRequest(shortcode: String, body: Body, user: UserADM) = + private def handleRestrictedViewSizeRequest(id: ProjectIdentifierADM, body: Body, user: UserADM) = for { - id <- ShortcodeIdentifier.fromString(shortcode).toZIO.mapError(e => BadRequestException(e.msg)) body <- body.asString payload <- ZIO.fromEither(body.fromJson[ProjectSetRestrictedViewSizePayload]).mapError(BadRequestException(_)) size <- ZIO.fromEither(RestrictedViewSize.make(payload.size)).mapError(BadRequestException(_)) From 69b5b4661605d6cc905a6c21360bb6ca272f7e6d Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Thu, 28 Sep 2023 12:29:41 +0200 Subject: [PATCH 49/51] remove watermark field from twirl template --- .../webapi/routing/admin/ProjectsRouteZ.scala | 11 +++++------ .../repo/service/KnoraProjectRepoLive.scala | 2 +- .../setProjectRestrictedViewSettings.scala.txt | 16 +--------------- 3 files changed, 7 insertions(+), 22 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala index 615e305974..eca18d3243 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteZ.scala @@ -12,19 +12,18 @@ import zio.json._ import zio.stream.ZStream import java.nio.file.Files + import dsp.errors.BadRequestException import dsp.valueobjects.Iri._ import dsp.valueobjects.RestrictedViewSize import org.knora.webapi.config.AppConfig import org.knora.webapi.http.handler.ExceptionHandlerZ import org.knora.webapi.http.middleware.AuthenticationMiddleware -import org.knora.webapi.messages.admin.responder.projectsmessages.{ - ProjectCreatePayloadADM, - ProjectIdentifierADM, - ProjectSetRestrictedViewSizePayload, - ProjectUpdatePayloadADM -} +import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectCreatePayloadADM +import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM._ +import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectSetRestrictedViewSizePayload +import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectUpdatePayloadADM import org.knora.webapi.messages.admin.responder.usersmessages.UserADM import org.knora.webapi.routing.RouteUtilZ import org.knora.webapi.slice.admin.api.service.ProjectADMRestService 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 ca786565fd..187c055085 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 @@ -112,7 +112,7 @@ final case class KnoraProjectRepoLive( size: RestrictedViewSize ): Task[Unit] = { val query = sparql.admin.txt - .setProjectRestrictedViewSettings(project.id.value, size.value, None) + .setProjectRestrictedViewSettings(project.id.value, size.value) triplestore.query(Update(query.toString)) } } diff --git a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/setProjectRestrictedViewSettings.scala.txt b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/setProjectRestrictedViewSettings.scala.txt index 4b122da5d9..ec499c6a93 100644 --- a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/setProjectRestrictedViewSettings.scala.txt +++ b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/setProjectRestrictedViewSettings.scala.txt @@ -11,12 +11,10 @@ * * @param iri project's IRI. * @param size project's restricted view size. - * @param watermark project's watermark. * *@ @(iri: IRI, - size: String, - watermark: Option[String]) + size: String) PREFIX rdf: PREFIX xsd: @@ -25,25 +23,13 @@ PREFIX knora-admin: WITH DELETE { <@iri> knora-admin:projectRestrictedViewSize ?prevSize . - - @if(watermark.nonEmpty) { - <@iri> knora-admin:projectRestrictedViewWatermark ?prevWatermark . - } } INSERT { <@iri> knora-admin:projectRestrictedViewSize "@size"^^xsd:string . - - @if(watermark.nonEmpty) { - <@iri> knora-admin:projectRestrictedViewWatermark "@watermark"^^xsd:string . - } } WHERE { <@iri> a knora-admin:knoraProject . OPTIONAL { <@iri> knora-admin:projectRestrictedViewSize ?prevSize . - - @if(watermark.nonEmpty) { - <@iri> knora-admin:projectRestrictedViewWatermark ?prevWatermark . - } } } From 98d2c570e72102723906a86e2f26c24aa8b42ce9 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Fri, 29 Sep 2023 12:42:10 +0200 Subject: [PATCH 50/51] update docs --- docs/03-endpoints/api-admin/projects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/03-endpoints/api-admin/projects.md b/docs/03-endpoints/api-admin/projects.md index d0ab0867e0..3f325794dc 100644 --- a/docs/03-endpoints/api-admin/projects.md +++ b/docs/03-endpoints/api-admin/projects.md @@ -823,7 +823,7 @@ a square, so that the width and height of the returned image are not greater tha Example: `!512,512` means the image's bigger side will be set to 512 pixels, setting the other side respectively to image aspect ratio. The percentage pattern looks like: `pct:X`, where X is the number between 1-100 representing the percentage the image will be scaled to. Example: `pct:1` means the image will be scaled to 1% of the original image -size. **Both routes are implemented in `ZIO-HTTP`, thus can be reached only under port `5555`.** +size. Permissions: ProjectAdmin/SystemAdmin From 2832866ff9546b5237fa96bbfd8f153cf801356e Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Fri, 29 Sep 2023 17:03:26 +0200 Subject: [PATCH 51/51] fmt --- .../scala/org/knora/webapi/routing/AroundDirectives.scala | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/routing/AroundDirectives.scala b/webapi/src/main/scala/org/knora/webapi/routing/AroundDirectives.scala index a6149b6d62..616258db72 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/AroundDirectives.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/AroundDirectives.scala @@ -6,9 +6,12 @@ package org.knora.webapi.routing import org.apache.pekko -import org.apache.pekko.http.scaladsl.model.StatusCodes.{MethodNotAllowed, NotFound} -import org.apache.pekko.http.scaladsl.model.{HttpResponse, StatusCodes} +import org.apache.pekko.http.scaladsl.model.HttpResponse +import org.apache.pekko.http.scaladsl.model.StatusCodes.MethodNotAllowed +import org.apache.pekko.http.scaladsl.model.StatusCodes.NotFound + import org.knora.webapi.instrumentation.InstrumentationSupport + import pekko.http.scaladsl.server.Directive0 import pekko.http.scaladsl.server.Directives._