From 5f840c0006cbf7891b2931ba83dd7e3fc5b75125 Mon Sep 17 00:00:00 2001 From: Raitis Veinbahs Date: Tue, 21 May 2024 13:28:08 +0200 Subject: [PATCH] refactor: Move actor message constructor exceptions, remove the message (#3249) --- .../PermissionsMessagesADMSpec.scala | 68 -------- .../admin/PermissionsResponderSpec.scala | 160 +++++++++++++----- .../PermissionsMessagesADM.scala | 45 ----- .../admin/PermissionsResponder.scala | 50 +++--- 4 files changed, 144 insertions(+), 179 deletions(-) diff --git a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/permissionsmessages/PermissionsMessagesADMSpec.scala b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/permissionsmessages/PermissionsMessagesADMSpec.scala index 6159c4cc67..6ca1764004 100644 --- a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/permissionsmessages/PermissionsMessagesADMSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/permissionsmessages/PermissionsMessagesADMSpec.scala @@ -319,74 +319,6 @@ class PermissionsMessagesADMSpec extends CoreSpec { ) assert(caught.getMessage === s"Anonymous Users are not allowed.") } - - "return 'BadRequest' if the supplied project IRI DefaultObjectAccessPermissionsStringForPropertyGetADM is not valid" in { - val projectIri = "" - val caught = intercept[BadRequestException]( - DefaultObjectAccessPermissionsStringForPropertyGetADM( - projectIri = projectIri, - resourceClassIri = SharedOntologyTestDataADM.IMAGES_BILD_RESOURCE_CLASS, - propertyIri = SharedOntologyTestDataADM.IMAGES_TITEL_PROPERTY, - targetUser = SharedTestDataADM.imagesUser02, - requestingUser = SharedTestDataADM.imagesUser01, - ), - ) - assert(caught.getMessage === s"Invalid project IRI $projectIri") - } - - "return 'BadRequest' if the supplied resourceClass IRI for DefaultObjectAccessPermissionsStringForPropertyGetADM is not valid" in { - val caught = intercept[BadRequestException]( - DefaultObjectAccessPermissionsStringForPropertyGetADM( - projectIri = SharedTestDataADM.imagesProjectIri, - resourceClassIri = SharedTestDataADM.customResourceIRI, - propertyIri = SharedOntologyTestDataADM.IMAGES_TITEL_PROPERTY, - targetUser = SharedTestDataADM.imagesReviewerUser, - requestingUser = SharedTestDataADM.imagesUser01, - ), - ) - // a resource IRI is given instead of a resource class IRI, exception should be thrown. - assert(caught.getMessage === s"Invalid resource class IRI: ${SharedTestDataADM.customResourceIRI}") - } - - "return 'BadRequest' if the supplied property IRI for DefaultObjectAccessPermissionsStringForPropertyGetADM is not valid" in { - val caught = intercept[BadRequestException]( - DefaultObjectAccessPermissionsStringForPropertyGetADM( - projectIri = SharedTestDataADM.imagesProjectIri, - resourceClassIri = SharedOntologyTestDataADM.IMAGES_BILD_RESOURCE_CLASS, - propertyIri = SharedTestDataADM.customValueIRI, - targetUser = SharedTestDataADM.imagesReviewerUser, - requestingUser = SharedTestDataADM.imagesUser01, - ), - ) - // a value IRI is given instead of a property IRI, exception should be thrown. - assert(caught.getMessage === s"Invalid property IRI: ${SharedTestDataADM.customValueIRI}") - } - - "return 'ForbiddenException' if the user requesting DefaultObjectAccessPermissionsStringForPropertyGetADM is not system or project admin" in { - val caught = intercept[ForbiddenException]( - DefaultObjectAccessPermissionsStringForPropertyGetADM( - projectIri = SharedTestDataADM.imagesProjectIri, - resourceClassIri = SharedOntologyTestDataADM.IMAGES_BILD_RESOURCE_CLASS, - propertyIri = SharedOntologyTestDataADM.IMAGES_TITEL_PROPERTY, - targetUser = SharedTestDataADM.imagesReviewerUser, - requestingUser = SharedTestDataADM.imagesUser02, - ), - ) - assert(caught.getMessage === "Default object access permissions can only be queried by system and project admin.") - } - - "return 'BadRequest' if the target user of DefaultObjectAccessPermissionsStringForPropertyGetADM is an Anonymous user" in { - val caught = intercept[BadRequestException]( - DefaultObjectAccessPermissionsStringForPropertyGetADM( - projectIri = SharedTestDataADM.imagesProjectIri, - resourceClassIri = SharedOntologyTestDataADM.IMAGES_BILD_RESOURCE_CLASS, - propertyIri = SharedOntologyTestDataADM.IMAGES_TITEL_PROPERTY, - targetUser = SharedTestDataADM.anonymousUser, - requestingUser = SharedTestDataADM.imagesUser01, - ), - ) - assert(caught.getMessage === s"Anonymous Users are not allowed.") - } } "Default Object Access Permission Create Requests" should { diff --git a/integration/src/test/scala/org/knora/webapi/responders/admin/PermissionsResponderSpec.scala b/integration/src/test/scala/org/knora/webapi/responders/admin/PermissionsResponderSpec.scala index 1eed24cec9..4720e40cdd 100644 --- a/integration/src/test/scala/org/knora/webapi/responders/admin/PermissionsResponderSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/responders/admin/PermissionsResponderSpec.scala @@ -18,12 +18,14 @@ import dsp.errors.ForbiddenException import dsp.errors.NotFoundException import org.knora.webapi.* import org.knora.webapi.messages.OntologyConstants +import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.admin.responder.permissionsmessages.* import org.knora.webapi.messages.store.triplestoremessages.RdfDataObject import org.knora.webapi.messages.util.KnoraSystemInstances import org.knora.webapi.messages.util.PermissionUtilADM import org.knora.webapi.routing.UnsafeZioRun import org.knora.webapi.sharedtestdata.SharedOntologyTestDataADM +import org.knora.webapi.sharedtestdata.SharedOntologyTestDataADM.* import org.knora.webapi.sharedtestdata.SharedPermissionsTestData.* import org.knora.webapi.sharedtestdata.SharedTestDataADM import org.knora.webapi.sharedtestdata.SharedTestDataADM.imagesProjectIri @@ -43,8 +45,8 @@ import org.knora.webapi.util.ZioScalaTestUtil.assertFailsWithA * This spec is used to test the [[PermissionsResponder]] actor. */ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { - private val rootUser = SharedTestDataADM.rootUser + override lazy val rdfDataObjects: List[RdfDataObject] = List( RdfDataObject( path = @@ -61,6 +63,8 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { private val permissionRestService = ZIO.serviceWithZIO[PermissionRestService] private val permissionsResponder = ZIO.serviceWithZIO[PermissionsResponder] + implicit val stringFormatter: StringFormatter = StringFormatter.getGeneralInstance + "The PermissionsResponderADM" when { "ask about administrative permissions " should { @@ -675,18 +679,20 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { } "return the default object access permissions 'string' for the 'knora-base:hasStillImageFileValue' property (system property)" in { - appActor ! DefaultObjectAccessPermissionsStringForPropertyGetADM( - projectIri = SharedTestDataADM.incunabulaProjectIri, - resourceClassIri = OntologyConstants.KnoraBase.StillImageRepresentation, - propertyIri = OntologyConstants.KnoraBase.HasStillImageFileValue, - targetUser = SharedTestDataADM.incunabulaProjectAdminUser, - requestingUser = KnoraSystemInstances.Users.SystemUser, - ) - expectMsg( - DefaultObjectAccessPermissionsStringResponseADM( + UnsafeZioRun + .runOrThrow( + permissionsResponder( + _.getDefaultValuePermissions( + projectIri = SharedTestDataADM.incunabulaProjectIri, + resourceClassIri = stringFormatter.toSmartIri(OntologyConstants.KnoraBase.StillImageRepresentation), + propertyIri = stringFormatter.toSmartIri(OntologyConstants.KnoraBase.HasStillImageFileValue), + targetUser = SharedTestDataADM.incunabulaProjectAdminUser, + ), + ), + ) + .shouldEqual( "M knora-admin:Creator,knora-admin:ProjectMember|V knora-admin:KnownUser,knora-admin:UnknownUser", - ), - ) + ) } "return the default object access permissions 'string' for the 'incunabula:book' resource class (project resource class)" in { @@ -718,18 +724,20 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { } "return the default object access permissions 'string' for the 'anything:hasInterval' property" in { - appActor ! DefaultObjectAccessPermissionsStringForPropertyGetADM( - projectIri = SharedTestDataADM.anythingProjectIri, - resourceClassIri = "http://www.knora.org/ontology/0001/anything#Thing", - propertyIri = "http://www.knora.org/ontology/0001/anything#hasInterval", - targetUser = SharedTestDataADM.anythingUser2, - requestingUser = KnoraSystemInstances.Users.SystemUser, - ) - expectMsg( - DefaultObjectAccessPermissionsStringResponseADM( + UnsafeZioRun + .runOrThrow( + permissionsResponder( + _.getDefaultValuePermissions( + projectIri = SharedTestDataADM.anythingProjectIri, + resourceClassIri = stringFormatter.toSmartIri("http://www.knora.org/ontology/0001/anything#Thing"), + propertyIri = stringFormatter.toSmartIri("http://www.knora.org/ontology/0001/anything#hasInterval"), + targetUser = SharedTestDataADM.anythingUser2, + ), + ), + ) + .shouldEqual( "CR knora-admin:Creator|M knora-admin:ProjectMember|V knora-admin:KnownUser|RV knora-admin:UnknownUser", - ), - ) + ) } "return the default object access permissions 'string' for the 'anything:Thing' class" in { @@ -747,29 +755,96 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { } "return the default object access permissions 'string' for the 'anything:Thing' class and 'anything:hasText' property" in { - appActor ! DefaultObjectAccessPermissionsStringForPropertyGetADM( - projectIri = SharedTestDataADM.anythingProjectIri, - resourceClassIri = "http://www.knora.org/ontology/0001/anything#Thing", - propertyIri = "http://www.knora.org/ontology/0001/anything#hasText", - targetUser = SharedTestDataADM.anythingUser1, - requestingUser = KnoraSystemInstances.Users.SystemUser, - ) - expectMsg(DefaultObjectAccessPermissionsStringResponseADM("CR knora-admin:Creator")) + UnsafeZioRun + .runOrThrow( + permissionsResponder( + _.getDefaultValuePermissions( + projectIri = SharedTestDataADM.anythingProjectIri, + resourceClassIri = stringFormatter.toSmartIri("http://www.knora.org/ontology/0001/anything#Thing"), + propertyIri = stringFormatter.toSmartIri("http://www.knora.org/ontology/0001/anything#hasText"), + targetUser = SharedTestDataADM.anythingUser1, + ), + ), + ) + .shouldEqual("CR knora-admin:Creator") } "return the default object access permissions 'string' for the 'images:Bild' class and 'anything:hasText' property" in { - appActor ! DefaultObjectAccessPermissionsStringForPropertyGetADM( - projectIri = SharedTestDataADM.anythingProjectIri, - resourceClassIri = s"${SharedOntologyTestDataADM.IMAGES_ONTOLOGY_IRI}#bild", - propertyIri = "http://www.knora.org/ontology/0001/anything#hasText", - targetUser = SharedTestDataADM.anythingUser2, - requestingUser = KnoraSystemInstances.Users.SystemUser, - ) - expectMsg( - DefaultObjectAccessPermissionsStringResponseADM( + UnsafeZioRun + .runOrThrow( + permissionsResponder( + _.getDefaultValuePermissions( + projectIri = SharedTestDataADM.anythingProjectIri, + resourceClassIri = stringFormatter.toSmartIri(s"${SharedOntologyTestDataADM.IMAGES_ONTOLOGY_IRI}#bild"), + propertyIri = stringFormatter.toSmartIri("http://www.knora.org/ontology/0001/anything#hasText"), + targetUser = SharedTestDataADM.anythingUser2, + ), + ), + ) + .shouldEqual( "CR knora-admin:Creator|M knora-admin:ProjectMember|V knora-admin:KnownUser|RV knora-admin:UnknownUser", - ), - ) + ) + } + + "return 'BadRequest' if the supplied project IRI DefaultObjectAccessPermissionsStringForPropertyGetADM is not valid" in { + val projectIri = "" + UnsafeZioRun + .runOrThrow( + permissionsResponder( + _.getDefaultValuePermissions( + projectIri = projectIri, + resourceClassIri = stringFormatter.toSmartIri(SharedOntologyTestDataADM.IMAGES_BILD_RESOURCE_CLASS), + propertyIri = stringFormatter.toSmartIri(SharedOntologyTestDataADM.IMAGES_TITEL_PROPERTY), + targetUser = SharedTestDataADM.imagesUser02, + ), + ).flip.map(_.getMessage), + ) + .shouldEqual(s"Invalid project IRI $projectIri") + } + + "return 'BadRequest' if the supplied resourceClass IRI for DefaultObjectAccessPermissionsStringForPropertyGetADM is not valid" in { + UnsafeZioRun + .runOrThrow( + permissionsResponder( + _.getDefaultValuePermissions( + projectIri = SharedTestDataADM.imagesProjectIri, + resourceClassIri = stringFormatter.toSmartIri(SharedTestDataADM.customResourceIRI), + propertyIri = stringFormatter.toSmartIri(SharedOntologyTestDataADM.IMAGES_TITEL_PROPERTY), + targetUser = SharedTestDataADM.imagesReviewerUser, + ), + ).flip.map(_.getMessage), + ) + .shouldEqual(s"Invalid resource class IRI: ${SharedTestDataADM.customResourceIRI}") + } + + "return 'BadRequest' if the supplied property IRI for DefaultObjectAccessPermissionsStringForPropertyGetADM is not valid" in { + UnsafeZioRun + .runOrThrow( + permissionsResponder( + _.getDefaultValuePermissions( + projectIri = SharedTestDataADM.imagesProjectIri, + resourceClassIri = stringFormatter.toSmartIri(SharedOntologyTestDataADM.IMAGES_BILD_RESOURCE_CLASS), + propertyIri = stringFormatter.toSmartIri(SharedTestDataADM.customValueIRI), + targetUser = SharedTestDataADM.imagesReviewerUser, + ), + ).flip.map(_.getMessage), + ) + .shouldEqual(s"Invalid property IRI: ${SharedTestDataADM.customValueIRI}") + } + + "return 'BadRequest' if the target user of DefaultObjectAccessPermissionsStringForPropertyGetADM is an Anonymous user" in { + UnsafeZioRun + .runOrThrow( + permissionsResponder( + _.getDefaultValuePermissions( + projectIri = SharedTestDataADM.imagesProjectIri, + resourceClassIri = stringFormatter.toSmartIri(SharedOntologyTestDataADM.IMAGES_BILD_RESOURCE_CLASS), + propertyIri = stringFormatter.toSmartIri(SharedOntologyTestDataADM.IMAGES_TITEL_PROPERTY), + targetUser = SharedTestDataADM.anonymousUser, + ), + ).flip.map(_.getMessage), + ) + .shouldEqual("Anonymous Users are not allowed.") } "return the default object access permissions 'string' for the 'anything:Thing' resource class for the root user (system admin and not member of project)" in { @@ -785,7 +860,6 @@ class PermissionsResponderSpec extends CoreSpec with ImplicitSender { ), ) } - } "ask to get the permission by IRI" should { diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/permissionsmessages/PermissionsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/permissionsmessages/PermissionsMessagesADM.scala index b55ac23ed5..d6307fd1d2 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/permissionsmessages/PermissionsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/permissionsmessages/PermissionsMessagesADM.scala @@ -313,51 +313,6 @@ case class DefaultObjectAccessPermissionsStringForResourceClassGetADM( if (targetUser.isAnonymousUser) throw BadRequestException("Anonymous Users are not allowed.") } -/** - * A message that requests default object access permissions for a - * resource class / property combination inside a specific project. A successful response will be a - * [[DefaultObjectAccessPermissionsStringResponseADM]]. - * - * NOTE: only used in tests now, can be refactored to a direct call. - * - * @param projectIri the project for which the default object permissions need to be retrieved. - * @param resourceClassIri the resource class which can also cary default object access permissions. - * @param propertyIri the property type which can also cary default object access permissions. - * @param targetUser the user for whom we calculate the permission - * @param requestingUser the requesting user. - */ -case class DefaultObjectAccessPermissionsStringForPropertyGetADM( - projectIri: IRI, - resourceClassIri: IRI, - propertyIri: IRI, - targetUser: User, - requestingUser: User, -) extends PermissionsResponderRequestADM { - - implicit protected val stringFormatter: StringFormatter = StringFormatter.getInstanceForConstantOntologies - ProjectIri.from(projectIri).getOrElse(throw BadRequestException(s"Invalid project IRI $projectIri")) - - // Check user's permission for the operation - if ( - !requestingUser.isSystemAdmin - && !requestingUser.permissions.isProjectAdmin(projectIri) - && !requestingUser.isSystemUser - ) { - // not a system admin - throw ForbiddenException("Default object access permissions can only be queried by system and project admin.") - } - - if (!stringFormatter.toSmartIri(resourceClassIri).isKnoraEntityIri) { - throw BadRequestException(s"Invalid resource class IRI: $resourceClassIri") - } - - if (!stringFormatter.toSmartIri(propertyIri).isKnoraEntityIri) { - throw BadRequestException(s"Invalid property IRI: $propertyIri") - } - - if (targetUser.isAnonymousUser) throw BadRequestException("Anonymous Users are not allowed.") -} - /** * A message that requests a permission (doap or ap) by its IRI. * A successful response will be an [[PermissionGetResponseADM]] object. diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/PermissionsResponder.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/PermissionsResponder.scala index 4d08fa89cf..4d74efac12 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/PermissionsResponder.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/PermissionsResponder.scala @@ -103,20 +103,6 @@ final case class PermissionsResponder( ResourceEntityType, targetUser, ) - case DefaultObjectAccessPermissionsStringForPropertyGetADM( - projectIri, - resourceClassIri, - propertyTypeIri, - targetUser, - _, - ) => - defaultObjectAccessPermissionsStringForEntityGetADM( - projectIri, - resourceClassIri, - Some(propertyTypeIri), - PropertyEntityType, - targetUser, - ) case PermissionByIriGetRequestADM(permissionIri, requestingUser) => permissionByIriGetRequestADM(permissionIri, requestingUser) case other => Responder.handleUnexpectedMessage(other, this.getClass.getName) @@ -1779,15 +1765,33 @@ final case class PermissionsResponder( propertyIri: SmartIri, targetUser: User, ): Task[String] = - defaultObjectAccessPermissionsStringForEntityGetADM( - projectIri = projectIri, - resourceClassIri = resourceClassIri.toString, - propertyIri = Some(propertyIri.toString), - entityType = PropertyEntityType, - targetUser = targetUser, - ).map { - _.permissionLiteral - } + for { + _ <- ZIO.getOrFailWith(BadRequestException(s"Invalid project IRI $projectIri"))( + ProjectIri.from(projectIri).toOption, + ) + + _ <- ZIO.unless(resourceClassIri.isKnoraEntityIri) { + ZIO.fail(BadRequestException(s"Invalid resource class IRI: $resourceClassIri")) + } + + _ <- ZIO.unless(propertyIri.isKnoraEntityIri) { + ZIO.fail(BadRequestException(s"Invalid property IRI: $propertyIri")) + } + + _ <- ZIO.when(targetUser.isAnonymousUser) { + ZIO.fail(BadRequestException("Anonymous Users are not allowed.")) + } + + permissionLiteral <- defaultObjectAccessPermissionsStringForEntityGetADM( + projectIri = projectIri, + resourceClassIri = resourceClassIri.toString, + propertyIri = Some(propertyIri.toString), + entityType = PropertyEntityType, + targetUser = targetUser, + ).map { + _.permissionLiteral + } + } yield permissionLiteral } object PermissionsResponder {