mirror of
https://github.com/appwrite/appwrite
synced 2026-05-23 08:58:35 +00:00
fixe endpoints
This commit is contained in:
parent
30373980f1
commit
80bb9a1f33
2 changed files with 60 additions and 24 deletions
|
|
@ -9,12 +9,15 @@ use Appwrite\SDK\AuthType;
|
|||
use Appwrite\SDK\ContentType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Database\Documents\User;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Exception\NotFound as NotFoundException;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Storage\Device;
|
||||
|
||||
class Delete extends Action
|
||||
{
|
||||
|
|
@ -37,6 +40,9 @@ class Delete extends Action
|
|||
->label('event', 'buckets.[bucketId].files.[fileId].delete')
|
||||
->label('audits.event', 'file.delete')
|
||||
->label('audits.resource', 'file/{request.fileId}')
|
||||
->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}')
|
||||
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT)
|
||||
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
|
||||
->label('sdk', new Method(
|
||||
namespace: 'storage',
|
||||
group: 'files',
|
||||
|
|
@ -51,12 +57,13 @@ class Delete extends Action
|
|||
],
|
||||
contentType: ContentType::NONE
|
||||
))
|
||||
->param('bucketId', '', new UID(), 'Bucket unique ID.')
|
||||
->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).')
|
||||
->param('fileId', '', new UID(), 'File ID.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForDeletes')
|
||||
->inject('queueForEvents')
|
||||
->inject('deviceForFiles')
|
||||
->inject('queueForDeletes')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
|
|
@ -65,47 +72,78 @@ class Delete extends Action
|
|||
string $fileId,
|
||||
Response $response,
|
||||
Database $dbForProject,
|
||||
Event $queueForEvents,
|
||||
Device $deviceForFiles,
|
||||
DeleteEvent $queueForDeletes,
|
||||
Event $queueForEvents
|
||||
) {
|
||||
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
if ($bucket->isEmpty()) {
|
||||
$isAPIKey = User::isApp(Authorization::getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged(Authorization::getRoles());
|
||||
|
||||
if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Validate delete permission
|
||||
$validator = new Authorization(Database::PERMISSION_DELETE);
|
||||
$validBucketDelete = $validator->isValid($bucket->getDelete());
|
||||
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
|
||||
|
||||
if (!$validBucketDelete && !$fileSecurity) {
|
||||
$validator = new Authorization(Database::PERMISSION_DELETE);
|
||||
$valid = $validator->isValid($bucket->getDelete());
|
||||
if (!$fileSecurity && !$valid) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
// Fetch file based on security
|
||||
if ($fileSecurity && !$validBucketDelete) {
|
||||
$file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId);
|
||||
} else {
|
||||
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId));
|
||||
}
|
||||
// Read permission should not be required for delete
|
||||
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId));
|
||||
|
||||
if ($file->isEmpty()) {
|
||||
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (!$dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId)) {
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove file from DB');
|
||||
// Make sure we don't delete the file before the document permission check occurs
|
||||
if ($fileSecurity && !$valid && !$validator->isValid($file->getDelete())) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$queueForDeletes
|
||||
->setType(DELETE_TYPE_DOCUMENT)
|
||||
->setDocument($file);
|
||||
$deviceDeleted = false;
|
||||
if ($file->getAttribute('chunksTotal') !== $file->getAttribute('chunksUploaded')) {
|
||||
$deviceDeleted = $deviceForFiles->abort(
|
||||
$file->getAttribute('path'),
|
||||
($file->getAttribute('metadata', [])['uploadId'] ?? '')
|
||||
);
|
||||
} else {
|
||||
$deviceDeleted = $deviceForFiles->delete($file->getAttribute('path'));
|
||||
}
|
||||
|
||||
if ($deviceDeleted) {
|
||||
$queueForDeletes
|
||||
->setType(DELETE_TYPE_CACHE_BY_RESOURCE)
|
||||
->setResourceType('bucket/' . $bucket->getId())
|
||||
->setResource('file/' . $fileId)
|
||||
;
|
||||
|
||||
try {
|
||||
if ($fileSecurity && !$valid) {
|
||||
$deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId);
|
||||
} else {
|
||||
$deleted = Authorization::skip(fn () => $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId));
|
||||
}
|
||||
} catch (NotFoundException) {
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (!$deleted) {
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove file from DB');
|
||||
}
|
||||
} else {
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to delete file from device');
|
||||
}
|
||||
|
||||
$queueForEvents
|
||||
->setParam('bucketId', $bucket->getId())
|
||||
->setParam('fileId', $file->getId())
|
||||
->setPayload($response->output($file, Response::MODEL_FILE));
|
||||
->setContext('bucket', $bucket)
|
||||
->setPayload($response->output($file, Response::MODEL_FILE))
|
||||
;
|
||||
|
||||
$response->noContent();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@ class Get extends Action
|
|||
->param('fileId', '', new UID(), 'File ID.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('mode')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
|
|
@ -58,7 +57,6 @@ class Get extends Action
|
|||
string $fileId,
|
||||
Response $response,
|
||||
Database $dbForProject,
|
||||
string $mode
|
||||
) {
|
||||
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
|
|
@ -70,7 +68,7 @@ class Get extends Action
|
|||
}
|
||||
|
||||
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
|
||||
$validator = new Authorization(\Utopia\Database\Database::PERMISSION_READ);
|
||||
$validator = new Authorization(Database::PERMISSION_READ);
|
||||
$valid = $validator->isValid($bucket->getRead());
|
||||
if (!$fileSecurity && !$valid) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
|
|
|
|||
Loading…
Reference in a new issue