| |   |
| 1 | = Exception Notifier Plugin for Rails |
| 2 | |
| 3 | The Exception Notifier plugin provides a mailer object and a default set of |
| 4 | templates for sending email notifications when errors occur in a Rails |
| 5 | application. The plugin is configurable, allowing programmers to specify: |
| 6 | |
| 7 | * the sender address of the email |
| 8 | * the recipient addresses |
| 9 | * the text used to prefix the subject line |
| 10 | |
| 11 | The email includes information about the current request, session, and |
| 12 | environment, and also gives a backtrace of the exception. |
| 13 | |
| 14 | == Usage |
| 15 | |
| 16 | First, include the ExceptionNotifiable mixin in whichever controller you want |
| 17 | to generate error emails (typically ApplicationController): |
| 18 | |
| 19 | class ApplicationController < ActionController::Base |
| 20 | include ExceptionNotifiable |
| 21 | ... |
| 22 | end |
| 23 | |
| 24 | Then, specify the email recipients in your environment: |
| 25 | |
| 26 | ExceptionNotifier.exception_recipients = %w(joe@schmoe.com bill@schmoe.com) |
| 27 | |
| 28 | And that's it! The defaults take care of the rest. |
| 29 | |
| 30 | == Configuration |
| 31 | |
| 32 | You can tweak other values to your liking, as well. In your environment file, |
| 33 | just set any or all of the following values: |
| 34 | |
| 35 | # defaults to exception.notifier@default.com |
| 36 | ExceptionNotifier.sender_address = |
| 37 | %("Application Error" <app.error@myapp.com>) |
| 38 | |
| 39 | # defaults to "[ERROR] " |
| 40 | ExceptionNotifier.email_prefix = "[APP] " |
| 41 | |
| 42 | Email notifications will only occur when the IP address is determined not to |
| 43 | be local. You can specify certain addresses to always be local so that you'll |
| 44 | get a detailed error instead of the generic error page. You do this in your |
| 45 | controller (or even per-controller): |
| 46 | |
| 47 | consider_local "64.72.18.143", "14.17.21.25" |
| 48 | |
| 49 | You can specify subnet masks as well, so that all matching addresses are |
| 50 | considered local: |
| 51 | |
| 52 | consider_local "64.72.18.143/24" |
| 53 | |
| 54 | The address "127.0.0.1" is always considered local. If you want to completely |
| 55 | reset the list of all addresses (for instance, if you wanted "127.0.0.1" to |
| 56 | NOT be considered local), you can simply do, somewhere in your controller: |
| 57 | |
| 58 | local_addresses.clear |
| 59 | |
| 60 | == Customization |
| 61 | |
| 62 | By default, the notification email includes four parts: request, session, |
| 63 | environment, and backtrace (in that order). You can customize how each of those |
| 64 | sections are rendered by placing a partial named for that part in your |
| 65 | app/views/exception_notifier directory (e.g., _session.rhtml). Each partial has |
| 66 | access to the following variables: |
| 67 | |
| 68 | * @controller: the controller that caused the error |
| 69 | * @request: the current request object |
| 70 | * @exception: the exception that was raised |
| 71 | * @host: the name of the host that made the request |
| 72 | * @backtrace: a sanitized version of the exception's backtrace |
| 73 | * @rails_root: a sanitized version of RAILS_ROOT |
| 74 | * @data: a hash of optional data values that were passed to the notifier |
| 75 | * @sections: the array of sections to include in the email |
| 76 | |
| 77 | You can reorder the sections, or exclude sections completely, by altering the |
| 78 | ExceptionNotifier.sections variable. You can even add new sections that |
| 79 | describe application-specific data--just add the section's name to the list |
| 80 | (whereever you'd like), and define the corresponding partial. Then, if your |
| 81 | new section requires information that isn't available by default, make sure |
| 82 | it is made available to the email using the exception_data macro: |
| 83 | |
| 84 | class ApplicationController < ActionController::Base |
| 85 | ... |
| 86 | protected |
| 87 | exception_data :additional_data |
| 88 | |
| 89 | def additional_data |
| 90 | { :document => @document, |
| 91 | :person => @person } |
| 92 | end |
| 93 | ... |
| 94 | end |
| 95 | |
| 96 | In the above case, @document and @person would be made available to the email |
| 97 | renderer, allowing your new section(s) to access and display them. See the |
| 98 | existing sections defined by the plugin for examples of how to write your own. |
| 99 | |
| 100 | == Advanced Customization |
| 101 | |
| 102 | By default, the email notifier will only notify on critical errors. For |
| 103 | ActiveRecord::RecordNotFound and ActionController::UnknownAction, it will |
| 104 | simply render the contents of your public/404.html file. Other exceptions |
| 105 | will render public/500.html and will send the email notification. If you want |
| 106 | to use different rules for the notification, you will need to implement your |
| 107 | own rescue_action_in_public method. You can look at the default implementation |
| 108 | in ExceptionNotifiable for an example of how to go about that. |
| 109 | |
| 110 | |
| 111 | Copyright (c) 2005 Jamis Buck, released under the MIT license |
| toggle raw diff |
--- /dev/null
+++ b/vendor/plugins/exception_notification/README
@@ -0,0 +1,111 @@
+= Exception Notifier Plugin for Rails
+
+The Exception Notifier plugin provides a mailer object and a default set of
+templates for sending email notifications when errors occur in a Rails
+application. The plugin is configurable, allowing programmers to specify:
+
+* the sender address of the email
+* the recipient addresses
+* the text used to prefix the subject line
+
+The email includes information about the current request, session, and
+environment, and also gives a backtrace of the exception.
+
+== Usage
+
+First, include the ExceptionNotifiable mixin in whichever controller you want
+to generate error emails (typically ApplicationController):
+
+ class ApplicationController < ActionController::Base
+ include ExceptionNotifiable
+ ...
+ end
+
+Then, specify the email recipients in your environment:
+
+ ExceptionNotifier.exception_recipients = %w(joe@schmoe.com bill@schmoe.com)
+
+And that's it! The defaults take care of the rest.
+
+== Configuration
+
+You can tweak other values to your liking, as well. In your environment file,
+just set any or all of the following values:
+
+ # defaults to exception.notifier@default.com
+ ExceptionNotifier.sender_address =
+ %("Application Error" <app.error@myapp.com>)
+
+ # defaults to "[ERROR] "
+ ExceptionNotifier.email_prefix = "[APP] "
+
+Email notifications will only occur when the IP address is determined not to
+be local. You can specify certain addresses to always be local so that you'll
+get a detailed error instead of the generic error page. You do this in your
+controller (or even per-controller):
+
+ consider_local "64.72.18.143", "14.17.21.25"
+
+You can specify subnet masks as well, so that all matching addresses are
+considered local:
+
+ consider_local "64.72.18.143/24"
+
+The address "127.0.0.1" is always considered local. If you want to completely
+reset the list of all addresses (for instance, if you wanted "127.0.0.1" to
+NOT be considered local), you can simply do, somewhere in your controller:
+
+ local_addresses.clear
+
+== Customization
+
+By default, the notification email includes four parts: request, session,
+environment, and backtrace (in that order). You can customize how each of those
+sections are rendered by placing a partial named for that part in your
+app/views/exception_notifier directory (e.g., _session.rhtml). Each partial has
+access to the following variables:
+
+* @controller: the controller that caused the error
+* @request: the current request object
+* @exception: the exception that was raised
+* @host: the name of the host that made the request
+* @backtrace: a sanitized version of the exception's backtrace
+* @rails_root: a sanitized version of RAILS_ROOT
+* @data: a hash of optional data values that were passed to the notifier
+* @sections: the array of sections to include in the email
+
+You can reorder the sections, or exclude sections completely, by altering the
+ExceptionNotifier.sections variable. You can even add new sections that
+describe application-specific data--just add the section's name to the list
+(whereever you'd like), and define the corresponding partial. Then, if your
+new section requires information that isn't available by default, make sure
+it is made available to the email using the exception_data macro:
+
+ class ApplicationController < ActionController::Base
+ ...
+ protected
+ exception_data :additional_data
+
+ def additional_data
+ { :document => @document,
+ :person => @person }
+ end
+ ...
+ end
+
+In the above case, @document and @person would be made available to the email
+renderer, allowing your new section(s) to access and display them. See the
+existing sections defined by the plugin for examples of how to write your own.
+
+== Advanced Customization
+
+By default, the email notifier will only notify on critical errors. For
+ActiveRecord::RecordNotFound and ActionController::UnknownAction, it will
+simply render the contents of your public/404.html file. Other exceptions
+will render public/500.html and will send the email notification. If you want
+to use different rules for the notification, you will need to implement your
+own rescue_action_in_public method. You can look at the default implementation
+in ExceptionNotifiable for an example of how to go about that.
+
+
+Copyright (c) 2005 Jamis Buck, released under the MIT license
\ No newline at end of file |
| |   |
| 1 | require 'ipaddr' |
| 2 | |
| 3 | # Copyright (c) 2005 Jamis Buck |
| 4 | # |
| 5 | # Permission is hereby granted, free of charge, to any person obtaining |
| 6 | # a copy of this software and associated documentation files (the |
| 7 | # "Software"), to deal in the Software without restriction, including |
| 8 | # without limitation the rights to use, copy, modify, merge, publish, |
| 9 | # distribute, sublicense, and/or sell copies of the Software, and to |
| 10 | # permit persons to whom the Software is furnished to do so, subject to |
| 11 | # the following conditions: |
| 12 | # |
| 13 | # The above copyright notice and this permission notice shall be |
| 14 | # included in all copies or substantial portions of the Software. |
| 15 | # |
| 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 18 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 19 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
| 20 | # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
| 21 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| 22 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 23 | module ExceptionNotifiable |
| 24 | def self.included(target) |
| 25 | target.extend(ClassMethods) |
| 26 | end |
| 27 | |
| 28 | module ClassMethods |
| 29 | def consider_local(*args) |
| 30 | local_addresses.concat(args.flatten.map { |a| IPAddr.new(a) }) |
| 31 | end |
| 32 | |
| 33 | def local_addresses |
| 34 | addresses = read_inheritable_attribute(:local_addresses) |
| 35 | unless addresses |
| 36 | addresses = [IPAddr.new("127.0.0.1")] |
| 37 | write_inheritable_attribute(:local_addresses, addresses) |
| 38 | end |
| 39 | addresses |
| 40 | end |
| 41 | |
| 42 | def exception_data(deliverer=self) |
| 43 | if deliverer == self |
| 44 | read_inheritable_attribute(:exception_data) |
| 45 | else |
| 46 | write_inheritable_attribute(:exception_data, deliverer) |
| 47 | end |
| 48 | end |
| 49 | |
| 50 | def exceptions_to_treat_as_404 |
| 51 | exceptions = [ActiveRecord::RecordNotFound, |
| 52 | ActionController::UnknownController, |
| 53 | ActionController::UnknownAction] |
| 54 | exceptions << ActionController::RoutingError if ActionController.const_defined?(:RoutingError) |
| 55 | exceptions |
| 56 | end |
| 57 | end |
| 58 | |
| 59 | private |
| 60 | |
| 61 | def local_request? |
| 62 | remote = IPAddr.new(request.remote_ip) |
| 63 | !self.class.local_addresses.detect { |addr| addr.include?(remote) }.nil? |
| 64 | end |
| 65 | |
| 66 | def render_404 |
| 67 | respond_to do |type| |
| 68 | type.html { render :file => "#{RAILS_ROOT}/public/404.html", :status => "404 Not Found" } |
| 69 | type.all { render :nothing => true, :status => "404 Not Found" } |
| 70 | end |
| 71 | end |
| 72 | |
| 73 | def render_500 |
| 74 | respond_to do |type| |
| 75 | type.html { render :file => "#{RAILS_ROOT}/public/500.html", :status => "500 Error" } |
| 76 | type.all { render :nothing => true, :status => "500 Error" } |
| 77 | end |
| 78 | end |
| 79 | |
| 80 | def rescue_action_in_public(exception) |
| 81 | case exception |
| 82 | when *self.class.exceptions_to_treat_as_404 |
| 83 | render_404 |
| 84 | |
| 85 | else |
| 86 | render_500 |
| 87 | |
| 88 | deliverer = self.class.exception_data |
| 89 | data = case deliverer |
| 90 | when nil then {} |
| 91 | when Symbol then send(deliverer) |
| 92 | when Proc then deliverer.call(self) |
| 93 | end |
| 94 | |
| 95 | ExceptionNotifier.deliver_exception_notification(exception, self, |
| 96 | request, data) |
| 97 | end |
| 98 | end |
| 99 | end |
| toggle raw diff |
--- /dev/null
+++ b/vendor/plugins/exception_notification/lib/exception_notifiable.rb
@@ -0,0 +1,99 @@
+require 'ipaddr'
+
+# Copyright (c) 2005 Jamis Buck
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+module ExceptionNotifiable
+ def self.included(target)
+ target.extend(ClassMethods)
+ end
+
+ module ClassMethods
+ def consider_local(*args)
+ local_addresses.concat(args.flatten.map { |a| IPAddr.new(a) })
+ end
+
+ def local_addresses
+ addresses = read_inheritable_attribute(:local_addresses)
+ unless addresses
+ addresses = [IPAddr.new("127.0.0.1")]
+ write_inheritable_attribute(:local_addresses, addresses)
+ end
+ addresses
+ end
+
+ def exception_data(deliverer=self)
+ if deliverer == self
+ read_inheritable_attribute(:exception_data)
+ else
+ write_inheritable_attribute(:exception_data, deliverer)
+ end
+ end
+
+ def exceptions_to_treat_as_404
+ exceptions = [ActiveRecord::RecordNotFound,
+ ActionController::UnknownController,
+ ActionController::UnknownAction]
+ exceptions << ActionController::RoutingError if ActionController.const_defined?(:RoutingError)
+ exceptions
+ end
+ end
+
+ private
+
+ def local_request?
+ remote = IPAddr.new(request.remote_ip)
+ !self.class.local_addresses.detect { |addr| addr.include?(remote) }.nil?
+ end
+
+ def render_404
+ respond_to do |type|
+ type.html { render :file => "#{RAILS_ROOT}/public/404.html", :status => "404 Not Found" }
+ type.all { render :nothing => true, :status => "404 Not Found" }
+ end
+ end
+
+ def render_500
+ respond_to do |type|
+ type.html { render :file => "#{RAILS_ROOT}/public/500.html", :status => "500 Error" }
+ type.all { render :nothing => true, :status => "500 Error" }
+ end
+ end
+
+ def rescue_action_in_public(exception)
+ case exception
+ when *self.class.exceptions_to_treat_as_404
+ render_404
+
+ else
+ render_500
+
+ deliverer = self.class.exception_data
+ data = case deliverer
+ when nil then {}
+ when Symbol then send(deliverer)
+ when Proc then deliverer.call(self)
+ end
+
+ ExceptionNotifier.deliver_exception_notification(exception, self,
+ request, data)
+ end
+ end
+end |
| |   |
| 1 | require 'pathname' |
| 2 | |
| 3 | # Copyright (c) 2005 Jamis Buck |
| 4 | # |
| 5 | # Permission is hereby granted, free of charge, to any person obtaining |
| 6 | # a copy of this software and associated documentation files (the |
| 7 | # "Software"), to deal in the Software without restriction, including |
| 8 | # without limitation the rights to use, copy, modify, merge, publish, |
| 9 | # distribute, sublicense, and/or sell copies of the Software, and to |
| 10 | # permit persons to whom the Software is furnished to do so, subject to |
| 11 | # the following conditions: |
| 12 | # |
| 13 | # The above copyright notice and this permission notice shall be |
| 14 | # included in all copies or substantial portions of the Software. |
| 15 | # |
| 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 18 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 19 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
| 20 | # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
| 21 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| 22 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 23 | class ExceptionNotifier < ActionMailer::Base |
| 24 | @@sender_address = %("Exception Notifier" <exception.notifier@default.com>) |
| 25 | cattr_accessor :sender_address |
| 26 | |
| 27 | @@exception_recipients = [] |
| 28 | cattr_accessor :exception_recipients |
| 29 | |
| 30 | @@email_prefix = "[ERROR] " |
| 31 | cattr_accessor :email_prefix |
| 32 | |
| 33 | @@sections = %w(request session environment backtrace) |
| 34 | cattr_accessor :sections |
| 35 | |
| 36 | def self.reloadable?; false; end |
| 37 | |
| 38 | def exception_notification(exception, controller, request, data={}) |
| 39 | content_type "text/plain" |
| 40 | |
| 41 | subject "#{email_prefix}#{controller.controller_name}##{controller.action_name} (#{exception.class}) #{exception.message.inspect}" |
| 42 | |
| 43 | recipients exception_recipients |
| 44 | from sender_address |
| 45 | |
| 46 | body data.merge({ :controller => controller, :request => request, |
| 47 | :exception => exception, :host => (request.env["HTTP_X_FORWARDED_HOST"] || request.env["HTTP_HOST"]), |
| 48 | :backtrace => sanitize_backtrace(exception.backtrace), |
| 49 | :rails_root => rails_root, :data => data, |
| 50 | :sections => sections }) |
| 51 | end |
| 52 | |
| 53 | def template_root |
| 54 | "#{File.dirname(__FILE__)}/../views" |
| 55 | end |
| 56 | |
| 57 | private |
| 58 | |
| 59 | def sanitize_backtrace(trace) |
| 60 | re = Regexp.new(/^#{Regexp.escape(rails_root)}/) |
| 61 | trace.map { |line| Pathname.new(line.gsub(re, "[RAILS_ROOT]")).cleanpath.to_s } |
| 62 | end |
| 63 | |
| 64 | def rails_root |
| 65 | @rails_root ||= Pathname.new(RAILS_ROOT).cleanpath.to_s |
| 66 | end |
| 67 | |
| 68 | end |
| toggle raw diff |
--- /dev/null
+++ b/vendor/plugins/exception_notification/lib/exception_notifier.rb
@@ -0,0 +1,68 @@
+require 'pathname'
+
+# Copyright (c) 2005 Jamis Buck
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+class ExceptionNotifier < ActionMailer::Base
+ @@sender_address = %("Exception Notifier" <exception.notifier@default.com>)
+ cattr_accessor :sender_address
+
+ @@exception_recipients = []
+ cattr_accessor :exception_recipients
+
+ @@email_prefix = "[ERROR] "
+ cattr_accessor :email_prefix
+
+ @@sections = %w(request session environment backtrace)
+ cattr_accessor :sections
+
+ def self.reloadable?; false; end
+
+ def exception_notification(exception, controller, request, data={})
+ content_type "text/plain"
+
+ subject "#{email_prefix}#{controller.controller_name}##{controller.action_name} (#{exception.class}) #{exception.message.inspect}"
+
+ recipients exception_recipients
+ from sender_address
+
+ body data.merge({ :controller => controller, :request => request,
+ :exception => exception, :host => (request.env["HTTP_X_FORWARDED_HOST"] || request.env["HTTP_HOST"]),
+ :backtrace => sanitize_backtrace(exception.backtrace),
+ :rails_root => rails_root, :data => data,
+ :sections => sections })
+ end
+
+ def template_root
+ "#{File.dirname(__FILE__)}/../views"
+ end
+
+ private
+
+ def sanitize_backtrace(trace)
+ re = Regexp.new(/^#{Regexp.escape(rails_root)}/)
+ trace.map { |line| Pathname.new(line.gsub(re, "[RAILS_ROOT]")).cleanpath.to_s }
+ end
+
+ def rails_root
+ @rails_root ||= Pathname.new(RAILS_ROOT).cleanpath.to_s
+ end
+
+end |
| |   |
| 1 | require 'pp' |
| 2 | |
| 3 | # Copyright (c) 2005 Jamis Buck |
| 4 | # |
| 5 | # Permission is hereby granted, free of charge, to any person obtaining |
| 6 | # a copy of this software and associated documentation files (the |
| 7 | # "Software"), to deal in the Software without restriction, including |
| 8 | # without limitation the rights to use, copy, modify, merge, publish, |
| 9 | # distribute, sublicense, and/or sell copies of the Software, and to |
| 10 | # permit persons to whom the Software is furnished to do so, subject to |
| 11 | # the following conditions: |
| 12 | # |
| 13 | # The above copyright notice and this permission notice shall be |
| 14 | # included in all copies or substantial portions of the Software. |
| 15 | # |
| 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 18 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 19 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
| 20 | # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
| 21 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| 22 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 23 | module ExceptionNotifierHelper |
| 24 | VIEW_PATH = "views/exception_notifier" |
| 25 | APP_PATH = "#{RAILS_ROOT}/app/#{VIEW_PATH}" |
| 26 | PARAM_FILTER_REPLACEMENT = "[FILTERED]" |
| 27 | |
| 28 | def render_section(section) |
| 29 | RAILS_DEFAULT_LOGGER.info("rendering section #{section.inspect}") |
| 30 | summary = render_overridable(section).strip |
| 31 | unless summary.blank? |
| 32 | title = render_overridable(:title, :locals => { :title => section }).strip |
| 33 | "#{title}\n\n#{summary.gsub(/^/, " ")}\n\n" |
| 34 | end |
| 35 | end |
| 36 | |
| 37 | def render_overridable(partial, options={}) |
| 38 | if File.exist?(path = "#{APP_PATH}/_#{partial}.rhtml") |
| 39 | render(options.merge(:file => path, :use_full_path => false)) |
| 40 | elsif File.exist?(path = "#{File.dirname(__FILE__)}/../#{VIEW_PATH}/_#{partial}.rhtml") |
| 41 | render(options.merge(:file => path, :use_full_path => false)) |
| 42 | else |
| 43 | "" |
| 44 | end |
| 45 | end |
| 46 | |
| 47 | def inspect_model_object(model, locals={}) |
| 48 | render_overridable(:inspect_model, |
| 49 | :locals => { :inspect_model => model, |
| 50 | :show_instance_variables => true, |
| 51 | :show_attributes => true }.merge(locals)) |
| 52 | end |
| 53 | |
| 54 | def inspect_value(value) |
| 55 | len = 512 |
| 56 | result = object_to_yaml(value).gsub(/\n/, "\n ").strip |
| 57 | result = result[0,len] + "... (#{result.length-len} bytes more)" if result.length > len+20 |
| 58 | result |
| 59 | end |
| 60 | |
| 61 | def object_to_yaml(object) |
| 62 | object.to_yaml.sub(/^---\s*/m, "") |
| 63 | end |
| 64 | |
| 65 | def exclude_raw_post_parameters? |
| 66 | @controller && @controller.respond_to?(:filter_parameters) |
| 67 | end |
| 68 | |
| 69 | def filter_sensitive_post_data_parameters(parameters) |
| 70 | exclude_raw_post_parameters? ? @controller.filter_parameters(parameters) : parameters |
| 71 | end |
| 72 | |
| 73 | def filter_sensitive_post_data_from_env(env_key, env_value) |
| 74 | return env_value unless exclude_raw_post_parameters? |
| 75 | return PARAM_FILTER_REPLACEMENT if (env_key =~ /RAW_POST_DATA/i) |
| 76 | return @controller.filter_parameters({env_key => env_value}).values[0] |
| 77 | end |
| 78 | end |
| toggle raw diff |
--- /dev/null
+++ b/vendor/plugins/exception_notification/lib/exception_notifier_helper.rb
@@ -0,0 +1,78 @@
+require 'pp'
+
+# Copyright (c) 2005 Jamis Buck
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+module ExceptionNotifierHelper
+ VIEW_PATH = "views/exception_notifier"
+ APP_PATH = "#{RAILS_ROOT}/app/#{VIEW_PATH}"
+ PARAM_FILTER_REPLACEMENT = "[FILTERED]"
+
+ def render_section(section)
+ RAILS_DEFAULT_LOGGER.info("rendering section #{section.inspect}")
+ summary = render_overridable(section).strip
+ unless summary.blank?
+ title = render_overridable(:title, :locals => { :title => section }).strip
+ "#{title}\n\n#{summary.gsub(/^/, " ")}\n\n"
+ end
+ end
+
+ def render_overridable(partial, options={})
+ if File.exist?(path = "#{APP_PATH}/_#{partial}.rhtml")
+ render(options.merge(:file => path, :use_full_path => false))
+ elsif File.exist?(path = "#{File.dirname(__FILE__)}/../#{VIEW_PATH}/_#{partial}.rhtml")
+ render(options.merge(:file => path, :use_full_path => false))
+ else
+ ""
+ end
+ end
+
+ def inspect_model_object(model, locals={})
+ render_overridable(:inspect_model,
+ :locals => { :inspect_model => model,
+ :show_instance_variables => true,
+ :show_attributes => true }.merge(locals))
+ end
+
+ def inspect_value(value)
+ len = 512
+ result = object_to_yaml(value).gsub(/\n/, "\n ").strip
+ result = result[0,len] + "... (#{result.length-len} bytes more)" if result.length > len+20
+ result
+ end
+
+ def object_to_yaml(object)
+ object.to_yaml.sub(/^---\s*/m, "")
+ end
+
+ def exclude_raw_post_parameters?
+ @controller && @controller.respond_to?(:filter_parameters)
+ end
+
+ def filter_sensitive_post_data_parameters(parameters)
+ exclude_raw_post_parameters? ? @controller.filter_parameters(parameters) : parameters
+ end
+
+ def filter_sensitive_post_data_from_env(env_key, env_value)
+ return env_value unless exclude_raw_post_parameters?
+ return PARAM_FILTER_REPLACEMENT if (env_key =~ /RAW_POST_DATA/i)
+ return @controller.filter_parameters({env_key => env_value}).values[0]
+ end
+end |
| |   |
| 1 | require 'test_helper' |
| 2 | require 'exception_notifier_helper' |
| 3 | |
| 4 | class ExceptionNotifierHelperTest < Test::Unit::TestCase |
| 5 | |
| 6 | class ExceptionNotifierHelperIncludeTarget |
| 7 | include ExceptionNotifierHelper |
| 8 | end |
| 9 | |
| 10 | def setup |
| 11 | @helper = ExceptionNotifierHelperIncludeTarget.new |
| 12 | end |
| 13 | |
| 14 | # No controller |
| 15 | |
| 16 | def test_should_not_exclude_raw_post_parameters_if_no_controller |
| 17 | assert !@helper.exclude_raw_post_parameters? |
| 18 | end |
| 19 | |
| 20 | # Controller, no filtering |
| 21 | |
| 22 | class ControllerWithoutFilterParameters; end |
| 23 | |
| 24 | def test_should_not_filter_env_values_for_raw_post_data_keys_if_controller_can_not_filter_parameters |
| 25 | stub_controller(ControllerWithoutFilterParameters.new) |
| 26 | assert @helper.filter_sensitive_post_data_from_env("RAW_POST_DATA", "secret").include?("secret") |
| 27 | end |
| 28 | def test_should_not_exclude_raw_post_parameters_if_controller_can_not_filter_parameters |
| 29 | stub_controller(ControllerWithoutFilterParameters.new) |
| 30 | assert !@helper.exclude_raw_post_parameters? |
| 31 | end |
| 32 | def test_should_return_params_if_controller_can_not_filter_parameters |
| 33 | stub_controller(ControllerWithoutFilterParameters.new) |
| 34 | assert_equal :params, @helper.filter_sensitive_post_data_parameters(:params) |
| 35 | end |
| 36 | |
| 37 | # Controller with filtering |
| 38 | |
| 39 | class ControllerWithFilterParameters |
| 40 | def filter_parameters(params); :filtered end |
| 41 | end |
| 42 | |
| 43 | def test_should_filter_env_values_for_raw_post_data_keys_if_controller_can_filter_parameters |
| 44 | stub_controller(ControllerWithFilterParameters.new) |
| 45 | assert !@helper.filter_sensitive_post_data_from_env("RAW_POST_DATA", "secret").include?("secret") |
| 46 | assert @helper.filter_sensitive_post_data_from_env("SOME_OTHER_KEY", "secret").include?("secret") |
| 47 | end |
| 48 | def test_should_exclude_raw_post_parameters_if_controller_can_filter_parameters |
| 49 | stub_controller(ControllerWithFilterParameters.new) |
| 50 | assert @helper.exclude_raw_post_parameters? |
| 51 | end |
| 52 | def test_should_delegate_param_filtering_to_controller_if_controller_can_filter_parameters |
| 53 | stub_controller(ControllerWithFilterParameters.new) |
| 54 | assert_equal :filtered, @helper.filter_sensitive_post_data_parameters(:params) |
| 55 | end |
| 56 | |
| 57 | private |
| 58 | def stub_controller(controller) |
| 59 | @helper.instance_variable_set(:@controller, controller) |
| 60 | end |
| 61 | end |
| toggle raw diff |
--- /dev/null
+++ b/vendor/plugins/exception_notification/test/exception_notifier_helper_test.rb
@@ -0,0 +1,61 @@
+require 'test_helper'
+require 'exception_notifier_helper'
+
+class ExceptionNotifierHelperTest < Test::Unit::TestCase
+
+ class ExceptionNotifierHelperIncludeTarget
+ include ExceptionNotifierHelper
+ end
+
+ def setup
+ @helper = ExceptionNotifierHelperIncludeTarget.new
+ end
+
+ # No controller
+
+ def test_should_not_exclude_raw_post_parameters_if_no_controller
+ assert !@helper.exclude_raw_post_parameters?
+ end
+
+ # Controller, no filtering
+
+ class ControllerWithoutFilterParameters; end
+
+ def test_should_not_filter_env_values_for_raw_post_data_keys_if_controller_can_not_filter_parameters
+ stub_controller(ControllerWithoutFilterParameters.new)
+ assert @helper.filter_sensitive_post_data_from_env("RAW_POST_DATA", "secret").include?("secret")
+ end
+ def test_should_not_exclude_raw_post_parameters_if_controller_can_not_filter_parameters
+ stub_controller(ControllerWithoutFilterParameters.new)
+ assert !@helper.exclude_raw_post_parameters?
+ end
+ def test_should_return_params_if_controller_can_not_filter_parameters
+ stub_controller(ControllerWithoutFilterParameters.new)
+ assert_equal :params, @helper.filter_sensitive_post_data_parameters(:params)
+ end
+
+ # Controller with filtering
+
+ class ControllerWithFilterParameters
+ def filter_parameters(params); :filtered end
+ end
+
+ def test_should_filter_env_values_for_raw_post_data_keys_if_controller_can_filter_parameters
+ stub_controller(ControllerWithFilterParameters.new)
+ assert !@helper.filter_sensitive_post_data_from_env("RAW_POST_DATA", "secret").include?("secret")
+ assert @helper.filter_sensitive_post_data_from_env("SOME_OTHER_KEY", "secret").include?("secret")
+ end
+ def test_should_exclude_raw_post_parameters_if_controller_can_filter_parameters
+ stub_controller(ControllerWithFilterParameters.new)
+ assert @helper.exclude_raw_post_parameters?
+ end
+ def test_should_delegate_param_filtering_to_controller_if_controller_can_filter_parameters
+ stub_controller(ControllerWithFilterParameters.new)
+ assert_equal :filtered, @helper.filter_sensitive_post_data_parameters(:params)
+ end
+
+ private
+ def stub_controller(controller)
+ @helper.instance_variable_set(:@controller, controller)
+ end
+end
\ No newline at end of file |