silverstripe-framework/src/Security/CMSMemberLoginForm.php

187 lines
6.2 KiB
PHP
Raw Normal View History

<?php
2016-06-23 01:37:22 +02:00
namespace SilverStripe\Security;
2016-09-09 08:43:05 +02:00
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Core\Convert;
use SilverStripe\Control\Controller;
use SilverStripe\Control\Session;
use SilverStripe\Forms\HiddenField;
use SilverStripe\Forms\PasswordField;
use SilverStripe\Forms\LiteralField;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\CheckboxField;
use SilverStripe\Forms\FormAction;
2016-06-23 01:37:22 +02:00
/**
* Provides the in-cms session re-authentication form for the "member" authenticator
*/
2016-11-29 00:31:16 +01:00
class CMSMemberLoginForm extends LoginForm
{
protected $authenticator_class = 'SilverStripe\\Security\\MemberAuthenticator';
/**
* Get link to use for external security actions
*
* @param string $action Action
* @return string
*/
public function getExternalLink($action = null)
{
return Security::create()->Link($action);
}
public function __construct(Controller $controller, $name)
{
// Set default fields
$fields = new FieldList(
HiddenField::create("AuthenticationMethod", null, $this->authenticator_class, $this),
HiddenField::create('tempid', null, $controller->getRequest()->requestVar('tempid')),
PasswordField::create("Password", _t('Member.PASSWORD', 'Password')),
LiteralField::create(
'forgotPassword',
sprintf(
'<p id="ForgotPassword"><a href="%s" target="_top">%s</a></p>',
$this->getExternalLink('lostpassword'),
_t('CMSMemberLoginForm.BUTTONFORGOTPASSWORD', "Forgot password?")
)
)
);
if (Security::config()->autologin_enabled) {
$fields->push(CheckboxField::create(
"Remember",
_t('Member.REMEMBERME', "Remember me next time?")
));
}
// Determine returnurl to redirect to parent page
$logoutLink = $this->getExternalLink('logout');
if ($returnURL = $controller->getRequest()->requestVar('BackURL')) {
$logoutLink = Controller::join_links($logoutLink, '?BackURL='.urlencode($returnURL));
}
// Make actions
$actions = new FieldList(
FormAction::create('dologin', _t('CMSMemberLoginForm.BUTTONLOGIN', "Log back in")),
LiteralField::create(
'doLogout',
sprintf(
'<p id="doLogout"><a href="%s" target="_top">%s</a></p>',
$logoutLink,
_t('CMSMemberLoginForm.BUTTONLOGOUT', "Log out")
)
)
);
parent::__construct($controller, $name, $fields, $actions);
}
/**
* Try to authenticate the user
*
* @param array $data Submitted data
* @return Member Returns the member object on successful authentication
* or NULL on failure.
*/
public function performLogin($data)
{
$authenticator = $this->authenticator_class;
/** @var Member $member */
$member = $authenticator::authenticate($data, $this);
if ($member) {
$member->logIn(isset($data['Remember']));
return $member;
}
$this->extend('authenticationFailed', $data);
return null;
}
/**
* Login form handler method
*
* This method is called when the user clicks on "Log in"
*
* @param array $data Submitted data
* @return HTTPResponse
*/
public function dologin($data)
{
if ($this->performLogin($data)) {
return $this->logInUserAndRedirect($data);
} else {
// Find best url to redirect back to
$request = $this->controller->getRequest();
$url = $request->getHeader('X-Backurl')
?: $request->getHeader('Referer')
?: $this->controller->Link('login');
return $this->controller->redirect($url);
}
}
/**
* Redirect the user to the change password form.
*
* @return HTTPResponse
*/
protected function redirectToChangePassword()
{
// Since this form is loaded via an iframe, this redirect must be performed via javascript
$changePasswordForm = new ChangePasswordForm($this->controller, 'SilverStripe\\Security\\ChangePasswordForm');
$changePasswordForm->sessionMessage(
_t('Member.PASSWORDEXPIRED', 'Your password has expired. Please choose a new one.'),
'good'
);
// Get redirect url
$changePasswordURL = $this->getExternalLink('changepassword');
if ($backURL = $this->controller->getRequest()->requestVar('BackURL')) {
Session::set('BackURL', $backURL);
$changePasswordURL = Controller::join_links($changePasswordURL, '?BackURL=' . urlencode($backURL));
}
$changePasswordURLATT = Convert::raw2att($changePasswordURL);
$changePasswordURLJS = Convert::raw2js($changePasswordURL);
$message = _t(
'CMSMemberLoginForm.PASSWORDEXPIRED',
'<p>Your password has expired. <a target="_top" href="{link}">Please choose a new one.</a></p>',
'Message displayed to user if their session cannot be restored',
array('link' => $changePasswordURLATT)
);
// Redirect to change password page
$this->controller->getResponse()->setStatusCode(200);
$this->controller->getResponse()->setBody(<<<PHP
<!DOCTYPE html>
<html><body>
$message
2016-01-24 06:12:45 +01:00
<script type="application/javascript">
setTimeout(function(){top.location.href = "$changePasswordURLJS";}, 0);
</script>
</body></html>
PHP
2016-11-29 00:31:16 +01:00
);
return $this->controller->getResponse();
}
/**
* Send user to the right location after login
*
* @param array $data
* @return HTTPResponse
*/
protected function logInUserAndRedirect($data)
{
// Check password expiry
if (Member::currentUser()->isPasswordExpired()) {
// Redirect the user to the external password change form if necessary
return $this->redirectToChangePassword();
} else {
// Link to success template
$url = $this->controller->Link('success');
return $this->controller->redirect($url);
}
}
}