1
0
Fork 0
mirror of synced 2024-06-30 04:00:34 +12:00

Merge branch 'feat-graphql-support' of https://github.com/appwrite/appwrite into graphql

This commit is contained in:
Christy Jacob 2021-03-10 19:36:43 +05:30
commit f1a7e9092c
140 changed files with 1535 additions and 885 deletions

View file

@ -2,12 +2,37 @@
- Anonymous login
# Version 0.7.1 (Not Released Yet)
# Version 0.7.1
## Features
- Better error logs on appwrite certificates worker
- Added option for Redis authentication
- Force adding a security email on setup
- SMTP is now disabled by default, no dummy SMTP is included in setup
- Added a new endpoint that returns the server and SDKs latest versions numbers #941
## Upgrades
- Upgraded redis extenstion lib to version 5.3.3
- Upgraded maxmind extenstion lib to version 1.10.0
- Upgraded utopia-php/cli lib to version 0.10.0
- Upgraded matomo/device-detector lib to version 4.1.0
- Upgraded dragonmantank/cron-expression lib to version 3.1.0
- Upgraded influxdb/influxdb-php lib to version 1.15.2
- Upgraded phpmailer/phpmailer lib to version 6.3.0
- Upgraded adhocore/jwt lib to version 1.1.2
- Upgraded domnikl/statsd to slickdeals/statsd version 3.0
## Bug Fixes
- Updated missing storage env vars
- Added option to for Redis authentication
- Force adding a security email on setup
- Better error logs on appwrite cretificates worker
- Fixed a bug, that Response format header was not added in the access-control-allow-header list.
- Fixed a bug where countryName is unknown on sessions (#933)
## Security
- Fixed an XSS vulnerability in the Appwrite console
# Version 0.7.0

View file

@ -143,7 +143,6 @@ Appwrite's current structure is a combination of both [Monolithic](https://en.wi
├── docs # Docs and tutorials
│ ├── examples
│ ├── references
│ ├── sdks
│ ├── services
│ ├── specs
│ └── tutorials
@ -157,13 +156,14 @@ Appwrite's current structure is a combination of both [Monolithic](https://en.wi
│ └── Appwrite
│ ├── Auth
│ ├── Database
│ ├── Detector
│ ├── Docker
│ ├── Event
│ ├── Extend
│ ├── Migration
│ ├── Network
│ ├── OpenSSL
│ ├── Resize
│ ├── Storage
│ ├── Specification
│ ├── Task
│ ├── Template
│ ├── URL

View file

@ -14,9 +14,9 @@ RUN composer update --ignore-platform-reqs --optimize-autoloader \
FROM php:7.4-cli-alpine as step1
ENV PHP_REDIS_VERSION=5.3.0 \
ENV PHP_REDIS_VERSION=5.3.3 \
PHP_SWOOLE_VERSION=v4.5.8 \
PHP_MAXMINDDB_VERSION=v1.8.0 \
PHP_MAXMINDDB_VERSION=v1.10.0 \
PHP_XDEBUG_VERSION=sdebug_2_9-beta
RUN \
@ -90,8 +90,11 @@ ENV _APP_SERVER=swoole \
_APP_INFLUXDB_PORT=8086 \
_APP_STATSD_HOST=telegraf \
_APP_STATSD_PORT=8125 \
_APP_SMTP_HOST=smtp \
_APP_SMTP_PORT=25 \
_APP_SMTP_HOST= \
_APP_SMTP_PORT= \
_APP_SMTP_SECURE= \
_APP_SMTP_USERNAME= \
_APP_SMTP_PASSWORD= \
_APP_FUNCTIONS_TIMEOUT=900 \
_APP_FUNCTIONS_CONTAINERS=10 \
_APP_FUNCTIONS_CPUS=1 \
@ -106,9 +109,6 @@ ENV _APP_SERVER=swoole \
# 1 Day = 86400 s
_APP_MAINTENANCE_RETENTION_ABUSE=86400 \
_APP_MAINTENANCE_INTERVAL=86400
#ENV _APP_SMTP_SECURE ''
#ENV _APP_SMTP_USERNAME ''
#ENV _APP_SMTP_PASSWORD ''
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

View file

@ -53,7 +53,7 @@ docker run -it --rm \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
--entrypoint="install" \
appwrite/appwrite:0.7.0
appwrite/appwrite:0.7.1
```
### Windows
@ -65,7 +65,7 @@ docker run -it --rm ^
--volume //var/run/docker.sock:/var/run/docker.sock ^
--volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^
--entrypoint="install" ^
appwrite/appwrite:0.7.0
appwrite/appwrite:0.7.1
```
#### PowerShell
@ -75,7 +75,7 @@ docker run -it --rm ,
--volume /var/run/docker.sock:/var/run/docker.sock ,
--volume ${pwd}/appwrite:/usr/src/code/appwrite:rw ,
--entrypoint="install" ,
appwrite/appwrite:0.7.0
appwrite/appwrite:0.7.1
```
Once the Docker installation completes, go to http://localhost to access the Appwrite console from your browser. Please note that on non-linux native hosts, the server might take a few minutes to start after installation completes.

View file

@ -32,7 +32,7 @@ return [
[
'key' => 'flutter',
'name' => 'Flutter',
'version' => '0.3.0',
'version' => '0.4.0-dev.2',
'url' => 'https://github.com/appwrite/sdk-for-flutter',
'package' => 'https://pub.dev/packages/appwrite',
'enabled' => true,
@ -165,7 +165,7 @@ return [
[
'key' => 'deno',
'name' => 'Deno',
'version' => '0.1.0',
'version' => '0.1.1',
'url' => 'https://github.com/appwrite/sdk-for-deno',
'package' => 'https://deno.land/x/appwrite',
'enabled' => true,
@ -199,7 +199,7 @@ return [
[
'key' => 'python',
'name' => 'Python',
'version' => '0.1.0',
'version' => '0.1.1',
'url' => 'https://github.com/appwrite/sdk-for-python',
'package' => 'https://pypi.org/project/appwrite/',
'enabled' => true,
@ -216,7 +216,7 @@ return [
[
'key' => 'ruby',
'name' => 'Ruby',
'version' => '2.0.0',
'version' => '2.0.2',
'url' => 'https://github.com/appwrite/sdk-for-ruby',
'package' => 'https://rubygems.org/gems/appwrite',
'enabled' => true,
@ -284,12 +284,12 @@ return [
[
'key' => 'dart',
'name' => 'Dart',
'version' => '0.2.0',
'version' => '0.4.0',
'url' => 'https://github.com/appwrite/sdk-for-dart',
'package' => 'https://pub.dev/packages/dart_appwrite',
'enabled' => true,
'beta' => true,
'dev' => true,
'dev' => false,
'hidden' => false,
'family' => APP_PLATFORM_SERVER,
'prism' => 'dart',
@ -301,7 +301,7 @@ return [
[
'key' => 'cli',
'name' => 'Command Line',
'version' => '0.5.0',
'version' => '0.6.0',
'url' => 'https://github.com/appwrite/sdk-for-cli',
'package' => 'https://github.com/appwrite/sdk-for-cli',
'enabled' => true,

View file

@ -105,9 +105,9 @@ return [
],
[
'name' => '_APP_SYSTEM_SECURITY_EMAIL_ADDRESS',
'description' => 'This is the email address used to issue SSL certificates for custom domains or the user agent in webhooks. The default value is \'security@localhost.test\'.',
'description' => 'This is the email address used to issue SSL certificates for custom domains or the user agent in your webhooks payload.',
'introduction' => '0.7.0',
'default' => 'security@localhost.test',
'default' => 'certs@appwrite.io',
'required' => false,
'question' => '',
],
@ -141,6 +141,22 @@ return [
'required' => false,
'question' => '',
],
[
'name' => '_APP_REDIS_USER',
'description' => 'Redis server user.',
'introduction' => '0.7',
'default' => '',
'required' => false,
'question' => '',
],
[
'name' => '_APP_REDIS_PASS',
'description' => 'Redis server password.',
'introduction' => '0.7',
'default' => '',
'required' => false,
'question' => '',
],
],
],
[
@ -239,17 +255,17 @@ return [
'variables' => [
[
'name' => '_APP_SMTP_HOST',
'description' => 'SMTP server host name address. Default value is: \'smtp\'. Pass an empty string to disable all mail sending from the server.',
'description' => 'SMTP server host name address. Use an empty string to disable all mail sending from the server. The default value for this variable is an empty string',
'introduction' => '',
'default' => 'smtp',
'default' => '',
'required' => false,
'question' => '',
],
[
'name' => '_APP_SMTP_PORT',
'description' => 'SMTP server TCP port. Default value is: \'25\'.',
'description' => 'SMTP server TCP port. Empty by default.',
'introduction' => '',
'default' => '25',
'default' => '',
'required' => false,
'question' => '',
],

View file

@ -236,9 +236,11 @@ App::post('/v1/account/sessions')
->setStatusCode(Response::STATUS_CODE_CREATED)
;
$countries = $locale->getText('countries');
$session
->setAttribute('current', true)
->setAttribute('countryName', (isset($countries[$session->getAttribute('countryCode')])) ? $countries[$session->getAttribute('countryCode')] : $locale->getText('locale.country.unknown'))
->setAttribute('countryName', (isset($countries[strtoupper($session->getAttribute('countryCode'))])) ? $countries[strtoupper($session->getAttribute('countryCode'))] : $locale->getText('locale.country.unknown'))
;
$response->dynamic($session, Response::MODEL_SESSION);
@ -253,8 +255,8 @@ App::get('/v1/account/sessions/oauth2/:provider')
->label('sdk.namespace', 'account')
->label('sdk.method', 'createOAuth2Session')
->label('sdk.description', '/docs/references/account/create-session-oauth2.md')
->label('sdk.response.code', 301)
->label('sdk.response.type', 'text/html')
->label('sdk.response.code', Response::STATUS_CODE_MOVED_PERMANENTLY)
->label('sdk.response.type', Response::CONTENT_TYPE_HTML)
->label('sdk.methodType', 'webAuth')
->label('abuse-limit', 50)
->label('abuse-key', 'ip:{ip}')
@ -679,8 +681,8 @@ App::get('/v1/account/sessions')
continue;
}
$token->setAttribute('countryName', (isset($countries[$token->getAttribute('contryCode')]))
? $countries[$token->getAttribute('contryCode')]
$token->setAttribute('countryName', (isset($countries[strtoupper($token->getAttribute('countryCode'))]))
? $countries[strtoupper($token->getAttribute('countryCode'))]
: $locale->getText('locale.country.unknown'));
$token->setAttribute('current', ($current == $token->getId()) ? true : false);

View file

@ -1,28 +1,28 @@
<?php
use Utopia\App;
use Utopia\Exception;
use Utopia\Validator\Boolean;
use Utopia\Validator\Text;
use Utopia\Validator\WhiteList;
use Utopia\Validator\Range;
use Utopia\Validator\URL;
use Utopia\Cache\Cache;
use Utopia\Cache\Adapter\Filesystem;
use Appwrite\Resize\Resize;
use Appwrite\URL\URL as URLParse;
use Appwrite\Utopia\Response;
use Utopia\Config\Config;
use Utopia\Validator\HexColor;
use chillerlan\QRCode\QRCode;
use chillerlan\QRCode\QROptions;
use Utopia\App;
use Utopia\Cache\Adapter\Filesystem;
use Utopia\Cache\Cache;
use Utopia\Config\Config;
use Utopia\Exception;
use Utopia\Image\Image;
use Utopia\Validator\Boolean;
use Utopia\Validator\HexColor;
use Utopia\Validator\Range;
use Utopia\Validator\Text;
use Utopia\Validator\URL;
use Utopia\Validator\WhiteList;
$avatarCallback = function ($type, $code, $width, $height, $quality, $response) {
/** @var Appwrite\Utopia\Response $response */
$code = \strtolower($code);
$type = \strtolower($type);
$set = Config::getParam('avatar-'.$type, []);
$set = Config::getParam('avatar-' . $type, []);
if (empty($set)) {
throw new Exception('Avatar set not found', 404);
@ -37,17 +37,17 @@ $avatarCallback = function ($type, $code, $width, $height, $quality, $response)
}
$output = 'png';
$date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT'; // 45 days cache
$key = \md5('/v1/avatars/:type/:code-'.$code.$width.$height.$quality.$output);
$date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT'; // 45 days cache
$key = \md5('/v1/avatars/:type/:code-' . $code . $width . $height . $quality . $output);
$path = $set[$code];
$type = 'png';
if (!\is_readable($path)) {
throw new Exception('File not readable in '.$path, 500);
throw new Exception('File not readable in ' . $path, 500);
}
$cache = new Cache(new Filesystem(APP_STORAGE_CACHE.'/app-0')); // Limit file number or size
$data = $cache->load($key, 60 * 60 * 24 * 30 * 3 /* 3 months */);
$cache = new Cache(new Filesystem(APP_STORAGE_CACHE . '/app-0')); // Limit file number or size
$data = $cache->load($key, 60 * 60 * 24 * 30 * 3/* 3 months */);
if ($data) {
//$output = (empty($output)) ? $type : $output;
@ -60,24 +60,23 @@ $avatarCallback = function ($type, $code, $width, $height, $quality, $response)
;
}
$resize = new Resize(\file_get_contents($path));
$image = new Image(\file_get_contents($path));
$resize->crop((int) $width, (int) $height);
$image->crop((int) $width, (int) $height);
$output = (empty($output)) ? $type : $output;
$data = $resize->output($output, $quality);
$data = $image->output($output, $quality);
$cache->save($key, $data);
$response
->setContentType('image/png')
->addHeader('Expires', $date)
->addHeader('X-Appwrite-Cache', 'miss')
->send($data, null);
;
unset($resize);
unset($image);
};
App::get('/v1/avatars/credit-cards/:code')
@ -91,7 +90,7 @@ App::get('/v1/avatars/credit-cards/:code')
->label('sdk.description', '/docs/references/avatars/get-credit-card.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG)
->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-credit-cards'))), 'Credit Card Code. Possible values: '.\implode(', ', \array_keys(Config::getParam('avatar-credit-cards'))).'.')
->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-credit-cards'))), 'Credit Card Code. Possible values: ' . \implode(', ', \array_keys(Config::getParam('avatar-credit-cards'))) . '.')
->param('width', 100, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('height', 100, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('quality', 100, new Range(0, 100), 'Image quality. Pass an integer between 0 to 100. Defaults to 100.', true)
@ -160,11 +159,11 @@ App::get('/v1/avatars/image')
$quality = 80;
$output = 'png';
$date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT'; // 45 days cache
$key = \md5('/v2/avatars/images-'.$url.'-'.$width.'/'.$height.'/'.$quality);
$date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT'; // 45 days cache
$key = \md5('/v2/avatars/images-' . $url . '-' . $width . '/' . $height . '/' . $quality);
$type = 'png';
$cache = new Cache(new Filesystem(APP_STORAGE_CACHE.'/app-0')); // Limit file number or size
$data = $cache->load($key, 60 * 60 * 24 * 7 /* 1 week */);
$cache = new Cache(new Filesystem(APP_STORAGE_CACHE . '/app-0')); // Limit file number or size
$data = $cache->load($key, 60 * 60 * 24 * 7/* 1 week */);
if ($data) {
return $response
@ -186,17 +185,17 @@ App::get('/v1/avatars/image')
}
try {
$resize = new Resize($fetch);
} catch (\Exception $exception) {
$image = new Image($fetch);
} catch (\Exception$exception) {
throw new Exception('Unable to parse image', 500);
}
$resize->crop((int) $width, (int) $height);
$image->crop((int) $width, (int) $height);
$output = (empty($output)) ? $type : $output;
$data = $resize->output($output, $quality);
$data = $image->output($output, $quality);
$cache->save($key, $data);
$response
@ -206,7 +205,7 @@ App::get('/v1/avatars/image')
->send($data);
;
unset($resize);
unset($image);
});
App::get('/v1/avatars/favicon')
@ -229,11 +228,11 @@ App::get('/v1/avatars/favicon')
$height = 56;
$quality = 80;
$output = 'png';
$date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT'; // 45 days cache
$key = \md5('/v2/avatars/favicon-'.$url);
$date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT'; // 45 days cache
$key = \md5('/v2/avatars/favicon-' . $url);
$type = 'png';
$cache = new Cache(new Filesystem(APP_STORAGE_CACHE.'/app-0')); // Limit file number or size
$data = $cache->load($key, 60 * 60 * 24 * 30 * 3 /* 3 months */);
$cache = new Cache(new Filesystem(APP_STORAGE_CACHE . '/app-0')); // Limit file number or size
$data = $cache->load($key, 60 * 60 * 24 * 30 * 3/* 3 months */);
if ($data) {
return $response
@ -316,7 +315,7 @@ App::get('/v1/avatars/favicon')
if (empty($outputHref) || empty($outputExt)) {
$default = \parse_url($url);
$outputHref = $default['scheme'].'://'.$default['host'].'/favicon.ico';
$outputHref = $default['scheme'] . '://' . $default['host'] . '/favicon.ico';
$outputExt = 'ico';
}
@ -343,13 +342,13 @@ App::get('/v1/avatars/favicon')
throw new Exception('Icon not found', 404);
}
$resize = new Resize($fetch);
$image = new Image($fetch);
$resize->crop((int) $width, (int) $height);
$image->crop((int) $width, (int) $height);
$output = (empty($output)) ? $type : $output;
$data = $resize->output($output, $quality);
$data = $image->output($output, $quality);
$cache->save($key, $data);
@ -359,7 +358,7 @@ App::get('/v1/avatars/favicon')
->addHeader('X-Appwrite-Cache', 'miss')
->send($data);
unset($resize);
unset($image);
});
App::get('/v1/avatars/qr')
@ -394,14 +393,14 @@ App::get('/v1/avatars/qr')
$response->addHeader('Content-Disposition', 'attachment; filename="qr.png"');
}
$resize = new Resize($qrcode->render($text));
$image = new Image($qrcode->render($text));
$resize->crop((int) $size, (int) $size);
$image->crop((int) $size, (int) $size);
$response
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache
->setContentType('image/png')
->send($resize->output('png', 9))
->send($image->output('png', 9))
;
});
@ -437,10 +436,10 @@ App::get('/v1/avatars/initials')
['color' => '#610038', 'background' => '#f5d1e6'], // PINK
['color' => '#386100', 'background' => '#dcf1bd'], // LIME
['color' => '#615800', 'background' => '#f1ecba'], // YELLOW
['color' => '#610008', 'background' => '#f6d2d5'] // RED
['color' => '#610008', 'background' => '#f6d2d5'], // RED
];
$rand = \rand(0, \count($themes)-1);
$rand = \rand(0, \count($themes) - 1);
$name = (!empty($name)) ? $name : $user->getAttribute('name', $user->getAttribute('email', ''));
$words = \explode(' ', \strtoupper($name));
@ -457,23 +456,23 @@ App::get('/v1/avatars/initials')
}
$length = \count($words);
$rand = \substr($code,-1);
$background = (!empty($background)) ? '#'.$background : $themes[$rand]['background'];
$color = (!empty($color)) ? '#'.$color : $themes[$rand]['color'];
$rand = \substr($code, -1);
$background = (!empty($background)) ? '#' . $background : $themes[$rand]['background'];
$color = (!empty($color)) ? '#' . $color : $themes[$rand]['color'];
$image = new \Imagick();
$draw = new \ImagickDraw();
$fontSize = \min($width, $height) / 2;
$draw->setFont(__DIR__."/../../../public/fonts/poppins-v9-latin-500.ttf");
$image->setFont(__DIR__."/../../../public/fonts/poppins-v9-latin-500.ttf");
$draw->setFont(__DIR__ . "/../../../public/fonts/poppins-v9-latin-500.ttf");
$image->setFont(__DIR__ . "/../../../public/fonts/poppins-v9-latin-500.ttf");
$draw->setFillColor(new \ImagickPixel($color));
$draw->setFontSize($fontSize);
$draw->setTextAlignment(\Imagick::ALIGN_CENTER);
$draw->annotation($width / 1.97, ($height / 2) + ($fontSize / 3), $initials);
$image->newImage($width, $height, $background);
$image->setImageFormat("png");
$image->drawImage($draw);
@ -481,7 +480,7 @@ App::get('/v1/avatars/initials')
//$image->setImageCompressionQuality(9 - round(($quality / 100) * 9));
$response
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache
->setContentType('image/png')
->send($image->getImageBlob())
;

View file

@ -294,7 +294,7 @@ App::put('/v1/functions/:functionId')
}
$original = $function->getAttribute('schedule', '');
$cron = (!empty($function->getAttribute('tag', null)) && !empty($schedule)) ? CronExpression::factory($schedule) : null;
$cron = (!empty($function->getAttribute('tag', null)) && !empty($schedule)) ? new CronExpression($schedule) : null;
$next = (!empty($function->getAttribute('tag', null)) && !empty($schedule)) ? $cron->getNextRunDate()->format('U') : null;
$function = $projectDB->updateDocument(array_merge($function->getArrayCopy(), [
@ -359,7 +359,7 @@ App::patch('/v1/functions/:functionId/tag')
}
$schedule = $function->getAttribute('schedule', '');
$cron = (empty($function->getAttribute('tag')) && !empty($schedule)) ? CronExpression::factory($schedule) : null;
$cron = (empty($function->getAttribute('tag')) && !empty($schedule)) ? new CronExpression($schedule) : null;
$next = (empty($function->getAttribute('tag')) && !empty($schedule)) ? $cron->getNextRunDate()->format('U') : null;
$function = $projectDB->updateDocument(array_merge($function->getArrayCopy(), [

View file

@ -943,7 +943,7 @@ App::post('/v1/projects/:projectId/tasks')
throw new Exception('Project not found', 404);
}
$cron = CronExpression::factory($schedule);
$cron = new CronExpression($schedule);
$next = ($status == 'play') ? $cron->getNextRunDate()->format('U') : null;
$security = ($security === '1' || $security === 'true' || $security === 1 || $security === true);
@ -1093,7 +1093,7 @@ App::put('/v1/projects/:projectId/tasks/:taskId')
throw new Exception('Task not found', 404);
}
$cron = CronExpression::factory($schedule);
$cron = new CronExpression($schedule);
$next = ($status == 'play') ? $cron->getNextRunDate()->format('U') : null;
$security = ($security === '1' || $security === 'true' || $security === 1 || $security === true);

View file

@ -18,7 +18,7 @@ use Utopia\Storage\Validator\File;
use Utopia\Storage\Validator\FileSize;
use Utopia\Storage\Validator\Upload;
use Utopia\Storage\Compression\Algorithms\GZIP;
use Appwrite\Resize\Resize;
use Utopia\Image\Image;
use Appwrite\OpenSSL\OpenSSL;
use Appwrite\Utopia\Response;
use Utopia\Config\Config;
@ -332,17 +332,17 @@ App::get('/v1/storage/files/:fileId/preview')
$source = $compressor->decompress($source);
}
$resize = new Resize($source);
$image = new Image($source);
$resize->crop((int) $width, (int) $height);
$image->crop((int) $width, (int) $height);
if (!empty($background)) {
$resize->setBackground('#'.$background);
$image->setBackground('#'.$background);
}
$output = (empty($output)) ? $type : $output;
$data = $resize->output($output, $quality);
$data = $image->output($output, $quality);
$cache->save($key, $data);
@ -353,7 +353,7 @@ App::get('/v1/storage/files/:fileId/preview')
->send($data)
;
unset($resize);
unset($image);
});
App::get('/v1/storage/files/:fileId/download')

View file

@ -207,8 +207,8 @@ App::get('/v1/users/:userId/sessions')
continue;
}
$token->setAttribute('countryName', (isset($countries[$token->getAttribute('contryCode')]))
? $countries[$token->getAttribute('contryCode')]
$token->setAttribute('countryName', (isset($countries[strtoupper($token->getAttribute('contryCode'))]))
? $countries[strtoupper($token->getAttribute('contryCode'))]
: $locale->getText('locale.country.unknown'));
$token->setAttribute('current', false);

View file

@ -120,7 +120,7 @@ App::init(function ($utopia, $request, $response, $console, $project, $user, $lo
->addHeader('Server', 'Appwrite')
->addHeader('X-Content-Type-Options', 'nosniff')
->addHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE')
->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-SDK-Version, Cache-Control, Expires, Pragma')
->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-SDK-Version, Cache-Control, Expires, Pragma')
->addHeader('Access-Control-Expose-Headers', 'X-Fallback-Cookies')
->addHeader('Access-Control-Allow-Origin', $refDomain)
->addHeader('Access-Control-Allow-Credentials', 'true')
@ -246,7 +246,7 @@ App::options(function ($request, $response) {
$response
->addHeader('Server', 'Appwrite')
->addHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE')
->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-SDK-Version, Cache-Control, Expires, Pragma, X-Fallback-Cookies')
->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-SDK-Version, Cache-Control, Expires, Pragma, X-Fallback-Cookies')
->addHeader('Access-Control-Expose-Headers', 'X-Fallback-Cookies')
->addHeader('Access-Control-Allow-Origin', $origin)
->addHeader('Access-Control-Allow-Credentials', 'true')

View file

@ -2,8 +2,9 @@
global $utopia, $request, $response;
use Appwrite\Database\Document;
use Appwrite\Utopia\Response;
use Utopia\App;
use Utopia\Response;
use Utopia\Validator\Numeric;
use Utopia\Validator\Text;
use Utopia\Validator\ArrayList;
@ -11,13 +12,16 @@ use Utopia\Validator\Host;
use Utopia\Storage\Validator\File;
App::get('/v1/mock/tests/foo')
->desc('Mock a get request for SDK tests')
->desc('Get Foo')
->groups(['mock'])
->label('scope', 'public')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'foo')
->label('sdk.method', 'get')
->label('sdk.description', 'Mock a get request for SDK tests')
->label('sdk.description', 'Mock a get request.')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_MOCK)
->label('sdk.mock', true)
->param('x', '', new Text(100), 'Sample string param')
->param('y', '', new Numeric(), 'Sample numeric param')
@ -26,13 +30,16 @@ App::get('/v1/mock/tests/foo')
});
App::post('/v1/mock/tests/foo')
->desc('Mock a post request for SDK tests')
->desc('Post Foo')
->groups(['mock'])
->label('scope', 'public')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'foo')
->label('sdk.method', 'post')
->label('sdk.description', 'Mock a post request for SDK tests')
->label('sdk.description', 'Mock a post request.')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_MOCK)
->label('sdk.mock', true)
->param('x', '', new Text(100), 'Sample string param')
->param('y', '', new Numeric(), 'Sample numeric param')
@ -41,13 +48,16 @@ App::post('/v1/mock/tests/foo')
});
App::patch('/v1/mock/tests/foo')
->desc('Mock a patch request for SDK tests')
->desc('Patch Foo')
->groups(['mock'])
->label('scope', 'public')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'foo')
->label('sdk.method', 'patch')
->label('sdk.description', 'Mock a get request for SDK tests')
->label('sdk.description', 'Mock a patch request.')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_MOCK)
->label('sdk.mock', true)
->param('x', '', new Text(100), 'Sample string param')
->param('y', '', new Numeric(), 'Sample numeric param')
@ -56,13 +66,16 @@ App::patch('/v1/mock/tests/foo')
});
App::put('/v1/mock/tests/foo')
->desc('Mock a put request for SDK tests')
->desc('Put Foo')
->groups(['mock'])
->label('scope', 'public')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'foo')
->label('sdk.method', 'put')
->label('sdk.description', 'Mock a put request for SDK tests')
->label('sdk.description', 'Mock a put request.')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_MOCK)
->label('sdk.mock', true)
->param('x', '', new Text(100), 'Sample string param')
->param('y', '', new Numeric(), 'Sample numeric param')
@ -71,13 +84,16 @@ App::put('/v1/mock/tests/foo')
});
App::delete('/v1/mock/tests/foo')
->desc('Mock a delete request for SDK tests')
->desc('Delete Foo')
->groups(['mock'])
->label('scope', 'public')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'foo')
->label('sdk.method', 'delete')
->label('sdk.description', 'Mock a delete request for SDK tests')
->label('sdk.description', 'Mock a delete request.')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_MOCK)
->label('sdk.mock', true)
->param('x', '', new Text(100), 'Sample string param')
->param('y', '', new Numeric(), 'Sample numeric param')
@ -86,13 +102,16 @@ App::delete('/v1/mock/tests/foo')
});
App::get('/v1/mock/tests/bar')
->desc('Mock a get request for SDK tests')
->desc('Get Bar')
->groups(['mock'])
->label('scope', 'public')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'bar')
->label('sdk.method', 'get')
->label('sdk.description', 'Mock a get request for SDK tests')
->label('sdk.description', 'Mock a get request.')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_MOCK)
->label('sdk.mock', true)
->param('x', '', new Text(100), 'Sample string param')
->param('y', '', new Numeric(), 'Sample numeric param')
@ -101,13 +120,16 @@ App::get('/v1/mock/tests/bar')
});
App::post('/v1/mock/tests/bar')
->desc('Mock a post request for SDK tests')
->desc('Post Bar')
->groups(['mock'])
->label('scope', 'public')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'bar')
->label('sdk.method', 'post')
->label('sdk.description', 'Mock a post request for SDK tests')
->label('sdk.description', 'Mock a post request.')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_MOCK)
->label('sdk.mock', true)
->param('x', '', new Text(100), 'Sample string param')
->param('y', '', new Numeric(), 'Sample numeric param')
@ -116,13 +138,16 @@ App::post('/v1/mock/tests/bar')
});
App::patch('/v1/mock/tests/bar')
->desc('Mock a patch request for SDK tests')
->desc('Patch Bar')
->groups(['mock'])
->label('scope', 'public')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'bar')
->label('sdk.method', 'patch')
->label('sdk.description', 'Mock a get request for SDK tests')
->label('sdk.description', 'Mock a patch request.')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_MOCK)
->label('sdk.mock', true)
->param('x', '', new Text(100), 'Sample string param')
->param('y', '', new Numeric(), 'Sample numeric param')
@ -131,13 +156,16 @@ App::patch('/v1/mock/tests/bar')
});
App::put('/v1/mock/tests/bar')
->desc('Mock a put request for SDK tests')
->desc('Put Bar')
->groups(['mock'])
->label('scope', 'public')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'bar')
->label('sdk.method', 'put')
->label('sdk.description', 'Mock a put request for SDK tests')
->label('sdk.description', 'Mock a put request.')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_MOCK)
->label('sdk.mock', true)
->param('x', '', new Text(100), 'Sample string param')
->param('y', '', new Numeric(), 'Sample numeric param')
@ -146,13 +174,16 @@ App::put('/v1/mock/tests/bar')
});
App::delete('/v1/mock/tests/bar')
->desc('Mock a delete request for SDK tests')
->desc('Delete Bar')
->groups(['mock'])
->label('scope', 'public')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'bar')
->label('sdk.method', 'delete')
->label('sdk.description', 'Mock a delete request for SDK tests')
->label('sdk.description', 'Mock a delete request.')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_MOCK)
->label('sdk.mock', true)
->param('x', '', new Text(100), 'Sample string param')
->param('y', '', new Numeric(), 'Sample numeric param')
@ -161,14 +192,17 @@ App::delete('/v1/mock/tests/bar')
});
App::post('/v1/mock/tests/general/upload')
->desc('Mock a post request for SDK tests')
->desc('Upload File')
->groups(['mock'])
->label('scope', 'public')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'general')
->label('sdk.method', 'upload')
->label('sdk.description', 'Mock a delete request for SDK tests')
->label('sdk.description', 'Mock a file upload request.')
->label('sdk.request.type', 'multipart/form-data')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_MOCK)
->label('sdk.mock', true)
->param('x', '', new Text(100), 'Sample string param')
->param('y', '', new Numeric(), 'Sample numeric param')
@ -203,13 +237,15 @@ App::post('/v1/mock/tests/general/upload')
});
App::get('/v1/mock/tests/general/redirect')
->desc('Mock a post request for SDK tests')
->desc('Redirect')
->groups(['mock'])
->label('scope', 'public')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'general')
->label('sdk.method', 'redirect')
->label('sdk.description', 'Mock a redirect request for SDK tests')
->label('sdk.description', 'Mock a redirect request.')
->label('sdk.response.code', Response::STATUS_CODE_MOVED_PERMANENTLY)
->label('sdk.response.type', Response::CONTENT_TYPE_HTML)
->label('sdk.mock', true)
->inject('response')
->action(function ($response) {
@ -219,25 +255,31 @@ App::get('/v1/mock/tests/general/redirect')
});
App::get('/v1/mock/tests/general/redirect/done')
->desc('Mock a post request for SDK tests')
->desc('Redirected')
->groups(['mock'])
->label('scope', 'public')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'general')
->label('sdk.method', 'redirected')
->label('sdk.description', 'Mock a redirected request for SDK tests')
->label('sdk.description', 'Mock a redirected request.')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_MOCK)
->label('sdk.mock', true)
->action(function () {
});
App::get('/v1/mock/tests/general/set-cookie')
->desc('Mock a cookie request for SDK tests')
->desc('Set Cookie')
->groups(['mock'])
->label('scope', 'public')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'general')
->label('sdk.method', 'setCookie')
->label('sdk.description', 'Mock a set cookie request for SDK tests')
->label('sdk.description', 'Mock a set cookie request.')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_MOCK)
->label('sdk.mock', true)
->inject('response')
->action(function ($response) {
@ -247,13 +289,16 @@ App::get('/v1/mock/tests/general/set-cookie')
});
App::get('/v1/mock/tests/general/get-cookie')
->desc('Mock a cookie request for SDK tests')
->desc('Get Cookie')
->groups(['mock'])
->label('scope', 'public')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'general')
->label('sdk.method', 'getCookie')
->label('sdk.description', 'Mock a get cookie request for SDK tests')
->label('sdk.description', 'Mock a cookie response.')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_MOCK)
->label('sdk.mock', true)
->inject('request')
->action(function ($request) {
@ -265,13 +310,15 @@ App::get('/v1/mock/tests/general/get-cookie')
});
App::get('/v1/mock/tests/general/empty')
->desc('Mock a post request for SDK tests')
->desc('Empty Response')
->groups(['mock'])
->label('scope', 'public')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'general')
->label('sdk.method', 'empty')
->label('sdk.description', 'Mock a redirected request for SDK tests')
->label('sdk.description', 'Mock a an empty response.')
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.model', Response::MODEL_NONE)
->label('sdk.mock', true)
->inject('response')
->action(function ($response) {
@ -280,8 +327,40 @@ App::get('/v1/mock/tests/general/empty')
$response->noContent();
});
App::get('/v1/mock/tests/general/400-error')
->desc('400 Error')
->groups(['mock'])
->label('scope', 'public')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'general')
->label('sdk.method', 'error400')
->label('sdk.description', 'Mock a an 400 failed request.')
->label('sdk.response.code', Response::STATUS_CODE_BAD_REQUEST)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ERROR)
->label('sdk.mock', true)
->action(function () {
throw new Exception('Mock 400 error', 400);
});
App::get('/v1/mock/tests/general/500-error')
->desc('500 Error')
->groups(['mock'])
->label('scope', 'public')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'general')
->label('sdk.method', 'error500')
->label('sdk.description', 'Mock a an 500 failed request.')
->label('sdk.response.code', Response::STATUS_CODE_INTERNAL_SERVER_ERROR)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ERROR)
->label('sdk.mock', true)
->action(function () {
throw new Exception('Mock 500 error', 500);
});
App::get('/v1/mock/tests/general/oauth2')
->desc('Mock an OAuth2 login route')
->desc('OAuth Login')
->groups(['mock'])
->label('scope', 'public')
->label('docs', false)
@ -298,7 +377,7 @@ App::get('/v1/mock/tests/general/oauth2')
});
App::get('/v1/mock/tests/general/oauth2/token')
->desc('Mock an OAuth2 login route')
->desc('OAuth2 Token')
->groups(['mock'])
->label('scope', 'public')
->label('docs', false)
@ -327,7 +406,7 @@ App::get('/v1/mock/tests/general/oauth2/token')
});
App::get('/v1/mock/tests/general/oauth2/user')
->desc('Mock an OAuth2 user route')
->desc('OAuth2 User')
->groups(['mock'])
->label('scope', 'public')
->label('docs', false)
@ -348,8 +427,9 @@ App::get('/v1/mock/tests/general/oauth2/user')
});
App::get('/v1/mock/tests/general/oauth2/success')
->label('scope', 'public')
->desc('OAuth2 Success')
->groups(['mock'])
->label('scope', 'public')
->label('docs', false)
->inject('response')
->action(function ($response) {
@ -361,6 +441,7 @@ App::get('/v1/mock/tests/general/oauth2/success')
});
App::get('/v1/mock/tests/general/oauth2/failure')
->desc('OAuth2 Failure')
->groups(['mock'])
->label('scope', 'public')
->label('docs', false)
@ -397,5 +478,5 @@ App::shutdown(function($utopia, $response, $request) {
throw new Exception('Failed to save resutls', 500);
}
$response->json(['result' => $route->getMethod() . ':' . $route->getURL() . ':passed']);
$response->dynamic(new Document(['result' => $route->getMethod() . ':' . $route->getURL() . ':passed']), Response::MODEL_MOCK);
}, ['utopia', 'response', 'request'], 'mock');

View file

@ -11,13 +11,18 @@ App::init(function ($utopia, $request, $response, $layout) {
/* AJAX check */
if (!empty($request->getQuery('version', ''))) {
$layout->setPath(__DIR__.'/../../views/layouts/empty.phtml');
$layout->setPath(__DIR__ . '/../../views/layouts/empty.phtml');
}
$port = $request->getPort();
$protocol = $request->getProtocol();
$domain = $request->getHostname();
$layout
->setParam('title', APP_NAME)
->setParam('protocol', $request->getProtocol())
->setParam('domain', $request->getHostname())
->setParam('protocol', $protocol)
->setParam('domain', $domain)
->setParam('endpoint', $protocol . '://' . $domain . ($port != 80 && $port != 443 ? ':' . $port : ''))
->setParam('home', App::getEnv('_APP_HOME'))
->setParam('setup', App::getEnv('_APP_SETUP'))
->setParam('class', 'unknown')
@ -34,10 +39,10 @@ App::init(function ($utopia, $request, $response, $layout) {
$time = (60 * 60 * 24 * 45); // 45 days cache
$response
->addHeader('Cache-Control', 'public, max-age='.$time)
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $time).' GMT') // 45 days cache
->addHeader('Cache-Control', 'public, max-age=' . $time)
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $time) . ' GMT') // 45 days cache
->addHeader('X-Frame-Options', 'SAMEORIGIN') // Avoid console and homepage from showing in iframes
->addHeader('X-XSS-Protection', '1; mode=block; report=/v1/xss?url='.\urlencode($request->getURI()))
->addHeader('X-XSS-Protection', '1; mode=block; report=/v1/xss?url=' . \urlencode($request->getURI()))
->addHeader('X-UA-Compatible', 'IE=Edge') // Deny IE browsers from going into quirks mode
;

View file

@ -144,6 +144,7 @@ App::get('/console/settings')
$page
->setParam('customDomainsEnabled', ($target->isKnown() && !$target->isTest()))
->setParam('customDomainsTarget', $target->get())
->setParam('smtpEnabled', (!empty(App::getEnv('_APP_SMTP_HOST'))))
;
$layout

View file

@ -375,4 +375,40 @@ App::get('/specs/:format')
$response
->json($specs->parse());
});
App::get('/versions')
->desc('Get Version')
->groups(['web', 'home'])
->label('scope', 'public')
->inject('response')
->action(function ($response) {
/** @var Appwrite\Utopia\Response $response */
$platforms = Config::getParam('platforms');
$versions = [
'server' => APP_VERSION_STABLE,
];
foreach($platforms as $platform) {
$languages = $platform['languages'] ?? [];
foreach ($languages as $key => $language) {
if(isset($language['dev']) && $language['dev']) {
continue;
}
if(isset($language['enabled']) && !$language['enabled']) {
continue;
}
$platformKey = $platform['key'] ?? '';
$languageKey = $language['key'] ?? '';
$version = $language['version'] ?? '';
$versions[$platformKey . '-' . $languageKey] = $version;
}
}
$response->json($versions);
});

View file

@ -35,13 +35,13 @@ use PDO as PDONative;
const APP_NAME = 'Appwrite';
const APP_DOMAIN = 'appwrite.io';
const APP_EMAIL_TEAM = 'team@localhost.test'; // Default email address
const APP_EMAIL_SECURITY = 'security@localhost.test'; // Default security email address
const APP_EMAIL_SECURITY = ''; // Default security email address
const APP_USERAGENT = APP_NAME.'-Server v%s. Please report abuse at %s';
const APP_MODE_DEFAULT = 'default';
const APP_MODE_ADMIN = 'admin';
const APP_PAGING_LIMIT = 12;
const APP_CACHE_BUSTER = 144;
const APP_VERSION_STABLE = '0.7.0';
const APP_VERSION_STABLE = '0.7.1';
const APP_STORAGE_UPLOADS = '/storage/uploads';
const APP_STORAGE_FUNCTIONS = '/storage/functions';
const APP_STORAGE_CACHE = '/storage/cache';
@ -92,9 +92,13 @@ Config::load('storage-mimes', __DIR__.'/config/storage/mimes.php');
Config::load('storage-inputs', __DIR__.'/config/storage/inputs.php');
Config::load('storage-outputs', __DIR__.'/config/storage/outputs.php');
Resque::setBackend(App::getEnv('_APP_REDIS_HOST', '')
.':'.App::getEnv('_APP_REDIS_PORT', ''));
$user = App::getEnv('_APP_REDIS_USER','');
$pass = App::getEnv('_APP_REDIS_PASS','');
if(!empty($user) || !empty($pass)) {
Resque::setBackend('redis://'.$user.':'.$pass.'@'.App::getEnv('_APP_REDIS_HOST', '').':'.App::getEnv('_APP_REDIS_PORT', ''));
} else {
Resque::setBackend(App::getEnv('_APP_REDIS_HOST', '').':'.App::getEnv('_APP_REDIS_PORT', ''));
}
/**
* DB Filters
*/
@ -177,6 +181,18 @@ $register->set('statsd', function () { // Register DB connection
$register->set('cache', function () { // Register cache connection
$redis = new Redis();
$redis->pconnect(App::getEnv('_APP_REDIS_HOST', ''), App::getEnv('_APP_REDIS_PORT', ''));
$user = App::getEnv('_APP_REDIS_USER','');
$pass = App::getEnv('_APP_REDIS_PASS','');
$auth = [];
if(!empty($user)) {
$auth["user"] = $user;
}
if(!empty($pass)) {
$auth["pass"] = $pass;
}
if(!empty($auth)) {
$redis->auth($auth);
}
$redis->setOption(Redis::OPT_READ_TIMEOUT, -1);
return $redis;

View file

@ -28,10 +28,9 @@ foreach ([
realpath(__DIR__ . '/../vendor/felixfbecker'),
realpath(__DIR__ . '/../vendor/twig/twig'),
realpath(__DIR__ . '/../vendor/guzzlehttp/guzzle'),
realpath(__DIR__ . '/../vendor/domnikl'),
realpath(__DIR__ . '/../vendor/domnikl'),
realpath(__DIR__ . '/../vendor/slickdeals'),
realpath(__DIR__ . '/../vendor/psr/log'),
realpath(__DIR__ . '/../vendor/piwik'),
realpath(__DIR__ . '/../vendor/matomo'),
realpath(__DIR__ . '/../vendor/symfony'),
] as $key => $value) {
if($value !== false) {

View file

@ -139,7 +139,6 @@ $cli
Console::success('SMTP................connected 👍');
} catch (\Throwable $th) {
Console::error('SMTP.............disconnected 👎');
var_dump($th);
}
$host = App::getEnv('_APP_STATSD_HOST', 'telegraf');

View file

@ -96,6 +96,16 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
$config = new CLI();
$config->setComposerVendor('appwrite');
$config->setComposerPackage('cli');
$config->setExecutableName('appwrite');
$config->setExecutableName('appwrite');
$config->setLogo("
_ _ _ ___ __ _____
/_\ _ __ _ ____ ___ __(_) |_ ___ / __\ / / \_ \
//_\\| '_ \| '_ \ \ /\ / / '__| | __/ _ \ / / / / / /\/
/ _ \ |_) | |_) \ V V /| | | | || __/ / /___/ /___/\/ /_
\_/ \_/ .__/| .__/ \_/\_/ |_| |_|\__\___| \____/\____/\____/
|_| |_|
");
break;
case 'php':
$config = new PHP();

View file

@ -114,7 +114,7 @@ $maxCells = 10;
<?php if(!$array): ?>
<?php switch($type):
case 'fileId': ?>
<img data-ls-if="{{node.<?php echo $this->escape($key); ?>}} != ''" src="" data-ls-attrs="src=//{{env.DOMAIN}}/v1/storage/files/{{node.<?php echo $this->escape($key); ?>}}/preview?width=65&height=65&project={{router.params.project}}&mode=admin" class="avatar" width="30" height="30" loading="lazy" />
<img data-ls-if="{{node.<?php echo $this->escape($key); ?>}} != ''" src="" data-ls-attrs="src={{env.ENDPOINT}}/v1/storage/files/{{node.<?php echo $this->escape($key); ?>}}/preview?width=65&height=65&project={{router.params.project}}&mode=admin" class="avatar" width="30" height="30" loading="lazy" />
<?php break; ?>
<?php case 'document': ?>
{...}

View file

@ -72,7 +72,7 @@ $rules = $collection->getAttribute('rules', []);
<?php if(!$array): ?>
<?php switch($type):
case 'fileId': ?>
<img data-ls-if="{{node.<?php echo $this->escape($key); ?>}} != ''" src="" data-ls-attrs="src=//{{env.DOMAIN}}/v1/storage/files/{{node.<?php echo $this->escape($key); ?>}}/preview?width=65&height=65&project={{router.params.project}}&mode=admin" class="avatar" width="30" height="30" loading="lazy" />
<img data-ls-if="{{node.<?php echo $this->escape($key); ?>}} != ''" src="" data-ls-attrs="src={{env.ENDPOINT}}/v1/storage/files/{{node.<?php echo $this->escape($key); ?>}}/preview?width=65&height=65&project={{router.params.project}}&mode=admin" class="avatar" width="30" height="30" loading="lazy" />
<?php break; ?>
<?php case 'document': ?>
{...}

View file

@ -54,7 +54,7 @@
<input type="radio" name="selected" data-ls-attrs="value={{file.$id}}" data-ls-bind="{{search.selected}}" />
</td>
<td data-title="x" class="">
<img src="" data-ls-attrs="src=//{{env.DOMAIN}}/v1/storage/files/{{file.$id}}/preview?width=65&height=65&project={{router.params.project}}&mode=admin" class="pull-start avatar" width="30" height="30" loading="lazy" />
<img src="" data-ls-attrs="src={{env.ENDPOINT}}/v1/storage/files/{{file.$id}}/preview?width=65&height=65&project={{router.params.project}}&mode=admin" class="pull-start avatar" width="30" height="30" loading="lazy" />
</td>
<td data-title="Name: " class="text-one-liner">
<span data-ls-bind="{{file.name}}" data-ls-attrs="title={{file.name}}" class="text-fade text-size-small"></span>
@ -64,6 +64,7 @@
</td>
<td data-title="Size: ">
<span class="text-fade text-size-small" data-ls-bind="{{file.sizeOriginal|humanFileSize}}"></span>
<span class="text-fade text-size-small" data-ls-bind="{{file.sizeOriginal|humanFileUnit}}"></span>
</td>
<td data-title="Created: ">
<span class="text-fade text-size-small" data-ls-bind="{{file.dateCreated|dateText}}"></span>

View file

@ -117,7 +117,7 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
<b data-ls-bind="{{tag.$id}}"></b> &nbsp;
<span class="text-fade" data-ls-bind="{{tag.command}}"></span>
<div class="text-size-small margin-top-small clear">
<span class="pull-start" data-ls-bind="Created {{tag.dateCreated|timeSince}} &nbsp; | &nbsp; {{tag.size|humanFileSize}}"></span>
<span class="pull-start" data-ls-bind="Created {{tag.dateCreated|timeSince}} &nbsp; | &nbsp; {{tag.size|humanFileSize}}{{tag.size|humanFileUnit}}"></span>
<form data-ls-if="{{tag.$id}} !== {{project-function.tag}}" name="functions.deleteTag" class="pull-start"
data-analytics
@ -596,9 +596,9 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
<p><b>PowerShell</b></p>
<div class="margin-bottom">
<textarea type="hidden" data-ls-bind="appwrite functions createTag ,
--functionId={{project-function.$id}} ,
--command='mycommand' ,
<textarea type="hidden" data-ls-bind="appwrite functions createTag `
--functionId={{project-function.$id}} `
--command='mycommand' `
--code='/myrepo/myfunction'" data-forms-code="powershell" data-lang="powershell" data-lang-label="PowerShell"></textarea>
</div>

View file

@ -97,7 +97,10 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
</div>
</div>
<div class="col span-3">
<div class="value margin-bottom-small"><span class="sum" data-ls-bind="{{usage.network.total|humanFileSize}}" data-default="0">0</span></div>
<div class="value margin-bottom-small">
<span class="sum" data-ls-bind="{{usage.network.total|humanFileSize}}" data-default="0">0</span>
<span data-ls-bind="{{usage.network.total|humanFileUnit}}" class="text-size-small unit"></span>
</div>
<div class="metric margin-bottom-small">Bandwidth</div>
<div class="margin-top-large value small">
@ -117,7 +120,10 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
<div class="margin-top-small"><b class="text-size-small unit">Documents</b></div>
</div>
<div class="col span-3">
<div class="value"><span class="sum" data-ls-bind="{{usage.storage.total|humanFileSize}}" data-default="0">0</span></div>
<div class="value">
<span class="sum" data-ls-bind="{{usage.storage.total|humanFileSize}}" data-default="0">0</span>
<span data-ls-bind="{{usage.storage.total|humanFileUnit}}" class="text-size-small unit"></span>
</div>
<div class="margin-top-small"><b class="text-size-small unit">Storage</b></div>
</div>
<div class="col span-3">

View file

@ -2,6 +2,7 @@
$customDomainsEnabled = $this->getParam('customDomainsEnabled', false);
$customDomainsTarget = $this->getParam('customDomainsTarget', false);
$smtpEnabled = $this->getParam('smtpEnabled', false);
?>
<div class="cover">
@ -135,7 +136,7 @@ $customDomainsTarget = $this->getParam('customDomainsTarget', false);
<label for="name">API Endpoint</label>
<div class="input-copy">
<input data-forms-copy type="text" disabled data-ls-bind="{{env.PROTOCOL}}://{{env.DOMAIN}}/v1" />
<input data-forms-copy type="text" disabled data-ls-bind="{{env.ENDPOINT}}/v1" />
</div>
<ul class="margin-bottom-large text-fade text-size-small">
@ -453,7 +454,7 @@ $customDomainsTarget = $this->getParam('customDomainsTarget', false);
data-failure-param-alert-classname="error">
<input name="teamId" type="hidden" data-ls-bind="{{member.teamId}}">
<input name="url" type="hidden" data-ls-bind="{{env.PROTOCOL}}://{{env.DOMAIN}}/auth/join?project={{router.params.project}}" />
<input name="url" type="hidden" data-ls-bind="{{env.ENDPOINT}}/auth/join?project={{router.params.project}}" />
<input name="email" type="hidden" data-ls-bind="{{member.email}}">
<input name="name" type="hidden" data-ls-bind="{{member.name}}">
<input name="roles" type="hidden" data-ls-bind="{{member.roles}}" data-cast-to="json">
@ -493,7 +494,7 @@ $customDomainsTarget = $this->getParam('customDomainsTarget', false);
data-failure-param-alert-classname="error">
<input name="teamId" id="team-teamId" type="hidden" data-ls-bind="{{console-project.teamId}}">
<input name="url" type="hidden" data-ls-bind="{{env.PROTOCOL}}://{{env.DOMAIN}}/auth/join?project={{router.params.project}}" />
<input name="url" type="hidden" data-ls-bind="{{env.ENDPOINT}}/auth/join?project={{router.params.project}}" />
<label for="email">Email</label>
<input name="email" id="email" type="email" autocomplete="email" required>
@ -506,10 +507,16 @@ $customDomainsTarget = $this->getParam('customDomainsTarget', false);
<option data-ls-attrs="value={{role.type}}" data-ls-bind="{{role.label}}"></option>
</select>
<?php if(!$smtpEnabled): ?>
<div class="box note padding-tiny warning margin-bottom text-align-center">
<i class="icon-warning"></i> SMTP connection is disabled. <a href="https://appwrite.io/docs/email-delivery" target="_blank" rel="noopener">Learn more <i class="icon-link-ext"></i></a>
</div>
<?php endif; ?>
<hr />
<div class="clear">
<button>Send Invite</button>
<button<?php if(!$smtpEnabled): ?> disabled<?php endif; ?>>Send Invite</button>
&nbsp; <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
</div>
</form>

View file

@ -113,7 +113,7 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
<tbody data-ls-loop="project-files.files" data-ls-as="file">
<tr>
<td class="hide">
<img src="" data-ls-attrs="src=//{{env.DOMAIN}}/v1/storage/files/{{file.$id}}/preview?width=65&height=65&project={{router.params.project}}&mode=admin" class="pull-start avatar" width="30" height="30" loading="lazy" />
<img src="" data-ls-attrs="src={{env.ENDPOINT}}/v1/storage/files/{{file.$id}}/preview?width=65&height=65&project={{router.params.project}}&mode=admin" class="pull-start avatar" width="30" height="30" loading="lazy" />
</td>
<td data-title="Name: " class="text-one-liner" data-ls-attrs="title={{file.name}}" >
<div data-ui-modal class="box modal sticky-footer width-large close" data-button-text="{{file.name}}" data-button-class="link" data-button-element="span">
@ -180,15 +180,15 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
<div class="margin-bottom-small">File Preview</div>
<div class="margin-bottom-small">
<img src="" class="file-preview" data-ls-attrs="src=//{{env.DOMAIN}}/v1/storage/files/{{file.$id}}/preview?width=350&height=250&project={{router.params.project}}&mode=admin" loading="lazy" width="225" height="160" />
<img src="" class="file-preview" data-ls-attrs="src={{env.ENDPOINT}}/v1/storage/files/{{file.$id}}/preview?width=350&height=250&project={{router.params.project}}&mode=admin" loading="lazy" width="225" height="160" />
</div>
<div class="margin-bottom-tiny">
<a href="" data-ls-attrs="href=//{{env.DOMAIN}}/v1/storage/files/{{file.$id}}/view?project={{router.params.project}}&mode=admin" target="_blank" rel="noopener"><i class="icon-angle-circled-right margin-start-negative-tiny margin-end-tiny"></i> New Window <i class="icon-link-ext"></i></a>
<a href="" data-ls-attrs="href={{env.ENDPOINT}}/v1/storage/files/{{file.$id}}/view?project={{router.params.project}}&mode=admin" target="_blank" rel="noopener"><i class="icon-angle-circled-right margin-start-negative-tiny margin-end-tiny"></i> New Window <i class="icon-link-ext"></i></a>
</div>
<div class="margin-bottom">
<a href="" data-ls-attrs="href=//{{env.DOMAIN}}/v1/storage/files/{{file.$id}}/download?project={{router.params.project}}&mode=admin" target="_blank" rel="noopener"><i class="icon-angle-circled-right margin-start-negative-tiny margin-end-tiny"></i> Download <i class="icon-link-ext"></i></a>
<a href="" data-ls-attrs="href={{env.ENDPOINT}}/v1/storage/files/{{file.$id}}/download?project={{router.params.project}}&mode=admin" target="_blank" rel="noopener"><i class="icon-angle-circled-right margin-start-negative-tiny margin-end-tiny"></i> Download <i class="icon-link-ext"></i></a>
</div>
</div>
</div>
@ -204,6 +204,7 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
</td>
<td data-title="Size: ">
<span class="text-fade text-size-small" data-ls-bind="{{file.sizeOriginal|humanFileSize}}"></span>
<span class="text-fade text-size-small" data-ls-bind="{{file.sizeOriginal|humanFileUnit}}"></span>
</td>
<td data-title="Created: ">
<span class="text-fade text-size-small" data-ls-bind="{{file.dateCreated|dateText}}"></span>

View file

@ -361,7 +361,7 @@ $providers = $this->getParam('providers', []);
<p>To complete set up, add this OAuth2 redirect URI to your <?php echo $this->escape(ucfirst($provider)); ?> app configuration.</p>
<div class="input-copy">
<input data-forms-copy type="text" disabled data-ls-bind="{{env.PROTOCOL}}://{{env.DOMAIN}}/v1/account/sessions/oauth2/callback/<?php echo $this->escape($provider); ?>/{{router.params.project}}" class="margin-bottom-no" />
<input data-forms-copy type="text" disabled data-ls-bind="{{env.ENDPOINT}}/v1/account/sessions/oauth2/callback/<?php echo $this->escape($provider); ?>/{{router.params.project}}" class="margin-bottom-no" />
</div>
</div>
</div>

View file

@ -145,7 +145,7 @@
data-failure-param-alert-classname="error">
<input name="teamId" id="team-teamId" type="hidden" data-ls-bind="{{team.$id}}">
<input name="url" type="hidden" data-ls-bind="{{env.PROTOCOL}}://{{env.DOMAIN}}" />
<input name="url" type="hidden" data-ls-bind="{{env.ENDPOINT}}" />
<label for="email">Email</label>
<input name="email" id="email" type="email" autocomplete="email" required>

View file

@ -23,7 +23,7 @@
<label>Email</label>
<input name="email" type="email" class="full-width" autocomplete="email" placeholder="me@example.com" required>
<input name="url" type="hidden" data-ls-bind="{{env.PROTOCOL}}://{{env.DOMAIN}}/auth/recovery/reset" />
<input name="url" type="hidden" data-ls-bind="{{env.ENDPOINT}}/auth/recovery/reset" />
<button type="submit" class="btn btn-primary"><i class="fa fa-sign-in"></i> Recover</button>
</form>

View file

@ -56,9 +56,12 @@ services:
- influxdb
environment:
- _APP_ENV
- _APP_CONSOLE_WHITELIST_EMAILS
- _APP_CONSOLE_WHITELIST_IPS
- _APP_SYSTEM_EMAIL_NAME
- _APP_SYSTEM_EMAIL_ADDRESS
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
- _APP_SYSTEM_RESPONSE_FORMAT
- _APP_OPTIONS_ABUSE
- _APP_OPTIONS_FORCE_HTTPS
- _APP_OPENSSL_KEY_V1
@ -66,6 +69,8 @@ services:
- _APP_DOMAIN_TARGET
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@ -104,6 +109,8 @@ services:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_STATSD_HOST
- _APP_STATSD_PORT
@ -121,6 +128,8 @@ services:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@ -142,6 +151,8 @@ services:
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@ -163,6 +174,8 @@ services:
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@ -187,6 +200,8 @@ services:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@ -211,6 +226,8 @@ services:
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DOMAIN_TARGET
- _APP_DB_HOST
- _APP_DB_PORT
@ -236,6 +253,8 @@ services:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@ -257,13 +276,14 @@ services:
- appwrite
depends_on:
- redis
- smtp
environment:
- _APP_ENV
- _APP_SYSTEM_EMAIL_NAME
- _APP_SYSTEM_EMAIL_ADDRESS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_SMTP_HOST
- _APP_SMTP_PORT
- _APP_SMTP_SECURE
@ -283,6 +303,8 @@ services:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_MAINTENANCE_INTERVAL
- _APP_MAINTENANCE_RETENTION_EXECUTION
- _APP_MAINTENANCE_RETENTION_ABUSE
@ -302,6 +324,8 @@ services:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
mariadb:
image: appwrite/mariadb:1.2.0 # fix issues when upgrading using: mysql_upgrade -u root -p
@ -318,16 +342,6 @@ services:
- MYSQL_PASSWORD=${_APP_DB_PASS}
command: 'mysqld --innodb-flush-method=fsync'
smtp:
image: appwrite/smtp:1.0.1
container_name: appwrite-smtp
restart: unless-stopped
networks:
- appwrite
environment:
- MAILNAME=appwrite
- RELAY_NETWORKS=:192.168.0.0/24:10.0.0.0/16
redis:
image: redis:6.0-alpine3.12
container_name: appwrite-redis

View file

@ -2,6 +2,7 @@
$protocol = $this->getParam('protocol', '');
$domain = $this->getParam('domain', '');
$endpoint = $this->getParam('endpoint', '');
$platforms = $this->getParam('platforms', []);
$version = $this->getParam('version', '0.0.0');
$isDev = $this->getParam('isDev', false);
@ -56,7 +57,7 @@ if(!empty($platforms)) {
<?php if (!empty($canonical)): ?>
<meta property="og:url" content="<?php echo $canonical; ?>" />
<?php endif; ?>
<meta property="og:image" content="<?php echo $protocol; ?>://<?php echo $domain; ?>/images/logo.png?v=<?php echo APP_CACHE_BUSTER; ?>" />
<meta property="og:image" content="<?php echo $endpoint; ?>/images/logo.png?v=<?php echo APP_CACHE_BUSTER; ?>" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
@ -71,6 +72,7 @@ if(!empty($platforms)) {
VERSION: '<?php echo $version; ?>',
CACHEBUSTER: '<?php echo $version; ?>/<?php echo APP_CACHE_BUSTER; ?>',
PROTOCOL: '<?php echo $protocol; ?>',
ENDPOINT: '<?php echo $endpoint; ?>',
DOMAIN: '<?php echo $domain; ?>',
HOME: '<?php echo $this->escape($this->getParam('home')); ?>',
SETUP: '<?php echo $this->escape($this->getParam('setup')); ?>',
@ -142,4 +144,4 @@ if(!empty($platforms)) {
<!-- Version <?php echo $version; ?> -->
</body>
</html>
</html>

View file

@ -110,14 +110,22 @@ class CertificatesV1
}
$staging = (App::isProduction()) ? '' : ' --dry-run';
$email = App::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS');
$response = \shell_exec("certbot certonly --webroot --noninteractive --agree-tos{$staging}"
." --email ".App::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS', 'security@localhost.test')
if(empty($email)) {
throw new Exception('You must set a valid security email address (_APP_SYSTEM_SECURITY_EMAIL_ADDRESS) to issue an SSL certificate');
}
$stdout = '';
$stderr = '';
$exit = Console::execute("certbot certonly --webroot --noninteractive --agree-tos{$staging}"
." --email ".$email
." -w ".APP_STORAGE_CERTIFICATES
." -d {$domain->get()}");
." -d {$domain->get()}", '', $stdout, $stderr);
if(!$response) {
throw new Exception('Failed to issue a certificate');
if($stderr || $exit !== 0) {
throw new Exception('Failed to issue a certificate with message: '.$stderr);
}
$path = APP_STORAGE_CERTIFICATES.'/'.$domain->get();
@ -129,19 +137,19 @@ class CertificatesV1
}
if(!@\rename('/etc/letsencrypt/live/'.$domain->get().'/cert.pem', APP_STORAGE_CERTIFICATES.'/'.$domain->get().'/cert.pem')) {
throw new Exception('Failed to rename certificate cert.pem: '.\json_encode($response));
throw new Exception('Failed to rename certificate cert.pem: '.\json_encode($stdout));
}
if(!@\rename('/etc/letsencrypt/live/'.$domain->get().'/chain.pem', APP_STORAGE_CERTIFICATES.'/'.$domain->get().'/chain.pem')) {
throw new Exception('Failed to rename certificate chain.pem: '.\json_encode($response));
throw new Exception('Failed to rename certificate chain.pem: '.\json_encode($stdout));
}
if(!@\rename('/etc/letsencrypt/live/'.$domain->get().'/fullchain.pem', APP_STORAGE_CERTIFICATES.'/'.$domain->get().'/fullchain.pem')) {
throw new Exception('Failed to rename certificate fullchain.pem: '.\json_encode($response));
throw new Exception('Failed to rename certificate fullchain.pem: '.\json_encode($stdout));
}
if(!@\rename('/etc/letsencrypt/live/'.$domain->get().'/privkey.pem', APP_STORAGE_CERTIFICATES.'/'.$domain->get().'/privkey.pem')) {
throw new Exception('Failed to rename certificate privkey.pem: '.\json_encode($response));
throw new Exception('Failed to rename certificate privkey.pem: '.\json_encode($stdout));
}
$certificate = \array_merge($certificate, [
@ -154,7 +162,7 @@ class CertificatesV1
'issueDate' => \time(),
'renewDate' => $renew,
'attempts' => 0,
'log' => \json_encode($response),
'log' => \json_encode($stdout),
]);
$certificate = $consoleDB->createDocument($certificate);

View file

@ -227,7 +227,7 @@ class FunctionsV1
return;
}
$cron = CronExpression::factory($function->getAttribute('schedule'));
$cron = new CronExpression($function->getAttribute('schedule'));
$next = (int) $cron->getNextRunDate()->format('U');
$function

View file

@ -82,7 +82,7 @@ class TasksV1
// Reschedule
$cron = CronExpression::factory($task->getAttribute('schedule'));
$cron = new CronExpression($task->getAttribute('schedule'));
$next = (int) $cron->getNextRunDate()->format('U');
$headers = (\is_array($task->getAttribute('httpHeaders', []))) ? $task->getAttribute('httpHeaders', []) : [];

View file

@ -1,3 +1,10 @@
#!/bin/sh
REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}" RESQUE_PHP='/usr/src/code/vendor/autoload.php' php /usr/src/code/vendor/bin/resque-scheduler
if [ -z "$_APP_REDIS_USER" ] || [ -z "$_APP_REDIS_PASS" ]
then
REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
else
REDIS_BACKEND="redis://${_APP_REDIS_USER}:${_APP_REDIS_PASS}@${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
fi
REDIS_BACKEND=$REDIS_BACKEND RESQUE_PHP='/usr/src/code/vendor/autoload.php' php /usr/src/code/vendor/bin/resque-scheduler

View file

@ -1,3 +1,10 @@
#!/bin/sh
QUEUE='v1-audits' APP_INCLUDE='/usr/src/code/app/workers/audits.php' REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}" php /usr/src/code/vendor/bin/resque -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php
if [ -z "$_APP_REDIS_USER" ] || [ -z "$_APP_REDIS_PASS" ]
then
REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
else
REDIS_BACKEND="redis://${_APP_REDIS_USER}:${_APP_REDIS_PASS}@${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
fi
QUEUE='v1-audits' APP_INCLUDE='/usr/src/code/app/workers/audits.php' php /usr/src/code/vendor/bin/resque -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php

