Cleanup and RequestFilter refactor

This commit is contained in:
Damian Mooyman 2017-06-09 15:07:35 +12:00
parent 5fce3308b4
commit 62753b3cb1
No known key found for this signature in database
GPG Key ID: 78B823A10DE27D1A
31 changed files with 337 additions and 335 deletions

View File

@ -1,16 +1,7 @@
--- ---
Name: coresecurity Name: coreauthentication
--- ---
SilverStripe\Security\MemberAuthenticator\MemberLoginForm:
required_fields:
- Email
- Password
SilverStripe\Core\Injector\Injector: SilverStripe\Core\Injector\Injector:
SilverStripe\Control\RequestProcessor:
properties:
filters:
- %$SilverStripe\Security\AuthenticationRequestFilter
SilverStripe\Security\MemberAuthenticator\SessionAuthenticationHandler: SilverStripe\Security\MemberAuthenticator\SessionAuthenticationHandler:
properties: properties:
SessionVariable: loggedInAs SessionVariable: loggedInAs
@ -19,14 +10,26 @@ SilverStripe\Core\Injector\Injector:
TokenCookieName: alc_enc TokenCookieName: alc_enc
DeviceCookieName: alc_device DeviceCookieName: alc_device
CascadeInTo: %$SilverStripe\Security\MemberAuthenticator\SessionAuthenticationHandler CascadeInTo: %$SilverStripe\Security\MemberAuthenticator\SessionAuthenticationHandler
SilverStripe\Security\IdentityStore: SilverStripe\Security\AuthenticationHandler:
class: SilverStripe\Security\AuthenticationRequestFilter class: SilverStripe\Security\RequestAuthenticationHandler
properties:
Handlers:
session: %$SilverStripe\Security\MemberAuthenticator\SessionAuthenticationHandler
alc: %$SilverStripe\Security\MemberAuthenticator\CookieAuthenticationHandler
---
Name: coresecurity
---
SilverStripe\Core\Injector\Injector:
SilverStripe\Security\AuthenticationRequestFilter:
properties:
AuthenticationHandler: %$SilverStripe\Security\AuthenticationHandler
SilverStripe\Control\RequestProcessor:
properties:
filters:
- %$SilverStripe\Security\AuthenticationRequestFilter
SilverStripe\Security\Security: SilverStripe\Security\Security:
properties: properties:
authenticators: Authenticators:
default: %$SilverStripe\Security\MemberAuthenticator\MemberAuthenticator default: %$SilverStripe\Security\MemberAuthenticator\MemberAuthenticator
cms: %$SilverStripe\Security\MemberAuthenticator\CMSMemberAuthenticator cms: %$SilverStripe\Security\MemberAuthenticator\CMSMemberAuthenticator
SilverStripe\Security\AuthenticationRequestFilter: SilverStripe\Security\IdentityStore: %$SilverStripe\Security\AuthenticationHandler
handlers:
session: SilverStripe\Security\MemberAuthenticator\SessionAuthenticationHandler
alc: SilverStripe\Security\MemberAuthenticator\CookieAuthenticationHandler

View File

@ -490,6 +490,17 @@ abstract class Database
*/ */
abstract public function datetimeDifferenceClause($date1, $date2); abstract public function datetimeDifferenceClause($date1, $date2);
/**
* String operator for concatenation of strings
*
* @return string
*/
public function concatOperator()
{
// @todo Make ' + ' in mssql
return ' || ';
}
/** /**
* Returns true if this database supports collations * Returns true if this database supports collations
* *

View File

@ -3,9 +3,7 @@
namespace SilverStripe\Security; namespace SilverStripe\Security;
use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\ORM\ValidationException; use SilverStripe\ORM\ValidationException;
use SilverStripe\Security\Member;
/** /**
* An AuthenticationHandler is responsible for providing an identity (in the form of a Member object) for * An AuthenticationHandler is responsible for providing an identity (in the form of a Member object) for
@ -15,7 +13,7 @@ use SilverStripe\Security\Member;
* request it should *not* attempt to redirect the visitor to a log-in from or 3rd party handler, as that * request it should *not* attempt to redirect the visitor to a log-in from or 3rd party handler, as that
* is the responsibiltiy of other systems. * is the responsibiltiy of other systems.
*/ */
interface AuthenticationHandler interface AuthenticationHandler extends IdentityStore
{ {
/** /**
* Given the current request, authenticate the request for non-session authorization (outside the CMS). * Given the current request, authenticate the request for non-session authorization (outside the CMS).

View File

@ -2,54 +2,40 @@
namespace SilverStripe\Security; namespace SilverStripe\Security;
use SilverStripe\Control\HTTPResponse_Exception;
use SilverStripe\Control\RequestFilter;
use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse; use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\HTTPResponse_Exception;
use SilverStripe\Control\RequestFilter;
use SilverStripe\Control\Session; use SilverStripe\Control\Session;
use SilverStripe\Dev\Debug;
use SilverStripe\ORM\DataModel;
use SilverStripe\Core\Config\Configurable; use SilverStripe\Core\Config\Configurable;
use SilverStripe\Core\Injector\Injector; use SilverStripe\ORM\DataModel;
use SilverStripe\ORM\ValidationException; use SilverStripe\ORM\ValidationException;
class AuthenticationRequestFilter implements RequestFilter, IdentityStore class AuthenticationRequestFilter implements RequestFilter
{ {
use Configurable; use Configurable;
/** /**
* @var array|AuthenticationHandler[] * @var AuthenticationHandler
*/ */
protected $handlers; protected $authenticationHandler;
/** /**
* This method currently uses a fallback as loading the handlers via YML has proven unstable * @return AuthenticationHandler
*
* @return array|AuthenticationHandler[]
*/ */
protected function getHandlers() public function getAuthenticationHandler()
{ {
if (is_array($this->handlers)) { return $this->authenticationHandler;
return $this->handlers;
}
return array_map(
function ($identifier) {
return Injector::inst()->get($identifier);
},
static::config()->get('handlers')
);
} }
/** /**
* Set an associative array of handlers * @param AuthenticationHandler $authenticationHandler
* * @return $this
* @param array|AuthenticationHandler[] $handlers
*/ */
public function setHandlers($handlers) public function setAuthenticationHandler(AuthenticationHandler $authenticationHandler)
{ {
$this->handlers = $handlers; $this->authenticationHandler = $authenticationHandler;
return $this;
} }
/** /**
@ -64,16 +50,9 @@ class AuthenticationRequestFilter implements RequestFilter, IdentityStore
public function preRequest(HTTPRequest $request, Session $session, DataModel $model) public function preRequest(HTTPRequest $request, Session $session, DataModel $model)
{ {
try { try {
/** @var AuthenticationHandler $handler */ $this
foreach ($this->getHandlers() as $name => $handler) { ->getAuthenticationHandler()
// @todo Update requestfilter logic to allow modification of initial response ->authenticateRequest($request);
// in order to add cookies, etc
$member = $handler->authenticateRequest($request);
if ($member) {
Security::setCurrentUser($member);
break;
}
}
} catch (ValidationException $e) { } catch (ValidationException $e) {
throw new HTTPResponse_Exception( throw new HTTPResponse_Exception(
"Bad log-in details: " . $e->getMessage(), "Bad log-in details: " . $e->getMessage(),
@ -93,43 +72,4 @@ class AuthenticationRequestFilter implements RequestFilter, IdentityStore
public function postRequest(HTTPRequest $request, HTTPResponse $response, DataModel $model) public function postRequest(HTTPRequest $request, HTTPResponse $response, DataModel $model)
{ {
} }
/**
* Log into the identity-store handlers attached to this request filter
*
* @param Member $member
* @param bool $persistent
* @param HTTPRequest $request
* @return HTTPResponse|void
*/
public function logIn(Member $member, $persistent = false, HTTPRequest $request = null)
{
$member->beforeMemberLoggedIn();
foreach ($this->getHandlers() as $handler) {
if ($handler instanceof IdentityStore) {
$handler->logIn($member, $persistent, $request);
}
}
Security::setCurrentUser($member);
$member->afterMemberLoggedIn();
}
/**
* Log out of all the identity-store handlers attached to this request filter
*
* @param HTTPRequest $request
* @return HTTPResponse|void
*/
public function logOut(HTTPRequest $request = null)
{
foreach ($this->getHandlers() as $handler) {
if ($handler instanceof IdentityStore) {
$handler->logOut($request);
}
}
Security::setCurrentUser(null);
}
} }

View File

@ -2,12 +2,9 @@
namespace SilverStripe\Security; namespace SilverStripe\Security;
use SilverStripe\Core\Config\Configurable;
use SilverStripe\Core\Extensible;
use SilverStripe\Core\Injector\Injectable;
use SilverStripe\Control\Controller;
use SilverStripe\Forms\Form;
use SilverStripe\ORM\ValidationResult; use SilverStripe\ORM\ValidationResult;
use SilverStripe\Security\MemberAuthenticator\LoginHandler;
use SilverStripe\Security\MemberAuthenticator\LogoutHandler;
/** /**
* Abstract base class for an authentication method * Abstract base class for an authentication method
@ -47,6 +44,7 @@ interface Authenticator
* be merged into a default controller. * be merged into a default controller.
* *
* @param string $link The base link to use for this RequestHandler * @param string $link The base link to use for this RequestHandler
* @return LoginHandler
*/ */
public function getLoginHandler($link); public function getLoginHandler($link);
@ -56,7 +54,7 @@ interface Authenticator
* The default URL of the RequestHandler should log the user out immediately and destroy the session. * The default URL of the RequestHandler should log the user out immediately and destroy the session.
* *
* @param string $link The base link to use for this RequestHandler * @param string $link The base link to use for this RequestHandler
* @return mixed * @return LogoutHandler
*/ */
public function getLogOutHandler($link); public function getLogOutHandler($link);
@ -75,7 +73,7 @@ interface Authenticator
/** /**
* @param $link * @param string $link
* @return mixed * @return mixed
*/ */
public function getLostPasswordHandler($link); public function getLostPasswordHandler($link);
@ -87,5 +85,5 @@ interface Authenticator
* @param ValidationResult $result A validationresult which is either valid or contains the error message(s) * @param ValidationResult $result A validationresult which is either valid or contains the error message(s)
* @return Member The matched member, or null if the authentication fails * @return Member The matched member, or null if the authentication fails
*/ */
public function authenticate($data, &$result); public function authenticate($data, &$result = null);
} }

