Merge remote-tracking branch 'origin/3.0' into 3.1

Conflicts:
	control/Director.php
This commit is contained in:
Ingo Schommer 2013-11-05 10:15:14 +01:00
commit 91f6039eed
7 changed files with 144 additions and 38 deletions

View File

@ -953,19 +953,23 @@ class Director implements TemplateGlobalProvider {
/* /*
* This function will return true if the site is in a live environment. * This function will return true if the site is in a live environment.
* For information about environment types, see {@link Director::$environment_type}. * 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 isLive() { public static function isLive($skipDatabase = false) {
return !(Director::isDev() || Director::isTest()); return !(Director::isDev($skipDatabase) || Director::isTest($skipDatabase));
} }
/** /**
* This function will return true if the site is in a development environment. * This function will return true if the site is in a development environment.
* For information about environment types, see {@link Director::$environment_type}. * For information about environment types, see {@link Director::set_environment_type()}.
* @param $dontTouchDB If true, the database checks are not performed, which allows certain DB checks *
* to not fail before the DB is ready. If false (default), DB checks are included. * @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 isDev($dontTouchDB = false) { public static function isDev($skipDatabase = false) {
// This variable is used to supress repetitions of the isDev security message below. // This variable is used to supress repetitions of the isDev security message below.
static $firstTimeCheckingGetVar = true; static $firstTimeCheckingGetVar = true;
@ -981,7 +985,7 @@ class Director implements TemplateGlobalProvider {
} }
// Use ?isDev=1 to get development access on the live server // Use ?isDev=1 to get development access on the live server
if(!$dontTouchDB && !$result && isset($_GET['isDev'])) { if(!$skipDatabase && !$result && isset($_GET['isDev'])) {
if(Security::database_is_ready()) { if(Security::database_is_ready()) {
if($firstTimeCheckingGetVar && !Permission::check('ADMIN')){ if($firstTimeCheckingGetVar && !Permission::check('ADMIN')){
BasicAuth::requireLogin("SilverStripe developer access. Use your CMS login", "ADMIN"); BasicAuth::requireLogin("SilverStripe developer access. Use your CMS login", "ADMIN");
@ -1005,11 +1009,14 @@ class Director implements TemplateGlobalProvider {
/** /**
* This function will return true if the site is in a test environment. * This function will return true if the site is in a test environment.
* For information about environment types, see {@link Director::$environment_type}. * 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() { public static function isTest($skipDatabase = false) {
// Use ?isTest=1 to get test access on the live server, or explicitly set your environment // Use ?isTest=1 to get test access on the live server, or explicitly set your environment
if(isset($_GET['isTest'])) { if(!$skipDatabase && isset($_GET['isTest'])) {
if(Security::database_is_ready()) { if(Security::database_is_ready()) {
BasicAuth::requireLogin("SilverStripe developer access. Use your CMS login", "ADMIN"); BasicAuth::requireLogin("SilverStripe developer access. Use your CMS login", "ADMIN");
$_SESSION['isTest'] = $_GET['isTest']; $_SESSION['isTest'] = $_GET['isTest'];
@ -1017,10 +1024,13 @@ class Director implements TemplateGlobalProvider {
return true; return true;
} }
} }
if(self::isDev()) return false;
if(Config::inst()->get('Director', 'environment_type')) { if(self::isDev($skipDatabase)) {
return Config::inst()->get('Director', 'environment_type') == 'test'; return false;
}
if(self::$environment_type) {
return self::$environment_type == 'test';
} }
// Check if we are running on one of the test servers // Check if we are running on one of the test servers

View File

@ -16,6 +16,8 @@ class SS_Backtrace {
'mysql_connect', 'mysql_connect',
'mssql_connect', 'mssql_connect',
'pg_connect', 'pg_connect',
array('mysqli', 'mysqli'),
array('mysqli', 'select_db'),
array('DB', 'connect'), array('DB', 'connect'),
array('Security', 'check_default_admin'), array('Security', 'check_default_admin'),
array('Security', 'encrypt_password'), array('Security', 'encrypt_password'),

View File

@ -129,7 +129,7 @@ class Deprecation {
*/ */
public static function notice($atVersion, $string = '', $scope = Deprecation::SCOPE_METHOD) { public static function notice($atVersion, $string = '', $scope = Deprecation::SCOPE_METHOD) {
// Never raise deprecation notices in a live environment // Never raise deprecation notices in a live environment
if(Director::isLive()) return; if(Director::isLive(true)) return;
$checkVersion = self::$version; $checkVersion = self::$version;
// Getting a backtrace is slow, so we only do it if we need it // Getting a backtrace is slow, so we only do it if we need it

View File

@ -72,6 +72,10 @@ class DevelopmentAdmin extends Controller {
} }
} }
// 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::reading_stage('Stage');
} }
public function index() { public function index() {

View File

@ -0,0 +1,35 @@
# 3.0.9
## Overview
### Default current Versioned "stage" to "Live" rather than "Stage"
Previously only the controllers responsible for page and CMS display
(`LeftAndMain` and `ContentController`) explicitly set a stage through
`Versioned::choose_site_stage()`. Unless this method is called,
the default stage will be "Stage", showing draft content.
Any direct subclasses of `Controller` interacting with "versioned" objects
are vulnerable to exposing unpublished content, unless `choose_site_stage()`
is called explicitly in their own logic.
In order to provide more secure default behaviour, we have changed
`choose_site_stage()` to be called on all requests, defaulting to the "Live" stage.
If your logic relies on querying draft content, use `Versioned::reading_stage('Stage')`.
Important: The `choose_site_stage()` call only deals with setting the default stage,
and doesn't check if the user is authenticated to view it. As with any other controller logic,
please use `DataObject->canView()` to determine permissions.
:::php
class MyController extends Controller {
private static $allowed_actions = array('showpage');
public function showpage($request) {
$page = Page::get()->byID($request->param('ID'));
if(!$page->canView()) return $this->httpError(401);
// continue with authenticated logic...
}
}
### API Changes
* 2013-08-03 [0e7231f](https://github.com/silverstripe/sapphire/commit/0e7231f) Disable discontinued Google Spellcheck in TinyMCE (Ingo Schommer)

View File

@ -2,6 +2,34 @@
## Upgrading ## Upgrading
### Default current Versioned "stage" to "Live" rather than "Stage"
Previously only the controllers responsible for page and CMS display
(`LeftAndMain` and `ContentController`) explicitly set a stage through
`Versioned::choose_site_stage()`. Unless this method is called,
the default stage will be "Stage", showing draft content.
Any direct subclasses of `Controller` interacting with "versioned" objects
are vulnerable to exposing unpublished content, unless `choose_site_stage()`
is called explicitly in their own logic.
In order to provide more secure default behaviour, we have changed
`choose_site_stage()` to be called on all requests, defaulting to the "Live" stage.
If your logic relies on querying draft content, use `Versioned::reading_stage('Stage')`.
Important: The `choose_site_stage()` call only deals with setting the default stage,
and doesn't check if the user is authenticated to view it. As with any other controller logic,
please use `DataObject->canView()` to determine permissions.
:::php
class MyController extends Controller {
private static $allowed_actions = array('showpage');
public function showpage($request) {
$page = Page::get()->byID($request->param('ID'));
if(!$page->canView()) return $this->httpError(401);
// continue with authenticated logic...
}
}
### Treedropdownfield showsearch defaults to true ### Treedropdownfield showsearch defaults to true
The showSearch option of TreedropdownField is now set to true by default. This is to provide a fallback ui for when children of a tree node fail to render (due to too many children). You may set search as false when initializing a TreedropdownField, or afterwards: The showSearch option of TreedropdownField is now set to true by default. This is to provide a fallback ui for when children of a tree node fail to render (due to too many children). You may set search as false when initializing a TreedropdownField, or afterwards:

View File

@ -157,6 +157,33 @@ The `$Content` variable contain the published content by default,
and only preview draft content if explicitly requested (e.g. by the "preview" feature in the CMS). and only preview draft content if explicitly requested (e.g. by the "preview" feature in the CMS).
If you want to force a specific stage, we recommend the `Controller->init()` method for this purpose. If you want to force a specific stage, we recommend the `Controller->init()` method for this purpose.
### Controllers
The current stage for each request is determined by `VersionedRequestFilter` before
any controllers initialize, through `Versioned::choose_site_stage()`.
It checks for a `Stage` GET parameter, so you can force
a draft stage by appending `?stage=Stage` to your request. The setting is "sticky"
in the PHP session, so any subsequent requests will also be in draft stage.
Important: The `choose_site_stage()` call only deals with setting the default stage,
and doesn't check if the user is authenticated to view it. As with any other controller logic,
please use `DataObject->canView()` to determine permissions, and avoid exposing unpublished
content to your users.
:::php
class MyController extends Controller {
private static $allowed_actions = array('showpage');
public function showpage($request) {
$page = Page::get()->byID($request->param('ID'));
if(!$page->canView()) return $this->httpError(401);
// continue with authenticated logic...
}
}
The `ContentController` class responsible for page display already has this built in,
so your own `canView()` checks are only necessary in controllers extending directly
from the `Controller` class.
## Recipes ## Recipes
### Trapping the publication event ### Trapping the publication event