9
bin/worker-certificates Normal file → Executable file
View file

@ -1,3 +1,10 @@
#!/bin/sh
QUEUE='v1-certificates' APP_INCLUDE='/usr/src/code/app/workers/certificates.php' REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}" php /usr/src/code/vendor/bin/resque -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php
if [ -z "$_APP_REDIS_USER" ] || [ -z "$_APP_REDIS_PASS" ]
then
REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
else
REDIS_BACKEND="redis://${_APP_REDIS_USER}:${_APP_REDIS_PASS}@${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
fi
QUEUE='v1-certificates' APP_INCLUDE='/usr/src/code/app/workers/certificates.php' php /usr/src/code/vendor/bin/resque -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php

View file

@ -1,3 +1,10 @@
#!/bin/sh
QUEUE='v1-deletes' APP_INCLUDE='/usr/src/code/app/workers/deletes.php' REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}" php /usr/src/code/vendor/bin/resque -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php
if [ -z "$_APP_REDIS_USER" ] || [ -z "$_APP_REDIS_PASS" ]
then
REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
else
REDIS_BACKEND="redis://${_APP_REDIS_USER}:${_APP_REDIS_PASS}@${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
fi
QUEUE='v1-deletes' APP_INCLUDE='/usr/src/code/app/workers/deletes.php' php /usr/src/code/vendor/bin/resque -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php

