Merge branch 'master' of https://github.com/appwrite/appwrite into feat-4803-flutter-web-platform-type
This commit is contained in:
commit
24a7caf936
32 changed files with 190 additions and 716 deletions
16
.github/PULL_REQUEST_TEMPLATE.md
vendored
16
.github/PULL_REQUEST_TEMPLATE.md
vendored
|
@ -11,21 +11,17 @@ Happy contributing!
|
||||||
|
|
||||||
## What does this PR do?
|
## What does this PR do?
|
||||||
|
|
||||||
(Provide a description of what this PR does.)
|
(Provide a description of what this PR does and why it's needed.)
|
||||||
|
|
||||||
## Test Plan
|
## Test Plan
|
||||||
|
|
||||||
(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work.)
|
(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work. Screenshots may also be helpful.)
|
||||||
|
|
||||||
## Related PRs and Issues
|
## Related PRs and Issues
|
||||||
|
|
||||||
(If this PR is related to any other PR or resolves any issue or related to any issue link all related PR and issues here.)
|
- (Related PR or issue)
|
||||||
|
|
||||||
### Have you added your change to the [Changelog](https://github.com/appwrite/appwrite/blob/master/CHANGES.md)?
|
## Checklist
|
||||||
|
|
||||||
(The CHANGES.md file tracks all the changes that make it to the `main` branch. Add your change to this file in the following format)
|
- [ ] Have you read the [Contributing Guidelines on issues](https://github.com/appwrite/appwrite/blob/master/CONTRIBUTING.md)?
|
||||||
- One line description of your PR [#pr_number](Link to your PR)
|
- [ ] If the PR includes a change to an API's metadata (desc, label, params, etc.), does it also include updated API specs and example docs?
|
||||||
|
|
||||||
### Have you read the [Contributing Guidelines on issues](https://github.com/appwrite/appwrite/blob/master/CONTRIBUTING.md)?
|
|
||||||
|
|
||||||
(Write your answer here.)
|
|
||||||
|
|
Binary file not shown.
BIN
app/assets/dbip/dbip-country-lite-2023-01.mmdb
Normal file
BIN
app/assets/dbip/dbip-country-lite-2023-01.mmdb
Normal file
Binary file not shown.
|
@ -482,9 +482,9 @@ return [
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => '_APP_STORAGE_DEVICE',
|
'name' => '_APP_STORAGE_DEVICE',
|
||||||
'description' => 'Select default storage device. The default value is \'Local\'. List of supported adapters are \'Local\', \'S3\', \'DOSpaces\', \'Backblaze\', \'Linode\' and \'Wasabi\'.',
|
'description' => 'Select default storage device. The default value is \'local\'. List of supported adapters are \'local\', \'s3\', \'dospaces\', \'backblaze\', \'linode\' and \'wasabi\'.',
|
||||||
'introduction' => '0.13.0',
|
'introduction' => '0.13.0',
|
||||||
'default' => 'Local',
|
'default' => 'local',
|
||||||
'required' => false,
|
'required' => false,
|
||||||
'question' => '',
|
'question' => '',
|
||||||
],
|
],
|
||||||
|
|
|
@ -10,8 +10,8 @@ use Appwrite\Event\Mail;
|
||||||
use Appwrite\Event\Phone as EventPhone;
|
use Appwrite\Event\Phone as EventPhone;
|
||||||
use Appwrite\Extend\Exception;
|
use Appwrite\Extend\Exception;
|
||||||
use Appwrite\Network\Validator\Email;
|
use Appwrite\Network\Validator\Email;
|
||||||
use Appwrite\Network\Validator\Host;
|
use Utopia\Validator\Host;
|
||||||
use Appwrite\Network\Validator\URL;
|
use Utopia\Validator\URL;
|
||||||
use Appwrite\OpenSSL\OpenSSL;
|
use Appwrite\OpenSSL\OpenSSL;
|
||||||
use Appwrite\Template\Template;
|
use Appwrite\Template\Template;
|
||||||
use Appwrite\URL\URL as URLParser;
|
use Appwrite\URL\URL as URLParser;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Appwrite\Extend\Exception;
|
use Appwrite\Extend\Exception;
|
||||||
use Appwrite\Network\Validator\URL;
|
use Utopia\Validator\URL;
|
||||||
use Appwrite\URL\URL as URLParse;
|
use Appwrite\URL\URL as URLParse;
|
||||||
use Appwrite\Utopia\Response;
|
use Appwrite\Utopia\Response;
|
||||||
use chillerlan\QRCode\QRCode;
|
use chillerlan\QRCode\QRCode;
|
||||||
|
|
|
@ -33,8 +33,8 @@ use Utopia\Database\Exception\Structure as StructureException;
|
||||||
use Utopia\Locale\Locale;
|
use Utopia\Locale\Locale;
|
||||||
use Appwrite\Auth\Auth;
|
use Appwrite\Auth\Auth;
|
||||||
use Appwrite\Network\Validator\Email;
|
use Appwrite\Network\Validator\Email;
|
||||||
use Appwrite\Network\Validator\IP;
|
use Utopia\Validator\IP;
|
||||||
use Appwrite\Network\Validator\URL;
|
use Utopia\Validator\URL;
|
||||||
use Appwrite\Utopia\Database\Validator\CustomId;
|
use Appwrite\Utopia\Database\Validator\CustomId;
|
||||||
use Appwrite\Utopia\Database\Validator\Query\Limit;
|
use Appwrite\Utopia\Database\Validator\Query\Limit;
|
||||||
use Appwrite\Utopia\Database\Validator\Query\Offset;
|
use Appwrite\Utopia\Database\Validator\Query\Offset;
|
||||||
|
|
|
@ -6,9 +6,9 @@ use Appwrite\Event\Certificate;
|
||||||
use Appwrite\Event\Delete;
|
use Appwrite\Event\Delete;
|
||||||
use Appwrite\Event\Validator\Event;
|
use Appwrite\Event\Validator\Event;
|
||||||
use Appwrite\Network\Validator\CNAME;
|
use Appwrite\Network\Validator\CNAME;
|
||||||
use Appwrite\Network\Validator\Domain as DomainValidator;
|
use Utopia\Validator\Domain as DomainValidator;
|
||||||
use Appwrite\Network\Validator\Origin;
|
use Appwrite\Network\Validator\Origin;
|
||||||
use Appwrite\Network\Validator\URL;
|
use Utopia\Validator\URL;
|
||||||
use Appwrite\Utopia\Database\Validator\CustomId;
|
use Appwrite\Utopia\Database\Validator\CustomId;
|
||||||
use Appwrite\Utopia\Response;
|
use Appwrite\Utopia\Response;
|
||||||
use Utopia\Abuse\Adapters\TimeLimit;
|
use Utopia\Abuse\Adapters\TimeLimit;
|
||||||
|
|
|
@ -65,7 +65,7 @@ App::post('/v1/storage/buckets')
|
||||||
->param('enabled', true, new Boolean(true), 'Is bucket enabled?', true)
|
->param('enabled', true, new Boolean(true), 'Is bucket enabled?', true)
|
||||||
->param('maximumFileSize', (int) App::getEnv('_APP_STORAGE_LIMIT', 0), new Range(1, (int) App::getEnv('_APP_STORAGE_LIMIT', 0)), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(App::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '. For self-hosted setups you can change the max limit by changing the `_APP_STORAGE_LIMIT` environment variable. [Learn more about storage environment variables](docs/environment-variables#storage)', true)
|
->param('maximumFileSize', (int) App::getEnv('_APP_STORAGE_LIMIT', 0), new Range(1, (int) App::getEnv('_APP_STORAGE_LIMIT', 0)), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(App::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '. For self-hosted setups you can change the max limit by changing the `_APP_STORAGE_LIMIT` environment variable. [Learn more about storage environment variables](docs/environment-variables#storage)', true)
|
||||||
->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true)
|
->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true)
|
||||||
->param('compression', 'none', new WhiteList([COMPRESSION_TYPE_NONE, COMPRESSION_TYPE_GZIP, COMPRESSION_TYPE_ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . COMPRESSION_TYPE_NONE . ', [' . COMPRESSION_TYPE_GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . COMPRESSION_TYPE_ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true)
|
->param('compression', COMPRESSION_TYPE_NONE, new WhiteList([COMPRESSION_TYPE_NONE, COMPRESSION_TYPE_GZIP, COMPRESSION_TYPE_ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . COMPRESSION_TYPE_NONE . ', [' . COMPRESSION_TYPE_GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . COMPRESSION_TYPE_ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true)
|
||||||
->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true)
|
->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true)
|
||||||
->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true)
|
->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true)
|
||||||
->inject('response')
|
->inject('response')
|
||||||
|
@ -237,7 +237,7 @@ App::put('/v1/storage/buckets/:bucketId')
|
||||||
->param('enabled', true, new Boolean(true), 'Is bucket enabled?', true)
|
->param('enabled', true, new Boolean(true), 'Is bucket enabled?', true)
|
||||||
->param('maximumFileSize', null, new Range(1, (int) App::getEnv('_APP_STORAGE_LIMIT', 0)), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human((int)App::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '. For self hosted version you can change the limit by changing _APP_STORAGE_LIMIT environment variable. [Learn more about storage environment variables](docs/environment-variables#storage)', true)
|
->param('maximumFileSize', null, new Range(1, (int) App::getEnv('_APP_STORAGE_LIMIT', 0)), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human((int)App::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '. For self hosted version you can change the limit by changing _APP_STORAGE_LIMIT environment variable. [Learn more about storage environment variables](docs/environment-variables#storage)', true)
|
||||||
->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true)
|
->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true)
|
||||||
->param('compression', 'none', new WhiteList([COMPRESSION_TYPE_NONE, COMPRESSION_TYPE_GZIP, COMPRESSION_TYPE_ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . COMPRESSION_TYPE_NONE . ', [' . COMPRESSION_TYPE_GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . COMPRESSION_TYPE_ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true)
|
->param('compression', COMPRESSION_TYPE_NONE, new WhiteList([COMPRESSION_TYPE_NONE, COMPRESSION_TYPE_GZIP, COMPRESSION_TYPE_ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . COMPRESSION_TYPE_NONE . ', [' . COMPRESSION_TYPE_GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . COMPRESSION_TYPE_ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true)
|
||||||
->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true)
|
->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true)
|
||||||
->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true)
|
->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true)
|
||||||
->inject('response')
|
->inject('response')
|
||||||
|
@ -501,7 +501,7 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($chunksUploaded === $chunks) {
|
if ($chunksUploaded === $chunks) {
|
||||||
if (App::getEnv('_APP_STORAGE_ANTIVIRUS') === 'enabled' && $bucket->getAttribute('antivirus', true) && $fileSize <= APP_LIMIT_ANTIVIRUS && App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL) === Storage::DEVICE_LOCAL) {
|
if (App::getEnv('_APP_STORAGE_ANTIVIRUS') === 'enabled' && $bucket->getAttribute('antivirus', true) && $fileSize <= APP_LIMIT_ANTIVIRUS && strtolower(App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL)) === Storage::DEVICE_LOCAL) {
|
||||||
$antivirus = new Network(
|
$antivirus = new Network(
|
||||||
App::getEnv('_APP_STORAGE_ANTIVIRUS_HOST', 'clamav'),
|
App::getEnv('_APP_STORAGE_ANTIVIRUS_HOST', 'clamav'),
|
||||||
(int) App::getEnv('_APP_STORAGE_ANTIVIRUS_PORT', 3310)
|
(int) App::getEnv('_APP_STORAGE_ANTIVIRUS_PORT', 3310)
|
||||||
|
@ -516,14 +516,14 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
||||||
$mimeType = $deviceFiles->getFileMimeType($path); // Get mime-type before compression and encryption
|
$mimeType = $deviceFiles->getFileMimeType($path); // Get mime-type before compression and encryption
|
||||||
$data = '';
|
$data = '';
|
||||||
// Compression
|
// Compression
|
||||||
$algorithm = $bucket->getAttribute('compression', 'none');
|
$algorithm = $bucket->getAttribute('compression', COMPRESSION_TYPE_NONE);
|
||||||
if ($fileSize <= APP_STORAGE_READ_BUFFER && $algorithm != 'none') {
|
if ($fileSize <= APP_STORAGE_READ_BUFFER && $algorithm != COMPRESSION_TYPE_NONE) {
|
||||||
$data = $deviceFiles->read($path);
|
$data = $deviceFiles->read($path);
|
||||||
switch ($algorithm) {
|
switch ($algorithm) {
|
||||||
case 'zstd':
|
case COMPRESSION_TYPE_ZSTD:
|
||||||
$compressor = new Zstd();
|
$compressor = new Zstd();
|
||||||
break;
|
break;
|
||||||
case 'gzip':
|
case COMPRESSION_TYPE_GZIP:
|
||||||
default:
|
default:
|
||||||
$compressor = new GZIP();
|
$compressor = new GZIP();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -7,7 +7,7 @@ use Appwrite\Event\Event;
|
||||||
use Appwrite\Event\Mail;
|
use Appwrite\Event\Mail;
|
||||||
use Appwrite\Extend\Exception;
|
use Appwrite\Extend\Exception;
|
||||||
use Appwrite\Network\Validator\Email;
|
use Appwrite\Network\Validator\Email;
|
||||||
use Appwrite\Network\Validator\Host;
|
use Utopia\Validator\Host;
|
||||||
use Appwrite\Template\Template;
|
use Appwrite\Template\Template;
|
||||||
use Appwrite\Utopia\Database\Validator\CustomId;
|
use Appwrite\Utopia\Database\Validator\CustomId;
|
||||||
use Appwrite\Utopia\Database\Validator\Queries;
|
use Appwrite\Utopia\Database\Validator\Queries;
|
||||||
|
|
|
@ -4,7 +4,7 @@ global $utopia, $request, $response;
|
||||||
|
|
||||||
use Appwrite\Extend\Exception;
|
use Appwrite\Extend\Exception;
|
||||||
use Utopia\Database\Document;
|
use Utopia\Database\Document;
|
||||||
use Appwrite\Network\Validator\Host;
|
use Utopia\Validator\Host;
|
||||||
use Appwrite\Utopia\Request;
|
use Appwrite\Utopia\Request;
|
||||||
use Appwrite\Utopia\Response;
|
use Appwrite\Utopia\Response;
|
||||||
use Appwrite\Utopia\Response\Model;
|
use Appwrite\Utopia\Response\Model;
|
||||||
|
|
|
@ -119,7 +119,7 @@ function logError(Throwable $error, string $action, Utopia\Route $route = null)
|
||||||
|
|
||||||
function getStorageDevice($root): Device
|
function getStorageDevice($root): Device
|
||||||
{
|
{
|
||||||
switch (App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL)) {
|
switch (strtolower(App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL))) {
|
||||||
case Storage::DEVICE_LOCAL:
|
case Storage::DEVICE_LOCAL:
|
||||||
default:
|
default:
|
||||||
return new Local($root);
|
return new Local($root);
|
||||||
|
|
|
@ -33,9 +33,7 @@ use Appwrite\Extend\PDO;
|
||||||
use Appwrite\GraphQL\Promises\Adapter\Swoole;
|
use Appwrite\GraphQL\Promises\Adapter\Swoole;
|
||||||
use Appwrite\GraphQL\Schema;
|
use Appwrite\GraphQL\Schema;
|
||||||
use Appwrite\Network\Validator\Email;
|
use Appwrite\Network\Validator\Email;
|
||||||
use Appwrite\Network\Validator\IP;
|
|
||||||
use Appwrite\Network\Validator\Origin;
|
use Appwrite\Network\Validator\Origin;
|
||||||
use Appwrite\Network\Validator\URL;
|
|
||||||
use Appwrite\OpenSSL\OpenSSL;
|
use Appwrite\OpenSSL\OpenSSL;
|
||||||
use Appwrite\Usage\Stats;
|
use Appwrite\Usage\Stats;
|
||||||
use MaxMind\Db\Reader;
|
use MaxMind\Db\Reader;
|
||||||
|
@ -74,6 +72,8 @@ use Utopia\Storage\Device\S3;
|
||||||
use Utopia\Storage\Device\Wasabi;
|
use Utopia\Storage\Device\Wasabi;
|
||||||
use Utopia\Storage\Storage;
|
use Utopia\Storage\Storage;
|
||||||
use Utopia\Validator\Range;
|
use Utopia\Validator\Range;
|
||||||
|
use Utopia\Validator\IP;
|
||||||
|
use Utopia\Validator\URL;
|
||||||
use Utopia\Validator\WhiteList;
|
use Utopia\Validator\WhiteList;
|
||||||
|
|
||||||
const APP_NAME = 'Appwrite';
|
const APP_NAME = 'Appwrite';
|
||||||
|
@ -605,7 +605,7 @@ $register->set('smtp', function () {
|
||||||
return $mail;
|
return $mail;
|
||||||
});
|
});
|
||||||
$register->set('geodb', function () {
|
$register->set('geodb', function () {
|
||||||
return new Reader(__DIR__ . '/assets/dbip/dbip-country-lite-2022-06.mmdb');
|
return new Reader(__DIR__ . '/assets/dbip/dbip-country-lite-2023-01.mmdb');
|
||||||
});
|
});
|
||||||
$register->set('db', function () {
|
$register->set('db', function () {
|
||||||
// This is usually for our workers or CLI commands scope
|
// This is usually for our workers or CLI commands scope
|
||||||
|
@ -969,7 +969,7 @@ App::setResource('deviceBuilds', function ($project) {
|
||||||
|
|
||||||
function getDevice($root): Device
|
function getDevice($root): Device
|
||||||
{
|
{
|
||||||
switch (App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL)) {
|
switch (strtolower(App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL))) {
|
||||||
case Storage::DEVICE_LOCAL:
|
case Storage::DEVICE_LOCAL:
|
||||||
default:
|
default:
|
||||||
return new Local($root);
|
return new Local($root);
|
||||||
|
|
|
@ -509,6 +509,7 @@ services:
|
||||||
entrypoint: worker-messaging
|
entrypoint: worker-messaging
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
container_name: appwrite-worker-messaging
|
container_name: appwrite-worker-messaging
|
||||||
|
restart: unless-stopped
|
||||||
networks:
|
networks:
|
||||||
- appwrite
|
- appwrite
|
||||||
depends_on:
|
depends_on:
|
||||||
|
|
|
@ -91,7 +91,7 @@ class BuildsV1 extends Worker
|
||||||
'outputPath' => '',
|
'outputPath' => '',
|
||||||
'runtime' => $function->getAttribute('runtime'),
|
'runtime' => $function->getAttribute('runtime'),
|
||||||
'source' => $deployment->getAttribute('path'),
|
'source' => $deployment->getAttribute('path'),
|
||||||
'sourceType' => App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL),
|
'sourceType' => strtolower(App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL)),
|
||||||
'stdout' => '',
|
'stdout' => '',
|
||||||
'stderr' => '',
|
'stderr' => '',
|
||||||
'endTime' => null,
|
'endTime' => null,
|
||||||
|
|
|
@ -44,9 +44,6 @@ class DeletesV1 extends Worker
|
||||||
case DELETE_TYPE_DATABASES:
|
case DELETE_TYPE_DATABASES:
|
||||||
$this->deleteDatabase($document, $project->getId());
|
$this->deleteDatabase($document, $project->getId());
|
||||||
break;
|
break;
|
||||||
case DELETE_TYPE_COLLECTIONS:
|
|
||||||
$this->deleteCollection($document, $project->getId());
|
|
||||||
break;
|
|
||||||
case DELETE_TYPE_PROJECTS:
|
case DELETE_TYPE_PROJECTS:
|
||||||
$this->deleteProject($document);
|
$this->deleteProject($document);
|
||||||
break;
|
break;
|
||||||
|
@ -66,6 +63,10 @@ class DeletesV1 extends Worker
|
||||||
$this->deleteBucket($document, $project->getId());
|
$this->deleteBucket($document, $project->getId());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
if (\str_starts_with($document->getCollection(), 'database_')) {
|
||||||
|
$this->deleteCollection($document, $project->getId());
|
||||||
|
break;
|
||||||
|
}
|
||||||
Console::error('No lazy delete operation available for document of type: ' . $document->getCollection());
|
Console::error('No lazy delete operation available for document of type: ' . $document->getCollection());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -172,6 +173,7 @@ class DeletesV1 extends Worker
|
||||||
/**
|
/**
|
||||||
* @param Document $document database document
|
* @param Document $document database document
|
||||||
* @param string $projectId
|
* @param string $projectId
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteDatabase(Document $document, string $projectId): void
|
protected function deleteDatabase(Document $document, string $projectId): void
|
||||||
{
|
{
|
||||||
|
@ -191,6 +193,7 @@ class DeletesV1 extends Worker
|
||||||
/**
|
/**
|
||||||
* @param Document $document teams document
|
* @param Document $document teams document
|
||||||
* @param string $projectId
|
* @param string $projectId
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteCollection(Document $document, string $projectId): void
|
protected function deleteCollection(Document $document, string $projectId): void
|
||||||
{
|
{
|
||||||
|
@ -217,6 +220,7 @@ class DeletesV1 extends Worker
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $hourlyUsageRetentionDatetime
|
* @param string $hourlyUsageRetentionDatetime
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteUsageStats(string $hourlyUsageRetentionDatetime)
|
protected function deleteUsageStats(string $hourlyUsageRetentionDatetime)
|
||||||
{
|
{
|
||||||
|
@ -232,6 +236,7 @@ class DeletesV1 extends Worker
|
||||||
/**
|
/**
|
||||||
* @param Document $document teams document
|
* @param Document $document teams document
|
||||||
* @param string $projectId
|
* @param string $projectId
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteMemberships(Document $document, string $projectId): void
|
protected function deleteMemberships(Document $document, string $projectId): void
|
||||||
{
|
{
|
||||||
|
@ -245,25 +250,62 @@ class DeletesV1 extends Worker
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Document $document project document
|
* @param Document $document project document
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteProject(Document $document): void
|
protected function deleteProject(Document $document): void
|
||||||
{
|
{
|
||||||
$projectId = $document->getId();
|
$projectId = $document->getId();
|
||||||
|
|
||||||
// Delete all DBs
|
// Delete project domains and certificates
|
||||||
$this->getProjectDB($projectId)->delete($projectId);
|
$dbForConsole = $this->getConsoleDB();
|
||||||
|
|
||||||
|
$domains = $dbForConsole->find('domains', [
|
||||||
|
Query::equal('projectInternalId', [$document->getInternalId()])
|
||||||
|
]);
|
||||||
|
|
||||||
|
foreach ($domains as $domain) {
|
||||||
|
$this->deleteCertificates($domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete project tables
|
||||||
|
$dbForProject = $this->getProjectDB($projectId, $document);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
$collections = $dbForProject->listCollections();
|
||||||
|
|
||||||
|
if (empty($collections)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($collections as $collection) {
|
||||||
|
$dbForProject->deleteCollection($collection->getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete metadata tables
|
||||||
|
try {
|
||||||
|
$dbForProject->deleteCollection('_metadata');
|
||||||
|
} catch (Exception) {
|
||||||
|
// Ignore: deleteCollection tries to delete a metadata entry after the collection is deleted,
|
||||||
|
// which will throw an exception here because the metadata collection is already deleted.
|
||||||
|
}
|
||||||
|
|
||||||
// Delete all storage directories
|
// Delete all storage directories
|
||||||
$uploads = $this->getFilesDevice($document->getId());
|
$uploads = $this->getFilesDevice($projectId);
|
||||||
$cache = new Local(APP_STORAGE_CACHE . '/app-' . $document->getId());
|
$functions = $this->getFunctionsDevice($projectId);
|
||||||
|
$builds = $this->getBuildsDevice($projectId);
|
||||||
|
$cache = $this->getCacheDevice($projectId);
|
||||||
|
|
||||||
$uploads->delete($uploads->getRoot(), true);
|
$uploads->delete($uploads->getRoot(), true);
|
||||||
|
$functions->delete($functions->getRoot(), true);
|
||||||
|
$builds->delete($builds->getRoot(), true);
|
||||||
$cache->delete($cache->getRoot(), true);
|
$cache->delete($cache->getRoot(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Document $document user document
|
* @param Document $document user document
|
||||||
* @param string $projectId
|
* @param string $projectId
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteUser(Document $document, string $projectId): void
|
protected function deleteUser(Document $document, string $projectId): void
|
||||||
{
|
{
|
||||||
|
@ -305,6 +347,7 @@ class DeletesV1 extends Worker
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $datetime
|
* @param string $datetime
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteExecutionLogs(string $datetime): void
|
protected function deleteExecutionLogs(string $datetime): void
|
||||||
{
|
{
|
||||||
|
@ -337,6 +380,7 @@ class DeletesV1 extends Worker
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $datetime
|
* @param string $datetime
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteRealtimeUsage(string $datetime): void
|
protected function deleteRealtimeUsage(string $datetime): void
|
||||||
{
|
{
|
||||||
|
@ -393,6 +437,7 @@ class DeletesV1 extends Worker
|
||||||
/**
|
/**
|
||||||
* @param string $resource
|
* @param string $resource
|
||||||
* @param string $projectId
|
* @param string $projectId
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteAuditLogsByResource(string $resource, string $projectId): void
|
protected function deleteAuditLogsByResource(string $resource, string $projectId): void
|
||||||
{
|
{
|
||||||
|
@ -406,6 +451,7 @@ class DeletesV1 extends Worker
|
||||||
/**
|
/**
|
||||||
* @param Document $document function document
|
* @param Document $document function document
|
||||||
* @param string $projectId
|
* @param string $projectId
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteFunction(Document $document, string $projectId): void
|
protected function deleteFunction(Document $document, string $projectId): void
|
||||||
{
|
{
|
||||||
|
@ -479,6 +525,7 @@ class DeletesV1 extends Worker
|
||||||
/**
|
/**
|
||||||
* @param Document $document deployment document
|
* @param Document $document deployment document
|
||||||
* @param string $projectId
|
* @param string $projectId
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteDeployment(Document $document, string $projectId): void
|
protected function deleteDeployment(Document $document, string $projectId): void
|
||||||
{
|
{
|
||||||
|
@ -528,9 +575,10 @@ class DeletesV1 extends Worker
|
||||||
/**
|
/**
|
||||||
* @param Document $document to be deleted
|
* @param Document $document to be deleted
|
||||||
* @param Database $database to delete it from
|
* @param Database $database to delete it from
|
||||||
* @param callable $callback to perform after document is deleted
|
* @param callable|null $callback to perform after document is deleted
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
|
* @throws \Utopia\Database\Exception\Authorization
|
||||||
*/
|
*/
|
||||||
protected function deleteById(Document $document, Database $database, callable $callback = null): bool
|
protected function deleteById(Document $document, Database $database, callable $callback = null): bool
|
||||||
{
|
{
|
||||||
|
@ -550,6 +598,7 @@ class DeletesV1 extends Worker
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param callable $callback
|
* @param callable $callback
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteForProjectIds(callable $callback): void
|
protected function deleteForProjectIds(callable $callback): void
|
||||||
{
|
{
|
||||||
|
@ -584,9 +633,10 @@ class DeletesV1 extends Worker
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $collection collectionID
|
* @param string $collection collectionID
|
||||||
* @param Query[] $queries
|
* @param array $queries
|
||||||
* @param Database $database
|
* @param Database $database
|
||||||
* @param callable $callback
|
* @param callable|null $callback
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function deleteByGroup(string $collection, array $queries, Database $database, callable $callback = null): void
|
protected function deleteByGroup(string $collection, array $queries, Database $database, callable $callback = null): void
|
||||||
{
|
{
|
||||||
|
@ -620,6 +670,7 @@ class DeletesV1 extends Worker
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Document $document certificates document
|
* @param Document $document certificates document
|
||||||
|
* @throws \Utopia\Database\Exception\Authorization
|
||||||
*/
|
*/
|
||||||
protected function deleteCertificates(Document $document): void
|
protected function deleteCertificates(Document $document): void
|
||||||
{
|
{
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
"utopia-php/config": "0.2.*",
|
"utopia-php/config": "0.2.*",
|
||||||
"utopia-php/database": "0.28.*",
|
"utopia-php/database": "0.28.*",
|
||||||
"utopia-php/domains": "1.1.*",
|
"utopia-php/domains": "1.1.*",
|
||||||
"utopia-php/framework": "0.25.*",
|
"utopia-php/framework": "0.26.*",
|
||||||
"utopia-php/image": "0.5.*",
|
"utopia-php/image": "0.5.*",
|
||||||
"utopia-php/locale": "0.4.*",
|
"utopia-php/locale": "0.4.*",
|
||||||
"utopia-php/logger": "0.3.*",
|
"utopia-php/logger": "0.3.*",
|
||||||
|
|
44
composer.lock
generated
44
composer.lock
generated
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "dbc502462e4afa550b1a1bc3898020b3",
|
"content-hash": "8782e69514f4564a3dcb44455161eedc",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "adhocore/jwt",
|
"name": "adhocore/jwt",
|
||||||
|
@ -1946,16 +1946,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "utopia-php/framework",
|
"name": "utopia-php/framework",
|
||||||
"version": "0.25.1",
|
"version": "0.26.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/utopia-php/framework.git",
|
"url": "https://github.com/utopia-php/framework.git",
|
||||||
"reference": "2391b397135586b2100d39e338827bef8d2f4ad0"
|
"reference": "e8da5576370366d3bf9c574ec855f8c96fe4f34e"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/utopia-php/framework/zipball/2391b397135586b2100d39e338827bef8d2f4ad0",
|
"url": "https://api.github.com/repos/utopia-php/framework/zipball/e8da5576370366d3bf9c574ec855f8c96fe4f34e",
|
||||||
"reference": "2391b397135586b2100d39e338827bef8d2f4ad0",
|
"reference": "e8da5576370366d3bf9c574ec855f8c96fe4f34e",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -1984,9 +1984,9 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/utopia-php/framework/issues",
|
"issues": "https://github.com/utopia-php/framework/issues",
|
||||||
"source": "https://github.com/utopia-php/framework/tree/0.25.1"
|
"source": "https://github.com/utopia-php/framework/tree/0.26.0"
|
||||||
},
|
},
|
||||||
"time": "2022-11-23T18:22:23+00:00"
|
"time": "2023-01-13T08:14:43+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "utopia-php/image",
|
"name": "utopia-php/image",
|
||||||
|
@ -2652,16 +2652,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "webonyx/graphql-php",
|
"name": "webonyx/graphql-php",
|
||||||
"version": "v14.11.8",
|
"version": "v14.11.9",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/webonyx/graphql-php.git",
|
"url": "https://github.com/webonyx/graphql-php.git",
|
||||||
"reference": "04a48693acd785330eefd3b0e4fa67df8dfee7c3"
|
"reference": "ff91c9f3cf241db702e30b2c42bcc0920e70ac70"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/webonyx/graphql-php/zipball/04a48693acd785330eefd3b0e4fa67df8dfee7c3",
|
"url": "https://api.github.com/repos/webonyx/graphql-php/zipball/ff91c9f3cf241db702e30b2c42bcc0920e70ac70",
|
||||||
"reference": "04a48693acd785330eefd3b0e4fa67df8dfee7c3",
|
"reference": "ff91c9f3cf241db702e30b2c42bcc0920e70ac70",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -2706,7 +2706,7 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/webonyx/graphql-php/issues",
|
"issues": "https://github.com/webonyx/graphql-php/issues",
|
||||||
"source": "https://github.com/webonyx/graphql-php/tree/v14.11.8"
|
"source": "https://github.com/webonyx/graphql-php/tree/v14.11.9"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -2714,7 +2714,7 @@
|
||||||
"type": "open_collective"
|
"type": "open_collective"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2022-09-21T15:35:03+00:00"
|
"time": "2023-01-06T12:12:50+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
|
@ -2771,30 +2771,30 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/instantiator",
|
"name": "doctrine/instantiator",
|
||||||
"version": "1.4.1",
|
"version": "1.5.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/doctrine/instantiator.git",
|
"url": "https://github.com/doctrine/instantiator.git",
|
||||||
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc"
|
"reference": "0a0fa9780f5d4e507415a065172d26a98d02047b"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc",
|
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b",
|
||||||
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc",
|
"reference": "0a0fa9780f5d4e507415a065172d26a98d02047b",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.1 || ^8.0"
|
"php": "^7.1 || ^8.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"doctrine/coding-standard": "^9",
|
"doctrine/coding-standard": "^9 || ^11",
|
||||||
"ext-pdo": "*",
|
"ext-pdo": "*",
|
||||||
"ext-phar": "*",
|
"ext-phar": "*",
|
||||||
"phpbench/phpbench": "^0.16 || ^1",
|
"phpbench/phpbench": "^0.16 || ^1",
|
||||||
"phpstan/phpstan": "^1.4",
|
"phpstan/phpstan": "^1.4",
|
||||||
"phpstan/phpstan-phpunit": "^1",
|
"phpstan/phpstan-phpunit": "^1",
|
||||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
|
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
|
||||||
"vimeo/psalm": "^4.22"
|
"vimeo/psalm": "^4.30 || ^5.4"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
@ -2821,7 +2821,7 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/doctrine/instantiator/issues",
|
"issues": "https://github.com/doctrine/instantiator/issues",
|
||||||
"source": "https://github.com/doctrine/instantiator/tree/1.4.1"
|
"source": "https://github.com/doctrine/instantiator/tree/1.5.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -2837,7 +2837,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2022-03-03T08:28:38+00:00"
|
"time": "2022-12-30T00:15:36+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "matthiasmullie/minify",
|
"name": "matthiasmullie/minify",
|
||||||
|
@ -5271,5 +5271,5 @@
|
||||||
"platform-overrides": {
|
"platform-overrides": {
|
||||||
"php": "8.0"
|
"php": "8.0"
|
||||||
},
|
},
|
||||||
"plugin-api-version": "2.3.0"
|
"plugin-api-version": "2.1.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -554,6 +554,7 @@ services:
|
||||||
entrypoint: worker-messaging
|
entrypoint: worker-messaging
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
container_name: appwrite-worker-messaging
|
container_name: appwrite-worker-messaging
|
||||||
|
restart: unless-stopped
|
||||||
image: appwrite-dev
|
image: appwrite-dev
|
||||||
networks:
|
networks:
|
||||||
- appwrite
|
- appwrite
|
||||||
|
|
|
@ -228,18 +228,18 @@ class Mapper
|
||||||
case 'Appwrite\Network\Validator\CNAME':
|
case 'Appwrite\Network\Validator\CNAME':
|
||||||
case 'Appwrite\Task\Validator\Cron':
|
case 'Appwrite\Task\Validator\Cron':
|
||||||
case 'Appwrite\Utopia\Database\Validator\CustomId':
|
case 'Appwrite\Utopia\Database\Validator\CustomId':
|
||||||
case 'Appwrite\Network\Validator\Domain':
|
case 'Utopia\Validator\Domain':
|
||||||
case 'Appwrite\Network\Validator\Email':
|
case 'Appwrite\Network\Validator\Email':
|
||||||
case 'Appwrite\Event\Validator\Event':
|
case 'Appwrite\Event\Validator\Event':
|
||||||
case 'Utopia\Validator\HexColor':
|
case 'Utopia\Validator\HexColor':
|
||||||
case 'Appwrite\Network\Validator\Host':
|
case 'Utopia\Validator\Host':
|
||||||
case 'Appwrite\Network\Validator\IP':
|
case 'Utopia\Validator\IP':
|
||||||
case 'Utopia\Database\Validator\Key':
|
case 'Utopia\Database\Validator\Key':
|
||||||
case 'Appwrite\Network\Validator\Origin':
|
case 'Utopia\Validator\Origin':
|
||||||
case 'Appwrite\Auth\Validator\Password':
|
case 'Appwrite\Auth\Validator\Password':
|
||||||
case 'Utopia\Validator\Text':
|
case 'Utopia\Validator\Text':
|
||||||
case 'Utopia\Database\Validator\UID':
|
case 'Utopia\Database\Validator\UID':
|
||||||
case 'Appwrite\Network\Validator\URL':
|
case 'Utopia\Validator\URL':
|
||||||
case 'Utopia\Validator\WhiteList':
|
case 'Utopia\Validator\WhiteList':
|
||||||
default:
|
default:
|
||||||
$type = Type::string();
|
$type = Type::string();
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Appwrite\Network\Validator;
|
|
||||||
|
|
||||||
use Utopia\Validator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Domain
|
|
||||||
*
|
|
||||||
* Validate that an variable is a valid domain address
|
|
||||||
*
|
|
||||||
* @package Utopia\Validator
|
|
||||||
*/
|
|
||||||
class Domain extends Validator
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Get Description
|
|
||||||
*
|
|
||||||
* Returns validator description
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getDescription(): string
|
|
||||||
{
|
|
||||||
return 'Value must be a valid domain';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is valid
|
|
||||||
*
|
|
||||||
* Validation will pass when $value is valid domain.
|
|
||||||
*
|
|
||||||
* Validates domain names against RFC 1034, RFC 1035, RFC 952, RFC 1123, RFC 2732, RFC 2181, and RFC 1123.
|
|
||||||
*
|
|
||||||
* @param mixed $value
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isValid($value): bool
|
|
||||||
{
|
|
||||||
if (empty($value)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_string($value)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (\filter_var($value, FILTER_VALIDATE_DOMAIN) === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is array
|
|
||||||
*
|
|
||||||
* Function will return true if object is array.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isArray(): bool
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Type
|
|
||||||
*
|
|
||||||
* Returns validator type.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getType(): string
|
|
||||||
{
|
|
||||||
return self::TYPE_STRING;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,84 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Appwrite\Network\Validator;
|
|
||||||
|
|
||||||
use Utopia\Validator\Hostname;
|
|
||||||
use Utopia\Validator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Host
|
|
||||||
*
|
|
||||||
* Validate that a host is allowed from given whitelisted hosts list
|
|
||||||
*
|
|
||||||
* @package Utopia\Validator
|
|
||||||
*/
|
|
||||||
class Host extends Validator
|
|
||||||
{
|
|
||||||
protected $whitelist = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $whitelist
|
|
||||||
*/
|
|
||||||
public function __construct(array $whitelist)
|
|
||||||
{
|
|
||||||
$this->whitelist = $whitelist;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Description
|
|
||||||
*
|
|
||||||
* Returns validator description
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getDescription(): string
|
|
||||||
{
|
|
||||||
return 'URL host must be one of: ' . \implode(', ', $this->whitelist);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is valid
|
|
||||||
*
|
|
||||||
* Validation will pass when $value starts with one of the given hosts
|
|
||||||
*
|
|
||||||
* @param mixed $value
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isValid($value): bool
|
|
||||||
{
|
|
||||||
// Check if value is valid URL
|
|
||||||
$urlValidator = new URL();
|
|
||||||
|
|
||||||
if (!$urlValidator->isValid($value)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$hostname = \parse_url($value, PHP_URL_HOST);
|
|
||||||
$hostnameValidator = new Hostname($this->whitelist);
|
|
||||||
return $hostnameValidator->isValid($hostname);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is array
|
|
||||||
*
|
|
||||||
* Function will return true if object is array.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isArray(): bool
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Type
|
|
||||||
*
|
|
||||||
* Returns validator type.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getType(): string
|
|
||||||
{
|
|
||||||
return self::TYPE_STRING;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,114 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Appwrite\Network\Validator;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use Utopia\Validator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* IP
|
|
||||||
*
|
|
||||||
* Validate that an variable is a valid IP address
|
|
||||||
*
|
|
||||||
* @package Utopia\Validator
|
|
||||||
*/
|
|
||||||
class IP extends Validator
|
|
||||||
{
|
|
||||||
public const ALL = 'all';
|
|
||||||
public const V4 = 'ipv4';
|
|
||||||
public const V6 = 'ipv6';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $type = self::ALL;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*
|
|
||||||
* Set a the type of IP check.
|
|
||||||
*
|
|
||||||
* @param string $type
|
|
||||||
*/
|
|
||||||
public function __construct(string $type = self::ALL)
|
|
||||||
{
|
|
||||||
if (!in_array($type, [self::ALL, self::V4, self::V6])) {
|
|
||||||
throw new Exception('Unsupported IP type');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->type = $type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Description
|
|
||||||
*
|
|
||||||
* Returns validator description
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getDescription(): string
|
|
||||||
{
|
|
||||||
return 'Value must be a valid IP address';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is valid
|
|
||||||
*
|
|
||||||
* Validation will pass when $value is valid IP address.
|
|
||||||
*
|
|
||||||
* @param mixed $value
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isValid($value): bool
|
|
||||||
{
|
|
||||||
switch ($this->type) {
|
|
||||||
case self::ALL:
|
|
||||||
if (\filter_var($value, FILTER_VALIDATE_IP)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case self::V4:
|
|
||||||
if (\filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case self::V6:
|
|
||||||
if (\filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is array
|
|
||||||
*
|
|
||||||
* Function will return true if object is array.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isArray(): bool
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Type
|
|
||||||
*
|
|
||||||
* Returns validator type.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getType(): string
|
|
||||||
{
|
|
||||||
return self::TYPE_STRING;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,92 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Appwrite\Network\Validator;
|
|
||||||
|
|
||||||
use Utopia\Validator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* URL
|
|
||||||
*
|
|
||||||
* Validate that an variable is a valid URL
|
|
||||||
*
|
|
||||||
* @package Appwrite\Network\Validator
|
|
||||||
*/
|
|
||||||
class URL extends Validator
|
|
||||||
{
|
|
||||||
protected array $allowedSchemes;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $allowedSchemes
|
|
||||||
*/
|
|
||||||
public function __construct(array $allowedSchemes = [])
|
|
||||||
{
|
|
||||||
$this->allowedSchemes = $allowedSchemes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Description
|
|
||||||
*
|
|
||||||
* Returns validator description
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getDescription(): string
|
|
||||||
{
|
|
||||||
if (!empty($this->allowedSchemes)) {
|
|
||||||
return 'Value must be a valid URL with following schemes (' . \implode(', ', $this->allowedSchemes) . ')';
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'Value must be a valid URL';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is valid
|
|
||||||
*
|
|
||||||
* Validation will pass when $value is valid URL.
|
|
||||||
*
|
|
||||||
* @param mixed $value
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isValid($value): bool
|
|
||||||
{
|
|
||||||
$sanitizedURL = '';
|
|
||||||
|
|
||||||
foreach (str_split($value) as $character) {
|
|
||||||
$sanitizedURL .= (ord($character) > 127) ? rawurlencode($character) : $character;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (\filter_var($sanitizedURL, FILTER_VALIDATE_URL) === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($this->allowedSchemes) && !\in_array(\parse_url($sanitizedURL, PHP_URL_SCHEME), $this->allowedSchemes)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is array
|
|
||||||
*
|
|
||||||
* Function will return true if object is array.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isArray(): bool
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Type
|
|
||||||
*
|
|
||||||
* Returns validator type.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getType(): string
|
|
||||||
{
|
|
||||||
return self::TYPE_STRING;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,22 +2,23 @@
|
||||||
|
|
||||||
namespace Appwrite\Resque;
|
namespace Appwrite\Resque;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
use Utopia\App;
|
use Utopia\App;
|
||||||
use Utopia\Cache\Cache;
|
|
||||||
use Utopia\Cache\Adapter\Redis as RedisCache;
|
use Utopia\Cache\Adapter\Redis as RedisCache;
|
||||||
|
use Utopia\Cache\Cache;
|
||||||
use Utopia\CLI\Console;
|
use Utopia\CLI\Console;
|
||||||
use Utopia\Database\Database;
|
|
||||||
use Utopia\Database\Adapter\MariaDB;
|
use Utopia\Database\Adapter\MariaDB;
|
||||||
|
use Utopia\Database\Database;
|
||||||
|
use Utopia\Database\Document;
|
||||||
|
use Utopia\Database\Validator\Authorization;
|
||||||
use Utopia\Storage\Device;
|
use Utopia\Storage\Device;
|
||||||
use Utopia\Storage\Storage;
|
use Utopia\Storage\Device\Backblaze;
|
||||||
use Utopia\Storage\Device\Local;
|
|
||||||
use Utopia\Storage\Device\DOSpaces;
|
use Utopia\Storage\Device\DOSpaces;
|
||||||
use Utopia\Storage\Device\Linode;
|
use Utopia\Storage\Device\Linode;
|
||||||
use Utopia\Storage\Device\Wasabi;
|
use Utopia\Storage\Device\Local;
|
||||||
use Utopia\Storage\Device\Backblaze;
|
|
||||||
use Utopia\Storage\Device\S3;
|
use Utopia\Storage\Device\S3;
|
||||||
use Exception;
|
use Utopia\Storage\Device\Wasabi;
|
||||||
use Utopia\Database\Validator\Authorization;
|
use Utopia\Storage\Storage;
|
||||||
|
|
||||||
abstract class Worker
|
abstract class Worker
|
||||||
{
|
{
|
||||||
|
@ -53,7 +54,7 @@ abstract class Worker
|
||||||
* @return void
|
* @return void
|
||||||
* @throws \Exception|\Throwable
|
* @throws \Exception|\Throwable
|
||||||
*/
|
*/
|
||||||
public function init()
|
public function init(): void
|
||||||
{
|
{
|
||||||
throw new Exception("Please implement init method in worker");
|
throw new Exception("Please implement init method in worker");
|
||||||
}
|
}
|
||||||
|
@ -65,7 +66,7 @@ abstract class Worker
|
||||||
* @return void
|
* @return void
|
||||||
* @throws \Exception|\Throwable
|
* @throws \Exception|\Throwable
|
||||||
*/
|
*/
|
||||||
public function run()
|
public function run(): void
|
||||||
{
|
{
|
||||||
throw new Exception("Please implement run method in worker");
|
throw new Exception("Please implement run method in worker");
|
||||||
}
|
}
|
||||||
|
@ -77,7 +78,7 @@ abstract class Worker
|
||||||
* @return void
|
* @return void
|
||||||
* @throws \Exception|\Throwable
|
* @throws \Exception|\Throwable
|
||||||
*/
|
*/
|
||||||
public function shutdown()
|
public function shutdown(): void
|
||||||
{
|
{
|
||||||
throw new Exception("Please implement shutdown method in worker");
|
throw new Exception("Please implement shutdown method in worker");
|
||||||
}
|
}
|
||||||
|
@ -151,35 +152,39 @@ abstract class Worker
|
||||||
/**
|
/**
|
||||||
* Register callback. Will be executed when error occurs.
|
* Register callback. Will be executed when error occurs.
|
||||||
* @param callable $callback
|
* @param callable $callback
|
||||||
* @param Throwable $error
|
* @return void
|
||||||
* @return self
|
|
||||||
*/
|
*/
|
||||||
public static function error(callable $callback): void
|
public static function error(callable $callback): void
|
||||||
{
|
{
|
||||||
\array_push(self::$errorCallbacks, $callback);
|
self::$errorCallbacks[] = $callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get internal project database
|
* Get internal project database
|
||||||
* @param string $projectId
|
* @param string $projectId
|
||||||
* @return Database
|
* @return Database
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function getProjectDB(string $projectId): Database
|
protected function getProjectDB(string $projectId, ?Document $project = null): Database
|
||||||
{
|
{
|
||||||
$consoleDB = $this->getConsoleDB();
|
if ($project === null) {
|
||||||
|
$consoleDB = $this->getConsoleDB();
|
||||||
|
|
||||||
if ($projectId === 'console') {
|
if ($projectId === 'console') {
|
||||||
return $consoleDB;
|
return $consoleDB;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var Document $project */
|
||||||
|
$project = Authorization::skip(fn() => $consoleDB->getDocument('projects', $projectId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var Document $project */
|
return $this->getDB(self::DATABASE_PROJECT, $projectId, $project->getInternalId(), $project);
|
||||||
$project = Authorization::skip(fn() => $consoleDB->getDocument('projects', $projectId));
|
|
||||||
|
|
||||||
return $this->getDB(self::DATABASE_PROJECT, $projectId, $project->getInternalId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get console database
|
* Get console database
|
||||||
* @return Database
|
* @return Database
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function getConsoleDB(): Database
|
protected function getConsoleDB(): Database
|
||||||
{
|
{
|
||||||
|
@ -187,24 +192,35 @@ abstract class Worker
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get console database
|
* Get database
|
||||||
* @param string $type One of (internal, external, console)
|
* @param string $type One of (project, console)
|
||||||
* @param string $projectId of internal or external DB
|
* @param string $projectId of project or console DB
|
||||||
|
* @param string $projectInternalId
|
||||||
|
* @param Document|null $project
|
||||||
* @return Database
|
* @return Database
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
private function getDB(string $type, string $projectId = '', string $projectInternalId = ''): Database
|
private function getDB(
|
||||||
{
|
string $type,
|
||||||
|
string $projectId = '',
|
||||||
|
string $projectInternalId = '',
|
||||||
|
?Document $project = null
|
||||||
|
): Database {
|
||||||
global $register;
|
global $register;
|
||||||
|
|
||||||
$namespace = '';
|
|
||||||
$sleep = DATABASE_RECONNECT_SLEEP; // overwritten when necessary
|
$sleep = DATABASE_RECONNECT_SLEEP; // overwritten when necessary
|
||||||
|
|
||||||
|
if ($project !== null) {
|
||||||
|
$projectId = $project->getId();
|
||||||
|
$projectInternalId = $project->getInternalId();
|
||||||
|
}
|
||||||
|
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case self::DATABASE_PROJECT:
|
case self::DATABASE_PROJECT:
|
||||||
if (!$projectId) {
|
if (!$projectId) {
|
||||||
throw new \Exception('ProjectID not provided - cannot get database');
|
throw new \Exception('ProjectID not provided - cannot get database');
|
||||||
}
|
}
|
||||||
$namespace = "_{$projectInternalId}";
|
$namespace = "_$projectInternalId";
|
||||||
break;
|
break;
|
||||||
case self::DATABASE_CONSOLE:
|
case self::DATABASE_CONSOLE:
|
||||||
$namespace = "_console";
|
$namespace = "_console";
|
||||||
|
@ -212,12 +228,11 @@ abstract class Worker
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new \Exception('Unknown database type: ' . $type);
|
throw new \Exception('Unknown database type: ' . $type);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$attempts = 0;
|
$attempts = 0;
|
||||||
|
|
||||||
do {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
$attempts++;
|
$attempts++;
|
||||||
$cache = new Cache(new RedisCache($register->get('cache')));
|
$cache = new Cache(new RedisCache($register->get('cache')));
|
||||||
|
@ -225,8 +240,12 @@ abstract class Worker
|
||||||
$database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
|
$database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
|
||||||
$database->setNamespace($namespace); // Main DB
|
$database->setNamespace($namespace); // Main DB
|
||||||
|
|
||||||
if (!empty($projectId) && !$database->getDocument('projects', $projectId)->isEmpty()) {
|
if (
|
||||||
throw new \Exception("Project does not exist: {$projectId}");
|
$project === null
|
||||||
|
&& !empty($projectId)
|
||||||
|
&& !$database->getDocument('projects', $projectId)->isEmpty()
|
||||||
|
) {
|
||||||
|
throw new \Exception("Project does not exist: $projectId");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($type === self::DATABASE_CONSOLE && !$database->exists($database->getDefaultDatabase(), Database::METADATA)) {
|
if ($type === self::DATABASE_CONSOLE && !$database->exists($database->getDefaultDatabase(), Database::METADATA)) {
|
||||||
|
@ -235,13 +254,13 @@ abstract class Worker
|
||||||
|
|
||||||
break; // leave loop if successful
|
break; // leave loop if successful
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
Console::warning("Database not ready. Retrying connection ({$attempts})...");
|
Console::warning("Database not ready. Retrying connection ($attempts)...");
|
||||||
if ($attempts >= DATABASE_RECONNECT_MAX_ATTEMPTS) {
|
if ($attempts >= DATABASE_RECONNECT_MAX_ATTEMPTS) {
|
||||||
throw new \Exception('Failed to connect to database: ' . $e->getMessage());
|
throw new \Exception('Failed to connect to database: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
sleep($sleep);
|
sleep($sleep);
|
||||||
}
|
}
|
||||||
} while ($attempts < DATABASE_RECONNECT_MAX_ATTEMPTS);
|
}
|
||||||
|
|
||||||
return $database;
|
return $database;
|
||||||
}
|
}
|
||||||
|
@ -251,7 +270,7 @@ abstract class Worker
|
||||||
* @param string $projectId of the project
|
* @param string $projectId of the project
|
||||||
* @return Device
|
* @return Device
|
||||||
*/
|
*/
|
||||||
protected function getFunctionsDevice($projectId): Device
|
protected function getFunctionsDevice(string $projectId): Device
|
||||||
{
|
{
|
||||||
return $this->getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $projectId);
|
return $this->getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $projectId);
|
||||||
}
|
}
|
||||||
|
@ -261,7 +280,7 @@ abstract class Worker
|
||||||
* @param string $projectId of the project
|
* @param string $projectId of the project
|
||||||
* @return Device
|
* @return Device
|
||||||
*/
|
*/
|
||||||
protected function getFilesDevice($projectId): Device
|
protected function getFilesDevice(string $projectId): Device
|
||||||
{
|
{
|
||||||
return $this->getDevice(APP_STORAGE_UPLOADS . '/app-' . $projectId);
|
return $this->getDevice(APP_STORAGE_UPLOADS . '/app-' . $projectId);
|
||||||
}
|
}
|
||||||
|
@ -272,19 +291,24 @@ abstract class Worker
|
||||||
* @param string $projectId of the project
|
* @param string $projectId of the project
|
||||||
* @return Device
|
* @return Device
|
||||||
*/
|
*/
|
||||||
protected function getBuildsDevice($projectId): Device
|
protected function getBuildsDevice(string $projectId): Device
|
||||||
{
|
{
|
||||||
return $this->getDevice(APP_STORAGE_BUILDS . '/app-' . $projectId);
|
return $this->getDevice(APP_STORAGE_BUILDS . '/app-' . $projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getCacheDevice(string $projectId): Device
|
||||||
|
{
|
||||||
|
return $this->getDevice(APP_STORAGE_CACHE . '/app-' . $projectId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Device based on selected storage environment
|
* Get Device based on selected storage environment
|
||||||
* @param string $root path of the device
|
* @param string $root path of the device
|
||||||
* @return Device
|
* @return Device
|
||||||
*/
|
*/
|
||||||
public function getDevice($root): Device
|
public function getDevice(string $root): Device
|
||||||
{
|
{
|
||||||
switch (App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL)) {
|
switch (strtolower(App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL))) {
|
||||||
case Storage::DEVICE_LOCAL:
|
case Storage::DEVICE_LOCAL:
|
||||||
default:
|
default:
|
||||||
return new Local($root);
|
return new Local($root);
|
||||||
|
|
|
@ -311,7 +311,7 @@ class OpenAPI3 extends Format
|
||||||
$node['schema']['format'] = 'email';
|
$node['schema']['format'] = 'email';
|
||||||
$node['schema']['x-example'] = 'email@example.com';
|
$node['schema']['x-example'] = 'email@example.com';
|
||||||
break;
|
break;
|
||||||
case 'Appwrite\Network\Validator\URL':
|
case 'Utopia\Validator\URL':
|
||||||
$node['schema']['type'] = $validator->getType();
|
$node['schema']['type'] = $validator->getType();
|
||||||
$node['schema']['format'] = 'url';
|
$node['schema']['format'] = 'url';
|
||||||
$node['schema']['x-example'] = 'https://example.com';
|
$node['schema']['x-example'] = 'https://example.com';
|
||||||
|
@ -391,7 +391,7 @@ class OpenAPI3 extends Format
|
||||||
case 'Utopia\Validator\Length':
|
case 'Utopia\Validator\Length':
|
||||||
$node['schema']['type'] = $validator->getType();
|
$node['schema']['type'] = $validator->getType();
|
||||||
break;
|
break;
|
||||||
case 'Appwrite\Network\Validator\Host':
|
case 'Utopia\Validator\Host':
|
||||||
$node['schema']['type'] = $validator->getType();
|
$node['schema']['type'] = $validator->getType();
|
||||||
$node['schema']['format'] = 'url';
|
$node['schema']['format'] = 'url';
|
||||||
$node['schema']['x-example'] = 'https://example.com';
|
$node['schema']['x-example'] = 'https://example.com';
|
||||||
|
|
|
@ -312,7 +312,7 @@ class Swagger2 extends Format
|
||||||
$node['format'] = 'email';
|
$node['format'] = 'email';
|
||||||
$node['x-example'] = 'email@example.com';
|
$node['x-example'] = 'email@example.com';
|
||||||
break;
|
break;
|
||||||
case 'Appwrite\Network\Validator\URL':
|
case 'Utopia\Validator\URL':
|
||||||
$node['type'] = $validator->getType();
|
$node['type'] = $validator->getType();
|
||||||
$node['format'] = 'url';
|
$node['format'] = 'url';
|
||||||
$node['x-example'] = 'https://example.com';
|
$node['x-example'] = 'https://example.com';
|
||||||
|
@ -393,7 +393,7 @@ class Swagger2 extends Format
|
||||||
case 'Utopia\Validator\Length':
|
case 'Utopia\Validator\Length':
|
||||||
$node['type'] = $validator->getType();
|
$node['type'] = $validator->getType();
|
||||||
break;
|
break;
|
||||||
case 'Appwrite\Network\Validator\Host':
|
case 'Utopia\Validator\Host':
|
||||||
$node['type'] = $validator->getType();
|
$node['type'] = $validator->getType();
|
||||||
$node['format'] = 'url';
|
$node['format'] = 'url';
|
||||||
$node['x-example'] = 'https://example.com';
|
$node['x-example'] = 'https://example.com';
|
||||||
|
|
|
@ -42,7 +42,7 @@ class Locale extends Model
|
||||||
])
|
])
|
||||||
->addRule('eu', [
|
->addRule('eu', [
|
||||||
'type' => self::TYPE_BOOLEAN,
|
'type' => self::TYPE_BOOLEAN,
|
||||||
'description' => 'True if country is part of the Europian Union.',
|
'description' => 'True if country is part of the European Union.',
|
||||||
'default' => false,
|
'default' => false,
|
||||||
'example' => false,
|
'example' => false,
|
||||||
])
|
])
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit\Network\Validators;
|
|
||||||
|
|
||||||
use Appwrite\Network\Validator\Domain;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class DomainTest extends TestCase
|
|
||||||
{
|
|
||||||
protected ?Domain $domain = null;
|
|
||||||
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
$this->domain = new Domain();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function tearDown(): void
|
|
||||||
{
|
|
||||||
$this->domain = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testIsValid(): void
|
|
||||||
{
|
|
||||||
// Assertions
|
|
||||||
$this->assertEquals(true, $this->domain->isValid('example.com'));
|
|
||||||
$this->assertEquals(true, $this->domain->isValid('subdomain.example.com'));
|
|
||||||
$this->assertEquals(true, $this->domain->isValid('subdomain.example-app.com'));
|
|
||||||
$this->assertEquals(true, $this->domain->isValid('subdomain.example_app.com'));
|
|
||||||
$this->assertEquals(true, $this->domain->isValid('subdomain-new.example.com'));
|
|
||||||
$this->assertEquals(true, $this->domain->isValid('subdomain_new.example.com'));
|
|
||||||
$this->assertEquals(true, $this->domain->isValid('localhost'));
|
|
||||||
$this->assertEquals(true, $this->domain->isValid('appwrite.io'));
|
|
||||||
$this->assertEquals(true, $this->domain->isValid('appwrite.org'));
|
|
||||||
$this->assertEquals(true, $this->domain->isValid('appwrite.org'));
|
|
||||||
$this->assertEquals(false, $this->domain->isValid(false));
|
|
||||||
$this->assertEquals(false, $this->domain->isValid('.'));
|
|
||||||
$this->assertEquals(false, $this->domain->isValid('..'));
|
|
||||||
$this->assertEquals(false, $this->domain->isValid(''));
|
|
||||||
$this->assertEquals(false, $this->domain->isValid(['string', 'string']));
|
|
||||||
$this->assertEquals(false, $this->domain->isValid(1));
|
|
||||||
$this->assertEquals(false, $this->domain->isValid(1.2));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utopia PHP Framework
|
|
||||||
*
|
|
||||||
* @package Framework
|
|
||||||
* @subpackage Tests
|
|
||||||
*
|
|
||||||
* @link https://github.com/utopia-php/framework
|
|
||||||
* @author Appwrite Team <team@appwrite.io>
|
|
||||||
* @version 1.0 RC4
|
|
||||||
* @license The MIT License (MIT) <http://www.opensource.org/licenses/mit-license.php>
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Tests\Unit\Network\Validators;
|
|
||||||
|
|
||||||
use Appwrite\Network\Validator\Host;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class HostTest extends TestCase
|
|
||||||
{
|
|
||||||
protected ?Host $host = null;
|
|
||||||
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
$this->host = new Host(['appwrite.io', 'subdomain.appwrite.test', 'localhost']);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function tearDown(): void
|
|
||||||
{
|
|
||||||
$this->host = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testIsValid(): void
|
|
||||||
{
|
|
||||||
// Assertions
|
|
||||||
$this->assertEquals($this->host->isValid('https://appwrite.io/link'), true);
|
|
||||||
$this->assertEquals($this->host->isValid('https://localhost'), true);
|
|
||||||
$this->assertEquals($this->host->isValid('localhost'), false);
|
|
||||||
$this->assertEquals($this->host->isValid('http://subdomain.appwrite.test/path'), true);
|
|
||||||
$this->assertEquals($this->host->isValid('http://test.subdomain.appwrite.test/path'), false);
|
|
||||||
$this->assertEquals($this->host->getType(), 'string');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,87 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utopia PHP Framework
|
|
||||||
*
|
|
||||||
* @package Framework
|
|
||||||
* @subpackage Tests
|
|
||||||
*
|
|
||||||
* @link https://github.com/utopia-php/framework
|
|
||||||
* @author Appwrite Team <team@appwrite.io>
|
|
||||||
* @version 1.0 RC4
|
|
||||||
* @license The MIT License (MIT) <http://www.opensource.org/licenses/mit-license.php>
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Tests\Unit\Network\Validators;
|
|
||||||
|
|
||||||
use Appwrite\Network\Validator\IP;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class IPTest extends TestCase
|
|
||||||
{
|
|
||||||
protected ?IP $validator;
|
|
||||||
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
$this->validator = new IP();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function tearDown(): void
|
|
||||||
{
|
|
||||||
$this->validator = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testIsValidIP(): void
|
|
||||||
{
|
|
||||||
$this->assertEquals($this->validator->isValid('2001:0db8:85a3:08d3:1319:8a2e:0370:7334'), true);
|
|
||||||
$this->assertEquals($this->validator->isValid('109.67.204.101'), true);
|
|
||||||
$this->assertEquals($this->validator->isValid(23.5), false);
|
|
||||||
$this->assertEquals($this->validator->isValid('23.5'), false);
|
|
||||||
$this->assertEquals($this->validator->isValid(null), false);
|
|
||||||
$this->assertEquals($this->validator->isValid(true), false);
|
|
||||||
$this->assertEquals($this->validator->isValid(false), false);
|
|
||||||
$this->assertEquals($this->validator->getType(), 'string');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testIsValidIPALL(): void
|
|
||||||
{
|
|
||||||
$this->validator = new IP(IP::ALL);
|
|
||||||
|
|
||||||
// Assertions
|
|
||||||
$this->assertEquals($this->validator->isValid('2001:0db8:85a3:08d3:1319:8a2e:0370:7334'), true);
|
|
||||||
$this->assertEquals($this->validator->isValid('109.67.204.101'), true);
|
|
||||||
$this->assertEquals($this->validator->isValid(23.5), false);
|
|
||||||
$this->assertEquals($this->validator->isValid('23.5'), false);
|
|
||||||
$this->assertEquals($this->validator->isValid(null), false);
|
|
||||||
$this->assertEquals($this->validator->isValid(true), false);
|
|
||||||
$this->assertEquals($this->validator->isValid(false), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testIsValidIPV4(): void
|
|
||||||
{
|
|
||||||
$this->validator = new IP(IP::V4);
|
|
||||||
|
|
||||||
// Assertions
|
|
||||||
$this->assertEquals($this->validator->isValid('2001:0db8:85a3:08d3:1319:8a2e:0370:7334'), false);
|
|
||||||
$this->assertEquals($this->validator->isValid('109.67.204.101'), true);
|
|
||||||
$this->assertEquals($this->validator->isValid(23.5), false);
|
|
||||||
$this->assertEquals($this->validator->isValid('23.5'), false);
|
|
||||||
$this->assertEquals($this->validator->isValid(null), false);
|
|
||||||
$this->assertEquals($this->validator->isValid(true), false);
|
|
||||||
$this->assertEquals($this->validator->isValid(false), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testIsValidIPV6(): void
|
|
||||||
{
|
|
||||||
$this->validator = new IP(IP::V6);
|
|
||||||
|
|
||||||
// Assertions
|
|
||||||
$this->assertEquals($this->validator->isValid('2001:0db8:85a3:08d3:1319:8a2e:0370:7334'), true);
|
|
||||||
$this->assertEquals($this->validator->isValid('109.67.204.101'), false);
|
|
||||||
$this->assertEquals($this->validator->isValid(23.5), false);
|
|
||||||
$this->assertEquals($this->validator->isValid('23.5'), false);
|
|
||||||
$this->assertEquals($this->validator->isValid(null), false);
|
|
||||||
$this->assertEquals($this->validator->isValid(true), false);
|
|
||||||
$this->assertEquals($this->validator->isValid(false), false);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utopia PHP Framework
|
|
||||||
*
|
|
||||||
* @package Framework
|
|
||||||
* @subpackage Tests
|
|
||||||
*
|
|
||||||
* @link https://github.com/utopia-php/framework
|
|
||||||
* @author Appwrite Team <team@appwrite.io>
|
|
||||||
* @version 1.0 RC4
|
|
||||||
* @license The MIT License (MIT) <http://www.opensource.org/licenses/mit-license.php>
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Tests\Unit\Network\Validators;
|
|
||||||
|
|
||||||
use Appwrite\Network\Validator\URL;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class URLTest extends TestCase
|
|
||||||
{
|
|
||||||
protected ?URL $url;
|
|
||||||
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
$this->url = new URL();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function tearDown(): void
|
|
||||||
{
|
|
||||||
$this->url = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testIsValid(): void
|
|
||||||
{
|
|
||||||
$this->assertEquals('Value must be a valid URL', $this->url->getDescription());
|
|
||||||
$this->assertEquals(true, $this->url->isValid('http://example.com'));
|
|
||||||
$this->assertEquals(true, $this->url->isValid('https://example.com'));
|
|
||||||
$this->assertEquals(true, $this->url->isValid('htts://example.com')); // does not validate protocol
|
|
||||||
$this->assertEquals(false, $this->url->isValid('example.com')); // though, requires some kind of protocol
|
|
||||||
$this->assertEquals(false, $this->url->isValid('http:/example.com'));
|
|
||||||
$this->assertEquals(true, $this->url->isValid('http://exa-mple.com'));
|
|
||||||
$this->assertEquals(false, $this->url->isValid('htt@s://example.com'));
|
|
||||||
$this->assertEquals(true, $this->url->isValid('http://www.example.com/foo%2\u00c2\u00a9zbar'));
|
|
||||||
$this->assertEquals(true, $this->url->isValid('http://www.example.com/?q=%3Casdf%3E'));
|
|
||||||
$this->assertEquals(true, $this->url->isValid('https://example.com/foo%2\u00c2\u00ä9zbär'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testIsValidAllowedSchemes(): void
|
|
||||||
{
|
|
||||||
$this->url = new URL(['http', 'https']);
|
|
||||||
$this->assertEquals('Value must be a valid URL with following schemes (http, https)', $this->url->getDescription());
|
|
||||||
$this->assertEquals(true, $this->url->isValid('http://example.com'));
|
|
||||||
$this->assertEquals(true, $this->url->isValid('https://example.com'));
|
|
||||||
$this->assertEquals(false, $this->url->isValid('gopher://www.example.com'));
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue