Commit b44212384e33e91d358c60bb906cc259d8354ad7

Authored by Marcin Ciunelis
2 parents 6eac8641 0d16f2af
Exists in master and in 1 other branch production

Merge branch 'master' into fingerprint

1 source 'http://rubygems.org' 1 source 'http://rubygems.org'
2 2
3 -gem 'rails', '3.2.6' 3 +gem 'rails', '3.2.8'
4 4
5 gem 'nokogiri' 5 gem 'nokogiri'
6 gem 'mongoid', '~> 2.4.10' 6 gem 'mongoid', '~> 2.4.10'
@@ -49,6 +49,7 @@ group :development, :test do @@ -49,6 +49,7 @@ group :development, :test do
49 end 49 end
50 # gem 'rpm_contrib' 50 # gem 'rpm_contrib'
51 # gem 'newrelic_rpm' 51 # gem 'newrelic_rpm'
  52 + gem 'capistrano'
52 end 53 end
53 54
54 group :test do 55 group :test do
@@ -2,35 +2,35 @@ GEM @@ -2,35 +2,35 @@ GEM
2 remote: http://rubygems.org/ 2 remote: http://rubygems.org/
3 specs: 3 specs:
4 SystemTimer (1.2.3) 4 SystemTimer (1.2.3)
5 - actionmailer (3.2.6)  
6 - actionpack (= 3.2.6) 5 + actionmailer (3.2.8)
  6 + actionpack (= 3.2.8)
7 mail (~> 2.4.4) 7 mail (~> 2.4.4)
8 actionmailer_inline_css (1.3.1) 8 actionmailer_inline_css (1.3.1)
9 actionmailer (>= 3.0.0) 9 actionmailer (>= 3.0.0)
10 nokogiri (>= 1.4.4) 10 nokogiri (>= 1.4.4)
11 premailer (>= 1.7.1) 11 premailer (>= 1.7.1)
12 - actionpack (3.2.6)  
13 - activemodel (= 3.2.6)  
14 - activesupport (= 3.2.6) 12 + actionpack (3.2.8)
  13 + activemodel (= 3.2.8)
  14 + activesupport (= 3.2.8)
15 builder (~> 3.0.0) 15 builder (~> 3.0.0)
16 erubis (~> 2.7.0) 16 erubis (~> 2.7.0)
17 - journey (~> 1.0.1) 17 + journey (~> 1.0.4)
18 rack (~> 1.4.0) 18 rack (~> 1.4.0)
19 rack-cache (~> 1.2) 19 rack-cache (~> 1.2)
20 rack-test (~> 0.6.1) 20 rack-test (~> 0.6.1)
21 sprockets (~> 2.1.3) 21 sprockets (~> 2.1.3)
22 - activemodel (3.2.6)  
23 - activesupport (= 3.2.6) 22 + activemodel (3.2.8)
  23 + activesupport (= 3.2.8)
24 builder (~> 3.0.0) 24 builder (~> 3.0.0)
25 - activerecord (3.2.6)  
26 - activemodel (= 3.2.6)  
27 - activesupport (= 3.2.6) 25 + activerecord (3.2.8)
  26 + activemodel (= 3.2.8)
  27 + activesupport (= 3.2.8)
28 arel (~> 3.0.2) 28 arel (~> 3.0.2)
29 tzinfo (~> 0.3.29) 29 tzinfo (~> 0.3.29)
30 - activeresource (3.2.6)  
31 - activemodel (= 3.2.6)  
32 - activesupport (= 3.2.6)  
33 - activesupport (3.2.6) 30 + activeresource (3.2.8)
  31 + activemodel (= 3.2.8)
  32 + activesupport (= 3.2.8)
  33 + activesupport (3.2.8)
34 i18n (~> 0.6) 34 i18n (~> 0.6)
35 multi_json (~> 1.0) 35 multi_json (~> 1.0)
36 addressable (2.3.2) 36 addressable (2.3.2)
@@ -39,7 +39,13 @@ GEM @@ -39,7 +39,13 @@ GEM
39 bson (1.6.2) 39 bson (1.6.2)
40 bson_ext (1.6.2) 40 bson_ext (1.6.2)
41 bson (~> 1.6.2) 41 bson (~> 1.6.2)
42 - builder (3.0.0) 42 + builder (3.0.3)
  43 + capistrano (2.13.3)
  44 + highline
  45 + net-scp (>= 1.0.0)
  46 + net-sftp (>= 2.0.0)
  47 + net-ssh (>= 2.0.14)
  48 + net-ssh-gateway (>= 1.1.0)