View file

@ -1,3 +1,10 @@
#!/bin/sh
QUEUE='v1-functions' APP_INCLUDE='/usr/src/code/app/workers/functions.php' REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}" php /usr/src/code/vendor/bin/resque -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php
if [ -z "$_APP_REDIS_USER" ] || [ -z "$_APP_REDIS_PASS" ]
then
REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
else
REDIS_BACKEND="redis://${_APP_REDIS_USER}:${_APP_REDIS_PASS}@${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
fi
QUEUE='v1-functions' APP_INCLUDE='/usr/src/code/app/workers/functions.php' php /usr/src/code/vendor/bin/resque -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php

View file

@ -1,3 +1,10 @@
#!/bin/sh
QUEUE='v1-mails' APP_INCLUDE='/usr/src/code/app/workers/mails.php' REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}" php /usr/src/code/vendor/bin/resque -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php
if [ -z "$_APP_REDIS_USER" ] || [ -z "$_APP_REDIS_PASS" ]
then
REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
else
REDIS_BACKEND="redis://${_APP_REDIS_USER}:${_APP_REDIS_PASS}@${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
fi
QUEUE='v1-mails' APP_INCLUDE='/usr/src/code/app/workers/mails.php' php /usr/src/code/vendor/bin/resque -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php

