Пример #1
0
 /**
  * Require basic authentication.  Will request a username and password if none is given.
  * 
  * Used by {@link Controller::init()}.
  * 
  * @param string $realm
  * @param string|array $permissionCode
  * @return Member $member 
  */
 static function requireLogin($realm, $permissionCode)
 {
     if (!Security::database_is_ready() || Director::is_cli()) {
         return true;
     }
     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) {
             $authenticated = true;
         }
     }
     // If we've failed the authentication mechanism, then show the login form
     if (!isset($authenticated)) {
         header("WWW-Authenticate: Basic realm=\"{$realm}\"");
         header($_SERVER['SERVER_PROTOCOL'] . ' 401 Unauthorized');
         if (isset($_SERVER['PHP_AUTH_USER'])) {
             echo _t('BasicAuth.ERRORNOTREC', "That username / password isn't recognised");
         } else {
             echo _t('BasicAuth.ENTERINFO', "Please enter a username and password.");
         }
         die;
     }
     if (!Permission::checkMember($member->ID, $permissionCode)) {
         header("WWW-Authenticate: Basic realm=\"{$realm}\"");
         header($_SERVER['SERVER_PROTOCOL'] . ' 401 Unauthorized');
         if (isset($_SERVER['PHP_AUTH_USER'])) {
             echo _t('BasicAuth.ERRORNOTADMIN', "That user is not an administrator.");
         }
         die;
     }
     return $member;
 }
 protected function logVisit()
 {
     if (!Security::database_is_ready()) {
         return;
     }
     DB::query(sprintf('UPDATE "Member" SET "LastVisited" = %s, "NumVisit" = "NumVisit" + 1 WHERE "ID" = %d', DB::get_conn()->now(), $this->owner->ID));
 }
 /**
  * Require basic authentication.  Will request a username and password if none is given.
  *
  * Used by {@link Controller::init()}.
  *
  * @throws SS_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 $member
  */
 public static function requireLogin($realm, $permissionCode = null, $tryUsingSessionLogin = true)
 {
     $isRunningTests = class_exists('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 SS_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 SS_HTTPResponse_Exception(null, 401);
         $e->setResponse($response);
         throw $e;
     }
     if ($permissionCode && !Permission::checkMember($member->ID, $permissionCode)) {
         $response = new SS_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 SS_HTTPResponse_Exception(null, 401);
         $e->setResponse($response);
         throw $e;
     }
     return $member;
 }
 function populateDefaults()
 {
     parent::populateDefaults();
     $this->Title = _t("OrderStatusLog.ORDERDISPATCHED", "Order Dispatched");
     $this->DispatchedOn = date('Y-m-d');
     if (Security::database_is_ready()) {
         if (Member::currentUser()) {
             $this->DispatchedBy = Member::currentUser()->getTitle();
         }
     }
 }
 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.
     $canAccess = Director::isDev() || !Security::database_is_ready() || Director::is_cli() && !SapphireTest::is_running_test() || 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.");
     }
 }
Пример #6
0
 /**
  * Updates the database schema, creating tables & fields as necessary.
  */
 function build()
 {
     if (Director::isLive() && Security::database_is_ready() && (!Member::currentUser() || !Member::currentUser()->isAdmin())) {
         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.");
         return;
     }
     // The default time limit of 30 seconds is normally not enough
     if (ini_get("safe_mode") != "1") {
         set_time_limit(600);
     }
     $this->doBuild(isset($_REQUEST['quiet']) || isset($_REQUEST['from_installer']));
 }
Пример #7
0
 /**
  * Initialisation function that is run before any action on the controller is called.
  *
  * @uses BasicAuth::requireLogin()
  */
 public function init()
 {
     if ($this->basicAuthEnabled) {
         BasicAuth::protect_site_if_necessary();
     }
     // Directly access the session variable just in case the Group or Member tables don't yet exist
     if (Member::config()->log_last_visited) {
         Deprecation::notice('4.0', 'Member::$LastVisited is deprecated. From 4.0 onwards you should implement this as a custom extension');
         if (Session::get('loggedInAs') && Security::database_is_ready() && ($member = Member::currentUser())) {
             DB::prepared_query(sprintf('UPDATE "Member" SET "LastVisited" = %s WHERE "ID" = ?', DB::get_conn()->now()), array($member->ID));
         }
     }
     // This is used to test that subordinate controllers are actually calling parent::init() - a common bug
     $this->baseInitCalled = true;
 }
