Improve the default LoginForm

- has the fields and actions extracted to a separate method, so it's more easily overridable
- Moved the global variable $_REQUEST to getting the info from the controller
- Updated string variables to `::class`
- Updated RequiredFields to be set in the YML, so it's overridable/updatable from either Config or code
This commit is contained in:
Simon Erkelens 2017-04-14 16:21:38 +12:00 committed by Sam Minnée
parent 8ad9207d85
commit 3f1f9d04b7
3 changed files with 79 additions and 51 deletions

4
_config/security.yml Normal file
View File

@ -0,0 +1,4 @@
SilverStripe\Security\MemberLoginForm:
required_fields:
- Email
- Password

View File

@ -22,7 +22,7 @@ abstract class Authenticator extends Object
*
* @var array
*/
private static $authenticators = array('SilverStripe\\Security\\MemberAuthenticator');
private static $authenticators = array(MemberAuthenticator::class);
/**
* Used to influence the order of authenticators on the login-screen
@ -30,7 +30,7 @@ abstract class Authenticator extends Object
*
* @var string
*/
private static $default_authenticator = 'SilverStripe\\Security\\MemberAuthenticator';
private static $default_authenticator = MemberAuthenticator::class;
/**
@ -113,7 +113,7 @@ abstract class Authenticator extends Object
return false;
}
if (is_subclass_of($authenticator, 'SilverStripe\\Security\\Authenticator') == false) {
if (is_subclass_of($authenticator, self::class) == false) {
return false;
}

View File

@ -35,6 +35,12 @@ class MemberLoginForm extends LoginForm
*/
public $loggedInAsField = 'FirstName';
/**
* Required fields for validation
* @var array
*/
private static $required_fields;
/**
* Constructor
*
@ -69,8 +75,8 @@ class MemberLoginForm extends LoginForm
Requirements::css($customCSS);
}
if (isset($_REQUEST['BackURL'])) {
$backURL = $_REQUEST['BackURL'];
if ($controller->request->getVar('BackURL')) {
$backURL = $controller->request->getVar('BackURL');
} else {
$backURL = Session::get('BackURL');
}
@ -84,45 +90,10 @@ class MemberLoginForm extends LoginForm
);
} else {
if (!$fields) {
$label = Member::singleton()->fieldLabel(Member::config()->unique_identifier_field);
$fields = FieldList::create(
HiddenField::create("AuthenticationMethod", null, $this->authenticator_class, $this),
// Regardless of what the unique identifer field is (usually 'Email'), it will be held in the
// 'Email' value, below:
$emailField = TextField::create("Email", $label, null, null, $this),
PasswordField::create("Password", _t('Member.PASSWORD', 'Password'))
);
if (Security::config()->remember_username) {
$emailField->setValue(Session::get('SessionForms.MemberLoginForm.Email'));
} else {
// Some browsers won't respect this attribute unless it's added to the form
$this->setAttribute('autocomplete', 'off');
$emailField->setAttribute('autocomplete', 'off');
}
if (Security::config()->autologin_enabled) {
$fields->push(
CheckboxField::create(
"Remember",
_t('Member.KEEPMESIGNEDIN', "Keep me signed in")
)->setAttribute(
'title',
sprintf(
_t('Member.REMEMBERME', "Remember me next time? (for %d days on this device)"),
RememberLoginHash::config()->uninherited('token_expiry_days')
)
)
);
}
$fields = $this->getFormFields();
}
if (!$actions) {
$actions = FieldList::create(
FormAction::create('dologin', _t('Member.BUTTONLOGIN', "Log in")),
LiteralField::create(
'forgotPassword',
'<p id="ForgotPassword"><a href="' . Security::lost_password_url() . '">'
. _t('Member.BUTTONLOSTPASSWORD', "I've lost my password") . '</a></p>'
)
);
$actions = $this->getFormActions();
}
}
@ -135,16 +106,69 @@ class MemberLoginForm extends LoginForm
parent::__construct($controller, $name, $fields, $actions);
$this->setValidator(RequiredFields::create('Email', 'Password'));
$this->setValidator(RequiredFields::create(self::config()->get('required_fields')));
}
// Focus on the email input when the page is loaded
$js = <<<JS
(function() {
var el = document.getElementById("MemberLoginForm_LoginForm_Email");
if(el && el.focus && (typeof jQuery == 'undefined' || jQuery(el).is(':visible'))) el.focus();
})();
JS;
Requirements::customScript($js, 'MemberLoginFormFieldFocus');
/**
* Build the FieldList for the login form
*
* @return FieldList
*/
protected function getFormFields()
{
$label = Member::singleton()->fieldLabel(Member::config()->unique_identifier_field);
$fields = FieldList::create(
HiddenField::create("AuthenticationMethod", null, $this->authenticator_class, $this),
// Regardless of what the unique identifer field is (usually 'Email'), it will be held in the
// 'Email' value, below:
// @todo Rename the field to a more generic covering name
$emailField = TextField::create("Email", $label, null, null, $this),
PasswordField::create("Password", _t('Member.PASSWORD', 'Password'))
);
$emailField->setAttribute('autofocus', 'true');
if (Security::config()->remember_username) {
$emailField->setValue(Session::get('SessionForms.MemberLoginForm.Email'));
} else {
// Some browsers won't respect this attribute unless it's added to the form
$this->setAttribute('autocomplete', 'off');
$emailField->setAttribute('autocomplete', 'off');
}
if (Security::config()->autologin_enabled) {
$fields->push(
CheckboxField::create(
"Remember",
_t('Member.KEEPMESIGNEDIN', "Keep me signed in")
)->setAttribute(
'title',
sprintf(
_t('Member.REMEMBERME', "Remember me next time? (for %d days on this device)"),
RememberLoginHash::config()->uninherited('token_expiry_days')
)
)
);
}
return $fields;
}
/**
* Build default login form action FieldList
*
* @return FieldList
*/
protected function getFormActions()
{
$actions = FieldList::create(
FormAction::create('dologin', _t('Member.BUTTONLOGIN', "Log in")),
LiteralField::create(
'forgotPassword',
'<p id="ForgotPassword"><a href="' . Security::lost_password_url() . '">'
. _t('Member.BUTTONLOSTPASSWORD', "I've lost my password") . '</a></p>'
)
);
return $actions;
}
public function restoreFormState()