/** * Register that we've had a permission failure trying to view the given page * * This will redirect to a login page. * If you don't provide a messageSet, a default will be used. * * @param Controller $controller The controller that you were on to cause the permission * failure. * @param string|array $messageSet The message to show to the user. This * can be a string, or a map of different * messages for different contexts. * If you pass an array, you can use the * following keys: * - default: The default message * - alreadyLoggedIn: The message to * show if the user * is already logged * in and lacks the * permission to * access the item. * * The alreadyLoggedIn value can contain a '%s' placeholder that will be replaced with a link * to log in. * @return SS_HTTPResponse */ public static function permissionFailure($controller = null, $messageSet = null) { self::set_ignore_disallowed_actions(true); if (!$controller) { $controller = Controller::curr(); } if (Director::is_ajax()) { $response = $controller ? $controller->getResponse() : new SS_HTTPResponse(); $response->setStatusCode(403); if (!Member::currentUser()) { $response->setBody(_t('ContentController.NOTLOGGEDIN', 'Not logged in')); $response->setStatusDescription(_t('ContentController.NOTLOGGEDIN', 'Not logged in')); // Tell the CMS to allow re-aunthentication if (CMSSecurity::enabled()) { $response->addHeader('X-Reauthenticate', '1'); } } return $response; } // Prepare the messageSet provided if (!$messageSet) { if ($configMessageSet = static::config()->get('default_message_set')) { $messageSet = $configMessageSet; } else { $messageSet = array('default' => _t('Security.NOTEPAGESECURED', "That page is secured. Enter your credentials below and we will send " . "you right along."), 'alreadyLoggedIn' => _t('Security.ALREADYLOGGEDIN', "You don't have access to this page. If you have another account that " . "can access that page, you can log in again below.", "%s will be replaced with a link to log in.")); } } if (!is_array($messageSet)) { $messageSet = array('default' => $messageSet); } $member = Member::currentUser(); // Work out the right message to show if ($member && $member->exists()) { $response = $controller ? $controller->getResponse() : new SS_HTTPResponse(); $response->setStatusCode(403); //If 'alreadyLoggedIn' is not specified in the array, then use the default //which should have been specified in the lines above if (isset($messageSet['alreadyLoggedIn'])) { $message = $messageSet['alreadyLoggedIn']; } else { $message = $messageSet['default']; } // Somewhat hackish way to render a login form with an error message. $me = new Security(); $form = $me->LoginForm(); $form->sessionMessage($message, 'warning'); Session::set('MemberLoginForm.force_message', 1); $loginResponse = $me->login(); if ($loginResponse instanceof SS_HTTPResponse) { return $loginResponse; } $response->setBody((string) $loginResponse); $controller->extend('permissionDenied', $member); return $response; } else { $message = $messageSet['default']; } Session::set("Security.Message.message", $message); Session::set("Security.Message.type", 'warning'); Session::set("BackURL", $_SERVER['REQUEST_URI']); // TODO AccessLogEntry needs an extension to handle permission denied errors // Audit logging hook $controller->extend('permissionDenied', $member); return $controller->redirect(Config::inst()->get('SilverStripe\\Security\\Security', 'login_url') . "?BackURL=" . urlencode($_SERVER['REQUEST_URI'])); }