Пример #8
0
	/**
	 * Initialisation function that is run before any action on the controller is called.
	 * 
	 * @uses BasicAuth::requireLogin()
	 */
	function init() {
		if($this->basicAuthEnabled) BasicAuth::protect_site_if_necessary();

		// Directly access the session variable just in case the Group or Member tables don't yet exist
		if(Session::get('loggedInAs') && Security::database_is_ready()) {
			$member = Member::currentUser();
			if($member) {
				if(!headers_sent()) Cookie::set("PastMember", true, 90, null, null, false, true);
				DB::query("UPDATE \"Member\" SET \"LastVisited\" = " . DB::getConn()->now() . " WHERE \"ID\" = $member->ID", null);
			}
		}
		
		// This is used to test that subordinate controllers are actually calling parent::init() - a common bug
		$this->baseInitCalled = true;
	}
Пример #9
0
 /**
  * Initialisation function that is run before any action on the controller is called.
  * 
  * @uses BasicAuth::requireLogin()
  */
 function init()
 {
     if ($this->basicAuthEnabled) {
         BasicAuth::protect_site_if_necessary();
     }
     // Directly access the session variable just in case the Group or Member tables don't yet exist
     if (Session::get('loggedInAs') && Security::database_is_ready()) {
         if ($member = Member::currentUser()) {
             if (!headers_sent()) {
                 Cookie::set("PastMember", true);
             }
             DB::query("UPDATE Member SET LastVisited = NOW() WHERE ID = {$member->ID}", null);
         }
     }
     // This is used to test that subordinate controllers are actually calling parent::init() - a common bug
     $this->baseInitCalled = true;
 }
 public 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.");
     }
     //render the debug view
     $renderer = Object::create('DebugView');
     $renderer->writeHeader();
     $renderer->writeInfo(_t("Shop.DEVTOOLSTITLE", "Shop Development Tools"), Director::absoluteBaseURL());
 }
Пример #11
0
 /**
  * Require basic authentication.  Will request a username and password if none is given.
  *
  * Used by {@link Controller::init()}.
  *
  * @throws SS_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 $member
  */
 public static function requireLogin($realm, $permissionCode = null, $tryUsingSessionLogin = true)
 {
     $isRunningTests = class_exists('SapphireTest', false) && SapphireTest::is_running_test();
     if (!Security::database_is_ready() || Director::is_cli() && !$isRunningTests) {
         return true;
     }
     $matches = array();
     if (isset($_SERVER['HTTP_AUTHORIZATION']) && preg_match('/Basic\\s+(.*)$/i', $_SERVER['HTTP_AUTHORIZATION'], $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 SS_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 SS_HTTPResponse_Exception(null, 401);
         $e->setResponse($response);
         throw $e;
     }
     if ($permissionCode && !Permission::checkMember($member->ID, $permissionCode)) {
         $response = new SS_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 SS_HTTPResponse_Exception(null, 401);
         $e->setResponse($response);
         throw $e;
     }
     return $member;
 }
Пример #12
0
	/**
	 * Initialisation function that is run before any action on the controller is called.
	 * 
	 * @uses BasicAuth::requireLogin()
	 */
	function init() {
		// Test and development sites should be secured, via basic-auth
		if(Director::isTest() && $this->basicAuthEnabled && Security::database_is_ready()) {
			BasicAuth::requireLogin("SilverStripe test website.  Use your  CMS login", "ADMIN");
		}		

		// Directly access the session variable just in case the Group or Member tables don't yet exist
		if(Session::get('loggedInAs') && Security::database_is_ready()) {
			if($member = Member::currentUser()) {
				Cookie::set("PastMember", true);
				DB::query("UPDATE Member SET LastVisited = NOW() WHERE ID = $member->ID", null);
			}
		}
		
		// This is used to test that subordinate controllers are actually calling parent::init() - a common bug
		$this->baseInitCalled = true;
	}
Пример #13
0
	/**
	 * Updates the database schema, creating tables & fields as necessary.
	 */
	function build() {
		if(Director::isLive() && Security::database_is_ready() && !Director::is_cli() && !Permission::check("ADMIN")) {
			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.");
			return;
		}

		// The default time limit of 30 seconds is normally not enough
		if(ini_get("safe_mode") != "1") {
			set_time_limit(600);
		}

		// Get all our classes
		ManifestBuilder::create_manifest_file();
		require(MANIFEST_FILE);
		
		$this->doBuild(isset($_REQUEST['quiet']) || isset($_REQUEST['from_installer']), !isset($_REQUEST['dont_populate']));
	}
Пример #14
0
	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() 
			// We need to ensure that DevelopmentAdminTest can simulate permission failures when running
			// "dev/tests" from CLI. 
			|| (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.");
		}
	}
