1
0
Fork 0
mirror of synced 2024-06-03 03:14:50 +12:00

Merge pull request #4661 from appwrite/fix-cache-permissions

enabling file permissions
This commit is contained in:
Torsten Dittmann 2022-11-15 18:03:10 +01:00 committed by GitHub
commit 27ddf8630b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 320 additions and 113 deletions

View file

@ -342,7 +342,6 @@ App::get('/v1/avatars/initials')
->desc('Get User Initials') ->desc('Get User Initials')
->groups(['api', 'avatars']) ->groups(['api', 'avatars'])
->label('scope', 'avatars.read') ->label('scope', 'avatars.read')
->label('cache', true)
->label('cache.resource', 'avatar/initials') ->label('cache.resource', 'avatar/initials')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'avatars') ->label('sdk.namespace', 'avatars')

View file

@ -783,6 +783,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
->groups(['api', 'storage']) ->groups(['api', 'storage'])
->label('scope', 'files.read') ->label('scope', 'files.read')
->label('cache', true) ->label('cache', true)
->label('cache.resourceType', 'bucket/{request.bucketId}')
->label('cache.resource', 'file/{request.fileId}') ->label('cache.resource', 'file/{request.fileId}')
->label('usage.metric', 'files.{scope}.requests.read') ->label('usage.metric', 'files.{scope}.requests.read')
->label('usage.params', ['bucketId:{request.bucketId}']) ->label('usage.params', ['bucketId:{request.bucketId}'])
@ -840,9 +841,6 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
$outputs = Config::getParam('storage-outputs'); $outputs = Config::getParam('storage-outputs');
$fileLogos = Config::getParam('storage-logos'); $fileLogos = Config::getParam('storage-logos');
$date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT'; // 45 days cache
$key = \md5($fileId . $width . $height . $gravity . $quality . $borderWidth . $borderColor . $borderRadius . $opacity . $rotation . $background . $output);
if ($fileSecurity && !$valid) { if ($fileSecurity && !$valid) {
$file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
} else { } else {

View file

@ -208,19 +208,52 @@ App::init()
$useCache = $route->getLabel('cache', false); $useCache = $route->getLabel('cache', false);
if ($useCache) { if ($useCache) {
$key = md5($request->getURI() . implode('*', $request->getParams())); $key = md5($request->getURI() . implode('*', $request->getParams())) . '*' . APP_CACHE_BUSTER;
$cache = new Cache( $cache = new Cache(
new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId()) new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId())
); );
$timestamp = 60 * 60 * 24 * 30; $timestamp = 60 * 60 * 24 * 30;
$data = $cache->load($key, $timestamp); $data = $cache->load($key, $timestamp);
if (!empty($data)) { if (!empty($data)) {
$data = json_decode($data, true); $data = json_decode($data, true);
$parts = explode('/', $data['resourceType']);
$type = $parts[0] ?? null;
if ($type === 'bucket') {
$bucketId = $parts[1] ?? null;
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) {
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
}
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
$validator = new Authorization(Database::PERMISSION_READ);
$valid = $validator->isValid($bucket->getRead());
if (!$fileSecurity && !$valid) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
$parts = explode('/', $data['resource']);
$fileId = $parts[1] ?? null;
if ($fileSecurity && !$valid) {
$file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
} else {
$file = Authorization::skip(fn() => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId));
}
if ($file->isEmpty()) {
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
}
}
$response $response
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $timestamp) . ' GMT') ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $timestamp) . ' GMT')
->addHeader('X-Appwrite-Cache', 'hit') ->addHeader('X-Appwrite-Cache', 'hit')
->setContentType($data['content-type']) ->setContentType($data['contentType'])
->send(base64_decode($data['payload'])) ->send(base64_decode($data['payload']))
; ;
@ -408,7 +441,7 @@ App::shutdown()
*/ */
$useCache = $route->getLabel('cache', false); $useCache = $route->getLabel('cache', false);
if ($useCache) { if ($useCache) {
$resource = null; $resource = $resourceType = null;
$data = $response->getPayload(); $data = $response->getPayload();
if (!empty($data['payload'])) { if (!empty($data['payload'])) {
@ -417,9 +450,16 @@ App::shutdown()
$resource = $parseLabel($pattern, $responsePayload, $requestParams, $user); $resource = $parseLabel($pattern, $responsePayload, $requestParams, $user);
} }
$key = md5($request->getURI() . implode('*', $request->getParams())); $pattern = $route->getLabel('cache.resourceType', null);
if (!empty($pattern)) {
$resourceType = $parseLabel($pattern, $responsePayload, $requestParams, $user);
}
$key = md5($request->getURI() . implode('*', $request->getParams())) . '*' . APP_CACHE_BUSTER;
$data = json_encode([ $data = json_encode([
'content-type' => $response->getContentType(), 'resourceType' => $resourceType,
'resource' => $resource,
'contentType' => $response->getContentType(),
'payload' => base64_encode($data['payload']), 'payload' => base64_encode($data['payload']),
]) ; ]) ;

100
composer.lock generated
View file

@ -115,15 +115,15 @@
}, },
{ {
"name": "appwrite/php-runtimes", "name": "appwrite/php-runtimes",
"version": "0.11.0", "version": "0.11.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/appwrite/runtimes.git", "url": "https://github.com/appwrite/runtimes.git",
"reference": "547fc026e11c0946846a8ac690898f5bf53be101" "reference": "9d74a477ba3333cbcfac565c46fcf19606b7b603"
}, },
"require": { "require": {
"php": ">=8.0", "php": ">=8.0",
"utopia-php/system": "0.4.*" "utopia-php/system": "0.6.*"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^9.3", "phpunit/phpunit": "^9.3",
@ -154,7 +154,7 @@
"php", "php",
"runtimes" "runtimes"
], ],
"time": "2022-08-15T14:03:36+00:00" "time": "2022-11-07T16:45:52+00:00"
}, },
{ {
"name": "chillerlan/php-qrcode", "name": "chillerlan/php-qrcode",
@ -300,16 +300,16 @@
}, },
{ {
"name": "colinmollenhour/credis", "name": "colinmollenhour/credis",
"version": "v1.13.1", "version": "v1.14.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/colinmollenhour/credis.git", "url": "https://github.com/colinmollenhour/credis.git",
"reference": "85df015088e00daf8ce395189de22c8eb45c8d49" "reference": "dccc8a46586475075fbb012d8bd523b8a938c2dc"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/colinmollenhour/credis/zipball/85df015088e00daf8ce395189de22c8eb45c8d49", "url": "https://api.github.com/repos/colinmollenhour/credis/zipball/dccc8a46586475075fbb012d8bd523b8a938c2dc",
"reference": "85df015088e00daf8ce395189de22c8eb45c8d49", "reference": "dccc8a46586475075fbb012d8bd523b8a938c2dc",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -341,9 +341,9 @@
"homepage": "https://github.com/colinmollenhour/credis", "homepage": "https://github.com/colinmollenhour/credis",
"support": { "support": {
"issues": "https://github.com/colinmollenhour/credis/issues", "issues": "https://github.com/colinmollenhour/credis/issues",
"source": "https://github.com/colinmollenhour/credis/tree/v1.13.1" "source": "https://github.com/colinmollenhour/credis/tree/v1.14.0"
}, },
"time": "2022-06-20T22:56:59+00:00" "time": "2022-11-09T01:18:39+00:00"
}, },
{ {
"name": "dragonmantank/cron-expression", "name": "dragonmantank/cron-expression",
@ -803,6 +803,72 @@
}, },
"time": "2020-12-26T17:45:17+00:00" "time": "2020-12-26T17:45:17+00:00"
}, },
{
"name": "laravel/pint",
"version": "v1.2.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/pint.git",
"reference": "1d276e4c803397a26cc337df908f55c2a4e90d86"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/pint/zipball/1d276e4c803397a26cc337df908f55c2a4e90d86",
"reference": "1d276e4c803397a26cc337df908f55c2a4e90d86",
"shasum": ""
},
"require": {
"ext-json": "*",
"ext-mbstring": "*",
"ext-tokenizer": "*",
"ext-xml": "*",
"php": "^8.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.11.0",
"illuminate/view": "^9.27",
"laravel-zero/framework": "^9.1.3",
"mockery/mockery": "^1.5.0",
"nunomaduro/larastan": "^2.2",
"nunomaduro/termwind": "^1.14.0",
"pestphp/pest": "^1.22.1"
},
"bin": [
"builds/pint"
],
"type": "project",
"autoload": {
"psr-4": {
"App\\": "app/",
"Database\\Seeders\\": "database/seeders/",
"Database\\Factories\\": "database/factories/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nuno Maduro",
"email": "enunomaduro@gmail.com"
}
],
"description": "An opinionated code formatter for PHP.",
"homepage": "https://laravel.com",
"keywords": [
"format",
"formatter",
"lint",
"linter",
"php"
],
"support": {
"issues": "https://github.com/laravel/pint/issues",
"source": "https://github.com/laravel/pint"
},
"time": "2022-09-13T15:07:15+00:00"
},
{ {
"name": "matomo/device-detector", "name": "matomo/device-detector",
"version": "6.0.0", "version": "6.0.0",
@ -2422,23 +2488,25 @@
}, },
{ {
"name": "utopia-php/system", "name": "utopia-php/system",
"version": "0.4.0", "version": "0.6.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/utopia-php/system.git", "url": "https://github.com/utopia-php/system.git",
"reference": "67c92c66ce8f0cc925a00bca89f7a188bf9183c0" "reference": "289c4327713deadc9c748b5317d248133a02f245"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/utopia-php/system/zipball/67c92c66ce8f0cc925a00bca89f7a188bf9183c0", "url": "https://api.github.com/repos/utopia-php/system/zipball/289c4327713deadc9c748b5317d248133a02f245",
"reference": "67c92c66ce8f0cc925a00bca89f7a188bf9183c0", "reference": "289c4327713deadc9c748b5317d248133a02f245",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"laravel/pint": "1.2.*",
"php": ">=7.4" "php": ">=7.4"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^9.3", "phpunit/phpunit": "^9.3",
"squizlabs/php_codesniffer": "^3.6",
"vimeo/psalm": "4.0.1" "vimeo/psalm": "4.0.1"
}, },
"type": "library", "type": "library",
@ -2471,9 +2539,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/utopia-php/system/issues", "issues": "https://github.com/utopia-php/system/issues",
"source": "https://github.com/utopia-php/system/tree/0.4.0" "source": "https://github.com/utopia-php/system/tree/0.6.0"
}, },
"time": "2021-02-04T14:14:49+00:00" "time": "2022-11-07T13:51:59+00:00"
}, },
{ {
"name": "utopia-php/websocket", "name": "utopia-php/websocket",

121
package-lock.json generated
View file

@ -433,12 +433,15 @@
} }
}, },
"node_modules/buffer-equal": { "node_modules/buffer-equal": {
"version": "1.0.0", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz",
"integrity": "sha512-tcBWO2Dl4e7Asr9hTGcpVrCe+F7DubpmqWCTbj4FHLmjqO2hIaC383acQubWtRJhdceqs5uBHs6Es+Sk//RKiQ==", "integrity": "sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=0.4.0" "node": ">=0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/buffer-from": { "node_modules/buffer-from": {
@ -805,13 +808,10 @@
} }
}, },
"node_modules/convert-source-map": { "node_modules/convert-source-map": {
"version": "1.8.0", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
"integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
"dev": true, "dev": true
"dependencies": {
"safe-buffer": "~5.1.1"
}
}, },
"node_modules/copy-anything": { "node_modules/copy-anything": {
"version": "2.0.6", "version": "2.0.6",
@ -1540,9 +1540,9 @@
"dev": true "dev": true
}, },
"node_modules/get-intrinsic": { "node_modules/get-intrinsic": {
"version": "1.1.2", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
"integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"function-bind": "^1.1.1", "function-bind": "^1.1.1",
@ -2196,9 +2196,9 @@
"dev": true "dev": true
}, },
"node_modules/is-core-module": { "node_modules/is-core-module": {
"version": "2.10.0", "version": "2.11.0",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
"integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"has": "^1.0.3" "has": "^1.0.3"
@ -2912,10 +2912,13 @@
} }
}, },
"node_modules/meow/node_modules/minimist": { "node_modules/meow/node_modules/minimist": {
"version": "1.2.6", "version": "1.2.7",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz",
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==",
"dev": true "dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
}, },
"node_modules/micromatch": { "node_modules/micromatch": {
"version": "3.1.10", "version": "3.1.10",
@ -3013,10 +3016,13 @@
} }
}, },
"node_modules/minimist": { "node_modules/minimist": {
"version": "0.2.1", "version": "0.2.2",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.1.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.2.tgz",
"integrity": "sha512-GY8fANSrTMfBVfInqJAY41QkOM+upUTytK1jZ0c8+3HdHrJxBJ3rF5i9moClXTE8uUSnUo8cAsCoxDXvSY4DHg==", "integrity": "sha512-g92kDfAOAszDRtHNagjZPPI/9lfOFaRBL/Ud6Z0RKZua/x+49awTydZLh5Gkhb80Xy5hmcvZNLGzscW5n5yd0g==",
"dev": true "dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
}, },
"node_modules/mixin-deep": { "node_modules/mixin-deep": {
"version": "1.3.2", "version": "1.3.2",
@ -3080,9 +3086,9 @@
} }
}, },
"node_modules/nan": { "node_modules/nan": {
"version": "2.16.0", "version": "2.17.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz",
"integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==", "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
@ -4854,9 +4860,9 @@
} }
}, },
"node_modules/tslib": { "node_modules/tslib": {
"version": "2.4.0", "version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==",
"dev": true "dev": true
}, },
"node_modules/turndown": { "node_modules/turndown": {
@ -5636,9 +5642,9 @@
} }
}, },
"buffer-equal": { "buffer-equal": {
"version": "1.0.0", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz",
"integrity": "sha512-tcBWO2Dl4e7Asr9hTGcpVrCe+F7DubpmqWCTbj4FHLmjqO2hIaC383acQubWtRJhdceqs5uBHs6Es+Sk//RKiQ==", "integrity": "sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==",
"dev": true "dev": true
}, },
"buffer-from": { "buffer-from": {
@ -5941,13 +5947,10 @@
} }
}, },
"convert-source-map": { "convert-source-map": {
"version": "1.8.0", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
"integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
"dev": true, "dev": true
"requires": {
"safe-buffer": "~5.1.1"
}
}, },
"copy-anything": { "copy-anything": {
"version": "2.0.6", "version": "2.0.6",
@ -6559,9 +6562,9 @@
"dev": true "dev": true
}, },
"get-intrinsic": { "get-intrinsic": {
"version": "1.1.2", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
"integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==",
"dev": true, "dev": true,
"requires": { "requires": {
"function-bind": "^1.1.1", "function-bind": "^1.1.1",
@ -7092,9 +7095,9 @@
"dev": true "dev": true
}, },
"is-core-module": { "is-core-module": {
"version": "2.10.0", "version": "2.11.0",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
"integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
"dev": true, "dev": true,
"requires": { "requires": {
"has": "^1.0.3" "has": "^1.0.3"
@ -7693,9 +7696,9 @@
}, },
"dependencies": { "dependencies": {
"minimist": { "minimist": {
"version": "1.2.6", "version": "1.2.7",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz",
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==",
"dev": true "dev": true
} }
} }
@ -7774,9 +7777,9 @@
} }
}, },
"minimist": { "minimist": {
"version": "0.2.1", "version": "0.2.2",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.1.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.2.tgz",
"integrity": "sha512-GY8fANSrTMfBVfInqJAY41QkOM+upUTytK1jZ0c8+3HdHrJxBJ3rF5i9moClXTE8uUSnUo8cAsCoxDXvSY4DHg==", "integrity": "sha512-g92kDfAOAszDRtHNagjZPPI/9lfOFaRBL/Ud6Z0RKZua/x+49awTydZLh5Gkhb80Xy5hmcvZNLGzscW5n5yd0g==",
"dev": true "dev": true
}, },
"mixin-deep": { "mixin-deep": {
@ -7831,9 +7834,9 @@
"dev": true "dev": true
}, },
"nan": { "nan": {
"version": "2.16.0", "version": "2.17.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz",
"integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==", "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
@ -9271,9 +9274,9 @@
"dev": true "dev": true
}, },
"tslib": { "tslib": {
"version": "2.4.0", "version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==",
"dev": true "dev": true
}, },
"turndown": { "turndown": {

View file

@ -25,10 +25,16 @@ class StorageCustomClientTest extends Scope
use SideClient; use SideClient;
use StoragePermissionsScope; use StoragePermissionsScope;
public function testBucketAnyPermissions(): void public function testCachedFilePreview(): void
{ {
/** /**
* Test for SUCCESS Create a bucket with File Level Security with no permissions.
Add a file with no permissions.
Login as UserA from SDK
Call File Preview from SDK all good userA can't see preview.
Add read permission to UserA, all good userA can now see preview.
Remove read permission for UserA.
Call File Preview from SDK and now userA can't see the preview.
*/ */
$bucket = $this->client->call(Client::METHOD_POST, '/storage/buckets', [ $bucket = $this->client->call(Client::METHOD_POST, '/storage/buckets', [
'content-type' => 'application/json', 'content-type' => 'application/json',
@ -37,22 +43,19 @@ class StorageCustomClientTest extends Scope
], [ ], [
'bucketId' => ID::unique(), 'bucketId' => ID::unique(),
'name' => 'Test Bucket', 'name' => 'Test Bucket',
'permissions' => [ 'fileSecurity' => true,
Permission::read(Role::any()), 'permissions' => [],
Permission::create(Role::any()),
Permission::update(Role::any()),
Permission::delete(Role::any()),
],
]); ]);
$bucketId = $bucket['body']['$id']; $bucketId = $bucket['body']['$id'];
$this->assertEquals(201, $bucket['headers']['status-code']); $this->assertEquals(201, $bucket['headers']['status-code']);
$this->assertNotEmpty($bucketId); $this->assertNotEmpty($bucketId);
$file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([
'content-type' => 'multipart/form-data', 'content-type' => 'multipart/form-data',
'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-project' => $this->getProject()['$id'],
], [ 'x-appwrite-key' => $this->getProject()['apiKey']
]), [
'fileId' => ID::unique(), 'fileId' => ID::unique(),
'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'), 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'),
]); ]);
@ -65,46 +68,142 @@ class StorageCustomClientTest extends Scope
$this->assertEquals('image/png', $file['body']['mimeType']); $this->assertEquals('image/png', $file['body']['mimeType']);
$this->assertEquals(47218, $file['body']['sizeOriginal']); $this->assertEquals(47218, $file['body']['sizeOriginal']);
$file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([
'content-type' => 'application/json', 'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
$this->assertEquals(404, $file['headers']['status-code']);
$file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
], [
'name' => 'permissions.png',
'permissions' => [
Permission::read(Role::user($this->getUser()['$id'])),
],
]); ]);
$this->assertEquals(200, $file['headers']['status-code']); $this->assertEquals(200, $file['headers']['status-code']);
$file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', [ $file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([
'content-type' => 'application/json', 'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-project' => $this->getProject()['$id'],
]); ], $this->getHeaders()));
$this->assertEquals(200, $file['headers']['status-code']);
$file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/download', [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
]);
$this->assertEquals(200, $file['headers']['status-code']);
$file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/view', [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
]);
$this->assertEquals(200, $file['headers']['status-code']); $this->assertEquals(200, $file['headers']['status-code']);
$file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [
'content-type' => 'application/json', 'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
], [ ], [
'name' => 'permissions.png', 'name' => 'permissions.png',
'permissions' => [],
]);
$this->assertEquals(200, $file['headers']['status-code']);
$file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
$this->assertEquals(404, $file['headers']['status-code']);
$file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]);
$this->assertEquals(204, $file['headers']['status-code']);
$this->assertEmpty($file['body']);
}
public function testBucketAnyPermissions(): void
{
/**
* Test for SUCCESS
*/
$bucket = $this->client->call(Client::METHOD_POST, '/storage/buckets', [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
], [
'bucketId' => ID::unique(),
'name' => 'Test Bucket',
'permissions' => [
Permission::read(Role::any()),
Permission::create(Role::any()),
Permission::update(Role::any()),
Permission::delete(Role::any()),
],
]);
$bucketId = $bucket['body']['$id'];
$this->assertEquals(201, $bucket['headers']['status-code']);
$this->assertNotEmpty($bucketId);
$file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [
'content-type' => 'multipart/form-data',
'x-appwrite-project' => $this->getProject()['$id'],
], [
'fileId' => ID::unique(),
'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'permissions.png'),
]);
$fileId = $file['body']['$id'];
$this->assertEquals($file['headers']['status-code'], 201);
$this->assertNotEmpty($fileId);
$this->assertEquals(true, DateTime::isValid($file['body']['$createdAt']));
$this->assertEquals('permissions.png', $file['body']['name']);
$this->assertEquals('image/png', $file['body']['mimeType']);
$this->assertEquals(47218, $file['body']['sizeOriginal']);
$file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
]);
$this->assertEquals(200, $file['headers']['status-code']);
$file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
]);
$this->assertEquals(200, $file['headers']['status-code']);
$file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/download', [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
]);
$this->assertEquals(200, $file['headers']['status-code']);
$file = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/view', [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
]);
$this->assertEquals(200, $file['headers']['status-code']);
$file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], [
'name' => 'permissions.png',
]); ]);
$this->assertEquals(200, $file['headers']['status-code']); $this->assertEquals(200, $file['headers']['status-code']);
$file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ $file = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [
'content-type' => 'application/json', 'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-project' => $this->getProject()['$id'],
]); ]);
$this->assertEquals(204, $file['headers']['status-code']); $this->assertEquals(204, $file['headers']['status-code']);