diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 403f5f8d..adaa08b6 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -16,6 +16,7 @@ class ApplicationController < ActionController::Base layout proc{ |controller| controller.mobile? ? "mobile" : "standard" } exempt_from_layout /\.js\.erb$/ + before_filter :check_for_deprecated_password_hash before_filter :set_session_expiration before_filter :set_time_zone before_filter :set_zindex_counter @@ -58,6 +59,15 @@ class ApplicationController < ActionController::Base end end end + + # Redirects to change_password_user_path if the current user uses a + # deprecated password hashing algorithm. + def check_for_deprecated_password_hash + if current_user and current_user.uses_deprecated_password? + notify :warning, t('users.you_have_to_reset_your_password') + redirect_to change_password_user_path current_user + end + end def render_failure message, status = 404 render :text => message, :status => status diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 470af029..4cf60081 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,6 +1,8 @@ class UsersController < ApplicationController before_filter :admin_login_required, :only => [ :index, :show, :destroy ] skip_before_filter :login_required, :only => [ :new, :create ] + skip_before_filter :check_for_deprecated_password_hash, + :only => [ :change_password ] prepend_before_filter :login_optional, :only => [ :new, :create ] # GET /users GET /users.xml diff --git a/config/locales/en.yml b/config/locales/en.yml index 2d75abcb..475d3710 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -778,6 +778,7 @@ en: register_with_cas: With your CAS username label_auth_type: Authentication type new_password_label: New password + you_have_to_reset_your_password: "You have to reset your password" new_user_title: TRACKS::Sign up as the admin user destroy_user: Destroy user total_users_count: You have a total of %{count} users diff --git a/features/handling_users_with_deprecated_password_hashes.feature b/features/handling_users_with_deprecated_password_hashes.feature new file mode 100644 index 00000000..388a3729 --- /dev/null +++ b/features/handling_users_with_deprecated_password_hashes.feature @@ -0,0 +1,21 @@ +Feature: Handling users with deprecated passwords hashes + In order to have my password hashed with BCrypt + As a user with password hashed with SHA1 + I have to be redirected to the password resetting form + + Background: + Given the following user records + | login | password_with_algorithm | + | new_hash_user | first_secret bcrypt | + | old_hash_user | another_secret sha1 | + + Scenario: A user with SHA1 password + Given I have logged in as "old_hash_user" with password "another_secret" + When I go to the homepage + Then I should be redirected to the change password page + And I should see "You have to reset your password" + + Scenario: A user with BCrypt password + Given I have logged in as "new_hash_user" with password "first_secret" + When I go to the homepage + Then I should be on the homepage diff --git a/features/support/paths.rb b/features/support/paths.rb index 52b32975..65579a71 100644 --- a/features/support/paths.rb +++ b/features/support/paths.rb @@ -104,6 +104,8 @@ module NavigationHelpers when /the tag page for "([^"]*)"/i @source_view = "tag" tag_path($1, options) + when /the change password page/ + change_password_user_path @current_user # Add more mappings here. # Here is an example that pulls values out of the Regexp: diff --git a/features/support/user.rb b/features/support/user.rb new file mode 100644 index 00000000..e40d3e89 --- /dev/null +++ b/features/support/user.rb @@ -0,0 +1,18 @@ +class User + # A method used in features' user records definitions. It accepts a string + # with a password and the name of a hashing algorithm ('sha1' or 'bcrypt') + # concatenated with a space. It encrypts user's password using the given + # mechanism and the given password value. + def password_with_algorithm=(x) + pass, algorithm = *x.split + case algorithm + when 'bcrypt' + change_password pass, pass + when 'sha1' + self.crypted_password = User.sha1 pass + self.password = self.password_confirmation = nil + else + raise "Unknown hashing algorithm: #{algorithm}" + end + end +end