Пример #15
0
 /**
  * This function will return true if the site is in a test environment.
  * For information about environment types, see {@link Director::set_environment_type()}.
  */
 static function isTest()
 {
     // Use ?isTest=1 to get test access on the live server, or explicitly set your environment
     if (isset($_GET['isTest'])) {
         if (Security::database_is_ready()) {
             BasicAuth::requireLogin("SilverStripe developer access. Use your CMS login", "ADMIN");
             $_SESSION['isTest'] = $_GET['isTest'];
         } else {
             return true;
         }
     }
     if (self::isDev()) {
         return false;
     }
     if (self::$environment_type) {
         return self::$environment_type == 'test';
     }
     // Check if we are running on one of the test servers
     if (isset($_SERVER['HTTP_HOST']) && in_array($_SERVER['HTTP_HOST'], Director::$test_servers)) {
         return true;
     }
     return false;
 }
Пример #16
0
     unset($_GET['flush']);
 } else {
     $chain->setSuppression(false);
 }
 // Load in core
 require_once 'core/Core.php';
 // Connect to database
 require_once 'model/DB.php';
 global $databaseConfig;
 if ($databaseConfig) {
     DB::connect($databaseConfig);
 }
 // Then if a flush was requested, redirect to it
 if ($token->parameterProvided() && !$token->tokenProvided()) {
     // First, check if we're in dev mode, or the database doesn't have any security data
     $canFlush = Director::isDev() || !Security::database_is_ready();
     // Otherwise, we start up the session if needed, then check for admin
     if (!$canFlush) {
         if (!isset($_SESSION) && Session::request_contains_session_id()) {
             Session::start();
         }
         if (Permission::check('ADMIN')) {
             $canFlush = true;
         } else {
             $loginPage = Director::absoluteURL(Config::inst()->get('Security', 'login_url'));
             $loginPage .= "?BackURL=" . urlencode($_SERVER['REQUEST_URI']);
             header('location: ' . $loginPage, true, 302);
             die;
         }
     }
     // And if we can flush, reload with an authority token
 public function setUp()
 {
     // We cannot run the tests on this abstract class.
     if (get_class($this) == "SapphireTest") {
         $this->skipTest = true;
     }
     if ($this->skipTest) {
         $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::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);
     Config::inst()->update('Cookie', 'report_errors', false);
     if (class_exists('RootURLController')) {
         RootURLController::reset();
     }
     if (class_exists('Translatable')) {
         Translatable::reset();
     }
     Versioned::reset();
     DataObject::reset();
     if (class_exists('SiteTree')) {
         SiteTree::reset();
     }
     Hierarchy::reset();
     if (Controller::has_curr()) {
         Controller::curr()->setSession(Injector::inst()->create('Session', array()));
     }
     Security::$database_is_ready = null;
     // Add controller-name auto-routing
     Config::inst()->update('Director', 'rules', array('$Controller//$Action/$ID/$OtherID' => '*'));
     $fixtureFile = static::get_fixture_file();
     $prefix = defined('SS_DATABASE_PREFIX') ? SS_DATABASE_PREFIX : 'ss_';
     // Set up email
     $this->originalMailer = Email::mailer();
     $this->mailer = new TestMailer();
     Email::set_mailer($this->mailer);
     Config::inst()->remove('Email', 'send_all_emails_to');
     // Todo: this could be a special test model
     $this->model = DataModel::inst();
     // Set up fixture
     if ($fixtureFile || $this->usesDatabase || !self::using_temp_db()) {
         if (substr(DB::get_conn()->getSelectedDatabase(), 0, strlen($prefix) + 5) != strtolower(sprintf('%stmpdb', $prefix))) {
             //echo "Re-creating temp database... ";
             self::create_temp_db();
             //echo "done.\n";
         }
         singleton('DataObject')->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();
             }
         }
         if ($fixtureFile) {
             $pathForClass = $this->getCurrentAbsolutePath();
             $fixtureFiles = is_array($fixtureFile) ? $fixtureFile : array($fixtureFile);
             $i = 0;
             foreach ($fixtureFiles as $fixtureFilePath) {
                 // Support fixture paths relative to the test class, rather than relative to webroot
                 // String checking is faster than file_exists() calls.
                 $isRelativeToFile = strpos('/', $fixtureFilePath) === false || preg_match('/^\\.\\./', $fixtureFilePath);
                 if ($isRelativeToFile) {
                     $resolvedPath = realpath($pathForClass . '/' . $fixtureFilePath);
                     if ($resolvedPath) {
                         $fixtureFilePath = $resolvedPath;
                     }
                 }
                 $fixture = Injector::inst()->create('YamlFixture', $fixtureFilePath);
                 $fixture->writeInto($this->getFixtureFactory());
                 $this->fixtures[] = $fixture;
                 // backwards compatibility: Load first fixture into $this->fixture
                 if ($i == 0) {
                     $this->fixture = $fixture;
                 }
                 $i++;
             }
         }
         $this->logInWithPermission("ADMIN");
     }
     // Preserve memory settings
     $this->originalMemoryLimit = ini_get('memory_limit');
     // turn off template debugging
     Config::inst()->update('SSViewer', 'source_file_comments', false);
     // Clear requirements
     Requirements::clear();
 }
