diff --git a/app/init.php b/app/init.php index 55781a89b1..b27d72bbc8 100644 --- a/app/init.php +++ b/app/init.php @@ -1912,7 +1912,7 @@ App::setResource( /** * JWT key from x-appwrite-key header. - * + * * @return array Decoded key-value pair from JWT */ App::setResource('dynamicKey', function (Request $request) { @@ -1924,7 +1924,7 @@ App::setResource('dynamicKey', function (Request $request) { [ $keyType, $authKey ] = \explode('_', $apiKey, 2); - if($keyType !== API_KEY_DYNAMIC) { + if ($keyType !== API_KEY_DYNAMIC) { return []; } diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index eb8d31ea59..44585bb45d 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -14,7 +14,6 @@ use Appwrite\Vcs\Comment; use Exception; use Executor\Executor; use Swoole\Coroutine as Co; -use Utopia\App; use Utopia\Cache\Cache; use Utopia\CLI\Console; use Utopia\Config\Config; diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 09c71dc004..7e663f139e 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -21,6 +21,7 @@ use Utopia\Database\Exception\Conflict; use Utopia\Database\Exception\Restricted; use Utopia\Database\Exception\Structure; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization as ValidatorAuthorization; use Utopia\DSN\DSN; use Utopia\Logger\Log; use Utopia\Platform\Action; @@ -91,7 +92,7 @@ class Deletes extends Action $this->deleteProject($dbForPlatform, $getProjectDB, $deviceForFiles, $deviceForSites, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $document); break; case DELETE_TYPE_SITES: - $this->deleteSite($dbForPlatform, $getProjectDB, $deviceForSites, $deviceForFunctions, $deviceForBuilds, $document, $certificates, $project); + $this->deleteSite($dbForPlatform, $getProjectDB, $deviceForSites, $deviceForFunctions, $deviceForBuilds, $deviceForFiles, $document, $certificates, $project); break; case DELETE_TYPE_FUNCTIONS: $this->deleteFunction($dbForPlatform, $getProjectDB, $deviceForFunctions, $deviceForBuilds, $certificates, $document, $project); @@ -747,7 +748,7 @@ class Deletes extends Action * @return void * @throws Exception */ - private function deleteSite(Database $dbForPlatform, callable $getProjectDB, Device $deviceForSites, Device $deviceForFunctions, Device $deviceForBuilds, Document $document, CertificatesAdapter $certificates, Document $project): void + private function deleteSite(Database $dbForPlatform, callable $getProjectDB, Device $deviceForSites, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForFiles, Document $document, CertificatesAdapter $certificates, Document $project): void { $dbForProject = $getProjectDB($project); $siteId = $document->getId(); @@ -781,9 +782,10 @@ class Deletes extends Action $deploymentInternalIds = []; $this->deleteByGroup('deployments', [ Query::equal('resourceInternalId', [$siteInternalId]) - ], $dbForProject, function (Document $document) use ($deviceForFunctions, &$deploymentInternalIds) { + ], $dbForProject, function (Document $document) use ($deviceForFunctions, $deviceForFiles, $dbForPlatform, &$deploymentInternalIds) { $deploymentInternalIds[] = $document->getInternalId(); $this->deleteDeploymentFiles($deviceForFunctions, $document); + $this->deleteDeploymentScreenshots($deviceForFiles, $dbForPlatform, $document); }); /** @@ -926,6 +928,53 @@ class Deletes extends Action $this->deleteRuntimes($getProjectDB, $document, $project); } + private function deleteDeploymentScreenshots(Device $deviceForFiles, Database $dbForPlatform, Document $deployment): void + { + $screenshotIds = []; + if (!empty($deployment->getAttribute('screenshot', ''))) { + $screenshotIds[] = $deployment->getAttribute('screenshot', ''); + } + if (!empty($deployment->getAttribute('screenshotDark', ''))) { + $screenshotIds[] = $deployment->getAttribute('screenshotDark', ''); + } + + if (empty($screenshotIds)) { + return; + } + Console::info("Deleting screenshots for deployment " . $deployment->getId()); + + $bucket = ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); + if ($bucket->isEmpty()) { + Console::error('Failed to get bucket for deployment screenshots'); + return; + } + + foreach ($screenshotIds as $id) { + $file = ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('bucket_' . $bucket->getInternalId(), $id)); + + if ($file->isEmpty()) { + Console::error('Failed to get deployment screenshot: ' . $id); + continue; + } + + $path = $file->getAttribute('path', ''); + + try { + if ($deviceForFiles->delete($path, true)) { + Console::success('Deleted deployment screenshot: ' . $path); + } else { + Console::error('Failed to delete deployment screenshot: ' . $path); + } + } catch (\Throwable $th) { + Console::error('Failed to delete deployment screenshot: ' . $path); + Console::error('[Error] Type: ' . get_class($th)); + Console::error('[Error] Message: ' . $th->getMessage()); + Console::error('[Error] File: ' . $th->getFile()); + Console::error('[Error] Line: ' . $th->getLine()); + } + } + } + /** * @param Device $device * @param Document $deployment