View File

@ -9,7 +9,6 @@ use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\HTTPResponse_Exception; use SilverStripe\Control\HTTPResponse_Exception;
use SilverStripe\Core\Config\Configurable; use SilverStripe\Core\Config\Configurable;
use SilverStripe\Dev\SapphireTest; use SilverStripe\Dev\SapphireTest;
use SilverStripe\Security\MemberAuthenticator\MemberAuthenticator; use SilverStripe\Security\MemberAuthenticator\MemberAuthenticator;
/** /**

View File

@ -3,14 +3,12 @@
namespace SilverStripe\Security; namespace SilverStripe\Security;
use SilverStripe\Admin\AdminRootController; use SilverStripe\Admin\AdminRootController;
use SilverStripe\Control\Controller;
use SilverStripe\Control\Director;
use SilverStripe\Control\HTTPResponse; use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\Session; use SilverStripe\Control\Session;
use SilverStripe\Core\Convert; use SilverStripe\Core\Convert;
use SilverStripe\Control\Director;
use SilverStripe\Control\Controller;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\ORM\FieldType\DBField; use SilverStripe\ORM\FieldType\DBField;
use SilverStripe\Security\MemberAuthenticator\CMSMemberAuthenticator;
use SilverStripe\View\Requirements; use SilverStripe\View\Requirements;
/** /**
@ -194,7 +192,7 @@ PHP
$backURLs = array( $backURLs = array(
$this->getRequest()->requestVar('BackURL'), $this->getRequest()->requestVar('BackURL'),
Session::get('BackURL'), Session::get('BackURL'),
Director::absoluteURL(AdminRootController::config()->url_base, true), Director::absoluteURL(AdminRootController::config()->get('url_base'), true),
); );
$backURL = null; $backURL = null;
foreach ($backURLs as $backURL) { foreach ($backURLs as $backURL) {

View File

@ -4,24 +4,24 @@ namespace SilverStripe\Security;
use SilverStripe\Admin\SecurityAdmin; use SilverStripe\Admin\SecurityAdmin;
use SilverStripe\Core\Convert; use SilverStripe\Core\Convert;
use SilverStripe\Forms\Form;
use SilverStripe\Forms\GridField\GridFieldAddExistingAutocompleter;
use SilverStripe\Forms\GridField\GridFieldDetailForm;
use SilverStripe\Forms\TextField;
use SilverStripe\Forms\DropdownField; use SilverStripe\Forms\DropdownField;
use SilverStripe\Forms\TextareaField;
use SilverStripe\Forms\Tab;
use SilverStripe\Forms\TabSet;
use SilverStripe\Forms\FieldList; use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\LiteralField; use SilverStripe\Forms\Form;
use SilverStripe\Forms\ListboxField; use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\HiddenField; use SilverStripe\Forms\GridField\GridFieldAddExistingAutocompleter;
use SilverStripe\Forms\HTMLEditor\HTMLEditorConfig;
use SilverStripe\Forms\GridField\GridFieldConfig_RelationEditor;
use SilverStripe\Forms\GridField\GridFieldButtonRow; use SilverStripe\Forms\GridField\GridFieldButtonRow;
use SilverStripe\Forms\GridField\GridFieldConfig_RelationEditor;
use SilverStripe\Forms\GridField\GridFieldDetailForm;
use SilverStripe\Forms\GridField\GridFieldExportButton; use SilverStripe\Forms\GridField\GridFieldExportButton;
use SilverStripe\Forms\GridField\GridFieldPrintButton; use SilverStripe\Forms\GridField\GridFieldPrintButton;
use SilverStripe\Forms\GridField\GridField; use SilverStripe\Forms\HiddenField;
use SilverStripe\Forms\HTMLEditor\HTMLEditorConfig;
use SilverStripe\Forms\ListboxField;
use SilverStripe\Forms\LiteralField;
use SilverStripe\Forms\Tab;
use SilverStripe\Forms\TabSet;
use SilverStripe\Forms\TextareaField;
use SilverStripe\Forms\TextField;
use SilverStripe\ORM\ArrayList; use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\DataObject; use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\DataQuery; use SilverStripe\ORM\DataQuery;
@ -29,7 +29,6 @@ use SilverStripe\ORM\HasManyList;
use SilverStripe\ORM\Hierarchy\Hierarchy; use SilverStripe\ORM\Hierarchy\Hierarchy;
use SilverStripe\ORM\ManyManyList; use SilverStripe\ORM\ManyManyList;
use SilverStripe\ORM\UnsavedRelationList; use SilverStripe\ORM\UnsavedRelationList;
use SilverStripe\View\Requirements;
/** /**
* A security group. * A security group.
@ -95,6 +94,7 @@ class Group extends DataObject
$doSet = new ArrayList(); $doSet = new ArrayList();
$children = Group::get()->filter("ParentID", $this->ID); $children = Group::get()->filter("ParentID", $this->ID);
/** @var Group $child */
foreach ($children as $child) { foreach ($children as $child) {
$doSet->push($child); $doSet->push($child);
$doSet->merge($child->getAllChildren()); $doSet->merge($child->getAllChildren());
@ -159,7 +159,7 @@ class Group extends DataObject
$detailForm = $config->getComponentByType(GridFieldDetailForm::class); $detailForm = $config->getComponentByType(GridFieldDetailForm::class);
$detailForm $detailForm
->setValidator(Member_Validator::create()) ->setValidator(Member_Validator::create())
->setItemEditFormCallback(function ($form, $component) use ($group) { ->setItemEditFormCallback(function ($form) use ($group) {
/** @var Form $form */ /** @var Form $form */
$record = $form->getRecord(); $record = $form->getRecord();
$groupsField = $form->Fields()->dataFieldByName('DirectGroups'); $groupsField = $form->Fields()->dataFieldByName('DirectGroups');
@ -369,9 +369,9 @@ class Group extends DataObject
{ {
$parent = $this; $parent = $this;
$items = []; $items = [];
while (isset($parent) && $parent instanceof Group) { while ($parent instanceof Group) {
$items[] = $parent->ID; $items[] = $parent->ID;
$parent = $parent->Parent; $parent = $parent->getParent();
} }
return $items; return $items;
} }
@ -395,12 +395,14 @@ class Group extends DataObject
->sort('"Sort"'); ->sort('"Sort"');
} }
/**
* @return string
*/
public function getTreeTitle() public function getTreeTitle()
{ {
if ($this->hasMethod('alternateTreeTitle')) { $title = htmlspecialchars($this->Title, ENT_QUOTES);
return $this->alternateTreeTitle(); $this->extend('updateTreeTitle', $title);
} return $title;
return htmlspecialchars($this->Title, ENT_QUOTES);
} }
/** /**

View File

@ -2,8 +2,8 @@
namespace SilverStripe\Security; namespace SilverStripe\Security;
use SilverStripe\ORM\DataObject;
use SilverStripe\Dev\CsvBulkLoader; use SilverStripe\Dev\CsvBulkLoader;
use SilverStripe\ORM\DataObject;
/** /**
* @todo Migrate Permission->Arg and Permission->Type values * @todo Migrate Permission->Arg and Permission->Type values
@ -15,12 +15,8 @@ class GroupCsvBulkLoader extends CsvBulkLoader
'Code' => 'Code', 'Code' => 'Code',
); );
public function __construct($objectClass = null) public function __construct($objectClass = Group::class)
{ {
if (!$objectClass) {
$objectClass = 'SilverStripe\\Security\\Group';
}
parent::__construct($objectClass); parent::__construct($objectClass);
} }

View File

@ -4,7 +4,6 @@ namespace SilverStripe\Security;
use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse; use SilverStripe\Control\HTTPResponse;
use SilverStripe\Core\Config\Configurable;
/** /**
* Represents an authentication handler that can have identities logged into & out of it. * Represents an authentication handler that can have identities logged into & out of it.
@ -19,7 +18,6 @@ interface IdentityStore
* @param Member $member The member to log in. * @param Member $member The member to log in.
* @param Boolean $persistent boolean If set to true, the login may persist beyond the current session. * @param Boolean $persistent boolean If set to true, the login may persist beyond the current session.
* @param HTTPRequest $request The request of the visitor that is logging in, to get, for example, cookies. * @param HTTPRequest $request The request of the visitor that is logging in, to get, for example, cookies.
* @return HTTPResponse $response The response object to modify, if needed.
*/ */
public function logIn(Member $member, $persistent = false, HTTPRequest $request = null); public function logIn(Member $member, $persistent = false, HTTPRequest $request = null);
@ -27,7 +25,6 @@ interface IdentityStore
* Log any logged-in member out of this identity store. * Log any logged-in member out of this identity store.
* *
* @param HTTPRequest $request The request of the visitor that is logging out, to get, for example, cookies. * @param HTTPRequest $request The request of the visitor that is logging out, to get, for example, cookies.
* @return HTTPResponse $response The response object to modify, if needed.
*/ */
public function logOut(HTTPRequest $request = null); public function logOut(HTTPRequest $request = null);
} }

View File

@ -2,7 +2,6 @@
namespace SilverStripe\Security; namespace SilverStripe\Security;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Forms\FieldList; use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\Form; use SilverStripe\Forms\Form;

View File

@ -3,19 +3,16 @@
namespace SilverStripe\Security; namespace SilverStripe\Security;
use IntlDateFormatter; use IntlDateFormatter;
use InvalidArgumentException;
use SilverStripe\Admin\LeftAndMain; use SilverStripe\Admin\LeftAndMain;
use SilverStripe\CMS\Controllers\CMSMain; use SilverStripe\CMS\Controllers\CMSMain;
use SilverStripe\Control\Controller; use SilverStripe\Control\Controller;
use SilverStripe\Control\Cookie;
use SilverStripe\Control\Director; use SilverStripe\Control\Director;
use SilverStripe\Control\Email\Email; use SilverStripe\Control\Email\Email;
use SilverStripe\Control\Email\Mailer; use SilverStripe\Control\Email\Mailer;
use SilverStripe\Control\Session;
use SilverStripe\Core\Convert; use SilverStripe\Core\Convert;
use SilverStripe\Core\Injector\Injector; use SilverStripe\Core\Injector\Injector;
use SilverStripe\Dev\Debug;
use SilverStripe\Dev\Deprecation; use SilverStripe\Dev\Deprecation;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Dev\TestMailer; use SilverStripe\Dev\TestMailer;
use SilverStripe\Forms\ConfirmedPasswordField; use SilverStripe\Forms\ConfirmedPasswordField;
use SilverStripe\Forms\DropdownField; use SilverStripe\Forms\DropdownField;
@ -23,7 +20,6 @@ use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\HTMLEditor\HTMLEditorConfig; use SilverStripe\Forms\HTMLEditor\HTMLEditorConfig;
use SilverStripe\Forms\ListboxField; use SilverStripe\Forms\ListboxField;
use SilverStripe\i18n\i18n; use SilverStripe\i18n\i18n;
use SilverStripe\MSSQL\MSSQLDatabase;
use SilverStripe\ORM\ArrayList; use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\DataList; use SilverStripe\ORM\DataList;
use SilverStripe\ORM\DataObject; use SilverStripe\ORM\DataObject;
@ -31,13 +27,10 @@ use SilverStripe\ORM\DB;
use SilverStripe\ORM\FieldType\DBDatetime; use SilverStripe\ORM\FieldType\DBDatetime;
use SilverStripe\ORM\HasManyList; use SilverStripe\ORM\HasManyList;
use SilverStripe\ORM\ManyManyList; use SilverStripe\ORM\ManyManyList;
use SilverStripe\ORM\SS_List;
use SilverStripe\ORM\Map; use SilverStripe\ORM\Map;
use SilverStripe\ORM\SS_List;
use SilverStripe\ORM\ValidationException; use SilverStripe\ORM\ValidationException;
use SilverStripe\ORM\ValidationResult; use SilverStripe\ORM\ValidationResult;
use SilverStripe\View\SSViewer;
use SilverStripe\View\TemplateGlobalProvider;
use DateTime;
/** /**
* The member class which represents the users of the system * The member class which represents the users of the system
@ -60,6 +53,7 @@ use DateTime;
* @property int $FailedLoginCount * @property int $FailedLoginCount
* @property string $DateFormat * @property string $DateFormat
* @property string $TimeFormat * @property string $TimeFormat
* @property string $SetPassword Pseudo-DB field for temp storage. Not emitted to DB
*/ */
class Member extends DataObject class Member extends DataObject
{ {
@ -482,9 +476,10 @@ class Member extends DataObject
public function regenerateTempID() public function regenerateTempID()
{ {
$generator = new RandomGenerator(); $generator = new RandomGenerator();
$lifetime = self::config()->get('temp_id_lifetime');
$this->TempIDHash = $generator->randomToken('sha1'); $this->TempIDHash = $generator->randomToken('sha1');
$this->TempIDExpired = self::config()->temp_id_lifetime $this->TempIDExpired = $lifetime
? date('Y-m-d H:i:s', strtotime(DBDatetime::now()->getValue()) + self::config()->temp_id_lifetime) ? date('Y-m-d H:i:s', strtotime(DBDatetime::now()->getValue()) + $lifetime)
: null; : null;
$this->write(); $this->write();
} }
@ -756,7 +751,7 @@ class Member extends DataObject
* *
* @param Member|null|int $member Member or member ID to log in as. * @param Member|null|int $member Member or member ID to log in as.
* Set to null or 0 to act as a logged out user. * Set to null or 0 to act as a logged out user.
* @param $callback * @param callable $callback
*/ */
public static function actAs($member, $callback) public static function actAs($member, $callback)
{ {
@ -837,7 +832,7 @@ class Member extends DataObject
// If a member with the same "unique identifier" already exists with a different ID, don't allow merging. // If a member with the same "unique identifier" already exists with a different ID, don't allow merging.
// Note: This does not a full replacement for safeguards in the controller layer (e.g. in a registration form), // Note: This does not a full replacement for safeguards in the controller layer (e.g. in a registration form),
// but rather a last line of defense against data inconsistencies. // but rather a last line of defense against data inconsistencies.
$identifierField = Member::config()->unique_identifier_field; $identifierField = Member::config()->get('unique_identifier_field');
if ($this->$identifierField) { if ($this->$identifierField) {
// Note: Same logic as Member_Validator class // Note: Same logic as Member_Validator class
$filter = [ $filter = [
@ -890,7 +885,7 @@ class Member extends DataObject
$this->Password, // this is assumed to be cleartext $this->Password, // this is assumed to be cleartext
$this->Salt, $this->Salt,
($this->PasswordEncryption) ? ($this->PasswordEncryption) ?
$this->PasswordEncryption : Security::config()->password_encryption_algorithm, $this->PasswordEncryption : Security::config()->get('password_encryption_algorithm'),
$this $this
); );
@ -1013,7 +1008,7 @@ class Member extends DataObject
} elseif ($group instanceof Group) { } elseif ($group instanceof Group) {
$groupCheckObj = $group; $groupCheckObj = $group;
} else { } else {
user_error('Member::inGroup(): Wrong format for $group parameter', E_USER_ERROR); throw new InvalidArgumentException('Member::inGroup(): Wrong format for $group parameter');
} }
if (!$groupCheckObj) { if (!$groupCheckObj) {
@ -1081,10 +1076,17 @@ class Member extends DataObject
*/ */
public static function set_title_columns($columns, $sep = ' ') public static function set_title_columns($columns, $sep = ' ')
{ {
Deprecation::notice('5.0', 'Use Member.title_format config instead');
if (!is_array($columns)) { if (!is_array($columns)) {
$columns = array($columns); $columns = array($columns);
} }
self::config()->title_format = array('columns' => $columns, 'sep' => $sep); self::config()->set(
'title_format',
[
'columns' => $columns,
'sep' => $sep
]
);
} }
//------------------- HELPER METHODS -----------------------------------// //------------------- HELPER METHODS -----------------------------------//
@ -1133,8 +1135,6 @@ class Member extends DataObject
*/ */
public static function get_title_sql() public static function get_title_sql()
{ {
// This should be abstracted to SSDatabase concatOperator or similar.
$op = (DB::get_conn() instanceof MSSQLDatabase) ? " + " : " || ";
// Get title_format with fallback to default // Get title_format with fallback to default
$format = static::config()->get('title_format'); $format = static::config()->get('title_format');
@ -1151,7 +1151,7 @@ class Member extends DataObject
} }
$sepSQL = Convert::raw2sql($format['sep'], true); $sepSQL = Convert::raw2sql($format['sep'], true);
$op = DB::get_conn()->concatOperator();
return "(" . join(" $op $sepSQL $op ", $columnsWithTablename) . ")"; return "(" . join(" $op $sepSQL $op ", $columnsWithTablename) . ")";
} }
@ -1305,6 +1305,7 @@ class Member extends DataObject
$membersList = new ArrayList(); $membersList = new ArrayList();
// This is a bit ineffective, but follow the ORM style // This is a bit ineffective, but follow the ORM style
/** @var Group $group */
foreach (Group::get()->byIDs($groupIDList) as $group) { foreach (Group::get()->byIDs($groupIDList) as $group) {
$membersList->merge($group->Members()); $membersList->merge($group->Members());
} }
@ -1332,7 +1333,7 @@ class Member extends DataObject
return ArrayList::create()->map(); return ArrayList::create()->map();
} }
if (!$groups || $groups->Count() == 0) { if (count($groups) == 0) {
$perms = array('ADMIN', 'CMS_ACCESS_AssetAdmin'); $perms = array('ADMIN', 'CMS_ACCESS_AssetAdmin');
if (class_exists(CMSMain::class)) { if (class_exists(CMSMain::class)) {
@ -1673,12 +1674,13 @@ class Member extends DataObject
*/ */
public function registerFailedLogin() public function registerFailedLogin()
{ {
if (self::config()->lock_out_after_incorrect_logins) { $lockOutAfterCount = self::config()->get('lock_out_after_incorrect_logins');
if ($lockOutAfterCount) {
// Keep a tally of the number of failed log-ins so that we can lock people out // Keep a tally of the number of failed log-ins so that we can lock people out
$this->FailedLoginCount = $this->FailedLoginCount + 1; $this->FailedLoginCount = $this->FailedLoginCount + 1;
if ($this->FailedLoginCount >= self::config()->lock_out_after_incorrect_logins) { if ($this->FailedLoginCount >= $lockOutAfterCount) {
$lockoutMins = self::config()->lock_out_delay_mins; $lockoutMins = self::config()->get('lock_out_delay_mins');
$this->LockedOutUntil = date('Y-m-d H:i:s', DBDatetime::now()->getTimestamp() + $lockoutMins * 60); $this->LockedOutUntil = date('Y-m-d H:i:s', DBDatetime::now()->getTimestamp() + $lockoutMins * 60);
$this->FailedLoginCount = 0; $this->FailedLoginCount = 0;
} }
@ -1692,7 +1694,7 @@ class Member extends DataObject
*/ */
public function registerSuccessfulLogin() public function registerSuccessfulLogin()
{ {
if (self::config()->lock_out_after_incorrect_logins) { if (self::config()->get('lock_out_after_incorrect_logins')) {
// Forgive all past login failures // Forgive all past login failures
$this->FailedLoginCount = 0; $this->FailedLoginCount = 0;
$this->write(); $this->write();

View File

@ -5,7 +5,6 @@ namespace SilverStripe\Security\MemberAuthenticator;
use SilverStripe\Control\HTTPResponse; use SilverStripe\Control\HTTPResponse;
use SilverStripe\Core\Convert; use SilverStripe\Core\Convert;
use SilverStripe\Security\CMSSecurity; use SilverStripe\Security\CMSSecurity;
use SilverStripe\Security\Member;
use SilverStripe\Security\Security; use SilverStripe\Security\Security;
class CMSLoginHandler extends LoginHandler class CMSLoginHandler extends LoginHandler

View File

@ -2,14 +2,14 @@
namespace SilverStripe\Security\MemberAuthenticator; namespace SilverStripe\Security\MemberAuthenticator;
use SilverStripe\Control\Session;
use SilverStripe\Control\RequestHandler; use SilverStripe\Control\RequestHandler;
use SilverStripe\Control\Session;
use SilverStripe\Forms\FieldList; use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\FormField;
use SilverStripe\Forms\PasswordField;
use SilverStripe\Forms\FormAction;
use SilverStripe\Forms\HiddenField;
use SilverStripe\Forms\Form; use SilverStripe\Forms\Form;
use SilverStripe\Forms\FormAction;
use SilverStripe\Forms\FormField;
use SilverStripe\Forms\HiddenField;
use SilverStripe\Forms\PasswordField;
use SilverStripe\Security\Security; use SilverStripe\Security\Security;
/** /**

View File

@ -4,18 +4,16 @@
namespace SilverStripe\Security\MemberAuthenticator; namespace SilverStripe\Security\MemberAuthenticator;
use SilverStripe\Control\Controller; use SilverStripe\Control\Controller;
use SilverStripe\Control\RequestHandler;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Control\HTTPResponse; use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\RequestHandler;
use SilverStripe\Control\Session; use SilverStripe\Control\Session;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\ORM\FieldType\DBDatetime; use SilverStripe\ORM\FieldType\DBDatetime;
use SilverStripe\ORM\FieldType\DBField; use SilverStripe\ORM\FieldType\DBField;
use SilverStripe\ORM\FieldType\DBHTMLText;
use SilverStripe\Security\Authenticator; use SilverStripe\Security\Authenticator;
use SilverStripe\Security\CMSSecurity; use SilverStripe\Security\IdentityStore;
use SilverStripe\Security\Member; use SilverStripe\Security\Member;
use SilverStripe\Security\Security; use SilverStripe\Security\Security;
use SilverStripe\Security\IdentityStore;
class ChangePasswordHandler extends RequestHandler class ChangePasswordHandler extends RequestHandler
{ {

View File

@ -2,20 +2,19 @@
namespace SilverStripe\Security\MemberAuthenticator; namespace SilverStripe\Security\MemberAuthenticator;
use SilverStripe\Control\HTTPResponse; use SilverStripe\Control\Cookie;
use SilverStripe\Security\Member;
use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPRequest;
use SilverStripe\Security\AuthenticationHandler as AuthenticationHandlerInterface; use SilverStripe\ORM\FieldType\DBDatetime;
use SilverStripe\Security\AuthenticationHandler;
use SilverStripe\Security\IdentityStore; use SilverStripe\Security\IdentityStore;
use SilverStripe\Security\Member;
use SilverStripe\Security\RememberLoginHash; use SilverStripe\Security\RememberLoginHash;
use SilverStripe\Security\Security; use SilverStripe\Security\Security;
use SilverStripe\ORM\FieldType\DBDatetime;
use SilverStripe\Control\Cookie;
/** /**
* Authenticate a member pased on a session cookie * Authenticate a member pased on a session cookie
*/ */
class CookieAuthenticationHandler implements AuthenticationHandlerInterface, IdentityStore class CookieAuthenticationHandler implements AuthenticationHandler
{ {
/** /**
@ -47,11 +46,12 @@ class CookieAuthenticationHandler implements AuthenticationHandlerInterface, Ide
* Set the name of the cookie used to track this device * Set the name of the cookie used to track this device
* *
* @param string $deviceCookieName * @param string $deviceCookieName
* @return null * @return $this
*/ */
public function setDeviceCookieName($deviceCookieName) public function setDeviceCookieName($deviceCookieName)
{ {
$this->deviceCookieName = $deviceCookieName; $this->deviceCookieName = $deviceCookieName;
return $this;
} }
/** /**
@ -68,10 +68,12 @@ class CookieAuthenticationHandler implements AuthenticationHandlerInterface, Ide
* Set the name of the cookie used to store an login token * Set the name of the cookie used to store an login token
* *
* @param string $tokenCookieName * @param string $tokenCookieName
* @return $this
*/ */
public function setTokenCookieName($tokenCookieName) public function setTokenCookieName($tokenCookieName)
{ {
$this->tokenCookieName = $tokenCookieName; $this->tokenCookieName = $tokenCookieName;
return $this;
} }
/** /**
@ -88,16 +90,17 @@ class CookieAuthenticationHandler implements AuthenticationHandlerInterface, Ide
* Set the name of the cookie used to store an login token * Set the name of the cookie used to store an login token
* *
* @param IdentityStore $cascadeInTo * @param IdentityStore $cascadeInTo
* @return null * @return $this
*/ */
public function setCascadeLogInTo(IdentityStore $cascadeInTo) public function setCascadeLogInTo(IdentityStore $cascadeInTo)
{ {
$this->cascadeInTo = $cascadeInTo; $this->cascadeInTo = $cascadeInTo;
return $this;
} }
/** /**
* @param HTTPRequest $request * @param HTTPRequest $request
* @return null|Member * @return Member
*/ */
public function authenticateRequest(HTTPRequest $request) public function authenticateRequest(HTTPRequest $request)
{ {
@ -115,71 +118,65 @@ class CookieAuthenticationHandler implements AuthenticationHandlerInterface, Ide
return null; return null;
} }
// check if autologin token matches
/** @var Member $member */ /** @var Member $member */
$member = Member::get()->byID($uid); $member = Member::get()->byID($uid);
if (!$member) {
return null;
}
$hash = $member->encryptWithUserSettings($token);
/** @var RememberLoginHash $rememberLoginHash */ /** @var RememberLoginHash $rememberLoginHash */
$rememberLoginHash = null; $rememberLoginHash = RememberLoginHash::get()
->filter(array(
// check if autologin token matches 'MemberID' => $member->ID,
if ($member) { 'DeviceID' => $deviceID,
$hash = $member->encryptWithUserSettings($token); 'Hash' => $hash
$rememberLoginHash = RememberLoginHash::get() ))->first();
->filter(array( if (!$rememberLoginHash) {
'MemberID' => $member->ID, return null;
'DeviceID' => $deviceID,
'Hash' => $hash
))->first();
if (!$rememberLoginHash) {
$member = null;
} else {
// Check for expired token
$expiryDate = new \DateTime($rememberLoginHash->ExpiryDate);
$now = DBDatetime::now();
$now = new \DateTime($now->Rfc2822());
if ($now > $expiryDate) {
$member = null;
}
}
} }
if ($member) { // Check for expired token
if ($this->cascadeInTo) { $expiryDate = new \DateTime($rememberLoginHash->ExpiryDate);
// @todo look at how to block "regular login" triggers from happening here $now = DBDatetime::now();
// @todo deal with the fact that the Session::current_session() isn't correct here :-/ $now = new \DateTime($now->Rfc2822());
$this->cascadeInTo->logIn($member, false, $request); if ($now > $expiryDate) {
} return null;
// @todo Consider whether response should be part of logIn() as well
// Renew the token
if ($rememberLoginHash) {
$rememberLoginHash->renew();
$tokenExpiryDays = RememberLoginHash::config()->uninherited('token_expiry_days');
Cookie::set(
$this->getTokenCookieName(),
$member->ID . ':' . $rememberLoginHash->getToken(),
$tokenExpiryDays,
null,
null,
false,
true
);
}
// Audit logging hook
$member->extend('memberAutoLoggedIn');
return $member;
} }
if ($this->cascadeInTo) {
// @todo look at how to block "regular login" triggers from happening here
// @todo deal with the fact that the Session::current_session() isn't correct here :-/
$this->cascadeInTo->logIn($member, false, $request);
}
// @todo Consider whether response should be part of logIn() as well
// Renew the token
$rememberLoginHash->renew();
$tokenExpiryDays = RememberLoginHash::config()->uninherited('token_expiry_days');
Cookie::set(
$this->getTokenCookieName(),
$member->ID . ':' . $rememberLoginHash->getToken(),
$tokenExpiryDays,
null,
null,
false,
true
);
// Audit logging hook
$member->extend('memberAutoLoggedIn');
return $member;
} }
/** /**
* @param Member $member * @param Member $member
* @param bool $persistent * @param bool $persistent
* @param HTTPRequest $request * @param HTTPRequest $request
* @return HTTPResponse|void
*/ */
public function logIn(Member $member, $persistent = false, HTTPRequest $request = null) public function logIn(Member $member, $persistent = false, HTTPRequest $request = null)
{ {
@ -218,8 +215,7 @@ class CookieAuthenticationHandler implements AuthenticationHandlerInterface, Ide
} }
/** /**
* @param HTTPRequest|null $request * @param HTTPRequest $request
* @return HTTPResponse|void
*/ */
public function logOut(HTTPRequest $request = null) public function logOut(HTTPRequest $request = null)
{ {

View File

@ -5,14 +5,14 @@ namespace SilverStripe\Security\MemberAuthenticator;
use SilverStripe\Control\Controller; use SilverStripe\Control\Controller;
use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse; use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\Session;
use SilverStripe\Control\RequestHandler; use SilverStripe\Control\RequestHandler;
use SilverStripe\Control\Session;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\ORM\ValidationResult; use SilverStripe\ORM\ValidationResult;
use SilverStripe\Security\Authenticator; use SilverStripe\Security\Authenticator;
use SilverStripe\Security\Security;
use SilverStripe\Security\Member;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Security\IdentityStore; use SilverStripe\Security\IdentityStore;
use SilverStripe\Security\Member;
use SilverStripe\Security\Security;
/** /**
* Handle login requests from MemberLoginForm * Handle login requests from MemberLoginForm

View File

@ -2,13 +2,10 @@
namespace SilverStripe\Security\MemberAuthenticator; namespace SilverStripe\Security\MemberAuthenticator;
use SilverStripe\Control\Cookie;
use SilverStripe\Control\RequestHandler; use SilverStripe\Control\RequestHandler;
use SilverStripe\Control\Session;
use SilverStripe\Core\Injector\Injector; use SilverStripe\Core\Injector\Injector;
use SilverStripe\Security\IdentityStore; use SilverStripe\Security\IdentityStore;
use SilverStripe\Security\Member; use SilverStripe\Security\Member;
use SilverStripe\Security\RememberLoginHash;
use SilverStripe\Security\Security; use SilverStripe\Security\Security;
/** /**

View File

@ -5,19 +5,12 @@ namespace SilverStripe\Security\MemberAuthenticator;
use SilverStripe\Control\Controller; use SilverStripe\Control\Controller;
use SilverStripe\Control\Email\Email; use SilverStripe\Control\Email\Email;
use SilverStripe\Control\HTTPResponse; use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\Session;
use SilverStripe\Control\RequestHandler; use SilverStripe\Control\RequestHandler;
use SilverStripe\Core\Injector\Injector; use SilverStripe\Core\Convert;
use SilverStripe\Forms\Form; use SilverStripe\Forms\Form;
use SilverStripe\ORM\ValidationResult; use SilverStripe\ORM\FieldType\DBField;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\EmailField;
use SilverStripe\Forms\FormAction;
use SilverStripe\Security\IdentityStore;
use SilverStripe\Security\Member; use SilverStripe\Security\Member;
use SilverStripe\Security\Security; use SilverStripe\Security\Security;
use SilverStripe\Core\Convert;
use SilverStripe\ORM\FieldType\DBField;
/** /**
* Handle login requests from MemberLoginForm * Handle login requests from MemberLoginForm

View File

@ -2,14 +2,14 @@
namespace SilverStripe\Security\MemberAuthenticator; namespace SilverStripe\Security\MemberAuthenticator;
use InvalidArgumentException;
use SilverStripe\Control\Controller; use SilverStripe\Control\Controller;
use SilverStripe\Control\Session; use SilverStripe\Control\Session;
use SilverStripe\ORM\ValidationResult; use SilverStripe\ORM\ValidationResult;
use InvalidArgumentException;
use SilverStripe\Security\Authenticator; use SilverStripe\Security\Authenticator;
use SilverStripe\Security\Security;
use SilverStripe\Security\Member;
use SilverStripe\Security\LoginAttempt; use SilverStripe\Security\LoginAttempt;
use SilverStripe\Security\Member;
use SilverStripe\Security\Security;
/** /**
* Authenticator for the default "member" method * Authenticator for the default "member" method
@ -162,7 +162,7 @@ class MemberAuthenticator implements Authenticator
} }
/** /**
* @param $link * @param string $link
* @return LostPasswordHandler * @return LostPasswordHandler
*/ */
public function getLostPasswordHandler($link) public function getLostPasswordHandler($link)

View File

@ -5,20 +5,19 @@ namespace SilverStripe\Security\MemberAuthenticator;
use SilverStripe\Control\Director; use SilverStripe\Control\Director;
use SilverStripe\Control\RequestHandler; use SilverStripe\Control\RequestHandler;
use SilverStripe\Control\Session; use SilverStripe\Control\Session;
use SilverStripe\Control\Controller; use SilverStripe\Forms\CheckboxField;
use SilverStripe\Forms\HiddenField;
use SilverStripe\Forms\FieldList; use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\FormAction; use SilverStripe\Forms\FormAction;
use SilverStripe\Forms\TextField; use SilverStripe\Forms\HiddenField;
use SilverStripe\Forms\PasswordField;
use SilverStripe\Forms\CheckboxField;
use SilverStripe\Forms\LiteralField; use SilverStripe\Forms\LiteralField;
use SilverStripe\Forms\PasswordField;
use SilverStripe\Forms\RequiredFields; use SilverStripe\Forms\RequiredFields;
use SilverStripe\Forms\TextField;
use SilverStripe\ORM\ValidationResult; use SilverStripe\ORM\ValidationResult;
use SilverStripe\Security\Member;
use SilverStripe\Security\Security;
use SilverStripe\Security\RememberLoginHash;
use SilverStripe\Security\LoginForm as BaseLoginForm; use SilverStripe\Security\LoginForm as BaseLoginForm;
use SilverStripe\Security\Member;
use SilverStripe\Security\RememberLoginHash;
use SilverStripe\Security\Security;
use SilverStripe\View\Requirements; use SilverStripe\View\Requirements;
/** /**
@ -42,9 +41,14 @@ class MemberLoginForm extends BaseLoginForm
/** /**
* Required fields for validation * Required fields for validation
*
* @config
* @var array * @var array
*/ */
private static $required_fields; private static $required_fields = [
'Email',
'Password',
];
/** /**
* Constructor * Constructor

View File

@ -3,21 +3,17 @@
namespace SilverStripe\Security\MemberAuthenticator; namespace SilverStripe\Security\MemberAuthenticator;
use SilverStripe\Control\Cookie; use SilverStripe\Control\Cookie;
use SilverStripe\Control\HTTPResponse; use SilverStripe\Control\Director;
use SilverStripe\ORM\DataObject;
use SilverStripe\Security\Member;
use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\Session; use SilverStripe\Control\Session;
use SilverStripe\Control\Director;
use SilverStripe\Security\AuthenticationHandler; use SilverStripe\Security\AuthenticationHandler;
use SilverStripe\Security\IdentityStore; use SilverStripe\Security\Member;
/** /**
* Authenticate a member pased on a session cookie * Authenticate a member pased on a session cookie
*/ */
class SessionAuthenticationHandler implements AuthenticationHandler, IdentityStore class SessionAuthenticationHandler implements AuthenticationHandler
{ {
/** /**
* @var string * @var string
*/ */
@ -44,27 +40,26 @@ class SessionAuthenticationHandler implements AuthenticationHandler, IdentitySto
} }
/** /**
* @inherit
* @param HTTPRequest $request * @param HTTPRequest $request
* @return null|DataObject|Member * @return Member
*/ */
public function authenticateRequest(HTTPRequest $request) public function authenticateRequest(HTTPRequest $request)
{ {
if ($id = Session::get($this->getSessionVariable())) { // If ID is a bad ID it will be treated as if the user is not logged in, rather than throwing a
// If ID is a bad ID it will be treated as if the user is not logged in, rather than throwing a // ValidationException
// ValidationException $id = Session::get($this->getSessionVariable());
return Member::get()->byID($id); if (!$id) {
return null;
} }
/** @var Member $member */
return null; $member = Member::get()->byID($id);
return $member;
} }
/** /**
* @inherit
* @param Member $member * @param Member $member
* @param bool $persistent * @param bool $persistent
* @param HTTPRequest|null $request * @param HTTPRequest $request
* @return HTTPResponse|void
*/ */
public function logIn(Member $member, $persistent = false, HTTPRequest $request = null) public function logIn(Member $member, $persistent = false, HTTPRequest $request = null)
{ {
@ -103,8 +98,7 @@ class SessionAuthenticationHandler implements AuthenticationHandler, IdentitySto
} }
/** /**
* @param HTTPRequest|null $request * @param HTTPRequest $request
* @return HTTPResponse|void
*/ */
public function logOut(HTTPRequest $request = null) public function logOut(HTTPRequest $request = null)
{ {

View File

@ -109,7 +109,7 @@ class Member_GroupSet extends ManyManyList
{ {
$id = $this->getForeignID(); $id = $this->getForeignID();
if ($id) { if ($id) {
return DataObject::get_by_id('SilverStripe\\Security\\Member', $id); return DataObject::get_by_id(Member::class, $id);
} }
} }
} }

View File

@ -2,8 +2,8 @@
namespace SilverStripe\Security; namespace SilverStripe\Security;
use SilverStripe\Forms\RequiredFields;
use SilverStripe\Forms\GridField\GridFieldDetailForm_ItemRequest; use SilverStripe\Forms\GridField\GridFieldDetailForm_ItemRequest;
use SilverStripe\Forms\RequiredFields;
/** /**
* Member Validator * Member Validator

View File

@ -2,8 +2,8 @@
namespace SilverStripe\Security; namespace SilverStripe\Security;
use SilverStripe\Core\Config\Config;
use ReflectionClass; use ReflectionClass;
use SilverStripe\Core\Config\Config;
/** /**
* Allows pluggable password encryption. * Allows pluggable password encryption.

View File

@ -4,12 +4,11 @@ namespace SilverStripe\Security;
use SilverStripe\Core\ClassInfo; use SilverStripe\Core\ClassInfo;
use SilverStripe\Core\Resettable; use SilverStripe\Core\Resettable;
use SilverStripe\Dev\Debug;
use SilverStripe\Dev\TestOnly; use SilverStripe\Dev\TestOnly;
use SilverStripe\i18n\i18nEntityProvider; use SilverStripe\i18n\i18nEntityProvider;
use SilverStripe\ORM\DB;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\ArrayList; use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\DB;
use SilverStripe\ORM\SS_List; use SilverStripe\ORM\SS_List;
use SilverStripe\View\TemplateGlobalProvider; use SilverStripe\View\TemplateGlobalProvider;
@ -459,7 +458,7 @@ class Permission extends DataObject implements TemplateGlobalProvider, Resettabl
/** /**
* Returns all members for a specific permission. * Returns all members for a specific permission.
* *
* @param $code String|array Either a single permission code, or a list of permission codes * @param string|array $code Either a single permission code, or a list of permission codes
* @return SS_List Returns a set of member that have the specified * @return SS_List Returns a set of member that have the specified
* permission. * permission.
*/ */

View File

@ -2,14 +2,13 @@
namespace SilverStripe\Security; namespace SilverStripe\Security;
use InvalidArgumentException;
use SilverStripe\Core\Config\Config; use SilverStripe\Core\Config\Config;
use SilverStripe\Forms\FormField; use SilverStripe\Forms\FormField;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\SS_List;
use SilverStripe\ORM\ArrayList; use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\DataObjectInterface; use SilverStripe\ORM\DataObjectInterface;
use SilverStripe\View\Requirements; use SilverStripe\ORM\SS_List;
use InvalidArgumentException;
/** /**
* Shows a categorized list of available permissions (through {@link Permission::get_codes()}). * Shows a categorized list of available permissions (through {@link Permission::get_codes()}).

View File

@ -2,10 +2,10 @@
namespace SilverStripe\Security; namespace SilverStripe\Security;
use SilverStripe\ORM\FieldType\DBDatetime;
use SilverStripe\ORM\DataObject;
use DateTime;
use DateInterval; use DateInterval;
use DateTime;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\FieldType\DBDatetime;
/** /**
* Persists a token associated with a device for users who opted for the "Remember Me" * Persists a token associated with a device for users who opted for the "Remember Me"
@ -16,7 +16,8 @@ use DateInterval;
* is discarded as well. * is discarded as well.
* *
* @property string $DeviceID * @property string $DeviceID
* @property string $RememberLoginHash * @property string $ExpiryDate
* @property string $Hash
* @method Member Member() * @method Member Member()
*/ */
class RememberLoginHash extends DataObject class RememberLoginHash extends DataObject

View File

@ -0,0 +1,83 @@
<?php
namespace SilverStripe\Security;
use SilverStripe\Control\HTTPRequest;
/**
* Core authentication handler / store
*/
class RequestAuthenticationHandler implements AuthenticationHandler
{
/**
* @var AuthenticationHandler[]
*/
protected $handlers = [];
/**
* This method currently uses a fallback as loading the handlers via YML has proven unstable
*
* @return AuthenticationHandler[]
*/
protected function getHandlers()
{
return $this->handlers;
}
/**
* Set an associative array of handlers
*
* @param AuthenticationHandler[] $handlers
* @return $this
*/
public function setHandlers(array $handlers)
{
$this->handlers = $handlers;
return $this;
}
public function authenticateRequest(HTTPRequest $request)
{
/** @var AuthenticationHandler $handler */
foreach ($this->getHandlers() as $name => $handler) {
// in order to add cookies, etc
$member = $handler->authenticateRequest($request);
if ($member) {
Security::setCurrentUser($member);
return;
}
}
}
/**
* Log into the identity-store handlers attached to this request filter
*
* @param Member $member
* @param bool $persistent
* @param HTTPRequest $request
*/
public function logIn(Member $member, $persistent = false, HTTPRequest $request = null)
{
$member->beforeMemberLoggedIn();
foreach ($this->getHandlers() as $handler) {
$handler->logIn($member, $persistent, $request);
}
Security::setCurrentUser($member);
$member->afterMemberLoggedIn();
}
/**
* Log out of all the identity-store handlers attached to this request filter
*
* @param HTTPRequest $request
*/
public function logOut(HTTPRequest $request = null)
{
foreach ($this->getHandlers() as $handler) {
$handler->logOut($request);
}
Security::setCurrentUser(null);
}
}

View File

@ -2,25 +2,26 @@
namespace SilverStripe\Security; namespace SilverStripe\Security;
use Page;
use LogicException; use LogicException;
use SilverStripe\CMS\Controllers\ContentController; use Page;
use SilverStripe\CMS\Controllers\ModelAsController;
use SilverStripe\Control\Controller; use SilverStripe\Control\Controller;
use SilverStripe\Control\Director; use SilverStripe\Control\Director;
use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse; use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\HTTPResponse_Exception; use SilverStripe\Control\HTTPResponse_Exception;
use SilverStripe\Control\Session;
use SilverStripe\Control\RequestHandler; use SilverStripe\Control\RequestHandler;
use SilverStripe\Control\Session;
use SilverStripe\Core\ClassInfo; use SilverStripe\Core\ClassInfo;
use SilverStripe\Core\Convert; use SilverStripe\Core\Convert;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Dev\Deprecation; use SilverStripe\Dev\Deprecation;
use SilverStripe\Dev\TestOnly; use SilverStripe\Dev\TestOnly;
use SilverStripe\Forms\Form; use SilverStripe\Forms\Form;
use SilverStripe\ORM\ArrayList; use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\DataModel; use SilverStripe\ORM\DataModel;
use SilverStripe\ORM\DB;
use SilverStripe\ORM\DataObject; use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\DB;
use SilverStripe\ORM\FieldType\DBField; use SilverStripe\ORM\FieldType\DBField;
use SilverStripe\ORM\FieldType\DBHTMLText; use SilverStripe\ORM\FieldType\DBHTMLText;
use SilverStripe\ORM\ValidationResult; use SilverStripe\ORM\ValidationResult;
@ -222,7 +223,7 @@ class Security extends Controller implements TemplateGlobalProvider
protected static $currentUser; protected static $currentUser;
/** /**
* @return array * @return Authenticator[]
*/ */
public function getAuthenticators() public function getAuthenticators()
{ {
@ -230,16 +231,13 @@ class Security extends Controller implements TemplateGlobalProvider
} }
/** /**
* @param array|Authenticator $authenticators * @param Authenticator[] $authenticators
*/ */
public function setAuthenticators(array $authenticators) public function setAuthenticators(array $authenticators)
{ {
$this->authenticators = $authenticators; $this->authenticators = $authenticators;
} }
/**
* @inheritdoc
*/
protected function init() protected function init()
{ {
parent::init(); parent::init();
@ -257,9 +255,6 @@ class Security extends Controller implements TemplateGlobalProvider
} }
} }
/**
* @inheritdoc
*/
public function index() public function index()
{ {
return $this->httpError(404); // no-op return $this->httpError(404); // no-op
@ -287,15 +282,15 @@ class Security extends Controller implements TemplateGlobalProvider
* Get all registered authenticators * Get all registered authenticators
* *
* @param int $service The type of service that is requested * @param int $service The type of service that is requested
* @return array Return an array of Authenticator objects * @return Authenticator[] Return an array of Authenticator objects
*/ */
public function getApplicableAuthenticators($service = Authenticator::LOGIN) public function getApplicableAuthenticators($service = Authenticator::LOGIN)
{ {
$authenticators = $this->authenticators; $authenticators = $this->authenticators;
/** @var Authenticator $class */ /** @var Authenticator $authenticator */
foreach ($authenticators as $name => $class) { foreach ($authenticators as $name => $authenticator) {
if (!($class->supportedServices() & $service)) { if (!($authenticator->supportedServices() & $service)) {
unset($authenticators[$name]); unset($authenticators[$name]);
} }
} }
@ -468,8 +463,10 @@ class Security extends Controller implements TemplateGlobalProvider
Deprecation::notice('5.0.0', 'Now handled by delegateToMultipleHandlers'); Deprecation::notice('5.0.0', 'Now handled by delegateToMultipleHandlers');
return array_map( return array_map(
function ($authenticator) { function (Authenticator $authenticator) {
return [$authenticator->getLoginHandler($this->Link())->loginForm()]; return [
$authenticator->getLoginHandler($this->Link())->loginForm()
];
}, },
$this->getApplicableAuthenticators() $this->getApplicableAuthenticators()
); );
@ -601,16 +598,14 @@ class Security extends Controller implements TemplateGlobalProvider
// Create new instance of page holder // Create new instance of page holder
/** @var Page $holderPage */ /** @var Page $holderPage */
$holderPage = new $pageClass; $holderPage = Injector::inst()->create($pageClass);
$holderPage->Title = $title; $holderPage->Title = $title;
/** @skipUpgrade */ /** @skipUpgrade */
$holderPage->URLSegment = 'Security'; $holderPage->URLSegment = 'Security';
// Disable ID-based caching of the log-in page by making it a random number // Disable ID-based caching of the log-in page by making it a random number
$holderPage->ID = -1 * random_int(1, 10000000); $holderPage->ID = -1 * random_int(1, 10000000);
$controllerClass = $holderPage->getControllerName(); $controller = ModelAsController::controller_for($holderPage);
/** @var ContentController $controller */
$controller = $controllerClass::create($holderPage);
$controller->setDataModel($this->model); $controller->setDataModel($this->model);
$controller->doInit(); $controller->doInit();
@ -713,8 +708,7 @@ class Security extends Controller implements TemplateGlobalProvider
$link = $this->Link('login'); $link = $this->Link('login');
// Delegate to a single handler - Security/login/<authname>/... // Delegate to a single handler - Security/login/<authname>/...
if ($authName && $this->hasAuthenticator($authName) if ($authName && $this->hasAuthenticator($authName)) {
) {
if ($request) { if ($request) {
$request->shift(); $request->shift();
} }
@ -733,7 +727,7 @@ class Security extends Controller implements TemplateGlobalProvider
array_walk( array_walk(
$handlers, $handlers,
function (&$auth, $name) use ($link) { function (Authenticator &$auth, $name) use ($link) {
$auth = $auth->getLoginHandler(Controller::join_links($link, $name)); $auth = $auth->getLoginHandler(Controller::join_links($link, $name));
} }
); );
@ -766,7 +760,7 @@ class Security extends Controller implements TemplateGlobalProvider
// Process each of the handlers // Process each of the handlers
$results = array_map( $results = array_map(
function ($handler) { function (RequestHandler $handler) {
return $handler->handleRequest($this->getRequest(), DataModel::inst()); return $handler->handleRequest($this->getRequest(), DataModel::inst());
}, },
$handlers $handlers
@ -1200,6 +1194,8 @@ class Security extends Controller implements TemplateGlobalProvider
/** /**
* For the database_is_ready call to return a certain value - used for testing * For the database_is_ready call to return a certain value - used for testing
*
* @param bool $isReady
*/ */
public static function force_database_is_ready($isReady) public static function force_database_is_ready($isReady)
{ {
@ -1220,7 +1216,7 @@ class Security extends Controller implements TemplateGlobalProvider
/** /**
* Set to true to ignore access to disallowed actions, rather than returning permission failure * Set to true to ignore access to disallowed actions, rather than returning permission failure
* Note that this is just a flag that other code needs to check with Security::ignore_disallowed_actions() * Note that this is just a flag that other code needs to check with Security::ignore_disallowed_actions()
* @param $flag True or false * @param bool $flag True or false
*/ */
public static function set_ignore_disallowed_actions($flag) public static function set_ignore_disallowed_actions($flag)
{ {

View File

@ -2,11 +2,11 @@
namespace SilverStripe\Security; namespace SilverStripe\Security;
use SilverStripe\Control\Controller;
use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\Session;
use SilverStripe\Core\Config\Configurable; use SilverStripe\Core\Config\Configurable;
use SilverStripe\Core\Injector\Injectable; use SilverStripe\Core\Injector\Injectable;
use SilverStripe\Control\Session;
use SilverStripe\Control\Controller;
use SilverStripe\Forms\FieldList; use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\HiddenField; use SilverStripe\Forms\HiddenField;
use SilverStripe\View\TemplateGlobalProvider; use SilverStripe\View\TemplateGlobalProvider;
@ -61,11 +61,11 @@ class SecurityToken implements TemplateGlobalProvider
protected $name = null; protected $name = null;
/** /**
* @param $name * @param string $name
*/ */
public function __construct($name = null) public function __construct($name = null)
{ {
$this->name = ($name) ? $name : self::get_default_name(); $this->name = $name ?: self::get_default_name();
} }
/** /**