public function processRecord($record, $columnMap, &$results, $preview = false) { // We match by 'Code', the ID property is confusing the importer if (isset($record['ID'])) { unset($record['ID']); } $objID = parent::processRecord($record, $columnMap, $results, $preview); $group = DataObject::get_by_id($this->objectClass, $objID); // set group hierarchies - we need to do this after all records // are imported to avoid missing "early" references to parents // which are imported later on in the CSV file. if (isset($record['ParentCode']) && $record['ParentCode']) { $parentGroup = DataObject::get_one('SilverStripe\\Security\\Group', array('"Group"."Code"' => $record['ParentCode'])); if ($parentGroup) { $group->ParentID = $parentGroup->ID; $group->write(); } } // set permission codes - these are all additive, meaning // existing permissions arent cleared. if (isset($record['PermissionCodes']) && $record['PermissionCodes']) { foreach (explode(',', $record['PermissionCodes']) as $code) { $p = DataObject::get_one('SilverStripe\\Security\\Permission', array('"Permission"."Code"' => $code, '"Permission"."GroupID"' => $group->ID)); if (!$p) { $p = new Permission(array('Code' => $code)); $p->write(); } $group->Permissions()->add($p); } } return $objID; }
protected function init() { parent::init(); if (!Director::is_cli() && !Permission::check('ADMIN')) { return Security::permissionFailure(); } }
public function init() { parent::init(); if (!Permission::check('ADMIN')) { return Security::permissionFailure($this); } }
public function testModelAdminOpens() { $this->autoFollowRedirection = false; $this->logInAs('admin'); $this->assertTrue((bool) Permission::check("ADMIN")); $this->assertEquals(200, $this->get('ModelAdminTest_Admin')->getStatusCode()); }
protected function init() { parent::init(); // Unless called from the command line, all CliControllers need ADMIN privileges if (!Director::is_cli() && !Permission::check("ADMIN")) { return Security::permissionFailure(); } }
public function init() { parent::init(); $canAccess = Director::isDev() || Director::is_cli() || Permission::check("ADMIN"); if (!$canAccess) { return Security::permissionFailure($this); } }
protected function init() { parent::init(); $isRunningTests = class_exists('SilverStripe\\Dev\\SapphireTest', false) && SapphireTest::is_running_test(); $canAccess = Director::isDev() || Director::is_cli() && !$isRunningTests || Permission::check("ADMIN"); if (!$canAccess) { Security::permissionFailure($this); } }
public function testDefaultAdmin() { $adminMembers = Permission::get_members_by_permission('ADMIN'); $this->assertEquals(0, $adminMembers->count()); $admin = Member::default_admin(); $this->assertInstanceOf('SilverStripe\\Security\\Member', $admin); $this->assertTrue(Permission::checkMember($admin, 'ADMIN')); $this->assertEquals($admin->Email, Security::default_admin_username()); $this->assertNull($admin->Password); }
public function run($request) { if (!Permission::check('ADMIN') && !Director::is_cli()) { $response = Security::permissionFailure(); if ($response) { $response->output(); } die; } SapphireTest::delete_all_temp_dbs(); }
protected function init() { parent::init(); // We allow access to this controller regardless of live-status or ADMIN permission only // if on CLI or with the database not ready. The latter makes it less errorprone to do an // initial schema build without requiring a default-admin login. // Access to this controller is always allowed in "dev-mode", or of the user is ADMIN. $isRunningTests = class_exists('SapphireTest', false) && SapphireTest::is_running_test(); $canAccess = Director::isDev() || !Security::database_is_ready() || Director::is_cli() && !$isRunningTests || Permission::check("ADMIN"); if (!$canAccess) { return Security::permissionFailure($this, "This page is secured and you need administrator rights to access it. " . "Enter your credentials below and we will send you right along."); } }
public function canView($member = null) { if (!$member && $member !== false) { $member = Member::currentUser(); } // cms menus only for logged-in members if (!$member) { return false; } // Check they can access the CMS and that they are trying to edit themselves if (Permission::checkMember($member, "CMS_ACCESS") && $member->ID === Member::currentUserID()) { return true; } return false; }
protected function init() { parent::init(); // Special case for dev/build: Defer permission checks to DatabaseAdmin->init() (see #4957) $requestedDevBuild = stripos($this->getRequest()->getURL(), 'dev/build') === 0 && stripos($this->getRequest()->getURL(), 'dev/build/defaults') === false; // We allow access to this controller regardless of live-status or ADMIN permission only // if on CLI. Access to this controller is always allowed in "dev-mode", or of the user is ADMIN. $canAccess = $requestedDevBuild || Director::isDev() || Director::is_cli() || Permission::check("ADMIN"); if (!$canAccess) { Security::permissionFailure($this); return; } // check for valid url mapping // lacking this information can cause really nasty bugs, // e.g. when running Director::test() from a FunctionalTest instance global $_FILE_TO_URL_MAPPING; if (Director::is_cli()) { if (isset($_FILE_TO_URL_MAPPING)) { $testPath = BASE_PATH; $matched = false; while ($testPath && $testPath != "/" && !preg_match('/^[A-Z]:\\\\$/', $testPath)) { if (isset($_FILE_TO_URL_MAPPING[$testPath])) { $matched = true; break; } $testPath = dirname($testPath); } if (!$matched) { echo 'Warning: You probably want to define ' . 'an entry in $_FILE_TO_URL_MAPPING that covers "' . Director::baseFolder() . '"' . "\n"; } } else { echo 'Warning: You probably want to define $_FILE_TO_URL_MAPPING in ' . 'your _ss_environment.php as instructed on the "sake" page of the doc.silverstripe.org wiki' . "\n"; } } // Backwards compat: Default to "draft" stage, which is important // for tasks like dev/build which call DataObject->requireDefaultRecords(), // but also for other administrative tasks which have assumptions about the default stage. Versioned::set_stage(Versioned::DRAFT); }
/** * @see SecurityAdmin_MemberImportForm * * @return Form */ public function GroupImportForm() { if (!Permission::check('ADMIN')) { return false; } $form = new GroupImportForm($this, 'GroupImportForm'); return $form; }
public function testEmptyMemberFails() { $member = new Member(); $this->assertFalse($member->exists()); $this->logInWithPermission('ADMIN'); $this->assertFalse(Permission::checkMember($member, 'ADMIN')); $this->assertFalse(Permission::checkMember($member, 'CMS_ACCESS_LeftAndMain')); }
/** * @param Member $member * @param array $context Additional context-specific data which might * affect whether (or where) this object could be created. * @return boolean */ public function canCreate($member = null, $context = array()) { $extended = $this->extendedCan(__FUNCTION__, $member, $context); if ($extended !== null) { return $extended; } return Permission::check('ADMIN', 'any', $member); }
public function can($perm, $member = null, $context = array()) { $perms = ["PERM_{$perm}", 'CAN_ALL']; return Permission::checkMember($member, $perms); }
/** * Check if this file can be modified * * @param Member $member * @return boolean */ public function canEdit($member = null) { if (!$member) { $member = Member::currentUser(); } $result = $this->extendedCan('canEdit', $member); if ($result !== null) { return $result; } return Permission::checkMember($member, array('CMS_ACCESS_AssetAdmin', 'CMS_ACCESS_LeftAndMain')); }
public function CanOrganiseSitetree() { return !Permission::check('SITETREE_REORGANISE') && !Permission::check('ADMIN') ? false : true; }
/** * Cleanup function to reset all the Filename fields. Visit File/fixfiles to call. */ public function fixfiles() { if (!Permission::check('ADMIN')) { return Security::permissionFailure($this); } $files = DataObject::get("File"); foreach ($files as $file) { $file->updateFilesystem(); echo "<li>", $file->Filename; $file->write(); } echo "<p>Done!"; }
public function canDelete($member = null) { return Permission::check('APPLY_ROLES', 'any', $member); }
/** * Create a member and group with the given permission code, and log in with it. * Returns the member ID. * * @param string|array $permCode Either a permission, or list of permissions * @return int Member ID */ public function logInWithPermission($permCode = "ADMIN") { if (is_array($permCode)) { $permArray = $permCode; $permCode = implode('.', $permCode); } else { $permArray = array($permCode); } // Check cached member if (isset($this->cache_generatedMembers[$permCode])) { $member = $this->cache_generatedMembers[$permCode]; } else { // Generate group with these permissions $group = Group::create(); $group->Title = "{$permCode} group"; $group->write(); // Create each individual permission foreach ($permArray as $permArrayItem) { $permission = Permission::create(); $permission->Code = $permArrayItem; $permission->write(); $group->Permissions()->add($permission); } $member = DataObject::get_one('SilverStripe\\Security\\Member', array('"Member"."Email"' => "{$permCode}@example.org")); if (!$member) { $member = Member::create(); } $member->FirstName = $permCode; $member->Surname = "User"; $member->Email = "{$permCode}@example.org"; $member->write(); $group->Members()->add($member); $this->cache_generatedMembers[$permCode] = $member; } $member->logIn(); return $member->ID; }
/** * Determine if the user has permission to attach existing files * By default returns true if the user has the CMS_ACCESS_AssetAdmin permission * * @return boolean */ public function canAttachExisting() { if (!$this->isActive()) { return false; } $can = $this->getConfig('canAttachExisting'); return is_bool($can) ? $can : Permission::check($can); }
/** * Return an existing member with administrator privileges, or create one of necessary. * * Will create a default 'Administrators' group if no group is found * with an ADMIN permission. Will create a new 'Admin' member with administrative permissions * if no existing Member with these permissions is found. * * Important: Any newly created administrator accounts will NOT have valid * login credentials (Email/Password properties), which means they can't be used for login * purposes outside of any default credentials set through {@link Security::setDefaultAdmin()}. * * @return Member */ public static function findAnAdministrator() { // coupling to subsites module $origSubsite = null; if (is_callable('Subsite::changeSubsite')) { $origSubsite = \Subsite::currentSubsiteID(); \Subsite::changeSubsite(0); } $member = null; // find a group with ADMIN permission $adminGroup = Permission::get_groups_by_permission('ADMIN')->first(); if (is_callable('Subsite::changeSubsite')) { \Subsite::changeSubsite($origSubsite); } if ($adminGroup) { $member = $adminGroup->Members()->First(); } if (!$adminGroup) { Group::singleton()->requireDefaultRecords(); $adminGroup = Permission::get_groups_by_permission('ADMIN')->first(); } if (!$member) { Member::singleton()->requireDefaultRecords(); $member = Permission::get_members_by_permission('ADMIN')->first(); } if (!$member) { $member = Member::default_admin(); } if (!$member) { // Failover to a blank admin $member = Member::create(); $member->FirstName = _t('Member.DefaultAdminFirstname', 'Default Admin'); $member->write(); // Add member to group instead of adding group to member // This bypasses the privilege escallation code in Member_GroupSet $adminGroup->DirectMembers()->add($member); } return $member; }
/** * Validate that this DBFile accepts this filename as valid * * @param string $filename * @throws ValidationException * @return bool */ protected function isValidFilename($filename) { $extension = strtolower(File::get_file_extension($filename)); // Validate true if within the list of allowed extensions $allowed = $this->getAllowedExtensions(); if ($allowed) { return in_array($extension, $allowed); } // If no extensions are configured, fallback to global list $globalList = File::config()->allowed_extensions; if (in_array($extension, $globalList)) { return true; } // Only admins can bypass global rules return !File::config()->apply_restrictions_to_admin && Permission::check('ADMIN'); }
public function onBeforeWrite() { parent::onBeforeWrite(); // Just in case we've altered someone's permissions Permission::flush_permission_cache(); }
/** * An internal utility function to set up variables in preparation for including a compiled * template, then do the include * * Effectively this is the common code that both SSViewer#process and SSViewer_FromString#process call * * @param string $cacheFile The path to the file that contains the template compiled to PHP * @param ViewableData $item The item to use as the root scope for the template * @param array $overlay Any variables to layer on top of the scope * @param array $underlay Any variables to layer underneath the scope * @param ViewableData $inheritedScope The current scope of a parent template including a sub-template * @return string The result of executing the template */ protected function includeGeneratedTemplate($cacheFile, $item, $overlay, $underlay, $inheritedScope = null) { if (isset($_GET['showtemplate']) && $_GET['showtemplate'] && Permission::check('ADMIN')) { $lines = file($cacheFile); echo "<h2>Template: {$cacheFile}</h2>"; echo "<pre>"; foreach ($lines as $num => $line) { echo str_pad($num + 1, 5) . htmlentities($line, ENT_COMPAT, 'UTF-8'); } echo "</pre>"; } $cache = $this->getPartialCacheStore(); $scope = new SSViewer_DataPresenter($item, $overlay, $underlay, $inheritedScope); $val = ''; include $cacheFile; return $val; }
/** * Default permissions for this ChangeSetItem * * @param string $perm * @param Member $member * @param array $context * @return bool */ public function can($perm, $member = null, $context = array()) { if (!$member) { $member = Member::currentUser(); } // Allow extensions to bypass default permissions, but only if // each change can be individually published. $extended = $this->extendedCan($perm, $member, $context); if ($extended !== null) { return $extended; } // Default permissions return (bool) Permission::checkMember($member, ChangeSet::config()->required_permission); }
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(); global $databaseConfig; // Redirect to the installer if no database is selected if (!isset($databaseConfig) || !isset($databaseConfig['database']) || !$databaseConfig['database']) {
/** * Check that the given action is allowed to be called from a URL. * It will interrogate {@link self::$allowed_actions} to determine this. * * @param string $action * @return bool * @throws Exception */ public function checkAccessAction($action) { $actionOrigCasing = $action; $action = strtolower($action); $isAllowed = false; $isDefined = false; // Get actions for this specific class (without inheritance) $definingClass = $this->definingClassForAction($actionOrigCasing); $allowedActions = $this->allowedActions($definingClass); // check if specific action is set if (isset($allowedActions[$action])) { $isDefined = true; $test = $allowedActions[$action]; if ($test === true || $test === 1 || $test === '1') { // TRUE should always allow access $isAllowed = true; } elseif (substr($test, 0, 2) == '->') { // Determined by custom method with "->" prefix list($method, $arguments) = Object::parse_class_spec(substr($test, 2)); $isAllowed = call_user_func_array(array($this, $method), $arguments); } else { // Value is a permission code to check the current member against $isAllowed = Permission::check($test); } } elseif (is_array($allowedActions) && ($key = array_search($action, $allowedActions, true)) !== false && is_numeric($key)) { // Allow numeric array notation (search for array value as action instead of key) $isDefined = true; $isAllowed = true; } elseif (is_array($allowedActions) && !count($allowedActions)) { // If defined as empty array, deny action $isAllowed = false; } elseif ($allowedActions === null) { // If undefined, allow action based on configuration $isAllowed = !Config::inst()->get('RequestHandler', 'require_allowed_actions'); } // If we don't have a match in allowed_actions, // whitelist the 'index' action as well as undefined actions based on configuration. if (!$isDefined && ($action == 'index' || empty($action))) { $isAllowed = true; } return $isAllowed; }
/** * Require basic authentication. Will request a username and password if none is given. * * Used by {@link Controller::init()}. * * @throws HTTPResponse_Exception * * @param string $realm * @param string|array $permissionCode Optional * @param boolean $tryUsingSessionLogin If true, then the method with authenticate against the * session log-in if those credentials are disabled. * @return Member|bool $member */ public static function requireLogin($realm, $permissionCode = null, $tryUsingSessionLogin = true) { $isRunningTests = class_exists('SilverStripe\\Dev\\SapphireTest', false) && SapphireTest::is_running_test(); if (!Security::database_is_ready() || Director::is_cli() && !$isRunningTests) { return true; } /* * Enable HTTP Basic authentication workaround for PHP running in CGI mode with Apache * Depending on server configuration the auth header may be in HTTP_AUTHORIZATION or * REDIRECT_HTTP_AUTHORIZATION * * The follow rewrite rule must be in the sites .htaccess file to enable this workaround * RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] */ $authHeader = isset($_SERVER['HTTP_AUTHORIZATION']) ? $_SERVER['HTTP_AUTHORIZATION'] : (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION']) ? $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] : null); $matches = array(); if ($authHeader && preg_match('/Basic\\s+(.*)$/i', $authHeader, $matches)) { list($name, $password) = explode(':', base64_decode($matches[1])); $_SERVER['PHP_AUTH_USER'] = strip_tags($name); $_SERVER['PHP_AUTH_PW'] = strip_tags($password); } $member = null; if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) { $member = MemberAuthenticator::authenticate(array('Email' => $_SERVER['PHP_AUTH_USER'], 'Password' => $_SERVER['PHP_AUTH_PW']), null); } if (!$member && $tryUsingSessionLogin) { $member = Member::currentUser(); } // If we've failed the authentication mechanism, then show the login form if (!$member) { $response = new HTTPResponse(null, 401); $response->addHeader('WWW-Authenticate', "Basic realm=\"{$realm}\""); if (isset($_SERVER['PHP_AUTH_USER'])) { $response->setBody(_t('BasicAuth.ERRORNOTREC', "That username / password isn't recognised")); } else { $response->setBody(_t('BasicAuth.ENTERINFO', "Please enter a username and password.")); } // Exception is caught by RequestHandler->handleRequest() and will halt further execution $e = new HTTPResponse_Exception(null, 401); $e->setResponse($response); throw $e; } if ($permissionCode && !Permission::checkMember($member->ID, $permissionCode)) { $response = new HTTPResponse(null, 401); $response->addHeader('WWW-Authenticate', "Basic realm=\"{$realm}\""); if (isset($_SERVER['PHP_AUTH_USER'])) { $response->setBody(_t('BasicAuth.ERRORNOTADMIN', "That user is not an administrator.")); } // Exception is caught by RequestHandler->handleRequest() and will halt further execution $e = new HTTPResponse_Exception(null, 401); $e->setResponse($response); throw $e; } return $member; }