Пример #18
0
 /**
  * Log the user in if the "remember login" cookie is set
  *
  * The <i>remember login token</i> will be changed on every successful
  * auto-login.
  */
 public static function autoLogin()
 {
     // Don't bother trying this multiple times
     if (!class_exists('SapphireTest') || !SapphireTest::is_running_test()) {
         self::$_already_tried_to_auto_log_in = true;
     }
     if (strpos(Cookie::get('alc_enc'), ':') === false || Session::get("loggedInAs") || !Security::database_is_ready()) {
         return;
     }
     if (strpos(Cookie::get('alc_enc'), ':') && Cookie::get('alc_device') && !Session::get("loggedInAs")) {
         list($uid, $token) = explode(':', Cookie::get('alc_enc'), 2);
         $deviceID = Cookie::get('alc_device');
         $member = Member::get()->byId($uid);
         $rememberLoginHash = null;
         // check if autologin token matches
         if ($member) {
             $hash = $member->encryptWithUserSettings($token);
             $rememberLoginHash = RememberLoginHash::get()->filter(array('MemberID' => $member->ID, 'DeviceID' => $deviceID, 'Hash' => $hash))->First();
             if (!$rememberLoginHash) {
                 $member = null;
             } else {
                 // Check for expired token
                 $expiryDate = new DateTime($rememberLoginHash->ExpiryDate);
                 $now = SS_Datetime::now();
                 $now = new DateTime($now->Rfc2822());
                 if ($now > $expiryDate) {
                     $member = null;
                 }
             }
         }
         if ($member) {
             self::session_regenerate_id();
             Session::set("loggedInAs", $member->ID);
             // This lets apache rules detect whether the user has logged in
             if (Member::config()->login_marker_cookie) {
                 Cookie::set(Member::config()->login_marker_cookie, 1, 0, null, null, false, true);
             }
             if ($rememberLoginHash) {
                 $rememberLoginHash->renew();
                 $tokenExpiryDays = Config::inst()->get('RememberLoginHash', 'token_expiry_days');
                 Cookie::set('alc_enc', $member->ID . ':' . $rememberLoginHash->getToken(), $tokenExpiryDays, null, null, false, true);
             }
             $member->write();
             // Audit logging hook
             $member->extend('memberAutoLoggedIn');
         }
     }
 }
Пример #19
0
 function testDatabaseIsReadyWithInsufficientMemberColumns()
 {
     // Assumption: The database has been built correctly by the test runner,
     // and has all columns present in the ORM
     DB::getConn()->renameField('Member', 'Email', 'Email_renamed');
     // Email column is now missing, which means we're not ready to do permission checks
     $this->assertFalse(Security::database_is_ready());
     // Rebuild the database (which re-adds the Email column), and try again
     $this->resetDBSchema(true);
     $this->assertTrue(Security::database_is_ready());
 }
