From f0312dc1112365bb53c44c61edfb6f5861f0e974 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Mon, 15 Jan 2024 16:17:16 +0100 Subject: [PATCH] refactor(admin/projects): Add missing internal to external response formatting (#2993) --- .../ProjectsMessagesADM.scala | 26 +++++--- .../api/service/ProjectsADMRestService.scala | 60 +++++++++++++------ .../admin/ProjectsServiceLiveSpec.scala | 18 +++--- 3 files changed, 70 insertions(+), 34 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 3591d8375f..f2e8492a18 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 @@ -30,7 +30,7 @@ import org.knora.webapi.IRI import org.knora.webapi.core.RelayedMessage import org.knora.webapi.messages.ResponderRequest.KnoraRequestADM import org.knora.webapi.messages.StringFormatter -import org.knora.webapi.messages.admin.responder.KnoraResponseADM +import org.knora.webapi.messages.admin.responder.AdminKnoraResponseADM import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM.* import org.knora.webapi.messages.store.triplestoremessages.TriplestoreJsonProtocol import org.knora.webapi.slice.admin.api.model.ProjectsEndpointsRequests.ProjectCreateRequest @@ -161,7 +161,9 @@ case class ProjectChangeRequestADM( * * @param projects information about all existing projects. */ -case class ProjectsGetResponseADM(projects: Seq[ProjectADM]) extends KnoraResponseADM with ProjectsADMJsonProtocol { +case class ProjectsGetResponseADM(projects: Seq[ProjectADM]) + extends AdminKnoraResponseADM + with ProjectsADMJsonProtocol { def toJsValue: JsValue = projectsResponseADMFormat.write(this) } @@ -170,7 +172,7 @@ case class ProjectsGetResponseADM(projects: Seq[ProjectADM]) extends KnoraRespon * * @param project all information about the project. */ -case class ProjectGetResponseADM(project: ProjectADM) extends KnoraResponseADM with ProjectsADMJsonProtocol { +case class ProjectGetResponseADM(project: ProjectADM) extends AdminKnoraResponseADM with ProjectsADMJsonProtocol { def toJsValue: JsValue = projectResponseADMFormat.write(this) } @@ -179,7 +181,7 @@ case class ProjectGetResponseADM(project: ProjectADM) extends KnoraResponseADM w * * @param members a list of members. */ -case class ProjectMembersGetResponseADM(members: Seq[User]) extends KnoraResponseADM with ProjectsADMJsonProtocol { +case class ProjectMembersGetResponseADM(members: Seq[User]) extends AdminKnoraResponseADM with ProjectsADMJsonProtocol { def toJsValue: JsValue = projectMembersGetResponseADMFormat.write(this) } @@ -189,7 +191,9 @@ case class ProjectMembersGetResponseADM(members: Seq[User]) extends KnoraRespons * * @param members a list of admin members. */ -case class ProjectAdminMembersGetResponseADM(members: Seq[User]) extends KnoraResponseADM with ProjectsADMJsonProtocol { +case class ProjectAdminMembersGetResponseADM(members: Seq[User]) + extends AdminKnoraResponseADM + with ProjectsADMJsonProtocol { def toJsValue: JsValue = projectAdminMembersGetResponseADMFormat.write(this) } @@ -199,7 +203,9 @@ case class ProjectAdminMembersGetResponseADM(members: Seq[User]) extends KnoraRe * * @param keywords a list of keywords. */ -case class ProjectsKeywordsGetResponseADM(keywords: Seq[String]) extends KnoraResponseADM with ProjectsADMJsonProtocol { +case class ProjectsKeywordsGetResponseADM(keywords: Seq[String]) + extends AdminKnoraResponseADM + with ProjectsADMJsonProtocol { def toJsValue: JsValue = projectsKeywordsGetResponseADMFormat.write(this) } @@ -208,7 +214,9 @@ case class ProjectsKeywordsGetResponseADM(keywords: Seq[String]) extends KnoraRe * * @param keywords a list of keywords. */ -case class ProjectKeywordsGetResponseADM(keywords: Seq[String]) extends KnoraResponseADM with ProjectsADMJsonProtocol { +case class ProjectKeywordsGetResponseADM(keywords: Seq[String]) + extends AdminKnoraResponseADM + with ProjectsADMJsonProtocol { def toJsValue: JsValue = projectKeywordsGetResponseADMFormat.write(this) } @@ -218,7 +226,7 @@ case class ProjectKeywordsGetResponseADM(keywords: Seq[String]) extends KnoraRes * @param settings the restricted view settings. */ case class ProjectRestrictedViewSettingsGetResponseADM(settings: ProjectRestrictedViewSettingsADM) - extends KnoraResponseADM + extends AdminKnoraResponseADM with ProjectsADMJsonProtocol { def toJsValue: JsValue = projectRestrictedViewGetResponseADMFormat.write(this) } @@ -234,7 +242,7 @@ object ProjectRestrictedViewSizeResponseADM { * * @param project the new project info of the created/modified project. */ -case class ProjectOperationResponseADM(project: ProjectADM) extends KnoraResponseADM with ProjectsADMJsonProtocol { +case class ProjectOperationResponseADM(project: ProjectADM) extends AdminKnoraResponseADM with ProjectsADMJsonProtocol { def toJsValue: JsValue = projectOperationResponseADMFormat.write(this) } 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 062b6e1452..95f60fd389 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 @@ -28,6 +28,7 @@ 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.AuthorizationRestService +import org.knora.webapi.slice.common.api.KnoraResponseRenderer @accessible trait ProjectADMRestService { @@ -76,6 +77,7 @@ trait ProjectADMRestService { } final case class ProjectsADMRestServiceLive( + format: KnoraResponseRenderer, responder: ProjectsResponderADM, projectRepo: KnoraProjectRepo, projectExportService: ProjectExportService, @@ -91,8 +93,10 @@ final case class ProjectsADMRestServiceLive( * * '''failure''': [[dsp.errors.NotFoundException]] when no project was found */ - def listAllProjects(): Task[ProjectsGetResponseADM] = - responder.projectsGetRequestADM(withSystemProjects = false) + def listAllProjects(): Task[ProjectsGetResponseADM] = for { + internal <- responder.projectsGetRequestADM(withSystemProjects = false) + external <- format.toExternal(internal) + } yield external /** * Finds the project by its [[ProjectIdentifierADM]] and returns the information as a [[ProjectGetResponseADM]]. @@ -103,7 +107,10 @@ final case class ProjectsADMRestServiceLive( * * '''failure''': [[dsp.errors.NotFoundException]] when no project for the given [[ProjectIdentifierADM]] can be found */ - def findProject(id: ProjectIdentifierADM): Task[ProjectGetResponseADM] = responder.getSingleProjectADMRequest(id) + def findProject(id: ProjectIdentifierADM): Task[ProjectGetResponseADM] = for { + internal <- responder.getSingleProjectADMRequest(id) + external <- format.toExternal(internal) + } yield external /** * Creates a project from the given payload. @@ -117,8 +124,10 @@ final case class ProjectsADMRestServiceLive( * can be found, if one was provided with the [[ProjectCreateRequest]] * [[dsp.errors.ForbiddenException]] when the requesting user is not allowed to perform the operation */ - def createProject(createReq: ProjectCreateRequest, user: User): Task[ProjectOperationResponseADM] = - ZIO.random.flatMap(_.nextUUID).flatMap(responder.projectCreateRequestADM(createReq, user, _)) + def createProject(createReq: ProjectCreateRequest, user: User): Task[ProjectOperationResponseADM] = for { + internal <- ZIO.random.flatMap(_.nextUUID).flatMap(responder.projectCreateRequestADM(createReq, user, _)) + external <- format.toExternal(internal) + } yield external /** * Deletes the project by its [[ProjectIri]]. @@ -135,8 +144,9 @@ final case class ProjectsADMRestServiceLive( val updatePayload = ProjectUpdateRequest(status = Some(Status.Inactive)) for { apiId <- Random.nextUUID - response <- responder.changeBasicInformationRequestADM(id.value, updatePayload, user, apiId) - } yield response + internal <- responder.changeBasicInformationRequestADM(id.value, updatePayload, user, apiId) + external <- format.toExternal(internal) + } yield external } /** @@ -155,8 +165,10 @@ final case class ProjectsADMRestServiceLive( id: IriIdentifier, updateReq: ProjectUpdateRequest, user: User - ): Task[ProjectOperationResponseADM] = - Random.nextUUID.flatMap(responder.changeBasicInformationRequestADM(id.value, updateReq, user, _)) + ): Task[ProjectOperationResponseADM] = for { + internal <- Random.nextUUID.flatMap(responder.changeBasicInformationRequestADM(id.value, updateReq, user, _)) + external <- format.toExternal(internal) + } yield external /** * Returns all data of a specific project, identified by its [[ProjectIri]]. @@ -187,8 +199,10 @@ final case class ProjectsADMRestServiceLive( * '''failure''': [[dsp.errors.NotFoundException]] when no project for the given [[ProjectIdentifierADM]] can be found * [[dsp.errors.ForbiddenException]] when the requesting user is not allowed to perform the operation */ - def getProjectMembers(user: User, id: ProjectIdentifierADM): Task[ProjectMembersGetResponseADM] = - responder.projectMembersGetRequestADM(id, user) + def getProjectMembers(user: User, id: ProjectIdentifierADM): Task[ProjectMembersGetResponseADM] = for { + internal <- responder.projectMembersGetRequestADM(id, user) + external <- format.toExternal(internal) + } yield external /** * Returns all project admins of a specific project, identified by its [[ProjectIdentifierADM]]. @@ -204,8 +218,10 @@ final case class ProjectsADMRestServiceLive( def getProjectAdminMembers( user: User, id: ProjectIdentifierADM - ): Task[ProjectAdminMembersGetResponseADM] = - responder.projectAdminMembersGetRequestADM(id, user) + ): Task[ProjectAdminMembersGetResponseADM] = for { + internal <- responder.projectAdminMembersGetRequestADM(id, user) + external <- format.toExternal(internal) + } yield external /** * Returns all keywords of all projects. @@ -215,7 +231,10 @@ final case class ProjectsADMRestServiceLive( * * '''failure''': [[dsp.errors.NotFoundException]] when no project was found */ - def listAllKeywords(): Task[ProjectsKeywordsGetResponseADM] = responder.projectsKeywordsGetRequestADM() + def listAllKeywords(): Task[ProjectsKeywordsGetResponseADM] = for { + internal <- responder.projectsKeywordsGetRequestADM() + external <- format.toExternal(internal) + } yield external /** * Returns all keywords of a specific project, identified by its [[ProjectIri]]. @@ -226,8 +245,10 @@ final case class ProjectsADMRestServiceLive( * * '''failure''': [[dsp.errors.NotFoundException]] when no project for the given [[ProjectIri]] can be found */ - def getKeywordsByProjectIri(iri: ProjectIri): Task[ProjectKeywordsGetResponseADM] = - responder.projectKeywordsGetRequestADM(iri) + def getKeywordsByProjectIri(iri: ProjectIri): Task[ProjectKeywordsGetResponseADM] = for { + internal <- responder.projectKeywordsGetRequestADM(iri) + external <- format.toExternal(internal) + } yield external /** * Returns the restricted view settings of a specific project, identified by its [[ProjectIri]]. @@ -239,7 +260,10 @@ final case class ProjectsADMRestServiceLive( * '''failure''': [[dsp.errors.NotFoundException]] when no project for the given [[ProjectIri]] can be found */ def getProjectRestrictedViewSettings(id: ProjectIdentifierADM): Task[ProjectRestrictedViewSettingsGetResponseADM] = - responder.projectRestrictedViewSettingsGetRequestADM(id) + for { + internal <- responder.projectRestrictedViewSettingsGetRequestADM(id) + external <- format.toExternal(internal) + } yield external /** * Sets project's restricted view settings. @@ -296,7 +320,7 @@ final case class ProjectsADMRestServiceLive( object ProjectsADMRestServiceLive { val layer: URLayer[ - ProjectsResponderADM & KnoraProjectRepo & ProjectExportService & ProjectImportService & AuthorizationRestService, + KnoraResponseRenderer & ProjectsResponderADM & KnoraProjectRepo & ProjectExportService & ProjectImportService & AuthorizationRestService, ProjectsADMRestServiceLive ] = ZLayer.fromFunction(ProjectsADMRestServiceLive.apply _) } 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 28dc8eb510..af5fece636 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 @@ -27,6 +27,8 @@ 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.slice.common.api.AuthorizationRestServiceLive +import org.knora.webapi.slice.common.api.KnoraResponseRenderer object ProjectsServiceLiveSpec extends ZIOSpecDefault { @@ -63,15 +65,17 @@ object ProjectsServiceLiveSpec extends ZIOSpecDefault { private def projectServiceLayer(exp: Expectation[ProjectsResponderADM]): ULayer[ProjectADMRestService] = ZLayer.make[ProjectADMRestService]( - ProjectsADMRestServiceLive.layer, - exp.toLayer, - org.knora.webapi.slice.common.api.AuthorizationRestServiceLive.layer, - ProjectExportServiceStub.layer, + AppConfig.layer, + AuthorizationRestServiceLive.layer, + DspIngestClientMock.layer, KnoraProjectRepoInMemory.layer, - ProjectImportServiceLive.layer, + KnoraResponseRenderer.layer, + ProjectExportServiceStub.layer, ProjectExportStorageServiceLive.layer, - AppConfig.layer, - DspIngestClientMock.layer + ProjectImportServiceLive.layer, + ProjectsADMRestServiceLive.layer, + StringFormatter.live, + exp.toLayer ) val getAllProjectsSpec: Spec[Any, Throwable] = test("get all projects") {