From 8c3d0da9d9473905377202d6dc04aac7052f4bc3 Mon Sep 17 00:00:00 2001 From: Prarup Gurung Date: Mon, 18 Dec 2023 13:08:45 +0545 Subject: [PATCH 1/3] Added test for sending share invitation to user with role --- tests/TestHelpers/GraphHelper.php | 91 +++++++++++++++++ .../apiSharingNg/shareInvitations.feature | 99 +++++++++++++++++++ .../features/bootstrap/FeatureContext.php | 16 +++ .../features/bootstrap/SharingNgContext.php | 38 ++++++- 4 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 tests/acceptance/features/apiSharingNg/shareInvitations.feature diff --git a/tests/TestHelpers/GraphHelper.php b/tests/TestHelpers/GraphHelper.php index 524e9862b02..773f2f455fe 100644 --- a/tests/TestHelpers/GraphHelper.php +++ b/tests/TestHelpers/GraphHelper.php @@ -60,6 +60,13 @@ public static function getSpaceIdRegex(): string { return self::getUUIDv4Regex() . '\\\$' . self::getUUIDv4Regex(); } + /** + * @return string + */ + public static function getShareIdRegex(): string { + return self::getUUIDv4Regex() . ':' . self::getUUIDv4Regex() . ':' . self::getUUIDv4Regex(); + } + /** * Key name can consist of @@@ * This function separate such key and return its actual value from actual drive response which can be used for assertion @@ -1532,4 +1539,88 @@ public static function getPermissionsList( self::getRequestHeaders() ); } + + /** + * Get the role id by name + * + * @param string $baseUrl + * @param string $xRequestId + * @param string $user + * @param string $password + * @param string $role + * + * @return string + * + */ + public static function getRoleIdByName( + string $baseUrl, + string $xRequestId, + string $user, + string $password, + string $role + ) : string { + $url = self::getBetaFullUrl($baseUrl, "roleManagement/permissions/roleDefinitions"); + + $response = HttpRequestHelper::get( + $url, + $xRequestId, + $user, + $password, + self::getRequestHeaders(), + ); + + $roles = \json_decode($response->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR); + + if (isset($roles)) { + foreach ($roles as $item) { + if ($item["displayName"] === $role) { + return $item["id"]; + } + } + } + } + + /** + * @param string $baseUrl + * @param string $xRequestId + * @param string $user + * @param string $password + * @param string $spaceId + * @param string $itemId + * @param string $shareeId + * @param string|null $role + * + * @return ResponseInterface + * @throws \JsonException + */ + public static function sendSharingInvitation( + string $baseUrl, + string $xRequestId, + string $user, + string $password, + string $spaceId, + string $itemId, + string $shareeId, + ?string $role + ): ResponseInterface { + $url = self::getBetaFullUrl($baseUrl, "drives/$spaceId/items/$itemId/invite"); + $body = []; + + $recipients['objectId'] = $shareeId; + $body['recipients'] = [$recipients]; + + if ($role !== null) { + $roleId = self::getRoleIdByName($baseUrl, $xRequestId, $user, $password, $role); + $body['roles'] = [$roleId]; + } + + return HttpRequestHelper::post( + $url, + $xRequestId, + $user, + $password, + self::getRequestHeaders(), + \json_encode($body) + ); + } } diff --git a/tests/acceptance/features/apiSharingNg/shareInvitations.feature b/tests/acceptance/features/apiSharingNg/shareInvitations.feature new file mode 100644 index 00000000000..708ff97d4c0 --- /dev/null +++ b/tests/acceptance/features/apiSharingNg/shareInvitations.feature @@ -0,0 +1,99 @@ +Feature: Send a sharing invitations + As the owner of a resource + I want to be able to send invitations to other users + So that they can have access to it + + https://owncloud.dev/libre-graph-api/#/drives.permissions/Invite + + Background: + Given these users have been created with default attributes and without skeleton files: + | username | + | Alice | + | Brian | + + + Scenario Outline: send sharing invitation to user with different roles via the Graph API + Given user "Alice" has uploaded file with content "to share" to "/textfile1.txt" + And user "Alice" has created folder "FolderToShare" + When user "Alice" sends the following share invitation using the Graph API: + | resourceType | | + | resource | | + | space | Personal | + | sharee | Brian | + | shareType | user | + | role | | + Then the HTTP status code should be "200" + And the JSON data of the response should match + """ + { + "type": "object", + "required": [ + "value" + ], + "properties": { + "value": { + "type": "array", + "items": { + "type": "object", + "required": [ + "id", + "roles", + "grantedToV2" + ], + "properties": { + "id": { + "type": "string", + "pattern": "^%share_id_pattern%$" + }, + "roles": { + "type": "array", + "items": { + "type": "string", + "pattern": "^%role_id_pattern%$" + } + }, + "grantedToV2": { + "type": "object", + "required": [ + "user" + ], + "properties": { + "user": { + "type": "object", + "required": [ + "id", + "displayName" + ], + "properties": { + "id": { + "type": "string", + "pattern": "^%user_id_pattern%$" + }, + "displayName": { + "type": "string", + "enum": [ + "Brian Murphy" + ] + } + } + } + } + } + } + } + } + } + } + """ + Examples: + | role | resource-type | path | + | Viewer | file | /textfile1.txt | + | Editor | file | /textfile1.txt | + | Co Owner | file | /textfile1.txt | + | Uploader | file | /textfile1.txt | + | Manager | file | /textfile1.txt | + | Viewer | folder | FolderToShare | + | Editor | folder | FolderToShare | + | Co Owner | folder | FolderToShare | + | Uploader | folder | FolderToShare | + | Manager | folder | FolderToShare | diff --git a/tests/acceptance/features/bootstrap/FeatureContext.php b/tests/acceptance/features/bootstrap/FeatureContext.php index 39ca02c7f66..a927e90c900 100644 --- a/tests/acceptance/features/bootstrap/FeatureContext.php +++ b/tests/acceptance/features/bootstrap/FeatureContext.php @@ -2783,6 +2783,22 @@ public function substituteInLineCodes( $this, "getGroupIdByGroupName" ], "parameter" => [$group] + ], + [ + "code" => "%role_id_pattern%", + "function" => [ + __NAMESPACE__ . '\TestHelpers\GraphHelper', + "getUUIDv4Regex" + ], + "parameter" => [] + ], + [ + "code" => "%share_id_pattern%", + "function" => [ + __NAMESPACE__ . '\TestHelpers\GraphHelper', + "getShareIdRegex" + ], + "parameter" => [] ] ]; if ($user !== null) { diff --git a/tests/acceptance/features/bootstrap/SharingNgContext.php b/tests/acceptance/features/bootstrap/SharingNgContext.php index c3de67cd570..8ab05cfb87d 100644 --- a/tests/acceptance/features/bootstrap/SharingNgContext.php +++ b/tests/acceptance/features/bootstrap/SharingNgContext.php @@ -22,6 +22,7 @@ use Behat\Behat\Context\Context; use Behat\Behat\Hook\Scope\BeforeScenarioScope; use TestHelpers\GraphHelper; +use Behat\Gherkin\Node\TableNode; require_once 'bootstrap.php'; @@ -63,7 +64,7 @@ public function before(BeforeScenarioScope $scope): void { */ public function theUserPermissionsListOfResource(string $user, string $fileOrFolder, string $resource, string $space):void { $spaceId = ($this->spacesContext->getSpaceByName($user, $space))["id"]; - + if ($fileOrFolder === 'folder') { $itemId = $this->spacesContext->getResourceId($user, $space, $resource); } else { @@ -80,4 +81,39 @@ public function theUserPermissionsListOfResource(string $user, string $fileOrFol ) ); } + + /** + * @When /^user "([^"]*)" sends the following share invitation using the Graph API:$/ + * + * @param string $user + * @param TableNode $table + * + * @return void + * @throws Exception + */ + public function userSendsTheFollowingShareInvitationUsingTheGraphApi(string $user, TableNode $table) { + $rows = $table->getRowsHash(); + $spaceId = ($this->spacesContext->getSpaceByName($user, $rows['space']))["id"]; + + $itemId = ($rows['resourceType'] === 'folder') + ? $this->spacesContext->getResourceId($user, $rows['space'], $rows['resource']) + : $this->spacesContext->getFileId($user, $rows['space'], $rows['resource']); + + $shareeId = ($rows['shareType'] === 'user') + ? $this->featureContext->getAttributeOfCreatedUser($rows['sharee'], 'id') + : $this->featureContext->getAttributeOfCreatedGroup($rows['sharee'], 'id'); + + $this->featureContext->setResponse( + GraphHelper::sendSharingInvitation( + $this->featureContext->getBaseUrl(), + $this->featureContext->getStepLineRef(), + $user, + $this->featureContext->getPasswordForUser($user), + $spaceId, + $itemId, + $shareeId, + $rows['role'] + ) + ); + } } From 3fad33332c7f01a618a37115dcb7947139586440 Mon Sep 17 00:00:00 2001 From: Prarup Gurung Date: Tue, 19 Dec 2023 13:03:04 +0545 Subject: [PATCH 2/3] Added test for sending share invitation to group with role --- tests/TestHelpers/GraphHelper.php | 5 + .../apiSharingNg/shareInvitations.feature | 93 +++++++++++++++++++ .../features/bootstrap/SharingNgContext.php | 3 +- 3 files changed, 100 insertions(+), 1 deletion(-) diff --git a/tests/TestHelpers/GraphHelper.php b/tests/TestHelpers/GraphHelper.php index 773f2f455fe..b2deb73f5e3 100644 --- a/tests/TestHelpers/GraphHelper.php +++ b/tests/TestHelpers/GraphHelper.php @@ -1601,11 +1601,16 @@ public static function sendSharingInvitation( string $spaceId, string $itemId, string $shareeId, + ?string $shareType, ?string $role ): ResponseInterface { $url = self::getBetaFullUrl($baseUrl, "drives/$spaceId/items/$itemId/invite"); $body = []; + if ($shareType === 'group') { + $recipients['@libre.graph.recipient.type'] = 'group'; + } + $recipients['objectId'] = $shareeId; $body['recipients'] = [$recipients]; diff --git a/tests/acceptance/features/apiSharingNg/shareInvitations.feature b/tests/acceptance/features/apiSharingNg/shareInvitations.feature index 708ff97d4c0..fe8d6f3beb9 100644 --- a/tests/acceptance/features/apiSharingNg/shareInvitations.feature +++ b/tests/acceptance/features/apiSharingNg/shareInvitations.feature @@ -97,3 +97,96 @@ Feature: Send a sharing invitations | Co Owner | folder | FolderToShare | | Uploader | folder | FolderToShare | | Manager | folder | FolderToShare | + + + Scenario Outline: send sharing invitation to group with different roles via the Graph API + Given user "Carol" has been created with default attributes and without skeleton files + And group "grp1" has been created + And the following users have been added to the following groups + | username | groupname | + | Brian | grp1 | + | Carol | grp1 | + And user "Alice" has uploaded file with content "to share" to "/textfile1.txt" + And user "Alice" has created folder "FolderToShare" + When user "Alice" sends the following share invitation using the Graph API: + | resourceType | | + | resource | | + | space | Personal | + | sharee | grp1 | + | shareType | group | + | role | | + Then the HTTP status code should be "200" + And the JSON data of the response should match + """ + { + "type": "object", + "required": [ + "value" + ], + "properties": { + "value": { + "type": "array", + "items": { + "type": "object", + "required": [ + "id", + "roles", + "grantedToV2" + ], + "properties": { + "id": { + "type": "string", + "pattern": "^%share_id_pattern%$" + }, + "roles": { + "type": "array", + "items": { + "type": "string", + "pattern": "^%role_id_pattern%$" + } + }, + "grantedToV2": { + "type": "object", + "required": [ + "group" + ], + "properties": { + "group": { + "type": "object", + "required": [ + "id", + "displayName" + ], + "properties": { + "id": { + "type": "string", + "pattern": "^%group_id_pattern%$" + }, + "displayName": { + "type": "string", + "enum": [ + "grp1" + ] + } + } + } + } + } + } + } + } + } + } + """ + Examples: + | role | resource-type | path | + | Viewer | file | /textfile1.txt | + | Editor | file | /textfile1.txt | + | Co Owner | file | /textfile1.txt | + | Uploader | file | /textfile1.txt | + | Manager | file | /textfile1.txt | + | Viewer | folder | FolderToShare | + | Editor | folder | FolderToShare | + | Co Owner | folder | FolderToShare | + | Uploader | folder | FolderToShare | + | Manager | folder | FolderToShare | diff --git a/tests/acceptance/features/bootstrap/SharingNgContext.php b/tests/acceptance/features/bootstrap/SharingNgContext.php index 8ab05cfb87d..6d1a37c4d0e 100644 --- a/tests/acceptance/features/bootstrap/SharingNgContext.php +++ b/tests/acceptance/features/bootstrap/SharingNgContext.php @@ -91,7 +91,7 @@ public function theUserPermissionsListOfResource(string $user, string $fileOrFol * @return void * @throws Exception */ - public function userSendsTheFollowingShareInvitationUsingTheGraphApi(string $user, TableNode $table) { + public function userSendsTheFollowingShareInvitationUsingTheGraphApi(string $user, TableNode $table): void { $rows = $table->getRowsHash(); $spaceId = ($this->spacesContext->getSpaceByName($user, $rows['space']))["id"]; @@ -112,6 +112,7 @@ public function userSendsTheFollowingShareInvitationUsingTheGraphApi(string $use $spaceId, $itemId, $shareeId, + $rows['shareType'], $rows['role'] ) ); From 6025953298857900a8833951fd78c7a0e9cc81b2 Mon Sep 17 00:00:00 2001 From: prajwol Date: Tue, 19 Dec 2023 17:11:48 +0545 Subject: [PATCH 3/3] add test for invite groups and users in one request --- tests/TestHelpers/GraphHelper.php | 25 ++++-- .../apiSharingNg/shareInvitations.feature | 83 ++++++++++++------- .../features/bootstrap/SharingNgContext.php | 14 +++- 3 files changed, 79 insertions(+), 43 deletions(-) diff --git a/tests/TestHelpers/GraphHelper.php b/tests/TestHelpers/GraphHelper.php index b2deb73f5e3..ec0ff647894 100644 --- a/tests/TestHelpers/GraphHelper.php +++ b/tests/TestHelpers/GraphHelper.php @@ -1587,7 +1587,8 @@ public static function getRoleIdByName( * @param string $password * @param string $spaceId * @param string $itemId - * @param string $shareeId + * @param array $shareeId + * @param array|null $shareType * @param string|null $role * * @return ResponseInterface @@ -1600,19 +1601,25 @@ public static function sendSharingInvitation( string $password, string $spaceId, string $itemId, - string $shareeId, - ?string $shareType, + array $shareeId, + ?array $shareType, ?string $role ): ResponseInterface { $url = self::getBetaFullUrl($baseUrl, "drives/$spaceId/items/$itemId/invite"); $body = []; - if ($shareType === 'group') { - $recipients['@libre.graph.recipient.type'] = 'group'; - } - - $recipients['objectId'] = $shareeId; - $body['recipients'] = [$recipients]; + for ($i = 0; $i < count($shareeId); $i++) { + if ($shareType[$i] === 'group') { + $body['recipients'][] = [ + "@libre.graph.recipient.type"=> "group", + "objectId" => $shareeId[$i] + ]; + } else { + $body['recipients'][] = [ + 'objectId' => $shareeId[$i] + ]; + } + } if ($role !== null) { $roleId = self::getRoleIdByName($baseUrl, $xRequestId, $user, $password, $role); diff --git a/tests/acceptance/features/apiSharingNg/shareInvitations.feature b/tests/acceptance/features/apiSharingNg/shareInvitations.feature index fe8d6f3beb9..eba8ec809e5 100644 --- a/tests/acceptance/features/apiSharingNg/shareInvitations.feature +++ b/tests/acceptance/features/apiSharingNg/shareInvitations.feature @@ -17,11 +17,11 @@ Feature: Send a sharing invitations And user "Alice" has created folder "FolderToShare" When user "Alice" sends the following share invitation using the Graph API: | resourceType | | - | resource | | - | space | Personal | - | sharee | Brian | - | shareType | user | - | role | | + | resource | | + | space | Personal | + | sharee | Brian | + | shareType | user | + | role | | Then the HTTP status code should be "200" And the JSON data of the response should match """ @@ -87,16 +87,16 @@ Feature: Send a sharing invitations """ Examples: | role | resource-type | path | - | Viewer | file | /textfile1.txt | - | Editor | file | /textfile1.txt | - | Co Owner | file | /textfile1.txt | - | Uploader | file | /textfile1.txt | - | Manager | file | /textfile1.txt | - | Viewer | folder | FolderToShare | - | Editor | folder | FolderToShare | - | Co Owner | folder | FolderToShare | - | Uploader | folder | FolderToShare | - | Manager | folder | FolderToShare | + | Viewer | file | /textfile1.txt | + | Editor | file | /textfile1.txt | + | Co Owner | file | /textfile1.txt | + | Uploader | file | /textfile1.txt | + | Manager | file | /textfile1.txt | + | Viewer | folder | FolderToShare | + | Editor | folder | FolderToShare | + | Co Owner | folder | FolderToShare | + | Uploader | folder | FolderToShare | + | Manager | folder | FolderToShare | Scenario Outline: send sharing invitation to group with different roles via the Graph API @@ -110,11 +110,11 @@ Feature: Send a sharing invitations And user "Alice" has created folder "FolderToShare" When user "Alice" sends the following share invitation using the Graph API: | resourceType | | - | resource | | - | space | Personal | - | sharee | grp1 | - | shareType | group | - | role | | + | resource | | + | space | Personal | + | sharee | grp1 | + | shareType | group | + | role | | Then the HTTP status code should be "200" And the JSON data of the response should match """ @@ -180,13 +180,36 @@ Feature: Send a sharing invitations """ Examples: | role | resource-type | path | - | Viewer | file | /textfile1.txt | - | Editor | file | /textfile1.txt | - | Co Owner | file | /textfile1.txt | - | Uploader | file | /textfile1.txt | - | Manager | file | /textfile1.txt | - | Viewer | folder | FolderToShare | - | Editor | folder | FolderToShare | - | Co Owner | folder | FolderToShare | - | Uploader | folder | FolderToShare | - | Manager | folder | FolderToShare | + | Viewer | file | /textfile1.txt | + | Editor | file | /textfile1.txt | + | Co Owner | file | /textfile1.txt | + | Uploader | file | /textfile1.txt | + | Manager | file | /textfile1.txt | + | Viewer | folder | FolderToShare | + | Editor | folder | FolderToShare | + | Co Owner | folder | FolderToShare | + | Uploader | folder | FolderToShare | + | Manager | folder | FolderToShare | + + + Scenario: send sharing invitation to user and group at once via the Graph API + Given these users have been created with default attributes and without skeleton files: + | username | + | Carol | + | Bob | + And the administrator has assigned the role "Admin" to user "Alice" using the Graph API + And user "Alice" has created a group "grp1" using the Graph API + And the administrator "Alice" has added the following users to a group "grp1" at once using the Graph API + | username | + | Brian | + | Carol | + And user "Alice" has uploaded file with content "to share" to "/textfile1.txt" + When user "Alice" sends the following share invitation using the Graph API: + | resourceType | file | + | resource | /textfile1.txt | + | space | Personal | + | sharee | grp1, Bob | + | shareType | group, user | + | role | Viewer | + Then the HTTP status code should be "200" + And the JSON data of the response should match diff --git a/tests/acceptance/features/bootstrap/SharingNgContext.php b/tests/acceptance/features/bootstrap/SharingNgContext.php index 6d1a37c4d0e..5c3478631bb 100644 --- a/tests/acceptance/features/bootstrap/SharingNgContext.php +++ b/tests/acceptance/features/bootstrap/SharingNgContext.php @@ -99,9 +99,15 @@ public function userSendsTheFollowingShareInvitationUsingTheGraphApi(string $use ? $this->spacesContext->getResourceId($user, $rows['space'], $rows['resource']) : $this->spacesContext->getFileId($user, $rows['space'], $rows['resource']); - $shareeId = ($rows['shareType'] === 'user') - ? $this->featureContext->getAttributeOfCreatedUser($rows['sharee'], 'id') - : $this->featureContext->getAttributeOfCreatedGroup($rows['sharee'], 'id'); + $sharee = array_map('trim', explode(',', $rows['sharee'])); + $shareType = array_map('trim', explode(',', $rows['shareType'])); + + $shareeId = []; + for ($i = 0; $i < count($sharee); $i++) { + $shareeId[] = ($shareType[$i] === 'user') + ? $this->featureContext->getAttributeOfCreatedUser($sharee[$i], 'id') + : $this->featureContext->getAttributeOfCreatedGroup($sharee[$i], 'id'); + } $this->featureContext->setResponse( GraphHelper::sendSharingInvitation( @@ -112,7 +118,7 @@ public function userSendsTheFollowingShareInvitationUsingTheGraphApi(string $use $spaceId, $itemId, $shareeId, - $rows['shareType'], + $shareType, $rows['role'] ) );