View file

@ -1,3 +1,10 @@
#!/bin/sh
QUEUE='v1-tasks' APP_INCLUDE='/usr/src/code/app/workers/tasks.php' REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}" php /usr/src/code/vendor/bin/resque -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php
if [ -z "$_APP_REDIS_USER" ] || [ -z "$_APP_REDIS_PASS" ]
then
REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
else
REDIS_BACKEND="redis://${_APP_REDIS_USER}:${_APP_REDIS_PASS}@${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
fi
QUEUE='v1-tasks' APP_INCLUDE='/usr/src/code/app/workers/tasks.php' php /usr/src/code/vendor/bin/resque -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php

View file

@ -1,3 +1,10 @@
#!/bin/sh
QUEUE='v1-usage' APP_INCLUDE='/usr/src/code/app/workers/usage.php' REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}" php /usr/src/code/vendor/bin/resque -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php
if [ -z "$_APP_REDIS_USER" ] || [ -z "$_APP_REDIS_PASS" ]
then
REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
else
REDIS_BACKEND="redis://${_APP_REDIS_USER}:${_APP_REDIS_PASS}@${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
fi
QUEUE='v1-usage' APP_INCLUDE='/usr/src/code/app/workers/usage.php' php /usr/src/code/vendor/bin/resque -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php

