mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-27 01:43:22 +00:00
Merge pull request #3700 from luisramos0/2-0-without-auth-devise
Remove dependency to spree_auth_devise
This commit is contained in:
3
Gemfile
3
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: 'spree/spree_auth_devise', branch: '2-0-stable'
|
||||
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
|
||||
|
||||
|
||||
27
Gemfile.lock
27
Gemfile.lock
@@ -66,26 +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_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
|
||||
@@ -180,7 +160,7 @@ GEM
|
||||
json (~> 1.4)
|
||||
nokogiri (>= 1.4.4)
|
||||
uuidtools (~> 2.1)
|
||||
bcrypt (3.1.11)
|
||||
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!
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
*
|
||||
|
||||
*= require admin/spree_backend
|
||||
*= require admin/spree_auth
|
||||
|
||||
*= require jquery-ui-timepicker-addon
|
||||
*= require shared/textAngular
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
6
app/controllers/metal_decorator.rb
Normal file
6
app/controllers/metal_decorator.rb
Normal file
@@ -0,0 +1,6 @@
|
||||
# For the API
|
||||
ActionController::Metal.class_eval do
|
||||
def spree_current_user
|
||||
@spree_current_user ||= env['warden'].user
|
||||
end
|
||||
end
|
||||
@@ -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
|
||||
|
||||
@@ -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])
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
131
app/controllers/spree/admin/users_controller.rb
Normal file
131
app/controllers/spree/admin/users_controller.rb
Normal file
@@ -0,0 +1,131 @@
|
||||
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)
|
||||
end
|
||||
render :edit
|
||||
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 = 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] || '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
|
||||
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
|
||||
end
|
||||
end
|
||||
end
|
||||
44
app/controllers/spree/user_passwords_controller.rb
Normal file
44
app/controllers/spree/user_passwords_controller.rb
Normal file
@@ -0,0 +1,44 @@
|
||||
module Spree
|
||||
class UserPasswordsController < Devise::PasswordsController
|
||||
helper 'spree/base', 'spree/store'
|
||||
|
||||
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
|
||||
end
|
||||
65
app/controllers/spree/user_registrations_controller.rb
Normal file
65
app/controllers/spree/user_registrations_controller.rb
Normal file
@@ -0,0 +1,65 @@
|
||||
module Spree
|
||||
class UserRegistrationsController < Devise::RegistrationsController
|
||||
helper 'spree/base', 'spree/store'
|
||||
|
||||
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
|
||||
end
|
||||
56
app/controllers/spree/user_sessions_controller.rb
Normal file
56
app/controllers/spree/user_sessions_controller.rb
Normal file
@@ -0,0 +1,56 @@
|
||||
module Spree
|
||||
class UserSessionsController < Devise::SessionsController
|
||||
helper 'spree/base', 'spree/store'
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
end
|
||||
@@ -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
|
||||
74
app/controllers/spree/users_controller.rb
Normal file
74
app/controllers/spree/users_controller.rb
Normal file
@@ -0,0 +1,74 @@
|
||||
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
|
||||
|
||||
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
|
||||
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: true)
|
||||
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
|
||||
end
|
||||
@@ -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
|
||||
47
app/mailers/spree/user_mailer.rb
Normal file
47
app/mailers/spree/user_mailer.rb
Normal file
@@ -0,0 +1,47 @@
|
||||
# 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.
|
||||
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
|
||||
|
||||
# This is a OFN specific email, not from Devise::Mailer
|
||||
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
|
||||
|
||||
# Overrides `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
|
||||
@@ -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
|
||||
184
app/models/spree/user.rb
Normal file
184
app/models/spree/user.rb
Normal file
@@ -0,0 +1,184 @@
|
||||
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") }
|
||||
|
||||
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 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)
|
||||
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(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?
|
||||
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
|
||||
return unless confirmed? && unconfirmed_email.nil? && !unconfirmed_email_changed?
|
||||
send_signup_confirmation
|
||||
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?
|
||||
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 ||= 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 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
|
||||
@@ -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
|
||||
6
app/overrides/admin_tab.rb
Normal file
6
app/overrides/admin_tab.rb
Normal file
@@ -0,0 +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')
|
||||
5
app/overrides/auth_admin_login_navigation_bar.rb
Normal file
5
app/overrides/auth_admin_login_navigation_bar.rb
Normal file
@@ -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')
|
||||
6
app/overrides/auth_shared_login_bar.rb
Normal file
6
app/overrides/auth_shared_login_bar.rb
Normal file
@@ -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')
|
||||
2
app/views/spree/admin/_users_tab.html.haml
Normal file
2
app/views/spree/admin/_users_tab.html.haml
Normal file
@@ -0,0 +1,2 @@
|
||||
- if can? :admin, Spree::User
|
||||
= tab(:users, url: spree.admin_users_path, icon: 'icon-user')
|
||||
15
app/views/spree/admin/users/new.html.haml
Normal file
15
app/views/spree/admin/users/new.html.haml
Normal file
@@ -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'
|
||||
15
app/views/spree/shared/_user_form.html.haml
Normal file
15
app/views/spree/shared/_user_form.html.haml
Normal file
@@ -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'
|
||||
14
app/views/spree/user_passwords/new.html.haml
Executable file
14
app/views/spree/user_passwords/new.html.haml
Executable file
@@ -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'
|
||||
@@ -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 = Rails.env.test? ? 1 : 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
|
||||
|
||||
# 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 = <YOUR CONSUMER SECRET>
|
||||
# twitter.consumer_key = <YOUR 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
|
||||
|
||||
@@ -45,9 +45,6 @@ end
|
||||
# Spree 2.0 recommends explicitly setting this here when using spree_auth_devise
|
||||
Spree.user_class = 'Spree::User'
|
||||
|
||||
# Don't log users out when setting a new password
|
||||
Spree::Auth::Config[: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?
|
||||
|
||||
@@ -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
|
||||
@@ -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:
|
||||
@@ -2933,6 +2935,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"
|
||||
|
||||
@@ -9,6 +9,32 @@ 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
|
||||
|
||||
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
|
||||
|
||||
82
db/default/users.rb
Normal file
82
db/default/users.rb
Normal file
@@ -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
|
||||
26
lib/spree/authentication_helpers.rb
Normal file
26
lib/spree/authentication_helpers.rb
Normal file
@@ -0,0 +1,26 @@
|
||||
module Spree
|
||||
module AuthenticationHelpers
|
||||
def self.included(receiver)
|
||||
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
|
||||
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
|
||||
@@ -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
|
||||
|
||||
57
spec/controllers/spree/admin/users_controller_spec.rb
Normal file
57
spec/controllers/spree/admin/users_controller_spec.rb
Normal file
@@ -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
|
||||
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
|
||||
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')
|
||||
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
|
||||
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')
|
||||
expect(test_user).to receive(:clear_spree_api_key!).and_return(true)
|
||||
spree_put :clear_api_key, id: test_user.id
|
||||
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
|
||||
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'
|
||||
expect(response).to redirect_to('/unauthorized')
|
||||
end
|
||||
|
||||
it 'should deny access to users without an admin role' do
|
||||
allow(user).to receive_messages has_spree_role?: false
|
||||
spree_post :index
|
||||
expect(response).to redirect_to('/unauthorized')
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -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
|
||||
|
||||
@@ -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') }
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -128,7 +128,6 @@ RSpec.configure do |config|
|
||||
spree_config.auto_capture = true
|
||||
end
|
||||
|
||||
Spree::Auth::Config[:signout_after_password_change] = false
|
||||
Spree::Api::Config[:requires_authentication] = true
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user