diff --git a/control/Director.php b/control/Director.php index 0236f8a68..46565d7b5 100644 --- a/control/Director.php +++ b/control/Director.php @@ -507,28 +507,28 @@ class Director implements TemplateGlobalProvider { */ public static function is_https() { $return = false; + + // See https://en.wikipedia.org/wiki/List_of_HTTP_header_fields + // See https://support.microsoft.com/?kbID=307347 + $headerOverride = false; + if(TRUSTED_PROXY) { + $headers = (defined('SS_TRUSTED_PROXY_PROTOCOL_HEADER')) ? array(SS_TRUSTED_PROXY_PROTOCOL_HEADER) : null; + if(!$headers) { + // Backwards compatible defaults + $headers = array('HTTP_X_FORWARDED_PROTO', 'HTTP_X_FORWARDED_PROTOCOL', 'HTTP_FRONT_END_HTTPS'); + } + foreach($headers as $header) { + $headerCompareVal = ($header === 'HTTP_FRONT_END_HTTPS' ? 'on' : 'https'); + if(!empty($_SERVER[$header]) && strtolower($_SERVER[$header]) == $headerCompareVal) { + $headerOverride = true; + break; + } + } + } + if ($protocol = Config::inst()->get('Director', 'alternate_protocol')) { $return = ($protocol == 'https'); - } else if( - TRUSTED_PROXY - && isset($_SERVER['HTTP_X_FORWARDED_PROTO']) - && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https' - ) { - // Convention for (non-standard) proxy signaling a HTTPS forward, - // see https://en.wikipedia.org/wiki/List_of_HTTP_header_fields - $return = true; - } else if( - TRUSTED_PROXY - && isset($_SERVER['HTTP_X_FORWARDED_PROTOCOL']) - && strtolower($_SERVER['HTTP_X_FORWARDED_PROTOCOL']) == 'https' - ) { - // Less conventional proxy header - $return = true; - } else if( - isset($_SERVER['HTTP_FRONT_END_HTTPS']) - && strtolower($_SERVER['HTTP_FRONT_END_HTTPS']) == 'on' - ) { - // Microsoft proxy convention: https://support.microsoft.com/?kbID=307347 + } else if($headerOverride) { $return = true; } else if((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off')) { $return = true; diff --git a/control/HTTPRequest.php b/control/HTTPRequest.php index 1aab8f26a..a75131371 100644 --- a/control/HTTPRequest.php +++ b/control/HTTPRequest.php @@ -655,14 +655,27 @@ class SS_HTTPRequest implements ArrayAccess { * @return string */ public function getIP() { - if (TRUSTED_PROXY && !empty($_SERVER['HTTP_CLIENT_IP'])) { - //check ip from share internet - return $_SERVER['HTTP_CLIENT_IP']; - } elseif (TRUSTED_PROXY && !empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { - //to check ip is pass from proxy - return $_SERVER['HTTP_X_FORWARDED_FOR']; + $headerOverrideIP = null; + if(TRUSTED_PROXY) { + $headers = (defined('SS_TRUSTED_PROXY_IP_HEADER')) ? array(SS_TRUSTED_PROXY_IP_HEADER) : null; + if(!$headers) { + // Backwards compatible defaults + $headers = array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR'); + } + foreach($headers as $header) { + if(!empty($_SERVER[$header])) { + $headerOverrideIP = $_SERVER[$header]; + break; + } + } + } + + if ($headerOverrideIP) { + return $headerOverrideIP; } elseif(isset($_SERVER['REMOTE_ADDR'])) { return $_SERVER['REMOTE_ADDR']; + } else { + return null; } } diff --git a/core/Constants.php b/core/Constants.php index 3e958a0ea..a7e1b92aa 100644 --- a/core/Constants.php +++ b/core/Constants.php @@ -179,10 +179,13 @@ if(!isset($_SERVER['HTTP_HOST'])) { /** * Fix HTTP_HOST from reverse proxies */ - if (TRUSTED_PROXY && isset($_SERVER['HTTP_X_FORWARDED_HOST'])) { - + $trustedProxyHeader = (defined('SS_TRUSTED_PROXY_HOST_HEADER')) + ? SS_TRUSTED_PROXY_HOST_HEADER + : 'HTTP_X_FORWARDED_HOST'; + + if (TRUSTED_PROXY && !empty($_SERVER[$trustedProxyHeader])) { // Get the first host, in case there's multiple separated through commas - $_SERVER['HTTP_HOST'] = strtok($_SERVER['HTTP_X_FORWARDED_HOST'], ','); + $_SERVER['HTTP_HOST'] = strtok($_SERVER[SS_TRUSTED_PROXY_HOST_HEADER], ','); } } diff --git a/core/startup/ParameterConfirmationToken.php b/core/startup/ParameterConfirmationToken.php index 6c98300a0..b141fa037 100644 --- a/core/startup/ParameterConfirmationToken.php +++ b/core/startup/ParameterConfirmationToken.php @@ -163,26 +163,25 @@ class ParameterConfirmationToken { // Are we http or https? Replicates Director::is_https() without its dependencies/ $proto = 'http'; - if( - TRUSTED_PROXY - && isset($_SERVER['HTTP_X_FORWARDED_PROTO']) - && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https' - ) { - // Convention for (non-standard) proxy signaling a HTTPS forward, - // see https://en.wikipedia.org/wiki/List_of_HTTP_header_fields - $proto = 'https'; - } else if( - TRUSTED_PROXY - && isset($_SERVER['HTTP_X_FORWARDED_PROTOCOL']) - && strtolower($_SERVER['HTTP_X_FORWARDED_PROTOCOL']) == 'https' - ) { - // Less conventional proxy header - $proto = 'https'; - } else if( - isset($_SERVER['HTTP_FRONT_END_HTTPS']) - && strtolower($_SERVER['HTTP_FRONT_END_HTTPS']) == 'on' - ) { - // Microsoft proxy convention: https://support.microsoft.com/?kbID=307347 + // See https://en.wikipedia.org/wiki/List_of_HTTP_header_fields + // See https://support.microsoft.com/?kbID=307347 + $headerOverride = false; + if(TRUSTED_PROXY) { + $headers = (defined('SS_TRUSTED_PROXY_PROTOCOL_HEADER')) ? array(SS_TRUSTED_PROXY_PROTOCOL_HEADER) : null; + if(!$headers) { + // Backwards compatible defaults + $headers = array('HTTP_X_FORWARDED_PROTO', 'HTTP_X_FORWARDED_PROTOCOL', 'HTTP_FRONT_END_HTTPS'); + } + foreach($headers as $header) { + $headerCompareVal = ($header === 'HTTP_FRONT_END_HTTPS' ? 'on' : 'https'); + if(!empty($_SERVER[$header]) && strtolower($_SERVER[$header]) == $headerCompareVal) { + $headerOverride = true; + break; + } + } + } + + if($headerOverride) { $proto = 'https'; } else if((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off')) { $proto = 'https'; @@ -190,9 +189,6 @@ class ParameterConfirmationToken { $proto = 'https'; } - if((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off')) $proto = 'https'; - if(isset($_SERVER['SSL'])) $proto = 'https'; - $parts = array_filter(array( // What's our host $_SERVER['HTTP_HOST'], diff --git a/dev/DevelopmentAdmin.php b/dev/DevelopmentAdmin.php index 348391085..55584cb20 100644 --- a/dev/DevelopmentAdmin.php +++ b/dev/DevelopmentAdmin.php @@ -33,7 +33,8 @@ class DevelopmentAdmin extends Controller { parent::init(); // Special case for dev/build: Defer permission checks to DatabaseAdmin->init() (see #4957) - $requestedDevBuild = (stripos($this->getRequest()->getURL(), 'dev/build') === 0); + $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. diff --git a/docs/en/02_Developer_Guides/09_Security/04_Secure_Coding.md b/docs/en/02_Developer_Guides/09_Security/04_Secure_Coding.md index 248c8d564..0d948f1c7 100644 --- a/docs/en/02_Developer_Guides/09_Security/04_Secure_Coding.md +++ b/docs/en/02_Developer_Guides/09_Security/04_Secure_Coding.md @@ -580,7 +580,11 @@ server IPs using the SS_TRUSTED_PROXY_IPS define in your _ss_environment.php. :::php define('SS_TRUSTED_PROXY_IPS', '127.0.0.1,192.168.0.1'); + define('SS_TRUSTED_PROXY_HOST_HEADER', 'HTTP_X_FORWARDED_HOST'); + define('SS_TRUSTED_PROXY_IP_HEADER', 'HTTP_X_FORWARDED_FOR'); + define('SS_TRUSTED_PROXY_PROTOCOL_HEADER', 'HTTP_X_FORWARDED_PROTOCOL'); +At the same time, you'll also need to define which headers you trust from these proxy IPs. Since there are multiple ways through which proxies can pass through HTTP information on the original hostname, IP and protocol, these values need to be adjusted for your specific proxy. The header names match their equivalent `$_SERVER` values. If there is no proxy server, 'none' can be used to distrust all clients. If only trusted servers will make requests then you can use '*' to trust all clients. @@ -603,7 +607,6 @@ In a future release this behaviour will be changed to be on by default, and this variable will be no longer necessary, thus it will be necessary to always set SS_TRUSTED_PROXY_IPS if using a proxy. - ## Related * [http://silverstripe.org/security-releases/](http://silverstripe.org/security-releases/) diff --git a/docs/en/04_Changelogs/3.2.2.md b/docs/en/04_Changelogs/3.2.2.md new file mode 100644 index 000000000..8252dd678 --- /dev/null +++ b/docs/en/04_Changelogs/3.2.2.md @@ -0,0 +1,40 @@ +# 3.2.2 + + + +## Change Log + +### Security + + * 2016-02-17 [faa94d5](https://github.com/silverstripe/silverstripe-framework/commit/faa94d51d570788dcebc2f2ef6e9de4d179ce1e4) Hostname, IP and Protocol Spoofing through HTTP Headers (Ingo Schommer) - See [ss-2016-003](http://www.silverstripe.org/download/security-releases/ss-2016-003) + * 2016-02-17 [15d4db3](https://github.com/silverstripe/silverstripe-framework/commit/15d4db3b4a7dbc9a7e089f9329a396f8408ed7d9) Block unauthenticated access to dev/build/defaults (Damian Mooyman) - See [ss-2015-028](http://www.silverstripe.org/download/security-releases/ss-2015-028) + * 2016-02-17 [e2c77c5](https://github.com/silverstripe/silverstripe-framework/commit/e2c77c5a8f13e901c51a3684210811559b592f0c) Ensure Gridfield actions respect CSRF (Damian Mooyman) - See [ss-2016-002](http://www.silverstripe.org/download/security-releases/ss-2016-002) + * 2015-11-11 [245e0aa](https://github.com/silverstripe/silverstripe-framework/commit/245e0aae2f5f3eb0acba1d198ad8e196bb224462) Fix FormField error messages not being encoded safely (Damian Mooyman) - See [ss-2015-026](http://www.silverstripe.org/download/security-releases/ss-2015-026) + * 2015-11-09 [53b3bc7](https://github.com/silverstripe/silverstripe-framework/commit/53b3bc707bcccb8f5e5060f85ab1398a0975bba2) Dont expose class on error (Hamish Friedlander) - See [ss-2015-025](http://www.silverstripe.org/download/security-releases/ss-2015-025) + * 2015-11-01 [ac4342d](https://github.com/silverstripe/silverstripe-framework/commit/ac4342d81d19201bd8d3814f168240db1ac565fe) XML escape RSSFeed $link parameter (Ingo Schommer) - See [ss-2015-022](http://www.silverstripe.org/download/security-releases/ss-2015-022) + * 2015-10-28 [97f21fd](https://github.com/silverstripe/silverstripe-framework/commit/97f21fddb3c565052f19ee3b35366f48e1e9a36f) Fix rewrite hash links XSS (Damian Mooyman) - See [ss-2015-021](http://www.silverstripe.org/download/security-releases/ss-2015-021) + +### Bugfixes + + * 2016-02-15 [8771859](https://github.com/silverstripe/silverstripe-framework/commit/87718597e8f04872c285808d0666fbb69c5100ba) "where" method in SQLUpdate Example (Richard Rudy) + * 2016-01-28 [3fcf1e2](https://github.com/silverstripe/silverstripe-framework/commit/3fcf1e2c98629dcd0048ff9447bad4cd30b4bf95) edge case on many many extra fields (fixes 4991) (Mark Stephens) + * 2016-01-27 [3d0178e](https://github.com/silverstripe/silverstripe-cms/commit/3d0178ebc0b7408442ad2532f998ed47839e7117) Use correct formaction for doRollback exemption (Damian Mooyman) + * 2016-01-24 [d8e354d](https://github.com/silverstripe/silverstripe-framework/commit/d8e354d144383fb6459adf92731853d2e54268d6) PHPDocs on DataList::getIDList() and UnsavedRelationList::getIDList() (Damian Mooyman) + * 2016-01-22 [bf8bf5e](https://github.com/silverstripe/silverstripe-framework/commit/bf8bf5e4d558126bb99ea63881f1885faafddd3d) Prevent Versioned::doRollbackTo from creating incorrect versions on subclasses of Versioned DataObjects (Damian Mooyman) + * 2016-01-21 [cca7129](https://github.com/silverstripe/silverstripe-framework/commit/cca7129385dbb3be1001a8861423c2cf490f02d4) Revert lost documentation (Damian Mooyman) + * 2016-01-11 [85ba918](https://github.com/silverstripe/silverstripe-framework/commit/85ba918a54f51dd524d45f2c93172a18421ae3bf) Update field IDs for file link (fixes silverstripe/silverstripe-cms#1307) (Loz Calver) + * 2016-01-11 [d637141](https://github.com/silverstripe/silverstripe-cms/commit/d6371414876e32e7369ec0219a57d2186cfe3f0f) preg_quote() anchors in SiteTreeLinkTracking (fixes #1359) (Loz Calver) + * 2016-01-05 [00544ff](https://github.com/silverstripe/silverstripe-framework/commit/00544ff100048afdb7ccb1905304dddf8ab3205a) session_regenerate_id uses config system (Daniel Hensby) + * 2016-01-05 [4335d8e](https://github.com/silverstripe/silverstripe-framework/commit/4335d8ed221a2b402299b32e31f97fc2956ec161) Members with no ID inherit logged in user permission (Daniel Hensby) + * 2015-12-15 [afbb5cf](https://github.com/silverstripe/silverstripe-framework/commit/afbb5cfed4d29aea5868f0f12cd735dc5abe10d3) Vimeo oEmbed endpoint redirecting to no www (UndefinedOffset) + * 2015-12-14 [d265c9b](https://github.com/silverstripe/silverstripe-framework/commit/d265c9b733ddac27d6df286ce000b09e1c69b986) Allow omitting a value for OptionsetField submissions (fixes #4824) (Loz Calver) + * 2015-12-11 [5a21b2f](https://github.com/silverstripe/silverstripe-framework/commit/5a21b2fb15ed9c675594f0f990765bd4f97155c7) Guard against users being added to all groups on unsaved Group. (Mateusz Uzdowski) + * 2015-11-27 [94742fa](https://github.com/silverstripe/silverstripe-framework/commit/94742fa3e2efad8f77f4acd1f9d06bf74916c5e6) Revert method visibility regression (Damian Mooyman) + * 2015-11-18 [e9b833f](https://github.com/silverstripe/silverstripe-framework/commit/e9b833f5f0f989af8d611f8cfe71f0b0e2cb0159) ConfirmedPassword field correctly reports mismatching passwords (Christopher Darling) + * 2015-11-17 [68d99be](https://github.com/silverstripe/silverstripe-framework/commit/68d99be24b63a933f041cd80a248a7b7fa8d588c) Hidden errors for composite fields nested inside FieldGroups (fixes #4773) (Loz Calver) + * 2015-11-17 [97e90b8](https://github.com/silverstripe/silverstripe-cms/commit/97e90b8ebd8078bb60ecea66bdd3761380f93a61) RedirectorPage toggles not working (fixes #1328) (Loz Calver) + * 2015-11-17 [b624eb9](https://github.com/silverstripe/silverstripe-cms/commit/b624eb98f1d1ff36811a3294ad29b31a50683d60) Setting target for unwritten VirtualPage breaks write (Loz Calver) + * 2015-11-16 [2983d82](https://github.com/silverstripe/silverstripe-cms/commit/2983d823d1eef293ef11aac9e01336e23ed52b59) Ensure VirtualPage forwards request/response data to virtual controllers (fixes #1329) (Loz Calver) + * 2015-11-12 [fea1158](https://github.com/silverstripe/silverstripe-framework/commit/fea1158d193ed4d037df94101e3b3f2d24a6ce49) Fix print button only displaying first page (Damian Mooyman) + * 2015-11-11 [a40812a](https://github.com/silverstripe/silverstripe-framework/commit/a40812ac3320d27f243ef0ed54aa003fc53720b6) Don’t reuse DBConnector (fixes #4735) (Sam Minnee) + * 2015-11-05 [f577ecb](https://github.com/silverstripe/silverstripe-framework/commit/f577ecb81149d0d09dc846204f17b2153a244b5a) prevent use cache on browser back button (Igor Nadj) diff --git a/docs/en/04_Changelogs/rc/3.2.2-rc2.md b/docs/en/04_Changelogs/rc/3.2.2-rc2.md new file mode 100644 index 000000000..41a03f1f8 --- /dev/null +++ b/docs/en/04_Changelogs/rc/3.2.2-rc2.md @@ -0,0 +1,11 @@ +# 3.2.2-rc2 + + + +## Change Log + +### Security + + * 2016-02-17 [faa94d5](https://github.com/silverstripe/silverstripe-framework/commit/faa94d51d570788dcebc2f2ef6e9de4d179ce1e4) Hostname, IP and Protocol Spoofing through HTTP Headers (Ingo Schommer) - See [ss-2016-003](http://www.silverstripe.org/download/security-releases/ss-2016-003) + * 2016-02-17 [15d4db3](https://github.com/silverstripe/silverstripe-framework/commit/15d4db3b4a7dbc9a7e089f9329a396f8408ed7d9) Block unauthenticated access to dev/build/defaults (Damian Mooyman) - See [ss-2015-028](http://www.silverstripe.org/download/security-releases/ss-2015-028) + * 2016-02-17 [e2c77c5](https://github.com/silverstripe/silverstripe-framework/commit/e2c77c5a8f13e901c51a3684210811559b592f0c) Ensure Gridfield actions respect CSRF (Damian Mooyman) - See [ss-2016-002](http://www.silverstripe.org/download/security-releases/ss-2016-002) diff --git a/forms/gridfield/GridField.php b/forms/gridfield/GridField.php index c18115514..e0414914d 100644 --- a/forms/gridfield/GridField.php +++ b/forms/gridfield/GridField.php @@ -833,6 +833,18 @@ class GridField extends FormField { */ public function gridFieldAlterAction($data, $form, SS_HTTPRequest $request) { $data = $request->requestVars(); + + // Protection against CSRF attacks + $token = $this + ->getForm() + ->getSecurityToken(); + if(!$token->checkRequest($request)) { + $this->httpError(400, _t("Form.CSRF_FAILED_MESSAGE", + "There seems to have been a technical problem. Please click the back button, ". + "refresh your browser, and try again." + )); + } + $name = $this->getName(); $fieldData = null; diff --git a/lang/cs.yml b/lang/cs.yml index 6245a3427..60ec7fad0 100644 --- a/lang/cs.yml +++ b/lang/cs.yml @@ -301,6 +301,8 @@ cs: FROMWEB: 'Z webu' FindInFolder: 'Hledat ve složce' IMAGEALT: 'Alternativní text (alt)' + IMAGEALTTEXT: 'Alternativní text (alt) - bude ukázán, když obrázek nemúže být zobrazen' + IMAGEALTTEXTDESC: 'Zobrazeno na obrazovce, když obrázek nemůže být zobrazen' IMAGEDIMENSIONS: Rozměry IMAGEHEIGHTPX: Výška IMAGETITLE: 'Titul text (tooltip) - další informace o obrázku' @@ -334,10 +336,13 @@ cs: LeftAndMain: CANT_REORGANISE: 'Nemáte oprávnění měnit stránky nejvyšší úrovně. Vaše změna nebyla uložena.' DELETED: Smazáno. + DropdownBatchActionsDefault: Akce HELP: Nápověda + PAGETYPE: 'Typ stránky' PERMAGAIN: 'Byli jste odhlášeni z CMS. Pokud se chcete znovu přihlásit, zadejte níže své uživatelské jméno a heslo.' PERMALREADY: 'Omlouvám se, ale nemůžete vstoupit do této části CMS. Pokud se chcete přihlásit jako někdo jiný, udělejte tak níže.' PERMDEFAULT: 'Musíte být přihlášen/a k přístup do oblasti administrace, níže zadejte vaše přihlašovací údaje, prosím.' + PLEASESAVE: 'Prosím uložte stránku: Tato stránka nemohla být aktualizována, ještě nebyla uložena.' PreviewButton: Náhled REORGANISATIONSUCCESSFUL: 'Strom webu reorganizován úspěšně.' SAVEDUP: Uloženo. diff --git a/lang/lt.yml b/lang/lt.yml index 2a06f3eb5..13d5c7e0f 100644 --- a/lang/lt.yml +++ b/lang/lt.yml @@ -301,6 +301,8 @@ lt: FROMWEB: 'Iš interneto' FindInFolder: 'Rasti kataloge' IMAGEALT: 'Alternatyvus tekstas (alt)' + IMAGEALTTEXT: 'Alternatyvus tekstas (alt) - rodomas, jeigu nepavyko parodyti paveikslėlio' + IMAGEALTTEXTDESC: 'Rodomas, jeigu nepavyko parodyti paveikslėlio' IMAGEDIMENSIONS: Matmenys IMAGEHEIGHTPX: Aukštis IMAGETITLE: 'Pavadinimo tekstas (tooltip) - papildomai informacijai apie paveikslėlį' @@ -334,10 +336,13 @@ lt: LeftAndMain: CANT_REORGANISE: 'Jūs neturite leidimo keisti aukščiausio lygio puslapių. Jūsų pakeitimai neišsaugoti.' DELETED: Ištrinta. + DropdownBatchActionsDefault: Veiksmai HELP: Pagalba + PAGETYPE: 'Puslapio tipas' PERMAGAIN: 'Jūs atsijungėte. Norėdami vėl prisijungti, įveskite savo duomenis į žemiau esančius laukelius.' PERMALREADY: 'Deja, bet Jūs negalite patekti į šią TVS dalį. Jeigu norite prisijungti kitu vartotoju, tai atlikite žemiau.' PERMDEFAULT: 'Jūs turite būti prisijungę, norėdami pasiekti administravimo zoną; prašome suvesti prisijungimo duomenis į žemiau esančius laukelius.' + PLEASESAVE: 'Prašome išsaugoti puslapį: Šis puslapis negali būti atnaujintas, nes jis dar nėra išsaugotas.' PreviewButton: Peržiūra REORGANISATIONSUCCESSFUL: 'Puslapių medis pertvarkytas sėkmingai.' SAVEDUP: Išsaugota. diff --git a/lang/sk.yml b/lang/sk.yml index 52bba5a82..9433fb357 100644 --- a/lang/sk.yml +++ b/lang/sk.yml @@ -301,6 +301,8 @@ sk: FROMWEB: 'Z webu' FindInFolder: 'Vyhľadať v priečinku' IMAGEALT: 'Atlernatívny text (alt)' + IMAGEALTTEXT: 'Atlernatívny text (alt) - sa zobrazí, ak nemôže byť zobrazený obrázok' + IMAGEALTTEXTDESC: 'Zobrazí sa na obrazovke, keď obrázok nemôže byť zobrazený' IMAGEDIMENSIONS: Rozmery IMAGEHEIGHTPX: Výška IMAGETITLE: 'Text titulky (tooltip) - pre doplňujúce informácie o obrázku' @@ -334,10 +336,13 @@ sk: LeftAndMain: CANT_REORGANISE: 'Nemáte oprávnenie meniť stránky najvyššej úrovne. Vaša zmena nebola uložená.' DELETED: Zmazané. + DropdownBatchActionsDefault: Akcie HELP: Pomoc + PAGETYPE: 'Typ stránky:' PERMAGAIN: 'Boli ste odhlásený' PERMALREADY: 'Je nám ľúto, ale k tejto časti CMS nemáte prístup . Ak sa chcete prihlásiť ako niekto iný, urobte tak nižšie.' PERMDEFAULT: 'Musíte byť prihlásený/á k prístupu do oblasti administrácie, zadajte vaše prihlasovacie údaje dole, prosím.' + PLEASESAVE: 'Prosím uložte stránku: Táto stránka nemôže byť aktualizovaná, ešte nebola uložená.' PreviewButton: Náhľad REORGANISATIONSUCCESSFUL: 'Strom webu bol reorganizovaný úspešne.' SAVEDUP: Uložené. diff --git a/tests/forms/gridfield/GridFieldDeleteActionTest.php b/tests/forms/gridfield/GridFieldDeleteActionTest.php index 2d0f2c4d6..2f4d2d909 100644 --- a/tests/forms/gridfield/GridFieldDeleteActionTest.php +++ b/tests/forms/gridfield/GridFieldDeleteActionTest.php @@ -42,15 +42,54 @@ class GridFieldDeleteActionTest extends SapphireTest { $this->assertEquals(3, count($deleteButtons), 'Delete buttons should show when logged in.'); } + public function testActionsRequireCSRF() { + $this->logInWithPermission('ADMIN'); + $this->setExpectedException( + 'SS_HTTPResponse_Exception', + _t("Form.CSRF_FAILED_MESSAGE", + "There seems to have been a technical problem. Please click the back button, ". + "refresh your browser, and try again." + ), + 400 + ); + $stateID = 'testGridStateActionField'; + $request = new SS_HTTPRequest( + 'POST', + 'url', + array(), + array( + 'action_gridFieldAlterAction?StateID='.$stateID, + 'SecurityID' => null, + ) + ); + $this->gridField->gridFieldAlterAction(array('StateID'=>$stateID), $this->form, $request); + } + public function testDeleteActionWithoutCorrectPermission() { if(Member::currentUser()) { Member::currentUser()->logOut(); } $this->setExpectedException('ValidationException'); $stateID = 'testGridStateActionField'; - Session::set($stateID, array('grid'=>'', 'actionName'=>'deleterecord', - 'args'=>array('RecordID'=>$this->idFromFixture('GridFieldAction_Delete_Team', 'team1')))); - $request = new SS_HTTPRequest('POST', 'url', array(), - array('action_gridFieldAlterAction?StateID='.$stateID=>true)); + Session::set( + $stateID, + array( + 'grid' => '', + 'actionName' => 'deleterecord', + 'args' => array( + 'RecordID' => $this->idFromFixture('GridFieldAction_Delete_Team', 'team1') + ) + ) + ); + $token = SecurityToken::inst(); + $request = new SS_HTTPRequest( + 'POST', + 'url', + array(), + array( + 'action_gridFieldAlterAction?StateID='.$stateID => true, + $token->getName() => $token->getValue(), + ) + ); $this->gridField->gridFieldAlterAction(array('StateID'=>$stateID), $this->form, $request); $this->assertEquals(3, $this->list->count(), 'User should\'t be able to delete records without correct permissions.'); @@ -59,10 +98,26 @@ class GridFieldDeleteActionTest extends SapphireTest { public function testDeleteActionWithAdminPermission() { $this->logInWithPermission('ADMIN'); $stateID = 'testGridStateActionField'; - Session::set($stateID, array('grid'=>'', 'actionName'=>'deleterecord', - 'args'=>array('RecordID'=>$this->idFromFixture('GridFieldAction_Delete_Team', 'team1')))); - $request = new SS_HTTPRequest('POST', 'url', array(), - array('action_gridFieldAlterAction?StateID='.$stateID=>true)); + Session::set( + $stateID, + array( + 'grid'=>'', + 'actionName'=>'deleterecord', + 'args' => array( + 'RecordID' => $this->idFromFixture('GridFieldAction_Delete_Team', 'team1') + ) + ) + ); + $token = SecurityToken::inst(); + $request = new SS_HTTPRequest( + 'POST', + 'url', + array(), + array( + 'action_gridFieldAlterAction?StateID='.$stateID=>true, + $token->getName() => $token->getValue(), + ) + ); $this->gridField->gridFieldAlterAction(array('StateID'=>$stateID), $this->form, $request); $this->assertEquals(2, $this->list->count(), 'User should be able to delete records with ADMIN permission.'); } @@ -76,11 +131,26 @@ class GridFieldDeleteActionTest extends SapphireTest { $form = new Form(new Controller(), 'mockform', new FieldList(array($this->gridField)), new FieldList()); $stateID = 'testGridStateActionField'; - Session::set($stateID, array('grid'=>'', 'actionName'=>'deleterecord', - 'args'=>array('RecordID'=>$this->idFromFixture('GridFieldAction_Delete_Team', 'team1')))); - $request = new SS_HTTPRequest('POST', 'url', array(), - array('action_gridFieldAlterAction?StateID='.$stateID=>true)); - + Session::set( + $stateID, + array( + 'grid'=>'', + 'actionName'=>'deleterecord', + 'args' => array( + 'RecordID' => $this->idFromFixture('GridFieldAction_Delete_Team', 'team1') + ) + ) + ); + $token = SecurityToken::inst(); + $request = new SS_HTTPRequest( + 'POST', + 'url', + array(), + array( + 'action_gridFieldAlterAction?StateID='.$stateID=>true, + $token->getName() => $token->getValue(), + ) + ); $this->gridField->gridFieldAlterAction(array('StateID'=>$stateID), $this->form, $request); $this->assertEquals(2, $this->list->count(), 'User should be able to delete records with ADMIN permission.');