diff --git a/app/controllers/user_sessions_controller.rb b/app/controllers/user_sessions_controller.rb index 7f9ccdeb4f..c819e26695 100644 --- a/app/controllers/user_sessions_controller.rb +++ b/app/controllers/user_sessions_controller.rb @@ -66,75 +66,82 @@ def create end end else - params[:user_session][:username] = params[:openid] if params[:openid] # second runthrough must preserve username username = params[:user_session][:username] if params[:user_session] - @user = User.find_by(username: username) - - # try finding by email, if that exists - if @user.nil? && !User.where(email: username).empty? - @user = User.find_by(email: username) - params[:user_session][:username] = @user.username - end - - if @user.nil? - flash[:warning] = "There is nobody in our system by that name, are you sure you have the right username?" - redirect_to '/login' - elsif params[:user_session].nil? || @user&.drupal_user&.status == 1 - # an existing Rails user - if params[:user_session].nil? || @user - if @user&.crypted_password.nil? # the user has not created a pwd in the new site - params[:user_session][:openid_identifier] = 'https://old.publiclab.org/people/' + username + '/identity' if username - params[:user_session].delete(:password) - params[:user_session].delete(:username) - params[:openid] = username # pack up username for second runthrough - end - @user_session = UserSession.new(username: params[:user_session][:username], - password: params[:user_session][:password], - remember_me: params[:user_session][:remember_me]) - saved = @user_session.save do |result| - if result - # replace this with temporarily saving pwd in session, - # and automatically saving it in the user record after login is completed - if current_user.crypted_password.nil? # the user has not created a pwd in the new site - flash[:warning] = I18n.t('user_sessions_controller.create_password_for_new_site') - redirect_to '/profile/edit' - else - flash[:notice] = I18n.t('user_sessions_controller.logged_in') - if session[:openid_return_to] # for openid login, redirects back to openid auth process - return_to = session[:openid_return_to] - session[:openid_return_to] = nil - redirect_to return_to - elsif session[:return_to] - return_to = session[:return_to] - session[:return_to] = nil - redirect_to return_to - elsif params[:return_to] - redirect_to params[:return_to] + u = User.find_by(username: username) + if u && u.password_checker != 0 + n = u.password_checker + hash = { 1 => "Facebook", 2 => "Github", 3 => "Google", 4 => "Twitter" } + s = "This account doesn't have a password set. It may be logged in with " + hash[n] + " account, or you can set a new password via Forget password feature" + flash[:error] = s + redirect_to '/' + else + params[:user_session][:username] = params[:openid] if params[:openid] # second runthrough must preserve username + @user = User.find_by(username: username) + # try finding by email, if that exists + if @user.nil? && !User.where(email: username).empty? + @user = User.find_by(email: username) + params[:user_session][:username] = @user.username + end + if @user.nil? + flash[:warning] = "There is nobody in our system by that name, are you sure you have the right username?" + redirect_to '/login' + elsif params[:user_session].nil? || @user&.drupal_user&.status == 1 + # an existing Rails user + if params[:user_session].nil? || @user + if @user&.crypted_password.nil? # the user has not created a pwd in the new site + params[:user_session][:openid_identifier] = 'https://old.publiclab.org/people/' + username + '/identity' if username + params[:user_session].delete(:password) + params[:user_session].delete(:username) + params[:openid] = username # pack up username for second runthrough + end + @user_session = UserSession.new(username: params[:user_session][:username], + password: params[:user_session][:password], + remember_me: params[:user_session][:remember_me]) + saved = @user_session.save do |result| + if result + # replace this with temporarily saving pwd in session, + # and automatically saving it in the user record after login is completed + if current_user.crypted_password.nil? # the user has not created a pwd in the new site + flash[:warning] = I18n.t('user_sessions_controller.create_password_for_new_site') + redirect_to '/profile/edit' else - redirect_to '/dashboard' + flash[:notice] = I18n.t('user_sessions_controller.logged_in') + if session[:openid_return_to] # for openid login, redirects back to openid auth process + return_to = session[:openid_return_to] + session[:openid_return_to] = nil + redirect_to return_to + elsif session[:return_to] + return_to = session[:return_to] + session[:return_to] = nil + redirect_to return_to + elsif params[:return_to] + redirect_to params[:return_to] + else + redirect_to '/dashboard' + end end + else + # Login failed; probably bad password. + # Errors will display on login form: + render action: 'new' end - else - # Login failed; probably bad password. - # Errors will display on login form: - render action: 'new' + end + else # not a native user + if !DrupalUser.find_by(name: username).nil? + # this is a user from the old site who hasn't registered on the new site + redirect_to controller: :users, action: :create, user: { openid_identifier: username } + else # totally new user! + flash[:warning] = I18n.t('user_sessions_controller.sign_up_to_join') + redirect_to '/signup' end end - else # not a native user - if !DrupalUser.find_by(name: username).nil? - # this is a user from the old site who hasn't registered on the new site - redirect_to controller: :users, action: :create, user: { openid_identifier: username } - else # totally new user! - flash[:warning] = I18n.t('user_sessions_controller.sign_up_to_join') - redirect_to '/signup' - end + elsif params[:user_session].nil? || @user&.drupal_user&.status == 5 + flash[:error] = I18n.t('user_sessions_controller.user_has_been_moderated', username: @user.username).html_safe + redirect_to '/' + else + flash[:error] = I18n.t('user_sessions_controller.user_has_been_banned', username: @user.username).html_safe + redirect_to '/' end - elsif params[:user_session].nil? || @user&.drupal_user&.status == 5 - flash[:error] = I18n.t('user_sessions_controller.user_has_been_moderated', username: @user.username).html_safe - redirect_to '/' - else - flash[:error] = I18n.t('user_sessions_controller.user_has_been_banned', username: @user.username).html_safe - redirect_to '/' end end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 8b0e0cf4e8..7dec61e241 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -227,6 +227,7 @@ def reset @user.reset_key = nil if @user.changed? && @user.save({}) flash[:notice] = I18n.t('users_controller.password_change_success') + @user.password_checker = 0 redirect_to "/dashboard" else flash[:error] = I18n.t('users_controller.password_reset_failed').html_safe diff --git a/app/models/user.rb b/app/models/user.rb index 893e9d2694..1c4980cc85 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -435,12 +435,14 @@ def self.create_with_omniauth(auth) charset = Array('A'..'Z') + Array('a'..'z') + Array(0..9) email_prefix = auth["info"]["email"].tr('.', '_').split('@')[0] email_prefix = auth["info"]["email"].tr('.', '_').split('@')[0] + Array.new(2) { charset.sample }.join until User.where(username: email_prefix).empty? + hash = { "facebook" => 1, "github" => 2, "google_oauth2" => 3, "twitter" => 4 } create! do |user| s = SecureRandom.urlsafe_base64 user.username = email_prefix user.email = auth["info"]["email"] user.password = s user.password_confirmation = s + user.password_checker = hash[auth["provider"]] user.save! end end diff --git a/db/migrate/20180801144533_add_password_checker_to_rusers_and_remove_password_checker_from_users.rb b/db/migrate/20180801144533_add_password_checker_to_rusers_and_remove_password_checker_from_users.rb new file mode 100644 index 0000000000..96b09b4950 --- /dev/null +++ b/db/migrate/20180801144533_add_password_checker_to_rusers_and_remove_password_checker_from_users.rb @@ -0,0 +1,6 @@ +class AddPasswordCheckerToRusersAndRemovePasswordCheckerFromUsers < ActiveRecord::Migration[5.2] + def change + remove_column :users, :password_checker, :integer + add_column :rusers, :password_checker, :integer, default: 0 + end +end diff --git a/db/schema.rb.example b/db/schema.rb.example index 1084e8e7df..d091fecabf 100644 --- a/db/schema.rb.example +++ b/db/schema.rb.example @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2018_07_21_102347) do +ActiveRecord::Schema.define(version: 2018_08_01_144533) do create_table "answer_selections", force: true do |t| t.integer "user_id" @@ -355,6 +355,7 @@ ActiveRecord::Schema.define(version: 2018_07_21_102347) do t.text "bio", limit: 2147483647 t.string "token" t.integer "status", default: 0 + t.integer "password_checker", default: 0 end add_index "rusers", ["created_at"], name: "index_rusers_created_at", using: :btree @@ -446,7 +447,6 @@ ActiveRecord::Schema.define(version: 2018_07_21_102347) do t.string "timezone_name", limit: 50, default: "", null: false t.decimal "lat", precision: 20, scale: 10, default: 0.0 t.decimal "lon", precision: 20, scale: 10, default: 0.0 - t.integer "password_checker", default: 0 end add_index "users", ["access"], name: "index_users_access", using: :btree diff --git a/doc/Omniauth.md b/doc/Omniauth.md index 5335f6d2cb..562bfe382e 100644 --- a/doc/Omniauth.md +++ b/doc/Omniauth.md @@ -85,3 +85,16 @@ OmniAuth.config.mock_auth[:provider] = OmniAuth::AuthHash.new({ This is a way of storing the hash returned by the OAuth service. Tester can then use these values by ``request.env['omniauth.auth'] = OmniAuth.config.mock_auth[:google_oauth2_2]`` + +## Notifications + +Let us define the password_checker field for authentication system +A user creates an account by the legacy authentication system 0 +Facebook 1 +Github 2 +Google 3 +Twitter 4 + +Password is set up by the client is denoted by zero. Password not set up is denoted by non zero field. +If a user who is not having password field set up tries to log in with password and username then they will be noticed with an error message to reset their password. +Upon setting up password, password_checker field is set to zero. diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb index 6118990774..4593904beb 100644 --- a/test/unit/user_test.rb +++ b/test/unit/user_test.rb @@ -212,10 +212,11 @@ class UserTest < ActiveSupport::TestCase end test 'create a user with omniauth if email prefix does exist in db' do - auth = {"uid" => "98740858591", "info" => { "email" => "jeff@gmail.com"}} + auth = {"uid" => "98740858591", "info" => { "email" => "jeff@gmail.com"},"provider"=>"facebook"} jeffrey = User.create_with_omniauth(auth) assert_not_nil jeffrey assert_equal jeffrey.email, "jeff@gmail.com" + assert_equal jeffrey.password_checker, 1 #as the username as "jeff" exists, hence username = "jeff" + 2 digit alphanumeric code will be created assert_not_equal jeffrey.username, "jeff" end