mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
delayed project deletion
This commit is contained in:
1 parent
a949a1ffd5
commit
c953a4815e
6 files changed
+263
-40
No files matched your search
@@ -19,7 +19,6 @@ use Appwrite\Utopia\Database\Validator\ProjectId;
|
||||
use Appwrite\Utopia\Database\Validator\Queries\Projects;
|
||||
use Appwrite\Utopia\Request;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Cron\CronExpression;
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use Utopia\App;
|
||||
use Utopia\Audit\Audit;
|
||||
@@ -358,9 +357,18 @@ App::get('/v1/projects')
|
||||
throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Project '{$projectId}' for the 'cursor' value not found.");
|
||||
}
|
||||
|
||||
if(!empty($cursorDocument->getAttribute('_deletedAt')) && $cursorDocument->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Project '{$projectId}' for the 'cursor' value not found.");
|
||||
}
|
||||
|
||||
$cursor->setValue($cursorDocument);
|
||||
}
|
||||
|
||||
$queries[] = query::or([
|
||||
query::isNull('_deletedAt'),
|
||||
query::lessThan('_deletedAt', DateTime::now())
|
||||
]);
|
||||
|
||||
$filterQueries = Query::groupByType($queries)['filters'];
|
||||
try {
|
||||
$projects = $dbForPlatform->find('projects', $queries);
|
||||
@@ -402,6 +410,10 @@ App::get('/v1/projects/:projectId')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$response->dynamic($project, Response::MODEL_PROJECT);
|
||||
});
|
||||
|
||||
@@ -435,10 +447,9 @@ App::patch('/v1/projects/:projectId')
|
||||
->param('legalCity', '', new Text(256), 'Project legal city. Max length: 256 chars.', true)
|
||||
->param('legalAddress', '', new Text(256), 'Project legal address. Max length: 256 chars.', true)
|
||||
->param('legalTaxId', '', new Text(256), 'Project legal tax ID. Max length: 256 chars.', true)
|
||||
->param('restore', null, new Boolean(), 'Restore project from being marked for deletion', true)
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
->action(function (string $projectId, string $name, string $description, string $logo, string $url, string $legalName, string $legalCountry, string $legalState, string $legalCity, string $legalAddress, string $legalTaxId, bool $restore, Response $response, Database $dbForPlatform) {
|
||||
->action(function (string $projectId, string $name, string $description, string $logo, string $url, string $legalName, string $legalCountry, string $legalState, string $legalCity, string $legalAddress, string $legalTaxId, Response $response, Database $dbForPlatform) {
|
||||
|
||||
$project = $dbForPlatform->getDocument('projects', $projectId);
|
||||
|
||||
@@ -446,7 +457,12 @@ App::patch('/v1/projects/:projectId')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$project
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
|
||||
$project = $dbForPlatform->updateDocument('projects', $project->getId(), $project
|
||||
->setAttribute('name', $name)
|
||||
->setAttribute('description', $description)
|
||||
->setAttribute('logo', $logo)
|
||||
@@ -457,14 +473,42 @@ App::patch('/v1/projects/:projectId')
|
||||
->setAttribute('legalCity', $legalCity)
|
||||
->setAttribute('legalAddress', $legalAddress)
|
||||
->setAttribute('legalTaxId', $legalTaxId)
|
||||
->setAttribute('search', implode(' ', [$projectId, $name]))
|
||||
;
|
||||
->setAttribute('search', implode(' ', [$projectId, $name])));
|
||||
|
||||
if (!empty($restore)) {
|
||||
$project->setAttribute('_deletedAt', null);
|
||||
$response->dynamic($project, Response::MODEL_PROJECT);
|
||||
});
|
||||
|
||||
App::patch('/v1/projects/:projectId/restore')
|
||||
->desc('Restore project from being a candidate for deletion')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk', new Method(
|
||||
namespace: 'projects',
|
||||
group: 'projects',
|
||||
name: 'restore',
|
||||
description: '/docs/references/projects/restore.md',
|
||||
auth: [AuthType::ADMIN],
|
||||
responses: [
|
||||
new SDKResponse(
|
||||
code: Response::STATUS_CODE_OK,
|
||||
model: Response::MODEL_PROJECT,
|
||||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
->action(function (string $projectId, Response $response, Database $dbForPlatform) {
|
||||
|
||||
$project = $dbForPlatform->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$project = $dbForPlatform->updateDocument('projects', $project->getId(), $project);
|
||||
$project = $dbForPlatform->updateDocument('projects', $project->getId(),
|
||||
$project->setAttribute('_deletedAt', null)
|
||||
);
|
||||
|
||||
$response->dynamic($project, Response::MODEL_PROJECT);
|
||||
});
|
||||
@@ -499,6 +543,10 @@ App::patch('/v1/projects/:projectId/team')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($team->isEmpty()) {
|
||||
throw new Exception(Exception::TEAM_NOT_FOUND);
|
||||
}
|
||||
@@ -574,6 +622,10 @@ App::patch('/v1/projects/:projectId/service')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$services = $project->getAttribute('services', []);
|
||||
$services[$service] = $status;
|
||||
|
||||
@@ -611,6 +663,10 @@ App::patch('/v1/projects/:projectId/service/all')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$allServices = array_keys(array_filter(Config::getParam('services'), fn ($element) => $element['optional']));
|
||||
|
||||
$services = [];
|
||||
@@ -653,6 +709,10 @@ App::patch('/v1/projects/:projectId/api')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$apis = $project->getAttribute('apis', []);
|
||||
$apis[$api] = $status;
|
||||
|
||||
@@ -690,6 +750,10 @@ App::patch('/v1/projects/:projectId/api/all')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$allApis = array_keys(Config::getParam('apis'));
|
||||
|
||||
$apis = [];
|
||||
@@ -734,6 +798,10 @@ App::patch('/v1/projects/:projectId/oauth2')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$providers = $project->getAttribute('oAuthProviders', []);
|
||||
|
||||
if ($appId !== null) {
|
||||
@@ -782,6 +850,10 @@ App::patch('/v1/projects/:projectId/auth/session-alerts')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$auths = $project->getAttribute('auths', []);
|
||||
$auths['sessionAlerts'] = $alerts;
|
||||
|
||||
@@ -821,6 +893,10 @@ App::patch('/v1/projects/:projectId/auth/memberships-privacy')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$auths = $project->getAttribute('auths', []);
|
||||
|
||||
$auths['membershipsUserName'] = $userName;
|
||||
@@ -862,6 +938,10 @@ App::patch('/v1/projects/:projectId/auth/limit')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$auths = $project->getAttribute('auths', []);
|
||||
$auths['limit'] = $limit;
|
||||
|
||||
@@ -900,6 +980,10 @@ App::patch('/v1/projects/:projectId/auth/duration')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$auths = $project->getAttribute('auths', []);
|
||||
$auths['duration'] = $duration;
|
||||
|
||||
@@ -942,6 +1026,10 @@ App::patch('/v1/projects/:projectId/auth/:method')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$auths = $project->getAttribute('auths', []);
|
||||
$auths[$authKey] = $status;
|
||||
|
||||
@@ -979,6 +1067,10 @@ App::patch('/v1/projects/:projectId/auth/password-history')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$auths = $project->getAttribute('auths', []);
|
||||
$auths['passwordHistory'] = $limit;
|
||||
|
||||
@@ -1017,6 +1109,10 @@ App::patch('/v1/projects/:projectId/auth/password-dictionary')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$auths = $project->getAttribute('auths', []);
|
||||
$auths['passwordDictionary'] = $enabled;
|
||||
|
||||
@@ -1055,6 +1151,10 @@ App::patch('/v1/projects/:projectId/auth/personal-data')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$auths = $project->getAttribute('auths', []);
|
||||
$auths['personalDataCheck'] = $enabled;
|
||||
|
||||
@@ -1093,6 +1193,10 @@ App::patch('/v1/projects/:projectId/auth/max-sessions')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$auths = $project->getAttribute('auths', []);
|
||||
$auths['maxSessions'] = $limit;
|
||||
|
||||
@@ -1139,6 +1243,10 @@ App::patch('/v1/projects/:projectId/auth/mock-numbers')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$auths = $project->getAttribute('auths', []);
|
||||
|
||||
$auths['mockNumbers'] = $numbers;
|
||||
@@ -1170,16 +1278,19 @@ App::delete('/v1/projects/:projectId')
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
->inject('dbForPlatform')
|
||||
->inject('queueForDeletes')
|
||||
->action(function (string $projectId, Response $response, Document $user, Database $dbForPlatform, Delete $queueForDeletes) {
|
||||
->action(function (string $projectId, Response $response, Database $dbForPlatform) {
|
||||
$project = $dbForPlatform->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$expiration = System::getEnv('_APP_PROJECTS_DELETE_EXPIRATION','3600');
|
||||
$deletedAt = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), (int)$expiration));
|
||||
$dbForPlatform->updateDocument('projects', $project->getId(),
|
||||
@@ -1226,6 +1337,10 @@ App::post('/v1/projects/:projectId/webhooks')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$security = (bool) filter_var($security, FILTER_VALIDATE_BOOLEAN);
|
||||
|
||||
$webhook = new Document([
|
||||
@@ -1284,6 +1399,10 @@ App::get('/v1/projects/:projectId/webhooks')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$webhooks = $dbForPlatform->find('webhooks', [
|
||||
Query::equal('projectInternalId', [$project->getInternalId()]),
|
||||
Query::limit(5000),
|
||||
@@ -1324,6 +1443,10 @@ App::get('/v1/projects/:projectId/webhooks/:webhookId')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$webhook = $dbForPlatform->findOne('webhooks', [
|
||||
Query::equal('$id', [$webhookId]),
|
||||
Query::equal('projectInternalId', [$project->getInternalId()]),
|
||||
@@ -1372,6 +1495,10 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$security = ($security === '1' || $security === 'true' || $security === 1 || $security === true);
|
||||
|
||||
$webhook = $dbForPlatform->findOne('webhooks', [
|
||||
@@ -1431,6 +1558,10 @@ App::patch('/v1/projects/:projectId/webhooks/:webhookId/signature')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$webhook = $dbForPlatform->findOne('webhooks', [
|
||||
Query::equal('$id', [$webhookId]),
|
||||
Query::equal('projectInternalId', [$project->getInternalId()]),
|
||||
@@ -1478,6 +1609,10 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$webhook = $dbForPlatform->findOne('webhooks', [
|
||||
Query::equal('$id', [$webhookId]),
|
||||
Query::equal('projectInternalId', [$project->getInternalId()]),
|
||||
@@ -1527,6 +1662,10 @@ App::post('/v1/projects/:projectId/keys')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$key = new Document([
|
||||
'$id' => ID::unique(),
|
||||
'$permissions' => [
|
||||
@@ -1581,6 +1720,10 @@ App::get('/v1/projects/:projectId/keys')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$keys = $dbForPlatform->find('keys', [
|
||||
Query::equal('projectInternalId', [$project->getInternalId()]),
|
||||
Query::limit(5000),
|
||||
@@ -1621,6 +1764,10 @@ App::get('/v1/projects/:projectId/keys/:keyId')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$key = $dbForPlatform->findOne('keys', [
|
||||
Query::equal('$id', [$keyId]),
|
||||
Query::equal('projectInternalId', [$project->getInternalId()]),
|
||||
@@ -1665,6 +1812,10 @@ App::put('/v1/projects/:projectId/keys/:keyId')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$key = $dbForPlatform->findOne('keys', [
|
||||
Query::equal('$id', [$keyId]),
|
||||
Query::equal('projectInternalId', [$project->getInternalId()]),
|
||||
@@ -1716,6 +1867,10 @@ App::delete('/v1/projects/:projectId/keys/:keyId')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$key = $dbForPlatform->findOne('keys', [
|
||||
Query::equal('$id', [$keyId]),
|
||||
Query::equal('projectInternalId', [$project->getInternalId()]),
|
||||
@@ -1764,6 +1919,10 @@ App::post('/v1/projects/:projectId/jwts')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$jwt = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', $duration, 0);
|
||||
|
||||
$response
|
||||
@@ -1810,6 +1969,10 @@ App::post('/v1/projects/:projectId/platforms')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$platform = new Document([
|
||||
'$id' => ID::unique(),
|
||||
'$permissions' => [
|
||||
@@ -1903,6 +2066,10 @@ App::get('/v1/projects/:projectId/platforms/:platformId')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$platform = $dbForPlatform->findOne('platforms', [
|
||||
Query::equal('$id', [$platformId]),
|
||||
Query::equal('projectInternalId', [$project->getInternalId()]),
|
||||
@@ -1947,6 +2114,10 @@ App::put('/v1/projects/:projectId/platforms/:platformId')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$platform = $dbForPlatform->findOne('platforms', [
|
||||
Query::equal('$id', [$platformId]),
|
||||
Query::equal('projectInternalId', [$project->getInternalId()]),
|
||||
@@ -2001,6 +2172,10 @@ App::delete('/v1/projects/:projectId/platforms/:platformId')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$platform = $dbForPlatform->findOne('platforms', [
|
||||
Query::equal('$id', [$platformId]),
|
||||
Query::equal('projectInternalId', [$project->getInternalId()]),
|
||||
@@ -2056,6 +2231,10 @@ App::patch('/v1/projects/:projectId/smtp')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Ensure required params for when enabling SMTP
|
||||
if ($enabled) {
|
||||
if (empty($senderName)) {
|
||||
@@ -2154,6 +2333,10 @@ App::post('/v1/projects/:projectId/smtp/tests')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$replyToEmail = !empty($replyTo) ? $replyTo : $senderEmail;
|
||||
|
||||
$subject = 'Custom SMTP email sample';
|
||||
@@ -2223,6 +2406,10 @@ App::get('/v1/projects/:projectId/templates/sms/:type/:locale')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$templates = $project->getAttribute('templates', []);
|
||||
$template = $templates['sms.' . $type . '-' . $locale] ?? null;
|
||||
|
||||
@@ -2269,6 +2456,10 @@ App::get('/v1/projects/:projectId/templates/email/:type/:locale')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$templates = $project->getAttribute('templates', []);
|
||||
$template = $templates['email.' . $type . '-' . $locale] ?? null;
|
||||
|
||||
@@ -2331,6 +2522,10 @@ App::patch('/v1/projects/:projectId/templates/sms/:type/:locale')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$templates = $project->getAttribute('templates', []);
|
||||
$templates['sms.' . $type . '-' . $locale] = [
|
||||
'message' => $message
|
||||
@@ -2380,6 +2575,10 @@ App::patch('/v1/projects/:projectId/templates/email/:type/:locale')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$templates = $project->getAttribute('templates', []);
|
||||
$templates['email.' . $type . '-' . $locale] = [
|
||||
'senderName' => $senderName,
|
||||
@@ -2435,6 +2634,10 @@ App::delete('/v1/projects/:projectId/templates/sms/:type/:locale')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$templates = $project->getAttribute('templates', []);
|
||||
$template = $templates['sms.' . $type . '-' . $locale] ?? null;
|
||||
|
||||
@@ -2484,6 +2687,10 @@ App::delete('/v1/projects/:projectId/templates/email/:type/:locale')
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$templates = $project->getAttribute('templates', []);
|
||||
$template = $templates['email.' . $type . '-' . $locale] ?? null;
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ use Utopia\CLI\Console;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Adapter\Pool as DatabasePool;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\DateTime;
|
||||
use Utopia\Database\DateTime as DatabaseDateTime;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
@@ -294,6 +295,10 @@ App::setResource('project', function ($dbForPlatform, $request, $console) {
|
||||
|
||||
$project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId));
|
||||
|
||||
if(!empty($project->getAttribute('_deletedAt')) && $project->getAttribute('_deletedAt') < DateTime::now()) {
|
||||
$project = new Document([]);
|
||||
}
|
||||
|
||||
return $project;
|
||||
}, ['dbForPlatform', 'request', 'console']);
|
||||
|
||||
|
||||
@@ -932,34 +932,6 @@ services:
|
||||
- _APP_DB_PASS
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
|
||||
appwrite-task-scheduler-projects:
|
||||
entrypoint: schedule-projects
|
||||
<<: *x-logging
|
||||
container_name: appwrite-task-scheduler-projects
|
||||
image: appwrite-dev
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- ./app:/usr/src/code/app
|
||||
- ./src:/usr/src/code/src
|
||||
depends_on:
|
||||
- mariadb
|
||||
- redis
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
|
||||
appwrite-assistant:
|
||||
container_name: appwrite-assistant
|
||||
image: appwrite/assistant:0.7.0
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Restore project from being a candidate for deletion.
|
||||
@@ -9,6 +9,7 @@ use Utopia\Database\Database;
|
||||
use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\System\System;
|
||||
|
||||
@@ -87,7 +88,26 @@ class Maintenance extends Action
|
||||
$this->renewCertificates($dbForPlatform, $queueForCertificates);
|
||||
$this->notifyDeleteCache($cacheRetention, $queueForDeletes);
|
||||
$this->notifyDeleteSchedules($schedulesDeletionRetention, $queueForDeletes);
|
||||
}, $interval, $delay);
|
||||
Console::warning("Deleting projects that there delete date smaller then ".DateTime::now());
|
||||
$dbForPlatform->foreach(
|
||||
'projects',
|
||||
function (Document $project) use ($dbForPlatform, $queueForDeletes) {
|
||||
|
||||
$queueForDeletes
|
||||
->setProject($project)
|
||||
->setType(DELETE_TYPE_DOCUMENT)
|
||||
->setDocument($project)
|
||||
->trigger();
|
||||
|
||||
Authorization::skip(fn () => $dbForPlatform->deleteDocument('projects', $project->getId()));
|
||||
}, [
|
||||
Query::lessThan('_deletedAt', DateTime::now()),
|
||||
Query::equal('region', [System::getEnv('_APP_REGION', 'default')]),
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
}, $interval, 0);
|
||||
}
|
||||
|
||||
private function notifyDeleteConnections(Delete $queueForDeletes): void
|
||||
|
||||
@@ -3876,7 +3876,25 @@ class ProjectsConsoleClientTest extends Scope
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(404, $project['headers']['status-code']);
|
||||
var_dump(['before restore' => $response['headers']['status-code']]);
|
||||
// restore from deletion
|
||||
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $projectId . '/restore', array_merge([
|
||||
'origin' => 'http://localhost',
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
|
||||
var_dump(['restore' => $response['headers']['status-code']]);
|
||||
|
||||
$project = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $project['headers']['status-code']);
|
||||
var_dump(['after restore' => $response['headers']['status-code']]);
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user