API HTTPRequestBuilder::createFromEnvironment() now cleans up live globals

BUG Fix issue with SSViewer
Fix Security / View tests
This commit is contained in:
Damian Mooyman 2017-06-21 12:13:15 +12:00
parent d88d4ed4e4
commit 5d235e64f3
No known key found for this signature in database
GPG Key ID: 78B823A10DE27D1A
30 changed files with 228 additions and 147 deletions

View File

@ -7,7 +7,7 @@ namespace SilverStripe\Control;
*/ */
class CLIRequestBuilder extends HTTPRequestBuilder class CLIRequestBuilder extends HTTPRequestBuilder
{ {
protected static function cleanEnvironment(array $variables) public static function cleanEnvironment(array $variables)
{ {
// Create all blank vars // Create all blank vars
foreach (['_REQUEST', '_GET', '_POST', '_SESSION', '_SERVER', '_COOKIE', '_ENV', '_FILES'] as $key) { foreach (['_REQUEST', '_GET', '_POST', '_SESSION', '_SERVER', '_COOKIE', '_ENV', '_FILES'] as $key) {

View File

@ -315,6 +315,9 @@ class Director implements TemplateGlobalProvider
$newVars['_SERVER']['REQUEST_URI'] = Director::baseURL() . $url; $newVars['_SERVER']['REQUEST_URI'] = Director::baseURL() . $url;
$newVars['_REQUEST'] = array_merge($newVars['_GET'], $newVars['_POST']); $newVars['_REQUEST'] = array_merge($newVars['_GET'], $newVars['_POST']);
// Normalise vars
$newVars = HTTPRequestBuilder::cleanEnvironment($newVars);
// Create new request // Create new request
$request = HTTPRequestBuilder::createFromVariables($newVars, $body); $request = HTTPRequestBuilder::createFromVariables($newVars, $body);
if ($headers) { if ($headers) {

View File

@ -15,8 +15,12 @@ class HTTPRequestBuilder
*/ */
public static function createFromEnvironment() public static function createFromEnvironment()
{ {
// Clean and update live global variables
$variables = static::cleanEnvironment(Environment::getVariables());
Environment::setVariables($variables); // Currently necessary for SSViewer, etc to work
// Health-check prior to creating environment // Health-check prior to creating environment
return static::createFromVariables(Environment::getVariables(), @file_get_contents('php://input')); return static::createFromVariables($variables, @file_get_contents('php://input'));
} }
/** /**
@ -28,8 +32,6 @@ class HTTPRequestBuilder
*/ */
public static function createFromVariables(array $variables, $input) public static function createFromVariables(array $variables, $input)
{ {
$variables = static::cleanEnvironment($variables);
// Strip `url` out of querystring // Strip `url` out of querystring
$url = $variables['_GET']['url']; $url = $variables['_GET']['url'];
unset($variables['_GET']['url']); unset($variables['_GET']['url']);
@ -92,7 +94,7 @@ class HTTPRequestBuilder
* @param array $variables * @param array $variables
* @return array Cleaned variables * @return array Cleaned variables
*/ */
protected static function cleanEnvironment(array $variables) public static function cleanEnvironment(array $variables)
{ {
// IIS will sometimes generate this. // IIS will sometimes generate this.
if (!empty($variables['_SERVER']['HTTP_X_ORIGINAL_URL'])) { if (!empty($variables['_SERVER']['HTTP_X_ORIGINAL_URL'])) {

View File

@ -34,7 +34,7 @@ class TempFolder
* *
* @return string * @return string
*/ */
protected static function getTempFolderUsername() public static function getTempFolderUsername()
{ {
$user = getenv('APACHE_RUN_USER'); $user = getenv('APACHE_RUN_USER');
if (!$user) { if (!$user) {

View File

@ -69,7 +69,7 @@ class CSSContentParser
* See {@link getByXpath()} for a more direct selector syntax. * See {@link getByXpath()} for a more direct selector syntax.
* *
* @param String $selector * @param String $selector
* @return SimpleXMLElement * @return SimpleXMLElement[]
*/ */
public function getBySelector($selector) public function getBySelector($selector)
{ {
@ -81,7 +81,7 @@ class CSSContentParser
* Allows querying the content through XPATH selectors. * Allows querying the content through XPATH selectors.
* *
* @param String $xpath SimpleXML compatible XPATH statement * @param String $xpath SimpleXML compatible XPATH statement
* @return SimpleXMLElement|false * @return SimpleXMLElement[]
*/ */
public function getByXpath($xpath) public function getByXpath($xpath)
{ {

View File

@ -6,6 +6,7 @@ use Exception;
use LogicException; use LogicException;
use PHPUnit_Framework_TestCase; use PHPUnit_Framework_TestCase;
use SilverStripe\CMS\Controllers\RootURLController; use SilverStripe\CMS\Controllers\RootURLController;
use SilverStripe\Control\CLIRequestBuilder;
use SilverStripe\Control\Controller; use SilverStripe\Control\Controller;
use SilverStripe\Control\Cookie; use SilverStripe\Control\Cookie;
use SilverStripe\Control\Director; use SilverStripe\Control\Director;
@ -889,9 +890,8 @@ class SapphireTest extends PHPUnit_Framework_TestCase
static::set_is_running_test(true); static::set_is_running_test(true);
// Mock request // Mock request
$session = new Session(isset($_SESSION) ? $_SESSION : array()); $_SERVER['argv'] = ['vendor/bin/phpunit', '/'];
$request = new HTTPRequest('GET', '/'); $request = CLIRequestBuilder::createFromEnvironment();
$request->setSession($session);
// Test application // Test application
$kernel = new TestKernel(BASE_PATH); $kernel = new TestKernel(BASE_PATH);

View File

@ -2,9 +2,12 @@
namespace SilverStripe\Forms; namespace SilverStripe\Forms;
use BadMethodCallException;
use SilverStripe\Control\Controller; use SilverStripe\Control\Controller;
use SilverStripe\Control\HasRequestHandler; use SilverStripe\Control\HasRequestHandler;
use SilverStripe\Control\HTTP; use SilverStripe\Control\HTTP;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\NullHTTPRequest;
use SilverStripe\Control\RequestHandler; use SilverStripe\Control\RequestHandler;
use SilverStripe\Control\Session; use SilverStripe\Control\Session;
use SilverStripe\Core\ClassInfo; use SilverStripe\Core\ClassInfo;
@ -341,6 +344,25 @@ class Form extends ViewableData implements HasRequestHandler
return $this; return $this;
} }
/**
* Helper to get current request for this form
*
* @return HTTPRequest
*/
protected function getRequest()
{
// Check if current request handler has a request object
$controller = $this->getController();
if ($controller && !($controller->getRequest() instanceof NullHTTPRequest)) {
return $controller->getRequest();
}
// Fall back to current controller
if (Controller::has_curr() && !(Controller::curr()->getRequest() instanceof NullHTTPRequest)) {
return Controller::curr()->getRequest();
}
return null;
}
/** /**
* Get session for this form * Get session for this form
* *
@ -348,9 +370,11 @@ class Form extends ViewableData implements HasRequestHandler
*/ */
protected function getSession() protected function getSession()
{ {
// Note: Session may not be available if this form doesn't have a request handler $request = $this->getRequest();
$controller = $this->getController() ?: Controller::curr(); if ($request) {
return $controller->getRequest()->getSession(); return $request->getSession();
}
throw new BadMethodCallException("Session not available in the current context");
} }
/** /**

View File

@ -8,7 +8,7 @@ use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse; 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\Debug;
use SilverStripe\Security\MemberAuthenticator\MemberAuthenticator; use SilverStripe\Security\MemberAuthenticator\MemberAuthenticator;
/** /**

View File

@ -18,9 +18,12 @@ class DefaultAdminService
use Injectable; use Injectable;
/** /**
* @var bool * Can be set to explicitly true or false, or left null.
* If null, hasDefaultAdmin() will be inferred from environment.
*
* @var bool|null
*/ */
protected static $has_default_admin = false; protected static $has_default_admin = null;
/** /**
* @var string * @var string
@ -72,7 +75,7 @@ class DefaultAdminService
"No default admin configured. Please call hasDefaultAdmin() before getting default admin username" "No default admin configured. Please call hasDefaultAdmin() before getting default admin username"
); );
} }
return static::$default_username; return static::$default_username ?: getenv('SS_DEFAULT_ADMIN_USERNAME');
} }
/** /**
@ -86,7 +89,7 @@ class DefaultAdminService
"No default admin configured. Please call hasDefaultAdmin() before getting default admin password" "No default admin configured. Please call hasDefaultAdmin() before getting default admin password"
); );
} }
return static::$default_password; return static::$default_password ?: getenv('SS_DEFAULT_ADMIN_PASSWORD');
} }
/** /**
@ -96,11 +99,16 @@ class DefaultAdminService
*/ */
public static function hasDefaultAdmin() public static function hasDefaultAdmin()
{ {
// Check environment if not explicitly set
if (!isset(static::$has_default_admin)) {
return !empty(getenv('SS_DEFAULT_ADMIN_USERNAME'))
&& !empty(getenv('SS_DEFAULT_ADMIN_PASSWORD'));
}
return static::$has_default_admin; return static::$has_default_admin;
} }
/** /**
* Flush the default admin credentials * Flush the default admin credentials.
*/ */
public static function clearDefaultAdmin() public static function clearDefaultAdmin()
{ {

View File

@ -3,17 +3,16 @@
namespace SilverStripe\Security\MemberAuthenticator; namespace SilverStripe\Security\MemberAuthenticator;
use InvalidArgumentException; use InvalidArgumentException;
use SilverStripe\Control\Controller;
use SilverStripe\Control\Session;
use SilverStripe\Core\Extensible;
use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPRequest;
use SilverStripe\Core\Extensible;
use SilverStripe\Dev\Debug;
use SilverStripe\ORM\ValidationResult; use SilverStripe\ORM\ValidationResult;
use SilverStripe\Security\Authenticator; use SilverStripe\Security\Authenticator;
use SilverStripe\Security\DefaultAdminService;
use SilverStripe\Security\LoginAttempt; use SilverStripe\Security\LoginAttempt;
use SilverStripe\Security\Member; use SilverStripe\Security\Member;
use SilverStripe\Security\PasswordEncryptor; use SilverStripe\Security\PasswordEncryptor;
use SilverStripe\Security\Security; use SilverStripe\Security\Security;
use SilverStripe\Security\DefaultAdminService;
/** /**
* Authenticator for the default "member" method * Authenticator for the default "member" method
@ -69,15 +68,15 @@ class MemberAuthenticator implements Authenticator
if ($result->isValid()) { if ($result->isValid()) {
// Check if default admin credentials are correct // Check if default admin credentials are correct
if (DefaultAdminService::isDefaultAdminCredentials($email, $data['Password'])) { if (DefaultAdminService::isDefaultAdminCredentials($email, $data['Password'])) {
return $member; return $member;
} else { } else {
$result->addError(_t( $result->addError(_t(
'SilverStripe\\Security\\Member.ERRORWRONGCRED', 'SilverStripe\\Security\\Member.ERRORWRONGCRED',
"The provided details don't seem to be correct. Please try again." "The provided details don't seem to be correct. Please try again."
)); ));
}
} }
} }
}
// Attempt to identify user by email // Attempt to identify user by email
if (!$member && $email) { if (!$member && $email) {

View File

@ -4,7 +4,6 @@ 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\Forms\CheckboxField; use SilverStripe\Forms\CheckboxField;
use SilverStripe\Forms\FieldList; use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\FormAction; use SilverStripe\Forms\FormAction;
@ -124,11 +123,11 @@ class MemberLoginForm extends BaseLoginForm
*/ */
protected function getFormFields() protected function getFormFields()
{ {
$request = $this->getController()->getRequest(); $request = $this->getRequest();
if ($request->getVar('BackURL')) { if ($request->getVar('BackURL')) {
$backURL = $request->getVar('BackURL'); $backURL = $request->getVar('BackURL');
} else { } else {
$backURL = Session::get('BackURL'); $backURL = $request->getSession()->get('BackURL');
} }
$label = Member::singleton()->fieldLabel(Member::config()->get('unique_identifier_field')); $label = Member::singleton()->fieldLabel(Member::config()->get('unique_identifier_field'));
@ -191,11 +190,13 @@ class MemberLoginForm extends BaseLoginForm
return $actions; return $actions;
} }
public function restoreFormState() public function restoreFormState()
{ {
parent::restoreFormState(); parent::restoreFormState();
$session = Controller::curr()->getRequest()->getSession(); $session = $this->getSession();
$forceMessage = $session->get('MemberLoginForm.force_message'); $forceMessage = $session->get('MemberLoginForm.force_message');
if (($member = Security::getCurrentUser()) && !$forceMessage) { if (($member = Security::getCurrentUser()) && !$forceMessage) {
$message = _t( $message = _t(

View File

@ -391,7 +391,7 @@ class Security extends Controller implements TemplateGlobalProvider
} }
static::singleton()->setLoginMessage($message, ValidationResult::TYPE_WARNING); static::singleton()->setLoginMessage($message, ValidationResult::TYPE_WARNING);
$loginResponse = static::singleton()->login(); $loginResponse = static::singleton()->login($controller ? $controller->getRequest() : $controller);
if ($loginResponse instanceof HTTPResponse) { if ($loginResponse instanceof HTTPResponse) {
return $loginResponse; return $loginResponse;
} }
@ -702,16 +702,20 @@ class Security extends Controller implements TemplateGlobalProvider
*/ */
public function login($request = null, $service = Authenticator::LOGIN) public function login($request = null, $service = Authenticator::LOGIN)
{ {
if ($request) {
$this->setRequest($request);
} elseif ($request) {
$request = $this->getRequest();
} else {
throw new HTTPResponse_Exception("No request available", 500);
}
// Check pre-login process // Check pre-login process
if ($response = $this->preLogin()) { if ($response = $this->preLogin()) {
return $response; return $response;
} }
$authName = null; $authName = null;
if (!$request) {
$request = $this->getRequest();
}
if ($request && $request->param('ID')) { if ($request && $request->param('ID')) {
$authName = $request->param('ID'); $authName = $request->param('ID');
} }

View File

@ -1325,9 +1325,12 @@ class Requirements_Backend
if ($minify && !$this->minifier) { if ($minify && !$this->minifier) {
throw new Exception( throw new Exception(
sprintf( sprintf(
'Cannot minify files without a minification service defined. <<<MESSAGE
Set %s::minifyCombinedFiles to false, or inject a %s service on Cannot minify files without a minification service defined.
%s.properties.minifier', Set %s::minifyCombinedFiles to false, or inject a %s service on
%s.properties.minifier
MESSAGE
,
__CLASS__, __CLASS__,
Requirements_Minifier::class, Requirements_Minifier::class,
__CLASS__ __CLASS__

View File

@ -2,9 +2,10 @@
namespace SilverStripe\Control\Tests; namespace SilverStripe\Control\Tests;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Control\PjaxResponseNegotiator;
use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\PjaxResponseNegotiator;
use SilverStripe\Control\Session;
use SilverStripe\Dev\SapphireTest;
class PjaxResponseNegotiatorTest extends SapphireTest class PjaxResponseNegotiatorTest extends SapphireTest
{ {
@ -19,6 +20,7 @@ class PjaxResponseNegotiatorTest extends SapphireTest
) )
); );
$request = new HTTPRequest('GET', '/'); // not setting pjax header $request = new HTTPRequest('GET', '/'); // not setting pjax header
$request->setSession(new Session([]));
$response = $negotiator->respond($request); $response = $negotiator->respond($request);
$this->assertEquals('default response', $response->getBody()); $this->assertEquals('default response', $response->getBody());
} }
@ -36,6 +38,7 @@ class PjaxResponseNegotiatorTest extends SapphireTest
) )
); );
$request = new HTTPRequest('GET', '/'); $request = new HTTPRequest('GET', '/');
$request->setSession(new Session([]));
$request->addHeader('X-Pjax', 'myfragment'); $request->addHeader('X-Pjax', 'myfragment');
$response = $negotiator->respond($request); $response = $negotiator->respond($request);
$this->assertEquals('{"myfragment":"myfragment response"}', $response->getBody()); $this->assertEquals('{"myfragment":"myfragment response"}', $response->getBody());
@ -57,6 +60,7 @@ class PjaxResponseNegotiatorTest extends SapphireTest
) )
); );
$request = new HTTPRequest('GET', '/'); $request = new HTTPRequest('GET', '/');
$request->setSession(new Session([]));
$request->addHeader('X-Pjax', 'myfragment,otherfragment'); $request->addHeader('X-Pjax', 'myfragment,otherfragment');
$request->addHeader('Accept', 'text/json'); $request->addHeader('Accept', 'text/json');
$response = $negotiator->respond($request); $response = $negotiator->respond($request);
@ -81,6 +85,7 @@ class PjaxResponseNegotiatorTest extends SapphireTest
); );
$request = new HTTPRequest('GET', '/'); $request = new HTTPRequest('GET', '/');
$request->setSession(new Session([]));
$request->addHeader('X-Pjax', 'alpha'); $request->addHeader('X-Pjax', 'alpha');
$request->addHeader('Accept', 'text/json'); $request->addHeader('Accept', 'text/json');

View File

@ -2,6 +2,7 @@
namespace SilverStripe\Core\Tests; namespace SilverStripe\Core\Tests;
use SilverStripe\Core\TempFolder;
use SilverStripe\Dev\SapphireTest; use SilverStripe\Dev\SapphireTest;
use SilverStripe\Control\Director; use SilverStripe\Control\Director;
@ -22,31 +23,31 @@ class CoreTest extends SapphireTest
public function testGetTempPathInProject() public function testGetTempPathInProject()
{ {
$user = getTempFolderUsername(); $user = TempFolder::getTempFolderUsername();
if (file_exists($this->tempPath)) { if (file_exists($this->tempPath)) {
$this->assertEquals(getTempFolder(BASE_PATH), $this->tempPath . DIRECTORY_SEPARATOR . $user); $this->assertEquals(TempFolder::getTempFolder(BASE_PATH), $this->tempPath . DIRECTORY_SEPARATOR . $user);
} else { } else {
$user = getTempFolderUsername(); $user = TempFolder::getTempFolderUsername();
$base = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'silverstripe-cache-php' . $base = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'silverstripe-cache-php' .
preg_replace('/[^\w-\.+]+/', '-', PHP_VERSION); preg_replace('/[^\w-\.+]+/', '-', PHP_VERSION);
// A typical Windows location for where sites are stored on IIS // A typical Windows location for where sites are stored on IIS
$this->assertEquals( $this->assertEquals(
$base . 'C--inetpub-wwwroot-silverstripe-test-project' . DIRECTORY_SEPARATOR . $user, $base . 'C--inetpub-wwwroot-silverstripe-test-project' . DIRECTORY_SEPARATOR . $user,
getTempFolder('C:\\inetpub\\wwwroot\\silverstripe-test-project') TempFolder::getTempFolder('C:\\inetpub\\wwwroot\\silverstripe-test-project')
); );
// A typical Mac OS X location for where sites are stored // A typical Mac OS X location for where sites are stored
$this->assertEquals( $this->assertEquals(
$base . '-Users-joebloggs-Sites-silverstripe-test-project' . DIRECTORY_SEPARATOR . $user, $base . '-Users-joebloggs-Sites-silverstripe-test-project' . DIRECTORY_SEPARATOR . $user,
getTempFolder('/Users/joebloggs/Sites/silverstripe-test-project') TempFolder::getTempFolder('/Users/joebloggs/Sites/silverstripe-test-project')
); );
// A typical Linux location for where sites are stored // A typical Linux location for where sites are stored
$this->assertEquals( $this->assertEquals(
$base . '-var-www-silverstripe-test-project' . DIRECTORY_SEPARATOR . $user, $base . '-var-www-silverstripe-test-project' . DIRECTORY_SEPARATOR . $user,
getTempFolder('/var/www/silverstripe-test-project') TempFolder::getTempFolder('/var/www/silverstripe-test-project')
); );
} }
} }
@ -54,7 +55,7 @@ class CoreTest extends SapphireTest
protected function tearDown() protected function tearDown()
{ {
parent::tearDown(); parent::tearDown();
$user = getTempFolderUsername(); $user = TempFolder::getTempFolderUsername();
$base = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'silverstripe-cache-php' . $base = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'silverstripe-cache-php' .
preg_replace('/[^\w-\.+]+/', '-', PHP_VERSION); preg_replace('/[^\w-\.+]+/', '-', PHP_VERSION);
foreach (array( foreach (array(

View File

@ -1,6 +1 @@
<?php <?php
use SilverStripe\Control\Director;
// Dynamically change environment
Director::set_environment_type('dev');

View File

@ -4,6 +4,7 @@ namespace SilverStripe\Core\Tests\Startup;
use SilverStripe\Control\Controller; use SilverStripe\Control\Controller;
use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\Session;
use SilverStripe\Core\Startup\ParameterConfirmationToken; use SilverStripe\Core\Startup\ParameterConfirmationToken;
use SilverStripe\Core\Tests\Startup\ParameterConfirmationTokenTest\ParameterConfirmationTokenTest_Token; use SilverStripe\Core\Tests\Startup\ParameterConfirmationTokenTest\ParameterConfirmationTokenTest_Token;
use SilverStripe\Core\Tests\Startup\ParameterConfirmationTokenTest\ParameterConfirmationTokenTest_ValidToken; use SilverStripe\Core\Tests\Startup\ParameterConfirmationTokenTest\ParameterConfirmationTokenTest_ValidToken;
@ -29,6 +30,7 @@ class ParameterConfirmationTokenTest extends SapphireTest
$get['parameterconfirmationtokentest_emptytoken'] = '1'; $get['parameterconfirmationtokentest_emptytoken'] = '1';
$get['parameterconfirmationtokentest_emptytokentoken'] = ''; $get['parameterconfirmationtokentest_emptytokentoken'] = '';
$this->request = new HTTPRequest('GET', '/', $get); $this->request = new HTTPRequest('GET', '/', $get);
$this->request->setSession(new Session([]));
} }
public function testParameterDetectsParameters() public function testParameterDetectsParameters()

View File

@ -4,6 +4,7 @@ namespace SilverStripe\Forms\Tests;
use SilverStripe\Control\Controller; use SilverStripe\Control\Controller;
use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\Session;
use SilverStripe\Dev\SapphireTest; use SilverStripe\Dev\SapphireTest;
use SilverStripe\Forms\FieldList; use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\FormAction; use SilverStripe\Forms\FormAction;
@ -24,6 +25,7 @@ class FormRequestHandlerTest extends SapphireTest
$form->disableSecurityToken(); $form->disableSecurityToken();
$handler = new TestFormRequestHandler($form); $handler = new TestFormRequestHandler($form);
$request = new HTTPRequest('POST', '/', null, ['action_mySubmitOnFormHandler' => 1]); $request = new HTTPRequest('POST', '/', null, ['action_mySubmitOnFormHandler' => 1]);
$request->setSession(new Session([]));
$response = $handler->httpSubmission($request); $response = $handler->httpSubmission($request);
$this->assertFalse($response->isError()); $this->assertFalse($response->isError());
} }
@ -39,6 +41,7 @@ class FormRequestHandlerTest extends SapphireTest
$form->disableSecurityToken(); $form->disableSecurityToken();
$handler = new FormRequestHandler($form); $handler = new FormRequestHandler($form);
$request = new HTTPRequest('POST', '/', null, ['action_mySubmitOnForm' => 1]); $request = new HTTPRequest('POST', '/', null, ['action_mySubmitOnForm' => 1]);
$request->setSession(new Session([]));
$response = $handler->httpSubmission($request); $response = $handler->httpSubmission($request);
$this->assertFalse($response->isError()); $this->assertFalse($response->isError());
} }

View File

@ -2,6 +2,7 @@
namespace SilverStripe\Forms\Tests; namespace SilverStripe\Forms\Tests;
use SilverStripe\Control\Session;
use SilverStripe\Forms\Tests\FormTest\TestController; use SilverStripe\Forms\Tests\FormTest\TestController;
use SilverStripe\Forms\Tests\FormTest\ControllerWithSecurityToken; use SilverStripe\Forms\Tests\FormTest\ControllerWithSecurityToken;
use SilverStripe\Forms\Tests\FormTest\ControllerWithStrictPostCheck; use SilverStripe\Forms\Tests\FormTest\ControllerWithStrictPostCheck;
@ -778,6 +779,7 @@ class FormTest extends FunctionalTest
'action_doSubmit' => 1 'action_doSubmit' => 1
) )
); );
$request->setSession(new Session([]));
$form->getRequestHandler()->httpSubmission($request); $form->getRequestHandler()->httpSubmission($request);
$button = $form->getRequestHandler()->buttonClicked(); $button = $form->getRequestHandler()->buttonClicked();
@ -798,6 +800,7 @@ class FormTest extends FunctionalTest
'action_doSubmit' => 1 'action_doSubmit' => 1
) )
); );
$request->setSession(new Session([]));
$form->getRequestHandler()->httpSubmission($request); $form->getRequestHandler()->httpSubmission($request);
$button = $form->getRequestHandler()->buttonClicked(); $button = $form->getRequestHandler()->buttonClicked();

View File

@ -5,6 +5,7 @@ namespace SilverStripe\Forms\Tests\GridField;
use SilverStripe\Control\Controller; use SilverStripe\Control\Controller;
use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse_Exception; use SilverStripe\Control\HTTPResponse_Exception;
use SilverStripe\Control\Session;
use SilverStripe\Dev\CSSContentParser; use SilverStripe\Dev\CSSContentParser;
use SilverStripe\Dev\SapphireTest; use SilverStripe\Dev\SapphireTest;
use SilverStripe\Forms\FieldList; use SilverStripe\Forms\FieldList;
@ -108,6 +109,7 @@ class GridFieldDeleteActionTest extends SapphireTest
'SecurityID' => null, 'SecurityID' => null,
) )
); );
$request->setSession(new Session([]));
$this->gridField->gridFieldAlterAction(array('StateID'=>$stateID), $this->form, $request); $this->gridField->gridFieldAlterAction(array('StateID'=>$stateID), $this->form, $request);
} }

View File

@ -4,6 +4,7 @@ namespace SilverStripe\Forms\Tests;
use SilverStripe\Assets\File; use SilverStripe\Assets\File;
use SilverStripe\Assets\Folder; use SilverStripe\Assets\Folder;
use SilverStripe\Control\Session;
use SilverStripe\Dev\CSSContentParser; use SilverStripe\Dev\CSSContentParser;
use SilverStripe\Dev\SapphireTest; use SilverStripe\Dev\SapphireTest;
use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPRequest;
@ -21,6 +22,7 @@ class TreeDropdownFieldTest extends SapphireTest
// case insensitive search against keyword 'sub' for folders // case insensitive search against keyword 'sub' for folders
$request = new HTTPRequest('GET', 'url', array('search'=>'sub')); $request = new HTTPRequest('GET', 'url', array('search'=>'sub'));
$request->setSession(new Session([]));
$response = $field->tree($request); $response = $field->tree($request);
$tree = $response->getBody(); $tree = $response->getBody();
@ -58,6 +60,7 @@ class TreeDropdownFieldTest extends SapphireTest
// case insensitive search against keyword 'sub' for files // case insensitive search against keyword 'sub' for files
$request = new HTTPRequest('GET', 'url', array('search'=>'sub')); $request = new HTTPRequest('GET', 'url', array('search'=>'sub'));
$request->setSession(new Session([]));
$response = $field->tree($request); $response = $field->tree($request);
$tree = $response->getBody(); $tree = $response->getBody();

View File

@ -2,6 +2,7 @@
namespace SilverStripe\Security\Tests; namespace SilverStripe\Security\Tests;
use SilverStripe\Security\BasicAuth;
use SilverStripe\Security\Member; use SilverStripe\Security\Member;
use SilverStripe\Security\Security; use SilverStripe\Security\Security;
use SilverStripe\Dev\FunctionalTest; use SilverStripe\Dev\FunctionalTest;
@ -29,24 +30,21 @@ class BasicAuthTest extends FunctionalTest
parent::setUp(); parent::setUp();
// Fixtures assume Email is the field used to identify the log in identity // Fixtures assume Email is the field used to identify the log in identity
Member::config()->unique_identifier_field = 'Email'; Member::config()->set('unique_identifier_field', 'Email');
Security::force_database_is_ready(true); // Prevents Member test subclasses breaking ready test Security::force_database_is_ready(true); // Prevents Member test subclasses breaking ready test
Member::config()->lock_out_after_incorrect_logins = 10; Member::config()->set('lock_out_after_incorrect_logins', 10);
// Temp disable is_cli() exemption for tests
BasicAuth::config()->set('ignore_cli', false);
} }
public function testBasicAuthEnabledWithoutLogin() public function testBasicAuthEnabledWithoutLogin()
{ {
$origUser = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : null;
$origPw = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : null;
unset($_SERVER['PHP_AUTH_USER']); unset($_SERVER['PHP_AUTH_USER']);
unset($_SERVER['PHP_AUTH_PW']); unset($_SERVER['PHP_AUTH_PW']);
$response = Director::test('BasicAuthTest_ControllerSecuredWithPermission', null, $_SESSION, null, null, $_SERVER); $response = Director::test('BasicAuthTest_ControllerSecuredWithPermission');
$this->assertEquals(401, $response->getStatusCode()); $this->assertEquals(401, $response->getStatusCode());
$_SERVER['PHP_AUTH_USER'] = $origUser;
$_SERVER['PHP_AUTH_PW'] = $origPw;
} }
public function testBasicAuthDoesntCallActionOrFurtherInitOnAuthFailure() public function testBasicAuthDoesntCallActionOrFurtherInitOnAuthFailure()

View File

@ -29,6 +29,7 @@ class ControllerSecuredWithPermission extends Controller implements TestOnly
public function index() public function index()
{ {
self::$index_called = true; self::$index_called = true;
return "index";
} }
public function Link($action = null) public function Link($action = null)

View File

@ -2,18 +2,18 @@
namespace SilverStripe\Security\Tests; namespace SilverStripe\Security\Tests;
use InvalidArgumentException;
use SilverStripe\Control\Controller; use SilverStripe\Control\Controller;
use SilverStripe\Dev\FunctionalTest;
use SilverStripe\ORM\ArrayList; use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\DataObject; use SilverStripe\ORM\DataObject;
use SilverStripe\Security\Group; use SilverStripe\Security\Group;
use SilverStripe\Dev\FunctionalTest; use SilverStripe\Security\Member;
use SilverStripe\Control\Session;
use SilverStripe\Security\Permission; use SilverStripe\Security\Permission;
use SilverStripe\Security\Tests\GroupTest\TestMember; use SilverStripe\Security\Tests\GroupTest\TestMember;
class GroupTest extends FunctionalTest class GroupTest extends FunctionalTest
{ {
protected static $fixture_file = 'GroupTest.yml'; protected static $fixture_file = 'GroupTest.yml';
protected static $extra_dataobjects = [ protected static $extra_dataobjects = [
@ -44,13 +44,14 @@ class GroupTest extends FunctionalTest
*/ */
public function testMemberGroupRelationForm() public function testMemberGroupRelationForm()
{ {
Session::set('loggedInAs', $this->idFromFixture(TestMember::class, 'admin')); $this->logInAs($this->idFromFixture(TestMember::class, 'admin'));
$adminGroup = $this->objFromFixture(Group::class, 'admingroup'); $adminGroup = $this->objFromFixture(Group::class, 'admingroup');
$parentGroup = $this->objFromFixture(Group::class, 'parentgroup'); $parentGroup = $this->objFromFixture(Group::class, 'parentgroup');
// Test single group relation through checkboxsetfield // Test single group relation through checkboxsetfield
$form = new GroupTest\MemberForm(Controller::curr(), 'Form'); $form = new GroupTest\MemberForm(Controller::curr(), 'Form');
/** @var Member $member */
$member = $this->objFromFixture(TestMember::class, 'admin'); $member = $this->objFromFixture(TestMember::class, 'admin');
$form->loadDataFrom($member); $form->loadDataFrom($member);
$checkboxSetField = $form->Fields()->fieldByName('Groups'); $checkboxSetField = $form->Fields()->fieldByName('Groups');
@ -110,7 +111,9 @@ class GroupTest extends FunctionalTest
public function testCollateAncestorIDs() public function testCollateAncestorIDs()
{ {
/** @var Group $parentGroup */
$parentGroup = $this->objFromFixture(Group::class, 'parentgroup'); $parentGroup = $this->objFromFixture(Group::class, 'parentgroup');
/** @var Group $childGroup */
$childGroup = $this->objFromFixture(Group::class, 'childgroup'); $childGroup = $this->objFromFixture(Group::class, 'childgroup');
$orphanGroup = new Group(); $orphanGroup = new Group();
$orphanGroup->ParentID = 99999; $orphanGroup->ParentID = 99999;
@ -144,6 +147,7 @@ class GroupTest extends FunctionalTest
*/ */
public function testCollateFamilyIds() public function testCollateFamilyIds()
{ {
/** @var Group $group */
$group = $this->objFromFixture(Group::class, 'parentgroup'); $group = $this->objFromFixture(Group::class, 'parentgroup');
$groupIds = $this->allFixtureIDs(Group::class); $groupIds = $this->allFixtureIDs(Group::class);
$ids = array_intersect_key($groupIds, array_flip(['parentgroup', 'childgroup', 'grandchildgroup'])); $ids = array_intersect_key($groupIds, array_flip(['parentgroup', 'childgroup', 'grandchildgroup']));
@ -152,11 +156,11 @@ class GroupTest extends FunctionalTest
/** /**
* Test that an exception is thrown if collateFamilyIDs is called on an unsaved Group * Test that an exception is thrown if collateFamilyIDs is called on an unsaved Group
* @expectedException InvalidArgumentException
* @expectedExceptionMessage Cannot call collateFamilyIDs on unsaved Group.
*/ */
public function testCannotCollateUnsavedGroupFamilyIds() public function testCannotCollateUnsavedGroupFamilyIds()
{ {
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Cannot call collateFamilyIDs on unsaved Group.');
$group = new Group; $group = new Group;
$group->collateFamilyIDs(); $group->collateFamilyIDs();
} }
@ -166,8 +170,8 @@ class GroupTest extends FunctionalTest
*/ */
public function testGetAllChildren() public function testGetAllChildren()
{ {
/** @var Group $group */
$group = $this->objFromFixture(Group::class, 'parentgroup'); $group = $this->objFromFixture(Group::class, 'parentgroup');
$children = $group->getAllChildren(); $children = $group->getAllChildren();
$this->assertInstanceOf(ArrayList::class, $children); $this->assertInstanceOf(ArrayList::class, $children);
$this->assertSame(['childgroup', 'grandchildgroup'], $children->column('Code')); $this->assertSame(['childgroup', 'grandchildgroup'], $children->column('Code'));
@ -204,7 +208,9 @@ class GroupTest extends FunctionalTest
public function testValidatesPrivilegeLevelOfParent() public function testValidatesPrivilegeLevelOfParent()
{ {
/** @var Group $nonAdminGroup */
$nonAdminGroup = $this->objFromFixture(Group::class, 'childgroup'); $nonAdminGroup = $this->objFromFixture(Group::class, 'childgroup');
/** @var Group $adminGroup */
$adminGroup = $this->objFromFixture(Group::class, 'admingroup'); $adminGroup = $this->objFromFixture(Group::class, 'admingroup');
// Making admin group parent of a non-admin group, effectively expanding is privileges // Making admin group parent of a non-admin group, effectively expanding is privileges
@ -226,6 +232,7 @@ class GroupTest extends FunctionalTest
$nonAdminGroup->write(); $nonAdminGroup->write();
$this->logInWithPermission('ADMIN'); $this->logInWithPermission('ADMIN');
/** @var Group $inheritedAdminGroup */
$inheritedAdminGroup = $this->objFromFixture(Group::class, 'group1'); $inheritedAdminGroup = $this->objFromFixture(Group::class, 'group1');
$inheritedAdminGroup->ParentID = $adminGroup->ID; $inheritedAdminGroup->ParentID = $adminGroup->ID;
$inheritedAdminGroup->write(); // only works with ADMIN login $inheritedAdminGroup->write(); // only works with ADMIN login

View File

@ -3,21 +3,20 @@
namespace SilverStripe\Security\Tests; namespace SilverStripe\Security\Tests;
use SilverStripe\Control\Controller; use SilverStripe\Control\Controller;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Injector\Injector; use SilverStripe\Core\Injector\Injector;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\ORM\FieldType\DBDatetime; use SilverStripe\ORM\FieldType\DBDatetime;
use SilverStripe\ORM\ValidationResult; use SilverStripe\ORM\ValidationResult;
use SilverStripe\Security\Authenticator; use SilverStripe\Security\Authenticator;
use SilverStripe\Security\DefaultAdminService;
use SilverStripe\Security\IdentityStore;
use SilverStripe\Security\Member;
use SilverStripe\Security\MemberAuthenticator\CMSMemberAuthenticator; use SilverStripe\Security\MemberAuthenticator\CMSMemberAuthenticator;
use SilverStripe\Security\MemberAuthenticator\CMSMemberLoginForm; use SilverStripe\Security\MemberAuthenticator\CMSMemberLoginForm;
use SilverStripe\Security\MemberAuthenticator\MemberAuthenticator; use SilverStripe\Security\MemberAuthenticator\MemberAuthenticator;
use SilverStripe\Security\Security;
use SilverStripe\Security\Member;
use SilverStripe\Security\MemberAuthenticator\MemberLoginForm; use SilverStripe\Security\MemberAuthenticator\MemberLoginForm;
use SilverStripe\Security\IdentityStore; use SilverStripe\Security\Security;
use SilverStripe\Core\Config\Config;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Security\DefaultAdminService;
class MemberAuthenticatorTest extends SapphireTest class MemberAuthenticatorTest extends SapphireTest
{ {
@ -54,6 +53,8 @@ class MemberAuthenticatorTest extends SapphireTest
public function testCustomIdentifierField() public function testCustomIdentifierField()
{ {
Member::config()->set('unique_identifier_field', 'Username');
$label = Member::singleton() $label = Member::singleton()
->fieldLabel(Member::config()->get('unique_identifier_field')); ->fieldLabel(Member::config()->get('unique_identifier_field'));
@ -69,7 +70,7 @@ class MemberAuthenticatorTest extends SapphireTest
// Create basic login form // Create basic login form
$frontendResponse = $authenticator $frontendResponse = $authenticator
->getLoginHandler($controller->link()) ->getLoginHandler($controller->link())
->handleRequest(new HTTPRequest('get', '/')); ->handleRequest(Controller::curr()->getRequest());
$this->assertTrue(is_array($frontendResponse)); $this->assertTrue(is_array($frontendResponse));
$this->assertTrue(isset($frontendResponse['Form'])); $this->assertTrue(isset($frontendResponse['Form']));

View File

@ -2,25 +2,22 @@
namespace SilverStripe\Security\Tests; namespace SilverStripe\Security\Tests;
use SilverStripe\Dev\Debug; use SilverStripe\Control\Controller;
use SilverStripe\Control\Director;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Convert;
use SilverStripe\Dev\FunctionalTest;
use SilverStripe\i18n\i18n;
use SilverStripe\ORM\DataObject; use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\FieldType\DBDatetime;
use SilverStripe\ORM\FieldType\DBClassName;
use SilverStripe\ORM\DB; use SilverStripe\ORM\DB;
use SilverStripe\ORM\FieldType\DBClassName;
use SilverStripe\ORM\FieldType\DBDatetime;
use SilverStripe\ORM\ValidationResult; use SilverStripe\ORM\ValidationResult;
use SilverStripe\Security\LoginAttempt; use SilverStripe\Security\LoginAttempt;
use SilverStripe\Security\Member; use SilverStripe\Security\Member;
use SilverStripe\Security\MemberAuthenticator\MemberAuthenticator; use SilverStripe\Security\MemberAuthenticator\MemberAuthenticator;
use SilverStripe\Security\Security; use SilverStripe\Security\Security;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Convert;
use SilverStripe\Dev\FunctionalTest;
use SilverStripe\Dev\TestOnly;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\Session;
use SilverStripe\Control\Director;
use SilverStripe\Control\Controller;
use SilverStripe\i18n\i18n;
/** /**
* Test the security class, including log-in form, change password form, etc * Test the security class, including log-in form, change password form, etc
@ -45,11 +42,11 @@ class SecurityTest extends FunctionalTest
/** /**
* @skipUpgrade * @skipUpgrade
*/ */
Member::config()->unique_identifier_field = 'Email'; Member::config()->set('unique_identifier_field', 'Email');
parent::setUp(); parent::setUp();
Config::modify()->merge('SilverStripe\\Control\\Director', 'alternate_base_url', '/'); Director::config()->set('alternate_base_url', '/');
} }
public function testAccessingAuthenticatedPageRedirectsToLoginForm() public function testAccessingAuthenticatedPageRedirectsToLoginForm()
@ -73,10 +70,9 @@ class SecurityTest extends FunctionalTest
public function testPermissionFailureSetsCorrectFormMessages() public function testPermissionFailureSetsCorrectFormMessages()
{ {
Config::nest();
// Controller that doesn't attempt redirections // Controller that doesn't attempt redirections
$controller = new SecurityTest\NullController(); $controller = new SecurityTest\NullController();
$controller->setRequest(Controller::curr()->getRequest());
$controller->setResponse(new HTTPResponse()); $controller->setResponse(new HTTPResponse());
$session = Controller::curr()->getRequest()->getSession(); $session = Controller::curr()->getRequest()->getSession();
@ -84,7 +80,7 @@ class SecurityTest extends FunctionalTest
$this->assertEquals('Oops, not allowed', $session->get('Security.Message.message')); $this->assertEquals('Oops, not allowed', $session->get('Security.Message.message'));
// Test that config values are used correctly // Test that config values are used correctly
Config::inst()->update(Security::class, 'default_message_set', 'stringvalue'); Config::modify()->set(Security::class, 'default_message_set', 'stringvalue');
Security::permissionFailure($controller); Security::permissionFailure($controller);
$this->assertEquals( $this->assertEquals(
'stringvalue', 'stringvalue',
@ -106,7 +102,7 @@ class SecurityTest extends FunctionalTest
// been fetched and output as part of it, so has been removed from the session // been fetched and output as part of it, so has been removed from the session
$this->logInWithPermission('EDITOR'); $this->logInWithPermission('EDITOR');
Config::inst()->update( Config::modify()->set(
Security::class, Security::class,
'default_message_set', 'default_message_set',
array('default' => 'default', 'alreadyLoggedIn' => 'You are already logged in!') array('default' => 'default', 'alreadyLoggedIn' => 'You are already logged in!')
@ -127,8 +123,6 @@ class SecurityTest extends FunctionalTest
$controller->getResponse()->getBody(), $controller->getResponse()->getBody(),
"Message set passed to Security::permissionFailure() didn't override Config values" "Message set passed to Security::permissionFailure() didn't override Config values"
); );
Config::unnest();
} }
/** /**
@ -200,7 +194,7 @@ class SecurityTest extends FunctionalTest
Security::setCurrentUser($member); Security::setCurrentUser($member);
/* View the Security/login page */ /* View the Security/login page */
$response = $this->get(Config::inst()->get(Security::class, 'login_url')); $this->get(Config::inst()->get(Security::class, 'login_url'));
$items = $this->cssParser()->getBySelector('#MemberLoginForm_LoginForm input.action'); $items = $this->cssParser()->getBySelector('#MemberLoginForm_LoginForm input.action');
@ -234,7 +228,7 @@ class SecurityTest extends FunctionalTest
$this->autoFollowRedirection = true; $this->autoFollowRedirection = true;
/* Attempt to get into the admin section */ /* Attempt to get into the admin section */
$response = $this->get(Config::inst()->get(Security::class, 'login_url')); $this->get(Config::inst()->get(Security::class, 'login_url'));
$items = $this->cssParser()->getBySelector('#MemberLoginForm_LoginForm input.text'); $items = $this->cssParser()->getBySelector('#MemberLoginForm_LoginForm input.text');
@ -251,7 +245,7 @@ class SecurityTest extends FunctionalTest
{ {
// Test that username does not persist // Test that username does not persist
$this->session()->set('SessionForms.MemberLoginForm.Email', 'myuser@silverstripe.com'); $this->session()->set('SessionForms.MemberLoginForm.Email', 'myuser@silverstripe.com');
Security::config()->remember_username = false; Security::config()->set('remember_username', false);
$this->get(Config::inst()->get(Security::class, 'login_url')); $this->get(Config::inst()->get(Security::class, 'login_url'));
$items = $this $items = $this
->cssParser() ->cssParser()
@ -265,7 +259,7 @@ class SecurityTest extends FunctionalTest
// Test that username does persist when necessary // Test that username does persist when necessary
$this->session()->set('SessionForms.MemberLoginForm.Email', 'myuser@silverstripe.com'); $this->session()->set('SessionForms.MemberLoginForm.Email', 'myuser@silverstripe.com');
Security::config()->remember_username = true; Security::config()->set('remember_username', true);
$this->get(Config::inst()->get(Security::class, 'login_url')); $this->get(Config::inst()->get(Security::class, 'login_url'));
$items = $this $items = $this
->cssParser() ->cssParser()
@ -373,7 +367,7 @@ class SecurityTest extends FunctionalTest
public function testChangePasswordForLoggedInUsers() public function testChangePasswordForLoggedInUsers()
{ {
$goodResponse = $this->doTestLoginForm('testuser@example.com', '1nitialPassword'); $this->doTestLoginForm('testuser@example.com', '1nitialPassword');
// Change the password // Change the password
$this->get('Security/changepassword?BackURL=test/back'); $this->get('Security/changepassword?BackURL=test/back');
@ -398,6 +392,7 @@ class SecurityTest extends FunctionalTest
public function testChangePasswordFromLostPassword() public function testChangePasswordFromLostPassword()
{ {
/** @var Member $admin */
$admin = $this->objFromFixture(Member::class, 'test'); $admin = $this->objFromFixture(Member::class, 'test');
$admin->FailedLoginCount = 99; $admin->FailedLoginCount = 99;
$admin->LockedOutUntil = DBDatetime::now()->getValue(); $admin->LockedOutUntil = DBDatetime::now()->getValue();
@ -406,8 +401,8 @@ class SecurityTest extends FunctionalTest
$this->assertNull($admin->AutoLoginHash, 'Hash is empty before lost password'); $this->assertNull($admin->AutoLoginHash, 'Hash is empty before lost password');
// Request new password by email // Request new password by email
$response = $this->get('Security/lostpassword'); $this->get('Security/lostpassword');
$response = $this->post('Security/lostpassword/LostPasswordForm', array('Email' => 'testuser@example.com')); $this->post('Security/lostpassword/LostPasswordForm', array('Email' => 'testuser@example.com'));
$this->assertEmailSent('testuser@example.com'); $this->assertEmailSent('testuser@example.com');
@ -427,8 +422,8 @@ class SecurityTest extends FunctionalTest
); );
// Follow redirection to form without hash in GET parameter // Follow redirection to form without hash in GET parameter
$response = $this->get('Security/changepassword'); $this->get('Security/changepassword');
$changedResponse = $this->doTestChangepasswordForm('1nitialPassword', 'changedPassword'); $this->doTestChangepasswordForm('1nitialPassword', 'changedPassword');
$this->assertEquals($this->idFromFixture(Member::class, 'test'), $this->session()->get('loggedInAs')); $this->assertEquals($this->idFromFixture(Member::class, 'test'), $this->session()->get('loggedInAs'));
// Check if we can login with the new password // Check if we can login with the new password
@ -444,18 +439,17 @@ class SecurityTest extends FunctionalTest
public function testRepeatedLoginAttemptsLockingPeopleOut() public function testRepeatedLoginAttemptsLockingPeopleOut()
{ {
$local = i18n::get_locale();
i18n::set_locale('en_US'); i18n::set_locale('en_US');
Member::config()->set('lock_out_after_incorrect_logins', 5);
Member::config()->lock_out_after_incorrect_logins = 5; Member::config()->set('lock_out_delay_mins', 15);
Member::config()->lock_out_delay_mins = 15;
// Login with a wrong password for more than the defined threshold // Login with a wrong password for more than the defined threshold
for ($i = 1; $i <= (Member::config()->lock_out_after_incorrect_logins+1); $i++) { for ($i = 1; $i <= 6; $i++) {
$this->doTestLoginForm('testuser@example.com', 'incorrectpassword'); $this->doTestLoginForm('testuser@example.com', 'incorrectpassword');
/** @var Member $member */
$member = DataObject::get_by_id(Member::class, $this->idFromFixture(Member::class, 'test')); $member = DataObject::get_by_id(Member::class, $this->idFromFixture(Member::class, 'test'));
if ($i < Member::config()->get('lock_out_after_incorrect_logins')) { if ($i < 5) {
$this->assertNull( $this->assertNull(
$member->LockedOutUntil, $member->LockedOutUntil,
'User does not have a lockout time set if under threshold for failed attempts' 'User does not have a lockout time set if under threshold for failed attempts'
@ -480,7 +474,7 @@ class SecurityTest extends FunctionalTest
'Your account has been temporarily disabled because of too many failed attempts at ' . 'Your account has been temporarily disabled because of too many failed attempts at ' .
'logging in. Please try again in {count} minutes.', 'logging in. Please try again in {count} minutes.',
null, null,
array('count' => Member::config()->lock_out_delay_mins) array('count' => 15)
); );
$this->assertHasMessage($msg); $this->assertHasMessage($msg);
@ -506,7 +500,7 @@ class SecurityTest extends FunctionalTest
$this->logOut(); $this->logOut();
// Login again with wrong password, but less attempts than threshold // Login again with wrong password, but less attempts than threshold
for ($i = 1; $i < Member::config()->lock_out_after_incorrect_logins; $i++) { for ($i = 1; $i < 5; $i++) {
$this->doTestLoginForm('testuser@example.com', 'incorrectpassword'); $this->doTestLoginForm('testuser@example.com', 'incorrectpassword');
} }
$this->assertNull($this->session()->get('loggedInAs')); $this->assertNull($this->session()->get('loggedInAs'));
@ -521,13 +515,11 @@ class SecurityTest extends FunctionalTest
$member->ID, $member->ID,
'The user can login successfully after lockout expires, if staying below the threshold' 'The user can login successfully after lockout expires, if staying below the threshold'
); );
i18n::set_locale($local);
} }
public function testAlternatingRepeatedLoginAttempts() public function testAlternatingRepeatedLoginAttempts()
{ {
Member::config()->lock_out_after_incorrect_logins = 3; Member::config()->set('lock_out_after_incorrect_logins', 3);
// ATTEMPTING LOG-IN TWICE WITH ONE ACCOUNT AND TWICE WITH ANOTHER SHOULDN'T LOCK ANYBODY OUT // ATTEMPTING LOG-IN TWICE WITH ONE ACCOUNT AND TWICE WITH ANOTHER SHOULDN'T LOCK ANYBODY OUT
@ -537,7 +529,9 @@ class SecurityTest extends FunctionalTest
$this->doTestLoginForm('noexpiry@silverstripe.com', 'incorrectpassword'); $this->doTestLoginForm('noexpiry@silverstripe.com', 'incorrectpassword');
$this->doTestLoginForm('noexpiry@silverstripe.com', 'incorrectpassword'); $this->doTestLoginForm('noexpiry@silverstripe.com', 'incorrectpassword');
/** @var Member $member1 */
$member1 = DataObject::get_by_id(Member::class, $this->idFromFixture(Member::class, 'test')); $member1 = DataObject::get_by_id(Member::class, $this->idFromFixture(Member::class, 'test'));
/** @var Member $member2 */
$member2 = DataObject::get_by_id(Member::class, $this->idFromFixture(Member::class, 'noexpiry')); $member2 = DataObject::get_by_id(Member::class, $this->idFromFixture(Member::class, 'noexpiry'));
$this->assertNull($member1->LockedOutUntil); $this->assertNull($member1->LockedOutUntil);
@ -557,17 +551,18 @@ class SecurityTest extends FunctionalTest
public function testUnsuccessfulLoginAttempts() public function testUnsuccessfulLoginAttempts()
{ {
Security::config()->login_recording = true; Security::config()->set('login_recording', true);
/* UNSUCCESSFUL ATTEMPTS WITH WRONG PASSWORD FOR EXISTING USER ARE LOGGED */ /* UNSUCCESSFUL ATTEMPTS WITH WRONG PASSWORD FOR EXISTING USER ARE LOGGED */
$this->doTestLoginForm('testuser@example.com', 'wrongpassword'); $this->doTestLoginForm('testuser@example.com', 'wrongpassword');
/** @var LoginAttempt $attempt */
$attempt = DataObject::get_one( $attempt = DataObject::get_one(
LoginAttempt::class, LoginAttempt::class,
array( array(
'"LoginAttempt"."Email"' => 'testuser@example.com' '"LoginAttempt"."Email"' => 'testuser@example.com'
) )
); );
$this->assertTrue(is_object($attempt)); $this->assertInstanceOf(LoginAttempt::class, $attempt);
$member = DataObject::get_one( $member = DataObject::get_one(
Member::class, Member::class,
array( array(
@ -594,16 +589,18 @@ class SecurityTest extends FunctionalTest
public function testSuccessfulLoginAttempts() public function testSuccessfulLoginAttempts()
{ {
Security::config()->login_recording = true; Security::config()->set('login_recording', true);
/* SUCCESSFUL ATTEMPTS ARE LOGGED */ /* SUCCESSFUL ATTEMPTS ARE LOGGED */
$this->doTestLoginForm('testuser@example.com', '1nitialPassword'); $this->doTestLoginForm('testuser@example.com', '1nitialPassword');
/** @var LoginAttempt $attempt */
$attempt = DataObject::get_one( $attempt = DataObject::get_one(
LoginAttempt::class, LoginAttempt::class,
array( array(
'"LoginAttempt"."Email"' => 'testuser@example.com' '"LoginAttempt"."Email"' => 'testuser@example.com'
) )
); );
/** @var Member $member */
$member = DataObject::get_one( $member = DataObject::get_one(
Member::class, Member::class,
array( array(
@ -646,7 +643,7 @@ class SecurityTest extends FunctionalTest
public function testDoNotSendEmptyRobotsHeaderIfNotDefined() public function testDoNotSendEmptyRobotsHeaderIfNotDefined()
{ {
Config::inst()->remove(Security::class, 'robots_tag'); Config::modify()->remove(Security::class, 'robots_tag');
$response = $this->get(Config::inst()->get(Security::class, 'login_url')); $response = $this->get(Config::inst()->get(Security::class, 'login_url'));
$robotsHeader = $response->getHeader('X-Robots-Tag'); $robotsHeader = $response->getHeader('X-Robots-Tag');
$this->assertNull($robotsHeader); $this->assertNull($robotsHeader);
@ -655,6 +652,11 @@ class SecurityTest extends FunctionalTest
/** /**
* Execute a log-in form using Director::test(). * Execute a log-in form using Director::test().
* Helper method for the tests above * Helper method for the tests above
*
* @param string $email
* @param string $password
* @param string $backURL
* @return HTTPResponse
*/ */
public function doTestLoginForm($email, $password, $backURL = 'test/link') public function doTestLoginForm($email, $password, $backURL = 'test/link')
{ {
@ -676,6 +678,10 @@ class SecurityTest extends FunctionalTest
/** /**
* Helper method to execute a change password form * Helper method to execute a change password form
*
* @param string $oldPassword
* @param string $newPassword
* @return HTTPResponse
*/ */
public function doTestChangepasswordForm($oldPassword, $newPassword) public function doTestChangepasswordForm($oldPassword, $newPassword)
{ {

View File

@ -86,6 +86,7 @@ class RequirementsTest extends SapphireTest
$backend->clearCombinedFiles(); $backend->clearCombinedFiles();
$backend->setCombinedFilesFolder('_combinedfiles'); $backend->setCombinedFilesFolder('_combinedfiles');
$backend->setMinifyCombinedFiles(false); $backend->setMinifyCombinedFiles(false);
$backend->setCombinedFilesEnabled(true);
Requirements::flush(); Requirements::flush();
} }
@ -193,6 +194,7 @@ class RequirementsTest extends SapphireTest
{ {
/** @var Requirements_Backend $backend */ /** @var Requirements_Backend $backend */
$backend = Injector::inst()->create(Requirements_Backend::class); $backend = Injector::inst()->create(Requirements_Backend::class);
$backend->setCombinedFilesEnabled(true);
$this->setupCombinedRequirements($backend); $this->setupCombinedRequirements($backend);
$combinedFileName = '/_combinedfiles/RequirementsTest_bc-2a55d56.js'; $combinedFileName = '/_combinedfiles/RequirementsTest_bc-2a55d56.js';

View File

@ -3,6 +3,7 @@
namespace SilverStripe\View\Tests; namespace SilverStripe\View\Tests;
use SilverStripe\Core\Injector\Injector; use SilverStripe\Core\Injector\Injector;
use SilverStripe\Core\TempFolder;
use SilverStripe\Versioned\Versioned; use SilverStripe\Versioned\Versioned;
use Psr\SimpleCache\CacheInterface; use Psr\SimpleCache\CacheInterface;
use SilverStripe\Dev\SapphireTest; use SilverStripe\Dev\SapphireTest;
@ -41,7 +42,7 @@ class SSViewerCacheBlockTest extends SapphireTest
$cache = null; $cache = null;
if ($cacheOn) { if ($cacheOn) {
$cache = new FilesystemCache('cacheblock', 0, getTempFolder()); // cache indefinitely $cache = new FilesystemCache('cacheblock', 0, TempFolder::getTempFolder(BASE_PATH)); // cache indefinitely
} else { } else {
$cache = new NullCache(); $cache = new NullCache();
} }

View File

@ -2,35 +2,35 @@
namespace SilverStripe\View\Tests; namespace SilverStripe\View\Tests;
use Exception;
use InvalidArgumentException;
use PHPUnit_Framework_MockObject_MockObject; use PHPUnit_Framework_MockObject_MockObject;
use SilverStripe\Assets\Tests\Storage\AssetStoreTest\TestAssetStore;
use SilverStripe\Control\ContentNegotiator;
use SilverStripe\Control\Controller; use SilverStripe\Control\Controller;
use SilverStripe\Control\Director; use SilverStripe\Control\Director;
use SilverStripe\Control\ContentNegotiator;
use SilverStripe\Control\HTTPResponse; use SilverStripe\Control\HTTPResponse;
use SilverStripe\Core\Convert; use SilverStripe\Core\Convert;
use SilverStripe\Core\Injector\Injector; use SilverStripe\Core\Injector\Injector;
use SilverStripe\Dev\SapphireTest; use SilverStripe\Dev\SapphireTest;
use SilverStripe\i18n\i18n; use SilverStripe\i18n\i18n;
use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\DataObject; use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\FieldType\DBField; use SilverStripe\ORM\FieldType\DBField;
use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\PaginatedList; use SilverStripe\ORM\PaginatedList;
use SilverStripe\Security\Member; use SilverStripe\Security\Permission;
use SilverStripe\Security\Security; use SilverStripe\Security\Security;
use SilverStripe\Security\SecurityToken; use SilverStripe\Security\SecurityToken;
use SilverStripe\Security\Permission;
use SilverStripe\View\ArrayData; use SilverStripe\View\ArrayData;
use SilverStripe\View\Requirements;
use SilverStripe\View\Requirements_Backend; use SilverStripe\View\Requirements_Backend;
use SilverStripe\View\Requirements_Minifier; use SilverStripe\View\Requirements_Minifier;
use SilverStripe\View\SSTemplateParser;
use SilverStripe\View\SSViewer; use SilverStripe\View\SSViewer;
use SilverStripe\View\Requirements; use SilverStripe\View\SSViewer_FromString;
use SilverStripe\View\Tests\SSViewerTest\SSViewerTestModel; use SilverStripe\View\Tests\SSViewerTest\SSViewerTestModel;
use SilverStripe\View\Tests\SSViewerTest\SSViewerTestModelController; use SilverStripe\View\Tests\SSViewerTest\SSViewerTestModelController;
use SilverStripe\View\ViewableData; use SilverStripe\View\ViewableData;
use SilverStripe\View\SSViewer_FromString;
use SilverStripe\View\SSTemplateParser;
use SilverStripe\Assets\Tests\Storage\AssetStoreTest\TestAssetStore;
use Exception;
class SSViewerTest extends SapphireTest class SSViewerTest extends SapphireTest
{ {
@ -213,8 +213,11 @@ class SSViewerTest extends SapphireTest
public function testRequirementsCombine() public function testRequirementsCombine()
{ {
/** @var Requirements_Backend $testBackend */
$testBackend = Injector::inst()->create(Requirements_Backend::class); $testBackend = Injector::inst()->create(Requirements_Backend::class);
$testBackend->setSuffixRequirements(false); $testBackend->setSuffixRequirements(false);
$testBackend->setCombinedFilesEnabled(true);
//$combinedTestFilePath = BASE_PATH . '/' . $testBackend->getCombinedFilesFolder() . '/testRequirementsCombine.js'; //$combinedTestFilePath = BASE_PATH . '/' . $testBackend->getCombinedFilesFolder() . '/testRequirementsCombine.js';
$jsFile = $this->getCurrentRelativePath() . '/SSViewerTest/javascript/bad.js'; $jsFile = $this->getCurrentRelativePath() . '/SSViewerTest/javascript/bad.js';
@ -237,9 +240,12 @@ class SSViewerTest extends SapphireTest
public function testRequirementsMinification() public function testRequirementsMinification()
{ {
/** @var Requirements_Backend $testBackend */
$testBackend = Injector::inst()->create(Requirements_Backend::class); $testBackend = Injector::inst()->create(Requirements_Backend::class);
$testBackend->setSuffixRequirements(false); $testBackend->setSuffixRequirements(false);
$testBackend->setMinifyCombinedFiles(true); $testBackend->setMinifyCombinedFiles(true);
$testBackend->setCombinedFilesEnabled(true);
$testFile = $this->getCurrentRelativePath() . '/SSViewerTest/javascript/RequirementsTest_a.js'; $testFile = $this->getCurrentRelativePath() . '/SSViewerTest/javascript/RequirementsTest_a.js';
$testFileContent = file_get_contents($testFile); $testFileContent = file_get_contents($testFile);
@ -263,10 +269,8 @@ class SSViewerTest extends SapphireTest
->method('minify'); ->method('minify');
$testBackend->processCombinedFiles(); $testBackend->processCombinedFiles();
$this->setExpectedExceptionRegExp( $this->expectException(Exception::class);
Exception::class, $this->expectExceptionMessageRegExp('/^Cannot minify files without a minification service defined./');
'/minification service/'
);
$testBackend->setMinifyCombinedFiles(true); $testBackend->setMinifyCombinedFiles(true);
$testBackend->setMinifier(null); $testBackend->setMinifier(null);
@ -1614,8 +1618,8 @@ after'
); );
// Let's throw something random in there. // Let's throw something random in there.
$this->setExpectedException('InvalidArgumentException'); $this->expectException(InvalidArgumentException::class);
SSViewer::get_templates_by_class(array()); SSViewer::get_templates_by_class(null);
} }
); );
} }
@ -1732,7 +1736,6 @@ EOC;
public function testRenderWithSourceFileComments() public function testRenderWithSourceFileComments()
{ {
Director::set_environment_type('dev');
SSViewer::config()->update('source_file_comments', true); SSViewer::config()->update('source_file_comments', true);
$i = __DIR__ . '/SSViewerTest/templates/Includes'; $i = __DIR__ . '/SSViewerTest/templates/Includes';
$f = __DIR__ . '/SSViewerTest/templates/SSViewerTestComments'; $f = __DIR__ . '/SSViewerTest/templates/SSViewerTestComments';
@ -1853,13 +1856,13 @@ EOC;
Requirements::set_backend($backend); Requirements::set_backend($backend);
$this->assertEquals(1, substr_count($template->process(array()), "a.css")); $this->assertEquals(1, substr_count($template->process(new ViewableData()), "a.css"));
$this->assertEquals(1, substr_count($template->process(array()), "b.css")); $this->assertEquals(1, substr_count($template->process(new ViewableData()), "b.css"));
// if we disable the requirements then we should get nothing // if we disable the requirements then we should get nothing
$template->includeRequirements(false); $template->includeRequirements(false);
$this->assertEquals(0, substr_count($template->process(array()), "a.css")); $this->assertEquals(0, substr_count($template->process(new ViewableData()), "a.css"));
$this->assertEquals(0, substr_count($template->process(array()), "b.css")); $this->assertEquals(0, substr_count($template->process(new ViewableData()), "b.css"));
} }
public function testRequireCallInTemplateInclude() public function testRequireCallInTemplateInclude()
@ -1873,7 +1876,7 @@ EOC;
$this->assertEquals( $this->assertEquals(
1, 1,
substr_count( substr_count(
$template->process(array()), $template->process(new ViewableData()),
"tests/php/View/SSViewerTest/javascript/RequirementsTest_a.js" "tests/php/View/SSViewerTest/javascript/RequirementsTest_a.js"
) )
); );

View File

@ -5,6 +5,10 @@ namespace SilverStripe\View\Tests\SSViewerTest;
use SilverStripe\Dev\TestOnly; use SilverStripe\Dev\TestOnly;
use SilverStripe\View\ViewableData; use SilverStripe\View\ViewableData;
/**
* @property string $TextValue
* @property string $HTMLValue
*/
class TestViewableData extends ViewableData implements TestOnly class TestViewableData extends ViewableData implements TestOnly
{ {