tripwire_notifier 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Jeffrey Chupp and Jeremy Weiskotten
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,76 @@
1
+ = Tripwire::Notifier
2
+
3
+ Stop hurting your users!
4
+
5
+ Tripwire captures validation errors from your Ruby on Rails application to help you identify and fix user experience issues. The Tripwire::Notifier gem makes it easy to hook up your app to the Tripwire web service.
6
+
7
+ If you haven't already signed up for a Tripwire account and set up your project, visit http://tripwireapp.com to do so now.
8
+
9
+
10
+ = Basic Usage
11
+
12
+ * Install the gem:
13
+
14
+ gem install tripwire_notifier
15
+
16
+ * Modify your config/environment.rb file to make your app aware of the tripwire_notifier gem by adding the following line to config/environment.rb:
17
+
18
+ config.gem 'tripwire_notifier'
19
+
20
+ * (Optionally) unpack the gem into your Rails app:
21
+
22
+ rake gems:unpack
23
+
24
+ * In your Rails app, create config/initializers/tripwire_notifier.rb and add the following line with the API key for your Tripwire project:
25
+
26
+ Tripwire::Notifier.api_key = "<YOUR API KEY>"
27
+
28
+ Your validation failures will now be tracked on your create and update actions in production mode. Feel free to start script/server in production mode and trigger some of your own.
29
+
30
+
31
+ = More Advanced Usage
32
+
33
+ === Tracking custom actions
34
+
35
+ Tripwire::Notifier assumes your app is RESTful, so it only monitors the create and update actions by default. If you're creating or updating records in non-RESTful actions, you can use an after_filter to make sure any validation failures in those actions are caught as well:
36
+
37
+ after_filter :log_validation_failures_to_tripwire, :only => [:create, :update, :my_custom_action]
38
+
39
+ === Filtering params
40
+
41
+ Tripwire::Notifier tracks the parameters submitted in actions that cause validation errors. Because your app may handle sensitive data, like passwords, credit card numbers, and nuclear launch codes, Tripwire::Notifier respects the built-in Rails parameter filtering that you enable with filter_parameter_logging in your ApplicationController. For example:
42
+
43
+ # Scrub sensitive parameters from your log
44
+ filter_parameter_logging :password, :secret
45
+
46
+ Per the Rails standard, those params will show up as "[FILTERED]" in the data submitted to Tripwire.
47
+
48
+ === Running in other environments
49
+
50
+ Tripwire::Notifier is only enabled in the production environment by default. If you want to enable it in additional environments, such as staging, you'll need to add the following line to your initializer file:
51
+
52
+ Tripwire::Notifier.monitored_environments << 'staging'
53
+
54
+
55
+ We plan to streamline the setup process in the future and provide additional detailed configuration options and documentation. Please feel free to contact us with feedback, questions, or suggestions about this process. Thanks!
56
+
57
+ == Contact information
58
+
59
+ * Twitter: @tripwireapp
60
+ * Email: jeremy@tripwireapp.com, jeff@tripwireapp.com
61
+
62
+
63
+ == Note on Patches/Pull Requests
64
+
65
+ * Fork the project.
66
+ * Make your feature addition or bug fix.
67
+ * Add tests for it. This is important so I don't break it in a
68
+ future version unintentionally.
69
+ * Commit, do not mess with rakefile, version, or history.
70
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
71
+ * Send me a pull request. Bonus points for topic branches.
72
+
73
+ == Copyright
74
+
75
+ Copyright (c) 2010 Jeffrey Chupp and Jeremy Weiskotten. See LICENSE for details.
76
+
data/Rakefile ADDED
@@ -0,0 +1,53 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "tripwire_notifier"
8
+ gem.summary = %Q{Tripwire (http://tripwireapp.com) captures validation errors from your Ruby on Rails application.}
9
+ gem.description = %Q{Tripwire captures validation errors from your Ruby on Rails application to help you identify and fix user experience issues. The Tripwire::Notifier gem makes it easy to hook up your app to the Tripwire web service.}
10
+ gem.email = ""
11
+ gem.homepage = "http://github.com/jeremyw/tripwire_notifier"
12
+ gem.authors = ["Jeffrey Chupp", "Jeremy Weiskotten"]
13
+ gem.add_development_dependency "shoulda", ">= 0"
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
19
+ end
20
+
21
+ require 'rake/testtask'
22
+ Rake::TestTask.new(:test) do |test|
23
+ test.libs << 'lib' << 'test'
24
+ test.pattern = 'test/**/test_*.rb'
25
+ test.verbose = true
26
+ end
27
+
28
+ begin
29
+ require 'rcov/rcovtask'
30
+ Rcov::RcovTask.new do |test|
31
+ test.libs << 'test'
32
+ test.pattern = 'test/**/test_*.rb'
33
+ test.verbose = true
34
+ end
35
+ rescue LoadError
36
+ task :rcov do
37
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
38
+ end
39
+ end
40
+
41
+ task :test => :check_dependencies
42
+
43
+ task :default => :test
44
+
45
+ require 'rake/rdoctask'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "tripwire_notifier #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.1
@@ -0,0 +1,107 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ require 'timeout'
4
+
5
+ # TODO: namespace the methods apart from log_validation_failures_to_tripwire ?
6
+ module Tripwire
7
+ module Notifier
8
+ API_VERSION = "alpha 1"
9
+ API_URL = 'http://api.tripwireapp.com/'
10
+
11
+ class << self
12
+ attr_accessor :api_key, :monitored_environments, :timeout_in_seconds
13
+ end
14
+
15
+ def self.included(base)
16
+ # set our defaults
17
+ self.monitored_environments = ['production']
18
+ self.timeout_in_seconds = 5
19
+
20
+ base.after_filter :log_validation_failures_to_tripwire, :only => [:create, :update]
21
+ end
22
+
23
+ def log_validation_failures_to_tripwire
24
+ if should_log_failures_to_tripwire? && records_with_errors.present?
25
+ begin
26
+ timeout(Tripwire::Notifier.timeout_in_seconds) do
27
+ Net::HTTP.post_form(
28
+ URI.parse(API_URL),
29
+ tripwire_params
30
+ )
31
+ end
32
+ rescue Exception => ex
33
+ warn "Could not submit tripwireapp notification: #{ex.class} - #{ex.message}" unless Rails.env.production?
34
+ end
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def should_log_failures_to_tripwire?
41
+ Tripwire::Notifier.monitored_environments.include?(Rails.env.to_s)
42
+ end
43
+
44
+ def records_with_errors
45
+ @records_with_errors ||= begin
46
+ instance_variable_names.map do |var_name|
47
+ var = instance_variable_get(var_name)
48
+ if var.is_a?(Array)
49
+ var.select{|v| record_has_errors?(v)}
50
+ else
51
+ var if record_has_errors?(var)
52
+ end
53
+ end.flatten.compact
54
+ end
55
+ end
56
+
57
+ def record_has_errors?(record)
58
+ record.respond_to?(:errors) && record.errors.present?
59
+ end
60
+
61
+ # TODO: remove assumptions about being called within a rails app (request, etc.) as part of framework agnosticism
62
+ def tripwire_params
63
+ # TODO: limit this in size - how big?
64
+ data = {:params => filtered_params} # TODO: this is going to make controller and action redundant
65
+
66
+ data.merge!(:current_user => current_user) if respond_to?(:current_user)
67
+ data.merge!(
68
+ :user_agent => request.user_agent,
69
+ :cookies => request.cookies,
70
+ :session => request.session
71
+ )
72
+
73
+ query = {
74
+ :api_key => Tripwire::Notifier.api_key,
75
+ :api_version => Tripwire::Notifier::API_VERSION,
76
+ :_controller => params['controller'],
77
+ :_action => params['action'],
78
+ :path => request.path,
79
+ :data => data.to_json
80
+ }
81
+
82
+ query[:failures] = records_with_errors.map do |record|
83
+ record.errors.map do |field, messages|
84
+ Array(messages).map do |message|
85
+ {
86
+ :model => record.class.to_s,
87
+ :field => field,
88
+ :message => message
89
+ }
90
+ end
91
+ end
92
+ end.flatten.to_json
93
+
94
+ query
95
+ end
96
+
97
+ def filtered_params
98
+ if respond_to?(:filter_parameters)
99
+ filter_parameters(params)
100
+ else
101
+ params
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ ActionController::Base.send(:include, Tripwire::Notifier)
data/test/helper.rb ADDED
@@ -0,0 +1,28 @@
1
+ require 'rubygems'
2
+ require 'redgreen'
3
+ require 'test/unit'
4
+ require 'ostruct'
5
+ require 'shoulda'
6
+ require 'action_controller'
7
+ require 'fakeweb'
8
+ require 'mocha'
9
+
10
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
11
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
12
+ require 'tripwire_notifier'
13
+
14
+ class Test::Unit::TestCase
15
+ end
16
+
17
+ class FooController < ActionController::Base
18
+ filter_parameter_logging :password
19
+ end
20
+
21
+ class BarController < ActionController::Base
22
+ def current_user
23
+ "joe"
24
+ end
25
+ end
26
+
27
+ class Rails
28
+ end
@@ -0,0 +1,115 @@
1
+ require 'helper'
2
+
3
+ class TestTripwire < Test::Unit::TestCase
4
+ def fake_controller(klass)
5
+ fake = klass.new
6
+ fake.params = {'action' => "foo", 'controller' => "bar"}
7
+ fake.request = OpenStruct.new(
8
+ :user_agent => 'FooFox',
9
+ :cookies => {'one' => 'two', 'three' => 'four'},
10
+ :session => {'something' => 'ok'}
11
+ )
12
+ fake
13
+ end
14
+
15
+ def setup
16
+ Rails.stubs(:env => 'production')
17
+
18
+ @foo_controller = fake_controller(FooController)
19
+
20
+ FakeWeb.register_uri(:post, Tripwire::Notifier::API_URL, :body => "")
21
+ Tripwire::Notifier.api_key = "SOME API KEY"
22
+ Tripwire::Notifier.monitored_environments = ['production']
23
+
24
+ @model_one = OpenStruct.new(:errors => {"bar" => "is blank"})
25
+ @model_two = OpenStruct.new(:errors => {"baz" => "is blank"})
26
+ @model_three = OpenStruct.new(:errors => {"f1" => "is blank","f2" => ["is too large", "is delicious"]})
27
+
28
+ @foo_controller.instance_variable_set("@lol", @model_one)
29
+ @foo_controller.instance_variable_set("@wtf", [@model_two, @model_three])
30
+
31
+ # we also set a non-errored model just to ensure that it is not matched
32
+ @foo_controller.instance_variable_set("@bbq", OpenStruct.new(:errors => []))
33
+ end
34
+
35
+ should "set an api key" do
36
+ Tripwire::Notifier.api_key = "Foo"
37
+
38
+ assert_equal "Foo", Tripwire::Notifier.api_key
39
+ end
40
+
41
+ should "set a timeout_in_seconds" do
42
+ assert_equal 5, Tripwire::Notifier.timeout_in_seconds
43
+ Tripwire::Notifier.timeout_in_seconds = 6
44
+ assert_equal 6, Tripwire::Notifier.timeout_in_seconds
45
+ end
46
+
47
+ should "set monitored environments" do
48
+ assert_equal ["production"], Tripwire::Notifier.monitored_environments
49
+ Tripwire::Notifier.monitored_environments = ['stage', 'development']
50
+ assert_equal ['stage', 'development'], Tripwire::Notifier.monitored_environments
51
+ end
52
+
53
+ should "respect monitored environments" do
54
+ assert @foo_controller.send(:should_log_failures_to_tripwire?)
55
+
56
+ Tripwire::Notifier.monitored_environments = ['stage', 'development']
57
+ assert !@foo_controller.send(:should_log_failures_to_tripwire?)
58
+ end
59
+
60
+ should "identify no errors by default" do
61
+ assert_equal [], FooController.new.send(:records_with_errors)
62
+ end
63
+
64
+ should "identify records with errors" do
65
+ assert_same_elements [@model_one, @model_two, @model_three], @foo_controller.send(:records_with_errors)
66
+ end
67
+
68
+ should "create params via tripwire_params" do
69
+ expected = [
70
+ {"model"=>"OpenStruct", "field"=>"baz", "message"=>"is blank"},
71
+ {"model"=>"OpenStruct", "field"=>"f1", "message"=>"is blank"},
72
+ {"model"=>"OpenStruct", "field"=>"f2", "message"=>"is too large"},
73
+ {"model"=>"OpenStruct", "field"=>"f2", "message"=>"is delicious"},
74
+ {"model"=>"OpenStruct", "field"=>"bar", "message"=>"is blank"}
75
+ ]
76
+
77
+ params = @foo_controller.send(:tripwire_params)
78
+ failures = JSON.parse(params[:failures])
79
+ assert_same_elements expected, failures
80
+ assert_same_elements Tripwire::Notifier::API_VERSION, params[:api_version]
81
+ assert_same_elements "SOME API KEY", params[:api_key]
82
+ end
83
+
84
+ should "submit errors via log_validation_failures_to_tripwire" do
85
+ Net::HTTP.expects(:post_form).with(URI.parse(Tripwire::Notifier::API_URL), @foo_controller.send(:tripwire_params))
86
+ @foo_controller.send(:log_validation_failures_to_tripwire)
87
+ end
88
+
89
+ should "log controller and action" do
90
+ assert_equal @foo_controller.params['action'], @foo_controller.send(:tripwire_params)[:_action]
91
+ assert_equal @foo_controller.params['controller'], @foo_controller.send(:tripwire_params)[:_controller]
92
+ end
93
+
94
+ should "log params" do
95
+ @foo_controller.params.merge!('lolcats' => "no longer funny")
96
+ assert_equal @foo_controller.params, JSON.parse(@foo_controller.send(:tripwire_params)[:data])['params']
97
+ end
98
+
99
+ should "filter params" do
100
+ @foo_controller.params.merge!('password' => "do not show", 'password_confirmation' => 'rollerskates')
101
+ assert_equal @foo_controller.params.merge('password' => "[FILTERED]", 'password_confirmation' => '[FILTERED]'), JSON.parse(@foo_controller.send(:tripwire_params)[:data])['params']
102
+ end
103
+
104
+ should "log current user if the method is exposed" do
105
+ assert_equal nil, JSON.parse(@foo_controller.send(:tripwire_params)[:data])['current_user']
106
+ assert_equal "joe", JSON.parse(fake_controller(BarController).send(:tripwire_params)[:data])['current_user']
107
+ end
108
+
109
+ [:cookies, :session, :user_agent].each do |kind|
110
+ should "log #{kind}" do
111
+ assert @foo_controller.request.send(kind).present?
112
+ assert_equal @foo_controller.request.send(kind), JSON.parse(fake_controller(BarController).send(:tripwire_params)[:data])[kind.to_s]
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,54 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{tripwire_notifier}
8
+ s.version = "0.1.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Jeffrey Chupp", "Jeremy Weiskotten"]
12
+ s.date = %q{2010-07-12}
13
+ s.description = %q{Tripwire captures validation errors from your Ruby on Rails application to help you identify and fix user experience issues. The Tripwire::Notifier gem makes it easy to hook up your app to the Tripwire web service.}
14
+ s.email = %q{}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "lib/tripwire_notifier.rb",
27
+ "test/helper.rb",
28
+ "test/test_tripwire.rb",
29
+ "tripwire_notifier.gemspec"
30
+ ]
31
+ s.homepage = %q{http://github.com/jeremyw/tripwire_notifier}
32
+ s.rdoc_options = ["--charset=UTF-8"]
33
+ s.require_paths = ["lib"]
34
+ s.rubygems_version = %q{1.3.7}
35
+ s.summary = %q{Tripwire (http://tripwireapp.com) captures validation errors from your Ruby on Rails application.}
36
+ s.test_files = [
37
+ "test/helper.rb",
38
+ "test/test_tripwire.rb"
39
+ ]
40
+
41
+ if s.respond_to? :specification_version then
42
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
43
+ s.specification_version = 3
44
+
45
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
46
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
47
+ else
48
+ s.add_dependency(%q<shoulda>, [">= 0"])
49
+ end
50
+ else
51
+ s.add_dependency(%q<shoulda>, [">= 0"])
52
+ end
53
+ end
54
+
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tripwire_notifier
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 1
10
+ version: 0.1.1
11
+ platform: ruby
12
+ authors:
13
+ - Jeffrey Chupp
14
+ - Jeremy Weiskotten
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2010-07-12 00:00:00 -04:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: shoulda
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 3
31
+ segments:
32
+ - 0
33
+ version: "0"
34
+ type: :development
35
+ version_requirements: *id001
36
+ description: Tripwire captures validation errors from your Ruby on Rails application to help you identify and fix user experience issues. The Tripwire::Notifier gem makes it easy to hook up your app to the Tripwire web service.
37
+ email: ""
38
+ executables: []
39
+
40
+ extensions: []
41
+
42
+ extra_rdoc_files:
43
+ - LICENSE
44
+ - README.rdoc
45
+ files:
46
+ - .document
47
+ - .gitignore
48
+ - LICENSE
49
+ - README.rdoc
50
+ - Rakefile
51
+ - VERSION
52
+ - lib/tripwire_notifier.rb
53
+ - test/helper.rb
54
+ - test/test_tripwire.rb
55
+ - tripwire_notifier.gemspec
56
+ has_rdoc: true
57
+ homepage: http://github.com/jeremyw/tripwire_notifier
58
+ licenses: []
59
+
60
+ post_install_message:
61
+ rdoc_options:
62
+ - --charset=UTF-8
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ hash: 3
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ hash: 3
80
+ segments:
81
+ - 0
82
+ version: "0"
83
+ requirements: []
84
+
85
+ rubyforge_project:
86
+ rubygems_version: 1.3.7
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: Tripwire (http://tripwireapp.com) captures validation errors from your Ruby on Rails application.
90
+ test_files:
91
+ - test/helper.rb
92
+ - test/test_tripwire.rb