Merge branch '1.8.x' of https://github.com/appwrite/appwrite into migrations-cleanup

# Conflicts:
#	composer.lock
This commit is contained in:
fogelito
2026-01-07 09:37:48 +02:00
5 changed files with 191 additions and 164 deletions
+1 -1
View File
@@ -697,7 +697,7 @@ App::get('/v1/avatars/screenshots')
}
$client = new Client();
$client->setTimeout(30);
$client->setTimeout(30 * 1000); // 30 seconds
$client->addHeader('content-type', Client::CONTENT_TYPE_APPLICATION_JSON);
// Convert indexed array to empty array (should not happen due to Assoc validator)
+8 -2
View File
@@ -47,7 +47,7 @@
"appwrite/php-clamav": "2.0.*",
"utopia-php/abuse": "1.*.*",
"utopia-php/analytics": "0.10.*",
"utopia-php/audit": "2.0.2-rc1",
"utopia-php/audit": "2.0.2-rc3",
"utopia-php/auth": "0.5.*",
"utopia-php/cache": "0.13.*",
"utopia-php/cli": "0.15.*",
@@ -59,7 +59,7 @@
"utopia-php/dns": "1.4.*",
"utopia-php/dsn": "0.2.1",
"utopia-php/framework": "0.33.*",
"utopia-php/fetch": "0.4.*",
"utopia-php/fetch": "0.5.*",
"utopia-php/image": "0.8.*",
"utopia-php/locale": "0.8.*",
"utopia-php/logger": "0.6.*",
@@ -100,6 +100,12 @@
"provide": {
"ext-phpiredis": "*"
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/utopia-php/migration.git"
}
],
"config": {
"platform": {
"php": "8.3"
Generated
+58 -48
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "ed8ed7aad5a4e5a4dc6bffd5b83d47c8",
"content-hash": "f63c88303152af32cae4c800b8642540",
"packages": [
{
"name": "adhocore/jwt",
@@ -3553,23 +3553,23 @@
},
{
"name": "utopia-php/audit",
"version": "2.0.2-rc1",
"version": "2.0.2-rc3",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/audit.git",
"reference": "7b35dab40bce66bda56eeeacd2bbcbf1e823f05f"
"reference": "f60a298b516300f56a328403b334b7d62a96e7e7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/7b35dab40bce66bda56eeeacd2bbcbf1e823f05f",
"reference": "7b35dab40bce66bda56eeeacd2bbcbf1e823f05f",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/f60a298b516300f56a328403b334b7d62a96e7e7",
"reference": "f60a298b516300f56a328403b334b7d62a96e7e7",
"shasum": ""
},
"require": {
"php": ">=8.0",
"utopia-php/database": "3.*",
"utopia-php/fetch": "^0.4.2",
"utopia-php/validators": "^0.1.0"
"utopia-php/fetch": "0.5.*",
"utopia-php/validators": "0.1.*"
},
"require-dev": {
"laravel/pint": "1.*",
@@ -3596,9 +3596,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/audit/issues",
"source": "https://github.com/utopia-php/audit/tree/2.0.2-rc1"
"source": "https://github.com/utopia-php/audit/tree/2.0.2-rc3"
},
"time": "2025-12-24T01:20:43+00:00"
"time": "2026-01-06T15:32:52+00:00"
},
{
"name": "utopia-php/auth",
@@ -4168,23 +4168,23 @@
},
{
"name": "utopia-php/emails",
"version": "0.6.3",
"version": "0.6.4",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/emails.git",
"reference": "9524d7f7bd1651a06fef8a3d964f774b04fe2918"
"reference": "fb2bd5c428e88f645b0f7ede0dd29ac0d120ec52"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/emails/zipball/9524d7f7bd1651a06fef8a3d964f774b04fe2918",
"reference": "9524d7f7bd1651a06fef8a3d964f774b04fe2918",
"url": "https://api.github.com/repos/utopia-php/emails/zipball/fb2bd5c428e88f645b0f7ede0dd29ac0d120ec52",
"reference": "fb2bd5c428e88f645b0f7ede0dd29ac0d120ec52",
"shasum": ""
},
"require": {
"php": ">=8.0",
"utopia-php/cli": "^0.15",
"utopia-php/domains": "^0.9",
"utopia-php/fetch": "^0.4",
"utopia-php/fetch": "^0.5",
"utopia-php/validators": "0.*"
},
"require-dev": {
@@ -4222,26 +4222,26 @@
],
"support": {
"issues": "https://github.com/utopia-php/emails/issues",
"source": "https://github.com/utopia-php/emails/tree/0.6.3"
"source": "https://github.com/utopia-php/emails/tree/0.6.4"
},
"time": "2025-11-26T12:27:47+00:00"
"time": "2025-12-18T16:36:50+00:00"
},
{
"name": "utopia-php/fetch",
"version": "0.4.2",
"version": "0.5.1",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/fetch.git",
"reference": "83986d1be75a2fae4e684107fe70dd78a8e19b77"
"reference": "a96a010e1c273f3888765449687baf58cbc61fcd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/fetch/zipball/83986d1be75a2fae4e684107fe70dd78a8e19b77",
"reference": "83986d1be75a2fae4e684107fe70dd78a8e19b77",
"url": "https://api.github.com/repos/utopia-php/fetch/zipball/a96a010e1c273f3888765449687baf58cbc61fcd",
"reference": "a96a010e1c273f3888765449687baf58cbc61fcd",
"shasum": ""
},
"require": {
"php": ">=8.0"
"php": ">=8.1"
},
"require-dev": {
"laravel/pint": "^1.5.0",
@@ -4261,9 +4261,9 @@
"description": "A simple library that provides an interface for making HTTP Requests.",
"support": {
"issues": "https://github.com/utopia-php/fetch/issues",
"source": "https://github.com/utopia-php/fetch/tree/0.4.2"
"source": "https://github.com/utopia-php/fetch/tree/0.5.1"
},
"time": "2025-04-25T13:48:02+00:00"
"time": "2025-12-18T16:25:10+00:00"
},
{
"name": "utopia-php/framework",
@@ -4516,16 +4516,16 @@
},
{
"name": "utopia-php/migration",
"version": "dev-cleanup-hook",
"version": "1.3.11",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/migration.git",
"reference": "88feeef1f9459a8fba6f0b978d4ddf27acabe167"
"reference": "798f0976a1c14234c4b283b858b08c9afbcc1662"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/migration/zipball/88feeef1f9459a8fba6f0b978d4ddf27acabe167",
"reference": "88feeef1f9459a8fba6f0b978d4ddf27acabe167",
"url": "https://api.github.com/repos/utopia-php/migration/zipball/798f0976a1c14234c4b283b858b08c9afbcc1662",
"reference": "798f0976a1c14234c4b283b858b08c9afbcc1662",
"shasum": ""
},
"require": {
@@ -4551,7 +4551,25 @@
"Utopia\\Migration\\": "src/Migration"
}
},
"notification-url": "https://packagist.org/downloads/",
"autoload-dev": {
"psr-4": {
"Utopia\\Tests\\": "tests/Migration"
}
},
"scripts": {
"test": [
"./vendor/bin/phpunit"
],
"lint": [
"./vendor/bin/pint --test"
],
"format": [
"./vendor/bin/pint"
],
"check": [
"./vendor/bin/phpstan analyse --level 3 src tests --memory-limit 2G"
]
},
"license": [
"MIT"
],
@@ -4564,10 +4582,10 @@
"utopia"
],
"support": {
"issues": "https://github.com/utopia-php/migration/issues",
"source": "https://github.com/utopia-php/migration/tree/cleanup-hook"
"source": "https://github.com/utopia-php/migration/tree/1.3.11",
"issues": "https://github.com/utopia-php/migration/issues"
},
"time": "2026-01-06T11:45:42+00:00"
"time": "2026-01-06T12:07:07+00:00"
},
{
"name": "utopia-php/mongo",
@@ -4838,23 +4856,23 @@
},
{
"name": "utopia-php/queue",
"version": "0.11.2",
"version": "0.11.3",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/queue.git",
"reference": "a854f7c4abc18e0eca55fc5608cd7088d71eb19f"
"reference": "f3b2623efe87595c9ed907b3efd587e77c622d3d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/queue/zipball/a854f7c4abc18e0eca55fc5608cd7088d71eb19f",
"reference": "a854f7c4abc18e0eca55fc5608cd7088d71eb19f",
"url": "https://api.github.com/repos/utopia-php/queue/zipball/f3b2623efe87595c9ed907b3efd587e77c622d3d",
"reference": "f3b2623efe87595c9ed907b3efd587e77c622d3d",
"shasum": ""
},
"require": {
"php": ">=8.3",
"php-amqplib/php-amqplib": "^3.7",
"utopia-php/cli": "0.15.*",
"utopia-php/fetch": "0.4.*",
"utopia-php/fetch": "0.5.*",
"utopia-php/framework": "0.33.*",
"utopia-php/pools": "0.8.*",
"utopia-php/telemetry": "*"
@@ -4898,9 +4916,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/queue/issues",
"source": "https://github.com/utopia-php/queue/tree/0.11.2"
"source": "https://github.com/utopia-php/queue/tree/0.11.3"
},
"time": "2025-12-17T09:32:35+00:00"
"time": "2025-12-19T10:56:22+00:00"
},
{
"name": "utopia-php/registry",
@@ -8943,18 +8961,10 @@
"time": "2024-03-07T20:33:40+00:00"
}
],
"aliases": [
{
"package": "utopia-php/migration",
"version": "dev-cleanup-hook",
"alias": "1.3.999",
"alias_normalized": "1.3.999.0"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {
"utopia-php/audit": 5,
"utopia-php/migration": 20
"utopia-php/audit": 5
},
"prefer-stable": false,
"prefer-lowest": false,
@@ -939,7 +939,7 @@ class Builds extends Action
}
$client = new FetchClient();
$client->setTimeout(\intval($resource->getAttribute('timeout', '15')));
$client->setTimeout(\intval($resource->getAttribute('timeout', '15')) * 1000);
$client->addHeader('content-type', FetchClient::CONTENT_TYPE_APPLICATION_JSON);
$bucket = Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots'));
+123 -112
View File
@@ -187,7 +187,7 @@ class Deletes extends Action
case DELETE_TYPE_MAINTENANCE:
$this->deleteExpiredTargets($project, $getProjectDB);
$this->deleteExecutionLogs($project, $getProjectDB, $executionRetention);
$this->deleteAuditLogs($project, $getProjectDB, $auditRetention);
$this->deleteAuditLogs($project, $getAudit, $auditRetention);
$this->deleteUsageStats($project, $getProjectDB, $getLogsDB, $hourlyUsageRetentionDatetime);
$this->deleteExpiredSessions($project, $getProjectDB);
$this->deleteExpiredTransactions($project, $getProjectDB);
@@ -516,125 +516,136 @@ class Deletes extends Action
$dsn = new DSN('mysql://' . $document->getAttribute('database', 'console'));
}
$dbForProject = $getProjectDB($document);
$projectCollectionIds = [
...\array_keys(Config::getParam('collections', [])['projects']),
SQL::COLLECTION,
AbuseDatabase::COLLECTION,
];
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
$sharedTablesV1 = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES_V1', ''));
$projectTables = !\in_array($dsn->getHost(), $sharedTables);
$sharedTablesV1 = \in_array($dsn->getHost(), $sharedTablesV1);
$sharedTablesV2 = !$projectTables && !$sharedTablesV1;
/**
* @var $dbForProject Database
*/
$dbForProject->foreach(Database::METADATA, function (Document $collection) use ($dbForProject, $projectTables, $projectCollectionIds) {
try {
if ($projectTables || !\in_array($collection->getId(), $projectCollectionIds)) {
$dbForProject->deleteCollection($collection->getId());
} else {
$this->deleteByGroup(
$collection->getId(),
[
Query::orderAsc()
],
database: $dbForProject
);
$dbForProject = $getProjectDB($document);
try {
/**
* Disable validation because of Cursor validation on $id underscores
*/
$dbForProject->disableValidation();
$projectCollectionIds = [
...\array_keys(Config::getParam('collections', [])['projects']),
SQL::COLLECTION,
AbuseDatabase::COLLECTION,
];
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
$sharedTablesV1 = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES_V1', ''));
$projectTables = !\in_array($dsn->getHost(), $sharedTables);
$sharedTablesV1 = \in_array($dsn->getHost(), $sharedTablesV1);
$sharedTablesV2 = !$projectTables && !$sharedTablesV1;
$dbForProject->foreach(Database::METADATA, function (Document $collection) use ($dbForProject, $projectTables, $projectCollectionIds) {
try {
if ($projectTables || !\in_array($collection->getId(), $projectCollectionIds)) {
$dbForProject->deleteCollection($collection->getId());
} else {
$this->deleteByGroup(
$collection->getId(),
[
Query::orderAsc()
],
database: $dbForProject
);
}
} catch (Throwable $e) {
Console::error('Error deleting ' . $collection->getId() . ' ' . $e->getMessage());
}
} catch (Throwable $e) {
Console::error('Error deleting ' . $collection->getId() . ' ' . $e->getMessage());
});
// Delete Platforms
$this->deleteByGroup('platforms', [
Query::equal('projectInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform);
// Delete project and function rules
$this->deleteByGroup('rules', [
Query::equal('projectInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform, function (Document $document) use ($dbForPlatform, $certificates) {
$this->deleteRule($dbForPlatform, $document, $certificates);
});
// Delete Keys
$this->deleteByGroup('keys', [
Query::equal('resourceType', ['projects']),
Query::equal('resourceInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform);
// Delete Webhooks
$this->deleteByGroup('webhooks', [
Query::equal('projectInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform);
// Delete VCS Installations
$this->deleteByGroup('installations', [
Query::equal('projectInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform);
// Delete VCS Repositories
$this->deleteByGroup('repositories', [
Query::equal('projectInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform);
// Delete VCS comments
$this->deleteByGroup('vcsComments', [
Query::equal('projectInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform);
// Delete Schedules
$this->deleteByGroup('schedules', [
Query::equal('projectId', [$projectId]),
Query::orderAsc()
], $dbForPlatform);
// Delete metadata table
if ($projectTables) {
$dbForProject->deleteCollection(Database::METADATA);
} elseif ($sharedTablesV1) {
$this->deleteByGroup(
Database::METADATA,
[
Query::orderAsc()
],
$dbForProject
);
} elseif ($sharedTablesV2) {
$queries = \array_map(
fn ($id) => Query::notEqual('$id', $id),
$projectCollectionIds
);
$queries[] = Query::orderAsc();
$this->deleteByGroup(
Database::METADATA,
$queries,
$dbForProject
);
}
});
// Delete Platforms
$this->deleteByGroup('platforms', [
Query::equal('projectInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform);
// Delete all storage directories
$deviceForFiles->delete($deviceForFiles->getRoot(), true);
$deviceForSites->delete($deviceForSites->getRoot(), true);
$deviceForFunctions->delete($deviceForFunctions->getRoot(), true);
$deviceForBuilds->delete($deviceForBuilds->getRoot(), true);
$deviceForCache->delete($deviceForCache->getRoot(), true);
// Delete project and function rules
$this->deleteByGroup('rules', [
Query::equal('projectInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform, function (Document $document) use ($dbForPlatform, $certificates) {
$this->deleteRule($dbForPlatform, $document, $certificates);
});
// Delete Keys
$this->deleteByGroup('keys', [
Query::equal('resourceType', ['projects']),
Query::equal('resourceInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform);
// Delete Webhooks
$this->deleteByGroup('webhooks', [
Query::equal('projectInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform);
// Delete VCS Installations
$this->deleteByGroup('installations', [
Query::equal('projectInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform);
// Delete VCS Repositories
$this->deleteByGroup('repositories', [
Query::equal('projectInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform);
// Delete VCS comments
$this->deleteByGroup('vcsComments', [
Query::equal('projectInternalId', [$projectInternalId]),
Query::orderAsc()
], $dbForPlatform);
// Delete Schedules
$this->deleteByGroup('schedules', [
Query::equal('projectId', [$projectId]),
Query::orderAsc()
], $dbForPlatform);
// Delete metadata table
if ($projectTables) {
$dbForProject->deleteCollection(Database::METADATA);
} elseif ($sharedTablesV1) {
$this->deleteByGroup(
Database::METADATA,
[
Query::orderAsc()
],
$dbForProject
);
} elseif ($sharedTablesV2) {
$queries = \array_map(
fn ($id) => Query::notEqual('$id', $id),
$projectCollectionIds
);
$queries[] = Query::orderAsc();
$this->deleteByGroup(
Database::METADATA,
$queries,
$dbForProject
);
} finally {
$dbForProject->enableValidation();
}
// Delete all storage directories
$deviceForFiles->delete($deviceForFiles->getRoot(), true);
$deviceForSites->delete($deviceForSites->getRoot(), true);
$deviceForFunctions->delete($deviceForFunctions->getRoot(), true);
$deviceForBuilds->delete($deviceForBuilds->getRoot(), true);
$deviceForCache->delete($deviceForCache->getRoot(), true);
}
/**