From 90fb75e7a0a9a8f54586b88f8c4e7021b7875688 Mon Sep 17 00:00:00 2001 From: Sepideh Alassi Date: Wed, 27 Jan 2021 17:59:50 +0100 Subject: [PATCH 1/4] fix (createPermission) don't try to get GroupADM object for given built-in groups --- .../admin/PermissionsResponderADM.scala | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/PermissionsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/PermissionsResponderADM.scala index 8e4a30cf75..57c3d52f4a 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/PermissionsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/PermissionsResponderADM.scala @@ -638,16 +638,21 @@ class PermissionsResponderADM(responderData: ResponderData) extends Responder(re throw NotFoundException(s"Project '${createRequest.forProject}' not found. Aborting request.")) // get group - maybeGroup <- (responderManager ? GroupGetADM( - groupIri = createRequest.forGroup, - featureFactoryConfig = featureFactoryConfig, - requestingUser = KnoraSystemInstances.Users.SystemUser - )).mapTo[Option[GroupADM]] - - // if it does not exist then throw an error - group: GroupADM = maybeGroup.getOrElse( - throw NotFoundException(s"Group '${createRequest.forGroup}' not found. Aborting request.")) - + groupIri: IRI <- if (OntologyConstants.KnoraAdmin.BuiltInGroups.contains(createRequest.forGroup)) { + Future.successful(createRequest.forGroup) + } else { + for { + maybeGroup <- (responderManager ? GroupGetADM( + groupIri = createRequest.forGroup, + featureFactoryConfig = featureFactoryConfig, + requestingUser = KnoraSystemInstances.Users.SystemUser + )).mapTo[Option[GroupADM]] + + // if it does not exist then throw an error + group: GroupADM = maybeGroup.getOrElse( + throw NotFoundException(s"Group '${createRequest.forGroup}' not found. Aborting request.")) + } yield group.id + } customPermissionIri: Option[SmartIri] = createRequest.id.map(iri => iri.toSmartIri) newPermissionIri: IRI <- checkOrCreateEntityIri(customPermissionIri, stringFormatter.makeRandomPermissionIri(project.shortcode)) @@ -660,7 +665,7 @@ class PermissionsResponderADM(responderData: ResponderData) extends Responder(re permissionClassIri = OntologyConstants.KnoraAdmin.AdministrativePermission, permissionIri = newPermissionIri, projectIri = project.id, - groupIri = group.id, + groupIri = groupIri, permissions = PermissionUtilADM.formatPermissionADMs(createRequest.hasPermissions, PermissionType.AP) ) .toString From c371675dc0e1ce08dfc2c7a6bef8b51c04a6f192 Mon Sep 17 00:00:00 2001 From: Sepideh Alassi Date: Wed, 27 Jan 2021 18:01:52 +0100 Subject: [PATCH 2/4] test (creatPermission) test ap creation for new project and a builtin group --- .../e2e/admin/PermissionsADME2ESpec.scala | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/admin/PermissionsADME2ESpec.scala b/webapi/src/test/scala/org/knora/webapi/e2e/admin/PermissionsADME2ESpec.scala index 7a7c859f5b..78a8737852 100644 --- a/webapi/src/test/scala/org/knora/webapi/e2e/admin/PermissionsADME2ESpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/e2e/admin/PermissionsADME2ESpec.scala @@ -263,6 +263,45 @@ class PermissionsADME2ESpec extends E2ESpec(PermissionsADME2ESpec.config) with T ) } + "create a new administrative permission for a new project" in { + val projectIri = "http://rdfh.ch/projects/3333" + val projectPayload = + s""" + |{ + | "projectIri": "$projectIri", + | "shortname": "newprojectWithIri", + | "shortcode": "3333", + | "longname": "new project with a custom IRI", + | "description": [{"value": "a project created with a custom IRI", "language": "en"}], + | "keywords": ["projectIRI"], + | "logo": "/fu/bar/baz.jpg", + | "status": true, + | "selfjoin": false + | + |} + |""".stripMargin + + val request = Post(baseApiUrl + s"/admin/projects", HttpEntity(ContentTypes.`application/json`, projectPayload)) ~> addCredentials( + BasicHttpCredentials(SharedTestDataADM.rootUser.email, SharedTestDataADM.testPass)) + val response: HttpResponse = singleAwaitingRequest(request) + response.status should be(StatusCodes.OK) + + val permissionPayload = + s"""{ + | "forGroup":"http://www.knora.org/ontology/knora-admin#ProjectMember", + | "forProject":"$projectIri", + | "hasPermissions":[{"additionalInformation":null,"name":"ProjectAdminGroupAllPermission","permissionCode":null}] + |}""".stripMargin + + val permissionRequest = Post(baseApiUrl + s"/admin/permissions/ap", + HttpEntity(ContentTypes.`application/json`, permissionPayload)) ~> addCredentials( + BasicHttpCredentials(SharedTestDataADM.rootUser.email, SharedTestDataADM.testPass)) + + val permissionResponse: HttpResponse = singleAwaitingRequest(permissionRequest) + assert(permissionResponse.status === StatusCodes.OK) + + } + "create a default object access permission" in { val createDefaultObjectAccessPermissionRequest: String = s"""{ From 54bd0ca12a2276e4d380378de9cb03796e51c889 Mon Sep 17 00:00:00 2001 From: Sepideh Alassi Date: Thu, 28 Jan 2021 12:13:42 +0100 Subject: [PATCH 3/4] fix (permissions) add the missing test data --- webapi/scripts/expected-client-test-data.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/webapi/scripts/expected-client-test-data.txt b/webapi/scripts/expected-client-test-data.txt index 68ac280a99..cfa31871f6 100644 --- a/webapi/scripts/expected-client-test-data.txt +++ b/webapi/scripts/expected-client-test-data.txt @@ -98,6 +98,8 @@ test-data/admin/permissions/create-defaultObjectAccess-permission-request.json test-data/admin/permissions/create-defaultObjectAccess-permission-response.json test-data/admin/permissions/create-defaultObjectAccess-permission-withCustomIRI-request.json test-data/admin/permissions/create-defaultObjectAccess-permission-withCustomIRI-response.json +test-data/admin/permissions/delete-administrative-permission-response.json +test-data/admin/permissions/delete-defaultObjectAccess-permission-response.json test-data/admin/permissions/get-administrative-permission-for-project-group-response.json test-data/admin/permissions/get-administrative-permissions-for-project-response.json test-data/admin/permissions/get-defaultObjectAccess-permissions-for-project-response.json From 3d92d5077ca90971d26460c2c488130b3d12d0b2 Mon Sep 17 00:00:00 2001 From: Sepideh Alassi Date: Thu, 28 Jan 2021 16:13:49 +0100 Subject: [PATCH 4/4] test (permission) validate given group IRI + tests --- .../PermissionsMessagesADM.scala | 13 +++++-- .../admin/PermissionsResponderADM.scala | 23 +++++++++++- .../PermissionsMessagesADMSpec.scala | 35 ++++++++++++++++++- 3 files changed, 67 insertions(+), 4 deletions(-) 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 47fb0447fa..e0c75a9bae 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 @@ -59,6 +59,9 @@ case class CreateAdministrativePermissionAPIRequestADM(id: Option[IRI] = None, id, throw BadRequestException(s"Invalid permission IRI ${id.get} is given.")) if (hasPermissions.isEmpty) throw BadRequestException("Permissions needs to be supplied.") + if (!OntologyConstants.KnoraAdmin.BuiltInGroups.contains(forGroup)) { + stringFormatter.validateGroupIri(forGroup, throw BadRequestException(s"Invalid group IRI ${forGroup}")) + } } /** @@ -85,18 +88,24 @@ case class CreateDefaultObjectAccessPermissionAPIRequestADM(id: Option[IRI] = No stringFormatter.validateOptionalPermissionIri( id, throw BadRequestException(s"Invalid permission IRI ${id.get} is given.")) + forGroup match { case Some(iri: IRI) => if (forResourceClass.isDefined) throw BadRequestException("Not allowed to supply groupIri and resourceClassIri together.") else if (forProperty.isDefined) throw BadRequestException("Not allowed to supply groupIri and propertyIri together.") - else Some(iri) + else { + if (!OntologyConstants.KnoraAdmin.BuiltInGroups.contains(iri)) { + stringFormatter.validateOptionalGroupIri(forGroup, + throw BadRequestException(s"Invalid group IRI ${forGroup.get}")) + } + } case None => if (forResourceClass.isEmpty && forProperty.isEmpty) { throw BadRequestException( "Either a group, a resource class, a property, or a combination of resource class and property must be given.") - } else None + } } forResourceClass match { diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/PermissionsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/PermissionsResponderADM.scala index 57c3d52f4a..01d294017d 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/PermissionsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/PermissionsResponderADM.scala @@ -1463,6 +1463,27 @@ class PermissionsResponderADM(responderData: ResponderData) extends Responder(re customPermissionIri: Option[SmartIri] = createRequest.id.map(iri => iri.toSmartIri) newPermissionIri: IRI <- checkOrCreateEntityIri(customPermissionIri, stringFormatter.makeRandomPermissionIri(project.shortcode)) + // verify group, if any given. + // Is a group given that is not a built-in one? + maybeGroupIri: Option[IRI] <- if (createRequest.forGroup.exists( + !OntologyConstants.KnoraAdmin.BuiltInGroups.contains(_))) { + // Yes. Check if it is a known group. + for { + maybeGroup <- (responderManager ? GroupGetADM( + groupIri = createRequest.forGroup.get, + featureFactoryConfig = featureFactoryConfig, + requestingUser = KnoraSystemInstances.Users.SystemUser + )).mapTo[Option[GroupADM]] + + group: GroupADM = maybeGroup.getOrElse( + throw NotFoundException(s"Group '${createRequest.forGroup}' not found. Aborting request.")) + } yield Some(group.id) + } else { + // No, return given group as it is. That means: + // If given group is a built-in one, no verification is necessary, return it as it is. + // In case no group IRI is given, returns None. + Future.successful(createRequest.forGroup) + } // Create the default object access permission. createNewDefaultObjectAccessPermissionSparqlString = org.knora.webapi.messages.twirl.queries.sparql.admin.txt @@ -1472,7 +1493,7 @@ class PermissionsResponderADM(responderData: ResponderData) extends Responder(re permissionIri = newPermissionIri, permissionClassIri = OntologyConstants.KnoraAdmin.DefaultObjectAccessPermission, projectIri = project.id, - maybeGroupIri = createRequest.forGroup, + maybeGroupIri = maybeGroupIri, maybeResourceClassIri = createRequest.forResourceClass, maybePropertyIri = createRequest.forProperty, permissions = PermissionUtilADM.formatPermissionADMs(createRequest.hasPermissions, PermissionType.OAP) diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/permissionsmessages/PermissionsMessagesADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/permissionsmessages/PermissionsMessagesADMSpec.scala index 203d328be0..3ab7a5a238 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/permissionsmessages/PermissionsMessagesADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/permissionsmessages/PermissionsMessagesADMSpec.scala @@ -119,6 +119,23 @@ class PermissionsMessagesADMSpec extends CoreSpec() { assert(caught.getMessage === "Invalid project IRI") } + "return 'BadRequest' if the supplied group IRI for AdministrativePermissionCreateRequestADM is not valid" in { + val groupIri = "invalid-group-iri" + val caught = intercept[BadRequestException]( + AdministrativePermissionCreateRequestADM( + createRequest = CreateAdministrativePermissionAPIRequestADM( + forProject = SharedTestDataADM.ANYTHING_PROJECT_IRI, + forGroup = groupIri, + hasPermissions = Set(PermissionADM.ProjectAdminAllPermission) + ), + featureFactoryConfig = defaultFeatureFactoryConfig, + requestingUser = SharedTestDataADM.imagesUser01, + apiRequestID = UUID.randomUUID() + ) + ) + assert(caught.getMessage === s"Invalid group IRI $groupIri") + } + "return 'BadRequest' if the supplied permission IRI for AdministrativePermissionCreateRequestADM is not valid" in { val permissionIri = "invalid-permission-IRI" val caught = intercept[BadRequestException]( @@ -428,7 +445,6 @@ class PermissionsMessagesADMSpec extends CoreSpec() { ) assert(caught.getMessage === s"Anonymous Users are not allowed.") } - } "Default Object Access Permission Create Requests" should { @@ -448,6 +464,23 @@ class PermissionsMessagesADMSpec extends CoreSpec() { assert(caught.getMessage === "Invalid project IRI") } + "return 'BadRequest' if the supplied group IRI for DefaultObjectAccessPermissionCreateRequestADM is not valid" in { + val groupIri = "invalid-group-iri" + val caught = intercept[BadRequestException]( + DefaultObjectAccessPermissionCreateRequestADM( + createRequest = CreateDefaultObjectAccessPermissionAPIRequestADM( + forProject = SharedTestDataADM.ANYTHING_PROJECT_IRI, + forGroup = Some(groupIri), + hasPermissions = Set(PermissionADM.changeRightsPermission(OntologyConstants.KnoraAdmin.ProjectMember)) + ), + featureFactoryConfig = defaultFeatureFactoryConfig, + requestingUser = SharedTestDataADM.imagesUser01, + apiRequestID = UUID.randomUUID() + ) + ) + assert(caught.getMessage === s"Invalid group IRI $groupIri") + } + "return 'BadRequest' if the supplied custom permission IRI for DefaultObjectAccessPermissionCreateRequestADM is not valid" in { val permissionIri = "invalid-permission-IRI" val caught = intercept[BadRequestException](