Пример #20
0
 /**
  * This function will return true if the site is in a test environment.
  * For information about environment types, see {@link Director::set_environment_type()}.
  *
  * @param $skipDatabase Skips database checks for current login permissions if set to TRUE,
  * which is useful for checks happening before the database is functional.
  */
 public static function isTest($skipDatabase = false)
 {
     // Use ?isTest=1 to get test access on the live server, or explicitly set your environment
     if (!$skipDatabase && isset($_GET['isTest'])) {
         if (Security::database_is_ready()) {
             BasicAuth::requireLogin("SilverStripe developer access. Use your CMS login", "ADMIN");
             $_SESSION['isTest'] = $_GET['isTest'];
         } else {
             return true;
         }
     }
     if (self::isDev($skipDatabase)) {
         return false;
     }
     if (Config::inst()->get('Director', 'environment_type')) {
         return Config::inst()->get('Director', 'environment_type') == 'test';
     }
     // Check if we are running on one of the test servers
     $testServers = (array) Config::inst()->get('Director', 'test_servers');
     if (isset($_SERVER['HTTP_HOST']) && in_array($_SERVER['HTTP_HOST'], $testServers)) {
         return true;
     }
     return false;
 }
 /**
  * standard SS method
  */
 function populateDefaults()
 {
     parent::populateDefaults();
     //can only run after first dev/build
     if (Security::database_is_ready()) {
         $controller = Controller::curr();
         if ($controller instanceof DatabaseAdmin) {
             //cant do this now.
         } else {
             if ($this->EcomConfig()->ShopPricesAreTaxExclusive) {
                 $this->InclusiveOrExclusive = "Exclusive";
             } else {
                 $this->InclusiveOrExclusive = "Inclusive";
             }
         }
     }
 }
 /**
  * standard SS method
  */
 function populateDefaults()
 {
     parent::populateDefaults();
     if (Security::database_is_ready()) {
         $this->AuthorID = Member::currentUserID();
     }
 }
Пример #23
0
function silverstripe_main($chain)
{
    global $token;
    if (isset($_GET['flush']) && !$token->tokenProvided()) {
        unset($_GET['flush']);
    } else {
        $chain->setSuppression(false);
    }
    /**
     * Include Sapphire's core code
     */
    require_once "core/Core.php";
    if (function_exists('mb_http_output')) {
        mb_http_output('UTF-8');
        mb_internal_encoding('UTF-8');
    }
    Session::start();
    if (isset($_GET['debug_profile'])) {
        Profiler::init();
        Profiler::mark('all_execution');
        Profiler::mark('main.php init');
    }
    // Connect to database
    require_once "core/model/DB.php";
    global $databaseConfig;
    if (isset($_GET['debug_profile'])) {
        Profiler::mark('DB::connect');
    }
    if ($databaseConfig) {
        DB::connect($databaseConfig);
    }
    if (isset($_GET['debug_profile'])) {
        Profiler::unmark('DB::connect');
    }
    if ($token->parameterProvided() && !$token->tokenProvided()) {
        // First, check if we're in dev mode, or the database doesn't have any security data
        $canFlush = Director::isDev() || !Security::database_is_ready();
        // Otherwise, we start up the session if needed, then check for admin
        if (!$canFlush) {
            if (!isset($_SESSION) && (isset($_COOKIE[session_name()]) || isset($_REQUEST[session_name()]))) {
                Session::start();
            }
            if (Permission::check('ADMIN')) {
                $canFlush = true;
            } else {
                $loginPage = Director::absoluteURL('Security/login');
                $loginPage .= "?BackURL=" . urlencode($_SERVER['REQUEST_URI']);
                header('location: ' . $loginPage, true, 302);
                die;
            }
        }
        // And if we can flush, reload with an authority token
        if ($canFlush) {
            $token->reloadWithToken();
        }
    }
}
Пример #24
0
 /**
  * Checks the database is in a state to perform security checks.
  * See {@link DatabaseAdmin->init()} for more information.
  *
  * @return bool
  */
 public static function database_is_ready()
 {
     // Used for unit tests
     if (self::$force_database_is_ready !== NULL) {
         return self::$force_database_is_ready;
     }
     if (self::$database_is_ready) {
         return self::$database_is_ready;
     }
     $requiredTables = ClassInfo::dataClassesFor('Member');
     $requiredTables[] = 'Group';
     $requiredTables[] = 'Permission';
     foreach ($requiredTables as $table) {
         // Skip test classes, as not all test classes are scaffolded at once
         if (is_subclass_of($table, 'TestOnly')) {
             continue;
         }
         // if any of the tables aren't created in the database
         if (!ClassInfo::hasTable($table)) {
             return false;
         }
         // HACK: DataExtensions aren't applied until a class is instantiated for
         // the first time, so create an instance here.
         singleton($table);
         // if any of the tables don't have all fields mapped as table columns
         $dbFields = DB::field_list($table);
         if (!$dbFields) {
             return false;
         }
         $objFields = DataObject::database_fields($table, false);
         $missingFields = array_diff_key($objFields, $dbFields);
         if ($missingFields) {
             return false;
         }
     }
     self::$database_is_ready = true;
     return true;
 }