43 capybara (1.1.2) 49 capybara (1.1.2)
44 mime-types (>= 1.16) 50 mime-types (>= 1.16)
45 nokogiri (>= 1.3.3) 51 nokogiri (>= 1.3.3)
@@ -86,18 +92,19 @@ GEM @@ -86,18 +92,19 @@ GEM
86 libxml-ruby (~> 2.0) 92 libxml-ruby (~> 2.0)
87 has_scope (0.5.1) 93 has_scope (0.5.1)
88 hashie (1.2.0) 94 hashie (1.2.0)
  95 + highline (1.6.13)
89 hike (1.2.1) 96 hike (1.2.1)
90 hoptoad_notifier (2.4.11) 97 hoptoad_notifier (2.4.11)
91 activesupport 98 activesupport
92 builder 99 builder
93 htmlentities (4.3.1) 100 htmlentities (4.3.1)
94 httpauth (0.1) 101 httpauth (0.1)
95 - i18n (0.6.0) 102 + i18n (0.6.1)
96 inherited_resources (1.3.1) 103 inherited_resources (1.3.1)
97 has_scope (~> 0.5.0) 104 has_scope (~> 0.5.0)
98 responders (~> 0.6) 105 responders (~> 0.6)
99 journey (1.0.4) 106 journey (1.0.4)
100 - json (1.7.4) 107 + json (1.7.5)
101 jwt (0.1.5) 108 jwt (0.1.5)
102 multi_json (>= 1.0) 109 multi_json (>= 1.0)
103 kaminari (0.13.0) 110 kaminari (0.13.0)
@@ -134,6 +141,13 @@ GEM @@ -134,6 +141,13 @@ GEM
134 railties (>= 3.0.0) 141 railties (>= 3.0.0)
135 multi_json (1.3.6) 142 multi_json (1.3.6)
136 multipart-post (1.1.5) 143 multipart-post (1.1.5)
  144 + net-scp (1.0.4)
  145 + net-ssh (>= 1.99.1)
  146 + net-sftp (2.0.5)
  147 + net-ssh (>= 2.0.9)
  148 + net-ssh (2.5.2)
  149 + net-ssh-gateway (1.1.0)
  150 + net-ssh (>= 1.99.1)
137 nokogiri (1.5.5) 151 nokogiri (1.5.5)
138 oa-core (0.3.2) 152 oa-core (0.3.2)
139 oauth2 (0.8.0) 153 oauth2 (0.8.0)
@@ -181,19 +195,19 @@ GEM @@ -181,19 +195,19 @@ GEM
181 rack-ssl-enforcer (0.2.4) 195 rack-ssl-enforcer (0.2.4)
182 rack-test (0.6.1) 196 rack-test (0.6.1)
183 rack (>= 1.0) 197 rack (>= 1.0)
184 - rails (3.2.6)  
185 - actionmailer (= 3.2.6)  
186 - actionpack (= 3.2.6)  
187 - activerecord (= 3.2.6)  
188 - activeresource (= 3.2.6)  
189 - activesupport (= 3.2.6) 198 + rails (3.2.8)
  199 + actionmailer (= 3.2.8)
  200 + actionpack (= 3.2.8)
  201 + activerecord (= 3.2.8)
  202 + activeresource (= 3.2.8)
  203 + activesupport (= 3.2.8)
190 bundler (~> 1.0) 204 bundler (~> 1.0)
191 - railties (= 3.2.6) 205 + railties (= 3.2.8)
192 rails_autolink (1.0.9) 206 rails_autolink (1.0.9)
193 rails (~> 3.1) 207 rails (~> 3.1)
194 - railties (3.2.6)  
195 - actionpack (= 3.2.6)  
196 - activesupport (= 3.2.6) 208 + railties (3.2.8)
  209 + actionpack (= 3.2.8)
  210 + activesupport (= 3.2.8)
197 rack-ssl (~> 1.3.2) 211 rack-ssl (~> 1.3.2)
198 rake (>= 0.8.7) 212 rake (>= 0.8.7)
199 rdoc (~> 3.4) 213 rdoc (~> 3.4)
@@ -244,7 +258,7 @@ GEM @@ -244,7 +258,7 @@ GEM
244 daemons (>= 1.0.9) 258 daemons (>= 1.0.9)
245 eventmachine (>= 0.12.6) 259 eventmachine (>= 0.12.6)
246 rack (>= 1.0.0) 260 rack (>= 1.0.0)
247 - thor (0.15.4) 261 + thor (0.16.0)
248 tilt (1.3.3) 262 tilt (1.3.3)
249 treetop (1.4.10) 263 treetop (1.4.10)
250 polyglot 264 polyglot
@@ -275,6 +289,7 @@ DEPENDENCIES @@ -275,6 +289,7 @@ DEPENDENCIES
275 actionmailer_inline_css (~> 1.3.0) 289 actionmailer_inline_css (~> 1.3.0)
276 bson (= 1.6.2) 290 bson (= 1.6.2)
277 bson_ext (= 1.6.2) 291 bson_ext (= 1.6.2)
  292 + capistrano
