public function testMemberGroupRelationForm() { Session::set('loggedInAs', $this->idFromFixture('GroupTest_Member', 'admin')); $adminGroup = $this->objFromFixture('SilverStripe\\Security\\Group', 'admingroup'); $parentGroup = $this->objFromFixture('SilverStripe\\Security\\Group', 'parentgroup'); $childGroup = $this->objFromFixture('SilverStripe\\Security\\Group', 'childgroup'); // Test single group relation through checkboxsetfield /** @skipUpgrade */ $form = new GroupTest_MemberForm($this, 'Form'); $member = $this->objFromFixture('GroupTest_Member', 'admin'); $form->loadDataFrom($member); $checkboxSetField = $form->Fields()->fieldByName('Groups'); $checkboxSetField->setValue(array($adminGroup->ID => $adminGroup->ID, $parentGroup->ID => $parentGroup->ID)); $form->saveInto($member); $updatedGroups = $member->Groups(); $this->assertEquals(2, count($updatedGroups->column()), "Adding a toplevel group works"); $this->assertContains($adminGroup->ID, $updatedGroups->column('ID')); $this->assertContains($parentGroup->ID, $updatedGroups->column('ID')); // Test unsetting relationship $form->loadDataFrom($member); $checkboxSetField = $form->Fields()->fieldByName('Groups'); $checkboxSetField->setValue(array($adminGroup->ID => $adminGroup->ID)); $form->saveInto($member); $member->flushCache(); $updatedGroups = $member->Groups(); $this->assertEquals(1, count($updatedGroups->column()), "Removing a previously added toplevel group works"); $this->assertContains($adminGroup->ID, $updatedGroups->column('ID')); // Test adding child group }
/** * @return array */ public function getAttributes() { // Store state in session, and pass ID to client side. $state = array('grid' => $this->getNameFromParent(), 'actionName' => $this->actionName, 'args' => $this->args); // Ensure $id doesn't contain only numeric characters $id = 'gf_' . substr(md5(serialize($state)), 0, 8); Session::set($id, $state); $actionData['StateID'] = $id; return array_merge(parent::getAttributes(), array('name' => 'action_gridFieldAlterAction' . '?' . http_build_query($actionData), 'data-url' => $this->gridField->Link())); }
/** * Gets the current state of this form as a nested array. * * @param Form $form * @return array */ public function getState(Form $form) { // Ensure that session errors are populated within form field messages $form->setupFormErrors(); // @todo - Replace with ValidationResult handling // Currently tri-state; null (unsubmitted), true (submitted-valid), false (submitted-invalid) $errors = Session::get("FormInfo.{$form->FormName()}.errors"); $valid = isset($errors) ? empty($errors) : null; $state = ['id' => $form->FormName(), 'fields' => [], 'valid' => $valid, 'messages' => []]; // flattened nested fields are returned, rather than only top level fields. $state['fields'] = array_merge($this->getFieldStates($form->Fields()), $this->getFieldStates($form->Actions())); if ($message = $form->Message()) { $state['messages'][] = ['value' => ['html' => $message], 'type' => $form->MessageType()]; } return $state; }
/** * Get the ID of the current logged in user * * @return int Returns the ID of the current logged in user or 0. */ public static function currentUserID() { $id = Session::get("loggedInAs"); if (!$id && !self::$_already_tried_to_auto_log_in) { self::autoLogin(); $id = Session::get("loggedInAs"); } return is_numeric($id) ? $id : 0; }
/** * Determine if a grant exists for the given FileID * * @param string $fileID * @return bool */ protected function isGranted($fileID) { // Since permissions are applied to the non-variant only, // map back to the original file before checking $originalID = $this->removeVariant($fileID); $granted = Session::get(self::GRANTS_SESSION) ?: array(); return !empty($granted[$originalID]); }
/** * Processing that occurs before a form is executed. * * This includes form validation, if it fails, we redirect back * to the form with appropriate error messages. * Always return true if the current form action is exempt from validation * * Triggered through {@link httpSubmission()}. * * Note that CSRF protection takes place in {@link httpSubmission()}, * if it fails the form data will never reach this method. * * @return boolean */ public function validate() { $action = $this->buttonClicked(); if ($action && $this->actionIsValidationExempt($action)) { return true; } if ($this->validator) { $errors = $this->validator->validate(); if ($errors) { // Load errors into session and post back $data = $this->getData(); // Encode validation messages as XML before saving into session state // As per Form::addErrorMessage() $errors = array_map(function ($error) { // Encode message as XML by default if ($error['message'] instanceof DBField) { $error['message'] = $error['message']->forTemplate(); } else { $error['message'] = Convert::raw2xml($error['message']); } return $error; }, $errors); Session::set("FormInfo.{$this->FormName()}.errors", $errors); Session::set("FormInfo.{$this->FormName()}.data", $data); return false; } } return true; }
/** * Forces the current page to be set in session, * which can be retrieved later through {@link currentPageID()}. * Keep in mind that setting an ID through GET/POST or * as a URL parameter will overrule this value. * * @param int $id */ public function setCurrentPageID($id) { $id = (int) $id; Session::set($this->sessionNamespace() . ".currentPage", $id); }
/** * Show the "change password" page. * This page can either be called directly by logged-in users * (in which case they need to provide their old password), * or through a link emailed through {@link lostpassword()}. * In this case no old password is required, authentication is ensured * through the Member.AutoLoginHash property. * * @see ChangePasswordForm * * @return string|HTTPRequest Returns the "change password" page as HTML code, or a redirect response */ public function changepassword() { $controller = $this->getResponseController(_t('Security.CHANGEPASSWORDHEADER', 'Change your password')); // if the controller calls Director::redirect(), this will break early if (($response = $controller->getResponse()) && $response->isFinished()) { return $response; } // Extract the member from the URL. /** @var Member $member */ $member = null; if (isset($_REQUEST['m'])) { $member = Member::get()->filter('ID', (int) $_REQUEST['m'])->first(); } // Check whether we are merely changin password, or resetting. if (isset($_REQUEST['t']) && $member && $member->validateAutoLoginToken($_REQUEST['t'])) { // On first valid password reset request redirect to the same URL without hash to avoid referrer leakage. // if there is a current member, they should be logged out if ($curMember = Member::currentUser()) { $curMember->logOut(); } // Store the hash for the change password form. Will be unset after reload within the ChangePasswordForm. Session::set('AutoLoginHash', $member->encryptWithUserSettings($_REQUEST['t'])); return $this->redirect($this->Link('changepassword')); } elseif (Session::get('AutoLoginHash')) { // Subsequent request after the "first load with hash" (see previous if clause). $customisedController = $controller->customise(array('Content' => '<p>' . _t('Security.ENTERNEWPASSWORD', 'Please enter a new password.') . '</p>', 'Form' => $this->ChangePasswordForm())); } elseif (Member::currentUser()) { // Logged in user requested a password change form. $customisedController = $controller->customise(array('Content' => '<p>' . _t('Security.CHANGEPASSWORDBELOW', 'You can change your password below.') . '</p>', 'Form' => $this->ChangePasswordForm())); } else { // Show friendly message if it seems like the user arrived here via password reset feature. if (isset($_REQUEST['m']) || isset($_REQUEST['t'])) { $customisedController = $controller->customise(array('Content' => _t('Security.NOTERESETLINKINVALID', '<p>The password reset link is invalid or expired.</p>' . '<p>You can request a new one <a href="{link1}">here</a> or change your password after' . ' you <a href="{link2}">logged in</a>.</p>', array('link1' => $this->Link('lostpassword'), 'link2' => $this->Link('login'))))); } else { return self::permissionFailure($this, _t('Security.ERRORPASSWORDPERMISSION', 'You must be logged in in order to change your password!')); } } return $customisedController->renderWith($this->getTemplatesFor('changepassword')); }
/** * Process the given URL, creating the appropriate controller and executing it. * * Request processing is handled as follows: * - Director::direct() creates a new HTTPResponse object and passes this to * Director::handleRequest(). * - Director::handleRequest($request) checks each of the Director rules and identifies a controller * to handle this request. * - Controller::handleRequest($request) is then called. This will find a rule to handle the URL, * and call the rule handling method. * - RequestHandler::handleRequest($request) is recursively called whenever a rule handling method * returns a RequestHandler object. * * In addition to request processing, Director will manage the session, and perform the output of * the actual response to the browser. * * @uses handleRequest() rule-lookup logic is handled by this. * @uses Controller::handleRequest() This handles the page logic for a Director::direct() call. * @param string $url * @param DataModel $model * @throws HTTPResponse_Exception */ public static function direct($url, DataModel $model) { // Validate $_FILES array before merging it with $_POST foreach ($_FILES as $k => $v) { if (is_array($v['tmp_name'])) { $v = ArrayLib::array_values_recursive($v['tmp_name']); foreach ($v as $tmpFile) { if ($tmpFile && !is_uploaded_file($tmpFile)) { user_error("File upload '{$k}' doesn't appear to be a valid upload", E_USER_ERROR); } } } else { if ($v['tmp_name'] && !is_uploaded_file($v['tmp_name'])) { user_error("File upload '{$k}' doesn't appear to be a valid upload", E_USER_ERROR); } } } $req = new HTTPRequest(isset($_SERVER['X-HTTP-Method-Override']) ? $_SERVER['X-HTTP-Method-Override'] : $_SERVER['REQUEST_METHOD'], $url, $_GET, ArrayLib::array_merge_recursive((array) $_POST, (array) $_FILES), @file_get_contents('php://input')); $headers = self::extract_request_headers($_SERVER); foreach ($headers as $header => $value) { $req->addHeader($header, $value); } // Initiate an empty session - doesn't initialize an actual PHP session until saved (see below) $session = Session::create(isset($_SESSION) ? $_SESSION : array()); // Only resume a session if its not started already, and a session identifier exists if (!isset($_SESSION) && Session::request_contains_session_id()) { $session->inst_start(); } $output = RequestProcessor::singleton()->preRequest($req, $session, $model); if ($output === false) { // @TODO Need to NOT proceed with the request in an elegant manner throw new HTTPResponse_Exception(_t('Director.INVALID_REQUEST', 'Invalid request'), 400); } $result = Director::handleRequest($req, $session, $model); // Save session data. Note that inst_save() will start/resume the session if required. $session->inst_save(); // Return code for a redirection request if (is_string($result) && substr($result, 0, 9) == 'redirect:') { $url = substr($result, 9); if (Director::is_cli()) { // on cli, follow SilverStripe redirects automatically Director::direct(str_replace(Director::absoluteBaseURL(), '', $url), DataModel::inst()); return; } else { $response = new HTTPResponse(); $response->redirect($url); $res = RequestProcessor::singleton()->postRequest($req, $response, $model); if ($res !== false) { $response->output(); } } // Handle a controller } elseif ($result) { if ($result instanceof HTTPResponse) { $response = $result; } else { $response = new HTTPResponse(); $response->setBody($result); } $res = RequestProcessor::singleton()->postRequest($req, $response, $model); if ($res !== false) { $response->output(); } else { // @TODO Proper response here. throw new HTTPResponse_Exception("Invalid response"); } //$controllerObj->getSession()->inst_save(); } }
/** * Sets the appropriate form message in session, with type. This will be shown once, * for the form specified. * * @param string $formname the form name you wish to use ( usually $form->FormName() ) * @param string $message the message you wish to add to it * @param string $type the type of message */ public static function setFormMessage($formname, $message, $type) { Session::set("FormInfo.{$formname}.formError.message", $message); Session::set("FormInfo.{$formname}.formError.type", $type); }
/** * Choose the stage the site is currently on. * * If $_GET['stage'] is set, then it will use that stage, and store it in * the session. * * if $_GET['archiveDate'] is set, it will use that date, and store it in * the session. * * If neither of these are set, it checks the session, otherwise the stage * is set to 'Live'. */ public static function choose_site_stage() { // Check any pre-existing session mode $preexistingMode = Session::get('readingMode'); // Determine the reading mode if (isset($_GET['stage'])) { $stage = ucfirst(strtolower($_GET['stage'])); if (!in_array($stage, array(static::DRAFT, static::LIVE))) { $stage = static::LIVE; } $mode = 'Stage.' . $stage; } elseif (isset($_GET['archiveDate']) && strtotime($_GET['archiveDate'])) { $mode = 'Archive.' . $_GET['archiveDate']; } elseif ($preexistingMode) { $mode = $preexistingMode; } else { $mode = static::DEFAULT_MODE; } // Save reading mode Versioned::set_reading_mode($mode); // Try not to store the mode in the session if not needed if ($preexistingMode && $preexistingMode !== $mode || !$preexistingMode && $mode !== static::DEFAULT_MODE) { Session::set('readingMode', $mode); } if (!headers_sent() && !Director::is_cli()) { if (Versioned::get_stage() == 'Live') { // clear the cookie if it's set if (Cookie::get('bypassStaticCache')) { Cookie::force_expiry('bypassStaticCache', null, null, false, true); } } else { // set the cookie if it's cleared if (!Cookie::get('bypassStaticCache')) { Cookie::set('bypassStaticCache', '1', 0, null, null, false, true); } } } }
public function testNonStandardPath() { Config::inst()->update('SilverStripe\\Control\\Session', 'store_path', realpath(dirname($_SERVER['DOCUMENT_ROOT']) . '/../session')); Session::start(); $this->assertEquals(Config::inst()->get('SilverStripe\\Control\\Session', 'store_path'), ''); }
public function testCanViewStage() { $public = $this->objFromFixture('VersionedTest_PublicStage', 'public1'); $private = $this->objFromFixture('VersionedTest_DataObject', 'page1'); Session::clear("loggedInAs"); Versioned::set_stage(Versioned::DRAFT); // Test that all (and only) public pages are viewable in stage mode // Unpublished records are not viewable in live regardless of permissions $this->assertTrue($public->canViewStage('Stage')); $this->assertFalse($private->canViewStage('Stage')); $this->assertFalse($public->canViewStage('Live')); $this->assertFalse($private->canViewStage('Live')); // Writing records to live should make both stage and live modes viewable $private->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); $public->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); $this->assertTrue($public->canViewStage('Stage')); $this->assertTrue($private->canViewStage('Stage')); $this->assertTrue($public->canViewStage('Live')); $this->assertTrue($private->canViewStage('Live')); // If the draft mode changes, the live mode remains public, although the updated // draft mode is secured for non-public records. $private->Title = 'Secret Title'; $private->write(); $public->Title = 'Public Title'; $public->write(); $this->assertTrue($public->canViewStage('Stage')); $this->assertFalse($private->canViewStage('Stage')); $this->assertTrue($public->canViewStage('Live')); $this->assertTrue($private->canViewStage('Live')); }
public function testCanEdit() { $file = $this->objFromFixture('SilverStripe\\Assets\\Image', 'gif'); // Test anonymous permissions Session::set('loggedInAs', null); $this->assertFalse($file->canEdit(), "Anonymous users can't edit files"); // Test permissionless user $this->objFromFixture('SilverStripe\\Security\\Member', 'frontend')->logIn(); $this->assertFalse($file->canEdit(), "Permissionless users can't edit files"); // Test global CMS section users $this->objFromFixture('SilverStripe\\Security\\Member', 'cms')->logIn(); $this->assertTrue($file->canEdit(), "Users with all CMS section access can edit files"); // Test cms access users without file access $this->objFromFixture('SilverStripe\\Security\\Member', 'security')->logIn(); $this->assertFalse($file->canEdit(), "Security CMS users can't edit files"); // Test asset-admin user $this->objFromFixture('SilverStripe\\Security\\Member', 'assetadmin')->logIn(); $this->assertTrue($file->canEdit(), "Asset admin users can edit files"); // Test admin $this->objFromFixture('SilverStripe\\Security\\Member', 'admin')->logIn(); $this->assertTrue($file->canEdit(), "Admins can edit files"); }
/** * Method to authenticate an user * * @param array $data Raw data to authenticate the user * @param Form $form Optional: If passed, better error messages can be * produced by using * {@link Form::sessionMessage()} * @return bool|Member Returns FALSE if authentication fails, otherwise * the member object * @see Security::setDefaultAdmin() */ public static function authenticate($data, Form $form = null) { // Find authenticated member $member = static::authenticate_member($data, $form, $success); // Optionally record every login attempt as a {@link LoginAttempt} object static::record_login_attempt($data, $member, $success); // Legacy migration to precision-safe password hashes. // A login-event with cleartext passwords is the only time // when we can rehash passwords to a different hashing algorithm, // bulk-migration doesn't work due to the nature of hashing. // See PasswordEncryptor_LegacyPHPHash class. if ($success && $member && isset(self::$migrate_legacy_hashes[$member->PasswordEncryption])) { $member->Password = $data['Password']; $member->PasswordEncryption = self::$migrate_legacy_hashes[$member->PasswordEncryption]; $member->write(); } if ($success) { Session::clear('BackURL'); } return $success ? $member : null; }
$chain->setSuppression(false); } // Load in core require_once 'Core/Core.php'; // Connect to database global $databaseConfig; if ($databaseConfig) { DB::connect($databaseConfig); } // Check if a token is requesting a redirect if (!$reloadToken) { return; } // Otherwise, we start up the session if needed if (!isset($_SESSION) && Session::request_contains_session_id()) { Session::start(); } // Next, check if we're in dev mode, or the database doesn't have any security data, or we are admin if (Director::isDev() || !Security::database_is_ready() || Permission::check('ADMIN')) { return $reloadToken->reloadWithToken(); } // Fail and redirect the user to the login page $loginPage = Director::absoluteURL(Security::config()->login_url); $loginPage .= "?BackURL=" . urlencode($_SERVER['REQUEST_URI']); header('location: ' . $loginPage, true, 302); die; })->thenIfErrored(function () use($reloadToken) { if ($reloadToken) { $reloadToken->reloadWithToken(); } })->execute();
public function testDeleteActionRemoveRelation() { $this->logInWithPermission('ADMIN'); $config = GridFieldConfig::create()->addComponent(new GridFieldDeleteAction(true)); $gridField = new GridField('testfield', 'testfield', $this->list, $config); $form = new Form(new Controller(), 'mockform', new FieldList(array($this->gridField)), new FieldList()); $stateID = 'testGridStateActionField'; Session::set($stateID, array('grid' => '', 'actionName' => 'deleterecord', 'args' => array('RecordID' => $this->idFromFixture('GridFieldAction_Delete_Team', 'team1')))); $token = SecurityToken::inst(); $request = new HTTPRequest('POST', 'url', array(), array('action_gridFieldAlterAction?StateID=' . $stateID => true, $token->getName() => $token->getValue())); $this->gridField->gridFieldAlterAction(array('StateID' => $stateID), $this->form, $request); $this->assertEquals(2, $this->list->count(), 'User should be able to delete records with ADMIN permission.'); }
public function testPermissionFailureSetsCorrectFormMessages() { Config::nest(); // Controller that doesn't attempt redirections $controller = new SecurityTest_NullController(); $controller->setResponse(new HTTPResponse()); Security::permissionFailure($controller, array('default' => 'Oops, not allowed')); $this->assertEquals('Oops, not allowed', Session::get('Security.Message.message')); // Test that config values are used correctly Config::inst()->update('SilverStripe\\Security\\Security', 'default_message_set', 'stringvalue'); Security::permissionFailure($controller); $this->assertEquals('stringvalue', Session::get('Security.Message.message'), 'Default permission failure message value was not present'); Config::inst()->remove('SilverStripe\\Security\\Security', 'default_message_set'); Config::inst()->update('SilverStripe\\Security\\Security', 'default_message_set', array('default' => 'arrayvalue')); Security::permissionFailure($controller); $this->assertEquals('arrayvalue', Session::get('Security.Message.message'), 'Default permission failure message value was not present'); // Test that non-default messages work. // NOTE: we inspect the response body here as the session message has already // been fetched and output as part of it, so has been removed from the session $this->logInWithPermission('EDITOR'); Config::inst()->update('SilverStripe\\Security\\Security', 'default_message_set', array('default' => 'default', 'alreadyLoggedIn' => 'You are already logged in!')); Security::permissionFailure($controller); $this->assertContains('You are already logged in!', $controller->getResponse()->getBody(), 'Custom permission failure message was ignored'); Security::permissionFailure($controller, array('default' => 'default', 'alreadyLoggedIn' => 'One-off failure message')); $this->assertContains('One-off failure message', $controller->getResponse()->getBody(), "Message set passed to Security::permissionFailure() didn't override Config values"); Config::unnest(); }
/** * This is the action that gets executed when a GridField_AlterAction gets clicked. * * @param array $data * @param Form $form * @param HTTPRequest $request * * @return string */ public function gridFieldAlterAction($data, $form, HTTPRequest $request) { $data = $request->requestVars(); // Protection against CSRF attacks $token = $this->getForm()->getSecurityToken(); if (!$token->checkRequest($request)) { $this->httpError(400, _t("Form.CSRF_FAILED_MESSAGE", "There seems to have been a technical problem. Please click the back button, " . "refresh your browser, and try again.")); } $name = $this->getName(); $fieldData = null; if (isset($data[$name])) { $fieldData = $data[$name]; } $state = $this->getState(false); /** @skipUpgrade */ if (isset($fieldData['GridState'])) { $state->setValue($fieldData['GridState']); } foreach ($data as $dataKey => $dataValue) { if (preg_match('/^action_gridFieldAlterAction\\?StateID=(.*)/', $dataKey, $matches)) { $stateChange = Session::get($matches[1]); $actionName = $stateChange['actionName']; $arguments = array(); if (isset($stateChange['args'])) { $arguments = $stateChange['args']; } $html = $this->handleAlterAction($actionName, $arguments, $data); if ($html) { return $html; } } } if ($request->getHeader('X-Pjax') === 'CurrentField') { return $this->FieldHolder(); } return $form->forTemplate(); }
public function setUp() { //nest config and injector for each test so they are effectively sandboxed per test Config::nest(); Injector::nest(); $this->originalReadingMode = Versioned::get_reading_mode(); // We cannot run the tests on this abstract class. if (get_class($this) == __CLASS__) { $this->markTestSkipped(sprintf('Skipping %s ', get_class($this))); return; } // Mark test as being run $this->originalIsRunningTest = self::$is_running_test; self::$is_running_test = true; // i18n needs to be set to the defaults or tests fail i18n::set_locale(i18n::config()->get('default_locale')); i18n::config()->date_format = null; i18n::config()->time_format = null; // Set default timezone consistently to avoid NZ-specific dependencies date_default_timezone_set('UTC'); // Remove password validation $this->originalMemberPasswordValidator = Member::password_validator(); $this->originalRequirements = Requirements::backend(); Member::set_password_validator(null); Cookie::config()->update('report_errors', false); if (class_exists('SilverStripe\\CMS\\Controllers\\RootURLController')) { RootURLController::reset(); } if (class_exists('Translatable')) { Translatable::reset(); } Versioned::reset(); DataObject::reset(); if (class_exists('SilverStripe\\CMS\\Model\\SiteTree')) { SiteTree::reset(); } Hierarchy::reset(); if (Controller::has_curr()) { Controller::curr()->setSession(Session::create(array())); } Security::$database_is_ready = null; // Add controller-name auto-routing // @todo Fix to work with namespaced controllers Director::config()->update('rules', array('$Controller//$Action/$ID/$OtherID' => '*')); $fixtureFiles = $this->getFixturePaths(); // Todo: this could be a special test model $this->model = DataModel::inst(); // Set up fixture if ($fixtureFiles || $this->usesDatabase) { if (!self::using_temp_db()) { self::create_temp_db(); } DataObject::singleton()->flushCache(); self::empty_temp_db(); foreach ($this->requireDefaultRecordsFrom as $className) { $instance = singleton($className); if (method_exists($instance, 'requireDefaultRecords')) { $instance->requireDefaultRecords(); } if (method_exists($instance, 'augmentDefaultRecords')) { $instance->augmentDefaultRecords(); } } foreach ($fixtureFiles as $fixtureFilePath) { $fixture = YamlFixture::create($fixtureFilePath); $fixture->writeInto($this->getFixtureFactory()); } $this->logInWithPermission("ADMIN"); } // Preserve memory settings $this->originalMemoryLimit = ini_get('memory_limit'); // turn off template debugging SSViewer::config()->update('source_file_comments', false); // Clear requirements Requirements::clear(); // Set up email $this->mailer = new TestMailer(); Injector::inst()->registerService($this->mailer, 'SilverStripe\\Control\\Email\\Mailer'); Email::config()->remove('send_all_emails_to'); }
/** * Given a successful login, tell the parent frame to close the dialog * * @return HTTPResponse|DBField */ public function success() { // Ensure member is properly logged in if (!Member::currentUserID()) { return $this->redirectToExternalLogin(); } // Get redirect url $controller = $this->getResponseController(_t('CMSSecurity.SUCCESS', 'Success')); $backURLs = array($this->getRequest()->requestVar('BackURL'), Session::get('BackURL'), Director::absoluteURL(AdminRootController::config()->url_base, true)); $backURL = null; foreach ($backURLs as $backURL) { if ($backURL && Director::is_site_url($backURL)) { break; } } // Show login $controller = $controller->customise(array('Content' => _t('CMSSecurity.SUCCESSCONTENT', '<p>Login success. If you are not automatically redirected ' . '<a target="_top" href="{link}">click here</a></p>', 'Login message displayed in the cms popup once a user has re-authenticated themselves', array('link' => $backURL)))); return $controller->renderWith($this->getTemplatesFor('success')); }
/** * Change the password * * @param array $data The user submitted data * @return HTTPResponse */ public function doChangePassword(array $data) { if ($member = Member::currentUser()) { // The user was logged in, check the current password if (empty($data['OldPassword']) || !$member->checkPassword($data['OldPassword'])->valid()) { $this->clearMessage(); $this->sessionMessage(_t('Member.ERRORPASSWORDNOTMATCH', "Your current password does not match, please try again"), "bad"); // redirect back to the form, instead of using redirectBack() which could send the user elsewhere. return $this->controller->redirect($this->controller->Link('changepassword')); } } if (!$member) { if (Session::get('AutoLoginHash')) { $member = Member::member_from_autologinhash(Session::get('AutoLoginHash')); } // The user is not logged in and no valid auto login hash is available if (!$member) { Session::clear('AutoLoginHash'); return $this->controller->redirect($this->controller->Link('login')); } } // Check the new password if (empty($data['NewPassword1'])) { $this->clearMessage(); $this->sessionMessage(_t('Member.EMPTYNEWPASSWORD', "The new password can't be empty, please try again"), "bad"); // redirect back to the form, instead of using redirectBack() which could send the user elsewhere. return $this->controller->redirect($this->controller->Link('changepassword')); } else { if ($data['NewPassword1'] == $data['NewPassword2']) { $isValid = $member->changePassword($data['NewPassword1']); if ($isValid->valid()) { // Clear locked out status $member->LockedOutUntil = null; $member->FailedLoginCount = null; $member->write(); if ($member->canLogIn()->valid()) { $member->logIn(); } // TODO Add confirmation message to login redirect Session::clear('AutoLoginHash'); if (!empty($_REQUEST['BackURL']) && Director::is_site_url($_REQUEST['BackURL'])) { $url = Director::absoluteURL($_REQUEST['BackURL']); return $this->controller->redirect($url); } else { // Redirect to default location - the login form saying "You are logged in as..." $redirectURL = HTTP::setGetVar('BackURL', Director::absoluteBaseURL(), $this->controller->Link('login')); return $this->controller->redirect($redirectURL); } } else { $this->clearMessage(); $this->sessionMessage(_t('Member.INVALIDNEWPASSWORD', "We couldn't accept that password: {password}", array('password' => nl2br("\n" . Convert::raw2xml($isValid->starredList())))), "bad", false); // redirect back to the form, instead of using redirectBack() which could send the user elsewhere. return $this->controller->redirect($this->controller->Link('changepassword')); } } else { $this->clearMessage(); $this->sessionMessage(_t('Member.ERRORNEWPASSWORD', "You have entered your new password differently, try again"), "bad"); // redirect back to the form, instead of using redirectBack() which could send the user elsewhere. return $this->controller->redirect($this->controller->Link('changepassword')); } } }
/** * Login in the user and figure out where to redirect the browser. * * The $data has this format * array( * 'AuthenticationMethod' => 'MemberAuthenticator', * 'Email' => '*****@*****.**', * 'Password' => '1nitialPassword', * 'BackURL' => 'test/link', * [Optional: 'Remember' => 1 ] * ) * * @param array $data * @return HTTPResponse */ protected function logInUserAndRedirect($data) { Session::clear('SessionForms.MemberLoginForm.Email'); Session::clear('SessionForms.MemberLoginForm.Remember'); if (Member::currentUser()->isPasswordExpired()) { if (isset($_REQUEST['BackURL']) && ($backURL = $_REQUEST['BackURL'])) { Session::set('BackURL', $backURL); } /** @skipUpgrade */ $cp = ChangePasswordForm::create($this->controller, 'ChangePasswordForm'); $cp->sessionMessage(_t('Member.PASSWORDEXPIRED', 'Your password has expired. Please choose a new one.'), 'good'); return $this->controller->redirect('Security/changepassword'); } // Absolute redirection URLs may cause spoofing if (!empty($_REQUEST['BackURL'])) { $url = $_REQUEST['BackURL']; if (Director::is_site_url($url)) { $url = Director::absoluteURL($url); } else { // Spoofing attack, redirect to homepage instead of spoofing url $url = Director::absoluteBaseURL(); } return $this->controller->redirect($url); } // If a default login dest has been set, redirect to that. if ($url = Security::config()->default_login_dest) { $url = Controller::join_links(Director::absoluteBaseURL(), $url); return $this->controller->redirect($url); } // Redirect the user to the page where they came from $member = Member::currentUser(); if ($member) { $firstname = Convert::raw2xml($member->FirstName); if (!empty($data['Remember'])) { Session::set('SessionForms.MemberLoginForm.Remember', '1'); $member->logIn(true); } else { $member->logIn(); } Session::set('Security.Message.message', _t('Member.WELCOMEBACK', "Welcome Back, {firstname}", array('firstname' => $firstname))); Session::set("Security.Message.type", "good"); } return Controller::curr()->redirectBack(); }
public function testCanView() { // Create changeset containing all items (unpublished) $this->logInWithPermission('ADMIN'); $changeSet = new ChangeSet(); $changeSet->write(); $base = $this->objFromFixture(ChangeSetTest_Base::class, 'base'); $changeSet->addObject($base); $changeSet->sync(); $this->assertEquals(5, $changeSet->Changes()->count()); // Check canView Session::clear("loggedInAs"); $this->assertFalse($changeSet->canView()); $this->logInWithPermission('SomeWrongPermission'); $this->assertFalse($changeSet->canView()); $this->logInWithPermission('CMS_ACCESS_CampaignAdmin'); $this->assertTrue($changeSet->canView()); }
/** * @param String $val */ public function setValue($val) { Session::set($this->getName(), $val); }
public function testCanUploadWithPermissionCode() { $field = UploadField::create('MyField'); Session::clear("loggedInAs"); $field->setCanUpload(true); $this->assertTrue($field->canUpload()); $field->setCanUpload(false); $this->assertFalse($field->canUpload()); $this->loginWithPermission('ADMIN'); $field->setCanUpload(false); $this->assertFalse($field->canUpload()); $field->setCanUpload('ADMIN'); $this->assertTrue($field->canUpload()); }
/** * Redirect the user to the change password form. * * @return HTTPResponse */ protected function redirectToChangePassword() { // Since this form is loaded via an iframe, this redirect must be performed via javascript $changePasswordForm = new ChangePasswordForm($this->controller, 'SilverStripe\\Security\\ChangePasswordForm'); $changePasswordForm->sessionMessage(_t('Member.PASSWORDEXPIRED', 'Your password has expired. Please choose a new one.'), 'good'); // Get redirect url $changePasswordURL = $this->getExternalLink('changepassword'); if ($backURL = $this->controller->getRequest()->requestVar('BackURL')) { Session::set('BackURL', $backURL); $changePasswordURL = Controller::join_links($changePasswordURL, '?BackURL=' . urlencode($backURL)); } $changePasswordURLATT = Convert::raw2att($changePasswordURL); $changePasswordURLJS = Convert::raw2js($changePasswordURL); $message = _t('CMSMemberLoginForm.PASSWORDEXPIRED', '<p>Your password has expired. <a target="_top" href="{link}">Please choose a new one.</a></p>', 'Message displayed to user if their session cannot be restored', array('link' => $changePasswordURLATT)); // Redirect to change password page $this->controller->getResponse()->setStatusCode(200); $this->controller->getResponse()->setBody(<<<PHP <!DOCTYPE html> <html><body> {$message} <script type="application/javascript"> setTimeout(function(){top.location.href = "{$changePasswordURLJS}";}, 0); </script> </body></html> PHP ); return $this->controller->getResponse(); }