Пример #25
0
 /**
  * Log the user in if the "remember login" cookie is set
  *
  * The <i>remember login token</i> will be changed on every successful
  * auto-login.
  */
 public static function autoLogin()
 {
     // Don't bother trying this multiple times
     self::$_already_tried_to_auto_log_in = true;
     if (strpos(Cookie::get('alc_enc'), ':') === false || Session::get("loggedInAs") || !Security::database_is_ready()) {
         return;
     }
     list($uid, $token) = explode(':', Cookie::get('alc_enc'), 2);
     $member = DataObject::get_by_id("Member", $uid);
     // check if autologin token matches
     if ($member) {
         $hash = $member->encryptWithUserSettings($token);
         if (!$member->RememberLoginToken || $member->RememberLoginToken !== $hash) {
             $member = null;
         }
     }
     if ($member) {
         self::session_regenerate_id();
         Session::set("loggedInAs", $member->ID);
         // This lets apache rules detect whether the user has logged in
         if (Member::config()->login_marker_cookie) {
             Cookie::set(Member::config()->login_marker_cookie, 1, 0, null, null, false, true);
         }
         $generator = new RandomGenerator();
         $token = $generator->randomToken('sha1');
         $hash = $member->encryptWithUserSettings($token);
         $member->RememberLoginToken = $hash;
         Cookie::set('alc_enc', $member->ID . ':' . $token, 90, null, null, false, true);
         $member->write();
         // Audit logging hook
         $member->extend('memberAutoLoggedIn');
     }
 }
Пример #26
0
    // Connect to database
    require_once 'model/DB.php';
    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(Config::inst()->get('Security', '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']) {
 /**
  * Log permission failures (where the status is set after init of page).
  */
 public function onAfterInit()
 {
     // Suppress errors if dev/build necessary
     if (!\Security::database_is_ready()) {
         return false;
     }
     $currentMember = \Member::currentUser();
     if (!($currentMember && $currentMember->exists())) {
         return false;
     }
     $statusCode = $this->owner->getResponse()->getStatusCode();
     if (substr($statusCode, 0, 1) == '4') {
         $this->logPermissionDenied($statusCode, $currentMember);
     }
 }
Пример #28
0
 /**
  * @deprecated Use Security::database_is_ready() instead.
  */
 static function ready()
 {
     user_error("ClassInfo::ready() deprectaed - use Security::database_is_ready()", E_USER_NOTICE);
     return Security::database_is_ready();
 }
Пример #29
0
 public function testDatabaseIsReadyWithInsufficientMemberColumns()
 {
     $old = Security::$force_database_is_ready;
     Security::$force_database_is_ready = null;
     Security::$database_is_ready = false;
     DataObject::clear_classname_spec_cache();
     // Assumption: The database has been built correctly by the test runner,
     // and has all columns present in the ORM
     DB::get_schema()->renameField('Member', 'Email', 'Email_renamed');
     // Email column is now missing, which means we're not ready to do permission checks
     $this->assertFalse(Security::database_is_ready());
     // Rebuild the database (which re-adds the Email column), and try again
     $this->resetDBSchema(true);
     $this->assertTrue(Security::database_is_ready());
     Security::$force_database_is_ready = $old;
 }