diff --git a/core/app/models/spree/order.rb b/core/app/models/spree/order.rb index 23b922a31c7..8c9f759a3a5 100644 --- a/core/app/models/spree/order.rb +++ b/core/app/models/spree/order.rb @@ -13,6 +13,7 @@ class Order < Spree::Base include Spree::Order::CurrencyUpdater include Spree::Order::Payments include Spree::NumberGenerator + include Spree::Core::TokenGenerator def generate_number(options = {}) options[:prefix] ||= 'R' @@ -628,10 +629,7 @@ def set_currency end def create_token - self.guest_token ||= loop do - random_token = SecureRandom.urlsafe_base64(nil, false) - break random_token unless self.class.exists?(guest_token: random_token) - end + self.guest_token ||= generate_guest_token end end end diff --git a/core/lib/spree/core.rb b/core/lib/spree/core.rb index 567daab262f..40ee546c4e2 100644 --- a/core/lib/spree/core.rb +++ b/core/lib/spree/core.rb @@ -43,6 +43,7 @@ def self.config(&block) module Core autoload :ProductFilters, "spree/core/product_filters" + autoload :TokenGenerator, "spree/core/token_generator" class GatewayError < RuntimeError; end class DestroyWithOrdersError < StandardError; end diff --git a/core/lib/spree/core/controller_helpers/auth.rb b/core/lib/spree/core/controller_helpers/auth.rb index 38b87fc889e..669e6566df1 100644 --- a/core/lib/spree/core/controller_helpers/auth.rb +++ b/core/lib/spree/core/controller_helpers/auth.rb @@ -3,6 +3,7 @@ module Core module ControllerHelpers module Auth extend ActiveSupport::Concern + include Spree::Core::TokenGenerator included do before_filter :set_guest_token @@ -24,8 +25,8 @@ def redirect_back_or_default(default) end def set_guest_token - unless cookies.signed[:guest_token].present? - cookies.permanent.signed[:guest_token] = SecureRandom.urlsafe_base64(nil, false) + if cookies.signed[:guest_token].blank? + cookies.permanent.signed[:guest_token] = generate_guest_token end end diff --git a/core/lib/spree/core/token_generator.rb b/core/lib/spree/core/token_generator.rb new file mode 100644 index 00000000000..90d2d4689b1 --- /dev/null +++ b/core/lib/spree/core/token_generator.rb @@ -0,0 +1,22 @@ +module Spree + module Core + module TokenGenerator + def generate_guest_token(model_class = Spree::Order) + loop do + token = "#{random_token}#{unique_ending}" + break token unless model_class.exists?(guest_token: token) + end + end + + private + + def random_token + SecureRandom.urlsafe_base64(nil, false) + end + + def unique_ending + (Time.now.to_f * 1000).to_i + end + end + end +end diff --git a/core/spec/lib/spree/core/token_generator_spec.rb b/core/spec/lib/spree/core/token_generator_spec.rb new file mode 100644 index 00000000000..7abf321a3e1 --- /dev/null +++ b/core/spec/lib/spree/core/token_generator_spec.rb @@ -0,0 +1,24 @@ +require 'spec_helper' + +describe Spree::Core::TokenGenerator do + class DummyClass + include Spree::Core::TokenGenerator + + attr_reader :created_at + + def initialize + @created_at = Time.now.to_i + end + end + + let(:dummy_class_instance) { DummyClass.new } + + describe 'generate_guest_token' do + let(:generated_token) { dummy_class_instance.generate_guest_token } + + it 'generates random token with timestamp' do + expect(generated_token.size).to eq 35 + expect(generated_token).to include dummy_class_instance.created_at.to_s + end + end +end diff --git a/core/spec/models/spree/order_spec.rb b/core/spec/models/spree/order_spec.rb index 297b56d1626..85cc7ba92f7 100644 --- a/core/spec/models/spree/order_spec.rb +++ b/core/spec/models/spree/order_spec.rb @@ -67,15 +67,15 @@ def compute(computable) end end - context "#create" do + context '#create' do let(:order) { Spree::Order.create } - it "should assign an order number" do + it 'should assign an order number' do expect(order.number).not_to be_nil end - it 'should create a randomized 22 character token' do - expect(order.guest_token.size).to eq(22) + it 'should create a randomized 35 character token' do + expect(order.guest_token.size).to eq(35) end end