spree_cm_commissioner 1.8.10 → 1.9.0
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 +25 -1
- data/app/controllers/spree/admin/user_events_controller.rb +9 -7
- data/app/controllers/spree/api/v2/storefront/vattanac_banks_controller.rb +25 -0
- data/app/controllers/spree/api/v2/tenant/change_passwords_controller.rb +32 -0
- data/app/controllers/spree/api/v2/tenant/id_cards_controller.rb +63 -0
- data/app/controllers/spree/api/v2/tenant/reset_passwords_controller.rb +35 -0
- data/app/controllers/spree/api/v2/tenant/tickets_controller.rb +25 -0
- data/app/controllers/spree/api/v2/tenant/user_contacts_controller.rb +33 -0
- data/app/controllers/spree_cm_commissioner/admin/roles_controller_decorator.rb +13 -0
- data/app/interactors/spree_cm_commissioner/firebase_email_fetcher.rb +25 -0
- data/app/interactors/spree_cm_commissioner/firebase_id_token_provider.rb +12 -1
- data/app/interactors/spree_cm_commissioner/user_id_token_authenticator.rb +11 -0
- data/app/interactors/spree_cm_commissioner/user_registration_with_id_token.rb +3 -3
- data/app/interactors/spree_cm_commissioner/user_vattanac_bank_web_app_authenticator.rb +30 -0
- data/app/interactors/spree_cm_commissioner/vattanac_bank_initiator.rb +116 -0
- data/app/models/spree_cm_commissioner/order_decorator.rb +1 -1
- data/app/models/spree_cm_commissioner/role_decorator.rb +9 -3
- data/app/models/spree_cm_commissioner/taxon_decorator.rb +0 -1
- data/app/models/spree_cm_commissioner/trip.rb +7 -0
- data/app/models/spree_cm_commissioner/trip_connection.rb +10 -5
- data/app/models/spree_cm_commissioner/user_identity_provider.rb +1 -1
- data/app/models/spree_cm_commissioner/variant_decorator.rb +19 -2
- data/app/models/spree_cm_commissioner/variant_options.rb +14 -0
- data/app/overrides/spree/admin/users/_form/roles_fields.html.erb.deface +2 -0
- data/app/queries/spree_cm_commissioner/tickets_searcher_query.rb +21 -0
- data/app/queries/spree_cm_commissioner/trip_query.rb +145 -0
- data/app/serializers/spree/v2/tenant/id_card_serializer.rb +12 -0
- data/app/serializers/spree/v2/tenant/reset_password_serializer.rb +8 -0
- data/app/serializers/spree/v2/tenant/ticket_serializer.rb +27 -0
- data/app/serializers/spree/v2/tenant/user_contact_serializer.rb +11 -0
- data/app/services/spree_cm_commissioner/aes_encryption_service.rb +52 -0
- data/app/services/spree_cm_commissioner/role_permissions_constructor.rb +42 -0
- data/app/services/spree_cm_commissioner/role_permissions_loader.rb +57 -0
- data/app/services/spree_cm_commissioner/rsa_service.rb +27 -0
- data/app/services/spree_cm_commissioner/user_authenticator.rb +4 -0
- data/app/views/spree/admin/user_events/_events.html.erb +1 -1
- data/app/views/spree/admin/user_events/index.html.erb +7 -3
- data/config/routes.rb +9 -2
- data/db/migrate/20250328072717_add_description_to_spree_roles.rb +1 -1
- data/db/migrate/20250328072841_add_vendor_id_to_spree_roles.rb +1 -1
- data/db/migrate/20250403025619_add_presentation_to_spree_role.rb +5 -0
- data/db/migrate/20250403042255_add_unique_constraint_to_name_in_spree_roles.rb +7 -0
- data/db/migrate/20250407092556_add_variant_id_to_cm_trips.rb +7 -0
- data/lib/spree_cm_commissioner/test_helper/factories/product_factory.rb +9 -0
- data/lib/spree_cm_commissioner/test_helper/factories/role_permission_factory.rb +11 -0
- data/lib/spree_cm_commissioner/test_helper/factories/trip_factory.rb +6 -0
- data/lib/spree_cm_commissioner/test_helper/factories/user_identity_provider_factory.rb +4 -0
- data/lib/spree_cm_commissioner/trip_query_result.rb +14 -0
- data/lib/spree_cm_commissioner/user_session_jwt_token.rb +5 -0
- data/lib/spree_cm_commissioner/version.rb +1 -1
- data/lib/spree_cm_commissioner.rb +2 -0
- data/spree_cm_commissioner.gemspec +1 -0
- metadata +44 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6aa3cfdf9976b9d40fa5c53533193d93ea1503b79b288c926e5efe8f371db0b5
|
4
|
+
data.tar.gz: f77a64037130b4d871c346534131a3fa664f5fb7cb344834b730e9a1c02e2177
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7296a57cfe2b468ff16941f59f8fe744157721df84d05532ee618a4736b5db2c7802975145a607d825b42ea009d460b114479a81e8009c2c5b1a359a7d576902
|
7
|
+
data.tar.gz: 6c8a2a04159368014afdbd2203281f647f2b054281ef1044817967d0e108517e9ddccc0fa04f42aec25ba6af9e24eef7b00f4c253a5d301cb53f145307ebd8fa
|
data/.env.example
CHANGED
data/Gemfile.lock
CHANGED
@@ -34,7 +34,7 @@ GIT
|
|
34
34
|
PATH
|
35
35
|
remote: .
|
36
36
|
specs:
|
37
|
-
spree_cm_commissioner (1.
|
37
|
+
spree_cm_commissioner (1.9.0)
|
38
38
|
activerecord-multi-tenant
|
39
39
|
activerecord_json_validator (~> 2.1, >= 2.1.3)
|
40
40
|
aws-sdk-cloudfront
|
@@ -46,6 +46,7 @@ PATH
|
|
46
46
|
dry-validation (~> 1.10)
|
47
47
|
elasticsearch (~> 8.5)
|
48
48
|
exception_notification
|
49
|
+
firebase-admin-sdk (~> 0.3.1)
|
49
50
|
font-awesome-sass (~> 6.4.0)
|
50
51
|
google-cloud-firestore
|
51
52
|
google-cloud-recaptcha_enterprise
|
@@ -269,6 +270,7 @@ GEM
|
|
269
270
|
database_cleaner-core (~> 2.0.0)
|
270
271
|
database_cleaner-core (2.0.1)
|
271
272
|
date (3.3.3)
|
273
|
+
declarative (0.0.20)
|
272
274
|
deface (1.9.0)
|
273
275
|
actionview (>= 5.2)
|
274
276
|
nokogiri (>= 1.6)
|
@@ -370,6 +372,11 @@ GEM
|
|
370
372
|
rake
|
371
373
|
fiber-annotation (0.2.0)
|
372
374
|
fiber-local (1.0.0)
|
375
|
+
firebase-admin-sdk (0.3.1)
|
376
|
+
faraday (> 1, < 3)
|
377
|
+
google-apis-fcm_v1 (>= 0.19.0, < 1.0)
|
378
|
+
googleauth (> 0.16, < 2.0)
|
379
|
+
jwt (>= 1.5, < 3.0)
|
373
380
|
flag-icons-rails (3.4.6.1)
|
374
381
|
sass-rails
|
375
382
|
flatpickr (4.6.13.0)
|
@@ -398,6 +405,16 @@ GEM
|
|
398
405
|
globalid (1.2.1)
|
399
406
|
activesupport (>= 6.1)
|
400
407
|
glyphicons (1.0.2)
|
408
|
+
google-apis-core (0.11.3)
|
409
|
+
addressable (~> 2.5, >= 2.5.1)
|
410
|
+
googleauth (>= 0.16.2, < 2.a)
|
411
|
+
httpclient (>= 2.8.1, < 3.a)
|
412
|
+
mini_mime (~> 1.0)
|
413
|
+
representable (~> 3.0)
|
414
|
+
retriable (>= 2.0, < 4.a)
|
415
|
+
rexml
|
416
|
+
google-apis-fcm_v1 (0.23.0)
|
417
|
+
google-apis-core (>= 0.11.0, < 2.a)
|
401
418
|
google-cloud-core (1.6.0)
|
402
419
|
google-cloud-env (~> 1.0)
|
403
420
|
google-cloud-errors (~> 1.0)
|
@@ -646,9 +663,14 @@ GEM
|
|
646
663
|
redis-client (0.17.0)
|
647
664
|
connection_pool
|
648
665
|
regexp_parser (2.8.2)
|
666
|
+
representable (3.2.0)
|
667
|
+
declarative (< 0.1.0)
|
668
|
+
trailblazer-option (>= 0.1.1, < 0.2.0)
|
669
|
+
uber (< 0.2.0)
|
649
670
|
responders (3.1.1)
|
650
671
|
actionpack (>= 5.2)
|
651
672
|
railties (>= 5.2)
|
673
|
+
retriable (3.1.2)
|
652
674
|
rexml (3.2.6)
|
653
675
|
rqrcode (2.2.0)
|
654
676
|
chunky_png (~> 1.0)
|
@@ -858,6 +880,7 @@ GEM
|
|
858
880
|
tinymce-rails (5.10.7.1)
|
859
881
|
railties (>= 3.1.1)
|
860
882
|
traces (0.11.1)
|
883
|
+
trailblazer-option (0.1.2)
|
861
884
|
turbo-rails (1.5.0)
|
862
885
|
actionpack (>= 6.0.0)
|
863
886
|
activejob (>= 6.0.0)
|
@@ -868,6 +891,7 @@ GEM
|
|
868
891
|
nokogiri (>= 1.6, < 2.0)
|
869
892
|
tzinfo (2.0.6)
|
870
893
|
concurrent-ruby (~> 1.0)
|
894
|
+
uber (0.1.0)
|
871
895
|
unf (0.1.4)
|
872
896
|
unf_ext
|
873
897
|
unf_ext (0.0.8.2)
|
@@ -2,22 +2,20 @@ module Spree
|
|
2
2
|
module Admin
|
3
3
|
class UserEventsController < Spree::Admin::ResourceController
|
4
4
|
before_action :load_parents, if: -> { params[:taxon_id].present? }
|
5
|
+
before_action :load_user, if: -> { params[:user_id].present? }
|
5
6
|
|
6
7
|
# override
|
7
8
|
def index
|
8
9
|
if params[:taxon_id].present?
|
9
10
|
@user_events = @taxon.user_events
|
10
|
-
|
11
|
-
@user = Spree::User.find(params[:user_id])
|
11
|
+
elsif params[:user_id].present?
|
12
12
|
@user_events = @user.user_events
|
13
|
+
else
|
14
|
+
flash[:error] = 'Invalid taxon or user' # rubocop:disable Rails/I18nLocaleTexts
|
15
|
+
redirect_back(fallback_location: collection_url)
|
13
16
|
end
|
14
17
|
end
|
15
18
|
|
16
|
-
# override
|
17
|
-
def new
|
18
|
-
@user = spree_current_user
|
19
|
-
end
|
20
|
-
|
21
19
|
# override
|
22
20
|
def create
|
23
21
|
user_event = SpreeCmCommissioner::UserEvent.new(permitted_resource_params)
|
@@ -32,6 +30,10 @@ module Spree
|
|
32
30
|
|
33
31
|
private
|
34
32
|
|
33
|
+
def load_user
|
34
|
+
@user = Spree::User.find(params[:user_id])
|
35
|
+
end
|
36
|
+
|
35
37
|
def load_parents
|
36
38
|
@taxon = Spree::Taxon.find(params[:taxon_id])
|
37
39
|
@taxonomy = @taxon.taxonomy
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Spree
|
2
|
+
module Api
|
3
|
+
module V2
|
4
|
+
module Storefront
|
5
|
+
class VattanacBanksController < Spree::Api::V2::BaseController
|
6
|
+
def create
|
7
|
+
result = SpreeCmCommissioner::VattanacBankInitiator.call(params: params)
|
8
|
+
|
9
|
+
if result.success?
|
10
|
+
render json: {
|
11
|
+
message: 'SUCCESS',
|
12
|
+
data: result.data
|
13
|
+
}
|
14
|
+
else
|
15
|
+
render json: {
|
16
|
+
message: 'FAILED',
|
17
|
+
error: result.error
|
18
|
+
}, status: result.status || :unprocessable_entity
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Spree
|
2
|
+
module Api
|
3
|
+
module V2
|
4
|
+
module Tenant
|
5
|
+
class ChangePasswordsController < BaseController
|
6
|
+
before_action :require_spree_current_user
|
7
|
+
|
8
|
+
def update
|
9
|
+
context = SpreeCmCommissioner::PasswordChanger.call(change_password_params)
|
10
|
+
|
11
|
+
if context.success?
|
12
|
+
render_serialized_payload { serialize_resource(context.user) }
|
13
|
+
else
|
14
|
+
render_error_payload(context.message)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def resource_serializer
|
19
|
+
Spree::V2::Tenant::UserSerializer
|
20
|
+
end
|
21
|
+
|
22
|
+
def change_password_params
|
23
|
+
result = params.permit(:current_password, :password, :password_confirmation)
|
24
|
+
result[:user] = spree_current_user
|
25
|
+
|
26
|
+
result.to_h
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Spree
|
2
|
+
module Api
|
3
|
+
module V2
|
4
|
+
module Tenant
|
5
|
+
class IdCardsController < BaseController
|
6
|
+
def create
|
7
|
+
context = SpreeCmCommissioner::GuestIdCardManager.call(
|
8
|
+
card_type: id_card_params[:card_type],
|
9
|
+
front_image_url: id_card_params[:front_image_url],
|
10
|
+
back_image_url: id_card_params[:back_image_url],
|
11
|
+
guest_id: id_card_params[:guest_id]
|
12
|
+
)
|
13
|
+
|
14
|
+
if context.success?
|
15
|
+
render_serialized_payload { serialize_resource(context.result) }
|
16
|
+
else
|
17
|
+
render_error_payload(context.message)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def update
|
22
|
+
context = SpreeCmCommissioner::GuestIdCardManager.call(
|
23
|
+
card_type: id_card_params[:card_type],
|
24
|
+
front_image_url: id_card_params[:front_image_url],
|
25
|
+
back_image_url: id_card_params[:back_image_url],
|
26
|
+
guest_id: id_card_params[:guest_id]
|
27
|
+
)
|
28
|
+
|
29
|
+
if context.success?
|
30
|
+
render_serialized_payload { serialize_resource(context.result) }
|
31
|
+
else
|
32
|
+
render_error_payload(context.message)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def destroy
|
37
|
+
id_card = SpreeCmCommissioner::IdCard.find(params[:id])
|
38
|
+
|
39
|
+
if id_card.destroy
|
40
|
+
head :no_content
|
41
|
+
else
|
42
|
+
render_error_payload('Failed to destroy ID card', 400)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def id_card_params
|
49
|
+
params.permit(:card_type, :front_image_url, :back_image_url, :guest_id)
|
50
|
+
end
|
51
|
+
|
52
|
+
def model_class
|
53
|
+
SpreeCmCommissioner::IdCard
|
54
|
+
end
|
55
|
+
|
56
|
+
def resource_serializer
|
57
|
+
Spree::V2::Tenant::IdCardSerializer
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Spree
|
2
|
+
module Api
|
3
|
+
module V2
|
4
|
+
module Tenant
|
5
|
+
class ResetPasswordsController < BaseController
|
6
|
+
def update
|
7
|
+
context = SpreeCmCommissioner::UserForgottenPasswordUpdater.call(update_params)
|
8
|
+
|
9
|
+
if context.success?
|
10
|
+
render_serialized_payload { serialize_resource(context.user) }
|
11
|
+
else
|
12
|
+
render_error_payload(context.message)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def resource_serializer
|
17
|
+
Spree::V2::Tenant::ResetPasswordSerializer
|
18
|
+
end
|
19
|
+
|
20
|
+
def update_params
|
21
|
+
params.permit(
|
22
|
+
:email,
|
23
|
+
:phone_number,
|
24
|
+
:country_code,
|
25
|
+
:pin_code,
|
26
|
+
:pin_code_token,
|
27
|
+
:password,
|
28
|
+
:password_confirmation
|
29
|
+
)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Spree
|
2
|
+
module Api
|
3
|
+
module V2
|
4
|
+
module Tenant
|
5
|
+
class TicketsController < BaseController
|
6
|
+
def index
|
7
|
+
render_serialized_payload do
|
8
|
+
serialize_collection(paginated_collection)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def collection
|
13
|
+
SpreeCmCommissioner::TicketsSearcherQuery.new(params, MultiTenant.current_tenant_id).call
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def collection_serializer
|
19
|
+
Spree::V2::Tenant::TicketSerializer
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Spree
|
2
|
+
module Api
|
3
|
+
module V2
|
4
|
+
module Tenant
|
5
|
+
class UserContactsController < BaseController
|
6
|
+
def update
|
7
|
+
options = user_with_pin_code_params
|
8
|
+
|
9
|
+
generator_context = ::SpreeCmCommissioner::UserContactUpdater.call(options)
|
10
|
+
|
11
|
+
if generator_context.success?
|
12
|
+
render_serialized_payload { serialize_resource(generator_context.user) }
|
13
|
+
else
|
14
|
+
render_error_payload(generator_context.message)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def user_with_pin_code_params
|
21
|
+
results = params.permit(:pin_code, :pin_code_token, :email, :phone_number)
|
22
|
+
results[:user] = spree_current_user
|
23
|
+
results.to_h
|
24
|
+
end
|
25
|
+
|
26
|
+
def resource_serializer
|
27
|
+
Spree::V2::Tenant::UserContactSerializer
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
module Admin
|
3
|
+
module RolesControllerDecorator
|
4
|
+
def index
|
5
|
+
@roles = Spree::Role.non_vendor.page(params[:page])
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
unless Spree::Admin::RolesController.ancestors.include?(SpreeCmCommissioner::Admin::RolesControllerDecorator)
|
12
|
+
Spree::Admin::RolesController.prepend(SpreeCmCommissioner::Admin::RolesControllerDecorator)
|
13
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'firebase-admin-sdk'
|
2
|
+
|
3
|
+
module SpreeCmCommissioner
|
4
|
+
class FirebaseEmailFetcher < BaseInteractor
|
5
|
+
delegate :user_id, to: :context
|
6
|
+
|
7
|
+
def call
|
8
|
+
manager = initialize_firebase_manager
|
9
|
+
user = manager.get_user_by(uid: context.user_id)
|
10
|
+
|
11
|
+
context.email = user.provider_data.first&.email
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def service_account
|
17
|
+
@service_account ||= Rails.application.credentials.cloud_firestore_service_account
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize_firebase_manager
|
21
|
+
@credentials ||= Firebase::Admin::Credentials.from_json(service_account.to_json)
|
22
|
+
@manager ||= Firebase::Admin::Auth::UserManager.new(service_account[:project_id], @credentials)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -85,8 +85,9 @@ module SpreeCmCommissioner
|
|
85
85
|
return nil if claim.nil?
|
86
86
|
|
87
87
|
provider_name = claim['firebase']['sign_in_provider']
|
88
|
+
user_id = claim['user_id']
|
88
89
|
sub = claim['firebase']['identities'][provider_name].first
|
89
|
-
email = claim['email']
|
90
|
+
email = claim['email'] || get_user_email(user_id)
|
90
91
|
name = claim['name']
|
91
92
|
|
92
93
|
{
|
@@ -97,6 +98,16 @@ module SpreeCmCommissioner
|
|
97
98
|
}
|
98
99
|
end
|
99
100
|
|
101
|
+
def get_user_email(user_id)
|
102
|
+
return nil if user_id.blank?
|
103
|
+
|
104
|
+
firebase_context = FirebaseEmailFetcher.call(user_id: user_id)
|
105
|
+
|
106
|
+
return unless firebase_context.success?
|
107
|
+
|
108
|
+
firebase_context.email
|
109
|
+
end
|
110
|
+
|
100
111
|
delegate :id_token, to: :context
|
101
112
|
end
|
102
113
|
end
|
@@ -7,6 +7,9 @@ module SpreeCmCommissioner
|
|
7
7
|
else
|
8
8
|
checker.user
|
9
9
|
end
|
10
|
+
|
11
|
+
update_user_email if context.user.email.blank?
|
12
|
+
|
10
13
|
context.fail!(message: 'account_temporarily_deleted') if context.user.soft_deleted?
|
11
14
|
end
|
12
15
|
|
@@ -15,6 +18,14 @@ module SpreeCmCommissioner
|
|
15
18
|
register_context.user
|
16
19
|
end
|
17
20
|
|
21
|
+
def update_user_email
|
22
|
+
firebase_context = FirebaseIdTokenProvider.call(id_token: context.id_token)
|
23
|
+
return unless firebase_context.success?
|
24
|
+
|
25
|
+
email = firebase_context.provider[:email]
|
26
|
+
context.user.update(email: email) if email.present?
|
27
|
+
end
|
28
|
+
|
18
29
|
def checker
|
19
30
|
@checker ||= SpreeCmCommissioner::UserIdTokenChecker.call(id_token: context.id_token)
|
20
31
|
@checker
|
@@ -6,7 +6,7 @@ module SpreeCmCommissioner
|
|
6
6
|
|
7
7
|
if firebase_context.success?
|
8
8
|
ActiveRecord::Base.transaction do
|
9
|
-
register_user!(firebase_context.provider[:name])
|
9
|
+
register_user!(firebase_context.provider[:name], firebase_context.provider[:email])
|
10
10
|
link_user_account!(firebase_context.provider)
|
11
11
|
end
|
12
12
|
else
|
@@ -14,8 +14,8 @@ module SpreeCmCommissioner
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
def register_user!(name)
|
18
|
-
user = Spree.user_class.new(password: SecureRandom.base64(16), **name_attributes(name))
|
17
|
+
def register_user!(name, email)
|
18
|
+
user = Spree.user_class.new(password: SecureRandom.base64(16), email: email, **name_attributes(name))
|
19
19
|
if user.save(validate: false)
|
20
20
|
context.user = user
|
21
21
|
else
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
class UserVattanacBankWebAppAuthenticator < BaseInteractor
|
3
|
+
delegate :session_id, to: :context
|
4
|
+
|
5
|
+
def call
|
6
|
+
return context.fail!(message: 'Invalid token') unless payload
|
7
|
+
return context.fail!(message: 'User not found') unless user
|
8
|
+
|
9
|
+
verify_token!
|
10
|
+
|
11
|
+
context.user = user
|
12
|
+
rescue JWT::DecodeError => e
|
13
|
+
context.fail!(message: "Decode error: #{e.message}")
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def payload
|
19
|
+
@payload ||= SpreeCmCommissioner::UserSessionJwtToken.decode(session_id)
|
20
|
+
end
|
21
|
+
|
22
|
+
def user
|
23
|
+
@user ||= Spree::User.find_by(id: payload['user_id']) if payload
|
24
|
+
end
|
25
|
+
|
26
|
+
def verify_token!
|
27
|
+
SpreeCmCommissioner::UserSessionJwtToken.decode(session_id, user.secure_token)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
class VattanacBankInitiator
|
3
|
+
include Interactor
|
4
|
+
|
5
|
+
def call
|
6
|
+
extract_encrypted_data_and_signature
|
7
|
+
verify_signature
|
8
|
+
decrypt_payload
|
9
|
+
find_or_create_user
|
10
|
+
construct_data
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def extract_encrypted_data_and_signature
|
16
|
+
data_param = context.params[:data]
|
17
|
+
context.fail!(message: 'Invalid payload format', status: :bad_request) if data_param.blank?
|
18
|
+
|
19
|
+
parts = data_param.to_s.split('.', 2)
|
20
|
+
context.fail!(message: 'Invalid payload format', status: :bad_request) unless parts.size == 2
|
21
|
+
|
22
|
+
encrypted_data, signature = parts
|
23
|
+
context.encrypted_data = encrypted_data
|
24
|
+
context.signature = signature
|
25
|
+
end
|
26
|
+
|
27
|
+
def verify_signature
|
28
|
+
public_key = ENV['VATTANAC_PUBLIC_KEY'].presence || Rails.application.credentials.vattanac.public_key
|
29
|
+
|
30
|
+
rsa_service = SpreeCmCommissioner::RsaService.new(
|
31
|
+
public_key: public_key
|
32
|
+
)
|
33
|
+
|
34
|
+
return if rsa_service.verify(context.encrypted_data, context.signature)
|
35
|
+
|
36
|
+
context.fail!(message: 'Invalid signature', status: :unauthorized)
|
37
|
+
end
|
38
|
+
|
39
|
+
def decrypt_payload
|
40
|
+
aes_key = ENV['VATTANAC_AES_SECRET_KEY'].presence || Rails.application.credentials.vattanac.aes_secret_key
|
41
|
+
|
42
|
+
context.fail!(message: 'Invalid AES key length', status: :unprocessable_entity) unless aes_key
|
43
|
+
|
44
|
+
begin
|
45
|
+
decrypted_json = SpreeCmCommissioner::AesEncryptionService.decrypt(context.encrypted_data, aes_key)
|
46
|
+
context.user_data = JSON.parse(decrypted_json)
|
47
|
+
rescue StandardError => e
|
48
|
+
context.fail!(message: 'Decryption failed', error: e.message, status: :unprocessable_entity)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def find_or_create_user
|
53
|
+
find_user_by_identity || find_existing_user || create_new_user
|
54
|
+
end
|
55
|
+
|
56
|
+
def find_user_by_identity
|
57
|
+
user_data = context.user_data
|
58
|
+
|
59
|
+
identity = SpreeCmCommissioner::UserIdentityProvider.vattanac_bank
|
60
|
+
.find_or_initialize_by(sub: user_data['id'])
|
61
|
+
|
62
|
+
if identity.persisted?
|
63
|
+
context.user = identity.user
|
64
|
+
else
|
65
|
+
context.identity = identity
|
66
|
+
end
|
67
|
+
|
68
|
+
context.user
|
69
|
+
end
|
70
|
+
|
71
|
+
def find_existing_user
|
72
|
+
user_data = context.user_data
|
73
|
+
|
74
|
+
context.user = Spree::User.find_by(
|
75
|
+
'email = ? OR phone_number = ?', user_data['email'], user_data['phoneNum']
|
76
|
+
)
|
77
|
+
end
|
78
|
+
|
79
|
+
def create_new_user
|
80
|
+
user_data = context.user_data
|
81
|
+
full_name = "#{user_data['firstName']} #{user_data['lastName']}"
|
82
|
+
identity = context.identity
|
83
|
+
|
84
|
+
identity.name = full_name
|
85
|
+
|
86
|
+
context.user = Spree::User.new(
|
87
|
+
first_name: user_data['firstName'],
|
88
|
+
last_name: user_data['lastName'],
|
89
|
+
email: user_data['email'],
|
90
|
+
phone_number: user_data['phoneNum'],
|
91
|
+
password: SecureRandom.base64(16),
|
92
|
+
user_identity_providers: [identity]
|
93
|
+
)
|
94
|
+
|
95
|
+
return if context.user.save
|
96
|
+
|
97
|
+
context.fail!(message: "User creation failed: #{context.user.errors.full_messages.join(', ')}")
|
98
|
+
end
|
99
|
+
|
100
|
+
def construct_data
|
101
|
+
user = context.user
|
102
|
+
context.data = {
|
103
|
+
sessionId: session_id,
|
104
|
+
name: user.full_name,
|
105
|
+
phone: user.phone_number,
|
106
|
+
email: user.email,
|
107
|
+
webUrl: "#{Spree::Store.default.formatted_url}/vattanac_bank_web_app?session_id=#{session_id}"
|
108
|
+
}
|
109
|
+
end
|
110
|
+
|
111
|
+
def session_id
|
112
|
+
payload = { user_id: context.user.id }
|
113
|
+
SpreeCmCommissioner::UserSessionJwtToken.encode(payload, context.user.reload.secure_token)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -46,7 +46,7 @@ module SpreeCmCommissioner
|
|
46
46
|
|
47
47
|
base.delegate :customer, to: :user, allow_nil: true
|
48
48
|
|
49
|
-
base.whitelisted_ransackable_associations |= %w[customer taxon payments invoice]
|
49
|
+
base.whitelisted_ransackable_associations |= %w[customer taxon payments guests invoice]
|
50
50
|
base.whitelisted_ransackable_attributes |= %w[intel_phone_number phone_number email number state]
|
51
51
|
|
52
52
|
def base.search_by_qr_data!(data)
|
@@ -10,10 +10,16 @@ module SpreeCmCommissioner
|
|
10
10
|
|
11
11
|
base.accepts_nested_attributes_for :role_permissions, allow_destroy: true
|
12
12
|
|
13
|
-
base.
|
14
|
-
base._validate_callbacks.each { |c| c.filter.attributes.delete(:name) if c.filter.respond_to?(:attributes) }
|
13
|
+
base.before_validation :generate_unique_name, if: -> { vendor_id.present? }
|
15
14
|
|
16
|
-
base.validates :
|
15
|
+
base.validates :presentation, uniqueness: { scope: :vendor_id }, presence: true, if: -> { vendor_id.present? }
|
16
|
+
end
|
17
|
+
|
18
|
+
def generate_unique_name
|
19
|
+
return if name.present?
|
20
|
+
return if presentation.blank?
|
21
|
+
|
22
|
+
self.name = "#{vendor.slug}-#{presentation.downcase.parameterize(separator: '-')}"
|
17
23
|
end
|
18
24
|
end
|
19
25
|
end
|
@@ -7,7 +7,6 @@ module SpreeCmCommissioner
|
|
7
7
|
|
8
8
|
base.preference :background_color, :string
|
9
9
|
base.preference :foreground_color, :string
|
10
|
-
base.preference :reports, :array, default: []
|
11
10
|
|
12
11
|
base.has_many :taxon_vendors, class_name: 'SpreeCmCommissioner::TaxonVendor'
|
13
12
|
base.has_many :vendors, through: :taxon_vendors
|
@@ -4,6 +4,7 @@ module SpreeCmCommissioner
|
|
4
4
|
attr_accessor :hours, :minutes, :seconds
|
5
5
|
|
6
6
|
before_validation :convert_duration_to_seconds
|
7
|
+
belongs_to :variant, class_name: 'Spree::Variant'
|
7
8
|
|
8
9
|
belongs_to :route, class_name: 'Spree::Product'
|
9
10
|
belongs_to :vehicle, class_name: 'SpreeCmCommissioner::Vehicle'
|
@@ -39,6 +40,12 @@ module SpreeCmCommissioner
|
|
39
40
|
{ hours: hours, minutes: minutes, seconds: seconds }
|
40
41
|
end
|
41
42
|
|
43
|
+
def arrival_time
|
44
|
+
return nil if departure_time.nil? || duration.nil?
|
45
|
+
|
46
|
+
departure_time + duration.seconds
|
47
|
+
end
|
48
|
+
|
42
49
|
private
|
43
50
|
|
44
51
|
def origin_and_destination_cannot_be_the_same
|