mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge branch '3.5.5' into 3.6.2
This commit is contained in:
commit
bd7abc73de
27
docs/en/04_Changelogs/beta/3.5.5-beta1.md
Normal file
27
docs/en/04_Changelogs/beta/3.5.5-beta1.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# 3.5.5-beta1
|
||||||
|
|
||||||
|
<!--- Changes below this line will be automatically regenerated -->
|
||||||
|
|
||||||
|
## Change Log
|
||||||
|
|
||||||
|
### Bugfixes
|
||||||
|
|
||||||
|
* 2017-08-28 [7b200a2](https://github.com/silverstripe/silverstripe-framework/commit/7b200a2a642a78bffcf0a2f417a4757fb216ecfb) add combinedFiles to clear logic (Christopher Joe)
|
||||||
|
* 2017-08-16 [eb80a5f](https://github.com/silverstripe/silverstripe-framework/commit/eb80a5f9e89e69480edc7f1c9c66cc7403f547f1) LastEdited no longer updated on skipped writes (Daniel Hensby)
|
||||||
|
* 2017-08-14 [b04a1ab](https://github.com/silverstripe/silverstripe-framework/commit/b04a1ab41c4051923e9d9a9af5dedfa5a3ef67d8) Truncate Error Issue when using views in a Unittest. (James Pluck)
|
||||||
|
* 2017-07-26 [31c5eeb](https://github.com/silverstripe/silverstripe-framework/commit/31c5eebda089867d61546106b36ca20b21a00026) Avoid JS errors for HTMLEditorFields in small holders (Daniel Hensby)
|
||||||
|
* 2017-07-26 [82c0632](https://github.com/silverstripe/silverstripe-framework/commit/82c0632f46e00a251d287811652429036d200eff) Use Config API for MemberAuthenticator::$migrate_legacy_hashes (fixes #7208) (Loz Calver)
|
||||||
|
* 2017-07-19 [292aaf6](https://github.com/silverstripe/silverstripe-framework/commit/292aaf65301b2be4bb5e6e1505ccbe98b8ade67f) Cache IDs grouped by site first (Daniel Hensby)
|
||||||
|
* 2017-07-18 [b77274c](https://github.com/silverstripe/silverstripe-framework/commit/b77274c1a3c3ab8cfa0abf939aa2e4735e534171) Add unique prefix to cache stores to prevent cache leak (Daniel Hensby)
|
||||||
|
* 2017-07-17 [515a7cb](https://github.com/silverstripe/silverstripe-cms/commit/515a7cb569f0cf90787b44fca8845760b539fabe) Make sure VirtualPage renders correct templates (Daniel Hensby)
|
||||||
|
* 2017-07-06 [a6db16b](https://github.com/silverstripe/silverstripe-framework/commit/a6db16b2298738e1ef1329329cbef7c6b33f993e) OS X issue with `Convert::html2raw`, `HTMLText::FirstSentence`, `HTMLText::Summary` and `Text::FirstSentence`. (Roman Schmid)
|
||||||
|
* 2017-06-29 [79a7b10](https://github.com/silverstripe/silverstripe-framework/commit/79a7b1016e6046af4f07fcd8bfb40773d1066b7e) add missing $rootCall param from LeftAndMain (Daniel Hensby)
|
||||||
|
* 2017-06-20 [e2116a7](https://github.com/silverstripe/silverstripe-framework/commit/e2116a70ef34433bfe712b4164ae416a76d4430d) Text colour in GridField filter headers for dropdown fields (Robbie Averill)
|
||||||
|
* 2017-06-14 [2afe018](https://github.com/silverstripe/silverstripe-framework/commit/2afe018dc7e380ac84f8e1f7986ce0247e9a254b) Ensure HasManyList foreign ID filter includes table name (fixes #7023) (Loz Calver)
|
||||||
|
* 2017-06-12 [53c84d9](https://github.com/silverstripe/silverstripe-framework/commit/53c84d93da0f0681fdcb3a061ebe529fd3cd9a9e) changetracker checkbox bugs (Brian Cairns)
|
||||||
|
* 2017-06-12 [a5c84b1](https://github.com/silverstripe/silverstripe-framework/commit/a5c84b12ab3c0759f696fc48fee3475bab6b3e20) Order of conditionals for getting default admin (Daniel Hensby)
|
||||||
|
* 2017-06-06 [4ad2cae](https://github.com/silverstripe/silverstripe-framework/commit/4ad2cae8642d21e37b5132e4040ca45d2d66c193) Upload_Validator failed to fetch max size from PHP ini values (fixes #6999) (Loz Calver)
|
||||||
|
* 2017-06-05 [5f5bfa5](https://github.com/silverstripe/silverstripe-framework/commit/5f5bfa5e7045cc96f89fca417f0a7d99dc662fab) create temp folder if it does not exist (Christopher Joe)
|
||||||
|
* 2017-06-02 [4b9d5dc](https://github.com/silverstripe/silverstripe-framework/commit/4b9d5dceb892a9c41925d058d953a8849b407276) tinymce image selection issue in newer versions of Chrome (Christopher Joe)
|
||||||
|
* 2017-05-29 [b436819](https://github.com/silverstripe/silverstripe-framework/commit/b4368196d1bcee9fd1714b044c8ae6580c7941c9) Use plural name for ModelAdmin tab name (Robbie Averill)
|
||||||
|
* 2017-05-09 [3dd3036](https://github.com/silverstripe/silverstripe-framework/commit/3dd3036792962d5384a72aa0132a64aca7d2ebc2) Ensure GridState_Component is added to GridField config even if we set config with GridField::setConfig (Klemen Dolinsek)
|
33
docs/en/04_Changelogs/beta/3.5.5-beta2.md
Normal file
33
docs/en/04_Changelogs/beta/3.5.5-beta2.md
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# 3.5.5-beta2
|
||||||
|
|
||||||
|
<!--- Changes below this line will be automatically regenerated -->
|
||||||
|
|
||||||
|
## Change Log
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
* 2017-09-04 [f0262a8](https://github.com/silverstripe/silverstripe-framework/commit/f0262a8fd9ab5fb51b178ace3c3487351217f5a0) User enumeration via timing attack mitigated (Daniel Hensby) - See [ss-2017-005](http://www.silverstripe.org/download/security-releases/ss-2017-005)
|
||||||
|
|
||||||
|
### Bugfixes
|
||||||
|
|
||||||
|
* 2017-09-12 [0aac4dd](https://github.com/silverstripe/silverstripe-cms/commit/0aac4ddb7ecf0f17eda8add235017c10c9f57255) Default LoginForm generated from default_authenticator (Daniel Hensby)
|
||||||
|
* 2017-09-12 [091d99f](https://github.com/silverstripe/silverstripe-framework/commit/091d99f599dcacf6aef2ad1df48311c2399f150c) Authenticators are more resilient to incomplete configuration (Daniel Hensby)
|
||||||
|
* 2017-08-28 [7b200a2](https://github.com/silverstripe/silverstripe-framework/commit/7b200a2a642a78bffcf0a2f417a4757fb216ecfb) add combinedFiles to clear logic (Christopher Joe)
|
||||||
|
* 2017-08-16 [eb80a5f](https://github.com/silverstripe/silverstripe-framework/commit/eb80a5f9e89e69480edc7f1c9c66cc7403f547f1) LastEdited no longer updated on skipped writes (Daniel Hensby)
|
||||||
|
* 2017-08-14 [b04a1ab](https://github.com/silverstripe/silverstripe-framework/commit/b04a1ab41c4051923e9d9a9af5dedfa5a3ef67d8) Truncate Error Issue when using views in a Unittest. (James Pluck)
|
||||||
|
* 2017-07-26 [31c5eeb](https://github.com/silverstripe/silverstripe-framework/commit/31c5eebda089867d61546106b36ca20b21a00026) Avoid JS errors for HTMLEditorFields in small holders (Daniel Hensby)
|
||||||
|
* 2017-07-26 [82c0632](https://github.com/silverstripe/silverstripe-framework/commit/82c0632f46e00a251d287811652429036d200eff) Use Config API for MemberAuthenticator::$migrate_legacy_hashes (fixes #7208) (Loz Calver)
|
||||||
|
* 2017-07-19 [292aaf6](https://github.com/silverstripe/silverstripe-framework/commit/292aaf65301b2be4bb5e6e1505ccbe98b8ade67f) Cache IDs grouped by site first (Daniel Hensby)
|
||||||
|
* 2017-07-18 [b77274c](https://github.com/silverstripe/silverstripe-framework/commit/b77274c1a3c3ab8cfa0abf939aa2e4735e534171) Add unique prefix to cache stores to prevent cache leak (Daniel Hensby)
|
||||||
|
* 2017-07-17 [515a7cb](https://github.com/silverstripe/silverstripe-cms/commit/515a7cb569f0cf90787b44fca8845760b539fabe) Make sure VirtualPage renders correct templates (Daniel Hensby)
|
||||||
|
* 2017-07-06 [a6db16b](https://github.com/silverstripe/silverstripe-framework/commit/a6db16b2298738e1ef1329329cbef7c6b33f993e) OS X issue with `Convert::html2raw`, `HTMLText::FirstSentence`, `HTMLText::Summary` and `Text::FirstSentence`. (Roman Schmid)
|
||||||
|
* 2017-06-29 [79a7b10](https://github.com/silverstripe/silverstripe-framework/commit/79a7b1016e6046af4f07fcd8bfb40773d1066b7e) add missing $rootCall param from LeftAndMain (Daniel Hensby)
|
||||||
|
* 2017-06-20 [e2116a7](https://github.com/silverstripe/silverstripe-framework/commit/e2116a70ef34433bfe712b4164ae416a76d4430d) Text colour in GridField filter headers for dropdown fields (Robbie Averill)
|
||||||
|
* 2017-06-14 [2afe018](https://github.com/silverstripe/silverstripe-framework/commit/2afe018dc7e380ac84f8e1f7986ce0247e9a254b) Ensure HasManyList foreign ID filter includes table name (fixes #7023) (Loz Calver)
|
||||||
|
* 2017-06-12 [53c84d9](https://github.com/silverstripe/silverstripe-framework/commit/53c84d93da0f0681fdcb3a061ebe529fd3cd9a9e) changetracker checkbox bugs (Brian Cairns)
|
||||||
|
* 2017-06-12 [a5c84b1](https://github.com/silverstripe/silverstripe-framework/commit/a5c84b12ab3c0759f696fc48fee3475bab6b3e20) Order of conditionals for getting default admin (Daniel Hensby)
|
||||||
|
* 2017-06-06 [4ad2cae](https://github.com/silverstripe/silverstripe-framework/commit/4ad2cae8642d21e37b5132e4040ca45d2d66c193) Upload_Validator failed to fetch max size from PHP ini values (fixes #6999) (Loz Calver)
|
||||||
|
* 2017-06-05 [5f5bfa5](https://github.com/silverstripe/silverstripe-framework/commit/5f5bfa5e7045cc96f89fca417f0a7d99dc662fab) create temp folder if it does not exist (Christopher Joe)
|
||||||
|
* 2017-06-02 [4b9d5dc](https://github.com/silverstripe/silverstripe-framework/commit/4b9d5dceb892a9c41925d058d953a8849b407276) tinymce image selection issue in newer versions of Chrome (Christopher Joe)
|
||||||
|
* 2017-05-29 [b436819](https://github.com/silverstripe/silverstripe-framework/commit/b4368196d1bcee9fd1714b044c8ae6580c7941c9) Use plural name for ModelAdmin tab name (Robbie Averill)
|
||||||
|
* 2017-05-09 [3dd3036](https://github.com/silverstripe/silverstripe-framework/commit/3dd3036792962d5384a72aa0132a64aca7d2ebc2) Ensure GridState_Component is added to GridField config even if we set config with GridField::setConfig (Klemen Dolinsek)
|
@ -102,9 +102,12 @@ abstract class Authenticator extends Object {
|
|||||||
if(is_subclass_of($authenticator, 'Authenticator') == false)
|
if(is_subclass_of($authenticator, 'Authenticator') == false)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(in_array($authenticator, self::$authenticators) == false) {
|
$authenticators = Config::inst()->get(__CLASS__, 'authenticators');
|
||||||
|
if(in_array($authenticator, $authenticators) == false) {
|
||||||
if(call_user_func(array($authenticator, 'on_register')) === true) {
|
if(call_user_func(array($authenticator, 'on_register')) === true) {
|
||||||
array_push(self::$authenticators, $authenticator);
|
Config::inst()->update(__CLASS__, 'authenticators', array(
|
||||||
|
$authenticator,
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -125,8 +128,11 @@ abstract class Authenticator extends Object {
|
|||||||
*/
|
*/
|
||||||
public static function unregister_authenticator($authenticator) {
|
public static function unregister_authenticator($authenticator) {
|
||||||
if(call_user_func(array($authenticator, 'on_unregister')) === true) {
|
if(call_user_func(array($authenticator, 'on_unregister')) === true) {
|
||||||
if(in_array($authenticator, self::$authenticators)) {
|
$authenticators = Config::inst()->get(__CLASS__, 'authenticators');
|
||||||
unset(self::$authenticators[array_search($authenticator, self::$authenticators)]);
|
if(($key = array_search($authenticator, $authenticators)) !== false) {
|
||||||
|
unset($authenticators[$key]);
|
||||||
|
Config::inst()->remove(__CLASS__, 'authenticators');
|
||||||
|
Config::inst()->update(__CLASS__, 'authenticators', $authenticators);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,7 +146,7 @@ abstract class Authenticator extends Object {
|
|||||||
* otherwise.
|
* otherwise.
|
||||||
*/
|
*/
|
||||||
public static function is_registered($authenticator) {
|
public static function is_registered($authenticator) {
|
||||||
return in_array($authenticator, self::$authenticators);
|
return in_array($authenticator, Config::inst()->get(__CLASS__, 'authenticators'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -151,13 +157,16 @@ abstract class Authenticator extends Object {
|
|||||||
* authenticators.
|
* authenticators.
|
||||||
*/
|
*/
|
||||||
public static function get_authenticators() {
|
public static function get_authenticators() {
|
||||||
// put default authenticator first (mainly for tab-order on loginform)
|
$authenticators = Config::inst()->get(__CLASS__, 'authenticators');
|
||||||
if($key = array_search(self::$default_authenticator,self::$authenticators)) {
|
$defaultAuthenticator = Config::inst()->get(__CLASS__, 'default_authenticator');
|
||||||
unset(self::$authenticators[$key]);
|
|
||||||
array_unshift(self::$authenticators, self::$default_authenticator);
|
// put default authenticator first if it isn't already
|
||||||
|
if (reset($authenticators) !== $defaultAuthenticator && ($key = array_search($defaultAuthenticator, $authenticators)) !== false) {
|
||||||
|
unset($authenticators[$key]);
|
||||||
|
array_unshift($authenticators, $defaultAuthenticator);
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::$authenticators;
|
return $authenticators;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -175,7 +184,9 @@ abstract class Authenticator extends Object {
|
|||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function get_default_authenticator() {
|
public static function get_default_authenticator() {
|
||||||
return self::$default_authenticator;
|
$authenticators = static::get_authenticators();
|
||||||
|
// the first authenticator is the default one
|
||||||
|
return reset($authenticators);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,9 +18,18 @@ abstract class LoginForm extends Form {
|
|||||||
* form.
|
* form.
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
|
|
||||||
protected $authenticator_class;
|
protected $authenticator_class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum amount of time authenticating is allowed to take in milliseconds.
|
||||||
|
*
|
||||||
|
* Protects against timing enumeration attacks
|
||||||
|
*
|
||||||
|
* @config
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private static $min_auth_time = 350;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the authenticator instance
|
* Get the authenticator instance
|
||||||
*
|
*
|
||||||
@ -44,5 +53,15 @@ abstract class LoginForm extends Form {
|
|||||||
return $authClass::get_name();
|
return $authClass::get_name();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setAuthenticatorClass($class)
|
||||||
|
{
|
||||||
|
$this->authenticator_class = $class;
|
||||||
|
$authenticatorField = $this->Fields()->dataFieldByName('AuthenticationMethod');
|
||||||
|
if ($authenticatorField) {
|
||||||
|
$authenticatorField->setValue($class);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,6 +150,10 @@ class MemberAuthenticator extends Authenticator {
|
|||||||
* @see Security::setDefaultAdmin()
|
* @see Security::setDefaultAdmin()
|
||||||
*/
|
*/
|
||||||
public static function authenticate($data, Form $form = null) {
|
public static function authenticate($data, Form $form = null) {
|
||||||
|
// minimum execution time for authenticating a member
|
||||||
|
$minExecTime = LoginForm::config()->min_auth_time / 1000;
|
||||||
|
$startTime = microtime(true);
|
||||||
|
|
||||||
// Find authenticated member
|
// Find authenticated member
|
||||||
$member = static::authenticate_member($data, $form, $success);
|
$member = static::authenticate_member($data, $form, $success);
|
||||||
|
|
||||||
@ -170,6 +174,11 @@ class MemberAuthenticator extends Authenticator {
|
|||||||
|
|
||||||
if($success) Session::clear('BackURL');
|
if($success) Session::clear('BackURL');
|
||||||
|
|
||||||
|
$waitFor = $minExecTime - (microtime(true) - $startTime);
|
||||||
|
if ($waitFor > 0) {
|
||||||
|
usleep($waitFor * 1000000);
|
||||||
|
}
|
||||||
|
|
||||||
return $success ? $member : null;
|
return $success ? $member : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,14 +188,18 @@ class MemberAuthenticator extends Authenticator {
|
|||||||
*
|
*
|
||||||
* @param Controller The parent controller, necessary to create the
|
* @param Controller The parent controller, necessary to create the
|
||||||
* appropriate form action tag
|
* appropriate form action tag
|
||||||
* @return Form Returns the login form to use with this authentication
|
* @return MemberLoginForm Returns the login form to use with this authentication
|
||||||
* method
|
* method
|
||||||
*/
|
*/
|
||||||
public static function get_login_form(Controller $controller) {
|
public static function get_login_form(Controller $controller) {
|
||||||
return MemberLoginForm::create($controller, "LoginForm");
|
return MemberLoginForm::create($controller, "LoginForm");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function get_cms_login_form(\Controller $controller) {
|
/**
|
||||||
|
* @param Controller $controller
|
||||||
|
* @return CMSMemberLoginForm
|
||||||
|
*/
|
||||||
|
public static function get_cms_login_form(Controller $controller) {
|
||||||
return CMSMemberLoginForm::create($controller, "LoginForm");
|
return CMSMemberLoginForm::create($controller, "LoginForm");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,6 +294,10 @@ JS;
|
|||||||
* @param array $data Submitted data
|
* @param array $data Submitted data
|
||||||
*/
|
*/
|
||||||
public function forgotPassword($data) {
|
public function forgotPassword($data) {
|
||||||
|
// minimum execution time for authenticating a member
|
||||||
|
$minExecTime = self::config()->min_auth_time / 1000;
|
||||||
|
$startTime = microtime(true);
|
||||||
|
|
||||||
// Ensure password is given
|
// Ensure password is given
|
||||||
if(empty($data['Email'])) {
|
if(empty($data['Email'])) {
|
||||||
$this->sessionMessage(
|
$this->sessionMessage(
|
||||||
@ -311,10 +315,8 @@ JS;
|
|||||||
// Allow vetoing forgot password requests
|
// Allow vetoing forgot password requests
|
||||||
$results = $this->extend('forgotPassword', $member);
|
$results = $this->extend('forgotPassword', $member);
|
||||||
if($results && is_array($results) && in_array(false, $results, true)) {
|
if($results && is_array($results) && in_array(false, $results, true)) {
|
||||||
return $this->controller->redirect('Security/lostpassword');
|
$this->controller->redirect('Security/lostpassword');
|
||||||
}
|
} elseif ($member) {
|
||||||
|
|
||||||
if($member) {
|
|
||||||
$token = $member->generateAutologinTokenAndStoreHash();
|
$token = $member->generateAutologinTokenAndStoreHash();
|
||||||
|
|
||||||
$e = Member_ForgotPasswordEmail::create();
|
$e = Member_ForgotPasswordEmail::create();
|
||||||
@ -338,6 +340,10 @@ JS;
|
|||||||
|
|
||||||
$this->controller->redirect('Security/lostpassword');
|
$this->controller->redirect('Security/lostpassword');
|
||||||
}
|
}
|
||||||
|
$waitFor = $minExecTime - (microtime(true) - $startTime);
|
||||||
|
if ($waitFor > 0) {
|
||||||
|
usleep($waitFor * 1000000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -221,4 +221,10 @@ class MemberAuthenticatorTest extends SapphireTest {
|
|||||||
$this->assertTrue($member->isLockedOut());
|
$this->assertTrue($member->isLockedOut());
|
||||||
$this->assertFalse($member->canLogIn()->valid());
|
$this->assertFalse($member->canLogIn()->valid());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testDefaultAuthenticatorWontReturnIfDisabled()
|
||||||
|
{
|
||||||
|
Authenticator::unregister('MemberAuthenticator');
|
||||||
|
$this->assertNotEquals('MemberAuthenticator', Authenticator::get_default_authenticator());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user