Skip to content
This repository was archived by the owner on Jan 6, 2023. It is now read-only.

Commit d5812f1

Browse files
committed
v2.2.2
1 parent b508d09 commit d5812f1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1387
-332
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ Directus allows you to manage multilingual content in as many languages as your
103103

104104
### Community
105105

106-
* **[Slack](https://slack.directus.io)** — Come join almost a thousand members discussing the future of Directus. Our helpful members are also quick to offer advice for simple questions you may have while getting started.
106+
* **[Slack](https://directus.chat)** — Come join over a thousand members discussing the future of Directus. Our helpful members are also quick to offer advice for simple questions you may have while getting started.
107107
* **[Twitter](https://twitter.com/directus)** — Follow us on Twitter to be the first to hear about product updates, see sneak peeks of new features, and vote on polls regarding the future of our platform.
108108

109109
### GitHub Tickets

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@
4242
"webonyx/graphql-php": "^0.13.0"
4343
},
4444
"require-dev": {
45-
"phpunit/phpunit": "^5.7.25"
45+
"phpunit/phpunit": "^5.7.25",
46+
"phpbench/phpbench": "@dev"
4647
},
4748
"suggest": {
4849
"paragonie/random_compat": "Generates cryptographically more secure pseudo-random bytes",
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
4+
use Phinx\Migration\AbstractMigration;
5+
6+
class AddLoginAttemptsAllowedSetting extends AbstractMigration
7+
{
8+
public function up()
9+
{
10+
$fieldObject = [
11+
'field' => 'login_attempts_allowed',
12+
'type' => 'integer',
13+
'interface' => 'numeric',
14+
];
15+
$collection = 'directus_settings';
16+
17+
$checkSql = sprintf('SELECT 1 FROM `directus_fields` WHERE `collection` = "%s" AND `field` = "%s";', $collection, $fieldObject['field']);
18+
$result = $this->query($checkSql)->fetch();
19+
20+
if (!$result) {
21+
$insertSqlFormat = 'INSERT INTO `directus_fields` (`collection`, `field`, `type`, `interface`) VALUES ("%s", "%s", "%s", "%s");';
22+
$insertSql = sprintf($insertSqlFormat, $collection, $fieldObject['field'], $fieldObject['type'], $fieldObject['interface']);
23+
$this->execute($insertSql);
24+
}
25+
26+
}
27+
}
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
<?php
2+
3+
4+
use Phinx\Migration\AbstractMigration;
5+
6+
class UpdateIstanbulTimezone extends AbstractMigration
7+
{
8+
public function up()
9+
{
10+
$options = json_encode([
11+
'choices' => [
12+
'Pacific/Midway' => '(UTC-11:00) Midway Island',
13+
'Pacific/Samoa' => '(UTC-11:00) Samoa',
14+
'Pacific/Honolulu' => '(UTC-10:00) Hawaii',
15+
'US/Alaska' => '(UTC-09:00) Alaska',
16+
'America/Los_Angeles' => '(UTC-08:00) Pacific Time (US & Canada)',
17+
'America/Tijuana' => '(UTC-08:00) Tijuana',
18+
'US/Arizona' => '(UTC-07:00) Arizona',
19+
'America/Chihuahua' => '(UTC-07:00) Chihuahua',
20+
'America/Mexico/La_Paz' => '(UTC-07:00) La Paz',
21+
'America/Mazatlan' => '(UTC-07:00) Mazatlan',
22+
'US/Mountain' => '(UTC-07:00) Mountain Time (US & Canada)',
23+
'America/Managua' => '(UTC-06:00) Central America',
24+
'US/Central' => '(UTC-06:00) Central Time (US & Canada)',
25+
'America/Guadalajara' => '(UTC-06:00) Guadalajara',
26+
'America/Mexico_City' => '(UTC-06:00) Mexico City',
27+
'America/Monterrey' => '(UTC-06:00) Monterrey',
28+
'Canada/Saskatchewan' => '(UTC-06:00) Saskatchewan',
29+
'America/Bogota' => '(UTC-05:00) Bogota',
30+
'US/Eastern' => '(UTC-05:00) Eastern Time (US & Canada)',
31+
'US/East-Indiana' => '(UTC-05:00) Indiana (East)',
32+
'America/Lima' => '(UTC-05:00) Lima',
33+
'America/Quito' => '(UTC-05:00) Quito',
34+
'Canada/Atlantic' => '(UTC-04:00) Atlantic Time (Canada)',
35+
'America/New_York' => '(UTC-04:00) New York',
36+
'America/Caracas' => '(UTC-04:30) Caracas',
37+
'America/La_Paz' => '(UTC-04:00) La Paz',
38+
'America/Santiago' => '(UTC-04:00) Santiago',
39+
'America/Santo_Domingo' => '(UTC-04:00) Santo Domingo',
40+
'Canada/Newfoundland' => '(UTC-03:30) Newfoundland',
41+
'America/Sao_Paulo' => '(UTC-03:00) Brasilia',
42+
'America/Argentina/Buenos_Aires' => '(UTC-03:00) Buenos Aires',
43+
'America/Argentina/GeorgeTown' => '(UTC-03:00) Georgetown',
44+
'America/Godthab' => '(UTC-03:00) Greenland',
45+
'America/Noronha' => '(UTC-02:00) Mid-Atlantic',
46+
'Atlantic/Azores' => '(UTC-01:00) Azores',
47+
'Atlantic/Cape_Verde' => '(UTC-01:00) Cape Verde Is.',
48+
'Africa/Casablanca' => '(UTC+00:00) Casablanca',
49+
'Europe/Edinburgh' => '(UTC+00:00) Edinburgh',
50+
'Etc/Greenwich' => '(UTC+00:00) Greenwich Mean Time : Dublin',
51+
'Europe/Lisbon' => '(UTC+00:00) Lisbon',
52+
'Europe/London' => '(UTC+00:00) London',
53+
'Africa/Monrovia' => '(UTC+00:00) Monrovia',
54+
'UTC' => '(UTC+00:00) UTC',
55+
'Europe/Amsterdam' => '(UTC+01:00) Amsterdam',
56+
'Europe/Belgrade' => '(UTC+01:00) Belgrade',
57+
'Europe/Berlin' => '(UTC+01:00) Berlin',
58+
'Europe/Bern' => '(UTC+01:00) Bern',
59+
'Europe/Bratislava' => '(UTC+01:00) Bratislava',
60+
'Europe/Brussels' => '(UTC+01:00) Brussels',
61+
'Europe/Budapest' => '(UTC+01:00) Budapest',
62+
'Europe/Copenhagen' => '(UTC+01:00) Copenhagen',
63+
'Europe/Ljubljana' => '(UTC+01:00) Ljubljana',
64+
'Europe/Madrid' => '(UTC+01:00) Madrid',
65+
'Europe/Paris' => '(UTC+01:00) Paris',
66+
'Europe/Prague' => '(UTC+01:00) Prague',
67+
'Europe/Rome' => '(UTC+01:00) Rome',
68+
'Europe/Sarajevo' => '(UTC+01:00) Sarajevo',
69+
'Europe/Skopje' => '(UTC+01:00) Skopje',
70+
'Europe/Stockholm' => '(UTC+01:00) Stockholm',
71+
'Europe/Vienna' => '(UTC+01:00) Vienna',
72+
'Europe/Warsaw' => '(UTC+01:00) Warsaw',
73+
'Africa/Lagos' => '(UTC+01:00) West Central Africa',
74+
'Europe/Zagreb' => '(UTC+01:00) Zagreb',
75+
'Europe/Athens' => '(UTC+02:00) Athens',
76+
'Europe/Bucharest' => '(UTC+02:00) Bucharest',
77+
'Africa/Cairo' => '(UTC+02:00) Cairo',
78+
'Africa/Harare' => '(UTC+02:00) Harare',
79+
'Europe/Helsinki' => '(UTC+02:00) Helsinki',
80+
'Asia/Jerusalem' => '(UTC+02:00) Jerusalem',
81+
'Europe/Kyiv' => '(UTC+02:00) Kyiv',
82+
'Africa/Johannesburg' => '(UTC+02:00) Pretoria',
83+
'Europe/Riga' => '(UTC+02:00) Riga',
84+
'Europe/Sofia' => '(UTC+02:00) Sofia',
85+
'Europe/Tallinn' => '(UTC+02:00) Tallinn',
86+
'Europe/Vilnius' => '(UTC+02:00) Vilnius',
87+
'Europe/Istanbul' => '(UTC+03:00) Istanbul',
88+
'Asia/Baghdad' => '(UTC+03:00) Baghdad',
89+
'Asia/Kuwait' => '(UTC+03:00) Kuwait',
90+
'Europe/Minsk' => '(UTC+03:00) Minsk',
91+
'Africa/Nairobi' => '(UTC+03:00) Nairobi',
92+
'Asia/Riyadh' => '(UTC+03:00) Riyadh',
93+
'Europe/Volgograd' => '(UTC+03:00) Volgograd',
94+
'Asia/Tehran' => '(UTC+03:30) Tehran',
95+
'Asia/Abu_Dhabi' => '(UTC+04:00) Abu Dhabi',
96+
'Asia/Baku' => '(UTC+04:00) Baku',
97+
'Europe/Moscow' => '(UTC+04:00) Moscow',
98+
'Asia/Muscat' => '(UTC+04:00) Muscat',
99+
'Europe/St_Petersburg' => '(UTC+04:00) St. Petersburg',
100+
'Asia/Tbilisi' => '(UTC+04:00) Tbilisi',
101+
'Asia/Yerevan' => '(UTC+04:00) Yerevan',
102+
'Asia/Kabul' => '(UTC+04:30) Kabul',
103+
'Asia/Islamabad' => '(UTC+05:00) Islamabad',
104+
'Asia/Karachi' => '(UTC+05:00) Karachi',
105+
'Asia/Tashkent' => '(UTC+05:00) Tashkent',
106+
'Asia/Calcutta' => '(UTC+05:30) Chennai',
107+
'Asia/Kolkata' => '(UTC+05:30) Kolkata',
108+
'Asia/Mumbai' => '(UTC+05:30) Mumbai',
109+
'Asia/New_Delhi' => '(UTC+05:30) New Delhi',
110+
'Asia/Sri_Jayawardenepura' => '(UTC+05:30) Sri Jayawardenepura',
111+
'Asia/Katmandu' => '(UTC+05:45) Kathmandu',
112+
'Asia/Almaty' => '(UTC+06:00) Almaty',
113+
'Asia/Astana' => '(UTC+06:00) Astana',
114+
'Asia/Dhaka' => '(UTC+06:00) Dhaka',
115+
'Asia/Yekaterinburg' => '(UTC+06:00) Ekaterinburg',
116+
'Asia/Rangoon' => '(UTC+06:30) Rangoon',
117+
'Asia/Bangkok' => '(UTC+07:00) Bangkok',
118+
'Asia/Hanoi' => '(UTC+07:00) Hanoi',
119+
'Asia/Jakarta' => '(UTC+07:00) Jakarta',
120+
'Asia/Novosibirsk' => '(UTC+07:00) Novosibirsk',
121+
'Asia/Beijing' => '(UTC+08:00) Beijing',
122+
'Asia/Chongqing' => '(UTC+08:00) Chongqing',
123+
'Asia/Hong_Kong' => '(UTC+08:00) Hong Kong',
124+
'Asia/Krasnoyarsk' => '(UTC+08:00) Krasnoyarsk',
125+
'Asia/Kuala_Lumpur' => '(UTC+08:00) Kuala Lumpur',
126+
'Australia/Perth' => '(UTC+08:00) Perth',
127+
'Asia/Singapore' => '(UTC+08:00) Singapore',
128+
'Asia/Taipei' => '(UTC+08:00) Taipei',
129+
'Asia/Ulan_Bator' => '(UTC+08:00) Ulaan Bataar',
130+
'Asia/Urumqi' => '(UTC+08:00) Urumqi',
131+
'Asia/Irkutsk' => '(UTC+09:00) Irkutsk',
132+
'Asia/Osaka' => '(UTC+09:00) Osaka',
133+
'Asia/Sapporo' => '(UTC+09:00) Sapporo',
134+
'Asia/Seoul' => '(UTC+09:00) Seoul',
135+
'Asia/Tokyo' => '(UTC+09:00) Tokyo',
136+
'Australia/Adelaide' => '(UTC+09:30) Adelaide',
137+
'Australia/Darwin' => '(UTC+09:30) Darwin',
138+
'Australia/Brisbane' => '(UTC+10:00) Brisbane',
139+
'Australia/Canberra' => '(UTC+10:00) Canberra',
140+
'Pacific/Guam' => '(UTC+10:00) Guam',
141+
'Australia/Hobart' => '(UTC+10:00) Hobart',
142+
'Australia/Melbourne' => '(UTC+10:00) Melbourne',
143+
'Pacific/Port_Moresby' => '(UTC+10:00) Port Moresby',
144+
'Australia/Sydney' => '(UTC+10:00) Sydney',
145+
'Asia/Yakutsk' => '(UTC+10:00) Yakutsk',
146+
'Asia/Vladivostok' => '(UTC+11:00) Vladivostok',
147+
'Pacific/Auckland' => '(UTC+12:00) Auckland',
148+
'Pacific/Fiji' => '(UTC+12:00) Fiji',
149+
'Pacific/Kwajalein' => '(UTC+12:00) International Date Line West',
150+
'Asia/Kamchatka' => '(UTC+12:00) Kamchatka',
151+
'Asia/Magadan' => '(UTC+12:00) Magadan',
152+
'Pacific/Marshall_Is' => '(UTC+12:00) Marshall Is.',
153+
'Asia/New_Caledonia' => '(UTC+12:00) New Caledonia',
154+
'Asia/Solomon_Is' => '(UTC+12:00) Solomon Is.',
155+
'Pacific/Wellington' => '(UTC+12:00) Wellington',
156+
'Pacific/Tongatapu' => '(UTC+13:00) Nuku\'alofa'
157+
],
158+
'placeholder' => 'Choose a timezone...'
159+
]);
160+
161+
$this->execute(\Directus\phinx_update(
162+
$this->getAdapter(),
163+
'directus_fields',
164+
['options' => $options],
165+
['collection' => 'directus_users', 'field' => 'timezone']
166+
));
167+
}
168+
}

public/.htaccess

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@ Options +SymLinksIfOwnerMatch
2323
<IfModule mod_php7.c>
2424
php_value upload_max_filesize 50M
2525
php_value post_max_size 100M
26-
</IfModule>
26+
</IfModule>

public/thumbnail/index.php

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@
4343
if (!$image) {
4444
// now we can create the thumb
4545
switch ($thumbnailer->action) {
46-
// http://image.intervention.io/api/resize
46+
// http://image.intervention.io/api/resize
4747
case 'contain':
4848
$image = $thumbnailer->contain();
4949
break;
50-
// http://image.intervention.io/api/fit
50+
// http://image.intervention.io/api/fit
5151
case 'crop':
5252
default:
5353
$image = $thumbnailer->crop();
@@ -58,13 +58,14 @@
5858
header('Content-type: ' . $thumbnailer->getThumbnailMimeType());
5959
header("Pragma: cache");
6060
header('Cache-Control: max-age=' . $timeToLive);
61-
header('Last-Modified: '. gmdate('D, d M Y H:i:s \G\M\T', time()));
62-
header('Expires: '. gmdate('D, d M Y H:i:s \G\M\T', time() + $timeToLive));
61+
header("Access-Control-Allow-Origin: *");
62+
header("Access-Control-Allow-Methods: PUT, GET, POST, DELETE, OPTIONS");
63+
header("Access-Control-Allow-Headers: Access-Control-Allow-Headers,Content-Type");
64+
header('Last-Modified: ' . gmdate('D, d M Y H:i:s \G\M\T', time()));
65+
header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time() + $timeToLive));
6366
echo $image;
6467
exit(0);
65-
}
66-
67-
catch (Exception $e) {
68+
} catch (Exception $e) {
6869
$filePath = ArrayUtils::get($settings, 'thumbnail_not_found_location');
6970
if (is_string($filePath) && !empty($filePath) && $filePath[0] !== '/') {
7071
$filePath = $basePath . '/' . $filePath;

public/uploads/_/originals/.htaccess

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@
88
deny from all
99
</FilesMatch>
1010

11+
<IfModule mod_headers.c>
12+
<FilesMatch "\.(jpe?g|png|gif|mp3|wav|ogg|m4a|mp4|mov|wmv|avi)$">
13+
Header set Access-Control-Allow-Origin "*"
14+
Header set Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"
15+
Header set Access-Control-Allow-Headers "Access-Control-Allow-Headers,Content-Type"
16+
</FilesMatch>
17+
</IfModule>
18+
1119
# Respond with 404 if the file doesn't exists
1220
# Before the API mod_rewrite catches the request
1321
<IfModule mod_rewrite.c>

src/core/Directus/Application/Application.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class Application extends App
1313
*
1414
* @var string
1515
*/
16-
const DIRECTUS_VERSION = '2.2.1';
16+
const DIRECTUS_VERSION = '2.2.2';
1717

1818
/**
1919
* NOT USED
@@ -142,7 +142,7 @@ public function setCheckRequirementsFunction(\Closure $function)
142142
protected function createConfig(array $appConfig)
143143
{
144144
return [
145-
'settings' => ArrayUtils::pull($appConfig, 'settings', []),
145+
'settings' => $appConfig['settings'],
146146
'config' => function () use ($appConfig) {
147147
return new Config($appConfig);
148148
}

src/core/Directus/Application/CoreServicesProvider.php

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
use Directus\Authentication\Sso\Social;
1919
use Directus\Authentication\User\Provider\UserTableGatewayProvider;
2020
use Directus\Cache\Response;
21+
use Directus\Cache\Exception\InvalidCacheAdapterException;
22+
use Directus\Cache\Exception\InvalidCacheConfigurationException;
2123
use Directus\Config\StatusMapping;
2224
use Directus\Database\Connection;
2325
use Directus\Database\Exception\ConnectionFailedException;
@@ -127,12 +129,14 @@ protected function getLogger()
127129

128130
$filenameFormat = '%s.%s.log';
129131
foreach (Logger::getLevels() as $name => $level) {
132+
if ($path !== "php://stdout" && $path !== "php://stderr") {
133+
$path . '/' . sprintf($filenameFormat, strtolower($name), date('Y-m-d'));
134+
}
130135
$handler = new StreamHandler(
131-
$path . '/' . sprintf($filenameFormat, strtolower($name), date('Y-m-d')),
136+
$path,
132137
$level,
133138
false
134139
);
135-
136140
$handler->setFormatter($formatter);
137141
$logger->pushHandler($handler);
138142
}
@@ -542,7 +546,7 @@ protected function getEmitter()
542546
];
543547
// Authenticated user can see their private info
544548
// Admin can see all users private info
545-
if (!$acl->isAdmin() && $userId !== (int)$row['id']) {
549+
if (!$acl->isAdmin() && $userId !== (int) $row['id']) {
546550
$omit = array_merge($omit, [
547551
'token',
548552
'email_notifications',
@@ -894,7 +898,7 @@ protected function getCache()
894898
$pool = $poolConfig;
895899
} else {
896900
if (!in_array($poolConfig['adapter'], ['apc', 'apcu', 'array', 'filesystem', 'memcached', 'memcache', 'redis', 'void'])) {
897-
throw new \Exception("Valid cache adapters are 'apc', 'apcu', 'filesystem', 'memcached', 'memcache', 'redis'");
901+
throw new InvalidCacheAdapterException();
898902
}
899903

900904
$pool = new VoidCachePool();
@@ -915,7 +919,7 @@ protected function getCache()
915919

916920
if ($adapter == 'filesystem') {
917921
if (empty($poolConfig['path']) || !is_string($poolConfig['path'])) {
918-
throw new \Exception('"cache.pool.path parameter is required for "filesystem" adapter and must be a string');
922+
throw new InvalidCacheConfigurationException($adapter);
919923
}
920924

921925
$cachePath = $poolConfig['path'];
@@ -931,6 +935,15 @@ protected function getCache()
931935
}
932936

933937
if ($adapter == 'memcached' || $adapter == 'memcache') {
938+
939+
if ($adapter == 'memcached' && !extension_loaded('memcached')) {
940+
throw new InvalidCacheConfigurationException($adapter);
941+
}
942+
943+
if ($adapter == 'memcache' && !extension_loaded('memcache')) {
944+
throw new InvalidCacheConfigurationException($adapter);
945+
}
946+
934947
$client = $adapter == 'memcached' ? new \Memcached() : new \Memcache();
935948
if (isset($poolConfig['url'])) {
936949
$urls = explode(';', $poolConfig['url']);
@@ -954,6 +967,11 @@ protected function getCache()
954967
}
955968

956969
if ($adapter == 'redis') {
970+
971+
if (!extension_loaded('redis')) {
972+
throw new InvalidCacheConfigurationException($adapter);
973+
}
974+
957975
$host = (isset($poolConfig['host'])) ? $poolConfig['host'] : 'localhost';
958976
$port = (isset($poolConfig['port'])) ? $poolConfig['port'] : 6379;
959977
$socket = (isset($poolConfig['socket'])) ? $poolConfig['socket'] : null;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace Directus\Authentication\Exception;
4+
5+
use Directus\Exception\NotFoundException;
6+
7+
class UserSuspendedException extends NotFoundException
8+
{
9+
const ERROR_CODE = 103;
10+
11+
public function __construct()
12+
{
13+
parent::__construct('Your account is suspended due to maximum allowed login attempts. Please contact your administrator to activate your account.', static::ERROR_CODE);
14+
}
15+
}

0 commit comments

Comments
 (0)