View file

@ -1,3 +1,10 @@
#!/bin/sh
QUEUE='v1-webhooks' APP_INCLUDE='/usr/src/code/app/workers/webhooks.php' REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}" php /usr/src/code/vendor/bin/resque -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php
if [ -z "$_APP_REDIS_USER" ] || [ -z "$_APP_REDIS_PASS" ]
then
REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
else
REDIS_BACKEND="redis://${_APP_REDIS_USER}:${_APP_REDIS_PASS}@${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
fi
QUEUE='v1-webhooks' APP_INCLUDE='/usr/src/code/app/workers/webhooks.php' php /usr/src/code/vendor/bin/resque -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php

View file

@ -39,7 +39,7 @@
"utopia-php/analytics": "0.1.*",
"utopia-php/audit": "0.5.*",
"utopia-php/cache": "0.2.*",
"utopia-php/cli": "0.9.0",
"utopia-php/cli": "0.10.0",
"utopia-php/config": "0.2.*",
"utopia-php/locale": "0.3.*",
"utopia-php/registry": "0.2.*",
@ -48,19 +48,20 @@
"utopia-php/swoole": "0.2.*",
"utopia-php/system": "0.4.*",
"utopia-php/storage": "0.4.*",
"utopia-php/image": "0.1.*",
"webonyx/graphql-php": "14.4.0",
"resque/php-resque": "1.3.6",
"matomo/device-detector": "3.13.0",
"dragonmantank/cron-expression": "3.0.1",
"domnikl/statsd": "3.0.2",
"influxdb/influxdb-php": "1.15.1",
"phpmailer/phpmailer": "6.1.7",
"matomo/device-detector": "4.1.0",
"dragonmantank/cron-expression": "3.1.0",
"influxdb/influxdb-php": "1.15.2",
"phpmailer/phpmailer": "6.3.0",
"chillerlan/php-qrcode": "4.3.0",
"adhocore/jwt": "1.1.0"
"adhocore/jwt": "1.1.2",
"slickdeals/statsd": "~3.0"
},
"require-dev": {
"appwrite/sdk-generator": "0.5.5",
"appwrite/sdk-generator": "0.6.3",
"phpunit/phpunit": "9.4.2",
"swoole/ide-helper": "4.5.5",
"vimeo/psalm": "4.1.1"

662
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -86,6 +86,8 @@ services:
- _APP_DOMAIN_TARGET
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@ -127,6 +129,8 @@ services:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_STATSD_HOST
- _APP_STATSD_PORT
@ -147,6 +151,8 @@ services:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@ -172,6 +178,8 @@ services:
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@ -196,6 +204,8 @@ services:
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@ -223,6 +233,8 @@ services:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@ -249,6 +261,8 @@ services:
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@ -276,6 +290,8 @@ services:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
@ -310,6 +326,8 @@ services:
- _APP_SYSTEM_EMAIL_ADDRESS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_SMTP_HOST
- _APP_SMTP_PORT
- _APP_SMTP_SECURE
@ -332,6 +350,8 @@ services:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_MAINTENANCE_INTERVAL
- _APP_MAINTENANCE_RETENTION_EXECUTION
- _APP_MAINTENANCE_RETENTION_ABUSE
@ -353,6 +373,8 @@ services:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
mariadb:
image: appwrite/mariadb:1.2.0 # fix issues when upgrading using: mysql_upgrade -u root -p

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.createOAuth2Session(
provider: 'amazon',
);
@ -19,4 +18,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.createRecovery(
email: 'email@example.com',
url: 'https://example.com',
@ -20,4 +19,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.createSession(
email: 'email@example.com',
password: 'password',
@ -20,4 +19,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.createVerification(
url: 'https://example.com',
);
@ -19,4 +18,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.create(
email: 'email@example.com',
password: 'password',
@ -20,4 +19,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.deleteSession(
sessionId: '[SESSION_ID]',
);
@ -19,4 +18,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.deleteSessions();
result
@ -17,4 +16,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.delete();
result
@ -17,4 +16,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.getLogs();
result
@ -17,4 +16,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.getPrefs();
result
@ -17,4 +16,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.getSessions();
result
@ -17,4 +16,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.get();
result
@ -17,4 +16,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.updateEmail(
email: 'email@example.com',
password: 'password',
@ -20,4 +19,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.updateName(
name: '[NAME]',
);
@ -19,4 +18,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.updatePassword(
password: 'password',
oldPassword: 'password',
@ -20,4 +19,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.updatePrefs(
prefs: {},
);
@ -19,4 +18,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.updateRecovery(
userId: '[USER_ID]',
secret: '[SECRET]',
@ -22,4 +21,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.updateVerification(
userId: '[USER_ID]',
secret: '[SECRET]',
@ -20,4 +19,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,10 +8,18 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
}
String result = avatars.getBrowser(
//displaying image
FutureBuilder(
future: avatars.getBrowser(
code: 'aa',
);
print(result); // Resource URL string
}
), //works for both public file and private file, for private files you need to be logged in
builder: (context, snapshot) {
return snapshot.hasData && snapshot.data != null
? Image.memory(
snapshot.data.data,
)
: CircularProgressIndicator();
},
);

View file

@ -8,10 +8,18 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
}
String result = avatars.getCreditCard(
//displaying image
FutureBuilder(
future: avatars.getCreditCard(
code: 'amex',
);
print(result); // Resource URL string
}
), //works for both public file and private file, for private files you need to be logged in
builder: (context, snapshot) {
return snapshot.hasData && snapshot.data != null
? Image.memory(
snapshot.data.data,
)
: CircularProgressIndicator();
},
);

View file

@ -8,10 +8,18 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
}
String result = avatars.getFavicon(
//displaying image
FutureBuilder(
future: avatars.getFavicon(
url: 'https://example.com',
);
print(result); // Resource URL string
}
), //works for both public file and private file, for private files you need to be logged in
builder: (context, snapshot) {
return snapshot.hasData && snapshot.data != null
? Image.memory(
snapshot.data.data,
)
: CircularProgressIndicator();
},
);

View file

@ -8,10 +8,18 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
}
String result = avatars.getFlag(
//displaying image
FutureBuilder(
future: avatars.getFlag(
code: 'af',
);
print(result); // Resource URL string
}
), //works for both public file and private file, for private files you need to be logged in
builder: (context, snapshot) {
return snapshot.hasData && snapshot.data != null
? Image.memory(
snapshot.data.data,
)
: CircularProgressIndicator();
},
);

