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.
* 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() {
return !(Director::isDev() || Director::isTest());
public static function isLive($skipDatabase = false) {
return !(Director::isDev($skipDatabase) || Director::isTest($skipDatabase));
}
/**
* This function will return true if the site is in a development environment.
* For information about environment types, see {@link Director::$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.
* 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 isDev($dontTouchDB = false) {
public static function isDev($skipDatabase = false) {
// This variable is used to supress repetitions of the isDev security message below.
static $firstTimeCheckingGetVar = true;
@ -981,7 +985,7 @@ class Director implements TemplateGlobalProvider {
}
// 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($firstTimeCheckingGetVar && !Permission::check('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.
* 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
if(isset($_GET['isTest'])) {
if(!$skipDatabase && isset($_GET['isTest'])) {
if(Security::database_is_ready()) {
BasicAuth::requireLogin("SilverStripe developer access. Use your CMS login", "ADMIN");
$_SESSION['isTest'] = $_GET['isTest'];
@ -1017,10 +1024,13 @@ class Director implements TemplateGlobalProvider {
return true;
}
}
if(self::isDev()) return false;
if(Config::inst()->get('Director', 'environment_type')) {
return Config::inst()->get('Director', 'environment_type') == 'test';
if(self::isDev($skipDatabase)) {
return false;
}
if(self::$environment_type) {
return self::$environment_type == 'test';
}
// Check if we are running on one of the test servers

View File

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

View File

@ -129,7 +129,7 @@ class Deprecation {
*/
public static function notice($atVersion, $string = '', $scope = Deprecation::SCOPE_METHOD) {
// Never raise deprecation notices in a live environment
if(Director::isLive()) return;
if(Director::isLive(true)) return;
$checkVersion = self::$version;
// 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() {

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
### 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
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).
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
### Trapping the publication event