From b57b3ff4541f2b617ab2640297226e65b2c6ee2e Mon Sep 17 00:00:00 2001 From: Will Rossiter Date: Mon, 13 Oct 2014 21:52:19 +1300 Subject: [PATCH] Clean up debugging documentation --- .../07_Debugging/00_Environment_Types.md | 88 ++++++++++ .../07_Debugging/01_Error_Handling.md | 106 +++++------- .../02_Developer_Guides/07_Debugging/index.md | 157 +++--------------- .../08_Performance/Profiling.md | 8 + .../{02_Member.md => 00_Member.md} | 4 +- .../{03_Permission.md => 02_Permission.md} | 0 .../{00_Security.md => 04_Secure_Coding.md} | 0 .../09_Security/How_To/Track_Member_Logins.md | 52 ------ .../02_Developer_Guides/09_Security/index.md | 11 +- 9 files changed, 172 insertions(+), 254 deletions(-) create mode 100644 docs/en/02_Developer_Guides/07_Debugging/00_Environment_Types.md create mode 100644 docs/en/02_Developer_Guides/08_Performance/Profiling.md rename docs/en/02_Developer_Guides/09_Security/{02_Member.md => 00_Member.md} (99%) rename docs/en/02_Developer_Guides/09_Security/{03_Permission.md => 02_Permission.md} (100%) rename docs/en/02_Developer_Guides/09_Security/{00_Security.md => 04_Secure_Coding.md} (100%) delete mode 100644 docs/en/02_Developer_Guides/09_Security/How_To/Track_Member_Logins.md diff --git a/docs/en/02_Developer_Guides/07_Debugging/00_Environment_Types.md b/docs/en/02_Developer_Guides/07_Debugging/00_Environment_Types.md new file mode 100644 index 000000000..f34991746 --- /dev/null +++ b/docs/en/02_Developer_Guides/07_Debugging/00_Environment_Types.md @@ -0,0 +1,88 @@ +title: Environment Types +summary: Configure your SilverStripe environment to define how your web application behaves. + +# Environment Types + +SilverStripe knows three different environment types (or "modes"). Each of the modes gives you different tools +and behaviors. The environment is managed either through a [YML configuration file](../configuration) or in a +[environment configuration file](../../getting_started/environment_management). + +The definition of setting an environment type in a `mysite/_config/app.yml` looks like + + :::yml + Director: + environment_type: 'dev' + +The definition of setting an environment type in a `_ss_environment.php` file looks like + + :::php + define('SS_ENVIRONMENT_TYPE', 'dev'); + +The three environment types you can set are `dev`, `test` and `live`. + +### Dev + +When developing your websites, adding page types or installing modules you should run your site in `dev`. In this mode +you will see full error back traces and view the development tools without having to be logged in as an administrator +user. + +
+**dev mode should not be enabled long term on live sites for security reasons**. In dev mode by outputting back traces +of function calls a hacker can gain information about your environment (including passwords) so you should use dev mode +on a public server very carefully. +
+ +### Test Mode + +Test mode is designed for staging environments or other private collaboration sites before deploying a site live. + +In this mode error messages are hidden from the user and SilverStripe includes `[api:BasicAuth]` integration if you +want to password protect the site. You can enable that but adding this to your `mysite/_config/app.yml` file: + + :::yml + --- + Only: + environment: 'test' + --- + BasicAuth: + entire_site_protected: true + +### Live Mode + +All error messages are suppressed from the user and the application is in it's most *secure* state. + +
+Live sites should always run in live mode. You should not run production websites in dev mode. +
+ + +## Checking Environment Type + +You can check for the current environment type in [config files](../configuration) through the `environment` variant. + +**mysite/_config/app.yml** + --- + Only: + environment: 'live' + --- + MyClass: + myvar: live_value + --- + Only: + environment: 'test' + --- + MyClass: + myvar: test_value + +Checking for what environment you're running in can also be done in PHP. Your application code may disable or enable +certain functionality depending on the environment type. + + :::php + if(Director::isLive()) { + // is in live + } else if(Director::isTest()) { + // is in test mode + } else if(Director::isDev()) { + // is in dev mode + } + diff --git a/docs/en/02_Developer_Guides/07_Debugging/01_Error_Handling.md b/docs/en/02_Developer_Guides/07_Debugging/01_Error_Handling.md index c40650521..013b7c939 100644 --- a/docs/en/02_Developer_Guides/07_Debugging/01_Error_Handling.md +++ b/docs/en/02_Developer_Guides/07_Debugging/01_Error_Handling.md @@ -1,23 +1,29 @@ +title: Error Handling +summary: Trap, fire and report user exceptions, warnings and errors. + # Error Handling -SilverStripe has its own error trapping and handling support. +SilverStripe has its own error trapping and handling support. On development sites, SilverStripe will deal harshly with +any warnings or errors: a full call-stack is shown and execution stops for anything, giving you early warning of a +potential issue to handle. + +## Triggering the error handler. + +You should use [user_error](http://www.php.net/user_error) to throw errors where appropriate. + + :::php + if(true == false) { + user_error("I have an error problem", E_USER_ERROR); + } + + if(0 / 0) { + user_error("This time I am warning you", E_USER_WARNING); + } ## Error Levels -SilverStripe recognises two basic levels of error: - -* **WARNING:** Something strange has happened; the system has attempted to continue as best it can, but the developers -need to look at this. This category also include areas where a newer version of SilverStripe requires changes to the -site's customised code. - -* **FATAL ERROR:** There is no way that the system can attempt to continue with the particular operation; it would be -dangerous to report success to the user. - -You should use [user_error](http://www.php.net/user_error) to throw errors where appropriate. The more information we -have about what's not right in the system, the better we can make the application. - -* **E_USER_WARNING:** Err on the side of over-reporting warnings. The more warnings we have, the less chance there is -of a developer leaving a bug. Throwing warnings provides a means of ensuring that developers know whow +* **E_USER_WARNING:** Err on the side of over-reporting warnings. Throwing warnings provides a means of ensuring that +developers know: * Deprecated functions / usage patterns * Strange data formats * Things that will prevent an internal function from continuing. Throw a warning and return null. @@ -25,63 +31,43 @@ of a developer leaving a bug. Throwing warnings provides a means of ensuring th * **E_USER_ERROR:** Throwing one of these errors is going to take down the production site. So you should only throw E_USER_ERROR if it's going to be **dangerous** or **impossible** to continue with the request. -Note that currently, the SilverStripe core doesn't follow these standards perfectly. - -* Right now, **every** failed SQL statement throws a fatal error. Many 'select' queries could probably be reduced to -warnings. -* A lot of assertion checking in the system that throws errors when it should throw warnings. - -## Friendly Website Errors - -An HTTP 500 error will be sent when there has been a fatal error on either a test or production site. You can make this -friendlier - much like the 404 page, the error content can be edited within the CMS. - -* Create a page of type `[api:ErrorPage]` -* Set the error code to 500 -* Publish the page. - -**HOW IT WORKS: **The publication script for `[api:ErrorPage]` will write the full HTML content, including the template styling, -to assets/error-500.html. The fatal error handler looks for the presence of this file, and if it exists, dumps the -content. This means that database access isn't required to provide a 500 error page. ## Filesystem Logs +You can indicate a log file relative to the site root. - -### From SilverStripe - -You can indicate a log file relative to the site root. The named file will have a terse log sent to it, and the full log -(an encoded file containing backtraces and things) will go to a file of a similar name, but with the suffix ".full" -added. - -`mysite/_config.php`: +**mysite/_config.php** :::php - // log errors and warnings - SS_Log::add_writer(new SS_LogFileWriter('/my/logfile/path'), SS_Log::WARN, '<='); - // or just errors - SS_Log::add_writer(new SS_LogFileWriter('/my/logfile/path'), SS_Log::ERR); + if(!Director::isDev()) { + // log errors and warnings + SS_Log::add_writer(new SS_LogFileWriter('/my/logfile/path'), SS_Log::WARN, '<='); -### From PHP - -In addition to SilverStripe-integrated logging, it is adviseable to fall back to PHPs native logging functionality. A -script might terminate before it reaches the SilverStripe errorhandling, for example in the case of a fatal error. - -`mysite/_config.php`: - - :::php - ini_set("log_errors", "On"); - ini_set("error_log", "/my/logfile/path"); + // or just errors + SS_Log::add_writer(new SS_LogFileWriter('/my/logfile/path'), SS_Log::ERR); + } +
+In addition to SilverStripe-integrated logging, it is advisable to fall back to PHPs native logging functionality. A +script might terminate before it reaches the SilverStripe error handling, for example in the case of a fatal error. Make +sure `log_errors` and `error_log` in your PHP ini file are configured. +
## Email Logs You can send both fatal errors and warnings in your code to a specified email-address. -`mysite/_config.php`: +**mysite/_config.php** :::php - // log errors and warnings - SS_Log::add_writer(new SS_LogEmailWriter('admin@domain.com'), SS_Log::WARN, '<='); - // or just errors - SS_Log::add_writer(new SS_LogEmailWriter('admin@domain.com'), SS_Log::ERR); \ No newline at end of file + if(!Director::isDev()) { + // log errors and warnings + SS_Log::add_writer(new SS_LogEmailWriter('admin@domain.com'), SS_Log::WARN, '<='); + + // or just errors + SS_Log::add_writer(new SS_LogEmailWriter('admin@domain.com'), SS_Log::ERR); + } + +## API Documentation + +* [api:SS_Log] \ No newline at end of file diff --git a/docs/en/02_Developer_Guides/07_Debugging/index.md b/docs/en/02_Developer_Guides/07_Debugging/index.md index 724d9f997..e0f5f3719 100644 --- a/docs/en/02_Developer_Guides/07_Debugging/index.md +++ b/docs/en/02_Developer_Guides/07_Debugging/index.md @@ -2,152 +2,33 @@ summary: Learn how to identify errors in your application and best practice for # Debugging -## Environment Types +SilverStripe can be a large and complex framework to debug, but there are ways to make debugging less painful. In this +guide we show the basics on defining the correct [Environment Type](environment_type) for your application and other +built-in helpers for dealing with application errors. -Silverstripe knows three different environment-types (or "debug-levels"). Each of the levels gives you different tools -and functionality. "dev", "test" and "live". You can either configure the environment of the site in your -[config.yml file](/topics/configuration) or in your [environment configuration file](/topics/environment-management). +[CHILDREN] -The definition of setting an environment in your `config.yml` looks like +## Performance - :::yml - Director: - environment_type: 'dev' +See the [Profiling](../performance/profiling) documentation for more information on profiling SilverStripe to track down +bottle-necks and identify slow moving parts of your application chain. -### Dev Mode +## Debugging Utilities -When developing your websites, adding page types or installing modules you should run your site in devmode. In this mode -you will be able to view full error backtraces and view the development tools without logging in as admin. - -To set your site to dev mode set this in your `config.yml` file - - :::yml - Director: - environment_type: 'dev' - - -Please note **devmode should not be enabled long term on live sites for security reasons**. In devmode by outputting -backtraces of function calls a hacker can gain information about your environment (including passwords) so you should -use devmode on a public server very very carefully - - -### Test Mode - -Test mode is designed for staging environments or other private collaboration sites before deploying a site live. You do -not need to use test mode if you do not have a staging environment or a place for testing which is on a public server) - -In this mode error messages are hidden from the user and it includes `[api:BasicAuth]` integration if you want to password -protect the site. - -To set your site to test mode set this in your `config.yml` file - - :::yml - Director: - environment_type: 'test' - - -A common situation is to enable password protected site viewing on your test site only. -You can enable that but adding this to your `config.yml` file: - - :::yml - --- - Only: - environment: 'test' - --- - BasicAuth: - entire_site_protected: true - -### Live Mode - -Live sites should always run in live mode. Error messages are suppressed from the user but can be optionally configured -to email the developers. This enables near real time reporting of any fatal errors or warnings on the site and can help -find any bugs users run into. - -To set your site to live mode set this in your `config.yml` file - - :::yml - Director: - environment_type: 'live' - -### Checking Environment Types - -You can check for the current environment type in [config files](/topics/configuration) through the "environment" variant. -This is useful for example when you have various API keys on your site and separate ones for dev / live or for configuring -environment settings based on type . - - --- - Only: - environment: 'test' - --- - MyClass: - myvar: myval - -In addition, you can use the following methods in PHP code: +The [api:Debug] class contains a number of static utility methods for more advanced debugging. :::php - Director::isDev(); - Director::isTest(); - Director::isLive(); + Debug::show($myVariable); + // similar to print_r($myVariable) but shows it in a more useful format. -## Email Errors + Debug::message("Wow, that's great"); + // prints a short debugging message. - :::yml - Debug: - send_errors_to: 'your@email.com' + SS_Backtrace::backtrace(); + // prints a calls-stack -## Customizing Error-Output +## API Documentation -You can customize "friendly error messages" in test/live-mode by creating *assets/error-500.html*. - -## URL Variable Tools - -You can get lots of information on the current rendering context without writing any code or launching a debugger: Just -attach some [Debug Parameters](/reference/urlvariabletools) to your current URL to see the compiled template, or all performed -SQL-queries. - -## Debugging methods - -The Debug class contains a number of static methods - -* *Debug::show($myVariable)*: performs a kind of *print_r($myVariable)*, but shows it in a more useful format. -* *Debug::message("Wow, that's great")*: prints a short debugging message. -* *SS_Backtrace::backtrace()*: prints a calls-stack - -### Error handling - -On development sites, we deal harshly with any warnings or errors: a full call-stack is shown and execution stops. This -is basically so that we deal with them promptly, since most warnings are indication that **something** is broken. - -On live sites, all errors are emailed to the address specified in the `Debug.send_errors_to` config setting. - -### Debugging techniques - -Since we don't have a decent interactive debugger going, we use the following debugging techniques: - -* Putting *Debug::show()* and *Debug::message()* at key places in the code can help you know what's going on. -Sometimes, it helps to put this debugging information into the core modules, although, if possible, try and get what you -need by using [url querystring variables](/reference/urlvariabletools). - -* Calling *user_error("breakpoint", E_USER_ERROR)* will kill execution at that point and give you a call stack to see -where you came from. Alternatively, *SS_Backtrace::backtrace()* gives you similar information without killing -execution. - -* There are some special [url querystring variables](/reference/urlvariabletools) that can be helpful in seeing what's going on -with core modules, such as the templates. - -* You can also use *$Debug* with *ViewableData* in templates. - -#### Unit Testing - -A good way to avoid writing the same test stubs and var_dump() commands over and over again is to codify them as [unit -tests](testing-guide). This way you integrate the debugging process right into your quality control, and eventually in -the development effort itself as "test-driven development". - -#### Profiling - -Profiling is the best way to identify bottle necks and other slow moving parts of your application prime for optimization. SilverStripe -does not include any profiling tools out of the box, but we recommend the use of existing tools such as [XHProf](https://github.com/facebook/xhprof/) -and [XDebug](http://xdebug.org/). - -* [Profiling with XHProf](http://techportal.inviqa.com/2009/12/01/profiling-with-xhprof/) -* [Profiling PHP Applications With xdebug](http://devzone.zend.com/1139/profiling-php-applications-with-xdebug/) \ No newline at end of file +* [api:SS_Log] +* [api:SS_Backtrace] +* [api:Debug] \ No newline at end of file diff --git a/docs/en/02_Developer_Guides/08_Performance/Profiling.md b/docs/en/02_Developer_Guides/08_Performance/Profiling.md new file mode 100644 index 000000000..5deae0b16 --- /dev/null +++ b/docs/en/02_Developer_Guides/08_Performance/Profiling.md @@ -0,0 +1,8 @@ +#### Profiling + +Profiling is the best way to identify bottle necks and other slow moving parts of your application prime for optimization. SilverStripe +does not include any profiling tools out of the box, but we recommend the use of existing tools such as [XHProf](https://github.com/facebook/xhprof/) +and [XDebug](http://xdebug.org/). + +* [Profiling with XHProf](http://techportal.inviqa.com/2009/12/01/profiling-with-xhprof/) +* [Profiling PHP Applications With xdebug](http://devzone.zend.com/1139/profiling-php-applications-with-xdebug/) \ No newline at end of file diff --git a/docs/en/02_Developer_Guides/09_Security/02_Member.md b/docs/en/02_Developer_Guides/09_Security/00_Member.md similarity index 99% rename from docs/en/02_Developer_Guides/09_Security/02_Member.md rename to docs/en/02_Developer_Guides/09_Security/00_Member.md index ce081caf5..0d6f4905a 100644 --- a/docs/en/02_Developer_Guides/09_Security/02_Member.md +++ b/docs/en/02_Developer_Guides/09_Security/00_Member.md @@ -1,3 +1,5 @@ +title: Members + # Member ## Introduction @@ -128,4 +130,4 @@ things, you should add appropriate `[api:Permission::checkMember()]` calls to th ## API Documentation -`[api:Member]` \ No newline at end of file +`[api:Member]` diff --git a/docs/en/02_Developer_Guides/09_Security/03_Permission.md b/docs/en/02_Developer_Guides/09_Security/02_Permission.md similarity index 100% rename from docs/en/02_Developer_Guides/09_Security/03_Permission.md rename to docs/en/02_Developer_Guides/09_Security/02_Permission.md diff --git a/docs/en/02_Developer_Guides/09_Security/00_Security.md b/docs/en/02_Developer_Guides/09_Security/04_Secure_Coding.md similarity index 100% rename from docs/en/02_Developer_Guides/09_Security/00_Security.md rename to docs/en/02_Developer_Guides/09_Security/04_Secure_Coding.md diff --git a/docs/en/02_Developer_Guides/09_Security/How_To/Track_Member_Logins.md b/docs/en/02_Developer_Guides/09_Security/How_To/Track_Member_Logins.md deleted file mode 100644 index cf2eaa688..000000000 --- a/docs/en/02_Developer_Guides/09_Security/How_To/Track_Member_Logins.md +++ /dev/null @@ -1,52 +0,0 @@ -# Howto: Track Member Logins - -Sometimes its good to know how active your users are, -and when they last visited the site (and logged on). -A simple `LastVisited` property on the `Member` record -with some hooks into the login process can achieve this. -In addition, a `NumVisit` property will tell us how -often the member has visited. Or more specifically, -how often he has started a browser session, either through -explicitly logging in or by invoking the "remember me" functionality. - - :::php - 'Datetime', - 'NumVisit' => 'Int', - ); - - public function memberLoggedIn() { - $this->logVisit(); - } - - public function memberAutoLoggedIn() { - $this->logVisit(); - } - - public function updateCMSFields(FieldList $fields) { - $fields->addFieldsToTab('Root.Main', array( - ReadonlyField::create('LastVisited', 'Last visited'), - ReadonlyField::create('NumVisits', 'Number of visits') - )); - } - - protected function logVisit() { - if(!Security::database_is_ready()) return; - - DB::query(sprintf( - 'UPDATE "Member" SET "LastVisited" = %s, "NumVisit" = "NumVisit" + 1 WHERE "ID" = %d', - DB::getConn()->now(), - $this->owner->ID - )); - } - } - -Now you just need to apply this extension through your config: - - :::yml - Member: - extensions: - - MyMemberExtension - diff --git a/docs/en/02_Developer_Guides/09_Security/index.md b/docs/en/02_Developer_Guides/09_Security/index.md index 93bb814aa..452e3c6b7 100644 --- a/docs/en/02_Developer_Guides/09_Security/index.md +++ b/docs/en/02_Developer_Guides/09_Security/index.md @@ -1,7 +1,12 @@ summary: This guide covers user authentication, the permission system and how to secure your code against malicious behaviors -[CHILDREN] +# Security and User Authentication -## How-to +This guide covers using and extending the user authentication in SilverStripe, permissions, user groups and roles, and +how to secure your code against malicious behaviors of both your users and hackers. -[CHILDREN How_To] \ No newline at end of file +[CHILDREN Exclude=How_to] + +## How to's + +[CHILDREN Folder=How_To] \ No newline at end of file