From fc0ffda8ec7950d36a9fc765753bcfc3f414ba38 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Fri, 5 Apr 2019 13:08:13 +0100 Subject: [PATCH 01/36] Bring routes and controllers from spree_auth_devise --- Gemfile | 2 +- Gemfile.lock | 26 ++-- .../spree/admin/base_controller_decorator.rb | 10 ++ .../customer_details_controller_decorator.rb | 12 ++ .../admin/resource_controller_decorator.rb | 4 + .../spree/admin/users_controller.rb | 124 ++++++++++++++++++ .../spree/base_controller_decorator.rb | 18 +++ app/controllers/spree/checkout_controller.rb | 44 +++++++ .../spree/user_passwords_controller.rb | 47 +++++++ .../spree/user_registrations_controller.rb | 67 ++++++++++ .../spree/user_sessions_controller.rb | 56 ++++++++ app/controllers/spree/users_controller.rb | 57 ++++++++ config/routes/spree.rb | 29 ++++ 13 files changed, 482 insertions(+), 14 deletions(-) create mode 100644 app/controllers/spree/admin/users_controller.rb create mode 100644 app/controllers/spree/base_controller_decorator.rb create mode 100644 app/controllers/spree/user_passwords_controller.rb create mode 100644 app/controllers/spree/user_registrations_controller.rb create mode 100644 app/controllers/spree/user_sessions_controller.rb create mode 100644 app/controllers/spree/users_controller.rb diff --git a/Gemfile b/Gemfile index 871a08794c..6cbec48c6b 100644 --- a/Gemfile +++ b/Gemfile @@ -24,7 +24,7 @@ gem 'spree_api', github: 'openfoodfoundation/spree', branch: '2-0-4-stable' gem 'spree_backend', github: 'openfoodfoundation/spree', branch: '2-0-4-stable' gem 'spree_core', github: 'openfoodfoundation/spree', branch: '2-0-4-stable' -gem 'spree_auth_devise', github: 'spree/spree_auth_devise', branch: '2-0-stable' +gem 'spree_auth_devise', github: 'luisramos0/spree_auth_devise', branch: '2-0-without-ctrls' gem 'spree_i18n', github: 'spree/spree_i18n', branch: '1-3-stable' # Our branch contains two changes diff --git a/Gemfile.lock b/Gemfile.lock index 890c8bdf5b..5dc405918e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -12,6 +12,18 @@ GIT specs: custom_error_message (1.1.1) +GIT + remote: https://github.com/luisramos0/spree_auth_devise.git + revision: 562ac6b0b821173f36405457ccfad103e9c5dc6a + branch: 2-0-without-ctrls + specs: + spree_auth_devise (2.0.0) + devise (~> 2.2.5) + devise-encryptable (= 0.1.2) + spree_backend (~> 2.0.0) + spree_core (~> 2.0.0) + spree_frontend (~> 2.0.0) + GIT remote: https://github.com/openfoodfoundation/better_spree_paypal_express.git revision: 27ad7165ea4c6e8c5f120b42b676cb9c2c272100 @@ -75,18 +87,6 @@ GIT spree_core (= 2.0.4) stringex (~> 1.5.1) -GIT - remote: https://github.com/spree/spree_auth_devise.git - revision: 0181835fb6ac77a05191d26f6f32a0f4a548d851 - branch: 2-0-stable - specs: - spree_auth_devise (2.0.0) - devise (~> 2.2.5) - devise-encryptable (= 0.1.2) - spree_backend (~> 2.0.0) - spree_core (~> 2.0.0) - spree_frontend (~> 2.0.0) - GIT remote: https://github.com/spree/spree_i18n.git revision: 752eb67204e9c5a4e22b62591a8fd55fe2285e43 @@ -180,7 +180,7 @@ GEM json (~> 1.4) nokogiri (>= 1.4.4) uuidtools (~> 2.1) - bcrypt (3.1.11) + bcrypt (3.1.12) bcrypt-ruby (3.1.5) bcrypt (>= 3.1.3) blockenspiel (0.5.0) diff --git a/app/controllers/spree/admin/base_controller_decorator.rb b/app/controllers/spree/admin/base_controller_decorator.rb index 6bdd57f0e8..941b679c59 100644 --- a/app/controllers/spree/admin/base_controller_decorator.rb +++ b/app/controllers/spree/admin/base_controller_decorator.rb @@ -47,6 +47,16 @@ Spree::Admin::BaseController.class_eval do end end + protected + + def model_class + const_name = controller_name.classify + if Spree.const_defined?(const_name) + return "Spree::#{const_name}".constantize + end + nil + end + private def active_distributors_not_ready_for_checkout diff --git a/app/controllers/spree/admin/orders/customer_details_controller_decorator.rb b/app/controllers/spree/admin/orders/customer_details_controller_decorator.rb index 41a3d721b1..47e829d3cb 100644 --- a/app/controllers/spree/admin/orders/customer_details_controller_decorator.rb +++ b/app/controllers/spree/admin/orders/customer_details_controller_decorator.rb @@ -1,4 +1,5 @@ Spree::Admin::Orders::CustomerDetailsController.class_eval do + before_filter :check_authorization before_filter :set_guest_checkout_status, only: :update def update @@ -25,6 +26,17 @@ Spree::Admin::Orders::CustomerDetailsController.class_eval do private + def check_authorization + load_order + session[:access_token] ||= params[:token] + + resource = @order + action = params[:action].to_sym + action = :edit if action == :show # show route renders :edit for this controller + + authorize! action, resource, session[:access_token] + end + def set_guest_checkout_status registered_user = Spree::User.find_by_email(params[:order][:email]) diff --git a/app/controllers/spree/admin/resource_controller_decorator.rb b/app/controllers/spree/admin/resource_controller_decorator.rb index 19293545ec..e7ba7ceb5b 100644 --- a/app/controllers/spree/admin/resource_controller_decorator.rb +++ b/app/controllers/spree/admin/resource_controller_decorator.rb @@ -14,3 +14,7 @@ module AuthorizeOnLoadResource end Spree::Admin::ResourceController.prepend(AuthorizeOnLoadResource) + +Spree::Admin::ResourceController.class_eval do + rescue_from CanCan::AccessDenied, :with => :unauthorized +end diff --git a/app/controllers/spree/admin/users_controller.rb b/app/controllers/spree/admin/users_controller.rb new file mode 100644 index 0000000000..9ecaff2845 --- /dev/null +++ b/app/controllers/spree/admin/users_controller.rb @@ -0,0 +1,124 @@ +module Spree + module Admin + class UsersController < ResourceController + rescue_from Spree::User::DestroyWithOrdersError, :with => :user_destroy_with_orders_error + + after_filter :sign_in_if_change_own_password, :only => :update + + # http://spreecommerce.com/blog/2010/11/02/json-hijacking-vulnerability/ + before_filter :check_json_authenticity, :only => :index + before_filter :load_roles, :only => [:edit, :new, :update, :create, :generate_api_key, :clear_api_key] + + def index + respond_with(@collection) do |format| + format.html + format.json { render :json => json_data } + end + end + + def create + if params[:user] + roles = params[:user].delete("spree_role_ids") + end + + @user = Spree::User.new(params[:user]) + if @user.save + + if roles + @user.spree_roles = roles.reject(&:blank?).collect{|r| Spree::Role.find(r)} + end + + flash.now[:success] = Spree.t(:created_successfully) + render :edit + else + render :new + end + end + + def update + if params[:user] + roles = params[:user].delete("spree_role_ids") + end + + if @user.update_attributes(params[:user]) + if roles + @user.spree_roles = roles.reject(&:blank?).collect{|r| Spree::Role.find(r)} + end + + flash.now[:success] = Spree.t(:account_updated) + render :edit + else + render :edit + end + end + + def generate_api_key + if @user.generate_spree_api_key! + flash[:success] = Spree.t('api.key_generated') + end + redirect_to edit_admin_user_path(@user) + end + + def clear_api_key + if @user.clear_spree_api_key! + flash[:success] = Spree.t('api.key_cleared') + end + redirect_to edit_admin_user_path(@user) + end + + protected + + def collection + return @collection if @collection.present? + if request.xhr? && params[:q].present? + #disabling proper nested include here due to rails 3.1 bug + #@collection = User.includes(:bill_address => [:state, :country], :ship_address => [:state, :country]). + @collection = Spree::User.includes(:bill_address, :ship_address) + .where("spree_users.email #{LIKE} :search + OR (spree_addresses.firstname #{LIKE} :search AND spree_addresses.id = spree_users.bill_address_id) + OR (spree_addresses.lastname #{LIKE} :search AND spree_addresses.id = spree_users.bill_address_id) + OR (spree_addresses.firstname #{LIKE} :search AND spree_addresses.id = spree_users.ship_address_id) + OR (spree_addresses.lastname #{LIKE} :search AND spree_addresses.id = spree_users.ship_address_id)", + { :search => "#{params[:q].strip}%" }) + .limit(params[:limit] || 100) + else + @search = Spree::User.registered.ransack(params[:q]) + @collection = @search.result.page(params[:page]).per(Spree::Config[:admin_products_per_page]) + end + end + + private + + # handling raise from Spree::Admin::ResourceController#destroy + def user_destroy_with_orders_error + invoke_callbacks(:destroy, :fails) + render :status => :forbidden, :text => Spree.t(:error_user_destroy_with_orders) + end + + # Allow different formats of json data to suit different ajax calls + def json_data + json_format = params[:json_format] or 'default' + case json_format + when 'basic' + collection.map { |u| { 'id' => u.id, 'name' => u.email } }.to_json + else + address_fields = [:firstname, :lastname, :address1, :address2, :city, :zipcode, :phone, :state_name, :state_id, :country_id] + includes = { :only => address_fields , :include => { :state => { :only => :name }, :country => { :only => :name } } } + + collection.to_json(:only => [:id, :email], :include => + { :bill_address => includes, :ship_address => includes }) + end + end + + def sign_in_if_change_own_password + if spree_current_user == @user && @user.password.present? + sign_in(@user, :event => :authentication, :bypass => true) + end + end + + def load_roles + @roles = Spree::Role.scoped + end + end + end +end diff --git a/app/controllers/spree/base_controller_decorator.rb b/app/controllers/spree/base_controller_decorator.rb new file mode 100644 index 0000000000..f907c70105 --- /dev/null +++ b/app/controllers/spree/base_controller_decorator.rb @@ -0,0 +1,18 @@ +Spree::BaseController.class_eval do + def spree_login_path + spree.login_path + end + + def spree_signup_path + spree.signup_path + end + + def spree_logout_path + spree.destroy_spree_user_session_path + end + + def spree_current_user + current_spree_user + end +end + diff --git a/app/controllers/spree/checkout_controller.rb b/app/controllers/spree/checkout_controller.rb index a01750072f..b75418f179 100644 --- a/app/controllers/spree/checkout_controller.rb +++ b/app/controllers/spree/checkout_controller.rb @@ -25,8 +25,52 @@ module Spree redirect_to main_app.checkout_path end + before_filter :check_registration, :except => [:registration, :update_registration] + + helper 'spree/users' + + def registration + @user = Spree::User.new + end + + def update_registration + fire_event("spree.user.signup", :order => current_order) + # hack - temporarily change the state to something other than cart so we can validate the order email address + current_order.state = current_order.checkout_steps.first + current_order.update_attribute(:email, params[:order][:email]) + # Run validations, then check for errors + # valid? may return false if the address state validations are present + current_order.valid? + if current_order.errors[:email].blank? + redirect_to checkout_path + else + flash[:registration_error] = t(:email_is_invalid, :scope => [:errors, :messages]) + @user = Spree::User.new + render 'registration' + end + end + private + def skip_state_validation? + %w(registration update_registration).include?(params[:action]) + end + + # Introduces a registration step whenever the +registration_step+ preference is true. + def check_registration + return unless Spree::Auth::Config[:registration_step] + return if spree_current_user or current_order.email + store_location + redirect_to spree.checkout_registration_path + end + + # Overrides the equivalent method defined in Spree::Core. This variation of the method will ensure that users + # are redirected to the tokenized order url unless authenticated as a registered user. + def completion_route + return order_path(@order) if spree_current_user + spree.token_order_path(@order, @order.token) + end + def load_order @order = current_order redirect_to main_app.cart_path && return unless @order diff --git a/app/controllers/spree/user_passwords_controller.rb b/app/controllers/spree/user_passwords_controller.rb new file mode 100644 index 0000000000..f18570a4fd --- /dev/null +++ b/app/controllers/spree/user_passwords_controller.rb @@ -0,0 +1,47 @@ +class Spree::UserPasswordsController < Devise::PasswordsController + helper 'spree/users', 'spree/base', 'spree/store' + + if defined?(Spree::Dash) + helper 'spree/analytics' + end + + include Spree::Core::ControllerHelpers::Auth + include Spree::Core::ControllerHelpers::Common + include Spree::Core::ControllerHelpers::Order + include Spree::Core::ControllerHelpers::SSL + + ssl_required + + # Overridden due to bug in Devise. + # respond_with resource, :location => new_session_path(resource_name) + # is generating bad url /session/new.user + # + # overridden to: + # respond_with resource, :location => spree.login_path + # + def create + self.resource = resource_class.send_reset_password_instructions(params[resource_name]) + + if resource.errors.empty? + set_flash_message(:notice, :send_instructions) if is_navigational_format? + respond_with resource, :location => spree.login_path + else + respond_with_navigational(resource) { render :new } + end + end + + # Devise::PasswordsController allows for blank passwords. + # Silly Devise::PasswordsController! + # Fixes spree/spree#2190. + def update + if params[:spree_user][:password].blank? + self.resource = resource_class.new + resource.reset_password_token = params[:spree_user][:reset_password_token] + set_flash_message(:error, :cannot_be_blank) + render :edit + else + super + end + end + +end diff --git a/app/controllers/spree/user_registrations_controller.rb b/app/controllers/spree/user_registrations_controller.rb new file mode 100644 index 0000000000..d36a3896be --- /dev/null +++ b/app/controllers/spree/user_registrations_controller.rb @@ -0,0 +1,67 @@ +class Spree::UserRegistrationsController < Devise::RegistrationsController + helper 'spree/users', 'spree/base', 'spree/store' + + if defined?(Spree::Dash) + helper 'spree/analytics' + end + + include Spree::Core::ControllerHelpers::Auth + include Spree::Core::ControllerHelpers::Common + include Spree::Core::ControllerHelpers::Order + include Spree::Core::ControllerHelpers::SSL + + ssl_required + before_filter :check_permissions, :only => [:edit, :update] + skip_before_filter :require_no_authentication + + # GET /resource/sign_up + def new + super + @user = resource + end + + # POST /resource/sign_up + def create + @user = build_resource(params[:spree_user]) + if resource.save + set_flash_message(:notice, :signed_up) + sign_in(:spree_user, @user) + session[:spree_user_signup] = true + associate_user + respond_with resource, location: after_sign_up_path_for(resource) + else + clean_up_passwords(resource) + render :new + end + end + + # GET /resource/edit + def edit + super + end + + # PUT /resource + def update + super + end + + # DELETE /resource + def destroy + super + end + + # GET /resource/cancel + # Forces the session data which is usually expired after sign + # in to be expired now. This is useful if the user wants to + # cancel oauth signing in/up in the middle of the process, + # removing all OAuth session data. + def cancel + super + end + + protected + def check_permissions + authorize!(:create, resource) + end + +end diff --git a/app/controllers/spree/user_sessions_controller.rb b/app/controllers/spree/user_sessions_controller.rb new file mode 100644 index 0000000000..98ae252b1e --- /dev/null +++ b/app/controllers/spree/user_sessions_controller.rb @@ -0,0 +1,56 @@ +class Spree::UserSessionsController < Devise::SessionsController + helper 'spree/users', 'spree/base', 'spree/store' + if defined?(Spree::Dash) + helper 'spree/analytics' + end + + include Spree::Core::ControllerHelpers::Auth + include Spree::Core::ControllerHelpers::Common + include Spree::Core::ControllerHelpers::Order + include Spree::Core::ControllerHelpers::SSL + + ssl_required :new, :create, :destroy, :update + ssl_allowed :login_bar + + def create + authenticate_spree_user! + + if spree_user_signed_in? + respond_to do |format| + format.html { + flash[:success] = Spree.t(:logged_in_succesfully) + redirect_back_or_default(after_sign_in_path_for(spree_current_user)) + } + format.js { + render :json => {:user => spree_current_user, + :ship_address => spree_current_user.ship_address, + :bill_address => spree_current_user.bill_address}.to_json + } + end + else + respond_to do |format| + format.html { + flash.now[:error] = t('devise.failure.invalid') + render :new + } + format.js { + render :json => { error: t('devise.failure.invalid') }, status: :unprocessable_entity + } + end + end + end + + def nav_bar + render :partial => 'spree/shared/nav_bar' + end + + private + def accurate_title + Spree.t(:login) + end + + def redirect_back_or_default(default) + redirect_to(session["spree_user_return_to"] || default) + session["spree_user_return_to"] = nil + end +end diff --git a/app/controllers/spree/users_controller.rb b/app/controllers/spree/users_controller.rb new file mode 100644 index 0000000000..286181aeb4 --- /dev/null +++ b/app/controllers/spree/users_controller.rb @@ -0,0 +1,57 @@ +class Spree::UsersController < Spree::StoreController + ssl_required + skip_before_filter :set_current_order, :only => :show + prepend_before_filter :load_object, :only => [:show, :edit, :update] + prepend_before_filter :authorize_actions, :only => :new + + include Spree::Core::ControllerHelpers + + def show + @orders = @user.orders.complete.order('completed_at desc') + end + + def create + @user = Spree::User.new(params[:user]) + if @user.save + + if current_order + session[:guest_token] = nil + end + + redirect_back_or_default(root_url) + else + render :new + end + end + + def update + if @user.update_attributes(params[:user]) + if params[:user][:password].present? + # this logic needed b/c devise wants to log us out after password changes + user = Spree::User.reset_password_by_token(params[:user]) + sign_in(@user, :event => :authentication, :bypass => !Spree::Auth::Config[:signout_after_password_change]) + end + redirect_to spree.account_url, :notice => Spree.t(:account_updated) + else + render :edit + end + end + + private + def load_object + @user ||= spree_current_user + if @user + authorize! params[:action].to_sym, @user + else + redirect_to spree.login_path + end + end + + def authorize_actions + authorize! params[:action].to_sym, Spree::User.new + end + + def accurate_title + Spree.t(:my_account) + end +end diff --git a/config/routes/spree.rb b/config/routes/spree.rb index cc221fc8d0..a5469bdf8b 100644 --- a/config/routes/spree.rb +++ b/config/routes/spree.rb @@ -9,6 +9,35 @@ Spree::Core::Engine.routes.draw do :skip => [:unlocks, :omniauth_callbacks], :path_names => { :sign_out => 'logout' }, :path_prefix => :user + + resources :users, :only => [:edit, :update] + + devise_scope :spree_user do + get '/login' => 'user_sessions#new', :as => :login + post '/login' => 'user_sessions#create', :as => :create_new_session + get '/logout' => 'user_sessions#destroy', :as => :logout + get '/signup' => 'user_registrations#new', :as => :signup + post '/signup' => 'user_registrations#create', :as => :registration + get '/password/recover' => 'user_passwords#new', :as => :recover_password + post '/password/recover' => 'user_passwords#create', :as => :reset_password + get '/password/change' => 'user_passwords#edit', :as => :edit_password + put '/password/change' => 'user_passwords#update', :as => :update_password + end + + match '/checkout/registration' => 'checkout#registration', :via => :get, :as => :checkout_registration + match '/checkout/registration' => 'checkout#update_registration', :via => :put, :as => :update_checkout_registration + + resource :session do + member do + get :nav_bar + end + end + + resource :account, :controller => 'users' + + namespace :admin do + resources :users + end end Spree::Core::Engine.routes.prepend do From fdcc4c2447144144168107984751ea73debd3562 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Fri, 5 Jul 2019 15:54:10 +0100 Subject: [PATCH 02/36] Remove dependency to spree auth devise --- Gemfile | 3 ++- Gemfile.lock | 27 +++------------------------ 2 files changed, 5 insertions(+), 25 deletions(-) diff --git a/Gemfile b/Gemfile index 6cbec48c6b..dbbd80089c 100644 --- a/Gemfile +++ b/Gemfile @@ -24,7 +24,6 @@ gem 'spree_api', github: 'openfoodfoundation/spree', branch: '2-0-4-stable' gem 'spree_backend', github: 'openfoodfoundation/spree', branch: '2-0-4-stable' gem 'spree_core', github: 'openfoodfoundation/spree', branch: '2-0-4-stable' -gem 'spree_auth_devise', github: 'luisramos0/spree_auth_devise', branch: '2-0-without-ctrls' gem 'spree_i18n', github: 'spree/spree_i18n', branch: '1-3-stable' # Our branch contains two changes @@ -37,6 +36,8 @@ gem 'stripe' # which is needed for Pin Payments (and possibly others). gem 'activemerchant', '~> 1.78' +gem 'devise', '~> 2.2.5' +gem 'devise-encryptable', '0.1.2' gem 'jwt', '~> 2.2' gem 'oauth2', '~> 1.4.1' # Used for Stripe Connect diff --git a/Gemfile.lock b/Gemfile.lock index 5dc405918e..11339eae89 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -12,18 +12,6 @@ GIT specs: custom_error_message (1.1.1) -GIT - remote: https://github.com/luisramos0/spree_auth_devise.git - revision: 562ac6b0b821173f36405457ccfad103e9c5dc6a - branch: 2-0-without-ctrls - specs: - spree_auth_devise (2.0.0) - devise (~> 2.2.5) - devise-encryptable (= 0.1.2) - spree_backend (~> 2.0.0) - spree_core (~> 2.0.0) - spree_frontend (~> 2.0.0) - GIT remote: https://github.com/openfoodfoundation/better_spree_paypal_express.git revision: 27ad7165ea4c6e8c5f120b42b676cb9c2c272100 @@ -78,14 +66,6 @@ GIT state_machine (= 1.2.0) stringex (~> 1.5.1) truncate_html (= 0.9.2) - spree_frontend (2.0.4) - canonical-rails - deface (>= 0.9.0) - jquery-rails (~> 3.0.0) - rails (~> 3.2.13) - spree_api (= 2.0.4) - spree_core (= 2.0.4) - stringex (~> 1.5.1) GIT remote: https://github.com/spree/spree_i18n.git @@ -180,7 +160,7 @@ GEM json (~> 1.4) nokogiri (>= 1.4.4) uuidtools (~> 2.1) - bcrypt (3.1.12) + bcrypt (3.1.13) bcrypt-ruby (3.1.5) bcrypt (>= 3.1.3) blockenspiel (0.5.0) @@ -189,8 +169,6 @@ GEM builder (3.0.4) byebug (9.0.6) cancan (1.6.10) - canonical-rails (0.1.0) - rails (>= 3.1, < 5.1) capybara (2.18.0) addressable mini_mime (>= 0.1.3) @@ -801,6 +779,8 @@ DEPENDENCIES deface (= 1.0.2) delayed_job_active_record delayed_job_web + devise (~> 2.2.5) + devise-encryptable (= 0.1.2) diffy eventmachine (>= 1.2.3) factory_bot_rails @@ -861,7 +841,6 @@ DEPENDENCIES skylight (< 2.0) spinjs-rails spree_api! - spree_auth_devise! spree_backend! spree_core! spree_i18n! From 2755cb9ec7180177cfd1ed0e103e79701e117751 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Fri, 5 Jul 2019 18:39:10 +0100 Subject: [PATCH 03/36] Add users_tab partial from spree_auth_devise --- app/views/spree/admin/_users_tab.html.erb | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 app/views/spree/admin/_users_tab.html.erb diff --git a/app/views/spree/admin/_users_tab.html.erb b/app/views/spree/admin/_users_tab.html.erb new file mode 100644 index 0000000000..5b3ffc9e60 --- /dev/null +++ b/app/views/spree/admin/_users_tab.html.erb @@ -0,0 +1,3 @@ +<% if can? :admin, Spree::User %> + <%= tab(:users, :url => spree.admin_users_path, :icon => 'icon-user') %> +<% end %> From 966901657366d1b0c59623124266c9021b62006c Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Fri, 5 Jul 2019 21:23:11 +0100 Subject: [PATCH 04/36] Add required views from spree_auth_devise --- app/views/spree/admin/users/new.html.erb | 23 +++++++++++++++++++++ app/views/spree/shared/_user_form.html.erb | 17 +++++++++++++++ app/views/spree/user_passwords/new.html.erb | 17 +++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 app/views/spree/admin/users/new.html.erb create mode 100644 app/views/spree/shared/_user_form.html.erb create mode 100755 app/views/spree/user_passwords/new.html.erb diff --git a/app/views/spree/admin/users/new.html.erb b/app/views/spree/admin/users/new.html.erb new file mode 100644 index 0000000000..9891bce060 --- /dev/null +++ b/app/views/spree/admin/users/new.html.erb @@ -0,0 +1,23 @@ +<% content_for :page_title do %> + <%= Spree.t(:new_user) %> +<% end %> + +<% content_for :page_actions do %> +
  • + <%= button_link_to Spree.t(:back_to_users_list), spree.admin_users_path, :icon => 'icon-arrow-left' %> +
  • +<% end %> + +
    + <%= render :partial => 'spree/shared/error_messages', :locals => { :target => @user } %> +
    + +
    + <%= form_for [:admin, @user] do |f| %> + <%= render :partial => 'form', :locals => { :f => f } %> + +
    + <%= render :partial => 'spree/admin/shared/new_resource_links' %> +
    + <% end %> +
    diff --git a/app/views/spree/shared/_user_form.html.erb b/app/views/spree/shared/_user_form.html.erb new file mode 100644 index 0000000000..a31902ca61 --- /dev/null +++ b/app/views/spree/shared/_user_form.html.erb @@ -0,0 +1,17 @@ +

    + <%= f.label :email, Spree.t(:email) %>
    + <%= f.email_field :email, :class => 'title' %> +

    +
    +

    + <%= f.label :password, Spree.t(:password) %>
    + <%= f.password_field :password, :class => 'title' %> +

    + +

    + <%= f.label :password_confirmation, Spree.t(:confirm_password) %>
    + <%= f.password_field :password_confirmation, :class => 'title' %> +

    +
    + +
    diff --git a/app/views/spree/user_passwords/new.html.erb b/app/views/spree/user_passwords/new.html.erb new file mode 100755 index 0000000000..a4330e4490 --- /dev/null +++ b/app/views/spree/user_passwords/new.html.erb @@ -0,0 +1,17 @@ +<%= render :partial => 'spree/shared/error_messages', :locals => { :target => @spree_user } %> + +
    +
    <%= Spree.t(:forgot_password) %>
    + +

    <%= Spree.t(:instructions_to_reset_password) %>

    + + <%= form_for Spree::User.new, :as => :spree_user, :url => spree.reset_password_path do |f| %> +

    + <%= f.label :email, Spree.t(:email) %>
    + <%= f.email_field :email %> +

    +

    + <%= f.submit Spree.t(:reset_password), :class => 'button primary' %> +

    + <% end %> +
    From a2a8b330b758d8e7bd1379efd902e24379f55119 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Fri, 5 Jul 2019 21:43:44 +0100 Subject: [PATCH 05/36] Add User class from spree_auth_devise as is --- app/models/spree/user.rb | 80 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 app/models/spree/user.rb diff --git a/app/models/spree/user.rb b/app/models/spree/user.rb new file mode 100644 index 0000000000..a82c891a04 --- /dev/null +++ b/app/models/spree/user.rb @@ -0,0 +1,80 @@ +module Spree + class User < ActiveRecord::Base + include Core::UserBanners + + devise :database_authenticatable, :token_authenticatable, :registerable, :recoverable, + :rememberable, :trackable, :validatable, :encryptable, :encryptor => 'authlogic_sha512' + + has_many :orders + belongs_to :ship_address, :foreign_key => 'ship_address_id', :class_name => 'Spree::Address' + belongs_to :bill_address, :foreign_key => 'bill_address_id', :class_name => 'Spree::Address' + + before_validation :set_login + before_destroy :check_completed_orders + + # Setup accessible (or protected) attributes for your model + attr_accessible :email, :password, :password_confirmation, :remember_me, :persistence_token, :login + + users_table_name = User.table_name + roles_table_name = Role.table_name + + scope :admin, lambda { includes(:spree_roles).where("#{roles_table_name}.name" => "admin") } + scope :registered, where("#{users_table_name}.email NOT LIKE ?", "%@example.net") + + class DestroyWithOrdersError < StandardError; end + + # Creates an anonymous user. An anonymous user is basically an auto-generated +User+ account that is created for the customer + # behind the scenes and its completely transparently to the customer. All +Orders+ must have a +User+ so this is necessary + # when adding to the "cart" (which is really an order) and before the customer has a chance to provide an email or to register. + def self.anonymous! + token = User.generate_token(:persistence_token) + User.create(:email => "#{token}@example.net", :password => token, :password_confirmation => token, :persistence_token => token) + end + + def self.admin_created? + User.admin.count > 0 + end + + def admin? + has_spree_role?('admin') + end + + def anonymous? + email =~ /@example.net$/ ? true : false + end + + def send_reset_password_instructions + generate_reset_password_token! + UserMailer.reset_password_instructions(self.id).deliver + end + + protected + def password_required? + !persisted? || password.present? || password_confirmation.present? + end + + private + + def check_completed_orders + raise DestroyWithOrdersError if orders.complete.present? + end + + def set_login + # for now force login to be same as email, eventually we will make this configurable, etc. + self.login ||= self.email if self.email + end + + # Generate a friendly string randomically to be used as token. + def self.friendly_token + SecureRandom.base64(15).tr('+/=', '-_ ').strip.delete("\n") + end + + # Generate a token by looping and ensuring does not already exist. + def self.generate_token(column) + loop do + token = friendly_token + break token unless find(:first, :conditions => { column => token }) + end + end + end +end From 4e33529845f63fcc027c2aa245925d080cb68118 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Fri, 5 Jul 2019 21:48:01 +0100 Subject: [PATCH 06/36] Merge user_decorator.rb into user.rb --- app/models/spree/user.rb | 95 +++++++++++++++++++++++++++++ app/models/spree/user_decorator.rb | 98 ------------------------------ 2 files changed, 95 insertions(+), 98 deletions(-) delete mode 100644 app/models/spree/user_decorator.rb diff --git a/app/models/spree/user.rb b/app/models/spree/user.rb index a82c891a04..138ea9f47b 100644 --- a/app/models/spree/user.rb +++ b/app/models/spree/user.rb @@ -21,6 +21,32 @@ module Spree scope :admin, lambda { includes(:spree_roles).where("#{roles_table_name}.name" => "admin") } scope :registered, where("#{users_table_name}.email NOT LIKE ?", "%@example.net") + # handle_asynchronously will define send_reset_password_instructions_with_delay. + # If handle_asynchronously is called twice, we get an infinite job loop. + handle_asynchronously :send_reset_password_instructions unless method_defined? :send_reset_password_instructions_with_delay + + has_many :enterprise_roles, dependent: :destroy + has_many :enterprises, through: :enterprise_roles + has_many :owned_enterprises, class_name: 'Enterprise', foreign_key: :owner_id, inverse_of: :owner + has_many :owned_groups, class_name: 'EnterpriseGroup', foreign_key: :owner_id, inverse_of: :owner + has_many :customers + has_many :credit_cards + + accepts_nested_attributes_for :enterprise_roles, allow_destroy: true + + accepts_nested_attributes_for :bill_address + accepts_nested_attributes_for :ship_address + + attr_accessible :enterprise_ids, :enterprise_roles_attributes, :enterprise_limit, :locale, :bill_address_attributes, :ship_address_attributes + after_create :associate_customers + + validate :limit_owned_enterprises + + # We use the same options as Spree and add :confirmable + devise :confirmable, reconfirmable: true + # TODO: Later versions of devise have a dedicated after_confirmation callback, so use that + after_update :welcome_after_confirm, if: lambda { confirmation_token_changed? && confirmation_token.nil? } + class DestroyWithOrdersError < StandardError; end # Creates an anonymous user. An anonymous user is basically an auto-generated +User+ account that is created for the customer @@ -48,6 +74,61 @@ module Spree UserMailer.reset_password_instructions(self.id).deliver end + def known_users + if admin? + Spree::User.scoped + else + Spree::User + .includes(:enterprises) + .where("enterprises.id IN (SELECT enterprise_id FROM enterprise_roles WHERE user_id = ?)", id) + end + end + + def build_enterprise_roles + Enterprise.all.find_each do |enterprise| + unless enterprise_roles.find_by_enterprise_id enterprise.id + enterprise_roles.build(enterprise: enterprise) + end + end + end + + def customer_of(enterprise) + return nil unless enterprise + customers.find_by_enterprise_id(enterprise) + end + + def welcome_after_confirm + # Send welcome email if we are confirming an user's email + # Note: this callback only runs on email confirmation + if confirmed? && unconfirmed_email.nil? && !unconfirmed_email_changed? + send_signup_confirmation + end + end + + def send_signup_confirmation + Delayed::Job.enqueue ConfirmSignupJob.new(id) + end + + def associate_customers + self.customers = Customer.where(email: email) + end + + def can_own_more_enterprises? + owned_enterprises(:reload).size < enterprise_limit + end + + def default_card + credit_cards.where(is_default: true).first + end + + # Checks whether the specified user is a superadmin, with full control of the + # instance + # + # @return [Boolean] + def superadmin? + has_spree_role?('admin') + end + protected def password_required? !persisted? || password.present? || password_confirmation.present? @@ -76,5 +157,19 @@ module Spree break token unless find(:first, :conditions => { column => token }) end end + + def limit_owned_enterprises + if owned_enterprises.size > enterprise_limit + errors.add(:owned_enterprises, I18n.t(:spree_user_enterprise_limit_error, email: email, enterprise_limit: enterprise_limit)) + end + end + + def remove_payments_in_checkout(enterprises) + enterprises.each do |enterprise| + enterprise.distributed_orders.each do |order| + order.payments.keep_if { |payment| payment.state != "checkout" } + end + end + end end end diff --git a/app/models/spree/user_decorator.rb b/app/models/spree/user_decorator.rb deleted file mode 100644 index 15d62b82f2..0000000000 --- a/app/models/spree/user_decorator.rb +++ /dev/null @@ -1,98 +0,0 @@ -Spree.user_class.class_eval do - # handle_asynchronously will define send_reset_password_instructions_with_delay. - # If handle_asynchronously is called twice, we get an infinite job loop. - handle_asynchronously :send_reset_password_instructions unless method_defined? :send_reset_password_instructions_with_delay - - has_many :enterprise_roles, dependent: :destroy - has_many :enterprises, through: :enterprise_roles - has_many :owned_enterprises, class_name: 'Enterprise', foreign_key: :owner_id, inverse_of: :owner - has_many :owned_groups, class_name: 'EnterpriseGroup', foreign_key: :owner_id, inverse_of: :owner - has_many :customers - has_many :credit_cards - - accepts_nested_attributes_for :enterprise_roles, allow_destroy: true - - accepts_nested_attributes_for :bill_address - accepts_nested_attributes_for :ship_address - - attr_accessible :enterprise_ids, :enterprise_roles_attributes, :enterprise_limit, :locale, :bill_address_attributes, :ship_address_attributes - after_create :associate_customers - - validate :limit_owned_enterprises - - # We use the same options as Spree and add :confirmable - devise :confirmable, reconfirmable: true - # TODO: Later versions of devise have a dedicated after_confirmation callback, so use that - after_update :welcome_after_confirm, if: lambda { confirmation_token_changed? && confirmation_token.nil? } - - def known_users - if admin? - Spree::User.scoped - else - Spree::User - .includes(:enterprises) - .where("enterprises.id IN (SELECT enterprise_id FROM enterprise_roles WHERE user_id = ?)", id) - end - end - - def build_enterprise_roles - Enterprise.all.find_each do |enterprise| - unless enterprise_roles.find_by_enterprise_id enterprise.id - enterprise_roles.build(enterprise: enterprise) - end - end - end - - def customer_of(enterprise) - return nil unless enterprise - customers.find_by_enterprise_id(enterprise) - end - - def welcome_after_confirm - # Send welcome email if we are confirming an user's email - # Note: this callback only runs on email confirmation - if confirmed? && unconfirmed_email.nil? && !unconfirmed_email_changed? - send_signup_confirmation - end - end - - def send_signup_confirmation - Delayed::Job.enqueue ConfirmSignupJob.new(id) - end - - def associate_customers - self.customers = Customer.where(email: email) - end - - def can_own_more_enterprises? - owned_enterprises(:reload).size < enterprise_limit - end - - def default_card - credit_cards.where(is_default: true).first - end - - # Checks whether the specified user is a superadmin, with full control of the - # instance - # - # @return [Boolean] - def superadmin? - has_spree_role?('admin') - end - - private - - def limit_owned_enterprises - if owned_enterprises.size > enterprise_limit - errors.add(:owned_enterprises, I18n.t(:spree_user_enterprise_limit_error, email: email, enterprise_limit: enterprise_limit)) - end - end - - def remove_payments_in_checkout(enterprises) - enterprises.each do |enterprise| - enterprise.distributed_orders.each do |order| - order.payments.keep_if { |payment| payment.state != "checkout" } - end - end - end -end From a83790951df8ad2bd532c388d4026ab646851bdb Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Fri, 5 Jul 2019 21:50:07 +0100 Subject: [PATCH 07/36] Add model auth_config from spree_auth_devise --- app/models/spree/auth_configuration.rb | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 app/models/spree/auth_configuration.rb diff --git a/app/models/spree/auth_configuration.rb b/app/models/spree/auth_configuration.rb new file mode 100644 index 0000000000..f4ccc91fcb --- /dev/null +++ b/app/models/spree/auth_configuration.rb @@ -0,0 +1,6 @@ +module Spree + class AuthConfiguration < Preferences::Configuration + preference :registration_step, :boolean, :default => true + preference :signout_after_password_change, :boolean, :default => true + end +end From 061e3cd7229af1978dbe9ddcfd80c4867d54271d Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Fri, 5 Jul 2019 22:29:51 +0100 Subject: [PATCH 08/36] Add user mailer from spree_auth_devise --- app/mailers/spree/user_mailer.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 app/mailers/spree/user_mailer.rb diff --git a/app/mailers/spree/user_mailer.rb b/app/mailers/spree/user_mailer.rb new file mode 100644 index 0000000000..8d8e95e7aa --- /dev/null +++ b/app/mailers/spree/user_mailer.rb @@ -0,0 +1,12 @@ +module Spree + class UserMailer < BaseMailer + def reset_password_instructions(user) + recipient = user.respond_to?(:id) ? user : Spree.user_class.find(user) + @edit_password_reset_url = spree.edit_spree_user_password_url(:reset_password_token => recipient.reset_password_token) + + mail(:to => recipient.email, :from => from_address, + :subject => Spree::Config[:site_name] + ' ' + + I18n.t(:subject, :scope => [:devise, :mailer, :reset_password_instructions])) + end + end +end From 893952f46bcb2156b723c2a57f9476adfb38679c Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Fri, 5 Jul 2019 22:31:06 +0100 Subject: [PATCH 09/36] Merge user_mailer_decorator into user_mailer --- app/mailers/spree/user_mailer.rb | 31 +++++++++++++++++++++ app/mailers/spree/user_mailer_decorator.rb | 32 ---------------------- 2 files changed, 31 insertions(+), 32 deletions(-) delete mode 100644 app/mailers/spree/user_mailer_decorator.rb diff --git a/app/mailers/spree/user_mailer.rb b/app/mailers/spree/user_mailer.rb index 8d8e95e7aa..be904c3d45 100644 --- a/app/mailers/spree/user_mailer.rb +++ b/app/mailers/spree/user_mailer.rb @@ -1,5 +1,7 @@ module Spree class UserMailer < BaseMailer + include I18nHelper + def reset_password_instructions(user) recipient = user.respond_to?(:id) ? user : Spree.user_class.find(user) @edit_password_reset_url = spree.edit_spree_user_password_url(:reset_password_token => recipient.reset_password_token) @@ -8,5 +10,34 @@ module Spree :subject => Spree::Config[:site_name] + ' ' + I18n.t(:subject, :scope => [:devise, :mailer, :reset_password_instructions])) end + + def signup_confirmation(user) + @user = user + I18n.with_locale valid_locale(@user) do + mail(to: user.email, from: from_address, + subject: t(:welcome_to) + Spree::Config[:site_name]) + end + end + + # Overriding `Spree::UserMailer.confirmation_instructions` which is + # overriding `Devise::Mailer.confirmation_instructions`. + def confirmation_instructions(user, _opts) + @user = user + @instance = Spree::Config[:site_name] + @contact = ContentConfig.footer_email + + I18n.with_locale valid_locale(@user) do + subject = t('spree.user_mailer.confirmation_instructions.subject') + mail(to: confirmation_email_address, + from: from_address, + subject: subject) + end + end + + private + + def confirmation_email_address + @user.pending_reconfirmation? ? @user.unconfirmed_email : @user.email + end end end diff --git a/app/mailers/spree/user_mailer_decorator.rb b/app/mailers/spree/user_mailer_decorator.rb deleted file mode 100644 index 52266a60b0..0000000000 --- a/app/mailers/spree/user_mailer_decorator.rb +++ /dev/null @@ -1,32 +0,0 @@ -Spree::UserMailer.class_eval do - include I18nHelper - - def signup_confirmation(user) - @user = user - I18n.with_locale valid_locale(@user) do - mail(to: user.email, from: from_address, - subject: t(:welcome_to) + Spree::Config[:site_name]) - end - end - - # Overriding `Spree::UserMailer.confirmation_instructions` which is - # overriding `Devise::Mailer.confirmation_instructions`. - def confirmation_instructions(user, _opts) - @user = user - @instance = Spree::Config[:site_name] - @contact = ContentConfig.footer_email - - I18n.with_locale valid_locale(@user) do - subject = t('spree.user_mailer.confirmation_instructions.subject') - mail(to: confirmation_email_address, - from: from_address, - subject: subject) - end - end - - private - - def confirmation_email_address - @user.pending_reconfirmation? ? @user.unconfirmed_email : @user.email - end -end From a413f22e126e095ba8754e9c49a442e78f493acd Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Fri, 5 Jul 2019 22:37:07 +0100 Subject: [PATCH 10/36] Remove unnecessary dependency to spree/users helper --- app/controllers/spree/checkout_controller.rb | 2 -- app/controllers/spree/user_passwords_controller.rb | 2 +- app/controllers/spree/user_registrations_controller.rb | 2 +- app/controllers/spree/user_sessions_controller.rb | 2 +- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/app/controllers/spree/checkout_controller.rb b/app/controllers/spree/checkout_controller.rb index b75418f179..f4fa56f492 100644 --- a/app/controllers/spree/checkout_controller.rb +++ b/app/controllers/spree/checkout_controller.rb @@ -27,8 +27,6 @@ module Spree before_filter :check_registration, :except => [:registration, :update_registration] - helper 'spree/users' - def registration @user = Spree::User.new end diff --git a/app/controllers/spree/user_passwords_controller.rb b/app/controllers/spree/user_passwords_controller.rb index f18570a4fd..0638fa8d9e 100644 --- a/app/controllers/spree/user_passwords_controller.rb +++ b/app/controllers/spree/user_passwords_controller.rb @@ -1,5 +1,5 @@ class Spree::UserPasswordsController < Devise::PasswordsController - helper 'spree/users', 'spree/base', 'spree/store' + helper 'spree/base', 'spree/store' if defined?(Spree::Dash) helper 'spree/analytics' diff --git a/app/controllers/spree/user_registrations_controller.rb b/app/controllers/spree/user_registrations_controller.rb index d36a3896be..4eeacb054c 100644 --- a/app/controllers/spree/user_registrations_controller.rb +++ b/app/controllers/spree/user_registrations_controller.rb @@ -1,5 +1,5 @@ class Spree::UserRegistrationsController < Devise::RegistrationsController - helper 'spree/users', 'spree/base', 'spree/store' + helper 'spree/base', 'spree/store' if defined?(Spree::Dash) helper 'spree/analytics' diff --git a/app/controllers/spree/user_sessions_controller.rb b/app/controllers/spree/user_sessions_controller.rb index 98ae252b1e..fee05ebf84 100644 --- a/app/controllers/spree/user_sessions_controller.rb +++ b/app/controllers/spree/user_sessions_controller.rb @@ -1,5 +1,5 @@ class Spree::UserSessionsController < Devise::SessionsController - helper 'spree/users', 'spree/base', 'spree/store' + helper 'spree/base', 'spree/store' if defined?(Spree::Dash) helper 'spree/analytics' end From 17448699f96a184038bd56d1faf37f94c8de51cb Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Fri, 5 Jul 2019 22:45:59 +0100 Subject: [PATCH 11/36] Bring devise initializer from spree_auth_devise and fix spree initializer details --- app/controllers/spree/checkout_controller.rb | 2 +- app/controllers/spree/users_controller.rb | 2 +- config/initializers/devise.rb | 143 ++++++++++++++++++- config/initializers/spree.rb | 7 +- config/initializers/spree_auth_devise.rb | 16 --- lib/spree/authentication_helpers.rb | 26 ++++ spec/spec_helper.rb | 2 +- 7 files changed, 177 insertions(+), 21 deletions(-) delete mode 100644 config/initializers/spree_auth_devise.rb create mode 100644 lib/spree/authentication_helpers.rb diff --git a/app/controllers/spree/checkout_controller.rb b/app/controllers/spree/checkout_controller.rb index f4fa56f492..c5eb64a62f 100644 --- a/app/controllers/spree/checkout_controller.rb +++ b/app/controllers/spree/checkout_controller.rb @@ -56,7 +56,7 @@ module Spree # Introduces a registration step whenever the +registration_step+ preference is true. def check_registration - return unless Spree::Auth::Config[:registration_step] + return unless AuthConfig[:registration_step] return if spree_current_user or current_order.email store_location redirect_to spree.checkout_registration_path diff --git a/app/controllers/spree/users_controller.rb b/app/controllers/spree/users_controller.rb index 286181aeb4..1de4b0eafe 100644 --- a/app/controllers/spree/users_controller.rb +++ b/app/controllers/spree/users_controller.rb @@ -29,7 +29,7 @@ class Spree::UsersController < Spree::StoreController if params[:user][:password].present? # this logic needed b/c devise wants to log us out after password changes user = Spree::User.reset_password_by_token(params[:user]) - sign_in(@user, :event => :authentication, :bypass => !Spree::Auth::Config[:signout_after_password_change]) + sign_in(@user, :event => :authentication, :bypass => !AuthConfig[:signout_after_password_change]) end redirect_to spree.account_url, :notice => Spree.t(:account_updated) else diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 9fef52fc8c..b2424cdbbd 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -1,5 +1,146 @@ +# Use this hook to configure devise mailer, warden hooks and so forth. The first +# four configuration values can also be set straight in your models. Devise.setup do |config| + # ==> Mailer Configuration + # Configure the e-mail address which will be shown in DeviseMailer. + config.mailer_sender = 'please-change-me@config-initializers-devise.com' + + # Configure the class responsible to send e-mails. + config.mailer = 'Spree::UserMailer' + + # ==> ORM configuration + # Load and configure the ORM. Supports :active_record (default) and + # :mongoid (bson_ext recommended) by default. Other ORMs may be + # available as additional gems. + require 'devise/orm/active_record' + + # ==> Configuration for any authentication mechanism + # Configure which keys are used when authenticating an user. By default is + # just :email. You can configure it to use [:username, :subdomain], so for + # authenticating an user, both parameters are required. Remember that those + # parameters are used only when authenticating and not when retrieving from + # session. If you need permissions, you should implement that in a before filter. + # config.authentication_keys = [ :email ] + + # Tell if authentication through request.params is enabled. True by default. + # config.params_authenticatable = true + + # Tell if authentication through HTTP Basic Auth is enabled. False by default. + config.http_authenticatable = true + + # Set this to true to use Basic Auth for AJAX requests. True by default. + #config.http_authenticatable_on_xhr = false + + # The realm used in Http Basic Authentication + config.http_authentication_realm = 'Spree Application' + + # ==> Configuration for :database_authenticatable + # For bcrypt, this is the cost for hashing the password and defaults to 10. If + # using other encryptors, it sets how many times you want the password re-encrypted. + config.stretches = 20 + + # Setup a pepper to generate the encrypted password. + config.pepper = Rails.configuration.secret_token + + # ==> Configuration for :confirmable + # The time you want to give your user to confirm his account. During this time + # he will be able to access your application without confirming. Default is nil. + # When confirm_within is zero, the user won't be able to sign in without confirming. + # You can use this to let your user access some features of your application + # without confirming the account, but blocking it after a certain period + # (ie 2 days). + # config.confirm_within = 2.days + + # ==> Configuration for :rememberable + # The time the user will be remembered without asking for credentials again. + # config.remember_for = 2.weeks + + # If true, a valid remember token can be re-used between multiple browsers. + # config.remember_across_browsers = true + + # If true, extends the user's remember period when remembered via cookie. + # config.extend_remember_period = false + + # ==> Configuration for :validatable + # Range for password length + # config.password_length = 6..20 + + # Regex to use to validate the email address + config.email_regexp = /^([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})$/i + + # ==> Configuration for :timeoutable + # The time you want to timeout the user session without activity. After this + # time the user will be asked for credentials again. + # config.timeout_in = 10.minutes + + # ==> Configuration for :lockable + # Defines which strategy will be used to lock an account. + # :failed_attempts = Locks an account after a number of failed attempts to sign in. + # :none = No lock strategy. You should handle locking by yourself. + # config.lock_strategy = :failed_attempts + + # Defines which strategy will be used to unlock an account. + # :email = Sends an unlock link to the user email + # :time = Re-enables login after a certain amount of time (see :unlock_in below) + # :both = Enables both strategies + # :none = No unlock strategy. You should handle unlocking by yourself. + # config.unlock_strategy = :both + + # Number of authentication tries before locking an account if lock_strategy + # is failed attempts. + # config.maximum_attempts = 20 + + # Time interval to unlock the account if :time is enabled as unlock_strategy. + # config.unlock_in = 1.hour + + # ==> Configuration for :token_authenticatable + # Defines name of the authentication token params key + config.token_authentication_key = :auth_token + + # ==> Scopes configuration + # Turn scoped views on. Before rendering 'sessions/new', it will first check for + # 'users/sessions/new'. It's turned off by default because it's slower if you + # are using only default views. + # config.scoped_views = true + + # Configure the default scope given to Warden. By default it's the first + # devise role declared in your routes. # Add a default scope to devise, to prevent it from checking # whether other devise enabled models are signed into a session or not config.default_scope = :spree_user -end \ No newline at end of file + + # Configure sign_out behavior. + # By default sign_out is scoped (i.e. /users/sign_out affects only :user scope). + # In case of sign_out_all_scopes set to true any logout action will sign out all active scopes. + # config.sign_out_all_scopes = false + + # ==> Navigation configuration + # Lists the formats that should be treated as navigational. Formats like + # :html, should redirect to the sign in page when the user does not have + # access, but formats like :xml or :json, should return 401. + # If you have any extra navigational formats, like :iphone or :mobile, you + # should add them to the navigational formats lists. Default is [:html] + config.navigational_formats = [:html, :json, :xml] + + # ==> Warden configuration + # If you want to use other strategies, that are not (yet) supported by Devise, + # you can configure them inside the config.warden block. The example below + # allows you to setup OAuth, using http://github.com/roman/warden_oauth + # + # config.warden do |manager| + # manager.oauth(:twitter) do |twitter| + # twitter.consumer_secret = + # twitter.consumer_key = + # twitter.options :site => 'http://twitter.com' + # end + # manager.default_strategies(:scope => :user).unshift :twitter_oauth + # end + # + # Time interval you can reset your password with a reset password key. + # Don't put a too small interval or your users won't have the time to + # change their passwords. + config.reset_password_within = 6.hours + config.sign_out_via = :get + + config.case_insensitive_keys = [:email] +end diff --git a/config/initializers/spree.rb b/config/initializers/spree.rb index df21b91421..68de82143e 100644 --- a/config/initializers/spree.rb +++ b/config/initializers/spree.rb @@ -42,11 +42,16 @@ Spree.config do |config| config.s3_protocol = ENV.fetch('S3_PROTOCOL', 'https') end +# Initialize authentication +require 'spree/authentication_helpers' +ApplicationController.send :include, Spree::AuthenticationHelpers + # Spree 2.0 recommends explicitly setting this here when using spree_auth_devise Spree.user_class = 'Spree::User' +AuthConfig = Spree::AuthConfiguration.new # Don't log users out when setting a new password -Spree::Auth::Config[:signout_after_password_change] = false +AuthConfig[:signout_after_password_change] = false # TODO Work out why this is necessary # Seems like classes within OFN module become 'uninitialized' when server reloads diff --git a/config/initializers/spree_auth_devise.rb b/config/initializers/spree_auth_devise.rb deleted file mode 100644 index a59badf636..0000000000 --- a/config/initializers/spree_auth_devise.rb +++ /dev/null @@ -1,16 +0,0 @@ -# `spree_auth_devise` gem decorators get loaded in a `to_prepare` callback -# referring to Spree classes that have not been loaded yet -# -# When this initializer is loaded we're sure that those Spree classes have been -# loaded and we load again the `spree_auth_devise` decorators to effectively -# apply them. -# -# Give a look at `if defined?(Spree::Admin::BaseController)` in the following file -# to get an example: -# https://github.com/openfoodfoundation/spree_auth_devise/blob/spree-upgrade-intermediate/app/controllers/spree/admin/admin_controller_decorator.rb#L1 -# -# TODO: remove this hack once we get to Spree 3.0 -gem_dir = Gem::Specification.find_by_name("spree_auth_devise").gem_dir -Dir.glob(File.join(gem_dir, 'app/**/*_decorator*.rb')) do |c| - load c -end diff --git a/lib/spree/authentication_helpers.rb b/lib/spree/authentication_helpers.rb new file mode 100644 index 0000000000..8ec570fc99 --- /dev/null +++ b/lib/spree/authentication_helpers.rb @@ -0,0 +1,26 @@ +module Spree + module AuthenticationHelpers + def self.included(receiver) + receiver.send :helper_method, :spree_current_user + receiver.send :helper_method, :spree_login_path + receiver.send :helper_method, :spree_signup_path + receiver.send :helper_method, :spree_logout_path + end + + def spree_current_user + current_spree_user + end + + def spree_login_path + spree.login_path + end + + def spree_signup_path + spree.signup_path + end + + def spree_logout_path + spree.logout_path + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index cad940fac8..b10e48068a 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -128,7 +128,7 @@ RSpec.configure do |config| spree_config.auto_capture = true end - Spree::Auth::Config[:signout_after_password_change] = false + AuthConfig[:signout_after_password_change] = false Spree::Api::Config[:requires_authentication] = true end From 7c0087cb3079e252e25a2e8d01a5f486dbad5905 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Sat, 6 Jul 2019 00:02:40 +0100 Subject: [PATCH 12/36] Remove reference to empty spree_auth css and js files from spree_auth_devise --- app/assets/javascripts/admin/all.js | 1 - app/assets/stylesheets/admin/all.scss | 1 - 2 files changed, 2 deletions(-) diff --git a/app/assets/javascripts/admin/all.js b/app/assets/javascripts/admin/all.js index 80625cfa55..d5600915d7 100644 --- a/app/assets/javascripts/admin/all.js +++ b/app/assets/javascripts/admin/all.js @@ -15,7 +15,6 @@ //= require angular-animate //= require angular-sanitize //= require admin/spree_backend -//= require admin/spree_auth //= require admin/spree_paypal_express //= require ../shared/ng-infinite-scroll.min.js //= require ../shared/ng-tags-input.min.js diff --git a/app/assets/stylesheets/admin/all.scss b/app/assets/stylesheets/admin/all.scss index 0e075ccc90..376c924105 100644 --- a/app/assets/stylesheets/admin/all.scss +++ b/app/assets/stylesheets/admin/all.scss @@ -5,7 +5,6 @@ * *= require admin/spree_backend - *= require admin/spree_auth *= require jquery-ui-timepicker-addon *= require shared/textAngular From 1a64a737d4c160de7b2eece50fde918e50e7aca1 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Sat, 6 Jul 2019 10:50:41 +0100 Subject: [PATCH 13/36] Add ActionController::Metal frorm spree_auth_devise for api authentication --- app/controllers/metal_decorator.rb | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 app/controllers/metal_decorator.rb diff --git a/app/controllers/metal_decorator.rb b/app/controllers/metal_decorator.rb new file mode 100644 index 0000000000..18ec22e4c8 --- /dev/null +++ b/app/controllers/metal_decorator.rb @@ -0,0 +1,6 @@ +# For the API +ActionController::Metal.class_eval do + def spree_current_user + @spree_current_user ||= env['warden'].user + end +end From f5579968176c710485b4b9ac2ca3d16cda158949 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Sat, 6 Jul 2019 11:28:31 +0100 Subject: [PATCH 14/36] Add deface overrides from spree_auth_devise for the users menu tab, the admin top bar and the shared login bar (maybe dead code this last one) --- app/overrides/admin_tab.rb | 7 +++++++ app/overrides/auth_admin_login_navigation_bar.rb | 5 +++++ app/overrides/auth_shared_login_bar.rb | 6 ++++++ 3 files changed, 18 insertions(+) create mode 100644 app/overrides/admin_tab.rb create mode 100644 app/overrides/auth_admin_login_navigation_bar.rb create mode 100644 app/overrides/auth_shared_login_bar.rb diff --git a/app/overrides/admin_tab.rb b/app/overrides/admin_tab.rb new file mode 100644 index 0000000000..d0c3cf33c3 --- /dev/null +++ b/app/overrides/admin_tab.rb @@ -0,0 +1,7 @@ +Deface::Override.new(:virtual_path => "spree/layouts/admin", + :name => "user_admin_tabs", + :insert_bottom => "[data-hook='admin_tabs'], #admin_tabs[data-hook]", + :partial => "spree/admin/users_tab", + :disabled => false, + :original => '031652cf5a054796022506622082ab6d2693699f') + diff --git a/app/overrides/auth_admin_login_navigation_bar.rb b/app/overrides/auth_admin_login_navigation_bar.rb new file mode 100644 index 0000000000..cb9aa807c8 --- /dev/null +++ b/app/overrides/auth_admin_login_navigation_bar.rb @@ -0,0 +1,5 @@ +Deface::Override.new(:virtual_path => "spree/layouts/admin", + :name => "auth_admin_login_navigation_bar", + :insert_top => "[data-hook='admin_login_navigation_bar'], #admin_login_navigation_bar[data-hook]", + :partial => "spree/layouts/admin/login_nav", + :original => '841227d0aedf7909d62237d8778df99100087715') diff --git a/app/overrides/auth_shared_login_bar.rb b/app/overrides/auth_shared_login_bar.rb new file mode 100644 index 0000000000..a833e46d08 --- /dev/null +++ b/app/overrides/auth_shared_login_bar.rb @@ -0,0 +1,6 @@ +Deface::Override.new(:virtual_path => "spree/shared/_nav_bar", + :name => "auth_shared_login_bar", + :insert_before => "li#search-bar", + :partial => "spree/shared/login_bar", + :disabled => false, + :original => 'eb3fa668cd98b6a1c75c36420ef1b238a1fc55ac') From b1cd950051a2343140976f6a5bee0700270ef645 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Sun, 7 Jul 2019 17:12:54 +0100 Subject: [PATCH 15/36] Add missing translation keys from spree_auth_devise --- config/locales/en.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index fe94c0fda4..4567533b19 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -103,8 +103,8 @@ en: confirmation_not_sent: "Error sending confirmation email" user_registrations: spree_user: - signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please open the link to activate your account." - unknown_error: "Something went wrong while creating your account. Check your email address and try again." + signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please open the link to activate your account." + unknown_error: "Something went wrong while creating your account. Check your email address and try again." failure: invalid: | Invalid email or password. @@ -116,6 +116,8 @@ en: user_passwords: spree_user: updated_not_active: "Your password has been reset, but your email has not been confirmed yet." + updated: "Your password was changed successfully. You are now signed in." + send_instructions: "You will receive an email with instructions about how to confirm your account in a few minutes." models: order_cycle: From 05a72be273a151fd65692685f61b84ec9ff5e1c6 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Sun, 7 Jul 2019 17:53:12 +0100 Subject: [PATCH 16/36] Move handle_asynchronously :send_reset_password_instructions to after send_reset_password_instructions declaration This was as it was before the merge of user_decorator and user, the declaration was in the original class and the handle_asynchronously part was in the decorator which was loaded after the main user class from spree_auth_devise, this commit restores the order and fixes a spec in authentication_spec --- app/models/spree/user.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/models/spree/user.rb b/app/models/spree/user.rb index 138ea9f47b..8c56863932 100644 --- a/app/models/spree/user.rb +++ b/app/models/spree/user.rb @@ -21,10 +21,6 @@ module Spree scope :admin, lambda { includes(:spree_roles).where("#{roles_table_name}.name" => "admin") } scope :registered, where("#{users_table_name}.email NOT LIKE ?", "%@example.net") - # handle_asynchronously will define send_reset_password_instructions_with_delay. - # If handle_asynchronously is called twice, we get an infinite job loop. - handle_asynchronously :send_reset_password_instructions unless method_defined? :send_reset_password_instructions_with_delay - has_many :enterprise_roles, dependent: :destroy has_many :enterprises, through: :enterprise_roles has_many :owned_enterprises, class_name: 'Enterprise', foreign_key: :owner_id, inverse_of: :owner @@ -73,6 +69,9 @@ module Spree generate_reset_password_token! UserMailer.reset_password_instructions(self.id).deliver end + # handle_asynchronously will define send_reset_password_instructions_with_delay. + # If handle_asynchronously is called twice, we get an infinite job loop. + handle_asynchronously :send_reset_password_instructions unless method_defined? :send_reset_password_instructions_with_delay def known_users if admin? From c8ac64566fdc173bde6dbf07d4daacb0f08cf4ba Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Sun, 7 Jul 2019 22:04:04 +0100 Subject: [PATCH 17/36] Merge spree/users_controller_decorator into spree/user_controller --- app/controllers/spree/users_controller.rb | 15 +++++++++++++- .../spree/users_controller_decorator.rb | 20 ------------------- 2 files changed, 14 insertions(+), 21 deletions(-) delete mode 100644 app/controllers/spree/users_controller_decorator.rb diff --git a/app/controllers/spree/users_controller.rb b/app/controllers/spree/users_controller.rb index 1de4b0eafe..100005400f 100644 --- a/app/controllers/spree/users_controller.rb +++ b/app/controllers/spree/users_controller.rb @@ -1,13 +1,26 @@ class Spree::UsersController < Spree::StoreController + layout 'darkswarm' ssl_required skip_before_filter :set_current_order, :only => :show prepend_before_filter :load_object, :only => [:show, :edit, :update] prepend_before_filter :authorize_actions, :only => :new include Spree::Core::ControllerHelpers + include I18nHelper + before_filter :set_locale + before_filter :enable_embedded_shopfront + + # Ignores invoice orders, only order where state: 'complete' def show - @orders = @user.orders.complete.order('completed_at desc') + @orders = @user.orders.where(state: 'complete').order('completed_at desc') + @unconfirmed_email = spree_current_user.unconfirmed_email + end + + # Endpoint for queries to check if a user is already registered + def registered_email + user = Spree.user_class.find_by_email params[:email] + render json: { registered: user.present? } end def create diff --git a/app/controllers/spree/users_controller_decorator.rb b/app/controllers/spree/users_controller_decorator.rb deleted file mode 100644 index e8073e7bbb..0000000000 --- a/app/controllers/spree/users_controller_decorator.rb +++ /dev/null @@ -1,20 +0,0 @@ -Spree::UsersController.class_eval do - layout 'darkswarm' - include I18nHelper - - before_filter :set_locale - before_filter :enable_embedded_shopfront - - # Override of spree_auth_devise default - # Ignores invoice orders, only order where state: 'complete' - def show - @orders = @user.orders.where(state: 'complete').order('completed_at desc') - @unconfirmed_email = spree_current_user.unconfirmed_email - end - - # Endpoint for queries to check if a user is already registered - def registered_email - user = Spree.user_class.find_by_email params[:email] - render json: { registered: user.present? } - end -end From 92968c5efefac2fafdc946c100f5f0da05d23021 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Sun, 7 Jul 2019 22:06:18 +0100 Subject: [PATCH 18/36] Merge spree/users_sessions_controller into spree/users_sessions from spree_auth_devise --- .../spree/user_sessions_controller.rb | 10 +++---- .../user_sessions_controller_decorator.rb | 29 ------------------- 2 files changed, 5 insertions(+), 34 deletions(-) delete mode 100644 app/controllers/spree/user_sessions_controller_decorator.rb diff --git a/app/controllers/spree/user_sessions_controller.rb b/app/controllers/spree/user_sessions_controller.rb index fee05ebf84..5975f7b159 100644 --- a/app/controllers/spree/user_sessions_controller.rb +++ b/app/controllers/spree/user_sessions_controller.rb @@ -12,19 +12,19 @@ class Spree::UserSessionsController < Devise::SessionsController ssl_required :new, :create, :destroy, :update ssl_allowed :login_bar + before_filter :set_checkout_redirect, only: :create + def create authenticate_spree_user! if spree_user_signed_in? respond_to do |format| format.html { - flash[:success] = Spree.t(:logged_in_succesfully) + flash[:success] = t('devise.success.logged_in_succesfully') redirect_back_or_default(after_sign_in_path_for(spree_current_user)) } format.js { - render :json => {:user => spree_current_user, - :ship_address => spree_current_user.ship_address, - :bill_address => spree_current_user.bill_address}.to_json + render json: { email: spree_current_user.login }, status: :ok } end else @@ -34,7 +34,7 @@ class Spree::UserSessionsController < Devise::SessionsController render :new } format.js { - render :json => { error: t('devise.failure.invalid') }, status: :unprocessable_entity + render json: { message: t('devise.failure.invalid') }, status: :unauthorized } end end diff --git a/app/controllers/spree/user_sessions_controller_decorator.rb b/app/controllers/spree/user_sessions_controller_decorator.rb deleted file mode 100644 index cdc202cca5..0000000000 --- a/app/controllers/spree/user_sessions_controller_decorator.rb +++ /dev/null @@ -1,29 +0,0 @@ -Spree::UserSessionsController.class_eval do - before_filter :set_checkout_redirect, only: :create - - def create - authenticate_spree_user! - - if spree_user_signed_in? - respond_to do |format| - format.html { - flash[:success] = t('devise.success.logged_in_succesfully') - redirect_back_or_default(after_sign_in_path_for(spree_current_user)) - } - format.js { - render json: { email: spree_current_user.login }, status: :ok - } - end - else - respond_to do |format| - format.html { - flash.now[:error] = t('devise.failure.invalid') - render :new - } - format.js { - render json: { message: t('devise.failure.invalid') }, status: :unauthorized - } - end - end - end -end From dcbdfbb0813cdb0bd7d10e9f961b04d2562f4e94 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Sun, 7 Jul 2019 22:52:32 +0100 Subject: [PATCH 19/36] Fix rubocop issues in multiple files copied from spree_auth_devise, mostly hash rockets --- .../spree/admin/users_controller.rb | 111 +++++++++-------- .../spree/user_passwords_controller.rb | 79 ++++++------ .../spree/user_registrations_controller.rb | 114 +++++++++--------- .../spree/user_sessions_controller.rb | 79 ++++++------ app/controllers/spree/users_controller.rb | 96 ++++++++------- app/mailers/spree/user_mailer.rb | 9 +- app/models/spree/auth_configuration.rb | 4 +- app/models/spree/user.rb | 112 +++++++++-------- app/overrides/admin_tab.rb | 13 +- .../auth_admin_login_navigation_bar.rb | 10 +- app/overrides/auth_shared_login_bar.rb | 12 +- 11 files changed, 333 insertions(+), 306 deletions(-) diff --git a/app/controllers/spree/admin/users_controller.rb b/app/controllers/spree/admin/users_controller.rb index 9ecaff2845..17ab1d041d 100644 --- a/app/controllers/spree/admin/users_controller.rb +++ b/app/controllers/spree/admin/users_controller.rb @@ -1,18 +1,19 @@ module Spree module Admin class UsersController < ResourceController - rescue_from Spree::User::DestroyWithOrdersError, :with => :user_destroy_with_orders_error + rescue_from Spree::User::DestroyWithOrdersError, with: :user_destroy_with_orders_error - after_filter :sign_in_if_change_own_password, :only => :update + after_filter :sign_in_if_change_own_password, only: :update # http://spreecommerce.com/blog/2010/11/02/json-hijacking-vulnerability/ - before_filter :check_json_authenticity, :only => :index - before_filter :load_roles, :only => [:edit, :new, :update, :create, :generate_api_key, :clear_api_key] + before_filter :check_json_authenticity, only: :index + before_filter :load_roles, only: [:edit, :new, :update, :create, + :generate_api_key, :clear_api_key] def index respond_with(@collection) do |format| format.html - format.json { render :json => json_data } + format.json { render json: json_data } end end @@ -25,7 +26,7 @@ module Spree if @user.save if roles - @user.spree_roles = roles.reject(&:blank?).collect{|r| Spree::Role.find(r)} + @user.spree_roles = roles.reject(&:blank?).collect{ |r| Spree::Role.find(r) } end flash.now[:success] = Spree.t(:created_successfully) @@ -42,14 +43,12 @@ module Spree if @user.update_attributes(params[:user]) if roles - @user.spree_roles = roles.reject(&:blank?).collect{|r| Spree::Role.find(r)} + @user.spree_roles = roles.reject(&:blank?).collect{ |r| Spree::Role.find(r) } end flash.now[:success] = Spree.t(:account_updated) - render :edit - else - render :edit end + render :edit end def generate_api_key @@ -68,57 +67,65 @@ module Spree protected - def collection - return @collection if @collection.present? - if request.xhr? && params[:q].present? - #disabling proper nested include here due to rails 3.1 bug - #@collection = User.includes(:bill_address => [:state, :country], :ship_address => [:state, :country]). - @collection = Spree::User.includes(:bill_address, :ship_address) - .where("spree_users.email #{LIKE} :search - OR (spree_addresses.firstname #{LIKE} :search AND spree_addresses.id = spree_users.bill_address_id) - OR (spree_addresses.lastname #{LIKE} :search AND spree_addresses.id = spree_users.bill_address_id) - OR (spree_addresses.firstname #{LIKE} :search AND spree_addresses.id = spree_users.ship_address_id) - OR (spree_addresses.lastname #{LIKE} :search AND spree_addresses.id = spree_users.ship_address_id)", - { :search => "#{params[:q].strip}%" }) - .limit(params[:limit] || 100) - else - @search = Spree::User.registered.ransack(params[:q]) - @collection = @search.result.page(params[:page]).per(Spree::Config[:admin_products_per_page]) - end + def collection + return @collection if @collection.present? + if request.xhr? && params[:q].present? + # Disabling proper nested include here due to rails 3.1 bug + @collection = Spree::User. + includes(:bill_address, :ship_address). + where("spree_users.email #{LIKE} :search + OR (spree_addresses.firstname #{LIKE} :search + AND spree_addresses.id = spree_users.bill_address_id) + OR (spree_addresses.lastname #{LIKE} :search + AND spree_addresses.id = spree_users.bill_address_id) + OR (spree_addresses.firstname #{LIKE} :search + AND spree_addresses.id = spree_users.ship_address_id) + OR (spree_addresses.lastname #{LIKE} :search + AND spree_addresses.id = spree_users.ship_address_id)", + search: "#{params[:q].strip}%"). + limit(params[:limit] || 100) + else + @search = Spree::User.registered.ransack(params[:q]) + @collection = @search. + result. + page(params[:page]). + per(Spree::Config[:admin_products_per_page]) end + end private - # handling raise from Spree::Admin::ResourceController#destroy - def user_destroy_with_orders_error - invoke_callbacks(:destroy, :fails) - render :status => :forbidden, :text => Spree.t(:error_user_destroy_with_orders) - end + # handling raise from Spree::Admin::ResourceController#destroy + def user_destroy_with_orders_error + invoke_callbacks(:destroy, :fails) + render status: :forbidden, text: Spree.t(:error_user_destroy_with_orders) + end - # Allow different formats of json data to suit different ajax calls - def json_data - json_format = params[:json_format] or 'default' - case json_format - when 'basic' - collection.map { |u| { 'id' => u.id, 'name' => u.email } }.to_json - else - address_fields = [:firstname, :lastname, :address1, :address2, :city, :zipcode, :phone, :state_name, :state_id, :country_id] - includes = { :only => address_fields , :include => { :state => { :only => :name }, :country => { :only => :name } } } + # Allow different formats of json data to suit different ajax calls + def json_data + json_format = params[:json_format] || 'default' + case json_format + when 'basic' + collection.map { |u| { 'id' => u.id, 'name' => u.email } }.to_json + else + address_fields = [:firstname, :lastname, :address1, :address2, :city, + :zipcode, :phone, :state_name, :state_id, :country_id] + includes = { only: address_fields, include: { state: { only: :name }, + country: { only: :name } } } - collection.to_json(:only => [:id, :email], :include => - { :bill_address => includes, :ship_address => includes }) - end + collection.to_json(only: [:id, :email], include: + { bill_address: includes, ship_address: includes }) end + end - def sign_in_if_change_own_password - if spree_current_user == @user && @user.password.present? - sign_in(@user, :event => :authentication, :bypass => true) - end - end + def sign_in_if_change_own_password + return unless spree_current_user == @user && @user.password.present? + sign_in(@user, event: :authentication, bypass: true) + end - def load_roles - @roles = Spree::Role.scoped - end + def load_roles + @roles = Spree::Role.scoped + end end end end diff --git a/app/controllers/spree/user_passwords_controller.rb b/app/controllers/spree/user_passwords_controller.rb index 0638fa8d9e..d6858c99f3 100644 --- a/app/controllers/spree/user_passwords_controller.rb +++ b/app/controllers/spree/user_passwords_controller.rb @@ -1,47 +1,48 @@ -class Spree::UserPasswordsController < Devise::PasswordsController - helper 'spree/base', 'spree/store' +module Spree + class UserPasswordsController < Devise::PasswordsController + helper 'spree/base', 'spree/store' - if defined?(Spree::Dash) - helper 'spree/analytics' - end + if defined?(Spree::Dash) + helper 'spree/analytics' + end - include Spree::Core::ControllerHelpers::Auth - include Spree::Core::ControllerHelpers::Common - include Spree::Core::ControllerHelpers::Order - include Spree::Core::ControllerHelpers::SSL + include Spree::Core::ControllerHelpers::Auth + include Spree::Core::ControllerHelpers::Common + include Spree::Core::ControllerHelpers::Order + include Spree::Core::ControllerHelpers::SSL - ssl_required + ssl_required - # Overridden due to bug in Devise. - # respond_with resource, :location => new_session_path(resource_name) - # is generating bad url /session/new.user - # - # overridden to: - # respond_with resource, :location => spree.login_path - # - def create - self.resource = resource_class.send_reset_password_instructions(params[resource_name]) + # Overridden due to bug in Devise. + # respond_with resource, :location => new_session_path(resource_name) + # is generating bad url /session/new.user + # + # overridden to: + # respond_with resource, :location => spree.login_path + # + def create + self.resource = resource_class.send_reset_password_instructions(params[resource_name]) - if resource.errors.empty? - set_flash_message(:notice, :send_instructions) if is_navigational_format? - respond_with resource, :location => spree.login_path - else - respond_with_navigational(resource) { render :new } + if resource.errors.empty? + set_flash_message(:notice, :send_instructions) if is_navigational_format? + respond_with resource, location: spree.login_path + else + respond_with_navigational(resource) { render :new } + end + end + + # Devise::PasswordsController allows for blank passwords. + # Silly Devise::PasswordsController! + # Fixes spree/spree#2190. + def update + if params[:spree_user][:password].blank? + self.resource = resource_class.new + resource.reset_password_token = params[:spree_user][:reset_password_token] + set_flash_message(:error, :cannot_be_blank) + render :edit + else + super + end end end - - # Devise::PasswordsController allows for blank passwords. - # Silly Devise::PasswordsController! - # Fixes spree/spree#2190. - def update - if params[:spree_user][:password].blank? - self.resource = resource_class.new - resource.reset_password_token = params[:spree_user][:reset_password_token] - set_flash_message(:error, :cannot_be_blank) - render :edit - else - super - end - end - end diff --git a/app/controllers/spree/user_registrations_controller.rb b/app/controllers/spree/user_registrations_controller.rb index 4eeacb054c..cd8687856c 100644 --- a/app/controllers/spree/user_registrations_controller.rb +++ b/app/controllers/spree/user_registrations_controller.rb @@ -1,67 +1,69 @@ -class Spree::UserRegistrationsController < Devise::RegistrationsController - helper 'spree/base', 'spree/store' +module Spree + class UserRegistrationsController < Devise::RegistrationsController + helper 'spree/base', 'spree/store' - if defined?(Spree::Dash) - helper 'spree/analytics' - end - - include Spree::Core::ControllerHelpers::Auth - include Spree::Core::ControllerHelpers::Common - include Spree::Core::ControllerHelpers::Order - include Spree::Core::ControllerHelpers::SSL - - ssl_required - before_filter :check_permissions, :only => [:edit, :update] - skip_before_filter :require_no_authentication - - # GET /resource/sign_up - def new - super - @user = resource - end - - # POST /resource/sign_up - def create - @user = build_resource(params[:spree_user]) - if resource.save - set_flash_message(:notice, :signed_up) - sign_in(:spree_user, @user) - session[:spree_user_signup] = true - associate_user - respond_with resource, location: after_sign_up_path_for(resource) - else - clean_up_passwords(resource) - render :new + if defined?(Spree::Dash) + helper 'spree/analytics' end - end - # GET /resource/edit - def edit - super - end + include Spree::Core::ControllerHelpers::Auth + include Spree::Core::ControllerHelpers::Common + include Spree::Core::ControllerHelpers::Order + include Spree::Core::ControllerHelpers::SSL - # PUT /resource - def update - super - end + ssl_required + before_filter :check_permissions, only: [:edit, :update] + skip_before_filter :require_no_authentication - # DELETE /resource - def destroy - super - end + # GET /resource/sign_up + def new + super + @user = resource + end - # GET /resource/cancel - # Forces the session data which is usually expired after sign - # in to be expired now. This is useful if the user wants to - # cancel oauth signing in/up in the middle of the process, - # removing all OAuth session data. - def cancel - super - end + # POST /resource/sign_up + def create + @user = build_resource(params[:spree_user]) + if resource.save + set_flash_message(:notice, :signed_up) + sign_in(:spree_user, @user) + session[:spree_user_signup] = true + associate_user + respond_with resource, location: after_sign_up_path_for(resource) + else + clean_up_passwords(resource) + render :new + end + end + + # GET /resource/edit + def edit + super + end + + # PUT /resource + def update + super + end + + # DELETE /resource + def destroy + super + end + + # GET /resource/cancel + # Forces the session data which is usually expired after sign + # in to be expired now. This is useful if the user wants to + # cancel oauth signing in/up in the middle of the process, + # removing all OAuth session data. + def cancel + super + end + + protected - protected def check_permissions authorize!(:create, resource) end - + end end diff --git a/app/controllers/spree/user_sessions_controller.rb b/app/controllers/spree/user_sessions_controller.rb index 5975f7b159..8e78b59b96 100644 --- a/app/controllers/spree/user_sessions_controller.rb +++ b/app/controllers/spree/user_sessions_controller.rb @@ -1,50 +1,52 @@ -class Spree::UserSessionsController < Devise::SessionsController - helper 'spree/base', 'spree/store' - if defined?(Spree::Dash) - helper 'spree/analytics' - end +module Spree + class UserSessionsController < Devise::SessionsController + helper 'spree/base', 'spree/store' + if defined?(Spree::Dash) + helper 'spree/analytics' + end - include Spree::Core::ControllerHelpers::Auth - include Spree::Core::ControllerHelpers::Common - include Spree::Core::ControllerHelpers::Order - include Spree::Core::ControllerHelpers::SSL + include Spree::Core::ControllerHelpers::Auth + include Spree::Core::ControllerHelpers::Common + include Spree::Core::ControllerHelpers::Order + include Spree::Core::ControllerHelpers::SSL - ssl_required :new, :create, :destroy, :update - ssl_allowed :login_bar + ssl_required :new, :create, :destroy, :update + ssl_allowed :login_bar - before_filter :set_checkout_redirect, only: :create + before_filter :set_checkout_redirect, only: :create - def create - authenticate_spree_user! + def create + authenticate_spree_user! - if spree_user_signed_in? - respond_to do |format| - format.html { - flash[:success] = t('devise.success.logged_in_succesfully') - redirect_back_or_default(after_sign_in_path_for(spree_current_user)) - } - format.js { - render json: { email: spree_current_user.login }, status: :ok - } - end - else - respond_to do |format| - format.html { - flash.now[:error] = t('devise.failure.invalid') - render :new - } - format.js { - render json: { message: t('devise.failure.invalid') }, status: :unauthorized - } + if spree_user_signed_in? + respond_to do |format| + format.html { + flash[:success] = t('devise.success.logged_in_succesfully') + redirect_back_or_default(after_sign_in_path_for(spree_current_user)) + } + format.js { + render json: { email: spree_current_user.login }, status: :ok + } + end + else + respond_to do |format| + format.html { + flash.now[:error] = t('devise.failure.invalid') + render :new + } + format.js { + render json: { message: t('devise.failure.invalid') }, status: :unauthorized + } + end end end - end - def nav_bar - render :partial => 'spree/shared/nav_bar' - end + def nav_bar + render partial: 'spree/shared/nav_bar' + end + + private - private def accurate_title Spree.t(:login) end @@ -53,4 +55,5 @@ class Spree::UserSessionsController < Devise::SessionsController redirect_to(session["spree_user_return_to"] || default) session["spree_user_return_to"] = nil end + end end diff --git a/app/controllers/spree/users_controller.rb b/app/controllers/spree/users_controller.rb index 100005400f..d958e6186b 100644 --- a/app/controllers/spree/users_controller.rb +++ b/app/controllers/spree/users_controller.rb @@ -1,56 +1,59 @@ -class Spree::UsersController < Spree::StoreController - layout 'darkswarm' - ssl_required - skip_before_filter :set_current_order, :only => :show - prepend_before_filter :load_object, :only => [:show, :edit, :update] - prepend_before_filter :authorize_actions, :only => :new +module Spree + class UsersController < Spree::StoreController + layout 'darkswarm' + ssl_required + skip_before_filter :set_current_order, only: :show + prepend_before_filter :load_object, only: [:show, :edit, :update] + prepend_before_filter :authorize_actions, only: :new - include Spree::Core::ControllerHelpers - include I18nHelper + include Spree::Core::ControllerHelpers + include I18nHelper - before_filter :set_locale - before_filter :enable_embedded_shopfront + before_filter :set_locale + before_filter :enable_embedded_shopfront - # Ignores invoice orders, only order where state: 'complete' - def show - @orders = @user.orders.where(state: 'complete').order('completed_at desc') - @unconfirmed_email = spree_current_user.unconfirmed_email - end - - # Endpoint for queries to check if a user is already registered - def registered_email - user = Spree.user_class.find_by_email params[:email] - render json: { registered: user.present? } - end - - def create - @user = Spree::User.new(params[:user]) - if @user.save - - if current_order - session[:guest_token] = nil - end - - redirect_back_or_default(root_url) - else - render :new + # Ignores invoice orders, only order where state: 'complete' + def show + @orders = @user.orders.where(state: 'complete').order('completed_at desc') + @unconfirmed_email = spree_current_user.unconfirmed_email end - end - def update - if @user.update_attributes(params[:user]) - if params[:user][:password].present? - # this logic needed b/c devise wants to log us out after password changes - user = Spree::User.reset_password_by_token(params[:user]) - sign_in(@user, :event => :authentication, :bypass => !AuthConfig[:signout_after_password_change]) - end - redirect_to spree.account_url, :notice => Spree.t(:account_updated) - else - render :edit + # Endpoint for queries to check if a user is already registered + def registered_email + user = Spree.user_class.find_by_email params[:email] + render json: { registered: user.present? } end - end - private + def create + @user = Spree::User.new(params[:user]) + if @user.save + + if current_order + session[:guest_token] = nil + end + + redirect_back_or_default(root_url) + else + render :new + end + end + + def update + if @user.update_attributes(params[:user]) + if params[:user][:password].present? + # this logic needed b/c devise wants to log us out after password changes + Spree::User.reset_password_by_token(params[:user]) + sign_in(@user, event: :authentication, + bypass: !AuthConfig[:signout_after_password_change]) + end + redirect_to spree.account_url, notice: Spree.t(:account_updated) + else + render :edit + end + end + + private + def load_object @user ||= spree_current_user if @user @@ -67,4 +70,5 @@ class Spree::UsersController < Spree::StoreController def accurate_title Spree.t(:my_account) end + end end diff --git a/app/mailers/spree/user_mailer.rb b/app/mailers/spree/user_mailer.rb index be904c3d45..b7aa292b55 100644 --- a/app/mailers/spree/user_mailer.rb +++ b/app/mailers/spree/user_mailer.rb @@ -4,11 +4,12 @@ module Spree def reset_password_instructions(user) recipient = user.respond_to?(:id) ? user : Spree.user_class.find(user) - @edit_password_reset_url = spree.edit_spree_user_password_url(:reset_password_token => recipient.reset_password_token) + @edit_password_reset_url = spree. + edit_spree_user_password_url(reset_password_token: recipient.reset_password_token) - mail(:to => recipient.email, :from => from_address, - :subject => Spree::Config[:site_name] + ' ' + - I18n.t(:subject, :scope => [:devise, :mailer, :reset_password_instructions])) + mail(to: recipient.email, from: from_address, + subject: Spree::Config[:site_name] + ' ' + + I18n.t(:subject, scope: [:devise, :mailer, :reset_password_instructions])) end def signup_confirmation(user) diff --git a/app/models/spree/auth_configuration.rb b/app/models/spree/auth_configuration.rb index f4ccc91fcb..1b9ed7ff7f 100644 --- a/app/models/spree/auth_configuration.rb +++ b/app/models/spree/auth_configuration.rb @@ -1,6 +1,6 @@ module Spree class AuthConfiguration < Preferences::Configuration - preference :registration_step, :boolean, :default => true - preference :signout_after_password_change, :boolean, :default => true + preference :registration_step, :boolean, default: true + preference :signout_after_password_change, :boolean, default: true end end diff --git a/app/models/spree/user.rb b/app/models/spree/user.rb index 8c56863932..cad09a6073 100644 --- a/app/models/spree/user.rb +++ b/app/models/spree/user.rb @@ -3,28 +3,31 @@ module Spree include Core::UserBanners devise :database_authenticatable, :token_authenticatable, :registerable, :recoverable, - :rememberable, :trackable, :validatable, :encryptable, :encryptor => 'authlogic_sha512' + :rememberable, :trackable, :validatable, :encryptable, encryptor: 'authlogic_sha512' has_many :orders - belongs_to :ship_address, :foreign_key => 'ship_address_id', :class_name => 'Spree::Address' - belongs_to :bill_address, :foreign_key => 'bill_address_id', :class_name => 'Spree::Address' + belongs_to :ship_address, foreign_key: 'ship_address_id', class_name: 'Spree::Address' + belongs_to :bill_address, foreign_key: 'bill_address_id', class_name: 'Spree::Address' before_validation :set_login before_destroy :check_completed_orders # Setup accessible (or protected) attributes for your model - attr_accessible :email, :password, :password_confirmation, :remember_me, :persistence_token, :login + attr_accessible :email, :password, :password_confirmation, + :remember_me, :persistence_token, :login users_table_name = User.table_name roles_table_name = Role.table_name scope :admin, lambda { includes(:spree_roles).where("#{roles_table_name}.name" => "admin") } - scope :registered, where("#{users_table_name}.email NOT LIKE ?", "%@example.net") + scope :registered, -> { where("#{users_table_name}.email NOT LIKE ?", "%@example.net") } has_many :enterprise_roles, dependent: :destroy has_many :enterprises, through: :enterprise_roles - has_many :owned_enterprises, class_name: 'Enterprise', foreign_key: :owner_id, inverse_of: :owner - has_many :owned_groups, class_name: 'EnterpriseGroup', foreign_key: :owner_id, inverse_of: :owner + has_many :owned_enterprises, class_name: 'Enterprise', + foreign_key: :owner_id, inverse_of: :owner + has_many :owned_groups, class_name: 'EnterpriseGroup', + foreign_key: :owner_id, inverse_of: :owner has_many :customers has_many :credit_cards @@ -33,7 +36,8 @@ module Spree accepts_nested_attributes_for :bill_address accepts_nested_attributes_for :ship_address - attr_accessible :enterprise_ids, :enterprise_roles_attributes, :enterprise_limit, :locale, :bill_address_attributes, :ship_address_attributes + attr_accessible :enterprise_ids, :enterprise_roles_attributes, :enterprise_limit, + :locale, :bill_address_attributes, :ship_address_attributes after_create :associate_customers validate :limit_owned_enterprises @@ -41,16 +45,20 @@ module Spree # We use the same options as Spree and add :confirmable devise :confirmable, reconfirmable: true # TODO: Later versions of devise have a dedicated after_confirmation callback, so use that - after_update :welcome_after_confirm, if: lambda { confirmation_token_changed? && confirmation_token.nil? } + after_update :welcome_after_confirm, if: lambda { + confirmation_token_changed? && confirmation_token.nil? + } class DestroyWithOrdersError < StandardError; end - # Creates an anonymous user. An anonymous user is basically an auto-generated +User+ account that is created for the customer - # behind the scenes and its completely transparently to the customer. All +Orders+ must have a +User+ so this is necessary - # when adding to the "cart" (which is really an order) and before the customer has a chance to provide an email or to register. + # Creates an anonymous user. An anonymous user is basically an auto-generated +User+ account + # that is created for the customer behind the scenes and it's transparent to the customer. + # All +Orders+ must have a +User+ so this is necessary when adding to the "cart" (an order) + # and before the customer has a chance to provide an email or to register. def self.anonymous! token = User.generate_token(:persistence_token) - User.create(:email => "#{token}@example.net", :password => token, :password_confirmation => token, :persistence_token => token) + User.create(email: "#{token}@example.net", + password: token, password_confirmation: token, persistence_token: token) end def self.admin_created? @@ -67,7 +75,7 @@ module Spree def send_reset_password_instructions generate_reset_password_token! - UserMailer.reset_password_instructions(self.id).deliver + UserMailer.reset_password_instructions(id).deliver end # handle_asynchronously will define send_reset_password_instructions_with_delay. # If handle_asynchronously is called twice, we get an infinite job loop. @@ -79,7 +87,8 @@ module Spree else Spree::User .includes(:enterprises) - .where("enterprises.id IN (SELECT enterprise_id FROM enterprise_roles WHERE user_id = ?)", id) + .where("enterprises.id IN (SELECT enterprise_id FROM enterprise_roles WHERE user_id = ?)", + id) end end @@ -99,9 +108,8 @@ module Spree def welcome_after_confirm # Send welcome email if we are confirming an user's email # Note: this callback only runs on email confirmation - if confirmed? && unconfirmed_email.nil? && !unconfirmed_email_changed? - send_signup_confirmation - end + return unless confirmed? && unconfirmed_email.nil? && !unconfirmed_email_changed? + send_signup_confirmation end def send_signup_confirmation @@ -129,46 +137,48 @@ module Spree end protected - def password_required? - !persisted? || password.present? || password_confirmation.present? - end + + def password_required? + !persisted? || password.present? || password_confirmation.present? + end private - def check_completed_orders - raise DestroyWithOrdersError if orders.complete.present? - end + def check_completed_orders + raise DestroyWithOrdersError if orders.complete.present? + end - def set_login - # for now force login to be same as email, eventually we will make this configurable, etc. - self.login ||= self.email if self.email - end + def set_login + # for now force login to be same as email, eventually we will make this configurable, etc. + self.login ||= email if email + end - # Generate a friendly string randomically to be used as token. - def self.friendly_token - SecureRandom.base64(15).tr('+/=', '-_ ').strip.delete("\n") - end + # Generate a friendly string randomically to be used as token. + def self.friendly_token + SecureRandom.base64(15).tr('+/=', '-_ ').strip.delete("\n") + end - # Generate a token by looping and ensuring does not already exist. - def self.generate_token(column) - loop do - token = friendly_token - break token unless find(:first, :conditions => { column => token }) - end - end - - def limit_owned_enterprises - if owned_enterprises.size > enterprise_limit - errors.add(:owned_enterprises, I18n.t(:spree_user_enterprise_limit_error, email: email, enterprise_limit: enterprise_limit)) - end - end - - def remove_payments_in_checkout(enterprises) - enterprises.each do |enterprise| - enterprise.distributed_orders.each do |order| - order.payments.keep_if { |payment| payment.state != "checkout" } - end + # Generate a token by looping and ensuring does not already exist. + def self.generate_token(column) + loop do + token = friendly_token + break token unless find(:first, conditions: { column => token }) + end + end + + def limit_owned_enterprises + return unless owned_enterprises.size > enterprise_limit + errors.add(:owned_enterprises, I18n.t(:spree_user_enterprise_limit_error, + email: email, + enterprise_limit: enterprise_limit)) + end + + def remove_payments_in_checkout(enterprises) + enterprises.each do |enterprise| + enterprise.distributed_orders.each do |order| + order.payments.keep_if { |payment| payment.state != "checkout" } end end + end end end diff --git a/app/overrides/admin_tab.rb b/app/overrides/admin_tab.rb index d0c3cf33c3..186a7a06f7 100644 --- a/app/overrides/admin_tab.rb +++ b/app/overrides/admin_tab.rb @@ -1,7 +1,6 @@ -Deface::Override.new(:virtual_path => "spree/layouts/admin", - :name => "user_admin_tabs", - :insert_bottom => "[data-hook='admin_tabs'], #admin_tabs[data-hook]", - :partial => "spree/admin/users_tab", - :disabled => false, - :original => '031652cf5a054796022506622082ab6d2693699f') - +Deface::Override.new(virtual_path: "spree/layouts/admin", + name: "user_admin_tabs", + insert_bottom: "[data-hook='admin_tabs'], #admin_tabs[data-hook]", + partial: "spree/admin/users_tab", + disabled: false, + original: '031652cf5a054796022506622082ab6d2693699f') diff --git a/app/overrides/auth_admin_login_navigation_bar.rb b/app/overrides/auth_admin_login_navigation_bar.rb index cb9aa807c8..8a171041af 100644 --- a/app/overrides/auth_admin_login_navigation_bar.rb +++ b/app/overrides/auth_admin_login_navigation_bar.rb @@ -1,5 +1,5 @@ -Deface::Override.new(:virtual_path => "spree/layouts/admin", - :name => "auth_admin_login_navigation_bar", - :insert_top => "[data-hook='admin_login_navigation_bar'], #admin_login_navigation_bar[data-hook]", - :partial => "spree/layouts/admin/login_nav", - :original => '841227d0aedf7909d62237d8778df99100087715') +Deface::Override.new(virtual_path: "spree/layouts/admin", + name: "auth_admin_login_navigation_bar", + insert_top: "[data-hook='admin_login_navigation_bar'], #admin_login_navigation_bar[data-hook]", + partial: "spree/layouts/admin/login_nav", + original: '841227d0aedf7909d62237d8778df99100087715') diff --git a/app/overrides/auth_shared_login_bar.rb b/app/overrides/auth_shared_login_bar.rb index a833e46d08..734c9f8112 100644 --- a/app/overrides/auth_shared_login_bar.rb +++ b/app/overrides/auth_shared_login_bar.rb @@ -1,6 +1,6 @@ -Deface::Override.new(:virtual_path => "spree/shared/_nav_bar", - :name => "auth_shared_login_bar", - :insert_before => "li#search-bar", - :partial => "spree/shared/login_bar", - :disabled => false, - :original => 'eb3fa668cd98b6a1c75c36420ef1b238a1fc55ac') +Deface::Override.new(virtual_path: "spree/shared/_nav_bar", + name: "auth_shared_login_bar", + insert_before: "li#search-bar", + partial: "spree/shared/login_bar", + disabled: false, + original: 'eb3fa668cd98b6a1c75c36420ef1b238a1fc55ac') From 8efd69c3d16162642b78b51dd549560454967229 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Mon, 8 Jul 2019 12:56:49 +0100 Subject: [PATCH 20/36] Remove unnecessary checkout registration code, it's not used in OFN --- app/controllers/checkout_controller.rb | 1 - app/controllers/spree/checkout_controller.rb | 35 -------------------- config/routes/spree.rb | 3 -- 3 files changed, 39 deletions(-) diff --git a/app/controllers/checkout_controller.rb b/app/controllers/checkout_controller.rb index 1ef23d92a9..c1fe12ce53 100644 --- a/app/controllers/checkout_controller.rb +++ b/app/controllers/checkout_controller.rb @@ -8,7 +8,6 @@ class CheckoutController < Spree::CheckoutController prepend_before_filter :require_order_cycle prepend_before_filter :require_distributor_chosen - skip_before_filter :check_registration before_filter :enable_embedded_shopfront include OrderCyclesHelper diff --git a/app/controllers/spree/checkout_controller.rb b/app/controllers/spree/checkout_controller.rb index c5eb64a62f..6323cf8ce0 100644 --- a/app/controllers/spree/checkout_controller.rb +++ b/app/controllers/spree/checkout_controller.rb @@ -25,43 +25,8 @@ module Spree redirect_to main_app.checkout_path end - before_filter :check_registration, :except => [:registration, :update_registration] - - def registration - @user = Spree::User.new - end - - def update_registration - fire_event("spree.user.signup", :order => current_order) - # hack - temporarily change the state to something other than cart so we can validate the order email address - current_order.state = current_order.checkout_steps.first - current_order.update_attribute(:email, params[:order][:email]) - # Run validations, then check for errors - # valid? may return false if the address state validations are present - current_order.valid? - if current_order.errors[:email].blank? - redirect_to checkout_path - else - flash[:registration_error] = t(:email_is_invalid, :scope => [:errors, :messages]) - @user = Spree::User.new - render 'registration' - end - end - private - def skip_state_validation? - %w(registration update_registration).include?(params[:action]) - end - - # Introduces a registration step whenever the +registration_step+ preference is true. - def check_registration - return unless AuthConfig[:registration_step] - return if spree_current_user or current_order.email - store_location - redirect_to spree.checkout_registration_path - end - # Overrides the equivalent method defined in Spree::Core. This variation of the method will ensure that users # are redirected to the tokenized order url unless authenticated as a registered user. def completion_route diff --git a/config/routes/spree.rb b/config/routes/spree.rb index a5469bdf8b..5613ae9c11 100644 --- a/config/routes/spree.rb +++ b/config/routes/spree.rb @@ -24,9 +24,6 @@ Spree::Core::Engine.routes.draw do put '/password/change' => 'user_passwords#update', :as => :update_password end - match '/checkout/registration' => 'checkout#registration', :via => :get, :as => :checkout_registration - match '/checkout/registration' => 'checkout#update_registration', :via => :put, :as => :update_checkout_registration - resource :session do member do get :nav_bar From 9416f61fb3b20aa7d30a77e21fbebed3fbff0aa2 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Mon, 8 Jul 2019 13:04:38 +0100 Subject: [PATCH 21/36] Remove spree/checkout_controller.completion_route only used in spree/checkout_controller.update which is never used in OFN. Checkout update happpens in the checkout_controller.update --- app/controllers/spree/checkout_controller.rb | 7 ------- 1 file changed, 7 deletions(-) diff --git a/app/controllers/spree/checkout_controller.rb b/app/controllers/spree/checkout_controller.rb index 6323cf8ce0..a01750072f 100644 --- a/app/controllers/spree/checkout_controller.rb +++ b/app/controllers/spree/checkout_controller.rb @@ -27,13 +27,6 @@ module Spree private - # Overrides the equivalent method defined in Spree::Core. This variation of the method will ensure that users - # are redirected to the tokenized order url unless authenticated as a registered user. - def completion_route - return order_path(@order) if spree_current_user - spree.token_order_path(@order, @order.token) - end - def load_order @order = current_order redirect_to main_app.cart_path && return unless @order From 0101dcdd93a21c32d50107595452fc91c5eb74b2 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Mon, 8 Jul 2019 13:10:52 +0100 Subject: [PATCH 22/36] Remove unused Spree::Dash from controllers brought from spree_auth_devise --- app/controllers/spree/user_passwords_controller.rb | 4 ---- app/controllers/spree/user_registrations_controller.rb | 4 ---- app/controllers/spree/user_sessions_controller.rb | 3 --- 3 files changed, 11 deletions(-) diff --git a/app/controllers/spree/user_passwords_controller.rb b/app/controllers/spree/user_passwords_controller.rb index d6858c99f3..bf8b13d379 100644 --- a/app/controllers/spree/user_passwords_controller.rb +++ b/app/controllers/spree/user_passwords_controller.rb @@ -2,10 +2,6 @@ module Spree class UserPasswordsController < Devise::PasswordsController helper 'spree/base', 'spree/store' - if defined?(Spree::Dash) - helper 'spree/analytics' - end - include Spree::Core::ControllerHelpers::Auth include Spree::Core::ControllerHelpers::Common include Spree::Core::ControllerHelpers::Order diff --git a/app/controllers/spree/user_registrations_controller.rb b/app/controllers/spree/user_registrations_controller.rb index cd8687856c..36f0852cef 100644 --- a/app/controllers/spree/user_registrations_controller.rb +++ b/app/controllers/spree/user_registrations_controller.rb @@ -2,10 +2,6 @@ module Spree class UserRegistrationsController < Devise::RegistrationsController helper 'spree/base', 'spree/store' - if defined?(Spree::Dash) - helper 'spree/analytics' - end - include Spree::Core::ControllerHelpers::Auth include Spree::Core::ControllerHelpers::Common include Spree::Core::ControllerHelpers::Order diff --git a/app/controllers/spree/user_sessions_controller.rb b/app/controllers/spree/user_sessions_controller.rb index 8e78b59b96..ad40063d8a 100644 --- a/app/controllers/spree/user_sessions_controller.rb +++ b/app/controllers/spree/user_sessions_controller.rb @@ -1,9 +1,6 @@ module Spree class UserSessionsController < Devise::SessionsController helper 'spree/base', 'spree/store' - if defined?(Spree::Dash) - helper 'spree/analytics' - end include Spree::Core::ControllerHelpers::Auth include Spree::Core::ControllerHelpers::Common From 10e123a9c441894be956e7d8588812ff78e02d3d Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Mon, 8 Jul 2019 13:11:57 +0100 Subject: [PATCH 23/36] Move spree/authentication_helpers injection from spree initializers directly to the application_controller Also, switch from using send to public_send making rubocop happier --- app/controllers/application_controller.rb | 2 ++ config/initializers/spree.rb | 4 ---- lib/spree/authentication_helpers.rb | 8 ++++---- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index ece563a420..0edfdd76b7 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,4 +1,5 @@ require 'open_food_network/referer_parser' +require 'spree/authentication_helpers' class ApplicationController < ActionController::Base protect_from_forgery @@ -7,6 +8,7 @@ class ApplicationController < ActionController::Base before_filter :set_cache_headers # prevent cart emptying via cache when using back button #1213 include EnterprisesHelper + include Spree::AuthenticationHelpers def redirect_to(options = {}, response_status = {}) ::Rails.logger.error("Redirected by #{begin diff --git a/config/initializers/spree.rb b/config/initializers/spree.rb index 68de82143e..aff82835e8 100644 --- a/config/initializers/spree.rb +++ b/config/initializers/spree.rb @@ -42,10 +42,6 @@ Spree.config do |config| config.s3_protocol = ENV.fetch('S3_PROTOCOL', 'https') end -# Initialize authentication -require 'spree/authentication_helpers' -ApplicationController.send :include, Spree::AuthenticationHelpers - # Spree 2.0 recommends explicitly setting this here when using spree_auth_devise Spree.user_class = 'Spree::User' diff --git a/lib/spree/authentication_helpers.rb b/lib/spree/authentication_helpers.rb index 8ec570fc99..3754bb0e2a 100644 --- a/lib/spree/authentication_helpers.rb +++ b/lib/spree/authentication_helpers.rb @@ -1,10 +1,10 @@ module Spree module AuthenticationHelpers def self.included(receiver) - receiver.send :helper_method, :spree_current_user - receiver.send :helper_method, :spree_login_path - receiver.send :helper_method, :spree_signup_path - receiver.send :helper_method, :spree_logout_path + receiver.public_send :helper_method, :spree_current_user + receiver.public_send :helper_method, :spree_login_path + receiver.public_send :helper_method, :spree_signup_path + receiver.public_send :helper_method, :spree_logout_path end def spree_current_user From 36e3362fc1ac8e53c37527804ca055e906689a02 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Mon, 8 Jul 2019 13:23:18 +0100 Subject: [PATCH 24/36] Adding missing translation that is now being used after being brought from spree_auth_devise --- config/locales/en.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/config/locales/en.yml b/config/locales/en.yml index 4567533b19..9f9516153c 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2930,6 +2930,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using inventory: Inventory zipcode: Postcode weight: Weight (per kg) + error_user_destroy_with_orders: "Users with completed orders may not be deleted" actions: update: "Update" From e897eb043909d3280c585cfcac450bd8ac0d2234 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Mon, 8 Jul 2019 13:33:35 +0100 Subject: [PATCH 25/36] Remove Spree::BaseController.class_eval, these methods are already in the application helper through spree::application_helpers We can ignore the difference in spree_logout_path as spree.logout_path is the user_sessions#destroy route --- .../spree/base_controller_decorator.rb | 18 ------------------ .../core/controller_helpers/order_decorator.rb | 2 +- 2 files changed, 1 insertion(+), 19 deletions(-) delete mode 100644 app/controllers/spree/base_controller_decorator.rb diff --git a/app/controllers/spree/base_controller_decorator.rb b/app/controllers/spree/base_controller_decorator.rb deleted file mode 100644 index f907c70105..0000000000 --- a/app/controllers/spree/base_controller_decorator.rb +++ /dev/null @@ -1,18 +0,0 @@ -Spree::BaseController.class_eval do - def spree_login_path - spree.login_path - end - - def spree_signup_path - spree.signup_path - end - - def spree_logout_path - spree.destroy_spree_user_session_path - end - - def spree_current_user - current_spree_user - end -end - diff --git a/lib/spree/core/controller_helpers/order_decorator.rb b/lib/spree/core/controller_helpers/order_decorator.rb index cb644bb701..6da1b42ee6 100644 --- a/lib/spree/core/controller_helpers/order_decorator.rb +++ b/lib/spree/core/controller_helpers/order_decorator.rb @@ -15,7 +15,7 @@ Spree::Core::ControllerHelpers::Order.class_eval do end alias_method_chain :current_order, :scoped_variants - # Override definition in spree/auth/app/controllers/spree/base_controller_decorator.rb + # Override definition in Spree::Core::ControllerHelpers::Order # Do not attempt to merge incomplete and current orders. Instead, destroy the incomplete orders. def set_current_order if user = try_spree_current_user From 1681e8a5725f7f5d7f0338362e2470304a1be89a Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Mon, 8 Jul 2019 14:06:01 +0100 Subject: [PATCH 26/36] Remove unused auth config --- app/controllers/spree/users_controller.rb | 2 +- app/models/spree/auth_configuration.rb | 6 ------ config/initializers/spree.rb | 4 ---- spec/spec_helper.rb | 1 - 4 files changed, 1 insertion(+), 12 deletions(-) delete mode 100644 app/models/spree/auth_configuration.rb diff --git a/app/controllers/spree/users_controller.rb b/app/controllers/spree/users_controller.rb index d958e6186b..41d48c71de 100644 --- a/app/controllers/spree/users_controller.rb +++ b/app/controllers/spree/users_controller.rb @@ -44,7 +44,7 @@ module Spree # this logic needed b/c devise wants to log us out after password changes Spree::User.reset_password_by_token(params[:user]) sign_in(@user, event: :authentication, - bypass: !AuthConfig[:signout_after_password_change]) + bypass: true) end redirect_to spree.account_url, notice: Spree.t(:account_updated) else diff --git a/app/models/spree/auth_configuration.rb b/app/models/spree/auth_configuration.rb deleted file mode 100644 index 1b9ed7ff7f..0000000000 --- a/app/models/spree/auth_configuration.rb +++ /dev/null @@ -1,6 +0,0 @@ -module Spree - class AuthConfiguration < Preferences::Configuration - preference :registration_step, :boolean, default: true - preference :signout_after_password_change, :boolean, default: true - end -end diff --git a/config/initializers/spree.rb b/config/initializers/spree.rb index aff82835e8..c2f6a118a1 100644 --- a/config/initializers/spree.rb +++ b/config/initializers/spree.rb @@ -45,10 +45,6 @@ end # Spree 2.0 recommends explicitly setting this here when using spree_auth_devise Spree.user_class = 'Spree::User' -AuthConfig = Spree::AuthConfiguration.new -# Don't log users out when setting a new password -AuthConfig[:signout_after_password_change] = false - # TODO Work out why this is necessary # Seems like classes within OFN module become 'uninitialized' when server reloads # unless the empty module is explicity 'registered' here. Something to do with autoloading? diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b10e48068a..499a810302 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -128,7 +128,6 @@ RSpec.configure do |config| spree_config.auto_capture = true end - AuthConfig[:signout_after_password_change] = false Spree::Api::Config[:requires_authentication] = true end From 86accc227e4721e84824965db115eb405dbff00c Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Mon, 8 Jul 2019 17:36:54 +0100 Subject: [PATCH 27/36] Convert erb files brought from spree_auth_devise to haml --- app/views/spree/admin/_users_tab.html.erb | 3 --- app/views/spree/admin/_users_tab.html.haml | 2 ++ app/views/spree/admin/users/new.html.erb | 23 -------------------- app/views/spree/admin/users/new.html.haml | 15 +++++++++++++ app/views/spree/shared/_user_form.html.erb | 17 --------------- app/views/spree/shared/_user_form.html.haml | 15 +++++++++++++ app/views/spree/user_passwords/new.html.erb | 17 --------------- app/views/spree/user_passwords/new.html.haml | 14 ++++++++++++ 8 files changed, 46 insertions(+), 60 deletions(-) delete mode 100644 app/views/spree/admin/_users_tab.html.erb create mode 100644 app/views/spree/admin/_users_tab.html.haml delete mode 100644 app/views/spree/admin/users/new.html.erb create mode 100644 app/views/spree/admin/users/new.html.haml delete mode 100644 app/views/spree/shared/_user_form.html.erb create mode 100644 app/views/spree/shared/_user_form.html.haml delete mode 100755 app/views/spree/user_passwords/new.html.erb create mode 100755 app/views/spree/user_passwords/new.html.haml diff --git a/app/views/spree/admin/_users_tab.html.erb b/app/views/spree/admin/_users_tab.html.erb deleted file mode 100644 index 5b3ffc9e60..0000000000 --- a/app/views/spree/admin/_users_tab.html.erb +++ /dev/null @@ -1,3 +0,0 @@ -<% if can? :admin, Spree::User %> - <%= tab(:users, :url => spree.admin_users_path, :icon => 'icon-user') %> -<% end %> diff --git a/app/views/spree/admin/_users_tab.html.haml b/app/views/spree/admin/_users_tab.html.haml new file mode 100644 index 0000000000..8be1861f50 --- /dev/null +++ b/app/views/spree/admin/_users_tab.html.haml @@ -0,0 +1,2 @@ +- if can? :admin, Spree::User + = tab(:users, url: spree.admin_users_path, icon: 'icon-user') diff --git a/app/views/spree/admin/users/new.html.erb b/app/views/spree/admin/users/new.html.erb deleted file mode 100644 index 9891bce060..0000000000 --- a/app/views/spree/admin/users/new.html.erb +++ /dev/null @@ -1,23 +0,0 @@ -<% content_for :page_title do %> - <%= Spree.t(:new_user) %> -<% end %> - -<% content_for :page_actions do %> -
  • - <%= button_link_to Spree.t(:back_to_users_list), spree.admin_users_path, :icon => 'icon-arrow-left' %> -
  • -<% end %> - -
    - <%= render :partial => 'spree/shared/error_messages', :locals => { :target => @user } %> -
    - -
    - <%= form_for [:admin, @user] do |f| %> - <%= render :partial => 'form', :locals => { :f => f } %> - -
    - <%= render :partial => 'spree/admin/shared/new_resource_links' %> -
    - <% end %> -
    diff --git a/app/views/spree/admin/users/new.html.haml b/app/views/spree/admin/users/new.html.haml new file mode 100644 index 0000000000..9fb68e689f --- /dev/null +++ b/app/views/spree/admin/users/new.html.haml @@ -0,0 +1,15 @@ += content_for :page_title do + = Spree.t(:new_user) + += content_for :page_actions do + %li + = button_link_to Spree.t(:back_to_users_list), spree.admin_users_path, icon: 'icon-arrow-left' + +%div + = render partial: 'spree/shared/error_messages', locals: { target: @user } + +%div + = form_for [:admin, @user] do |f| + = render partial: 'form', locals: { f: f } + %div + = render partial: 'spree/admin/shared/new_resource_links' diff --git a/app/views/spree/shared/_user_form.html.erb b/app/views/spree/shared/_user_form.html.erb deleted file mode 100644 index a31902ca61..0000000000 --- a/app/views/spree/shared/_user_form.html.erb +++ /dev/null @@ -1,17 +0,0 @@ -

    - <%= f.label :email, Spree.t(:email) %>
    - <%= f.email_field :email, :class => 'title' %> -

    -
    -

    - <%= f.label :password, Spree.t(:password) %>
    - <%= f.password_field :password, :class => 'title' %> -

    - -

    - <%= f.label :password_confirmation, Spree.t(:confirm_password) %>
    - <%= f.password_field :password_confirmation, :class => 'title' %> -

    -
    - -
    diff --git a/app/views/spree/shared/_user_form.html.haml b/app/views/spree/shared/_user_form.html.haml new file mode 100644 index 0000000000..ddee06e421 --- /dev/null +++ b/app/views/spree/shared/_user_form.html.haml @@ -0,0 +1,15 @@ +%p + = f.label :email, Spree.t(:email) + %br + = f.email_field :email, class: 'title' + +%div{"id" => "password-credentials"} + %p + = f.label :password, Spree.t(:password) + %br + = f.password_field :password, class: 'title' + + %p + = f.label :password_confirmation, Spree.t(:confirm_password) + %br + = f.password_field :password_confirmation, class: 'title' diff --git a/app/views/spree/user_passwords/new.html.erb b/app/views/spree/user_passwords/new.html.erb deleted file mode 100755 index a4330e4490..0000000000 --- a/app/views/spree/user_passwords/new.html.erb +++ /dev/null @@ -1,17 +0,0 @@ -<%= render :partial => 'spree/shared/error_messages', :locals => { :target => @spree_user } %> - -
    -
    <%= Spree.t(:forgot_password) %>
    - -

    <%= Spree.t(:instructions_to_reset_password) %>

    - - <%= form_for Spree::User.new, :as => :spree_user, :url => spree.reset_password_path do |f| %> -

    - <%= f.label :email, Spree.t(:email) %>
    - <%= f.email_field :email %> -

    -

    - <%= f.submit Spree.t(:reset_password), :class => 'button primary' %> -

    - <% end %> -
    diff --git a/app/views/spree/user_passwords/new.html.haml b/app/views/spree/user_passwords/new.html.haml new file mode 100755 index 0000000000..604f7ebf8c --- /dev/null +++ b/app/views/spree/user_passwords/new.html.haml @@ -0,0 +1,14 @@ += render partial: 'spree/shared/error_messages', locals: { target: @spree_user } + +%div{"id" => "forgot-password"} + %h6= Spree.t(:forgot_password) + + %p= Spree.t(:instructions_to_reset_password) + + = form_for Spree::User.new, as: :spree_user, url: spree.reset_password_path do |f| + %p + = f.label :email, Spree.t(:email) + %br + = f.email_field :email + %p + = f.submit Spree.t(:reset_password), class: 'button primary' From 942824cd74ca4528d2f58c507352bddc6a94d49c Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Thu, 11 Jul 2019 16:37:30 +0100 Subject: [PATCH 28/36] Improve comments in UserMailer --- app/mailers/spree/user_mailer.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/mailers/spree/user_mailer.rb b/app/mailers/spree/user_mailer.rb index b7aa292b55..68d37c4b99 100644 --- a/app/mailers/spree/user_mailer.rb +++ b/app/mailers/spree/user_mailer.rb @@ -1,7 +1,10 @@ +# This mailer is configured to be the Devise mailer +# Some methods here override Devise::Mailer methods module Spree class UserMailer < BaseMailer include I18nHelper + # Overrides `Devise::Mailer.reset_password_instructions` def reset_password_instructions(user) recipient = user.respond_to?(:id) ? user : Spree.user_class.find(user) @edit_password_reset_url = spree. @@ -12,6 +15,7 @@ module Spree I18n.t(:subject, scope: [:devise, :mailer, :reset_password_instructions])) end + # This is a OFN specific email, not from Devise::Mailer def signup_confirmation(user) @user = user I18n.with_locale valid_locale(@user) do @@ -20,8 +24,7 @@ module Spree end end - # Overriding `Spree::UserMailer.confirmation_instructions` which is - # overriding `Devise::Mailer.confirmation_instructions`. + # Overrides `Devise::Mailer.confirmation_instructions` def confirmation_instructions(user, _opts) @user = user @instance = Spree::Config[:site_name] From 5378bb7b345cd2ce000ffe93cdbeb786c775945f Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Thu, 11 Jul 2019 17:45:56 +0100 Subject: [PATCH 29/36] Add adapted version of spree/admin/users_controller_spec from spree_auth_devise --- .../spree/admin/users_controller_spec.rb | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 spec/controllers/spree/admin/users_controller_spec.rb diff --git a/spec/controllers/spree/admin/users_controller_spec.rb b/spec/controllers/spree/admin/users_controller_spec.rb new file mode 100644 index 0000000000..df62b60482 --- /dev/null +++ b/spec/controllers/spree/admin/users_controller_spec.rb @@ -0,0 +1,57 @@ +require 'spec_helper' +require 'spree/testing_support/bar_ability' + +describe Spree::Admin::UsersController do + context '#authorize_admin' do + let(:user) { create(:user) } + let(:test_user) { create(:user) } + + before do + controller.stub spree_current_user: user + Spree::User.stub(:find).with(test_user.id.to_s).and_return(test_user) + user.spree_roles.clear + end + + it 'should grant access to users with an admin role' do + user.spree_roles << Spree::Role.find_or_create_by_name('admin') + spree_post :index + response.should render_template :index + end + + it "allows admins to update a user's API key" do + user.spree_roles << Spree::Role.find_or_create_by_name('admin') + test_user.should_receive(:generate_spree_api_key!).and_return(true) + puts user.id + puts test_user.id + spree_put :generate_api_key, id: test_user.id + response.should redirect_to(spree.edit_admin_user_path(test_user)) + end + + it "allows admins to clear a user's API key" do + user.spree_roles << Spree::Role.find_or_create_by_name('admin') + test_user.should_receive(:clear_spree_api_key!).and_return(true) + spree_put :clear_api_key, id: test_user.id + response.should redirect_to(spree.edit_admin_user_path(test_user)) + end + + it 'should deny access to users with an bar role' do + user.spree_roles << Spree::Role.find_or_create_by_name('bar') + Spree::Ability.register_ability(BarAbility) + spree_post :index + response.should redirect_to('/unauthorized') + end + + it 'should deny access to users with an bar role' do + user.spree_roles << Spree::Role.find_or_create_by_name('bar') + Spree::Ability.register_ability(BarAbility) + spree_post :update, id: '9' + response.should redirect_to('/unauthorized') + end + + it 'should deny access to users without an admin role' do + user.stub has_spree_role?: false + spree_post :index + response.should redirect_to('/unauthorized') + end + end +end From 7cab99efdf7ae7c8dfc9c5866a190dcb386a793c Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Thu, 11 Jul 2019 18:07:23 +0100 Subject: [PATCH 30/36] Run transpec on users_controller --- .../spree/admin/users_controller_spec.rb | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/spec/controllers/spree/admin/users_controller_spec.rb b/spec/controllers/spree/admin/users_controller_spec.rb index df62b60482..a42630964d 100644 --- a/spec/controllers/spree/admin/users_controller_spec.rb +++ b/spec/controllers/spree/admin/users_controller_spec.rb @@ -7,51 +7,51 @@ describe Spree::Admin::UsersController do let(:test_user) { create(:user) } before do - controller.stub spree_current_user: user - Spree::User.stub(:find).with(test_user.id.to_s).and_return(test_user) + allow(controller).to receive_messages spree_current_user: user + allow(Spree::User).to receive(:find).with(test_user.id.to_s).and_return(test_user) user.spree_roles.clear end it 'should grant access to users with an admin role' do user.spree_roles << Spree::Role.find_or_create_by_name('admin') spree_post :index - response.should render_template :index + expect(response).to render_template :index end it "allows admins to update a user's API key" do user.spree_roles << Spree::Role.find_or_create_by_name('admin') - test_user.should_receive(:generate_spree_api_key!).and_return(true) + expect(test_user).to receive(:generate_spree_api_key!).and_return(true) puts user.id puts test_user.id spree_put :generate_api_key, id: test_user.id - response.should redirect_to(spree.edit_admin_user_path(test_user)) + expect(response).to redirect_to(spree.edit_admin_user_path(test_user)) end it "allows admins to clear a user's API key" do user.spree_roles << Spree::Role.find_or_create_by_name('admin') - test_user.should_receive(:clear_spree_api_key!).and_return(true) + expect(test_user).to receive(:clear_spree_api_key!).and_return(true) spree_put :clear_api_key, id: test_user.id - response.should redirect_to(spree.edit_admin_user_path(test_user)) + expect(response).to redirect_to(spree.edit_admin_user_path(test_user)) end it 'should deny access to users with an bar role' do user.spree_roles << Spree::Role.find_or_create_by_name('bar') Spree::Ability.register_ability(BarAbility) spree_post :index - response.should redirect_to('/unauthorized') + expect(response).to redirect_to('/unauthorized') end it 'should deny access to users with an bar role' do user.spree_roles << Spree::Role.find_or_create_by_name('bar') Spree::Ability.register_ability(BarAbility) spree_post :update, id: '9' - response.should redirect_to('/unauthorized') + expect(response).to redirect_to('/unauthorized') end it 'should deny access to users without an admin role' do - user.stub has_spree_role?: false + allow(user).to receive_messages has_spree_role?: false spree_post :index - response.should redirect_to('/unauthorized') + expect(response).to redirect_to('/unauthorized') end end end From ac0123734af7f3ad7afb02e506a4f942beaa9065 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Thu, 11 Jul 2019 18:31:57 +0100 Subject: [PATCH 31/36] Add some tests from spree/users_controller_spec from spree_auth_devise --- spec/controllers/spree/users_controller_spec.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/spec/controllers/spree/users_controller_spec.rb b/spec/controllers/spree/users_controller_spec.rb index 95001084dd..8e68b73720 100644 --- a/spec/controllers/spree/users_controller_spec.rb +++ b/spec/controllers/spree/users_controller_spec.rb @@ -54,4 +54,19 @@ describe Spree::UsersController, type: :controller do expect(json_response['registered']).to eq false end end + + context '#load_object' do + it 'should redirect to signup path if user is not found' do + allow(controller).to receive_messages(spree_current_user: nil) + spree_put :update, user: { email: 'foobar@example.com' } + expect(response).to redirect_to('/login') + end + end + + context '#create' do + it 'should create a new user' do + spree_post :create, user: { email: 'foobar@example.com', password: 'foobar123', password_confirmation: 'foobar123' } + expect(assigns[:user].new_record?).to be_falsey + end + end end From 791ff842aafc32ae1982fe7f4ca88f499b00b598 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Thu, 11 Jul 2019 19:33:25 +0100 Subject: [PATCH 32/36] Add some tests to models/spree/user_spec from spre_auth_devise --- spec/models/spree/user_spec.rb | 41 ++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/spec/models/spree/user_spec.rb b/spec/models/spree/user_spec.rb index bd1d7ad78c..d73042c67a 100644 --- a/spec/models/spree/user_spec.rb +++ b/spec/models/spree/user_spec.rb @@ -180,4 +180,45 @@ describe Spree.user_class do end end end + + before(:all) { Spree::Role.create name: 'admin' } + + it '#admin?' do + expect(create(:admin_user).admin?).to be_truthy + expect(create(:user).admin?).to be_falsey + end + + context '#create' do + let(:user) { build(:user) } + + it 'should not be anonymous' do + expect(user).not_to be_anonymous + end + end + + context '#destroy' do + it 'can not delete if it has completed orders' do + order = build(:order, completed_at: Time.zone.now) + order.save + user = order.user + + expect { user.destroy }.to raise_exception(Spree::User::DestroyWithOrdersError) + end + end + + context 'anonymous!' do + let(:user) { Spree::User.anonymous! } + + it 'should create a new user' do + expect(user.new_record?).to be_falsey + end + + it 'should create a user with an example.net email' do + expect(user.email).to match(/@example.net$/) + end + + it 'should be anonymous' do + expect(user).to be_anonymous + end + end end From eacd76bfa45c20dbd19f0ca473c9e7a1ce021083 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Thu, 11 Jul 2019 19:44:10 +0100 Subject: [PATCH 33/36] Add spec to features/admin/products_spec from spre_auth_devise --- spec/features/admin/products_spec.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/spec/features/admin/products_spec.rb b/spec/features/admin/products_spec.rb index 7b91c80909..1756cdc539 100644 --- a/spec/features/admin/products_spec.rb +++ b/spec/features/admin/products_spec.rb @@ -17,6 +17,12 @@ feature ' @enterprise_fees = (0..2).map { |i| create(:enterprise_fee, enterprise: @distributors[i]) } end + context "as anonymous user" do + it "is redirected to login page when attempting to access product listing" do + expect { visit spree.admin_products_path }.not_to raise_error + end + end + describe "creating a product" do let!(:tax_category) { create(:tax_category, name: 'Test Tax Category') } From 71b648e9fa399ae74e3c9e2bd4311ee1dee1f954 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Thu, 11 Jul 2019 20:03:54 +0100 Subject: [PATCH 34/36] Add some tests to features/admin/users_spec from spree_auth_devise --- spec/features/admin/users_spec.rb | 57 +++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/spec/features/admin/users_spec.rb b/spec/features/admin/users_spec.rb index 862e0fe6e0..d58ba686a6 100644 --- a/spec/features/admin/users_spec.rb +++ b/spec/features/admin/users_spec.rb @@ -10,6 +10,63 @@ feature "Managing users" do quick_login_as_admin end + context "from the index page" do + before do + create(:user, :email => "a@example.com") + create(:user, :email => "b@example.com") + + visit spree.admin_path + click_link "Users" + end + + context "users index page with sorting" do + before(:each) do + click_link "users_email_title" + end + + it "should be able to list users with order email asc" do + expect(page).to have_css('table#listing_users') + within("table#listing_users") do + expect(page).to have_content("a@example.com") + expect(page).to have_content("b@example.com") + end + end + + it "should be able to list users with order email desc" do + click_link "users_email_title" + within("table#listing_users") do + expect(page).to have_content("a@example.com") + expect(page).to have_content("b@example.com") + end + end + end + + context "searching users" do + it "should display the correct results for a user search" do + fill_in "q_email_cont", :with => "a@example" + click_button "Search" + within("table#listing_users") do + expect(page).to have_content("a@example") + expect(page).not_to have_content("b@example") + end + end + end + + context "editing users" do + before(:each) do + click_link("a@example.com") + end + + it "should let me edit the user password" do + fill_in "user_password", :with => "welcome" + fill_in "user_password_confirmation", :with => "welcome" + click_button "Update" + + expect(page).to have_content("Account updated") + end + end + end + describe "creating a user" do it "shows no confirmation message to start with" do visit spree.new_admin_user_path From 18006ea9c811ad4b2ddb9fc43ec05686d4c82d94 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Fri, 12 Jul 2019 10:12:53 +0100 Subject: [PATCH 35/36] Change devise config to speed up password encryption in tests --- config/initializers/devise.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index b2424cdbbd..6f0a508ac4 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -37,7 +37,7 @@ Devise.setup do |config| # ==> Configuration for :database_authenticatable # For bcrypt, this is the cost for hashing the password and defaults to 10. If # using other encryptors, it sets how many times you want the password re-encrypted. - config.stretches = 20 + config.stretches = Rails.env.test? ? 1 : 20 # Setup a pepper to generate the encrypted password. config.pepper = Rails.configuration.secret_token From 6d7c41c04b5fada6a8a31e475a10cd85fc880ead Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Sat, 20 Jul 2019 20:48:49 +0100 Subject: [PATCH 36/36] Bring db/default/users from spree_auth_devise, this is necessary to create the first user in the DB --- db/default/users.rb | 82 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 db/default/users.rb diff --git a/db/default/users.rb b/db/default/users.rb new file mode 100644 index 0000000000..bf60502187 --- /dev/null +++ b/db/default/users.rb @@ -0,0 +1,82 @@ +require 'highline/import' + +# see last line where we create an admin if there is none, asking for email and password +def prompt_for_admin_password + if ENV['ADMIN_PASSWORD'] + password = ENV['ADMIN_PASSWORD'].dup + say "Admin Password #{password}" + else + password = ask('Password [spree123]: ') do |q| + q.echo = false + q.validate = /^(|.{5,40})$/ + q.responses[:not_valid] = 'Invalid password. Must be at least 5 characters long.' + q.whitespace = :strip + end + password = 'spree123' if password.blank? + end + + password +end + +def prompt_for_admin_email + if ENV['ADMIN_EMAIL'] + email = ENV['ADMIN_EMAIL'].dup + say "Admin User #{email}" + else + email = ask('Email [spree@example.com]: ') do |q| + q.echo = true + q.whitespace = :strip + end + email = 'spree@example.com' if email.blank? + end + + email +end + +def create_admin_user + if ENV['AUTO_ACCEPT'] + password = 'spree123' + email = 'spree@example.com' + else + puts 'Create the admin user (press enter for defaults).' + #name = prompt_for_admin_name unless name + email = prompt_for_admin_email + password = prompt_for_admin_password + end + attributes = { + :password => password, + :password_confirmation => password, + :email => email, + :login => email + } + + load 'spree/user.rb' + + if Spree::User.find_by_email(email) + say "\nWARNING: There is already a user with the email: #{email}, so no account changes were made. If you wish to create an additional admin user, please run rake spree_auth:admin:create again with a different email.\n\n" + else + admin = Spree::User.new(attributes) + if admin.save + role = Spree::Role.find_or_create_by_name 'admin' + admin.spree_roles << role + admin.save + say "Done!" + else + say "There was some problems with persisting new admin user:" + admin.errors.full_messages.each do |error| + say error + end + end + end +end + +if Spree::User.admin.empty? + create_admin_user +else + puts 'Admin user has already been previously created.' + if agree('Would you like to create a new admin user? (yes/no)') + create_admin_user + else + puts 'No admin user created.' + end +end