Commit a3fb360ceee40b08d9bd3e753bbe605de1bc411b
Exists in
master
and in
1 other branch
Merge branch 'master' of github.com:fxposter/errbit
Showing
16 changed files
with
105 additions
and
44 deletions
Show diff stats
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
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 | + | ... | ... |
| ... | ... | @@ -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); | ... | ... |