View file

@ -8,10 +8,18 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
}
String result = avatars.getImage(
//displaying image
FutureBuilder(
future: avatars.getImage(
url: 'https://example.com',
);
print(result); // Resource URL string
}
), //works for both public file and private file, for private files you need to be logged in
builder: (context, snapshot) {
return snapshot.hasData && snapshot.data != null
? Image.memory(
snapshot.data.data,
)
: CircularProgressIndicator();
},
);

View file

@ -8,9 +8,17 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
}
String result = avatars.getInitials(
);
print(result); // Resource URL string
}
//displaying image
FutureBuilder(
future: avatars.getInitials(
), //works for both public file and private file, for private files you need to be logged in
builder: (context, snapshot) {
return snapshot.hasData && snapshot.data != null
? Image.memory(
snapshot.data.data,
)
: CircularProgressIndicator();
},
);

View file

@ -8,10 +8,18 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
}
String result = avatars.getQR(
//displaying image
FutureBuilder(
future: avatars.getQR(
text: '[TEXT]',
);
print(result); // Resource URL string
}
), //works for both public file and private file, for private files you need to be logged in
builder: (context, snapshot) {
return snapshot.hasData && snapshot.data != null
? Image.memory(
snapshot.data.data,
)
: CircularProgressIndicator();
},
);

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = database.createDocument(
collectionId: '[COLLECTION_ID]',
data: {},
@ -22,4 +21,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = database.deleteDocument(
collectionId: '[COLLECTION_ID]',
documentId: '[DOCUMENT_ID]',
@ -20,4 +19,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = database.getDocument(
collectionId: '[COLLECTION_ID]',
documentId: '[DOCUMENT_ID]',
@ -20,4 +19,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = database.listDocuments(
collectionId: '[COLLECTION_ID]',
);
@ -19,4 +18,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = database.updateDocument(
collectionId: '[COLLECTION_ID]',
documentId: '[DOCUMENT_ID]',
@ -23,4 +22,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = functions.createExecution(
functionId: '[FUNCTION_ID]',
);
@ -19,4 +18,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = functions.getExecution(
functionId: '[FUNCTION_ID]',
executionId: '[EXECUTION_ID]',
@ -20,4 +19,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = functions.listExecutions(
functionId: '[FUNCTION_ID]',
);
@ -19,4 +18,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = locale.getContinents();
result
@ -17,4 +16,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = locale.getCountriesEU();
result
@ -17,4 +16,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = locale.getCountriesPhones();
result
@ -17,4 +16,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = locale.getCountries();
result
@ -17,4 +16,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = locale.getCurrencies();
result
@ -17,4 +16,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = locale.getLanguages();
result
@ -17,4 +16,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = locale.get();
result
@ -17,4 +16,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -9,7 +9,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = storage.createFile(
file: await MultipartFile.fromFile('./path-to-files/image.jpg', 'image.jpg'),
read: [],
@ -22,4 +21,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = storage.deleteFile(
fileId: '[FILE_ID]',
);
@ -19,4 +18,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,10 +8,18 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
}
String result = storage.getFileDownload(
//displaying image
FutureBuilder(
future: storage.getFileDownload(
fileId: '[FILE_ID]',
);
print(result); // Resource URL string
}
), //works for both public file and private file, for private files you need to be logged in
builder: (context, snapshot) {
return snapshot.hasData && snapshot.data != null
? Image.memory(
snapshot.data.data,
)
: CircularProgressIndicator();
},
);

View file

@ -8,10 +8,18 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
}
String result = storage.getFilePreview(
//displaying image
FutureBuilder(
future: storage.getFilePreview(
fileId: '[FILE_ID]',
);
print(result); // Resource URL string
}
), //works for both public file and private file, for private files you need to be logged in
builder: (context, snapshot) {
return snapshot.hasData && snapshot.data != null
? Image.memory(
snapshot.data.data,
)
: CircularProgressIndicator();
},
);

View file

@ -8,10 +8,18 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
}
String result = storage.getFileView(
//displaying image
FutureBuilder(
future: storage.getFileView(
fileId: '[FILE_ID]',
);
print(result); // Resource URL string
}
), //works for both public file and private file, for private files you need to be logged in
builder: (context, snapshot) {
return snapshot.hasData && snapshot.data != null
? Image.memory(
snapshot.data.data,
)
: CircularProgressIndicator();
},
);

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = storage.getFile(
fileId: '[FILE_ID]',
);
@ -19,4 +18,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = storage.listFiles(
);
@ -18,4 +17,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = storage.updateFile(
fileId: '[FILE_ID]',
read: [],
@ -21,4 +20,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = teams.createMembership(
teamId: '[TEAM_ID]',
email: 'email@example.com',
@ -22,4 +21,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = teams.create(
name: '[NAME]',
);
@ -19,4 +18,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = teams.deleteMembership(
teamId: '[TEAM_ID]',
inviteId: '[INVITE_ID]',
@ -20,4 +19,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

View file

@ -8,7 +8,6 @@ void main() { // Init SDK
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = teams.delete(
teamId: '[TEAM_ID]',
);
@ -19,4 +18,4 @@ void main() { // Init SDK
}).catchError((error) {
print(error.response);
});
}
}

Some files were not shown because too many files have changed in this diff Show more