278 capybara 293 capybara
279 database_cleaner (~> 0.6.0) 294 database_cleaner (~> 0.6.0)
280 debugger 295 debugger
@@ -299,7 +314,7 @@ DEPENDENCIES @@ -299,7 +314,7 @@ DEPENDENCIES
299 oruen_redmine_client 314 oruen_redmine_client
300 pivotal-tracker 315 pivotal-tracker
301 rack-ssl-enforcer 316 rack-ssl-enforcer
302 - rails (= 3.2.6) 317 + rails (= 3.2.8)
303 rails_autolink (~> 1.0.9) 318 rails_autolink (~> 1.0.9)
304 ri_cal 319 ri_cal
305 rspec (~> 2.6) 320 rspec (~> 2.6)
app/assets/stylesheets/errbit.css
@@ -841,15 +841,30 @@ table.comment tbody th { @@ -841,15 +841,30 @@ table.comment tbody th {
841 height: 20px; 841 height: 20px;
842 line-height: 0.5em; 842 line-height: 0.5em;
843 } 843 }
  844 +table.comment th span, table.comment th img {
  845 + vertical-align: middle;
  846 +}
  847 +table.comment th span.comment-info {
  848 + line-height: 21px;
  849 +}
  850 +table.comment img.gravatar {
  851 + margin-right: 7px;
  852 +}
  853 +
844 table.comment tbody td { 854 table.comment tbody td {
845 background-color: #F9F9F9; 855 background-color: #F9F9F9;
846 } 856 }
847 #content-comments a.destroy-comment { 857 #content-comments a.destroy-comment {
848 color: #EE0000; 858 color: #EE0000;
849 margin-right: 5px; 859 margin-right: 5px;
  860 + margin-top: 2px;
  861 + font-size: 21px;
  862 + line-height: 1;
  863 + float: right;
850 } 864 }
851 #content-comments a.destroy-comment:hover { 865 #content-comments a.destroy-comment:hover {
852 text-decoration: none; 866 text-decoration: none;
  867 + color: #AA0000;
853 } 868 }
854 #content-comments #comment_submit { 869 #content-comments #comment_submit {
855 margin-top: 15px; 870 margin-top: 15px;
@@ -878,3 +893,12 @@ table.errs tr td.message .inline_comment em.commenter { @@ -878,3 +893,12 @@ table.errs tr td.message .inline_comment em.commenter {
878 893
879 .current.asc:after { content: ' ↑'; } 894 .current.asc:after { content: ' ↑'; }
880 .current.desc:after { content: ' ↓'; } 895 .current.desc:after { content: ' ↓'; }
  896 +
  897 +
  898 +table.users td {
  899 + vertical-align: middle;
  900 +}
  901 +table.users td img.gravatar {
  902 + vertical-align: middle;
  903 + margin-left: 3px;
  904 +}
app/helpers/errs_helper.rb
@@ -13,5 +13,19 @@ module ErrsHelper @@ -13,5 +13,19 @@ module ErrsHelper
13 truncate(msg, :length => 300).scan(/.{1,5}/).map { |s| h(s) }.join("​").html_safe 13 truncate(msg, :length => 300).scan(/.{1,5}/).map { |s| h(s) }.join("​").html_safe
14 end 14 end
15 end 15 end
  16 +
  17 + def gravatar_tag(email, options = {})
  18 + image_tag gravatar_url(email, options), :alt => email, :class => 'gravatar'
  19 + end
  20 +
  21 + def gravatar_url(email, options = {})
  22 + default_options = {
  23 + :d => Errbit::Config.gravatar_default,
  24 + }
  25 + options.reverse_merge! default_options
  26 + params = options.extract!(:s, :d).delete_if { |k, v| v.blank? }
  27 + email_hash = Digest::MD5.hexdigest(email)
  28 + "http://www.gravatar.com/avatar/#{email_hash}?#{params.to_query}"
  29 + end
16 end 30 end
17 31
app/models/error_report.rb
@@ -2,7 +2,7 @@ require 'digest/sha1' @@ -2,7 +2,7 @@ require 'digest/sha1'
2 require 'hoptoad_notifier' 2 require 'hoptoad_notifier'
3 3
4 class ErrorReport 4 class ErrorReport
5 - attr_reader :error_class, :message, :backtrace, :request, :server_environment, :api_key, :notifier, :user_attributes 5 + attr_reader :error_class, :message, :backtrace, :request, :server_environment, :api_key, :notifier, :user_attributes, :current_user
6 6
7 def initialize(xml_or_attributes) 7 def initialize(xml_or_attributes)
8 @attributes = (xml_or_attributes.is_a?(String) ? Hoptoad.parse_xml!(xml_or_attributes) : xml_or_attributes).with_indifferent_access 8 @attributes = (xml_or_attributes.is_a?(String) ? Hoptoad.parse_xml!(xml_or_attributes) : xml_or_attributes).with_indifferent_access
@@ -37,7 +37,9 @@ class ErrorReport @@ -37,7 +37,9 @@ class ErrorReport
37 :request => request, 37 :request => request,
38 :server_environment => server_environment, 38 :server_environment => server_environment,
39 :notifier => notifier, 39 :notifier => notifier,
40 - :user_attributes => user_attributes) 40 + :user_attributes => user_attributes,
  41 + :current_user => current_user
  42 + )
