spree_cm_commissioner 2.9.1.pre.pre2 → 2.9.1.pre.pre4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/app/controllers/spree/api/v2/tenant/user_account_linkages_controller.rb +1 -2
- data/app/controllers/spree_cm_commissioner/api/v2/storefront/checkout_controller_decorator.rb +14 -1
- data/app/interactors/spree_cm_commissioner/account_linkage.rb +1 -13
- data/app/interactors/spree_cm_commissioner/user_fb_token_authenticator.rb +0 -1
- data/app/models/spree_cm_commissioner/current.rb +8 -0
- data/app/models/spree_cm_commissioner/pricing_model_route.rb +8 -0
- data/app/models/spree_cm_commissioner/trip.rb +3 -0
- data/app/request_schemas/spree_cm_commissioner/user_account_linkage_request_schema.rb +2 -4
- data/app/services/spree_cm_commissioner/inventory_holds/validate_limits.rb +1 -1
- data/app/services/spree_cm_commissioner/pricing_models/create_with_rule_groups.rb +9 -3
- data/app/services/spree_cm_commissioner/pricing_models/preview.rb +49 -6
- data/app/services/spree_cm_commissioner/pricing_models/update_with_rule_groups.rb +10 -7
- data/app/services/spree_cm_commissioner/user_authenticator.rb +0 -5
- data/db/migrate/20260630000001_add_trip_to_cm_pricing_model_routes.rb +7 -0
- data/lib/spree_cm_commissioner/test_helper/factories/pricing_model_trip_factory.rb +11 -0
- data/lib/spree_cm_commissioner/version.rb +1 -1
- metadata +5 -5
- data/app/interactors/spree_cm_commissioner/fetch_facebook_user_data_from_jwt.rb +0 -90
- data/app/interactors/spree_cm_commissioner/user_fb_jwt_authenticator.rb +0 -37
- data/app/interactors/spree_cm_commissioner/user_fb_jwt_checker.rb +0 -20
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ebefceb78297eb71b4dcb417b47de1c9440786f17942f341aa5cff394558b2aa
|
|
4
|
+
data.tar.gz: 4fae27019658db8352dd7001445b331355d7b20f321b079c211e4e87889789eb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ed1b54c40e5288bc4e04e467c978b531f80b49985e387e4ed5a65908dd9b8152fe024fd4dcfdadba2f279b385fc8250588b3cd674125abf4a4ddd4d0306560b1
|
|
7
|
+
data.tar.gz: 283fa4cceb6e50ef28eba6e0eb4ecbdba5ca2984a377009934d057606840ce101db088d4f766c8d37b623bff61fe5b030867c99540ea00e33ed3067c20a4c243
|
data/Gemfile.lock
CHANGED
|
@@ -15,8 +15,7 @@ module Spree
|
|
|
15
15
|
context = SpreeCmCommissioner::AccountLinkage.call(
|
|
16
16
|
user: spree_current_user,
|
|
17
17
|
id_token: params[:id_token],
|
|
18
|
-
fb_access_token: params[:fb_access_token]
|
|
19
|
-
fb_jwt: params[:fb_jwt]
|
|
18
|
+
fb_access_token: params[:fb_access_token]
|
|
20
19
|
)
|
|
21
20
|
|
|
22
21
|
if context.success?
|
data/app/controllers/spree_cm_commissioner/api/v2/storefront/checkout_controller_decorator.rb
CHANGED
|
@@ -7,9 +7,22 @@ module SpreeCmCommissioner
|
|
|
7
7
|
base.include SpreeCmCommissioner::OrderConcern
|
|
8
8
|
base.include SpreeCmCommissioner::TurnstileProtectable
|
|
9
9
|
|
|
10
|
-
base.before_action
|
|
10
|
+
base.before_action :set_load_test_bypass_current
|
|
11
|
+
base.before_action -> { verify_turnstile! }, only: %i[create_payment]
|
|
11
12
|
end
|
|
12
13
|
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def set_load_test_bypass_current
|
|
17
|
+
key = ENV.fetch('LOAD_TEST_BYPASS_KEY', nil)
|
|
18
|
+
return if key.blank?
|
|
19
|
+
|
|
20
|
+
provided = request.headers.fetch('X-Request-Verify', nil).to_s
|
|
21
|
+
SpreeCmCommissioner::Current.load_test_bypass = ActiveSupport::SecurityUtils.secure_compare(provided, key)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
public
|
|
25
|
+
|
|
13
26
|
# Override Spree's default behavior:
|
|
14
27
|
# By default, Spree raises an error if `complete` is called on a completed or confirmed order.
|
|
15
28
|
# We want to allow this call to succeed, so the API can be used both to:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module SpreeCmCommissioner
|
|
2
2
|
class AccountLinkage
|
|
3
3
|
include Interactor
|
|
4
|
-
delegate :id_token, :fb_access_token, :
|
|
4
|
+
delegate :id_token, :fb_access_token, :user, to: :context
|
|
5
5
|
|
|
6
6
|
# id_token:, user:
|
|
7
7
|
def call
|
|
@@ -10,8 +10,6 @@ module SpreeCmCommissioner
|
|
|
10
10
|
handle_id_token
|
|
11
11
|
elsif fb_access_token.present?
|
|
12
12
|
handle_fb_access_token
|
|
13
|
-
elsif fb_jwt.present?
|
|
14
|
-
handle_fb_jwt
|
|
15
13
|
else
|
|
16
14
|
context.fail!(message: 'missing_social_token')
|
|
17
15
|
end
|
|
@@ -39,16 +37,6 @@ module SpreeCmCommissioner
|
|
|
39
37
|
end
|
|
40
38
|
end
|
|
41
39
|
|
|
42
|
-
def handle_fb_jwt
|
|
43
|
-
facebook_context = FetchFacebookUserDataFromJwt.call(fb_jwt: fb_jwt)
|
|
44
|
-
|
|
45
|
-
if facebook_context.success?
|
|
46
|
-
build_user_identify_provider(facebook_context.provider)
|
|
47
|
-
else
|
|
48
|
-
context.fail!(message: facebook_context.message)
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
|
|
52
40
|
# {
|
|
53
41
|
# provider_name: provider_name,
|
|
54
42
|
# email: email,
|
|
@@ -5,7 +5,6 @@ module SpreeCmCommissioner
|
|
|
5
5
|
# :fb_access_token, :tenant_id (optional)
|
|
6
6
|
def call
|
|
7
7
|
context.fail!(message: 'fb_access_token_missing') unless fb_access_token
|
|
8
|
-
context.fail!(message: checker.message) if checker.failure?
|
|
9
8
|
|
|
10
9
|
context.user = if checker.user.nil?
|
|
11
10
|
register_user
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
class Current < ActiveSupport::CurrentAttributes
|
|
3
|
+
# Set to true for the duration of a load-test request so that rate-limiting
|
|
4
|
+
# services deeper in the call chain (e.g. InventoryHolds::ValidateLimits) can
|
|
5
|
+
# skip their checks without needing the request object threaded through them.
|
|
6
|
+
attribute :load_test_bypass
|
|
7
|
+
end
|
|
8
|
+
end
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
module SpreeCmCommissioner
|
|
2
|
+
# A pricing-model assignment. A row is either:
|
|
3
|
+
# - route-scoped: trip_id NULL, keyed by route + O-D (unchanged legacy behaviour), or
|
|
4
|
+
# - trip-scoped: trip_id set, keyed by that specific trip + its own O-D (overrides route pricing
|
|
5
|
+
# for that trip only).
|
|
2
6
|
class PricingModelRoute < Base
|
|
3
7
|
belongs_to :route, class_name: 'SpreeCmCommissioner::Route'
|
|
8
|
+
belongs_to :trip, class_name: 'SpreeCmCommissioner::Trip', optional: true
|
|
4
9
|
belongs_to :pricing_model, class_name: 'SpreeCmCommissioner::PricingModel'
|
|
5
10
|
belongs_to :origin_place, class_name: 'SpreeCmCommissioner::Place'
|
|
6
11
|
belongs_to :destination_place, class_name: 'SpreeCmCommissioner::Place'
|
|
7
12
|
|
|
13
|
+
scope :route_scoped, -> { where(trip_id: nil) }
|
|
14
|
+
scope :trip_scoped, -> { where.not(trip_id: nil) }
|
|
15
|
+
|
|
8
16
|
scope :for_origin_destination, lambda { |origin_place_id, destination_place_id|
|
|
9
17
|
where(origin_place_id: origin_place_id, destination_place_id: destination_place_id)
|
|
10
18
|
}
|
|
@@ -52,6 +52,9 @@ module SpreeCmCommissioner
|
|
|
52
52
|
has_many :trip_blazer_queries, as: :queryable, class_name: 'SpreeCmCommissioner::BlazerQueryable'
|
|
53
53
|
has_many :blazer_queries, through: :trip_blazer_queries, source: :blazer_query, class_name: 'Blazer::Query'
|
|
54
54
|
|
|
55
|
+
has_many :pricing_model_routes, class_name: 'SpreeCmCommissioner::PricingModelRoute', dependent: :destroy
|
|
56
|
+
has_many :pricing_models, through: :pricing_model_routes, class_name: 'SpreeCmCommissioner::PricingModel'
|
|
57
|
+
|
|
55
58
|
has_many :trip_stops, class_name: 'SpreeCmCommissioner::TripStop', dependent: :destroy
|
|
56
59
|
has_many :boarding_trip_stops, -> { boarding.order('departure_time ASC NULLS LAST, id ASC') }, class_name: 'SpreeCmCommissioner::TripStop'
|
|
57
60
|
has_many :drop_off_trip_stops, -> { drop_off.order('arrival_time ASC NULLS LAST') }, class_name: 'SpreeCmCommissioner::TripStop'
|
|
@@ -3,15 +3,13 @@ module SpreeCmCommissioner
|
|
|
3
3
|
params do
|
|
4
4
|
optional(:id_token).maybe(:string)
|
|
5
5
|
optional(:fb_access_token).maybe(:string)
|
|
6
|
-
optional(:fb_jwt).maybe(:string)
|
|
7
6
|
end
|
|
8
7
|
|
|
9
|
-
rule(:id_token, :fb_access_token
|
|
8
|
+
rule(:id_token, :fb_access_token) do
|
|
10
9
|
idt = values[:id_token]
|
|
11
10
|
fbt = values[:fb_access_token]
|
|
12
|
-
fbj = values[:fb_jwt]
|
|
13
11
|
|
|
14
|
-
key(:base).failure('id_token_or_fb_access_token_required') if blank_or_empty?(idt) && blank_or_empty?(fbt)
|
|
12
|
+
key(:base).failure('id_token_or_fb_access_token_required') if blank_or_empty?(idt) && blank_or_empty?(fbt)
|
|
15
13
|
end
|
|
16
14
|
|
|
17
15
|
private
|
|
@@ -15,7 +15,7 @@ module SpreeCmCommissioner
|
|
|
15
15
|
# Validates all inventory hold limits for the given order
|
|
16
16
|
def call(order:)
|
|
17
17
|
validate_user_hold_limits!(order) if order.user.present?
|
|
18
|
-
validate_ip_rate_limit!(order)
|
|
18
|
+
validate_ip_rate_limit!(order) unless SpreeCmCommissioner::Current.load_test_bypass
|
|
19
19
|
validate_cooldown!(order)
|
|
20
20
|
|
|
21
21
|
success(nil)
|
|
@@ -3,13 +3,13 @@ module SpreeCmCommissioner
|
|
|
3
3
|
class CreateWithRuleGroups
|
|
4
4
|
prepend ::Spree::ServiceModule::Base
|
|
5
5
|
|
|
6
|
-
def call(vendor:, params:, route: nil, origin_place_id: nil, destination_place_id: nil)
|
|
6
|
+
def call(vendor:, params:, route: nil, trip: nil, origin_place_id: nil, destination_place_id: nil) # rubocop:disable Metrics/ParameterLists
|
|
7
7
|
pricing_model = vendor.pricing_models.new(model_params(params))
|
|
8
8
|
|
|
9
9
|
ApplicationRecord.transaction do
|
|
10
10
|
pricing_model.save!
|
|
11
11
|
build_rule_groups(pricing_model, params[:rule_groups])
|
|
12
|
-
create_route_assignment(pricing_model, route, origin_place_id, destination_place_id) if route.present?
|
|
12
|
+
create_route_assignment(pricing_model, route, trip, origin_place_id, destination_place_id) if route.present?
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
success(pricing_model)
|
|
@@ -41,11 +41,17 @@ module SpreeCmCommissioner
|
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
# A row is trip-scoped when a trip is given (overrides route pricing for that trip);
|
|
45
|
+
# otherwise route-scoped (unchanged legacy behaviour). Trip-scoped rows take their O-D from
|
|
46
|
+
# the trip so they match the trip's own journey at resolution time.
|
|
47
|
+
def create_route_assignment(pricing_model, route, trip, origin_place_id, destination_place_id)
|
|
48
|
+
origin_place_id = trip.origin_place_id if trip.present?
|
|
49
|
+
destination_place_id = trip.destination_place_id if trip.present?
|
|
45
50
|
return unless origin_place_id.present? && destination_place_id.present?
|
|
46
51
|
|
|
47
52
|
PricingModelRoute.create!(
|
|
48
53
|
route: route,
|
|
54
|
+
trip: trip,
|
|
49
55
|
pricing_model: pricing_model,
|
|
50
56
|
origin_place_id: origin_place_id,
|
|
51
57
|
destination_place_id: destination_place_id
|
|
@@ -39,29 +39,72 @@ module SpreeCmCommissioner
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
def find_pricing_models(group_contexts)
|
|
42
|
-
|
|
42
|
+
transit_pricing_models(group_contexts) + variant_pricing_models(group_contexts)
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
# Trip-level pricing overrides route-level pricing for the same journey; route pricing
|
|
46
|
+
# is the fallback when the trip (or connected journey's parent trip) has none assigned.
|
|
47
|
+
def transit_pricing_models(group_contexts)
|
|
46
48
|
transit_contexts = group_contexts.select { |ctx| ctx.trip_id.present? }
|
|
47
49
|
return [] if transit_contexts.blank?
|
|
48
50
|
|
|
49
51
|
origin_place_id, destination_place_id = determine_origin_destination(transit_contexts)
|
|
50
52
|
return [] if origin_place_id.blank? || destination_place_id.blank?
|
|
51
53
|
|
|
52
|
-
vendor_ids = transit_contexts
|
|
54
|
+
vendor_ids = transit_vendor_ids(transit_contexts)
|
|
53
55
|
return [] if vendor_ids.blank?
|
|
54
56
|
|
|
55
|
-
|
|
57
|
+
trip_level_pricing_models(
|
|
58
|
+
trip_ids: trip_candidate_ids(transit_contexts),
|
|
59
|
+
origin_place_id: origin_place_id,
|
|
60
|
+
destination_place_id: destination_place_id,
|
|
61
|
+
vendor_ids: vendor_ids
|
|
62
|
+
).presence || route_level_pricing_models(
|
|
63
|
+
route_ids: trip_route_ids(transit_contexts),
|
|
64
|
+
origin_place_id: origin_place_id,
|
|
65
|
+
destination_place_id: destination_place_id,
|
|
66
|
+
vendor_ids: vendor_ids
|
|
67
|
+
)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def trip_level_pricing_models(trip_ids:, origin_place_id:, destination_place_id:, vendor_ids:)
|
|
71
|
+
return [] if trip_ids.empty?
|
|
56
72
|
|
|
57
73
|
scope = SpreeCmCommissioner::PricingModelRoute
|
|
58
74
|
.active
|
|
75
|
+
.trip_scoped
|
|
76
|
+
.where(trip_id: trip_ids)
|
|
59
77
|
.for_origin_destination(origin_place_id, destination_place_id)
|
|
60
|
-
.includes(:pricing_model)
|
|
61
78
|
|
|
79
|
+
pricing_models_for(scope, vendor_ids)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def route_level_pricing_models(route_ids:, origin_place_id:, destination_place_id:, vendor_ids:)
|
|
83
|
+
scope = SpreeCmCommissioner::PricingModelRoute
|
|
84
|
+
.active
|
|
85
|
+
.route_scoped
|
|
86
|
+
.for_origin_destination(origin_place_id, destination_place_id)
|
|
62
87
|
scope = scope.where(route_id: route_ids) if route_ids.any?
|
|
63
88
|
|
|
64
|
-
scope
|
|
89
|
+
pricing_models_for(scope, vendor_ids)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Resolves a PricingModelRoute scope into its pricing models, restricted to vendors
|
|
93
|
+
# actually present among the line items being priced.
|
|
94
|
+
def pricing_models_for(scope, vendor_ids)
|
|
95
|
+
scope.includes(:pricing_model).map(&:pricing_model).select { |pm| vendor_ids.include?(pm.vendor_id) }
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# A booking's legs can each have their own trip-level price, and a connected journey
|
|
99
|
+
# (multiple legs sharing connected_trip_id) can also have its own price on the shared
|
|
100
|
+
# parent trip. This returns every trip id worth checking for either case.
|
|
101
|
+
def trip_candidate_ids(transit_contexts)
|
|
102
|
+
connected_trip_id = Integer(transit_contexts.first&.connected_trip_id.to_s, exception: false)
|
|
103
|
+
(transit_contexts.map(&:trip_id) + [connected_trip_id]).compact.uniq
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def transit_vendor_ids(transit_contexts)
|
|
107
|
+
transit_contexts.map { |ctx| variant_vendor_id(ctx.variant_id) }.compact.uniq
|
|
65
108
|
end
|
|
66
109
|
|
|
67
110
|
def variant_pricing_models(group_contexts)
|
|
@@ -3,11 +3,11 @@ module SpreeCmCommissioner
|
|
|
3
3
|
class UpdateWithRuleGroups
|
|
4
4
|
prepend ::Spree::ServiceModule::Base
|
|
5
5
|
|
|
6
|
-
def call(pricing_model:, params:, route: nil, origin_place_id: nil, destination_place_id: nil)
|
|
6
|
+
def call(pricing_model:, params:, route: nil, trip: nil, origin_place_id: nil, destination_place_id: nil) # rubocop:disable Metrics/ParameterLists
|
|
7
7
|
ApplicationRecord.transaction do
|
|
8
8
|
pricing_model.update!(model_params(params))
|
|
9
9
|
sync_rule_groups(pricing_model, params[:rule_groups])
|
|
10
|
-
update_route_assignment(pricing_model, route, origin_place_id, destination_place_id) if route.present?
|
|
10
|
+
update_route_assignment(pricing_model, route, trip, origin_place_id, destination_place_id) if route.present?
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
success(pricing_model)
|
|
@@ -47,14 +47,17 @@ module SpreeCmCommissioner
|
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
# Each pricing model created via this flow has a single assignment row; update it in place so
|
|
51
|
+
# the assigned trip (and O-D) can be changed on edit. Trip-scoped rows take O-D from the trip.
|
|
52
|
+
def update_route_assignment(pricing_model, route, trip, origin_place_id, destination_place_id)
|
|
53
|
+
origin_place_id = trip.origin_place_id if trip.present?
|
|
54
|
+
destination_place_id = trip.destination_place_id if trip.present?
|
|
51
55
|
return unless origin_place_id.present? && destination_place_id.present?
|
|
52
56
|
|
|
53
|
-
route_assignment = PricingModelRoute.find_or_initialize_by(
|
|
54
|
-
route: route,
|
|
55
|
-
pricing_model: pricing_model
|
|
56
|
-
)
|
|
57
|
+
route_assignment = PricingModelRoute.find_or_initialize_by(pricing_model: pricing_model)
|
|
57
58
|
route_assignment.update!(
|
|
59
|
+
route: route,
|
|
60
|
+
trip: trip,
|
|
58
61
|
origin_place_id: origin_place_id,
|
|
59
62
|
destination_place_id: destination_place_id
|
|
60
63
|
)
|
|
@@ -4,7 +4,6 @@ module SpreeCmCommissioner
|
|
|
4
4
|
# :username, :password
|
|
5
5
|
# :id_token
|
|
6
6
|
# :fb_access_token
|
|
7
|
-
# :fb_jwt
|
|
8
7
|
# :telegram_init_data, :tg_bot
|
|
9
8
|
# :session_id
|
|
10
9
|
|
|
@@ -43,9 +42,6 @@ module SpreeCmCommissioner
|
|
|
43
42
|
when 'facebook_auth'
|
|
44
43
|
options = { fb_access_token: params[:fb_access_token], tenant_id: tenant_id }
|
|
45
44
|
SpreeCmCommissioner::UserFbTokenAuthenticator.call(options)
|
|
46
|
-
when 'facebook_jwt_auth'
|
|
47
|
-
options = { fb_jwt: params[:fb_jwt], tenant_id: tenant_id }
|
|
48
|
-
SpreeCmCommissioner::UserFbJwtAuthenticator.call(options)
|
|
49
45
|
when 'telegram_web_app_auth'
|
|
50
46
|
options = { telegram_init_data: params[:telegram_init_data], telegram_bot_username: params[:tg_bot] }
|
|
51
47
|
SpreeCmCommissioner::UserTelegramWebAppAuthenticator.call(options)
|
|
@@ -59,7 +55,6 @@ module SpreeCmCommissioner
|
|
|
59
55
|
return 'login_auth' if params.key?(:username) && params.key?(:password)
|
|
60
56
|
return 'social_auth' if params.key?(:id_token)
|
|
61
57
|
return 'facebook_auth' if params.key?(:fb_access_token)
|
|
62
|
-
return 'facebook_jwt_auth' if params.key?(:fb_jwt)
|
|
63
58
|
return 'telegram_web_app_auth' if params.key?(:telegram_init_data) && params.key?(:tg_bot)
|
|
64
59
|
return 'vattanac_bank_web_app_auth' if params.key?(:session_id)
|
|
65
60
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
FactoryBot.define do
|
|
2
|
+
# A trip-scoped PricingModelRoute row — overrides route pricing for one specific trip.
|
|
3
|
+
# origin/destination default to the trip's own O-D (mirrors how trip pricing is resolved).
|
|
4
|
+
factory :cm_pricing_model_trip, class: 'SpreeCmCommissioner::PricingModelRoute' do
|
|
5
|
+
association :pricing_model, factory: :cm_pricing_model
|
|
6
|
+
association :trip, factory: :cm_trip
|
|
7
|
+
route { trip.route || create(:cm_route, origin_place: trip.origin_place, destination_place: trip.destination_place) }
|
|
8
|
+
origin_place { trip.origin_place }
|
|
9
|
+
destination_place { trip.destination_place }
|
|
10
|
+
end
|
|
11
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: spree_cm_commissioner
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.9.1.pre.
|
|
4
|
+
version: 2.9.1.pre.pre4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- You
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-07-
|
|
11
|
+
date: 2026-07-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: spree
|
|
@@ -1243,7 +1243,6 @@ files:
|
|
|
1243
1243
|
- app/interactors/spree_cm_commissioner/event_qr_generator.rb
|
|
1244
1244
|
- app/interactors/spree_cm_commissioner/existing_account_checker.rb
|
|
1245
1245
|
- app/interactors/spree_cm_commissioner/fetch_facebook_user_data.rb
|
|
1246
|
-
- app/interactors/spree_cm_commissioner/fetch_facebook_user_data_from_jwt.rb
|
|
1247
1246
|
- app/interactors/spree_cm_commissioner/firebase_email_fetcher.rb
|
|
1248
1247
|
- app/interactors/spree_cm_commissioner/firebase_email_fetcher_cron_executor.rb
|
|
1249
1248
|
- app/interactors/spree_cm_commissioner/firebase_id_token_provider.rb
|
|
@@ -1320,8 +1319,6 @@ files:
|
|
|
1320
1319
|
- app/interactors/spree_cm_commissioner/user_contact_updater.rb
|
|
1321
1320
|
- app/interactors/spree_cm_commissioner/user_device_token_deregister.rb
|
|
1322
1321
|
- app/interactors/spree_cm_commissioner/user_device_token_register.rb
|
|
1323
|
-
- app/interactors/spree_cm_commissioner/user_fb_jwt_authenticator.rb
|
|
1324
|
-
- app/interactors/spree_cm_commissioner/user_fb_jwt_checker.rb
|
|
1325
1322
|
- app/interactors/spree_cm_commissioner/user_fb_token_authenticator.rb
|
|
1326
1323
|
- app/interactors/spree_cm_commissioner/user_fb_token_checker.rb
|
|
1327
1324
|
- app/interactors/spree_cm_commissioner/user_forgotten_password_updater.rb
|
|
@@ -1515,6 +1512,7 @@ files:
|
|
|
1515
1512
|
- app/models/spree_cm_commissioner/configuration.rb
|
|
1516
1513
|
- app/models/spree_cm_commissioner/crew_invite.rb
|
|
1517
1514
|
- app/models/spree_cm_commissioner/crew_invite_link.rb
|
|
1515
|
+
- app/models/spree_cm_commissioner/current.rb
|
|
1518
1516
|
- app/models/spree_cm_commissioner/customer.rb
|
|
1519
1517
|
- app/models/spree_cm_commissioner/customer_notification.rb
|
|
1520
1518
|
- app/models/spree_cm_commissioner/customer_promotion_rule.rb
|
|
@@ -3412,6 +3410,7 @@ files:
|
|
|
3412
3410
|
- db/migrate/20260623082233_create_cm_claims.rb
|
|
3413
3411
|
- db/migrate/20260624175658_add_unique_index_to_cm_claims.rb
|
|
3414
3412
|
- db/migrate/20260629000001_add_term_of_use_to_spree_vendors.rb
|
|
3413
|
+
- db/migrate/20260630000001_add_trip_to_cm_pricing_model_routes.rb
|
|
3415
3414
|
- db/migrate/20260701000001_add_device_info_to_cm_waiting_room_sessions.rb
|
|
3416
3415
|
- db/migrate/20260703065239_add_position_to_cm_voting_contestants.rb
|
|
3417
3416
|
- docker-compose.yml
|
|
@@ -3512,6 +3511,7 @@ files:
|
|
|
3512
3511
|
- lib/spree_cm_commissioner/test_helper/factories/pricing_action_factory.rb
|
|
3513
3512
|
- lib/spree_cm_commissioner/test_helper/factories/pricing_model_factory.rb
|
|
3514
3513
|
- lib/spree_cm_commissioner/test_helper/factories/pricing_model_route_factory.rb
|
|
3514
|
+
- lib/spree_cm_commissioner/test_helper/factories/pricing_model_trip_factory.rb
|
|
3515
3515
|
- lib/spree_cm_commissioner/test_helper/factories/pricing_model_variant_factory.rb
|
|
3516
3516
|
- lib/spree_cm_commissioner/test_helper/factories/pricing_rule_factory.rb
|
|
3517
3517
|
- lib/spree_cm_commissioner/test_helper/factories/pricing_rule_group_factory.rb
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
module SpreeCmCommissioner
|
|
2
|
-
class FetchFacebookUserDataFromJwt < BaseInteractor
|
|
3
|
-
JWKS_URL = 'https://limited.facebook.com/.well-known/oauth/openid/jwks/'.freeze
|
|
4
|
-
EXPECTED_ISSUER = 'https://www.facebook.com'.freeze
|
|
5
|
-
|
|
6
|
-
delegate :fb_jwt, to: :context
|
|
7
|
-
|
|
8
|
-
def call
|
|
9
|
-
context.fail!(message: 'fb_jwt_missing') if fb_jwt.blank?
|
|
10
|
-
|
|
11
|
-
claim = decode_jwt
|
|
12
|
-
|
|
13
|
-
context.provider = {
|
|
14
|
-
identity_type: SpreeCmCommissioner::UserIdentityProvider.identity_types[:facebook],
|
|
15
|
-
sub: claim['sub'],
|
|
16
|
-
name: claim['name'],
|
|
17
|
-
email: nil, # Facebook Limited Login JWT does not include email
|
|
18
|
-
first_name: claim['given_name'],
|
|
19
|
-
last_name: claim['family_name'],
|
|
20
|
-
picture: claim['picture']
|
|
21
|
-
}
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
private
|
|
25
|
-
|
|
26
|
-
def decode_jwt
|
|
27
|
-
result = JWT.decode(fb_jwt, nil, true, algorithms: ['RS256']) do |header|
|
|
28
|
-
kid = header['kid']
|
|
29
|
-
jwk_data = find_jwk(fetch_jwks, kid) || find_jwk(refresh_jwks, kid)
|
|
30
|
-
context.fail!(message: 'invalid_facebook_jwt_kid') unless jwk_data
|
|
31
|
-
public_key_from_jwk(jwk_data)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
claim = result[0]
|
|
35
|
-
context.fail!(message: 'invalid_facebook_issuer') if claim['iss'] != EXPECTED_ISSUER
|
|
36
|
-
claim
|
|
37
|
-
rescue JWT::ExpiredSignature
|
|
38
|
-
context.fail!(message: 'fb_jwt_expired')
|
|
39
|
-
rescue JWT::DecodeError => e
|
|
40
|
-
context.fail!(message: e.message)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def find_jwk(jwks, kid)
|
|
44
|
-
jwks['keys'].find { |k| k['kid'] == kid }
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def public_key_from_jwk(jwk_data)
|
|
48
|
-
n = OpenSSL::BN.new(Base64.urlsafe_decode64(jwk_data['n']), 2)
|
|
49
|
-
e = OpenSSL::BN.new(Base64.urlsafe_decode64(jwk_data['e']), 2)
|
|
50
|
-
|
|
51
|
-
pkcs1 = OpenSSL::ASN1::Sequence([
|
|
52
|
-
OpenSSL::ASN1::Integer(n),
|
|
53
|
-
OpenSSL::ASN1::Integer(e)
|
|
54
|
-
]
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
spki = OpenSSL::ASN1::Sequence([
|
|
58
|
-
OpenSSL::ASN1::Sequence([
|
|
59
|
-
OpenSSL::ASN1::ObjectId('rsaEncryption'),
|
|
60
|
-
OpenSSL::ASN1::Null(nil)
|
|
61
|
-
]
|
|
62
|
-
),
|
|
63
|
-
OpenSSL::ASN1::BitString(pkcs1.to_der)
|
|
64
|
-
]
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
OpenSSL::PKey::RSA.new(spki.to_der)
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def refresh_jwks
|
|
71
|
-
Rails.cache.delete('facebook-limited-jwks')
|
|
72
|
-
fetch_jwks
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def fetch_jwks
|
|
76
|
-
Rails.cache.fetch('facebook-limited-jwks', expires_in: 1.hour) do
|
|
77
|
-
url = URI(JWKS_URL)
|
|
78
|
-
http = Net::HTTP.new(url.host, url.port)
|
|
79
|
-
http.use_ssl = true
|
|
80
|
-
http.open_timeout = 5
|
|
81
|
-
http.read_timeout = 10
|
|
82
|
-
response = http.get(url.request_uri)
|
|
83
|
-
JSON.parse(response.body)
|
|
84
|
-
end
|
|
85
|
-
rescue StandardError => e
|
|
86
|
-
CmAppLogger.error("Facebook JWKS fetch error: #{e.message}")
|
|
87
|
-
context.fail!(message: 'facebook_jwks_fetch_error')
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
end
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
module SpreeCmCommissioner
|
|
2
|
-
class UserFbJwtAuthenticator < BaseInteractor
|
|
3
|
-
delegate :fb_jwt, :tenant_id, to: :context
|
|
4
|
-
|
|
5
|
-
# :fb_jwt, :tenant_id (optional)
|
|
6
|
-
def call
|
|
7
|
-
context.fail!(message: 'fb_jwt_missing') unless fb_jwt
|
|
8
|
-
context.fail!(message: checker.message) if checker.failure?
|
|
9
|
-
|
|
10
|
-
context.user = if checker.user.nil?
|
|
11
|
-
register_user
|
|
12
|
-
else
|
|
13
|
-
checker.user
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
context.fail!(message: 'account_temporarily_deleted') if context.user.soft_deleted?
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
private
|
|
20
|
-
|
|
21
|
-
def checker
|
|
22
|
-
@checker ||= SpreeCmCommissioner::UserFbJwtChecker.call(
|
|
23
|
-
fb_jwt: fb_jwt,
|
|
24
|
-
tenant_id: tenant_id
|
|
25
|
-
)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def register_user
|
|
29
|
-
register_context = SpreeCmCommissioner::UserRegistrationWithFbToken.call(
|
|
30
|
-
provider: checker.provider,
|
|
31
|
-
tenant_id: tenant_id
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
register_context.user
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
module SpreeCmCommissioner
|
|
2
|
-
class UserFbJwtChecker < BaseInteractor
|
|
3
|
-
delegate :tenant_id, :fb_jwt, to: :context
|
|
4
|
-
|
|
5
|
-
def call
|
|
6
|
-
fb_data = SpreeCmCommissioner::FetchFacebookUserDataFromJwt.call(fb_jwt: fb_jwt)
|
|
7
|
-
context.fail!(message: fb_data.message) if fb_data.failure?
|
|
8
|
-
|
|
9
|
-
context.provider = fb_data.provider
|
|
10
|
-
|
|
11
|
-
identity_checker = SpreeCmCommissioner::UserIdentityChecker.call(
|
|
12
|
-
identity_type: context.provider[:identity_type],
|
|
13
|
-
sub: context.provider[:sub],
|
|
14
|
-
tenant_id: tenant_id
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
context.user = identity_checker.success? ? identity_checker.user : nil
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|