Files
opencloud/tests/acceptance/TestHelpers/SharingHelper.php
Jörn Friedrich Dreyer a5c9cbc26e drop project reference in testsuite headers, copyright and license remain
Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
2025-01-29 17:20:44 +01:00

269 lines
8.0 KiB
PHP

<?php declare(strict_types=1);
/**
* @author Artur Neumann <artur@jankaritech.com>
* @copyright Copyright (c) 2017 Artur Neumann artur@jankaritech.com
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License,
* as published by the Free Software Foundation;
* either version 3 of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace TestHelpers;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use InvalidArgumentException;
use Psr\Http\Message\ResponseInterface;
use SimpleXMLElement;
/**
* manage Shares via OCS API
*
* @author Artur Neumann <artur@jankaritech.com>
*
*/
class SharingHelper {
public const PERMISSION_TYPES = [
'read' => 1,
'update' => 2,
'create' => 4,
'delete' => 8,
'invite' => 0
];
public const SHARE_TYPES = [
'user' => 0,
'group' => 1,
'public_link' => 3,
'federated' => 6,
];
public const SHARE_STATES = [
'accepted' => 0,
'pending' => 1,
'rejected' => 2,
'declined' => 2, // declined is a synonym for rejected.
];
/**
*
* @param string $baseUrl baseURL of the OpenCloud installation without /ocs.
* @param string $user user that creates the share.
* @param string $password password of the user that creates the share.
* @param string $path The path to the file or folder which should be shared.
* @param string|int $shareType The type of the share. This can be one of:
* 0 = user, 1 = group, 3 = public (link),
* 6 = federated (cloud share).
* Pass either the number or the keyword.
* @param string $xRequestId
* @param string|null $shareWith The user or group id with which the file should
* be shared.
* @param boolean|null $publicUpload Whether to allow public upload to a public
* shared folder.
* @param string|null $sharePassword The password to protect the public link
* share with.
* @param string|int|string[]|int[]|null $permissions The permissions to set on the share.
* 1 = read; 2 = update; 4 = create;
* 8 = delete; 16 = share
* (default: 31, for public shares: 1)
* Pass either the (total) number or array of numbers,
* or any of the above keywords or array of keywords.
* @param string|null $linkName A (human-readable) name for the share,
* which can be up to 64 characters in length.
* @param string|null $expireDate An expire date for public link shares.
* This argument expects a date string
* in the format 'YYYY-MM-DD'.
* @param string|null $space_ref
* @param int $ocsApiVersion
* @param int $sharingApiVersion
* @param string $sharingApp
*
* @return ResponseInterface
* @throws InvalidArgumentException|GuzzleException
*/
public static function createShare(
string $baseUrl,
string $user,
string $password,
string $path,
$shareType,
string $xRequestId = '',
?string $shareWith = null,
?bool $publicUpload = false,
?string $sharePassword = null,
$permissions = null,
?string $linkName = null,
?string $expireDate = null,
?string $space_ref = null,
int $ocsApiVersion = 1,
int $sharingApiVersion = 1,
string $sharingApp = 'files_sharing'
): ResponseInterface {
$fd = [];
foreach ([$path, $baseUrl, $user, $password] as $variableToCheck) {
if (!\is_string($variableToCheck)) {
throw new InvalidArgumentException(
"mandatory argument missing or wrong type ($variableToCheck => "
. \gettype($variableToCheck) . ")"
);
}
}
if ($permissions !== null) {
$fd['permissions'] = self::getPermissionSum($permissions);
} elseif ($shareType !== "public_link") {
// sharing without permissions should automatically set the permission to 15 for share and 1 for public link
$fd['permissions'] = 15;
}
if (!\in_array($ocsApiVersion, [1, 2], true)) {
throw new InvalidArgumentException(
"invalid ocsApiVersion ($ocsApiVersion)"
);
}
if (!\in_array($sharingApiVersion, [1, 2], true)) {
throw new InvalidArgumentException(
"invalid sharingApiVersion ($sharingApiVersion)"
);
}
$fullUrl = $baseUrl;
if (\substr($fullUrl, -1) !== '/') {
$fullUrl .= '/';
}
$fullUrl .= "ocs/v$ocsApiVersion.php/apps/$sharingApp/api/v$sharingApiVersion/shares";
$fd['path'] = $path;
$fd['shareType'] = self::getShareType($shareType);
if ($shareWith !== null) {
$fd['shareWith'] = $shareWith;
}
if ($publicUpload !== null) {
$fd['publicUpload'] = $publicUpload;
}
if ($sharePassword !== null) {
$fd['password'] = $sharePassword;
}
if ($linkName !== null) {
$fd['name'] = $linkName;
}
if ($expireDate !== null) {
$fd['expireDate'] = $expireDate;
}
if ($space_ref !== null) {
$fd['space_ref'] = $space_ref;
}
$headers = ['OCS-APIREQUEST' => 'true'];
return HttpRequestHelper::post(
$fullUrl,
$xRequestId,
$user,
$password,
$headers,
$fd
);
}
/**
* Calculates the permission sum (int) from the given permissions.
* Permissions can be passed in as int, string or array of int or string
* 'read' => 1
* 'update' => 2
* 'create' => 4
* 'delete' => 8
* 'share' => 16
* 'invite' => 0
*
* @param string[]|string|int|int[] $permissions
*
* @return int
* @throws InvalidArgumentException
*
*/
public static function getPermissionSum($permissions): int {
if (\is_numeric($permissions)) {
// Allow any permission number so that test scenarios can
// specifically test invalid permission values
return (int) $permissions;
}
if (!\is_array($permissions)) {
$permissions = [$permissions];
}
$permissionSum = 0;
foreach ($permissions as $permission) {
if (\array_key_exists($permission, self::PERMISSION_TYPES)) {
$permissionSum += self::PERMISSION_TYPES[$permission];
} elseif (\in_array($permission, self::PERMISSION_TYPES, true)) {
$permissionSum += $permission;
} else {
throw new InvalidArgumentException(
"invalid permission type ($permission)"
);
}
}
if ($permissionSum < 0 || $permissionSum > 31) {
throw new InvalidArgumentException(
"invalid permission total ($permissionSum)"
);
}
return $permissionSum;
}
/**
* returns the share type number corresponding to the share type keyword
*
* @param string|int $shareType a keyword from SHARE_TYPES or a share type number
*
* @return int
* @throws InvalidArgumentException
*
*/
public static function getShareType($shareType): int {
if (\array_key_exists($shareType, self::SHARE_TYPES)) {
return self::SHARE_TYPES[$shareType];
} else {
if (\ctype_digit($shareType)) {
$shareType = (int) $shareType;
}
$key = \array_search($shareType, self::SHARE_TYPES, true);
if ($key !== false) {
return self::SHARE_TYPES[$key];
}
throw new InvalidArgumentException(
"invalid share type ($shareType)"
);
}
}
/**
*
* @param SimpleXMLElement $responseXmlObject
* @param string $errorMessage
*
* @return string
* @throws Exception
*
*/
public static function getLastShareIdFromResponse(
SimpleXMLElement $responseXmlObject,
string $errorMessage = "cannot find share id in response"
): string {
$xmlPart = $responseXmlObject->xpath("//data/element[last()]/id");
if (!\is_array($xmlPart) || (\count($xmlPart) === 0)) {
throw new Exception($errorMessage);
}
return $xmlPart[0]->__toString();
}
}