41 43
42 err = app.find_or_create_err!( 44 err = app.find_or_create_err!(
43 :error_class => error_class, 45 :error_class => error_class,
app/models/notice.rb
@@ -11,6 +11,7 @@ class Notice @@ -11,6 +11,7 @@ class Notice
11 field :request, :type => Hash 11 field :request, :type => Hash
12 field :notifier, :type => Hash 12 field :notifier, :type => Hash
13 field :user_attributes, :type => Hash 13 field :user_attributes, :type => Hash
  14 + field :current_user, :type => Hash
14 field :error_class 15 field :error_class
15 16
16 belongs_to :err 17 belongs_to :err
app/views/errs/show.html.haml
@@ -28,9 +28,12 @@ @@ -28,9 +28,12 @@
28 %table.comment 28 %table.comment
29 %tr 29 %tr
30 %th 30 %th
31 - %span= link_to '✘'.html_safe, app_err_comment_path(@app, @problem, comment), :method => :delete, :data => { :confirm => "Are sure you don't need this comment?" }, :class => "destroy-comment"  
32 - = time_ago_in_words(comment.created_at, true) << " ago by "  
33 - = link_to comment.user.email, user_path(comment.user) 31 + - if Errbit::Config.use_gravatar
  32 + = gravatar_tag comment.user.email, :s => 24
  33 + %span.comment-info
  34 + = time_ago_in_words(comment.created_at, true) << " ago by "
  35 + = link_to comment.user.email, user_path(comment.user)
  36 + %span.delete= link_to '&#10008;'.html_safe, app_err_comment_path(@app, @problem, comment), :method => :delete, :data => { :confirm => "Are sure you don't need this comment?" }, :class => "destroy-comment"
34 %tr 37 %tr
35 %td= comment.body.gsub("\n", "<br>").html_safe 38 %td= comment.body.gsub("\n", "<br>").html_safe
36 - if Errbit::Config.allow_comments_with_issue_tracker || !@app.issue_tracker_configured? 39 - if Errbit::Config.allow_comments_with_issue_tracker || !@app.issue_tracker_configured?
app/views/layouts/application.html.haml
@@ -18,7 +18,7 @@ @@ -18,7 +18,7 @@
18 = render 'shared/navigation' if current_user 18 = render 'shared/navigation' if current_user
19 = render 'shared/session' 19 = render 'shared/session'
20 #content-wrapper 20 #content-wrapper
21 - #content-title{ :class => (yield :title_css_class).to_s } 21 + #content-title{ :class => (yield :title_css_class).to_s, :style => (yield :title_style) }
22 %h1= yield :title 22 %h1= yield :title
23 %span.meta= yield :meta 23 %span.meta= yield :meta
24 - if (action_bar = yield(:action_bar)).present? 24 - if (action_bar = yield(:action_bar)).present?
@@ -33,3 +33,4 @@ @@ -33,3 +33,4 @@
33 #footer= "Powered by #{link_to 'Errbit', 'http://github.com/errbit/errbit', :target => '_blank'}: the open source error catcher.".html_safe 33 #footer= "Powered by #{link_to 'Errbit', 'http://github.com/errbit/errbit', :target => '_blank'}: the open source error catcher.".html_safe
34 = yield :scripts 34 = yield :scripts
35 35
  36 += yield :before_title
36 \ No newline at end of file 37 \ No newline at end of file
app/views/users/index.html.haml
@@ -2,9 +2,11 @@ @@ -2,9 +2,11 @@
2 - content_for :action_bar do 2 - content_for :action_bar do
3 %span= link_to('Add a New User', new_user_path, :class => 'add') 3 %span= link_to('Add a New User', new_user_path, :class => 'add')
4 4
5 -%table 5 +%table.users
6 %thead 6 %thead
7 %tr 7 %tr
  8 + - if Errbit::Config.use_gravatar
  9 + %th
8 %th Name 10 %th Name
9 - if Errbit::Config.user_has_username 11 - if Errbit::Config.user_has_username
10 %th Username 12 %th Username
@@ -13,6 +15,8 @@ @@ -13,6 +15,8 @@
13 %tbody 15 %tbody
14 - @users.each do |user| 16 - @users.each do |user|
15 %tr 17 %tr
  18 + - if Errbit::Config.use_gravatar
  19 + %td= gravatar_tag user.email, :s => 24
16 %td.nowrap= link_to user.name, user_path(user) 20 %td.nowrap= link_to user.name, user_path(user)
17 - if Errbit::Config.user_has_username 21 - if Errbit::Config.user_has_username
18 %td= user.username 22 %td= user.username
app/views/users/show.html.haml
1 - content_for :title, @user.name 1 - content_for :title, @user.name
  2 +- if Errbit::Config.use_gravatar
  3 + - content_for :title_style do
  4 + background: url('#{gravatar_url @user.email, :s => 86}') no-repeat;
  5 + padding-left: 106px;
  6 +
2 - content_for :action_bar do 7 - content_for :action_bar do
3 = render 'shared/link_github_account', :user => @user 8 = render 'shared/link_github_account', :user => @user
4 %span= link_to('Add a New User', new_user_path, :class => 'add') 9 %span= link_to('Add a New User', new_user_path, :class => 'add')
5 = link_to 'edit', edit_user_path(@user), :class => 'button' 10 = link_to 'edit', edit_user_path(@user), :class => 'button'
6 = link_to 'destroy', user_path(@user), :method => :delete, :data => { :confirm => 'Seriously?' }, :class => 'button' 11 = link_to 'destroy', user_path(@user), :method => :delete, :data => { :confirm => 'Seriously?' }, :class => 'button'
7 12
8 -  
9 %table.single_user 13 %table.single_user
10 %tr 14 %tr
11 %th Email 15 %th Email
config/config.example.yml
@@ -39,6 +39,11 @@ user_has_username: false @@ -39,6 +39,11 @@ user_has_username: false
39 # but you want to leave a short comment. 39 # but you want to leave a short comment.
40 allow_comments_with_issue_tracker: true 40 allow_comments_with_issue_tracker: true
41 41
  42 +# Enable Gravatar.
  43 +use_gravatar: true
  44 +# Default Gravatar image, can be: mm, identicon, monsterid, wavatar, retro.
  45 +gravatar_default: identicon
  46 +
42 # Setup your deploy options for capistrano. 47 # Setup your deploy options for capistrano.
43 deployment: 48 deployment:
44 hosts: 49 hosts:
config/initializers/_load_config.rb
@@ -13,6 +13,10 @@ unless defined?(Errbit::Config) @@ -13,6 +13,10 @@ unless defined?(Errbit::Config)
13 Errbit::Config.confirm_resolve_err = ENV['ERRBIT_CONFIRM_RESOLVE_ERR'] 13 Errbit::Config.confirm_resolve_err = ENV['ERRBIT_CONFIRM_RESOLVE_ERR']
14 Errbit::Config.user_has_username = ENV['ERRBIT_USER_HAS_USERNAME'] 14 Errbit::Config.user_has_username = ENV['ERRBIT_USER_HAS_USERNAME']
15 Errbit::Config.allow_comments_with_issue_tracker = ENV['ERRBIT_ALLOW_COMMENTS_WITH_ISSUE_TRACKER'] 15 Errbit::Config.allow_comments_with_issue_tracker = ENV['ERRBIT_ALLOW_COMMENTS_WITH_ISSUE_TRACKER']
  16 + Errbit::Config.enforce_ssl = ENV['ERRBIT_ENFORCE_SSL']
  17 +
  18 + Errbit::Config.use_gravatar = ENV['ERRBIT_USE_GRAVATAR']
  19 + Errbit::Config.gravatar_default = ENV['ERRBIT_GRAVATAR_DEFAULT']
16 20
17 Errbit::Config.github_authentication = ENV['GITHUB_AUTHENTICATION'] 21 Errbit::Config.github_authentication = ENV['GITHUB_AUTHENTICATION']
18 Errbit::Config.github_client_id = ENV['GITHUB_CLIENT_ID'] 22 Errbit::Config.github_client_id = ENV['GITHUB_CLIENT_ID']
config/initializers/omniauth.rb 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +OmniAuth.config.logger = Rails.logger
db/migrate/20110422152027_move_notices_to_separate_collection.rb
@@ -5,6 +5,10 @@ class MoveNoticesToSeparateCollection &lt; Mongoid::Migration @@ -5,6 +5,10 @@ class MoveNoticesToSeparateCollection &lt; Mongoid::Migration
5 errs = mongo_db.collection("errs").find({ }, :fields => ["notices"]) 5 errs = mongo_db.collection("errs").find({ }, :fields => ["notices"])
6 errs.each do |err| 6 errs.each do |err|
7 next unless err['notices'] 7 next unless err['notices']
  8 +
  9 + # This Err was created after the Problem->Err->Notice redesign
  10 + next if err['app_id'].nil? or err['problem_id']
  11 +
8 e = Err.find(err['_id']) 12 e = Err.find(err['_id'])
9 # disable email notifications 13 # disable email notifications
10 old_notify = e.app.notify_on_errs? 14 old_notify = e.app.notify_on_errs?
db/migrate/20120530005915_rename_klass_to_error_class.rb
1 class RenameKlassToErrorClass < Mongoid::Migration 1 class RenameKlassToErrorClass < Mongoid::Migration
2 def self.up 2 def self.up
3 [Problem, Err, Notice].each do |model| 3 [Problem, Err, Notice].each do |model|
4 - model.collection.update({}, {'$rename' => {'klass' => 'error_class'}}, multi: true, safe: true) 4 + model.collection.update({}, {'$rename' => {'klass' => 'error_class'}}, :multi => true, :safe => true)
5 end 5 end
6 end 6 end
7 7
8 def self.down 8 def self.down
9 [Problem, Err, Notice].each do |model| 9 [Problem, Err, Notice].each do |model|
10 - model.collection.update({}, {'$rename' => {'error_class' => 'klass'}}, multi: true, safe: true) 10 + model.collection.update({}, {'$rename' => {'error_class' => 'klass'}}, :multi => true, :safe => true)
11 end 11 end
12 end 12 end
13 end 13 end
db/migrate/20120603112130_change_github_url_to_github_repo.rb
1 class ChangeGithubUrlToGithubRepo < Mongoid::Migration 1 class ChangeGithubUrlToGithubRepo < Mongoid::Migration
2 def self.up 2 def self.up
3 - App.collection.update({}, {'$rename' => {'github_url' => 'github_repo'}}, multi: true, safe: true) 3 + App.collection.update({}, {'$rename' => {'github_url' => 'github_repo'}}, :multi => true, :safe => true)
4 App.all.each do |app| 4 App.all.each do |app|
5 app.send :normalize_github_repo 5 app.send :normalize_github_repo
6 app.save 6 app.save
@@ -8,7 +8,7 @@ class ChangeGithubUrlToGithubRepo &lt; Mongoid::Migration @@ -8,7 +8,7 @@ class ChangeGithubUrlToGithubRepo &lt; Mongoid::Migration
8 end 8 end
9 9
10 def self.down 10 def self.down
11 - App.collection.update({}, {'$rename' => {'github_repo' => 'github_url'}}, multi: true, safe: true) 11 + App.collection.update({}, {'$rename' => {'github_repo' => 'github_url'}}, :multi => true, :safe => true)
12 App.all.each do |app| 12 App.all.each do |app|
13 unless app.github_repo.include?("github.com") 13 unless app.github_repo.include?("github.com")
14 app.update_attribute :github_url, "https://github.com/" << app.github_url 14 app.update_attribute :github_url, "https://github.com/" << app.github_url
lib/hoptoad.rb
@@ -3,7 +3,7 @@ require &#39;hoptoad/v2&#39; @@ -3,7 +3,7 @@ require &#39;hoptoad/v2&#39;
3 module Hoptoad 3 module Hoptoad
4 class ApiVersionError < StandardError 4 class ApiVersionError < StandardError
5 def initialize 5 def initialize
6 - super "Wrong API Version: Expecting 2.0, 2.1, or 2.2" 6 + super "Wrong API Version: Expecting 2.0, 2.1, 2.2 or 2.3"
7 end 7 end
8 end 8 end
9 9
@@ -16,7 +16,7 @@ module Hoptoad @@ -16,7 +16,7 @@ module Hoptoad
16 private 16 private
17 def self.get_version_processor(version) 17 def self.get_version_processor(version)
18 case version 18 case version
19 - when /2\.[012]/; Hoptoad::V2 19 + when /2\.[0123]/; Hoptoad::V2
20 else; raise ApiVersionError 20 else; raise ApiVersionError
21 end 21 end
22 end 22 end
lib/hoptoad/v2.rb
@@ -59,7 +59,8 @@ module Hoptoad @@ -59,7 +59,8 @@ module Hoptoad
59 59
60 :api_key => notice['api-key'], 60 :api_key => notice['api-key'],
61 :notifier => notice['notifier'], 61 :notifier => notice['notifier'],
62 - :user_attributes => notice['user-attributes'] || {} 62 + :user_attributes => notice['user-attributes'] || {},
  63 + :current_user => notice['current-user'] || {}
63 } 64 }
64 end 65 end
65 end 66 end
spec/controllers/notices_controller_spec.rb
@@ -13,7 +13,7 @@ describe NoticesController do @@ -13,7 +13,7 @@ describe NoticesController do
13 @notice = App.report_error!(@xml) 13 @notice = App.report_error!(@xml)
14 end 14 end
15 15
16 - it "generates a notice from xml [POST]" do 16 + it "generates a notice from raw xml [POST]" do
17 App.should_receive(:report_error!).with(@xml).and_return(@notice) 17 App.should_receive(:report_error!).with(@xml).and_return(@notice)
18 request.should_receive(:raw_post).and_return(@xml) 18 request.should_receive(:raw_post).and_return(@xml)
19 post :create, :format => :xml 19 post :create, :format => :xml
@@ -24,6 +24,16 @@ describe NoticesController do @@ -24,6 +24,16 @@ describe NoticesController do
24 response.body.should match(%r{<url[^>]*>(.+)#{locate_path(@notice.id)}</url>}) 24 response.body.should match(%r{<url[^>]*>(.+)#{locate_path(@notice.id)}</url>})
25 end 25 end
26 26
  27 + it "generates a notice from xml in a data param [POST]" do
  28 + App.should_receive(:report_error!).with(@xml).and_return(@notice)
  29 + post :create, :data => @xml, :format => :xml
  30 + response.should be_success
  31 + # Same RegExp from Airbrake::Sender#send_to_airbrake (https://github.com/airbrake/airbrake/blob/master/lib/airbrake/sender.rb#L53)
  32 + # Inspired by https://github.com/airbrake/airbrake/blob/master/test/sender_test.rb
  33 + response.body.should match(%r{<id[^>]*>#{@notice.id}</id>})
  34 + response.body.should match(%r{<url[^>]*>(.+)#{locate_path(@notice.id)}</url>})
  35 + end
  36 +
27 it "generates a notice from xml [GET]" do 37 it "generates a notice from xml [GET]" do
28 App.should_receive(:report_error!).with(@xml).and_return(@notice) 38 App.should_receive(:report_error!).with(@xml).and_return(@notice)
29 get :create, :data => @xml, :format => :xml 39 get :create, :data => @xml, :format => :xml
spec/fixtures/hoptoad_test_notice.xml
1 <?xml version="1.0" encoding="UTF-8"?> 1 <?xml version="1.0" encoding="UTF-8"?>
2 -<notice version="2.0"> 2 +<notice version="2.3">
3 <api-key>APIKEY</api-key> 3 <api-key>APIKEY</api-key>
4 <notifier> 4 <notifier>
5 <name>Hoptoad Notifier</name> 5 <name>Hoptoad Notifier</name>
@@ -144,4 +144,10 @@ @@ -144,4 +144,10 @@
144 <project-root>/path/to/sample/project</project-root> 144 <project-root>/path/to/sample/project</project-root>
145 <environment-name>development</environment-name> 145 <environment-name>development</environment-name>
146 </server-environment> 146 </server-environment>
  147 + <current-user>
  148 + <id>123</id>
  149 + <name>Mr. Bean</name>
  150 + <email>mr.bean@example.com</email>
  151 + <username>mrbean</username>
  152 + </current-user>
147 </notice> 153 </notice>
spec/helpers/errs_helper_spec.rb
@@ -9,4 +9,27 @@ describe ErrsHelper do @@ -9,4 +9,27 @@ describe ErrsHelper do
9 truncated.should_not include('<', '>') 9 truncated.should_not include('<', '>')
10 end 10 end
11 end 11 end
  12 +
  13 + describe "#gravatar_tag" do
  14 + let(:email) { "gravatar@example.com" }
  15 + let(:email_hash) { Digest::MD5.hexdigest email }
  16 + let(:base_url) { "http://www.gravatar.com/avatar/#{email_hash}" }
  17 +
  18 + context "default config" do
  19 + before do
  20 + Errbit::Config.stub(:use_gravatar).and_return(true)
  21 + Errbit::Config.stub(:gravatar_default).and_return('identicon')
  22 + end
  23 +
  24 + it "should render image_tag with correct alt and src" do
  25 + expected = "<img alt=\"#{email}\" class=\"gravatar\" src=\"#{base_url}?d=identicon&amp;s=48\" />"
  26 + helper.gravatar_tag(email, :s => 48).should eq(expected)
  27 + end
  28 +
  29 + it "should override :d" do
  30 + expected = "<img alt=\"#{email}\" class=\"gravatar\" src=\"#{base_url}?d=retro&amp;s=48\" />"
  31 + helper.gravatar_tag(email, :d => 'retro', :s => 48).should eq(expected)
  32 + end
  33 + end
  34 + end
12 end 35 end
spec/models/app_spec.rb
@@ -230,6 +230,15 @@ describe App do @@ -230,6 +230,15 @@ describe App do
230 lambda { @notice = App.report_error!(xml) }.should_not raise_error 230 lambda { @notice = App.report_error!(xml) }.should_not raise_error
231 @notice.backtrace.length.should == 1 231 @notice.backtrace.length.should == 1
232 end 232 end
  233 +
  234 + it 'captures the current_user' do
  235 + @notice = App.report_error!(@xml)
  236 + @notice.current_user['id'].should == '123'
  237 + @notice.current_user['name'].should == 'Mr. Bean'
  238 + @notice.current_user['email'].should == 'mr.bean@example.com'
  239 + @notice.current_user['username'].should == 'mrbean'
  240 + end
  241 +
233 end 242 end
234 243
235 244
spec/views/errs/show.html.haml_spec.rb
@@ -90,6 +90,7 @@ describe &quot;errs/show.html.haml&quot; do @@ -90,6 +90,7 @@ describe &quot;errs/show.html.haml&quot; do
90 describe "content_for :comments with comments disabled for configured issue tracker" do 90 describe "content_for :comments with comments disabled for configured issue tracker" do
91 before do 91 before do
92 Errbit::Config.stub(:allow_comments_with_issue_tracker).and_return(false) 92 Errbit::Config.stub(:allow_comments_with_issue_tracker).and_return(false)
  93 + Errbit::Config.stub(:use_gravatar).and_return(true)
93 end 94 end
94 95
95 it 'should display comments and new comment form when no issue tracker' do 96 it 'should display comments and new comment form when no issue tracker' do
@@ -99,6 +100,7 @@ describe &quot;errs/show.html.haml&quot; do @@ -99,6 +100,7 @@ describe &quot;errs/show.html.haml&quot; do
99 render 100 render
100 101
101 view.content_for(:comments).should include('Test comment') 102 view.content_for(:comments).should include('Test comment')
  103 + view.content_for(:comments).should have_selector('img[src^="http://www.gravatar.com/avatar"]')
102 view.content_for(:comments).should include('Add a comment') 104 view.content_for(:comments).should include('Add a comment')
103 end 105 end
104 106
@@ -117,6 +119,7 @@ describe &quot;errs/show.html.haml&quot; do @@ -117,6 +119,7 @@ describe &quot;errs/show.html.haml&quot; do
117 render 119 render
118 120
119 view.content_for(:comments).should include('Test comment') 121 view.content_for(:comments).should include('Test comment')
  122 + view.content_for(:comments).should have_selector('img[src^="http://www.gravatar.com/avatar"]')
120 view.content_for(:comments).should_not include('Add a comment') 123 view.content_for(:comments).should_not include('Add a comment')
121 end 124 end
122 end 125 end
spec/views/users/show.html.haml_spec.rb
@@ -2,7 +2,7 @@ require &#39;spec_helper&#39; @@ -2,7 +2,7 @@ require &#39;spec_helper&#39;
2 2
3 describe 'users/show.html.haml' do 3 describe 'users/show.html.haml' do
4 let(:user) do 4 let(:user) do
5 - stub_model(User, :created_at => Time.now) 5 + stub_model(User, :created_at => Time.now, :email => "test@example.com")
6 end 6 end
7 7
8 before do 8 before do