diff --git a/integration/src/test/scala/org/knora/sipi/SipiIT.scala b/integration/src/test/scala/org/knora/sipi/SipiIT.scala index d5f3b71325..d0fbd56a14 100644 --- a/integration/src/test/scala/org/knora/sipi/SipiIT.scala +++ b/integration/src/test/scala/org/knora/sipi/SipiIT.scala @@ -23,8 +23,7 @@ import scala.util.Try import org.knora.sipi.MockDspApiServer.verify.* import org.knora.webapi.config.AppConfig -import org.knora.webapi.messages.admin.responder.KnoraResponseADM -import org.knora.webapi.messages.admin.responder.sipimessages.* +import org.knora.webapi.messages.admin.responder.projectsmessages.PermissionCodeAndProjectRestrictedViewSettings import org.knora.webapi.messages.util.KnoraSystemInstances.Users.SystemUser import org.knora.webapi.routing.JwtService import org.knora.webapi.routing.JwtServiceLive @@ -317,7 +316,11 @@ object MockDspApiServer { def resetAndStubGetResponse(url: String, status: Int): URIO[WireMockServer, WireMockServer] = resetAndGetWireMockServer.tap(server => ZIO.succeed(stubGetJsonResponse(server, url, status))) - def resetAndStubGetResponse(url: String, status: Int, body: KnoraResponseADM): URIO[WireMockServer, WireMockServer] = + def resetAndStubGetResponse( + url: String, + status: Int, + body: PermissionCodeAndProjectRestrictedViewSettings, + ): URIO[WireMockServer, WireMockServer] = resetAndGetWireMockServer.tap(server => ZIO.succeed(stubGetJsonResponse(server, url, status, Some(body)))) def resetAndAllowWithPermissionCode( @@ -349,9 +352,10 @@ object MockDspApiServer { server: WireMockServer, url: String, status: Int, - body: Option[KnoraResponseADM] = None, + body: Option[PermissionCodeAndProjectRestrictedViewSettings] = None, ): Unit = { - val json = body.map(_.toJsValue.compactPrint).orNull + val json = + body.map(it => PermissionCodeAndProjectRestrictedViewSettings.codec.encoder.encodeJson(it).toString).orNull val jsonResponse = aResponse().withStatus(status).withBody(json).withHeader("Content-Type", "application/json") val stubBuilder = get(urlEqualTo(url)).willReturn(jsonResponse) server.stubFor(stubBuilder) diff --git a/integration/src/test/scala/org/knora/webapi/e2e/admin/AdminFilesE2ESpec.scala b/integration/src/test/scala/org/knora/webapi/e2e/admin/AdminFilesE2ESpec.scala index d3b47788cf..cabf1e81f8 100644 --- a/integration/src/test/scala/org/knora/webapi/e2e/admin/AdminFilesE2ESpec.scala +++ b/integration/src/test/scala/org/knora/webapi/e2e/admin/AdminFilesE2ESpec.scala @@ -7,14 +7,10 @@ package org.knora.webapi.e2e.admin import org.apache.pekko.http.scaladsl.model.* import org.apache.pekko.http.scaladsl.model.headers.BasicHttpCredentials -import org.apache.pekko.http.scaladsl.unmarshalling.Unmarshal - -import scala.concurrent.Await -import scala.concurrent.duration.* import org.knora.webapi.E2ESpec -import org.knora.webapi.messages.admin.responder.sipimessages.PermissionCodeAndProjectRestrictedViewSettings -import org.knora.webapi.messages.admin.responder.sipimessages.SipiResponderResponseADMJsonProtocol.* +import org.knora.webapi.messages.admin.responder.projectsmessages.PermissionCodeAndProjectRestrictedViewSettings +import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectRestrictedViewSettingsADM import org.knora.webapi.messages.store.triplestoremessages.RdfDataObject import org.knora.webapi.messages.store.triplestoremessages.TriplestoreJsonProtocol import org.knora.webapi.routing.Authenticator @@ -49,14 +45,14 @@ class AdminFilesE2ESpec extends E2ESpec with TriplestoreJsonProtocol { addCredentials(BasicHttpCredentials(anythingAdminEmail, testPass)) val response: HttpResponse = singleAwaitingRequest(request) - // println(response.toString) - assert(response.status == StatusCodes.OK) - val fr: PermissionCodeAndProjectRestrictedViewSettings = - Await.result(Unmarshal(response.entity).to[PermissionCodeAndProjectRestrictedViewSettings], 1.seconds) + val result: PermissionCodeAndProjectRestrictedViewSettings = + PermissionCodeAndProjectRestrictedViewSettings.codec + .decodeJson(responseToString(response)) + .getOrElse(throw new AssertionError(s"Could not decode response for ${responseToString(response)}.")) - fr.permissionCode shouldEqual 8 + assert(result == PermissionCodeAndProjectRestrictedViewSettings(8, None)) } "return RV (1) permission code" in { @@ -66,14 +62,16 @@ class AdminFilesE2ESpec extends E2ESpec with TriplestoreJsonProtocol { addCredentials(BasicHttpCredentials(normalUserEmail, testPass)) val response: HttpResponse = singleAwaitingRequest(request) - // println(response.toString) - assert(response.status == StatusCodes.OK) - val fr: PermissionCodeAndProjectRestrictedViewSettings = - Await.result(Unmarshal(response.entity).to[PermissionCodeAndProjectRestrictedViewSettings], 1.seconds) + val result: PermissionCodeAndProjectRestrictedViewSettings = + PermissionCodeAndProjectRestrictedViewSettings.codec + .decodeJson(responseToString(response)) + .getOrElse(throw new AssertionError(s"Could not decode response for ${responseToString(response)}.")) - (fr.permissionCode === 1) should be(true) + assert( + result == PermissionCodeAndProjectRestrictedViewSettings(1, Some(ProjectRestrictedViewSettingsADM(None, false))), + ) } "return 404 Not Found if a file value is in a deleted resource" in { @@ -93,11 +91,14 @@ class AdminFilesE2ESpec extends E2ESpec with TriplestoreJsonProtocol { assert(response.status == StatusCodes.OK) - val fr: PermissionCodeAndProjectRestrictedViewSettings = - Await.result(Unmarshal(response.entity).to[PermissionCodeAndProjectRestrictedViewSettings], 1.seconds) - - (fr.permissionCode === 1) should be(true) + val result: PermissionCodeAndProjectRestrictedViewSettings = + PermissionCodeAndProjectRestrictedViewSettings.codec + .decodeJson(responseToString(response)) + .getOrElse(throw new AssertionError(s"Could not decode response for ${responseToString(response)}.")) + assert( + result == PermissionCodeAndProjectRestrictedViewSettings(1, Some(ProjectRestrictedViewSettingsADM(None, false))), + ) } } } diff --git a/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2ESpec.scala b/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2ESpec.scala index 36b0b4ff6b..d231e3cdbb 100644 --- a/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2ESpec.scala +++ b/integration/src/test/scala/org/knora/webapi/e2e/admin/ProjectsADME2ESpec.scala @@ -63,11 +63,8 @@ class ProjectsADME2ESpec extends E2ESpec with ProjectsADMJsonProtocol { "return all projects excluding built-in system projects" in { val request = Get(baseApiUrl + s"/admin/projects") ~> addCredentials(BasicHttpCredentials(rootEmail, testPass)) val response = singleAwaitingRequest(request) - // log.debug(s"response: {}", response) assert(response.status === StatusCodes.OK) - // log.debug("projects as objects: {}", AkkaHttpUtils.httpResponseToJson(response).fields("projects").convertTo[Seq[ProjectInfoV1]]) - val projects: Seq[ProjectADM] = AkkaHttpUtils.httpResponseToJson(response).fields("projects").convertTo[Seq[ProjectADM]] projects.size should be(6) @@ -88,7 +85,6 @@ class ProjectsADME2ESpec extends E2ESpec with ProjectsADMJsonProtocol { BasicHttpCredentials(rootEmail, testPass), ) val response: HttpResponse = singleAwaitingRequest(request) - // log.debug(s"response: {}", response) assert(response.status === StatusCodes.OK) clientTestDataCollector.addFile( TestDataFileContent( @@ -107,7 +103,6 @@ class ProjectsADME2ESpec extends E2ESpec with ProjectsADMJsonProtocol { BasicHttpCredentials(rootEmail, testPass), ) val response: HttpResponse = singleAwaitingRequest(request) - // log.debug(s"response: {}", response) assert(response.status === StatusCodes.OK) } @@ -116,7 +111,6 @@ class ProjectsADME2ESpec extends E2ESpec with ProjectsADMJsonProtocol { BasicHttpCredentials(rootEmail, testPass), ) val response: HttpResponse = singleAwaitingRequest(request) - // log.debug(s"response: {}", response) assert(response.status === StatusCodes.OK) } @@ -125,11 +119,14 @@ class ProjectsADME2ESpec extends E2ESpec with ProjectsADMJsonProtocol { BasicHttpCredentials(rootEmail, testPass), ) val response: HttpResponse = singleAwaitingRequest(request) - logger.debug(s"response: {}", response) assert(response.status === StatusCodes.OK) - val settings: ProjectRestrictedViewSettingsADM = - AkkaHttpUtils.httpResponseToJson(response).fields("settings").convertTo[ProjectRestrictedViewSettingsADM] + val settings = + ProjectRestrictedViewSettingsGetResponseADM.codec + .decodeJson(responseToString(response)) + .getOrElse(throw new AssertionError(s"Could not decode response for ${responseToString(response)}.")) + .settings + settings.size should be(Some("!512,512")) settings.watermark should be(true) @@ -150,11 +147,14 @@ class ProjectsADME2ESpec extends E2ESpec with ProjectsADMJsonProtocol { baseApiUrl + s"/admin/projects/shortname/$projectShortname/RestrictedViewSettings", ) ~> addCredentials(BasicHttpCredentials(rootEmail, testPass)) val response: HttpResponse = singleAwaitingRequest(request) - logger.debug(s"response: {}", response) assert(response.status === StatusCodes.OK) val settings: ProjectRestrictedViewSettingsADM = - AkkaHttpUtils.httpResponseToJson(response).fields("settings").convertTo[ProjectRestrictedViewSettingsADM] + ProjectRestrictedViewSettingsGetResponseADM.codec + .decodeJson(responseToString(response)) + .getOrElse(throw new AssertionError(s"Could not decode response for ${responseToString(response)}.")) + .settings + settings.size should be(Some("!512,512")) settings.watermark should be(true) } @@ -164,11 +164,14 @@ class ProjectsADME2ESpec extends E2ESpec with ProjectsADMJsonProtocol { baseApiUrl + s"/admin/projects/shortcode/$projectShortcode/RestrictedViewSettings", ) ~> addCredentials(BasicHttpCredentials(rootEmail, testPass)) val response: HttpResponse = singleAwaitingRequest(request) - logger.debug(s"response: {}", response) assert(response.status === StatusCodes.OK) val settings: ProjectRestrictedViewSettingsADM = - AkkaHttpUtils.httpResponseToJson(response).fields("settings").convertTo[ProjectRestrictedViewSettingsADM] + ProjectRestrictedViewSettingsGetResponseADM.codec + .decodeJson(responseToString(response)) + .getOrElse(throw new AssertionError(s"Could not decode response for ${responseToString(response)}.")) + .settings + settings.size should be(Some("!512,512")) settings.watermark should be(true) } diff --git a/integration/src/test/scala/org/knora/webapi/responders/admin/AssetPermissionsResponderSpec.scala b/integration/src/test/scala/org/knora/webapi/responders/admin/AssetPermissionsResponderSpec.scala index dbafbaed11..cebb54bc45 100644 --- a/integration/src/test/scala/org/knora/webapi/responders/admin/AssetPermissionsResponderSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/responders/admin/AssetPermissionsResponderSpec.scala @@ -8,9 +8,9 @@ package org.knora.webapi.responders.admin import org.apache.pekko.testkit.* import org.knora.webapi.* +import org.knora.webapi.messages.admin.responder.projectsmessages.PermissionCodeAndProjectRestrictedViewSettings import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM.ShortcodeIdentifier import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectRestrictedViewSettingsADM -import org.knora.webapi.messages.admin.responder.sipimessages.* import org.knora.webapi.messages.store.triplestoremessages.RdfDataObject import org.knora.webapi.routing.UnsafeZioRun import org.knora.webapi.sharedtestdata.SharedTestDataADM diff --git a/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMSpec.scala b/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMSpec.scala index 716697509e..ade0620b94 100644 --- a/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMSpec.scala @@ -55,7 +55,7 @@ class ProjectsResponderADMSpec extends CoreSpec with ImplicitSender { .fromString(SharedTestDataADM.incunabulaProject.id) .getOrElseWith(e => throw BadRequestException(e.head.getMessage)), ) - expectMsg(ProjectGetResponseADM(SharedTestDataADM.incunabulaProject)) + expectMsg(ProjectGetResponse(SharedTestDataADM.incunabulaProject)) } @@ -65,7 +65,7 @@ class ProjectsResponderADMSpec extends CoreSpec with ImplicitSender { .fromString(SharedTestDataADM.incunabulaProject.shortname) .getOrElseWith(e => throw BadRequestException(e.head.getMessage)), ) - expectMsg(ProjectGetResponseADM(SharedTestDataADM.incunabulaProject)) + expectMsg(ProjectGetResponse(SharedTestDataADM.incunabulaProject)) } "return 'NotFoundException' when the project IRI is unknown" in { diff --git a/integration/src/test/scala/org/knora/webapi/responders/v2/OntologyResponderV2Spec.scala b/integration/src/test/scala/org/knora/webapi/responders/v2/OntologyResponderV2Spec.scala index 28b5280a5a..6eda6361d4 100644 --- a/integration/src/test/scala/org/knora/webapi/responders/v2/OntologyResponderV2Spec.scala +++ b/integration/src/test/scala/org/knora/webapi/responders/v2/OntologyResponderV2Spec.scala @@ -22,7 +22,7 @@ import org.knora.webapi.messages.SmartIri import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectADM import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectGetRequestADM -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectGetResponseADM +import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectGetResponse import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM import org.knora.webapi.messages.store.cacheservicemessages.CacheServiceGetProjectADM import org.knora.webapi.messages.store.triplestoremessages.* @@ -163,7 +163,7 @@ class OntologyResponderV2Spec extends CoreSpec with ImplicitSender { "invalidate cached project information when adding an ontology to a project" in { // ernsure that the project is cached appActor ! ProjectGetRequestADM(ProjectIdentifierADM.IriIdentifier.unsafeFrom(imagesProjectIri.toString)) - expectMsgType[ProjectGetResponseADM](timeout) + expectMsgType[ProjectGetResponse](timeout) appActor ! CacheServiceGetProjectADM(ProjectIdentifierADM.IriIdentifier.unsafeFrom(imagesProjectIri.toString)) val cachedProjectBefore = expectMsgType[Option[ProjectADM]](timeout) assert(cachedProjectBefore.isDefined) 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 ee4e6d025d..7fdfe40588 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,6 +14,8 @@ import spray.json.RootJsonFormat import sttp.tapir.Codec import sttp.tapir.CodecFormat.TextPlain import sttp.tapir.DecodeResult +import zio.json.DeriveJsonCodec +import zio.json.JsonCodec import zio.prelude.Validation import java.util.UUID @@ -46,7 +48,7 @@ sealed trait ProjectsResponderRequestADM extends KnoraRequestADM with RelayedMes // Requests /** * Get info about a single project identified either through its IRI, shortname or shortcode. The response is in form - * of [[ProjectGetResponseADM]]. External use. + * of [[ProjectGetResponse]]. External use. * * @param identifier the IRI, email, or username of the project. */ @@ -90,15 +92,20 @@ case class ProjectChangeRequestADM( // Responses +object ProjectCodec { + implicit val projectCodec: JsonCodec[ProjectADM] = DeriveJsonCodec.gen[ProjectADM] +} + /** * Represents the Knora API ADM JSON response to a request for information about all projects. * * @param projects information about all existing projects. */ -case class ProjectsGetResponseADM(projects: Seq[ProjectADM]) - extends AdminKnoraResponseADM - with ProjectsADMJsonProtocol { - def toJsValue: JsValue = projectsResponseADMFormat.write(this) +case class ProjectsGetResponse(projects: Seq[ProjectADM]) +object ProjectsGetResponse { + // can be removed as soon as ProjectADM can define its own codec + import ProjectCodec.projectCodec + implicit val codec: JsonCodec[ProjectsGetResponse] = DeriveJsonCodec.gen[ProjectsGetResponse] } /** @@ -106,8 +113,11 @@ case class ProjectsGetResponseADM(projects: Seq[ProjectADM]) * * @param project all information about the project. */ -case class ProjectGetResponseADM(project: ProjectADM) extends AdminKnoraResponseADM with ProjectsADMJsonProtocol { - def toJsValue: JsValue = projectResponseADMFormat.write(this) +case class ProjectGetResponse(project: ProjectADM) +object ProjectGetResponse { + // can be removed as soon as ProjectADM can define its own codec + import ProjectCodec.projectCodec + implicit val codec: JsonCodec[ProjectGetResponse] = DeriveJsonCodec.gen[ProjectGetResponse] } /** @@ -137,10 +147,9 @@ case class ProjectAdminMembersGetResponseADM(members: Seq[User]) * * @param keywords a list of keywords. */ -case class ProjectsKeywordsGetResponseADM(keywords: Seq[String]) - extends AdminKnoraResponseADM - with ProjectsADMJsonProtocol { - def toJsValue: JsValue = projectsKeywordsGetResponseADMFormat.write(this) +case class ProjectsKeywordsGetResponse(keywords: Seq[String]) +object ProjectsKeywordsGetResponse { + implicit val codec: JsonCodec[ProjectsKeywordsGetResponse] = DeriveJsonCodec.gen[ProjectsKeywordsGetResponse] } /** @@ -148,10 +157,9 @@ case class ProjectsKeywordsGetResponseADM(keywords: Seq[String]) * * @param keywords a list of keywords. */ -case class ProjectKeywordsGetResponseADM(keywords: Seq[String]) - extends AdminKnoraResponseADM - with ProjectsADMJsonProtocol { - def toJsValue: JsValue = projectKeywordsGetResponseADMFormat.write(this) +case class ProjectKeywordsGetResponse(keywords: Seq[String]) +object ProjectKeywordsGetResponse { + implicit val codec: JsonCodec[ProjectKeywordsGetResponse] = DeriveJsonCodec.gen[ProjectKeywordsGetResponse] } /** @@ -160,9 +168,24 @@ case class ProjectKeywordsGetResponseADM(keywords: Seq[String]) * @param settings the restricted view settings. */ case class ProjectRestrictedViewSettingsGetResponseADM(settings: ProjectRestrictedViewSettingsADM) - extends AdminKnoraResponseADM - with ProjectsADMJsonProtocol { - def toJsValue: JsValue = projectRestrictedViewGetResponseADMFormat.write(this) +object ProjectRestrictedViewSettingsGetResponseADM { + implicit val codec: JsonCodec[ProjectRestrictedViewSettingsGetResponseADM] = + DeriveJsonCodec.gen[ProjectRestrictedViewSettingsGetResponseADM] +} + +/** + * Represents the JSON response to a request for a information about a `FileValue`. + * + * @param permissionCode a code representing the user's maximum permission on the file. + * @param restrictedViewSettings the project's restricted view settings. + */ +case class PermissionCodeAndProjectRestrictedViewSettings( + permissionCode: Int, + restrictedViewSettings: Option[ProjectRestrictedViewSettingsADM], +) +object PermissionCodeAndProjectRestrictedViewSettings { + implicit val codec: JsonCodec[PermissionCodeAndProjectRestrictedViewSettings] = + DeriveJsonCodec.gen[PermissionCodeAndProjectRestrictedViewSettings] } /** @@ -370,7 +393,11 @@ object ProjectIdentifierADM { * @param size the restricted view size. * @param watermark the watermark file. */ -case class ProjectRestrictedViewSettingsADM(size: Option[String], watermark: Boolean) extends ProjectsADMJsonProtocol +case class ProjectRestrictedViewSettingsADM(size: Option[String], watermark: Boolean) +object ProjectRestrictedViewSettingsADM { + implicit val codec: JsonCodec[ProjectRestrictedViewSettingsADM] = + DeriveJsonCodec.gen[ProjectRestrictedViewSettingsADM] +} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // JSON formatting @@ -397,14 +424,6 @@ trait ProjectsADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol "selfjoin", ), ) - implicit val projectsResponseADMFormat: RootJsonFormat[ProjectsGetResponseADM] = rootFormat( - lazyFormat(jsonFormat(ProjectsGetResponseADM, "projects")), - ) - implicit val projectResponseADMFormat: RootJsonFormat[ProjectGetResponseADM] = rootFormat( - lazyFormat(jsonFormat(ProjectGetResponseADM, "project")), - ) - implicit val projectRestrictedViewSettingsADMFormat: RootJsonFormat[ProjectRestrictedViewSettingsADM] = - jsonFormat(ProjectRestrictedViewSettingsADM, "size", "watermark") implicit val projectAdminMembersGetResponseADMFormat: RootJsonFormat[ProjectAdminMembersGetResponseADM] = rootFormat( lazyFormat(jsonFormat(ProjectAdminMembersGetResponseADM, "members")), @@ -412,12 +431,7 @@ trait ProjectsADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol implicit val projectMembersGetResponseADMFormat: RootJsonFormat[ProjectMembersGetResponseADM] = rootFormat( lazyFormat(jsonFormat(ProjectMembersGetResponseADM, "members")), ) - implicit val projectsKeywordsGetResponseADMFormat: RootJsonFormat[ProjectsKeywordsGetResponseADM] = - jsonFormat(ProjectsKeywordsGetResponseADM, "keywords") - implicit val projectKeywordsGetResponseADMFormat: RootJsonFormat[ProjectKeywordsGetResponseADM] = - jsonFormat(ProjectKeywordsGetResponseADM, "keywords") - 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/messages/admin/responder/sipimessages/SipiMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/sipimessages/SipiMessagesADM.scala deleted file mode 100644 index df613bae18..0000000000 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/sipimessages/SipiMessagesADM.scala +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright © 2021 - 2024 Swiss National Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.knora.webapi.messages.admin.responder.sipimessages - -import org.apache.pekko.http.scaladsl.marshallers.sprayjson.SprayJsonSupport -import spray.json.DefaultJsonProtocol -import spray.json.JsValue -import spray.json.NullOptions -import spray.json.RootJsonFormat - -import org.knora.webapi.messages.admin.responder.AdminKnoraResponseADM -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectRestrictedViewSettingsADM -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectsADMJsonProtocol - -/** - * Represents the JSON response to a request for a information about a `FileValue`. - * - * @param permissionCode a code representing the user's maximum permission on the file. - * @param restrictedViewSettings the project's restricted view settings. - */ -case class PermissionCodeAndProjectRestrictedViewSettings( - permissionCode: Int, - restrictedViewSettings: Option[ProjectRestrictedViewSettingsADM], -) extends AdminKnoraResponseADM { - def toJsValue: JsValue = SipiResponderResponseADMJsonProtocol.sipiFileInfoGetResponseADMFormat.write(this) -} - -/** - * A spray-json protocol for generating Knora API v1 JSON providing data about representations of a resource. - */ -object SipiResponderResponseADMJsonProtocol - extends SprayJsonSupport - with DefaultJsonProtocol - with NullOptions - with ProjectsADMJsonProtocol { - - implicit val sipiFileInfoGetResponseADMFormat: RootJsonFormat[PermissionCodeAndProjectRestrictedViewSettings] = - jsonFormat2(PermissionCodeAndProjectRestrictedViewSettings) -} diff --git a/webapi/src/main/scala/org/knora/webapi/messages/util/ConstructResponseUtilV2.scala b/webapi/src/main/scala/org/knora/webapi/messages/util/ConstructResponseUtilV2.scala index bb6a982236..6dbe748f6e 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/util/ConstructResponseUtilV2.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/util/ConstructResponseUtilV2.scala @@ -23,7 +23,7 @@ import org.knora.webapi.messages.OntologyConstants import org.knora.webapi.messages.SmartIri import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectGetRequestADM -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectGetResponseADM +import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectGetResponse import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM.* import org.knora.webapi.messages.store.triplestoremessages.SparqlExtendedConstructResponse.ConstructPredicateObjects import org.knora.webapi.messages.store.triplestoremessages.* @@ -1539,7 +1539,7 @@ final case class ConstructResponseUtilV2Live( for { projectResponse <- messageRelay - .ask[ProjectGetResponseADM]( + .ask[ProjectGetResponse]( ProjectGetRequestADM(identifier = IriIdentifier .fromString(resourceAttachedToProject) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/resourcemessages/ResourceMessagesV2.scala b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/resourcemessages/ResourceMessagesV2.scala index 5999ecad84..0222a36970 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/resourcemessages/ResourceMessagesV2.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/resourcemessages/ResourceMessagesV2.scala @@ -25,7 +25,7 @@ import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.ValuesValidator.xsdDateTimeStampToInstant import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectADM import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectGetRequestADM -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectGetResponseADM +import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectGetResponse import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM.* import org.knora.webapi.messages.util.PermissionUtilADM.EntityPermission import org.knora.webapi.messages.util.* @@ -713,7 +713,7 @@ object CreateResourceRequestV2 { ) projectId <- IriIdentifier.fromString(projectIri.toString).toZIO.mapError(e => BadRequestException(e.getMessage)) - projectInfoResponse <- MessageRelay.ask[ProjectGetResponseADM](ProjectGetRequestADM(projectId)) + projectInfoResponse <- MessageRelay.ask[ProjectGetResponse](ProjectGetRequestADM(projectId)) _ <- ZIO.attempt(maybeCustomResourceIri.foreach { iri => if (!iri.isKnoraResourceIri) { diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/AssetPermissionsResponder.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/AssetPermissionsResponder.scala index b3115f2563..ef5ab36111 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/AssetPermissionsResponder.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/AssetPermissionsResponder.scala @@ -11,8 +11,8 @@ import dsp.errors.InconsistentRepositoryDataException import dsp.errors.NotFoundException import org.knora.webapi.messages.SmartIri import org.knora.webapi.messages.StringFormatter +import org.knora.webapi.messages.admin.responder.projectsmessages.PermissionCodeAndProjectRestrictedViewSettings import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM.ShortcodeIdentifier -import org.knora.webapi.messages.admin.responder.sipimessages.PermissionCodeAndProjectRestrictedViewSettings import org.knora.webapi.messages.store.triplestoremessages.IriSubjectV2 import org.knora.webapi.messages.store.triplestoremessages.LiteralV2 import org.knora.webapi.messages.store.triplestoremessages.SparqlExtendedConstructResponse 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 5e26832e23..8c34ea8ecd 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 @@ -54,18 +54,18 @@ trait ProjectsResponderADM { * @return all the projects as a [[ProjectADM]]. * [[NotFoundException]] if no projects are found. */ - def getNonSystemProjects: Task[ProjectsGetResponseADM] + def getNonSystemProjects: Task[ProjectsGetResponse] /** * Gets the project with the given project IRI, shortname, shortcode or UUID and returns the information - * as a [[ProjectGetResponseADM]]. + * as a [[ProjectGetResponse]]. * * @param id the IRI, shortname, shortcode or UUID of the project. - * @return Information about the project as a [[ProjectGetResponseADM]]. + * @return Information about the project as a [[ProjectGetResponse]]. * * [[NotFoundException]] When no project for the given IRI can be found. */ - def getSingleProjectADMRequest(id: ProjectIdentifierADM): Task[ProjectGetResponseADM] + def getSingleProjectADMRequest(id: ProjectIdentifierADM): Task[ProjectGetResponse] /** * Tries to retrieve a [[ProjectADM]] either from triplestore or cache if caching is enabled. @@ -96,17 +96,17 @@ trait ProjectsResponderADM { /** * Gets all unique keywords for all projects and returns them. Returns an empty list if none are found. * - * @return all keywords for all projects as [[ProjectsKeywordsGetResponseADM]] + * @return all keywords for all projects as [[ProjectsKeywordsGetResponse]] */ - def projectsKeywordsGetRequestADM(): Task[ProjectsKeywordsGetResponseADM] + def projectsKeywordsGetRequestADM(): Task[ProjectsKeywordsGetResponse] /** * Gets all keywords for a single project and returns them. Returns an empty list if none are found. * * @param projectIri the IRI of the project. - * @return keywords for a projects as [[ProjectKeywordsGetResponseADM]] + * @return keywords for a projects as [[ProjectKeywordsGetResponse]] */ - def projectKeywordsGetRequestADM(projectIri: ProjectIri): Task[ProjectKeywordsGetResponseADM] + def projectKeywordsGetRequestADM(projectIri: ProjectIri): Task[ProjectKeywordsGetResponse] /** * Get project's restricted view settings. @@ -211,29 +211,29 @@ final case class ProjectsResponderADMLive( * Gets all the projects but not system projects. * Filters out system projects in response. * - * @return all non-system projects as a [[ProjectsGetResponseADM]]. + * @return all non-system projects as a [[ProjectsGetResponse]]. * [[NotFoundException]] if no projects are found. */ - override def getNonSystemProjects: Task[ProjectsGetResponseADM] = + override def getNonSystemProjects: Task[ProjectsGetResponse] = projectService.findAll.map(_.filter(_.id.startsWith("http://rdfh.ch/projects/"))).flatMap { case Nil => ZIO.fail(NotFoundException(s"No projects found")) - case projects => ZIO.succeed(ProjectsGetResponseADM(projects)) + case projects => ZIO.succeed(ProjectsGetResponse(projects)) } /** * Gets the project with the given project IRI, shortname, shortcode or UUID and returns the information - * as a [[ProjectGetResponseADM]]. + * as a [[ProjectGetResponse]]. * * @param id the IRI, shortname, shortcode or UUID of the project. - * @return Information about the project as a [[ProjectGetResponseADM]]. + * @return Information about the project as a [[ProjectGetResponse]]. * * [[NotFoundException]] When no project for the given IRI can be found. */ - override def getSingleProjectADMRequest(id: ProjectIdentifierADM): Task[ProjectGetResponseADM] = + override def getSingleProjectADMRequest(id: ProjectIdentifierADM): Task[ProjectGetResponse] = projectService .findByProjectIdentifier(id) .someOrFail(NotFoundException(s"Project '${getId(id)}' not found")) - .map(ProjectGetResponseADM.apply) + .map(ProjectGetResponse.apply) /** * Gets the members of a project with the given IRI, shortname, shortcode or UUID. Returns an empty list @@ -323,18 +323,18 @@ final case class ProjectsResponderADMLive( /** * Gets all unique keywords for all projects and returns them. Returns an empty list if none are found. * - * @return all keywords for all projects as [[ProjectsKeywordsGetResponseADM]] + * @return all keywords for all projects as [[ProjectsKeywordsGetResponse]] */ - override def projectsKeywordsGetRequestADM(): Task[ProjectsKeywordsGetResponseADM] = + override def projectsKeywordsGetRequestADM(): Task[ProjectsKeywordsGetResponse] = projectService.findAllProjectsKeywords /** * Gets all keywords for a single project and returns them. Returns an empty list if none are found. * * @param projectIri the IRI of the project. - * @return keywords for a projects as [[ProjectKeywordsGetResponseADM]] + * @return keywords for a projects as [[ProjectKeywordsGetResponse]] */ - override def projectKeywordsGetRequestADM(projectIri: ProjectIri): Task[ProjectKeywordsGetResponseADM] = + override def projectKeywordsGetRequestADM(projectIri: ProjectIri): Task[ProjectKeywordsGetResponse] = for { id <- IriIdentifier.fromString(projectIri.value).toZIO.mapError(e => BadRequestException(e.getMessage)) keywords <- projectService @@ -398,7 +398,7 @@ final case class ProjectsResponderADMLive( ): Task[ProjectRestrictedViewSettingsGetResponseADM] = projectRestrictedViewSettingsGetADM(id) .someOrFail(NotFoundException(s"Project '${getId(id)}' not found.")) - .map(ProjectRestrictedViewSettingsGetResponseADM) + .map(ProjectRestrictedViewSettingsGetResponseADM.apply) /** * Update project's basic information. diff --git a/webapi/src/main/scala/org/knora/webapi/routing/RouteUtilADM.scala b/webapi/src/main/scala/org/knora/webapi/routing/RouteUtilADM.scala index 26aa942b8f..d36fdbdeec 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/RouteUtilADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/RouteUtilADM.scala @@ -63,8 +63,6 @@ object RouteUtilADM { } response match { - case ProjectsGetResponseADM(projects) => ProjectsGetResponseADM(projects.map(projectAsExternalRepresentation)) - case ProjectGetResponseADM(project) => ProjectGetResponseADM(projectAsExternalRepresentation(project)) case ProjectMembersGetResponseADM(members) => ProjectMembersGetResponseADM(members.map(userAsExternalRepresentation)) case ProjectAdminMembersGetResponseADM(members) => @@ -91,6 +89,25 @@ object RouteUtilADM { } } + def transformResponseIntoExternalFormat[A](response: A): ZIO[StringFormatter, Throwable, A] = + ZIO + .serviceWithZIO[StringFormatter] { sf => + ZIO.attempt { + def projectAsExternalRepresentation(project: ProjectADM): ProjectADM = { + val ontologiesExternal = + project.ontologies.map(sf.toSmartIri(_)).map(_.toOntologySchema(ApiV2Complex).toString) + project.copy(ontologies = ontologiesExternal) + } + + response match { + case ProjectsGetResponse(projects) => ProjectsGetResponse(projects.map(projectAsExternalRepresentation)) + case ProjectGetResponse(project) => ProjectGetResponse(projectAsExternalRepresentation(project)) + case _ => response + } + } + } + .map(_.asInstanceOf[A]) + /** * Sends a message to a responder and completes the HTTP request by returning the response as JSON. * diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/FilesEndpoints.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/FilesEndpoints.scala index f1a77470d1..816f42d639 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/FilesEndpoints.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/FilesEndpoints.scala @@ -7,12 +7,11 @@ package org.knora.webapi.slice.admin.api import sttp.tapir.EndpointInput.PathCapture import sttp.tapir.* -import sttp.tapir.generic.auto.* -import sttp.tapir.json.spray.jsonBody +import sttp.tapir.generic.auto.schemaForCaseClass +import sttp.tapir.json.zio.jsonBody import zio.ZLayer -import org.knora.webapi.messages.admin.responder.sipimessages.PermissionCodeAndProjectRestrictedViewSettings -import org.knora.webapi.messages.admin.responder.sipimessages.SipiResponderResponseADMJsonProtocol.* +import org.knora.webapi.messages.admin.responder.projectsmessages.PermissionCodeAndProjectRestrictedViewSettings import org.knora.webapi.slice.admin.api.AdminPathVariables.projectShortcode import org.knora.webapi.slice.admin.api.Codecs.TapirCodec.sparqlEncodedString import org.knora.webapi.slice.admin.api.FilesPathVar.filename diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/FilesEndpointsHandler.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/FilesEndpointsHandler.scala index c1cee756c5..6498b9f5a8 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/FilesEndpointsHandler.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/FilesEndpointsHandler.scala @@ -7,8 +7,8 @@ package org.knora.webapi.slice.admin.api import zio.ZLayer +import org.knora.webapi.messages.admin.responder.projectsmessages.PermissionCodeAndProjectRestrictedViewSettings import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM.ShortcodeIdentifier -import org.knora.webapi.messages.admin.responder.sipimessages.PermissionCodeAndProjectRestrictedViewSettings import org.knora.webapi.responders.admin.AssetPermissionsResponder import org.knora.webapi.slice.admin.domain.model.User import org.knora.webapi.slice.common.api.HandlerMapper diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/ProjectsEndpoints.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/ProjectsEndpoints.scala index 5e0e1b3de6..b777d54a14 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/ProjectsEndpoints.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/ProjectsEndpoints.scala @@ -47,47 +47,47 @@ final case class ProjectsEndpoints( val getAdminProjects = baseEndpoints.publicEndpoint.get .in(projectsBase) - .out(sprayJsonBody[ProjectsGetResponseADM]) + .out(zioJsonBody[ProjectsGetResponse]) .description("Returns all projects.") val getAdminProjectsKeywords = baseEndpoints.publicEndpoint.get .in(projectsBase / keywords) - .out(sprayJsonBody[ProjectsKeywordsGetResponseADM]) + .out(zioJsonBody[ProjectsKeywordsGetResponse]) .description("Returns all unique keywords for all projects as a list.") val getAdminProjectsByProjectIri = baseEndpoints.publicEndpoint.get .in(projectsByIri) - .out(sprayJsonBody[ProjectGetResponseADM]) + .out(zioJsonBody[ProjectGetResponse]) .description("Returns a single project identified by the IRI.") val getAdminProjectsByProjectShortcode = baseEndpoints.publicEndpoint.get .in(projectsByShortcode) - .out(sprayJsonBody[ProjectGetResponseADM]) + .out(zioJsonBody[ProjectGetResponse]) .description("Returns a single project identified by the shortcode.") val getAdminProjectsByProjectShortname = baseEndpoints.publicEndpoint.get .in(projectsByShortname) - .out(sprayJsonBody[ProjectGetResponseADM]) + .out(zioJsonBody[ProjectGetResponse]) .description("Returns a single project identified by the shortname.") val getAdminProjectsKeywordsByProjectIri = baseEndpoints.publicEndpoint.get .in(projectsByIri / keywords) - .out(sprayJsonBody[ProjectKeywordsGetResponseADM]) + .out(zioJsonBody[ProjectKeywordsGetResponse]) .description("Returns all keywords for a single project.") val getAdminProjectsByProjectIriRestrictedViewSettings = baseEndpoints.publicEndpoint.get .in(projectsByIri / restrictedViewSettings) - .out(sprayJsonBody[ProjectRestrictedViewSettingsGetResponseADM]) + .out(zioJsonBody[ProjectRestrictedViewSettingsGetResponseADM]) .description("Returns the project's restricted view settings identified by the IRI.") val getAdminProjectsByProjectShortcodeRestrictedViewSettings = baseEndpoints.publicEndpoint.get .in(projectsByShortcode / restrictedViewSettings) - .out(sprayJsonBody[ProjectRestrictedViewSettingsGetResponseADM]) + .out(zioJsonBody[ProjectRestrictedViewSettingsGetResponseADM]) .description("Returns the project's restricted view settings identified by the shortcode.") val getAdminProjectsByProjectShortnameRestrictedViewSettings = baseEndpoints.publicEndpoint.get .in(projectsByShortname / restrictedViewSettings) - .out(sprayJsonBody[ProjectRestrictedViewSettingsGetResponseADM]) + .out(zioJsonBody[ProjectRestrictedViewSettingsGetResponseADM]) .description("Returns the project's restricted view settings identified by the shortname.") } diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/GroupsRestService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/GroupsRestService.scala index 6fc51e28d9..c514fe44a1 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/GroupsRestService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/GroupsRestService.scala @@ -38,7 +38,7 @@ final case class GroupsRestServiceLive( ) extends GroupsRestService { override def getGroups: Task[GroupsGetResponseADM] = for { internal <- responder.groupsGetADM.map(GroupsGetResponseADM) - external <- format.toExternal(internal) + external <- format.toExternalADM(internal) } yield external override def getGroupByIri(iri: GroupIri): Task[GroupGetResponseADM] = @@ -47,13 +47,13 @@ final case class GroupsRestServiceLive( .groupGetADM(iri.value) .someOrFail(NotFoundException(s"Group <${iri.value}> not found.")) .map(GroupGetResponseADM.apply) - external <- format.toExternal(internal) + external <- format.toExternalADM(internal) } yield external override def getGroupMembers(iri: GroupIri, user: User): Task[GroupMembersGetResponseADM] = for { internal <- responder.groupMembersGetRequest(iri, user) - external <- format.toExternal(internal) + external <- format.toExternalADM(internal) } yield external override def postGroup(request: GroupCreateRequest, user: User): Task[GroupGetResponseADM] = @@ -61,7 +61,7 @@ final case class GroupsRestServiceLive( _ <- auth.ensureSystemAdminOrProjectAdmin(user, request.project) uuid <- Random.nextUUID internal <- responder.createGroup(request, uuid) - external <- format.toExternal(internal) + external <- format.toExternalADM(internal) } yield external override def putGroup(iri: GroupIri, request: GroupUpdateRequest, user: User): Task[GroupGetResponseADM] = @@ -69,7 +69,7 @@ final case class GroupsRestServiceLive( _ <- auth.ensureSystemAdminOrProjectAdminOfGroup(user, iri) uuid <- Random.nextUUID internal <- responder.updateGroup(iri, request, uuid) - external <- format.toExternal(internal) + external <- format.toExternalADM(internal) } yield external override def putGroupStatus(iri: GroupIri, request: GroupStatusUpdateRequest, user: User): Task[GroupGetResponseADM] = @@ -77,7 +77,7 @@ final case class GroupsRestServiceLive( _ <- auth.ensureSystemAdminOrProjectAdminOfGroup(user, iri) uuid <- Random.nextUUID internal <- responder.updateGroupStatus(iri, request, uuid) - external <- format.toExternal(internal) + external <- format.toExternalADM(internal) } yield external override def deleteGroup(iri: GroupIri, user: User): Task[GroupGetResponseADM] = @@ -85,7 +85,7 @@ final case class GroupsRestServiceLive( _ <- auth.ensureSystemAdminOrProjectAdminOfGroup(user, iri) uuid <- Random.nextUUID internal <- responder.deleteGroup(iri, uuid) - external <- format.toExternal(internal) + external <- format.toExternalADM(internal) } yield external } diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/PermissionsRestService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/PermissionsRestService.scala index 11493b9642..1712953257 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/PermissionsRestService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/PermissionsRestService.scala @@ -51,7 +51,7 @@ final case class PermissionsRestService( _ <- ensureProjectIriStrExistsAndUserHasAccess(request.forProject, user) uuid <- Random.nextUUID result <- responder.createAdministrativePermission(request, user, uuid) - ext <- format.toExternal(result) + ext <- format.toExternalADM(result) } yield ext private def ensureProjectIriStrExistsAndUserHasAccess(projectIri: String, user: User): Task[KnoraProject] = @@ -73,14 +73,14 @@ final case class PermissionsRestService( for { _ <- ensureProjectIriExistsAndUserHasAccess(value, user) result <- responder.getPermissionsApByProjectIri(value.value) - ext <- format.toExternal(result) + ext <- format.toExternalADM(result) } yield ext def getPermissionsByProjectIri(projectIri: ProjectIri, user: User): Task[PermissionsForProjectGetResponseADM] = for { _ <- ensureProjectIriExistsAndUserHasAccess(projectIri, user) result <- responder.getPermissionsByProjectIri(projectIri) - ext <- format.toExternal(result) + ext <- format.toExternalADM(result) } yield ext def deletePermission(permissionIri: PermissionIri, user: User): Task[PermissionDeleteResponseADM] = @@ -88,7 +88,7 @@ final case class PermissionsRestService( _ <- auth.ensureSystemAdmin(user) uuid <- Random.nextUUID result <- responder.deletePermission(permissionIri, user, uuid) - ext <- format.toExternal(result) + ext <- format.toExternalADM(result) } yield ext def createDefaultObjectAccessPermission( @@ -99,7 +99,7 @@ final case class PermissionsRestService( _ <- ensureProjectIriStrExistsAndUserHasAccess(request.forProject, user) uuid <- Random.nextUUID result <- responder.createDefaultObjectAccessPermission(request, user, uuid) - ext <- format.toExternal(result) + ext <- format.toExternalADM(result) } yield ext def updatePermissionHasPermissions( @@ -114,7 +114,7 @@ final case class PermissionsRestService( .fromOption(NonEmptyChunk.fromIterableOption(request.hasPermissions)) .mapBoth(_ => BadRequestException("hasPermissions must not be empty"), identity) result <- responder.updatePermissionHasPermissions(permissionIri, newHasPermissions, user, uuid) - ext <- format.toExternal(result) + ext <- format.toExternalADM(result) } yield ext def updatePermissionProperty( @@ -126,7 +126,7 @@ final case class PermissionsRestService( _ <- auth.ensureSystemAdmin(user) uuid <- Random.nextUUID result <- responder.updatePermissionProperty(permissionIri, request, user, uuid) - ext <- format.toExternal(result) + ext <- format.toExternalADM(result) } yield ext def updatePermissionResourceClass( @@ -138,7 +138,7 @@ final case class PermissionsRestService( _ <- auth.ensureSystemAdmin(user) uuid <- Random.nextUUID result <- responder.updatePermissionResourceClass(permissionIri, request, user, uuid) - ext <- format.toExternal(result) + ext <- format.toExternalADM(result) } yield ext def updatePermissionGroup( @@ -151,7 +151,7 @@ final case class PermissionsRestService( groupIri <- ZIO.fromEither(GroupIri.from(request.forGroup)).mapError(BadRequestException(_)) uuid <- Random.nextUUID result <- responder.updatePermissionsGroup(permissionIri, groupIri, user, uuid) - ext <- format.toExternal(result) + ext <- format.toExternalADM(result) } yield ext def getPermissionsDaopByProjectIri( @@ -161,7 +161,7 @@ final case class PermissionsRestService( for { _ <- ensureProjectIriExistsAndUserHasAccess(projectIri, user) result <- responder.getPermissionsDaopByProjectIri(projectIri) - ext <- format.toExternal(result) + ext <- format.toExternalADM(result) } yield ext def getPermissionsApByProjectAndGroupIri( @@ -172,7 +172,7 @@ final case class PermissionsRestService( for { _ <- ensureProjectIriExistsAndUserHasAccess(projectIri, user) result <- responder.getPermissionsApByProjectAndGroupIri(projectIri.value, groupIri.value) - ext <- format.toExternal(result) + ext <- format.toExternalADM(result) } yield ext } 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 e01e32b9db..872d563b39 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 @@ -34,9 +34,9 @@ import org.knora.webapi.slice.common.api.KnoraResponseRenderer @accessible trait ProjectADMRestService { - def listAllProjects(): Task[ProjectsGetResponseADM] + def listAllProjects(): Task[ProjectsGetResponse] - def findProject(id: ProjectIdentifierADM): Task[ProjectGetResponseADM] + def findProject(id: ProjectIdentifierADM): Task[ProjectGetResponse] def createProject(createReq: ProjectCreateRequest, user: User): Task[ProjectOperationResponseADM] @@ -64,9 +64,9 @@ trait ProjectADMRestService { def getProjectAdminMembers(user: User, id: ProjectIdentifierADM): Task[ProjectAdminMembersGetResponseADM] - def listAllKeywords(): Task[ProjectsKeywordsGetResponseADM] + def listAllKeywords(): Task[ProjectsKeywordsGetResponse] - def getKeywordsByProjectIri(iri: ProjectIri): Task[ProjectKeywordsGetResponseADM] + def getKeywordsByProjectIri(iri: ProjectIri): Task[ProjectKeywordsGetResponse] def getProjectRestrictedViewSettings(id: ProjectIdentifierADM): Task[ProjectRestrictedViewSettingsGetResponseADM] @@ -88,28 +88,28 @@ final case class ProjectsADMRestServiceLive( ) extends ProjectADMRestService { /** - * Returns all projects as a [[ProjectsGetResponseADM]]. + * Returns all projects as a [[ProjectsGetResponse]]. * * @return - * '''success''': information about the projects as a [[ProjectsGetResponseADM]] + * '''success''': information about the projects as a [[ProjectsGetResponse]] * * '''failure''': [[dsp.errors.NotFoundException]] when no project was found */ - def listAllProjects(): Task[ProjectsGetResponseADM] = for { + def listAllProjects(): Task[ProjectsGetResponse] = for { internal <- responder.getNonSystemProjects external <- format.toExternal(internal) } yield external /** - * Finds the project by its [[ProjectIdentifierADM]] and returns the information as a [[ProjectGetResponseADM]]. + * Finds the project by its [[ProjectIdentifierADM]] and returns the information as a [[ProjectGetResponse]]. * * @param id a [[ProjectIdentifierADM]] instance * @return - * '''success''': information about the project as a [[ProjectGetResponseADM]] + * '''success''': information about the project as a [[ProjectGetResponse]] * * '''failure''': [[dsp.errors.NotFoundException]] when no project for the given [[ProjectIdentifierADM]] can be found */ - def findProject(id: ProjectIdentifierADM): Task[ProjectGetResponseADM] = for { + def findProject(id: ProjectIdentifierADM): Task[ProjectGetResponse] = for { internal <- responder.getSingleProjectADMRequest(id) external <- format.toExternal(internal) } yield external @@ -128,7 +128,7 @@ final case class ProjectsADMRestServiceLive( */ def createProject(createReq: ProjectCreateRequest, user: User): Task[ProjectOperationResponseADM] = for { internal <- ZIO.random.flatMap(_.nextUUID).flatMap(responder.projectCreateRequestADM(createReq, user, _)) - external <- format.toExternal(internal) + external <- format.toExternalADM(internal) } yield external /** @@ -147,7 +147,7 @@ final case class ProjectsADMRestServiceLive( for { apiId <- Random.nextUUID internal <- responder.changeBasicInformationRequestADM(id.value, updatePayload, user, apiId) - external <- format.toExternal(internal) + external <- format.toExternalADM(internal) } yield external } @@ -169,7 +169,7 @@ final case class ProjectsADMRestServiceLive( user: User, ): Task[ProjectOperationResponseADM] = for { internal <- Random.nextUUID.flatMap(responder.changeBasicInformationRequestADM(id.value, updateReq, user, _)) - external <- format.toExternal(internal) + external <- format.toExternalADM(internal) } yield external /** @@ -203,7 +203,7 @@ final case class ProjectsADMRestServiceLive( */ def getProjectMembers(user: User, id: ProjectIdentifierADM): Task[ProjectMembersGetResponseADM] = for { internal <- responder.projectMembersGetRequestADM(id, user) - external <- format.toExternal(internal) + external <- format.toExternalADM(internal) } yield external /** @@ -222,18 +222,18 @@ final case class ProjectsADMRestServiceLive( id: ProjectIdentifierADM, ): Task[ProjectAdminMembersGetResponseADM] = for { internal <- responder.projectAdminMembersGetRequestADM(id, user) - external <- format.toExternal(internal) + external <- format.toExternalADM(internal) } yield external /** * Returns all keywords of all projects. * * @return - * '''success''': list of all keywords as a [[ProjectsKeywordsGetResponseADM]] + * '''success''': list of all keywords as a [[ProjectsKeywordsGetResponse]] * * '''failure''': [[dsp.errors.NotFoundException]] when no project was found */ - def listAllKeywords(): Task[ProjectsKeywordsGetResponseADM] = for { + def listAllKeywords(): Task[ProjectsKeywordsGetResponse] = for { internal <- responder.projectsKeywordsGetRequestADM() external <- format.toExternal(internal) } yield external @@ -243,11 +243,11 @@ final case class ProjectsADMRestServiceLive( * * @param iri the [[ProjectIri]] of the project * @return - * '''success''': ist of all keywords as a [[ProjectKeywordsGetResponseADM]] + * '''success''': ist of all keywords as a [[ProjectKeywordsGetResponse]] * * '''failure''': [[dsp.errors.NotFoundException]] when no project for the given [[ProjectIri]] can be found */ - def getKeywordsByProjectIri(iri: ProjectIri): Task[ProjectKeywordsGetResponseADM] = for { + def getKeywordsByProjectIri(iri: ProjectIri): Task[ProjectKeywordsGetResponse] = for { internal <- responder.projectKeywordsGetRequestADM(iri) external <- format.toExternal(internal) } yield external diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/UsersRestService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/UsersRestService.scala index 997024b435..ff9715c935 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/UsersRestService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/UsersRestService.scala @@ -60,7 +60,7 @@ final case class UsersRestService( .filterOrFail(_.nonEmpty)(NotFoundException("No users found")) .map(_.map(_.filterUserInformation(requestingUser, UserInformationType.Restricted)).sorted) .map(UsersGetResponseADM.apply) - external <- format.toExternal(internal) + external <- format.toExternalADM(internal) } yield external def deleteUser(requestingUser: User, deleteIri: UserIri): Task[UserResponseADM] = for { @@ -83,7 +83,7 @@ final case class UsersRestService( .findUserByIri(userIri) .map(_.map(_.groups).getOrElse(Seq.empty)) .map(UserGroupMembershipsGetResponseADM) - .flatMap(format.toExternal) + .flatMap(format.toExternalADM) def createUser(requestingUser: User, userCreateRequest: Requests.UserCreateRequest): Task[UserResponseADM] = for { @@ -97,7 +97,7 @@ final case class UsersRestService( for { kUser <- getKnoraUserOrNotFound(userIri) projects <- projectService.findByIds(kUser.isInProject) - external <- format.toExternal(UserProjectMembershipsGetResponseADM(projects)) + external <- format.toExternalADM(UserProjectMembershipsGetResponseADM(projects)) } yield external private def getKnoraUserOrNotFound(userIri: UserIri) = @@ -107,7 +107,7 @@ final case class UsersRestService( for { kUser <- getKnoraUserOrNotFound(userIri) projects <- projectService.findByIds(kUser.isInProjectAdminGroup) - external <- format.toExternal(UserProjectAdminMembershipsGetResponseADM(projects)) + external <- format.toExternalADM(UserProjectAdminMembershipsGetResponseADM(projects)) } yield external def getUserByUsername(requestingUser: User, username: Username): Task[UserResponseADM] = for { @@ -219,7 +219,7 @@ final case class UsersRestService( private def asExternalUserResponseADM(requestingUser: User, user: User): Task[UserResponseADM] = { val userFiltered = user.filterUserInformation(requestingUser, UserInformationType.Restricted) - format.toExternal(UserResponseADM(userFiltered)) + format.toExternalADM(UserResponseADM(userFiltered)) } def addUserToProjectAsAdmin( 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 cac2e2778a..e946769479 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 @@ -10,8 +10,8 @@ import zio.* 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.ProjectKeywordsGetResponse +import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectsKeywordsGetResponse import org.knora.webapi.slice.admin.domain.model.KnoraProject import org.knora.webapi.slice.admin.domain.model.KnoraProject.* import org.knora.webapi.slice.admin.domain.model.RestrictedView @@ -76,17 +76,17 @@ final case class ProjectADMService( restrictedView, ) - def findAllProjectsKeywords: Task[ProjectsKeywordsGetResponseADM] = + def findAllProjectsKeywords: Task[ProjectsKeywordsGetResponse] = for { projects <- projectRepo.findAll() keywords = projects.flatMap(_.keywords.map(_.value)).distinct.sorted - } yield ProjectsKeywordsGetResponseADM(keywords) + } yield ProjectsKeywordsGetResponse(keywords) - def findProjectKeywordsBy(id: ProjectIdentifierADM): Task[Option[ProjectKeywordsGetResponseADM]] = + def findProjectKeywordsBy(id: ProjectIdentifierADM): Task[Option[ProjectKeywordsGetResponse]] = for { projectMaybe <- projectRepo.findById(id) keywordsMaybe = projectMaybe.map(_.keywords.map(_.value)) - result = keywordsMaybe.map(ProjectKeywordsGetResponseADM(_)) + result = keywordsMaybe.map(ProjectKeywordsGetResponse(_)) } yield result def getNamedGraphsForProject(project: KnoraProject): Task[List[InternalIri]] = { diff --git a/webapi/src/main/scala/org/knora/webapi/slice/common/api/KnoraResponseRenderer.scala b/webapi/src/main/scala/org/knora/webapi/slice/common/api/KnoraResponseRenderer.scala index 6baafa91b2..cb434aca8a 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/common/api/KnoraResponseRenderer.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/common/api/KnoraResponseRenderer.scala @@ -35,11 +35,17 @@ final class KnoraResponseRenderer(config: AppConfig, stringFormatter: StringForm * @param response the response that should be transformed * @return the transformed [[AdminKnoraResponseADM]] */ - def toExternal[A <: AdminKnoraResponseADM](response: A): Task[A] = + def toExternalADM[A <: AdminKnoraResponseADM](response: A): Task[A] = RouteUtilADM .transformResponseIntoExternalFormat(response) .provide(ZLayer.succeed(stringFormatter)) .mapAttempt(_.asInstanceOf[A]) + + def toExternal[A](response: A): Task[A] = + RouteUtilADM + .transformResponseIntoExternalFormat(response) + .provide(ZLayer.succeed(stringFormatter)) + } object KnoraResponseRenderer {