diff --git a/CHANGES.md b/CHANGES.md
index eba15ca01d..11f67a9ecd 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -4,10 +4,32 @@
# Version 0.7.1 (Not Released Yet)
-- Updated missing storage env vars
-- Added option to for Redis authentication
-- Force adding a security email on setup
+## Features
+
- Better error logs on appwrite cretificates 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
+
+## Bug Fixes
+
+- Updated missing storage env vars
+
+## Security
+
+- Fixed an XSS vulnerability in the Appwrite console
# Version 0.7.0
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index a994337483..dd7217a9af 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -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
diff --git a/Dockerfile b/Dockerfile
index c7316bd1d4..7cd404b7ae 100755
--- a/Dockerfile
+++ b/Dockerfile
@@ -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
diff --git a/README.md b/README.md
index 681c8710ad..950c5a3010 100644
--- a/README.md
+++ b/README.md
@@ -81,7 +81,7 @@ docker run -it --rm ,
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.
-For advanced production and custom installation, check out our Docker [environment variables](docs/tutorials/environment-variables.md) docs. You can also use our public [docker-compose.yml](https://appwrite.io/docker-compose.yml) file to manually set up and environment.
+For advanced production and custom installation, check out our Docker [environment variables](docs/tutorials/environment-variables.md) docs. You can also use our public [docker-compose.yml](https://appwrite.io/docker-compose.yml) file to manually set up an environment.
### Upgrade from an Older Version
@@ -133,13 +133,13 @@ Looking for more SDKs? - Help us by contributing a pull request to our [SDK Gene
## Contributing
-All code contributions - including those of people having commit access - must go through a pull request and approved by a core developer before being merged. This is to ensure proper review of all the code.
+All code contributions - including those of people having commit access - must go through a pull request and be approved by a core developer before being merged. This is to ensure a proper review of all the code.
We truly ❤️ pull requests! If you wish to help, you can learn more about how you can contribute to this project in the [contribution guide](CONTRIBUTING.md).
## Security
-For security issues, kindly email us at [security@appwrite.io](mailto:security@appwrite.io) instead of posting a public issue in GitHub.
+For security issues, kindly email us at [security@appwrite.io](mailto:security@appwrite.io) instead of posting a public issue on GitHub.
## Follow Us
diff --git a/app/config/variables.php b/app/config/variables.php
index e842283c2c..14b29bc451 100644
--- a/app/config/variables.php
+++ b/app/config/variables.php
@@ -105,10 +105,10 @@ 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',
- 'required' => false,
+ 'default' => '',
+ 'required' => true,
'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' => '',
],
diff --git a/app/controllers/api/avatars.php b/app/controllers/api/avatars.php
index fe2b53f71f..a094dc672a 100644
--- a/app/controllers/api/avatars.php
+++ b/app/controllers/api/avatars.php
@@ -1,28 +1,28 @@
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())
;
diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php
index e51fdd044f..7a6b11bcda 100644
--- a/app/controllers/api/functions.php
+++ b/app/controllers/api/functions.php
@@ -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(), [
diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php
index ed0d3a4435..63c99ffaee 100644
--- a/app/controllers/api/projects.php
+++ b/app/controllers/api/projects.php
@@ -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);
diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php
index 98980fd6bd..d4500e95aa 100644
--- a/app/controllers/api/storage.php
+++ b/app/controllers/api/storage.php
@@ -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')
diff --git a/app/controllers/shared/web.php b/app/controllers/shared/web.php
index 43eaf74d09..526a4dbb62 100644
--- a/app/controllers/shared/web.php
+++ b/app/controllers/shared/web.php
@@ -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
;
diff --git a/app/controllers/web/console.php b/app/controllers/web/console.php
index 6b3e105aa3..b41f1d1f86 100644
--- a/app/controllers/web/console.php
+++ b/app/controllers/web/console.php
@@ -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
diff --git a/app/controllers/web/home.php b/app/controllers/web/home.php
index f302f0af33..1a25dc2ee6 100644
--- a/app/controllers/web/home.php
+++ b/app/controllers/web/home.php
@@ -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);
});
\ No newline at end of file
diff --git a/app/init.php b/app/init.php
index ed2441d51b..a70ed1b88e 100644
--- a/app/init.php
+++ b/app/init.php
@@ -34,7 +34,7 @@ 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';
@@ -91,9 +91,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
*/
@@ -176,6 +180,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;
diff --git a/app/tasks/doctor.php b/app/tasks/doctor.php
index 2918d4f1e4..0f601bb5b5 100644
--- a/app/tasks/doctor.php
+++ b/app/tasks/doctor.php
@@ -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');
diff --git a/app/views/console/database/collection.phtml b/app/views/console/database/collection.phtml
index afe0365ee8..45d3287cf5 100644
--- a/app/views/console/database/collection.phtml
+++ b/app/views/console/database/collection.phtml
@@ -114,7 +114,7 @@ $maxCells = 10;
-
+
{...}
diff --git a/app/views/console/database/search/documents.phtml b/app/views/console/database/search/documents.phtml
index 1b656dc4e4..6fb67feab1 100644
--- a/app/views/console/database/search/documents.phtml
+++ b/app/views/console/database/search/documents.phtml
@@ -72,7 +72,7 @@ $rules = $collection->getAttribute('rules', []);
-
+
{...}
diff --git a/app/views/console/database/search/files.phtml b/app/views/console/database/search/files.phtml
index f8c39f4a87..0a1b4d739c 100644
--- a/app/views/console/database/search/files.phtml
+++ b/app/views/console/database/search/files.phtml
@@ -54,7 +54,7 @@
To complete set up, add this OAuth2 redirect URI to your escape(ucfirst($provider)); ?> app configuration.