Commit a3fb360ceee40b08d9bd3e753bbe605de1bc411b

Authored by Pavel Forkert
2 parents 60425256 0029a957
Exists in master and in 1 other branch production

Merge branch 'master' of github.com:fxposter/errbit

README.md
... ... @@ -100,58 +100,58 @@ for you. Checkout [Hoptoad](http://hoptoadapp.com) from the guys over at
100 100  
101 101 **Configuring LDAP authentication:**
102 102  
103   - 1. Add the following line to Errbit's Gemfile:
  103 + 1. In `config/config.yml`, set `user_has_username` to `true`
  104 + 2. Follow the instructions at https://github.com/cschiewek/devise_ldap_authenticatable
  105 + to set up the devise_ldap_authenticatable gem.
104 106  
105   - gem "devise_ldap_authenticatable", :git => "git://github.com/cschiewek/devise_ldap_authenticatable.git"
  107 + 3. If you are authenticating by `username`, you will need to set the user's email
  108 + after authentication. You can do this by adding the following lines to `app/models/user.rb`:
106 109  
107   - 2. Install new dependencies
108   -
109   - bundle install
110   -
111   - 3. Run the rails generator for `devise_ldap_authenticatable`
112   -
113   - rails generate devise_ldap_authenticatable:install --advanced
114   -
115   - 4. Configure your LDAP settings in `config/initializers/devise.rb`.
116   -
117   - 5. If you want to authenticate via `username`, then add the following lines to `app/models/user.rb`:
118   -
119   - field :username
120   - before_save :set_ldap_email
121   - def set_ldap_email
122   - self.email = Devise::LdapAdapter.get_ldap_param(self.username, "mail")
123   - end
124   -
125   -To learn more, please follow the instructions at https://github.com/cschiewek/devise_ldap_authenticatable
  110 + before_save :set_ldap_email
  111 + def set_ldap_email
  112 + self.email = Devise::LdapAdapter.get_ldap_param(self.username, "mail")
  113 + end
126 114  
127 115  
128 116 Upgrading
129 117 ---------
130   -*Note*: If upgrading from a version of Errbit that used Notices embedded in Errs please run:
  118 +*Note*: When upgrading Errbit, please run:
131 119  
132 120 1. git pull origin master ( assuming origin is the github.com/jdpace/errbit repo )
133 121 2. rake db:migrate
134 122  
135   -Lighthouseapp integration
  123 +If we change the way that data is stored, this will run any migrations to bring your database up to date.
  124 +
  125 +
  126 +Lighthouseapp Integration
136 127 -------------------------
137 128  
138 129 * Account is the name of your subdomain, i.e. **litcafe** for project at http://litcafe.lighthouseapp.com/projects/73466-face/overview
139 130 * Errbit uses token-based authentication. Get your API Token or visit [http://help.lighthouseapp.com/kb/api/how-do-i-get-an-api-token](http://help.lighthouseapp.com/kb/api/how-do-i-get-an-api-token) to learn how to get it.
140 131 * Project id is number identifier of your project, i.e. **73466** for project at http://litcafe.lighthouseapp.com/projects/73466-face/overview
141 132  
142   -Redmine integration
  133 +Redmine Integration
143 134 -------------------------
144 135  
145 136 * Account is the host of your redmine installation, i.e. **http://redmine.org**
146 137 * Errbit uses token-based authentication. Get your API Key or visit [http://www.redmine.org/projects/redmine/wiki/Rest_api#Authentication](http://www.redmine.org/projects/redmine/wiki/Rest_api#Authentication) to learn how to get it.
147 138 * Project id is an identifier of your project, i.e. **chilliproject** for project at http://www.redmine.org/projects/chilliproject
148 139  
149   -Pivotal Tracker integration
  140 +Pivotal Tracker Integration
150 141 -------------------------
151 142  
152 143 * Errbit uses token-based authentication. Get your API Key or visit [http://www.pivotaltracker.com/help/api](http://www.pivotaltracker.com/help/api) to learn how to get it.
153 144 * Project id is an identifier of your project, i.e. **24324** for project at http://www.pivotaltracker.com/projects/24324
154 145  
  146 +Thoughtworks Mingle Integration
  147 +-------------------------------
  148 +
  149 +* Account is the host of your mingle installation. i.e. **https://mingle.example.com** *note*: You should use SSL if possible.
  150 +* Errbit uses 'sign-in name' & password authentication. You may want to set up an **errbit** user with limited rights.
  151 +* Project id is the identifier of your project, i.e. **awesomeapp** for project at https://mingle.example.com/projects/awesomeapp
  152 +* Card properties are comma separated key value pairs. You must specify a 'card_type', but anything else is optional. i.e. card_type = Defect, status = Open, priority = Essential
  153 +
  154 +
155 155 TODO
156 156 ----
157 157  
... ...
app/models/user.rb
... ... @@ -7,6 +7,7 @@ class User
7 7 :recoverable, :rememberable, :trackable,
8 8 :validatable, :token_authenticatable
9 9  
  10 + field :email
10 11 field :name
11 12 field :admin, :type => Boolean, :default => false
12 13 field :per_page, :type => Fixnum, :default => PER_PAGE
... ... @@ -18,6 +19,11 @@ class User
18 19  
19 20 attr_protected :admin
20 21  
  22 + if Errbit::Config.user_has_username
  23 + field :username
  24 + validates_presence_of :username
  25 + end
  26 +
21 27 # Mongoid doesn't seem to currently support
22 28 # referencing embedded documents
23 29 def watchers
... ... @@ -45,3 +51,4 @@ class User
45 51 watchers.each(&:destroy)
46 52 end
47 53 end
  54 +
... ...
app/views/errs/_table.html.haml
... ... @@ -15,7 +15,7 @@
15 15 - if current_page?(:controller => 'errs')
16 16 %span.environment= link_to err.environment, errs_path(environment: err.environment)
17 17 - else
18   - %span.environment= link_to err.environment, app_path(environment: err.environment)
  18 + %span.environment= link_to err.environment, app_path(err.app, environment: err.environment)
19 19 %td.message
20 20 = link_to err.message, app_err_path(err.app, err)
21 21 %em= err.where
... ...
app/views/users/_fields.html.haml
... ... @@ -3,7 +3,12 @@
3 3 .required
4 4 = f.label :name
5 5 = f.text_field :name
6   -
  6 +
  7 +- if Errbit::Config.user_has_username
  8 + .required
  9 + = f.label :username
  10 + = f.text_field :username
  11 +
7 12 .required
8 13 = f.label :email
9 14 = f.text_field :email
... ... @@ -11,11 +16,11 @@
11 16 .required
12 17 = f.label 'Entries per page'
13 18 = f.select :per_page, [10, 20, 30, 50, 75, 100]
14   -
  19 +
15 20 .required
16 21 = f.label :password
17 22 = f.password_field :password
18   -
  23 +
19 24 .required
20 25 = f.label :password_confirmation
21 26 = f.password_field :password_confirmation
... ... @@ -23,4 +28,5 @@
23 28 - if current_user.admin?
24 29 .checkbox
25 30 = f.check_box :admin
26   - = f.label :admin, 'Admin?'
27 31 \ No newline at end of file
  32 + = f.label :admin, 'Admin?'
  33 +
... ...
app/views/users/index.html.haml
... ... @@ -6,13 +6,17 @@
6 6 %thead
7 7 %tr
8 8 %th Name
  9 + - if Errbit::Config.user_has_username
  10 + %th Username
9 11 %th.main Email
10 12 %th Admin?
11 13 %tbody
12 14 - @users.each do |user|
13 15 %tr
14 16 %td.nowrap= link_to user.name, user_path(user)
  17 + - if Errbit::Config.user_has_username
  18 + %td= user.username
15 19 %td= user.email
16 20 %td= user.admin? ? 'Y' : 'N'
17 21 = will_paginate @users, :previous_label => '« Previous', :next_label => 'Next »'
18   -
19 22 \ No newline at end of file
  23 +
... ...
app/views/users/show.html.haml
1 1 - content_for :title, @user.name
2 2 - content_for :action_bar do
  3 + %span= link_to('Add a New User', new_user_path, :class => 'add')
3 4 = link_to 'edit', edit_user_path(@user), :class => 'button'
4 5 = link_to 'destroy', user_path(@user), :method => :delete, :confirm => 'Seriously?', :class => 'button'
5 6  
... ... @@ -7,9 +8,14 @@
7 8 %tr
8 9 %th Email
9 10 %td.main= @user.email
  11 + - if Errbit::Config.user_has_username
  12 + %tr
  13 + %th Username
  14 + %td.main= @user.username
10 15 %tr
11 16 %th Admin?
12 17 %td= @user.admin? ? 'Y' : 'N'
13 18 %tr
14 19 %th Created
15   - %td= @user.created_at.to_s(:micro)
16 20 \ No newline at end of file
  21 + %td= @user.created_at.to_s(:micro)
  22 +
... ...
config/config.example.yml
... ... @@ -6,6 +6,7 @@
6 6 # be copied to shared/config on the server when
7 7 # `cap deploy:setup` is ran the first time. Be sure
8 8 # to place production specific settings there
  9 +# You will need to restart the server after changing any settings.
9 10  
10 11 # The host of your errbit server
11 12 host: errbit.example.com
... ... @@ -14,8 +15,8 @@ host: errbit.example.com
14 15 # will be sent from.
15 16 email_from: errbit@example.com
16 17  
17   -# if you turn on this option, email_at_notices will be configured on per app basis
18   -# at App edit page
  18 +# If you turn on this option, email_at_notices can be
  19 +# configured on a per app basis, at the App edit page
19 20 per_app_email_at_notices: false
20 21  
21 22 # Configure when emails are sent for an error.
... ... @@ -23,4 +24,10 @@ per_app_email_at_notices: false
23 24 # an email notification.
24 25 email_at_notices: [1, 10, 100]
25 26  
  27 +# Configure whether or not the user should be prompted before resolving an error.
26 28 confirm_resolve_err: true
  29 +
  30 +# Add an optional 'username' field to Users.
  31 +# Helpful if you want to plug in your own authentication strategy.
  32 +user_has_username: false
  33 +
... ...
config/initializers/_load_config.rb
... ... @@ -14,7 +14,8 @@ if ENV['HEROKU']
14 14 :domain => ENV['SENDGRID_DOMAIN']
15 15 }
16 16 else
17   - yaml = File.read(Rails.root.join('config','config.yml'))
  17 + config_file = Rails.env == "test" ? "config.example.yml" : "config.yml"
  18 + yaml = File.read(Rails.root.join('config', config_file))
18 19 config = YAML.load(yaml)
19 20  
20 21 config.merge!(config.delete(Rails.env)) if config.has_key?(Rails.env)
... ...
config/initializers/devise.rb
... ... @@ -20,7 +20,7 @@ Devise.setup do |config|
20 20 # authenticating an user, both parameters are required. Remember that those
21 21 # parameters are used only when authenticating and not when retrieving from
22 22 # session. If you need permissions, you should implement that in a before filter.
23   - # config.authentication_keys = [ :email ]
  23 + config.authentication_keys = [ Errbit::Config.user_has_username ? :username : :email ]
24 24  
25 25 # Tell if authentication through request.params is enabled. True by default.
26 26 # config.params_authenticatable = true
... ... @@ -140,3 +140,4 @@ Devise.setup do |config|
140 140 # manager.default_strategies(:scope => :user).unshift :twitter_oauth
141 141 # end
142 142 end
  143 +
... ...
config/initializers/overrides.rb
1 1 require Rails.root.join('lib/overrides/mongoid/relations/builder.rb')
  2 +require Rails.root.join('lib/overrides/devise/failure_app.rb')
  3 +
... ...
config/initializers/secret_token.rb
... ... @@ -4,4 +4,5 @@
4 4 # If you change this key, all old signed cookies will become invalid!
5 5 # Make sure the secret is at least 30 characters and all random,
6 6 # no regular words or you'll be exposed to dictionary attacks.
7   -Errbit::Application.config.secret_token = '41f6b3871b375769786c379a3e542d67a7a234926f926778ed634f40a9480ba6d7b0768993e9852aafcaa73d6b8ddd2ed3b46208b92305e8c21936574f74a9a4'
  7 +Errbit::Application.config.secret_token = '6b74778101638fa9c156b3928c9492fb2481ab842538bea838d21f9c9993f649f5806449584266d413d0b2f1104162b3066a86512ed71ededd627cd41f939614'
  8 +
... ...
config/locales/devise.en.yml
... ... @@ -10,7 +10,10 @@ en:
10 10 unauthenticated: 'You need to sign in before continuing.'
11 11 unconfirmed: 'You have to confirm your account before continuing.'
12 12 locked: 'Your account is locked.'
13   - invalid: 'Invalid email or password.'
  13 + invalid: 'Invalid login details.'
  14 + user:
  15 + email_invalid: 'Invalid email or password.'
  16 + username_invalid: 'Invalid username or password.'
14 17 invalid_token: 'Invalid authentication token.'
15 18 timeout: 'Your session expired, please sign in again to continue.'
16 19 inactive: 'Your account was not activated yet.'
... ... @@ -37,3 +40,4 @@ en:
37 40 subject: 'Reset password instructions'
38 41 unlock_instructions:
39 42 subject: 'Unlock Instructions'
  43 +
... ...
db/seeds.rb
... ... @@ -2,10 +2,12 @@ puts "Seeding database"
2 2 puts "-------------------------------"
3 3  
4 4 # Create an initial Admin User
  5 +admin_username = "errbit"
5 6 admin_email = "errbit@#{Errbit::Config.host}"
6 7 admin_pass = 'password'
7 8  
8 9 puts "Creating an initial admin user:"
  10 +puts "-- username: #{admin_username}" if Errbit::Config.user_has_username
9 11 puts "-- email: #{admin_email}"
10 12 puts "-- password: #{admin_pass}"
11 13 puts ""
... ... @@ -16,6 +18,8 @@ user = User.where(:email => admin_email).first || User.new({
16 18 :password => admin_pass,
17 19 :password_confirmation => admin_pass
18 20 })
  21 +user.username = admin_username if Errbit::Config.user_has_username
19 22  
20 23 user.admin = true
21 24 user.save!
  25 +
... ...
lib/overrides/devise/failure_app.rb 0 → 100644
... ... @@ -0,0 +1,15 @@
  1 +Devise::FailureApp.class_eval do
  2 + protected
  3 + # Handles both 'email_invalid' and 'username_invalid' messages.
  4 + def i18n_message(default = nil)
  5 + message = warden.message || warden_options[:message] || default || :unauthenticated
  6 +
  7 + if message.is_a?(Symbol)
  8 + I18n.t(:"#{scope}.#{Devise.authentication_keys.first}_#{message}", :resource_name => scope,
  9 + :scope => "devise.failure", :default => [message, message.to_s])
  10 + else
  11 + message.to_s
  12 + end
  13 + end
  14 +end
  15 +
... ...
public/javascripts/form.js
... ... @@ -66,12 +66,16 @@ function removeNestedItem() {
66 66  
67 67  
68 68 function activateTypeSelector(field_class, section_class) {
69   - section_class = section_class || field_class+"_params"; // section_class can be deduced if not given
  69 + var section_class = section_class || field_class+"_params"; // section_class can be deduced if not given
  70 + // disable all inactive tabs to avoid sending its values on server
  71 + $('div.'+field_class+' > div.'+section_class).not('.chosen').find('input')
  72 + .attr('disabled','disabled').val('');
  73 +
70 74 $('div.'+field_class+' input[name*='+field_class+'_type]').live('click', function(){
71 75 var chosen = $(this).val();
72 76 var wrapper = $(this).closest('.nested');
73   - wrapper.find('div.chosen.'+section_class).removeClass('chosen');
74   - wrapper.find('div.'+section_class+'.'+chosen).addClass('chosen');
  77 + wrapper.find('div.chosen.'+section_class).removeClass('chosen').find('input').attr('disabled','disabled');
  78 + wrapper.find('div.'+section_class+'.'+chosen).addClass('chosen').find('input').removeAttr('disabled');
75 79 });
76 80 }
77 81  
... ...
public/javascripts/notifier.js
... ... @@ -6,7 +6,7 @@ var Errbit = {
6 6 <notifier>\
7 7 <name>errbit_notifier_js</name>\
8 8 <version>2.0</version>\
9   - <url>http://NOTIFIER_HOST</url>\
  9 + <url>https://github.com/jdpace/errbit</url>\
10 10 </notifier>\
11 11 <error>\
12 12 <class>EXCEPTION_CLASS</class>\
... ... @@ -30,7 +30,7 @@ var Errbit = {
30 30 notify: function(error) {
31 31 var xml = escape(Errbit.generateXML(error));
32 32 var host = Errbit.host || 'github.com/jdpace/errbit';
33   - var url = '//' + host + '/notifier_api/v2/notices?data=' + xml;
  33 + var url = '//' + host + '/notifier_api/v2/notices.xml?data=' + xml;
34 34 var request = document.createElement('iframe');
35 35  
36 36 request.style.width = '1px';
... ... @@ -103,7 +103,6 @@ var Errbit = {
103 103 }
104 104  
105 105 xml = xml.replace('</request>', data + '</request>')
106   - .replace('NOTIFIER_HOST', host)
107 106 .replace('REQUEST_URL', url)
108 107 .replace('REQUEST_ACTION', action)
109 108 .replace('REQUEST_COMPONENT', component);
... ...