spree_cm_commissioner 2.8.15.pre.pre9 → 2.8.15
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/.env.example +4 -0
- data/Gemfile.lock +2 -2
- data/app/controllers/concerns/spree_cm_commissioner/content_cachable.rb +8 -0
- data/app/controllers/concerns/spree_cm_commissioner/load_test_account_management.rb +80 -0
- data/app/controllers/concerns/spree_cm_commissioner/load_test_account_scope.rb +39 -0
- data/app/controllers/concerns/spree_cm_commissioner/load_test_bypassable.rb +29 -0
- data/app/controllers/concerns/spree_cm_commissioner/load_test_login_token_generation.rb +53 -0
- data/app/controllers/concerns/spree_cm_commissioner/order_concern.rb +5 -0
- data/app/controllers/concerns/spree_cm_commissioner/turnstile_protectable.rb +9 -7
- data/app/controllers/spree/admin/guests_controller.rb +4 -2
- data/app/controllers/spree/admin/system/load_test_accounts_controller.rb +24 -0
- data/app/controllers/spree/admin/system/load_test_flows_controller.rb +11 -0
- data/app/controllers/spree/admin/system/load_test_login_tokens_controller.rb +16 -0
- data/app/controllers/spree/admin/system/load_testing_controller.rb +9 -0
- data/app/controllers/spree/admin/users_controller_decorator.rb +18 -0
- data/app/controllers/spree/api/chatrace/guests_controller.rb +1 -1
- data/app/controllers/spree/api/v2/operator/event_charts_controller.rb +1 -0
- data/app/controllers/spree/api/v2/operator/guest_json_gzips_controller.rb +14 -4
- data/app/controllers/spree/api/v2/storefront/account/guest_dynamic_fields_controller.rb +19 -48
- data/app/controllers/spree/api/v2/storefront/account/mark_guest_info_complete_controller.rb +2 -2
- data/app/controllers/spree/api/v2/storefront/account/orders_controller_decorator.rb +5 -15
- data/app/controllers/spree/api/v2/storefront/account/saved_guests_controller.rb +65 -0
- data/app/controllers/spree/api/v2/storefront/account_checker_controller.rb +4 -0
- data/app/controllers/spree/api/v2/storefront/draft_orders_controller.rb +52 -0
- data/app/controllers/spree/api/v2/storefront/guests_controller.rb +10 -9
- data/app/controllers/spree/api/v2/storefront/order_histories_controller.rb +0 -1
- data/app/controllers/spree/api/v2/storefront/payment_methods_controller.rb +40 -0
- data/app/controllers/spree/api/v2/storefront/preview_sections_controller.rb +1 -7
- data/app/controllers/spree/api/v2/storefront/telegram_oauth_tokens_controller.rb +61 -0
- data/app/controllers/spree/api/v2/storefront/waiting_room_sessions_controller.rb +8 -1
- data/app/controllers/spree/api/v2/tenant/account/orders_controller.rb +1 -1
- data/app/controllers/spree/api/v2/tenant/account/saved_guests_controller.rb +70 -0
- data/app/controllers/spree/api/v2/tenant/draft_orders_controller.rb +50 -0
- data/app/controllers/spree/api/v2/tenant/episodes_controller.rb +3 -1
- data/app/controllers/spree/api/v2/tenant/guests_controller.rb +11 -21
- data/app/controllers/spree/api/v2/tenant/my_votes_controller.rb +51 -0
- data/app/controllers/spree/api/v2/tenant/order_histories_controller.rb +2 -1
- data/app/controllers/spree/api/v2/tenant/payment_methods_controller.rb +54 -0
- data/app/controllers/spree/api/v2/tenant/preview_products_controller.rb +1 -1
- data/app/controllers/spree/api/v2/tenant/preview_sections_controller.rb +1 -7
- data/app/controllers/spree/api/v2/tenant/show_people_controller.rb +1 -4
- data/app/controllers/spree/api/v2/tenant/show_person_assignments_controller.rb +4 -1
- data/app/controllers/spree/api/v2/tenant/voting_contestants_controller.rb +6 -3
- data/app/controllers/spree/api/v2/tenant/waiting_room_sessions_controller.rb +8 -1
- data/app/controllers/spree_cm_commissioner/admin/orders_controller_decorator.rb +9 -0
- data/app/controllers/spree_cm_commissioner/admin/variants_controller_decorator.rb +17 -0
- data/app/controllers/spree_cm_commissioner/api/v2/storefront/checkout_controller_decorator.rb +3 -3
- data/app/finders/spree_cm_commissioner/payment_methods/find.rb +59 -0
- data/app/finders/spree_cm_commissioner/routes/find.rb +1 -1
- data/app/interactors/spree_cm_commissioner/create_ticket.rb +7 -3
- data/app/interactors/spree_cm_commissioner/host_matcher.rb +6 -5
- data/app/interactors/spree_cm_commissioner/telegram_oauth_id_token_provider.rb +99 -0
- data/app/interactors/spree_cm_commissioner/telegram_oauth_token_exchanger.rb +71 -0
- data/app/interactors/spree_cm_commissioner/turnstile_token_validator.rb +43 -13
- data/app/interactors/spree_cm_commissioner/user_id_token_authenticator.rb +2 -5
- data/app/interactors/spree_cm_commissioner/user_password_authenticator.rb +23 -1
- data/app/interactors/spree_cm_commissioner/user_telegram_oauth_authenticator.rb +88 -0
- data/app/interactors/spree_cm_commissioner/waiting_guests_caller.rb +11 -2
- data/app/interactors/spree_cm_commissioner/waiting_room_session_creator.rb +31 -6
- data/app/jobs/spree_cm_commissioner/maintenance_tasks/guest_data_fill_stage_batch_job.rb +28 -0
- data/app/mailers/spree/order_mailer_decorator.rb +2 -0
- data/app/models/concerns/spree_cm_commissioner/event_metadata.rb +17 -2
- data/app/models/concerns/spree_cm_commissioner/guest_data_fill_stage_concern.rb +82 -0
- data/app/models/concerns/spree_cm_commissioner/kyc_bitwise.rb +17 -0
- data/app/models/concerns/spree_cm_commissioner/line_item_durationable.rb +4 -0
- data/app/models/concerns/spree_cm_commissioner/line_item_guests_concern.rb +1 -1
- data/app/models/concerns/spree_cm_commissioner/line_items_filter_scope.rb +5 -3
- data/app/models/concerns/spree_cm_commissioner/option_type_attr_type.rb +0 -1
- data/app/models/concerns/spree_cm_commissioner/order_qr_codeable.rb +39 -0
- data/app/models/concerns/spree_cm_commissioner/order_scopes.rb +5 -0
- data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +26 -31
- data/app/models/concerns/spree_cm_commissioner/product_delegation.rb +2 -0
- data/app/models/concerns/spree_cm_commissioner/purchase_limitable.rb +59 -0
- data/app/models/concerns/spree_cm_commissioner/store_preference.rb +2 -0
- data/app/models/concerns/spree_cm_commissioner/tenant_preference.rb +2 -0
- data/app/models/concerns/spree_cm_commissioner/variant_options_concern.rb +0 -1
- data/app/models/spree_cm_commissioner/check_in_session.rb +36 -0
- data/app/models/spree_cm_commissioner/current.rb +11 -0
- data/app/models/spree_cm_commissioner/dynamic_field.rb +12 -0
- data/app/models/spree_cm_commissioner/exports/operator_guest_json_gzip.rb +26 -1
- data/app/models/spree_cm_commissioner/guest.rb +5 -144
- data/app/models/spree_cm_commissioner/guest_dynamic_field.rb +43 -71
- data/app/models/spree_cm_commissioner/homepage_section_relatable.rb +25 -0
- data/app/models/spree_cm_commissioner/line_item_decorator.rb +4 -3
- data/app/models/spree_cm_commissioner/maintenance_tasks/event.rb +9 -1
- data/app/models/spree_cm_commissioner/maintenance_tasks/guest_data_fill_stage.rb +21 -0
- data/app/models/spree_cm_commissioner/order_decorator.rb +22 -31
- data/app/models/spree_cm_commissioner/payment_method_decorator.rb +2 -0
- data/app/models/spree_cm_commissioner/pricing_model_route.rb +8 -0
- data/app/models/spree_cm_commissioner/product_decorator.rb +2 -22
- data/app/models/spree_cm_commissioner/product_dynamic_field.rb +17 -0
- data/app/models/spree_cm_commissioner/request_guard.rb +19 -0
- data/app/models/spree_cm_commissioner/role_decorator.rb +52 -4
- data/app/models/spree_cm_commissioner/role_user_decorator.rb +11 -0
- data/app/models/spree_cm_commissioner/seat_layout.rb +12 -4
- data/app/models/spree_cm_commissioner/show.rb +3 -1
- data/app/models/spree_cm_commissioner/show_episode.rb +3 -1
- data/app/models/spree_cm_commissioner/show_person.rb +5 -1
- data/app/models/spree_cm_commissioner/show_person_assignment.rb +1 -1
- data/app/models/spree_cm_commissioner/taxon_decorator.rb +2 -0
- data/app/models/spree_cm_commissioner/tenant.rb +17 -6
- data/app/models/spree_cm_commissioner/trip.rb +18 -1
- data/app/models/spree_cm_commissioner/user_decorator.rb +67 -1
- data/app/models/spree_cm_commissioner/variant_options.rb +0 -4
- data/app/models/spree_cm_commissioner/vehicle_type.rb +1 -0
- data/app/models/spree_cm_commissioner/voting_contestant.rb +21 -7
- data/app/models/spree_cm_commissioner/waiting_room_session.rb +14 -0
- data/app/overrides/spree/admin/payment_methods/index/pagination.html.erb.deface +3 -0
- data/app/overrides/spree/admin/payment_methods/index/preserve_tab_in_search.html.erb.deface +4 -0
- data/app/overrides/spree/admin/products/_form/enable_social_sharing_email.html.erb.deface +13 -0
- data/app/overrides/spree/admin/shared/_order_summary/internal_note.html.erb.deface +23 -0
- data/app/overrides/spree/admin/shared/_order_summary/internal_note_modal.html.erb.deface +40 -0
- data/app/overrides/spree/admin/stores/_form/telegram_auth.html.erb.deface +73 -0
- data/app/overrides/spree/admin/variants/index/fixture_action.html.erb.deface +9 -0
- data/app/queries/spree_cm_commissioner/event_chart_queries.rb +25 -9
- data/app/queries/spree_cm_commissioner/guest_searcher_query.rb +16 -3
- data/app/queries/spree_cm_commissioner/multi_leg_trips_query.rb +7 -0
- data/app/queries/spree_cm_commissioner/pie_chart_event_aggregator_queries.rb +3 -2
- data/app/queries/spree_cm_commissioner/single_leg_trips_query.rb +2 -1
- data/app/queries/spree_cm_commissioner/user_votes_per_contestant_query.rb +48 -0
- data/app/serializers/spree/v2/storefront/line_item_serializer_decorator.rb +2 -2
- data/app/serializers/spree/v2/storefront/product_serializer_decorator.rb +4 -0
- data/app/serializers/spree/v2/storefront/taxon_serializer_decorator.rb +1 -0
- data/app/serializers/spree/v2/storefront/user_serializer_decorator.rb +5 -2
- data/app/serializers/spree/v2/storefront/variant_serializer_decorator.rb +2 -1
- data/app/serializers/spree/v2/tenant/my_vote_serializer.rb +19 -0
- data/app/serializers/spree/v2/tenant/product_serializer.rb +5 -0
- data/app/serializers/spree/v2/tenant/saved_guest_serializer.rb +23 -0
- data/app/serializers/spree/v2/tenant/show_episode_serializer.rb +1 -9
- data/app/serializers/spree/v2/tenant/show_serializer.rb +2 -1
- data/app/serializers/spree/v2/tenant/user_serializer.rb +1 -1
- data/app/serializers/spree/v2/tenant/variant_serializer.rb +2 -1
- data/app/serializers/spree/v2/tenant/voting_contestant_serializer.rb +2 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/cart_serializer_decorator.rb +1 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/guest_serializer.rb +3 -6
- data/app/serializers/spree_cm_commissioner/v2/storefront/ticket_transfer_serializer.rb +2 -2
- data/app/serializers/spree_cm_commissioner/v2/storefront/trip_result_serializer.rb +2 -2
- data/app/serializers/spree_cm_commissioner/v2/storefront/trip_serializer.rb +3 -1
- data/app/services/spree_cm_commissioner/api_caches/invalidate.rb +24 -3
- data/app/services/spree_cm_commissioner/check_ins/create_bulk.rb +10 -6
- data/app/services/spree_cm_commissioner/draft_order/create.rb +95 -0
- data/app/services/spree_cm_commissioner/{cart/create_guest.rb → guests/create.rb} +12 -10
- data/app/services/spree_cm_commissioner/guests/refresh_data_fill_stage.rb +20 -0
- data/app/services/spree_cm_commissioner/guests/send_dynamic_field_notification.rb +15 -0
- data/app/services/spree_cm_commissioner/guests/update.rb +68 -0
- data/app/services/spree_cm_commissioner/imports/contestants/create.rb +19 -1
- data/app/services/spree_cm_commissioner/inventory_holds/validate_limits.rb +8 -3
- data/app/services/spree_cm_commissioner/line_items/validate_purchase_limits.rb +97 -0
- data/app/services/spree_cm_commissioner/load_test/create_accounts.rb +68 -0
- data/app/services/spree_cm_commissioner/load_test/destroy_accounts.rb +47 -0
- data/app/services/spree_cm_commissioner/load_test/flow_registry.rb +26 -0
- data/app/services/spree_cm_commissioner/load_test/generate_booking_ticket_data.rb +204 -0
- data/app/services/spree_cm_commissioner/load_test/generate_voting_fixture_data.rb +178 -0
- data/app/services/spree_cm_commissioner/load_test/login_token.rb +46 -0
- data/app/services/spree_cm_commissioner/operator_guest_json_gzips/create.rb +14 -7
- data/app/services/spree_cm_commissioner/order/guests/update.rb +53 -0
- data/app/services/spree_cm_commissioner/organizer/export_guest_csv_service.rb +12 -11
- 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/show_contestants/normalize_video_highlights.rb +5 -1
- data/app/services/spree_cm_commissioner/trips/update_single_leg.rb +6 -1
- data/app/services/spree_cm_commissioner/user_authenticator.rb +22 -1
- data/app/services/spree_cm_commissioner/voting_contestants/advancer.rb +10 -3
- data/app/services/spree_cm_commissioner/voting_contestants/assigner.rb +20 -2
- data/app/services/spree_cm_commissioner/voting_contestants/bulk_updater.rb +15 -9
- data/app/services/spree_cm_commissioner/voting_credits/allocate.rb +13 -2
- data/app/services/spree_cm_commissioner/voting_leaderboards/time_range_result.rb +79 -0
- data/app/views/spree/admin/featured_trips/index.html.erb +1 -1
- data/app/views/spree/admin/guests/_form.html.erb +37 -0
- data/app/views/spree/admin/shared/_system_tabs.html.erb +7 -0
- data/app/views/spree/admin/system/load_test_accounts/_login_tokens_modal.html.erb +52 -0
- data/app/views/spree/admin/system/load_test_accounts/index.html.erb +175 -0
- data/app/views/spree/admin/system/load_test_flows/index.html.erb +66 -0
- data/app/views/spree/admin/system/load_testing/index.html.erb +25 -0
- data/app/views/spree/admin/tenants/_form.html.erb +40 -1
- data/app/views/spree/admin/tenants/form/_telegram_auth.html.erb +61 -0
- data/app/views/spree/admin/variants/fixture.html.erb +49 -0
- data/config/initializers/doorkeeper.rb +10 -6
- data/config/initializers/spree_permitted_attributes.rb +51 -0
- data/config/load_test_flows/platform.yml +25 -0
- data/config/load_test_flows/tenant.yml +93 -0
- data/config/locales/en.yml +127 -13
- data/config/locales/km.yml +39 -8
- data/config/routes.rb +26 -1
- data/db/migrate/20260630000001_add_trip_to_cm_pricing_model_routes.rb +7 -0
- data/db/migrate/20260701000001_add_device_info_to_cm_waiting_room_sessions.rb +14 -0
- data/db/migrate/20260703065239_add_position_to_cm_voting_contestants.rb +6 -0
- data/db/migrate/20260708150000_add_name_and_short_name_to_cm_trips.rb +6 -0
- data/db/migrate/20260713022227_add_advanced_to_episode_id_to_cm_voting_contestants.rb +8 -0
- data/db/migrate/20260714002626_rename_data_fill_stage_phase_on_cm_guests.rb +5 -0
- data/db/migrate/20260720000001_add_check_in_fields_to_spree_roles.rb +11 -0
- data/db/migrate/20260723000000_add_payment_host_to_cm_tenants.rb +6 -0
- data/db/migrate/20260723000001_add_metadata_to_spree_roles.rb +11 -0
- data/db/migrate/20260728074153_add_role_to_cm_exports.rb +5 -0
- data/db/migrate/20260729000000_add_visibility_to_cm_trips.rb +6 -0
- data/db/migrate/20260729000001_add_session_created_at_index_to_cm_votes.rb +12 -0
- data/db/migrate/20260730000000_add_purchase_limit_scopes_to_spree_orders.rb +22 -0
- data/lib/spree_cm_commissioner/test_helper/factories/option_type_factory.rb +0 -6
- data/lib/spree_cm_commissioner/test_helper/factories/pricing_model_trip_factory.rb +11 -0
- data/lib/spree_cm_commissioner/test_helper/factories/vehicle_factory.rb +1 -1
- data/lib/spree_cm_commissioner/trip_result.rb +3 -1
- data/lib/spree_cm_commissioner/version.rb +1 -1
- data/lib/tasks/recompute_guest_data_fill_stage.rake +19 -0
- metadata +78 -14
- data/app/controllers/spree/api/v2/storefront/saved_guests_controller.rb +0 -77
- data/app/interactors/spree_cm_commissioner/guest_dynamic_field_notification_sender.rb +0 -11
- data/app/interactors/spree_cm_commissioner/guest_dynamic_fields_manager.rb +0 -33
- data/app/serializers/spree/v2/storefront/order_serializer_decorator.rb +0 -63
- data/app/serializers/spree_cm_commissioner/v2/storefront/guest_minimal_serializer.rb +0 -30
- data/app/serializers/spree_cm_commissioner/v2/storefront/line_item_minimal_serializer.rb +0 -57
- data/app/serializers/spree_cm_commissioner/v2/storefront/ticket_transfer_minimal_serializer.rb +0 -17
- data/app/services/spree_cm_commissioner/update_guest_service.rb +0 -129
- data/app/services/spree_cm_commissioner/users/incomplete_guest_checker_service.rb +0 -34
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ca0138759a1da40541b5d076fb9709847d44d88885593f5b69921993cfd26591
|
|
4
|
+
data.tar.gz: 79408535d56a9d4b62cac5154a316f6652d6d8664c04a030f00588b39f7ddd24
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3e1a90b2f9115755fcd8cb777e0cd4d3c05b950a8a1b913ac526be4c5967d062533b5683bf48d3ca979e726347bb1945520b0701337872e7626d2fc3524d7952
|
|
7
|
+
data.tar.gz: 8b4813fe21cc8495e2a512ea1662e2105ba61994c1866794bd9da91ef5c805b1b49cc9d8ea5cdf53f35dd2fe6a96295491eea72853cfdaf899377264922e8a84
|
data/.env.example
CHANGED
|
@@ -32,6 +32,10 @@ WAITING_ROOM_MAX_ETA_BATCH_SIZE=50 # cap on batch size assumed when estimating t
|
|
|
32
32
|
VATTANAC_AES_SECRET_KEY= ""
|
|
33
33
|
VATTANAC_PUBLIC_KEY=""
|
|
34
34
|
|
|
35
|
+
# Telegram OAuth (OpenID Connect) login client_id/client_secret are configured
|
|
36
|
+
# per tenant (or on the default store for tenant-less logins) from the admin
|
|
37
|
+
# under Telegram Authentication - see docs/authentication/telegram-login.md.
|
|
38
|
+
|
|
35
39
|
# Organizer URL
|
|
36
40
|
ORGANIZER_URL=http://127.0.0.1:4000/organizer
|
|
37
41
|
|
data/Gemfile.lock
CHANGED
|
@@ -34,7 +34,7 @@ GIT
|
|
|
34
34
|
PATH
|
|
35
35
|
remote: .
|
|
36
36
|
specs:
|
|
37
|
-
spree_cm_commissioner (2.8.15
|
|
37
|
+
spree_cm_commissioner (2.8.15)
|
|
38
38
|
activerecord-multi-tenant
|
|
39
39
|
activerecord_json_validator (~> 2.1, >= 2.1.3)
|
|
40
40
|
aws-sdk-cloudfront
|
|
@@ -886,7 +886,7 @@ GEM
|
|
|
886
886
|
spree_backend (>= 4.3.0.rc1)
|
|
887
887
|
spree_emails (>= 4.3.0.rc1)
|
|
888
888
|
spree_extension
|
|
889
|
-
spree_vpago (2.
|
|
889
|
+
spree_vpago (2.3.4)
|
|
890
890
|
faraday
|
|
891
891
|
google-cloud-firestore
|
|
892
892
|
spree_api (>= 4.5)
|
|
@@ -27,6 +27,13 @@ module SpreeCmCommissioner
|
|
|
27
27
|
PopularRoutesController
|
|
28
28
|
RoutePlacesController
|
|
29
29
|
ShowsController
|
|
30
|
+
EpisodesController
|
|
31
|
+
ShowPeopleController
|
|
32
|
+
ShowPersonAssignmentsController
|
|
33
|
+
ShowContestantsController
|
|
34
|
+
VotePackagesController
|
|
35
|
+
ShowEliminationSessionsController
|
|
36
|
+
PaymentMethodsController
|
|
30
37
|
].freeze
|
|
31
38
|
|
|
32
39
|
# Priority 3: Moderate Freshness (30 minutes)
|
|
@@ -46,6 +53,7 @@ module SpreeCmCommissioner
|
|
|
46
53
|
HIGH_FRESHNESS_CONTROLLERS = %w[
|
|
47
54
|
TripsController
|
|
48
55
|
TripSearchController
|
|
56
|
+
VotingContestantsController
|
|
49
57
|
].freeze
|
|
50
58
|
|
|
51
59
|
def shared_max_age
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
module LoadTestAccountManagement
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
include SpreeCmCommissioner::LoadTestAccountScope
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
before_action :authorize_load_testing!, only: %i[create bulk_destroy]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Ensures N load-test accounts exist (idempotent) for `load_test_tenant` (nil = platform).
|
|
12
|
+
def create
|
|
13
|
+
result = SpreeCmCommissioner::LoadTest::CreateAccounts.call(**pool_params)
|
|
14
|
+
|
|
15
|
+
if result.success?
|
|
16
|
+
flash[:success] = "#{result.value[:created]} load-test accounts created."
|
|
17
|
+
else
|
|
18
|
+
flash[:error] = result.error.value
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
redirect_to manage_accounts_redirect_path
|
|
22
|
+
rescue StandardError => e
|
|
23
|
+
flash[:error] = e.message
|
|
24
|
+
redirect_to manage_accounts_redirect_path
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def bulk_destroy
|
|
28
|
+
result = SpreeCmCommissioner::LoadTest::DestroyAccounts.call(**pool_params)
|
|
29
|
+
|
|
30
|
+
if result.success?
|
|
31
|
+
flash[:success] = "#{result.value[:destroyed]} destroyed, #{result.value[:not_found]} not found (already removed)."
|
|
32
|
+
else
|
|
33
|
+
flash[:error] = result.error.value
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
redirect_to manage_accounts_redirect_path
|
|
37
|
+
rescue StandardError => e
|
|
38
|
+
flash[:error] = e.message
|
|
39
|
+
redirect_to manage_accounts_redirect_path
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
# Default: cancancan's `authorize!`. Override in the including controller if it doesn't use
|
|
45
|
+
# cancancan (e.g. the organizer dashboard, which authorizes via RoleAuthorization/can_manage?).
|
|
46
|
+
def authorize_load_testing!
|
|
47
|
+
authorize! :manage, :load_testing
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Where create/bulk_destroy redirect back to. Must be implemented by the including controller
|
|
51
|
+
# (points at its own Load Test Accounts page).
|
|
52
|
+
def manage_accounts_redirect_path
|
|
53
|
+
raise NotImplementedError, "#{self.class} must implement #manage_accounts_redirect_path"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def pool_params
|
|
57
|
+
{
|
|
58
|
+
client_id: resolve_client_id,
|
|
59
|
+
count: params[:count].presence&.to_i || 20,
|
|
60
|
+
email_prefix: params[:email_prefix].presence || 'loadtest',
|
|
61
|
+
email_domain: params[:email_domain].presence
|
|
62
|
+
}
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Carries the form field values through the redirect so the index page re-renders with the
|
|
66
|
+
# same count/prefix/domain/page/per_page the admin/organizer just submitted with.
|
|
67
|
+
def redirect_params
|
|
68
|
+
params.slice(:count, :email_prefix, :email_domain, :page, :per_page).permit!
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def resolve_client_id
|
|
72
|
+
return nil if load_test_tenant.nil?
|
|
73
|
+
|
|
74
|
+
application = Spree::OauthApplication.where(tenant_id: load_test_tenant.id).order(:id).first
|
|
75
|
+
raise "No OAuth application found for tenant #{load_test_tenant.name}" unless application
|
|
76
|
+
|
|
77
|
+
application.uid
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
module LoadTestAccountScope
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
private
|
|
6
|
+
|
|
7
|
+
# The tenant these accounts are scoped to. nil means the platform (no tenant). Must be
|
|
8
|
+
# implemented by the including controller.
|
|
9
|
+
def load_test_tenant
|
|
10
|
+
raise NotImplementedError, "#{self.class} must implement #load_test_tenant"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
DEFAULT_EXPORT_PER_PAGE = 10
|
|
14
|
+
|
|
15
|
+
# Queried fresh from the DB every time, so it's always in sync with the current pool rather than
|
|
16
|
+
# a stashed file or session state.
|
|
17
|
+
#
|
|
18
|
+
# Filters the `load_test_account` flag in SQL via the model's `load_test_accounts` scope (see
|
|
19
|
+
# UserDecorator), so only the tenant's load-test accounts are considered — never the whole users
|
|
20
|
+
# table. Unlike the old `order(:id).limit(2000).select(&:...)` approach, there's no scan cap:
|
|
21
|
+
# newly created accounts (highest ids, ordered first below) always show up even on tenants with
|
|
22
|
+
# far more than 2,000 users.
|
|
23
|
+
#
|
|
24
|
+
# Kaminari pages on the relation itself, so the DB only ever loads the current page's rows
|
|
25
|
+
# (`LIMIT`/`OFFSET`) — never the full pool into memory — via the same `page`/`per_page` params
|
|
26
|
+
# and `paginate` view helper every other index page in this app uses.
|
|
27
|
+
#
|
|
28
|
+
# Shared between LoadTestAccountManagement (lists/mutates the pool) and
|
|
29
|
+
# LoadTestLoginTokenGeneration (mints tokens for exactly the page shown), so both controllers
|
|
30
|
+
# resolve the same page the same way.
|
|
31
|
+
def export_accounts
|
|
32
|
+
Spree::User.where(tenant_id: load_test_tenant&.id)
|
|
33
|
+
.load_test_accounts
|
|
34
|
+
.order(id: :desc)
|
|
35
|
+
.page(params[:page])
|
|
36
|
+
.per(params[:per_page] || DEFAULT_EXPORT_PER_PAGE)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
# Sets Current.load_test_bypass when the request carries the correct X-Request-Verify secret, so
|
|
3
|
+
# anti-abuse services (e.g. InventoryHolds::ValidateLimits) can skip their checks for trusted
|
|
4
|
+
# load tests. No-op unless LOAD_TEST_BYPASS_KEY is set. Include in any controller that can
|
|
5
|
+
# trigger such a check.
|
|
6
|
+
module LoadTestBypassable
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
|
|
9
|
+
included do
|
|
10
|
+
before_action :set_load_test_bypass_current
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
# Always assigns the flag (false unless the request carries the correct
|
|
16
|
+
# secret), so its value never leaks from a previous request.
|
|
17
|
+
def set_load_test_bypass_current
|
|
18
|
+
SpreeCmCommissioner::Current.load_test_bypass = load_test_bypass_requested?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def load_test_bypass_requested?
|
|
22
|
+
key = ENV.fetch('LOAD_TEST_BYPASS_KEY', nil)
|
|
23
|
+
return false if key.blank?
|
|
24
|
+
|
|
25
|
+
provided = request.headers.fetch('X-Request-Verify', nil).to_s
|
|
26
|
+
ActiveSupport::SecurityUtils.secure_compare(provided, key)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
module LoadTestLoginTokenGeneration
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
include SpreeCmCommissioner::LoadTestAccountScope
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
before_action :authorize_load_testing!, only: %i[create]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Mints a fresh, stateless login-token JWT for each account on the requested page (same
|
|
12
|
+
# page/per_page as the Load Test Accounts index) and returns them as JSON. Nothing is
|
|
13
|
+
# persisted — the tokens are self-contained and verified by signature + expiry alone (see
|
|
14
|
+
# SpreeCmCommissioner::LoadTest::LoginToken).
|
|
15
|
+
def create
|
|
16
|
+
render json: login_tokens_payload(export_accounts)
|
|
17
|
+
rescue StandardError => e
|
|
18
|
+
render json: { error: e.message }, status: :unprocessable_entity
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
# Default: cancancan's `authorize!`. Override in the including controller if it doesn't use
|
|
24
|
+
# cancancan (e.g. the organizer dashboard, which authorizes via RoleAuthorization/can_manage?).
|
|
25
|
+
def authorize_load_testing!
|
|
26
|
+
authorize! :manage, :load_testing
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# aud claim: the admin/organizer who minted the tokens. No fallback — both hosting controllers
|
|
30
|
+
# already require an authenticated user for every action here, so spree_current_user being
|
|
31
|
+
# absent would be a bug worth raising on, not silently mislabeling as 'system'.
|
|
32
|
+
def token_audience
|
|
33
|
+
spree_current_user.id
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# user_id + the user_id_token are all k6 needs (email and expiry are already claims inside the
|
|
37
|
+
# JWT itself — sub / exp — and the token alone identifies + authenticates the account via
|
|
38
|
+
# UserPasswordAuthenticator's token-only path). expires_at is included too, purely so the
|
|
39
|
+
# generated-tokens list can show it to a human without decoding the JWT. Named `user_id_token`
|
|
40
|
+
# (not `id_token`) so UserAuthenticator can route on the params key alone, without decoding
|
|
41
|
+
# every request's `id_token` to check whether it's a load-test token.
|
|
42
|
+
def login_tokens_payload(accounts)
|
|
43
|
+
accounts.map do |user|
|
|
44
|
+
generated = SpreeCmCommissioner::LoadTest::LoginToken.generate(user: user, audience: token_audience)
|
|
45
|
+
{
|
|
46
|
+
user_id: user.id,
|
|
47
|
+
user_id_token: generated[:token],
|
|
48
|
+
expires_at: generated[:expires_at]
|
|
49
|
+
}
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -12,6 +12,7 @@ module SpreeCmCommissioner
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
@spree_current_order.last_ip_address = request.remote_ip
|
|
15
|
+
@spree_current_order.device_id = device_id if device_id.present?
|
|
15
16
|
@spree_current_order
|
|
16
17
|
end
|
|
17
18
|
|
|
@@ -25,5 +26,9 @@ module SpreeCmCommissioner
|
|
|
25
26
|
state: params[:state]
|
|
26
27
|
)
|
|
27
28
|
end
|
|
29
|
+
|
|
30
|
+
def device_id
|
|
31
|
+
params[:device_id].presence
|
|
32
|
+
end
|
|
28
33
|
end
|
|
29
34
|
end
|
|
@@ -27,13 +27,15 @@ module SpreeCmCommissioner
|
|
|
27
27
|
return unless result.failure?
|
|
28
28
|
|
|
29
29
|
render json: {
|
|
30
|
-
errors: [
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
30
|
+
errors: [
|
|
31
|
+
{
|
|
32
|
+
status: '403',
|
|
33
|
+
error_code: 'human_verification_failed',
|
|
34
|
+
title: I18n.t('turnstile.verification_failed'),
|
|
35
|
+
detail: result.message,
|
|
36
|
+
turnstile_error_code: result.respond_to?(:error_code) ? result.error_code : nil
|
|
37
|
+
}
|
|
38
|
+
]
|
|
37
39
|
}, status: :forbidden
|
|
38
40
|
end
|
|
39
41
|
|
|
@@ -80,8 +80,10 @@ module Spree
|
|
|
80
80
|
|
|
81
81
|
def permitted_resource_params
|
|
82
82
|
params.require(object_name).permit(:first_name, :last_name, :gender, :dob, :occupation_id,
|
|
83
|
-
:nationality_id, :age, :emergency_contact,
|
|
84
|
-
:seat_number, :phone_number
|
|
83
|
+
:nationality_id, :age, :emergency_contact,
|
|
84
|
+
:line_item_id, :seat_number, :phone_number, :contact,
|
|
85
|
+
:other_organization, :expectation, :address,
|
|
86
|
+
:social_contact_platform, :social_contact
|
|
85
87
|
)
|
|
86
88
|
end
|
|
87
89
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Admin
|
|
3
|
+
module System
|
|
4
|
+
class LoadTestAccountsController < Spree::Admin::BaseController
|
|
5
|
+
include SpreeCmCommissioner::LoadTestAccountManagement
|
|
6
|
+
|
|
7
|
+
def index
|
|
8
|
+
@export_accounts = export_accounts
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
# nil = platform. Admin load testing never operates on a tenant.
|
|
14
|
+
def load_test_tenant
|
|
15
|
+
nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def manage_accounts_redirect_path
|
|
19
|
+
admin_system_load_test_accounts_path(**redirect_params)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Admin
|
|
3
|
+
module System
|
|
4
|
+
class LoadTestLoginTokensController < Spree::Admin::BaseController
|
|
5
|
+
include SpreeCmCommissioner::LoadTestLoginTokenGeneration
|
|
6
|
+
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
# nil = platform. Admin load testing never operates on a tenant.
|
|
10
|
+
def load_test_tenant
|
|
11
|
+
nil
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -20,8 +20,26 @@ module Spree
|
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
+
# override
|
|
24
|
+
def update
|
|
25
|
+
preserve_non_form_roles
|
|
26
|
+
super
|
|
27
|
+
end
|
|
28
|
+
|
|
23
29
|
private
|
|
24
30
|
|
|
31
|
+
# Role types the user form doesn't render (assigned in organizer dashboards), e.g. check-in groups and preview.
|
|
32
|
+
NON_FORM_ROLE_TYPES = %i[check_in preview].freeze
|
|
33
|
+
|
|
34
|
+
# spree_role_ids= replaces the whole role set, so a submit that omits these would drop them. Merge
|
|
35
|
+
# the user's existing ones back in so they survive. Skip when the form didn't submit roles at all.
|
|
36
|
+
def preserve_non_form_roles
|
|
37
|
+
return if params.dig(:user, :spree_role_ids).nil?
|
|
38
|
+
|
|
39
|
+
preserved_ids = @user.spree_roles.where(role_type: NON_FORM_ROLE_TYPES).pluck(:id).map(&:to_s)
|
|
40
|
+
params[:user][:spree_role_ids] = (params[:user][:spree_role_ids] + preserved_ids).uniq
|
|
41
|
+
end
|
|
42
|
+
|
|
25
43
|
def build_profile
|
|
26
44
|
return unless permitted_resource_params[:profile]
|
|
27
45
|
|
|
@@ -53,7 +53,7 @@ module Spree
|
|
|
53
53
|
preferences upload_later social_contact_platform user_id
|
|
54
54
|
bib_number bib_prefix bib_index public_metadata private_metadata
|
|
55
55
|
seat_number intel_phone_number block_id saved_guest_id
|
|
56
|
-
|
|
56
|
+
data_fill_stage
|
|
57
57
|
].freeze
|
|
58
58
|
|
|
59
59
|
def guest_base_columns
|
|
@@ -26,6 +26,8 @@ module Spree
|
|
|
26
26
|
|
|
27
27
|
result = SpreeCmCommissioner::OperatorGuestJsonGzips::Create.call(
|
|
28
28
|
exportable: exportable,
|
|
29
|
+
# Scope the offline file to the requesting operator's check-in role (nil = unrestricted).
|
|
30
|
+
role: spree_current_user.check_in_role_for(exportable),
|
|
29
31
|
force_create: false,
|
|
30
32
|
options: {
|
|
31
33
|
created_by_id: spree_current_user.id.to_s,
|
|
@@ -53,11 +55,19 @@ module Spree
|
|
|
53
55
|
end
|
|
54
56
|
|
|
55
57
|
# override
|
|
58
|
+
# Scope the list to the requesting operator's check-in group, the same way the create cache
|
|
59
|
+
# does — otherwise a restricted crew could list (and download via exported_file_url) other
|
|
60
|
+
# groups' files for the event.
|
|
56
61
|
def scope
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
62
|
+
exportable = Spree::Taxon.find(params[:taxon_id])
|
|
63
|
+
|
|
64
|
+
SpreeCmCommissioner::Exports::OperatorGuestJsonGzip
|
|
65
|
+
.where(
|
|
66
|
+
exportable_type: 'Spree::Taxon',
|
|
67
|
+
exportable_id: params[:taxon_id],
|
|
68
|
+
role_id: spree_current_user.check_in_role_for(exportable)&.id
|
|
69
|
+
)
|
|
70
|
+
.order(created_at: :desc)
|
|
61
71
|
end
|
|
62
72
|
|
|
63
73
|
# override
|
|
@@ -4,69 +4,40 @@ module Spree
|
|
|
4
4
|
module Storefront
|
|
5
5
|
module Account
|
|
6
6
|
class GuestDynamicFieldsController < ::Spree::Api::V2::ResourceController
|
|
7
|
+
ALLOWED_PHASES = %w[pre_registration post_registration].freeze
|
|
8
|
+
|
|
7
9
|
before_action :require_spree_current_user
|
|
8
10
|
before_action :load_guest
|
|
9
11
|
|
|
10
12
|
def update_dynamic_field
|
|
11
|
-
phase
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
process_dynamic_field(field)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
@guest.save_and_move_to_next_stage
|
|
13
|
+
return render_error_payload('Invalid phase') unless ALLOWED_PHASES.include?(params[:phase])
|
|
14
|
+
return render_error_payload('No dynamic fields provided') if dynamic_fields_params.blank?
|
|
15
|
+
|
|
16
|
+
result = SpreeCmCommissioner::Guests::Update.call(
|
|
17
|
+
guest: @guest,
|
|
18
|
+
guest_params: {
|
|
19
|
+
guest_dynamic_fields_attributes: dynamic_fields_params.map { |f| { dynamic_field_id: f[:id], value: f[:value] } }
|
|
20
|
+
}
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
if result.success?
|
|
24
|
+
render_serialized_payload { serialize_guest(result.value[:guest]) }
|
|
25
|
+
else
|
|
26
|
+
render_error_payload(result.error)
|
|
29
27
|
end
|
|
30
|
-
|
|
31
|
-
render_serialized_payload { serialize_guest(@guest) }
|
|
32
|
-
rescue ActiveRecord::RecordInvalid => e
|
|
33
|
-
render_error_payload(e.record.errors, 422)
|
|
34
|
-
rescue ActiveRecord::RecordNotFound => e
|
|
35
|
-
render_error_payload(e.message, 404)
|
|
36
28
|
end
|
|
37
29
|
|
|
38
30
|
private
|
|
39
31
|
|
|
40
32
|
def dynamic_fields_params
|
|
41
|
-
params
|
|
42
|
-
field.permit(:id, :value)
|
|
43
|
-
end
|
|
33
|
+
Array(params[:dynamic_fields]).map { |field| field.permit(:id, :value) }
|
|
44
34
|
end
|
|
45
35
|
|
|
46
36
|
def load_guest
|
|
47
37
|
@guest = SpreeCmCommissioner::Guest.find(params[:guest_id])
|
|
48
38
|
|
|
49
|
-
unless spree_current_user.guests.exists?(id: @guest.id) ||
|
|
50
|
-
|
|
51
|
-
render_error_payload('Unauthorized', 401)
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def process_dynamic_field(field)
|
|
56
|
-
dynamic_field = SpreeCmCommissioner::DynamicField.find(field[:id])
|
|
57
|
-
guest_field = @guest.guest_dynamic_fields.build(dynamic_field_id: dynamic_field.id)
|
|
58
|
-
|
|
59
|
-
if dynamic_field.requires_dynamic_field_options?
|
|
60
|
-
option = dynamic_field.dynamic_field_options.find_by(value: field[:value])
|
|
61
|
-
raise ActiveRecord::RecordNotFound, "Invalid value for dynamic field #{dynamic_field.label}" unless option
|
|
62
|
-
|
|
63
|
-
guest_field.dynamic_field_option = option
|
|
64
|
-
guest_field.value = option.value
|
|
65
|
-
else
|
|
66
|
-
guest_field.value = field[:value]
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
guest_field.save!
|
|
39
|
+
raise CanCan::AccessDenied unless spree_current_user.guests.exists?(id: @guest.id) ||
|
|
40
|
+
@guest.line_item.order.user == spree_current_user
|
|
70
41
|
end
|
|
71
42
|
|
|
72
43
|
def serialize_guest(guest)
|
|
@@ -7,7 +7,7 @@ module Spree
|
|
|
7
7
|
before_action :require_spree_current_user
|
|
8
8
|
|
|
9
9
|
def update
|
|
10
|
-
|
|
10
|
+
spree_current_user.clear_has_incomplete_guest_info_cache
|
|
11
11
|
render_success
|
|
12
12
|
end
|
|
13
13
|
|
|
@@ -18,7 +18,7 @@ module Spree
|
|
|
18
18
|
{
|
|
19
19
|
success: true,
|
|
20
20
|
message: 'Guest information marked as complete',
|
|
21
|
-
has_incomplete_guest_info:
|
|
21
|
+
has_incomplete_guest_info: spree_current_user.has_incomplete_guest_info?
|
|
22
22
|
}
|
|
23
23
|
end
|
|
24
24
|
end
|
|
@@ -24,21 +24,11 @@ module Spree
|
|
|
24
24
|
private
|
|
25
25
|
|
|
26
26
|
def find_orders_with_incomplete_guest_info
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
order.line_items.any? do |line_item|
|
|
33
|
-
line_item.guests.any? do |guest|
|
|
34
|
-
guest.pre_registration_completed? &&
|
|
35
|
-
guest.post_registration_fields? &&
|
|
36
|
-
!guest.post_registration_completed?
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end.map(&:id)
|
|
40
|
-
|
|
41
|
-
spree_current_user.orders.where(id: incomplete_order_ids)
|
|
27
|
+
spree_current_user.orders
|
|
28
|
+
.complete
|
|
29
|
+
.joins(:guests)
|
|
30
|
+
.merge(SpreeCmCommissioner::Guest.post_registration)
|
|
31
|
+
.distinct
|
|
42
32
|
end
|
|
43
33
|
|
|
44
34
|
def collection_finder
|