diff --git a/CHANGES.md b/CHANGES.md
index eba15ca01d..d0cd072bc4 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -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
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 950c5a3010..3d4bd75733 100644
--- a/README.md
+++ b/README.md
@@ -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.
diff --git a/app/config/variables.php b/app/config/variables.php
index e842283c2c..369a860fe2 100644
--- a/app/config/variables.php
+++ b/app/config/variables.php
@@ -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' => '',
],
diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php
index e7f36af332..fd09aaa3d5 100644
--- a/app/controllers/api/account.php
+++ b/app/controllers/api/account.php
@@ -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);
@@ -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);
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/api/users.php b/app/controllers/api/users.php
index efb0041cee..dbff5a0191 100644
--- a/app/controllers/api/users.php
+++ b/app/controllers/api/users.php
@@ -205,8 +205,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);
diff --git a/app/controllers/general.php b/app/controllers/general.php
index 614c400048..fe00160388 100644
--- a/app/controllers/general.php
+++ b/app/controllers/general.php
@@ -117,7 +117,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')
@@ -237,7 +237,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')
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..effa61ad56 100644
--- a/app/init.php
+++ b/app/init.php
@@ -34,13 +34,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';
@@ -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/preload.php b/app/preload.php
index f73aaea61a..7c8ae00938 100644
--- a/app/preload.php
+++ b/app/preload.php
@@ -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) {
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.