spree_cm_commissioner 1.19.0 ā 1.21.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/Gemfile.lock +5 -1
- data/app/controllers/spree/api/v2/organizer/invite_guests_controller.rb +1 -1
- data/app/factory/spree_cm_commissioner/invite_guest_claimed_telegram_message_factory.rb +37 -84
- data/app/interactors/spree_cm_commissioner/pin_code_sender.rb +0 -1
- data/app/interactors/spree_cm_commissioner/sms.rb +1 -1
- data/app/interactors/spree_cm_commissioner/user_id_token_authenticator.rb +7 -3
- data/app/interactors/spree_cm_commissioner/user_id_token_checker.rb +11 -3
- data/app/interactors/spree_cm_commissioner/user_identity_checker.rb +12 -6
- data/app/interactors/spree_cm_commissioner/user_registration_with_id_token.rb +7 -1
- data/app/jobs/spree_cm_commissioner/sms_pin_code_job.rb +1 -1
- data/app/models/spree_cm_commissioner/user_identity_provider.rb +26 -4
- data/app/serializers/spree/v2/tenant/user_serializer.rb +1 -0
- data/app/services/spree_cm_commissioner/user_authenticator.rb +1 -1
- data/db/migrate/20250715103333_remove_indexes_from_cm_user_identity_providers.rb +13 -0
- data/lib/spree_cm_commissioner/test_helper/factories/user_identity_provider_factory.rb +1 -1
- data/lib/spree_cm_commissioner/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz: '
|
3
|
+
metadata.gz: 7043a8acbe6da011c50dcf6d5f9c4fa4c09d44f0c273c7d8c5f35e9da6430628
|
4
|
+
data.tar.gz: '049dc2649fbb41b2e43945741baf9c7815ddc11b38a83cec8157c2eac5ed8431'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 17233d10bfd72385a100faf262a0c236017970a4429e33098a7992dd64c217ff02c06168931f3472ef8e5a3245786df65c72f0123f2cacca58223b66c5ca6a3f
|
7
|
+
data.tar.gz: 68bac4de8bf2b866b75ccbcfef5c53b50786427d7cbe87e4d17fa0b284186cfbd08d71fbe8c5fe496dfce6b1e6340a6bb0be4cbac00103388c7545397ad417d1
|
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.21.0)
|
38
38
|
activerecord-multi-tenant
|
39
39
|
activerecord_json_validator (~> 2.1, >= 2.1.3)
|
40
40
|
aws-sdk-cloudfront
|
@@ -572,6 +572,10 @@ GEM
|
|
572
572
|
nokogiri (1.15.4)
|
573
573
|
mini_portile2 (~> 2.8.2)
|
574
574
|
racc (~> 1.4)
|
575
|
+
nokogiri (1.15.4-x86_64-darwin)
|
576
|
+
racc (~> 1.4)
|
577
|
+
nokogiri (1.15.4-x86_64-linux)
|
578
|
+
racc (~> 1.4)
|
575
579
|
noticed (1.6.3)
|
576
580
|
http (>= 4.0.0)
|
577
581
|
rails (>= 5.2.0)
|
@@ -20,7 +20,7 @@ module Spree
|
|
20
20
|
|
21
21
|
if guest.save
|
22
22
|
@invite_guest.update(claimed_status: :claimed) if @line_item.guests.count == @invite_guest.quantity
|
23
|
-
send_guest_claimed_invitation_telegram_alert_to_vendor(guest)
|
23
|
+
send_guest_claimed_invitation_telegram_alert_to_vendor(guest) if guest.event.vendor.preferred_telegram_chat_id.present?
|
24
24
|
|
25
25
|
render json: SpreeCmCommissioner::V2::Storefront::GuestSerializer.new(guest.reload).serializable_hash
|
26
26
|
else
|
@@ -1,26 +1,17 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
#
|
4
|
-
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
|
9
|
-
# <b>
|
10
|
-
# <i>š Distance: 5km, T-shirt:
|
11
|
-
# <i>šļø
|
12
|
-
|
13
|
-
#
|
14
|
-
#
|
15
|
-
# <b>5km Running Ticket</b>
|
16
|
-
# <i>š Distance: 5km, T-shirt: S</i>
|
17
|
-
# <i>šļø Nov 15, 2023 -> Nov 17, 2023</i>
|
18
|
-
# <i>šŖ Temple Run with Sai</i>
|
19
|
-
#
|
20
|
-
# <b>š Claimed By</b>
|
21
|
-
# Name: Vaneath Awesome
|
22
|
-
# Tel: <code>+85570760548</code>
|
23
|
-
# Email: <code>admin_dev@cm.com</code>
|
1
|
+
# <p>š£ --- <b>[NEW GUEST CLAIMED INVITATION]</b> ---</p>
|
2
|
+
|
3
|
+
# <p>⨠<b>Ticket Successfully Claimed!</b> āØ</p>
|
4
|
+
|
5
|
+
# <p><b>š Claimed By</b><br>
|
6
|
+
# Name: Orng SreyMoch<br>
|
7
|
+
# Tel: <code>0966827830</code></p>
|
8
|
+
|
9
|
+
# <p><b>Run Ticket + 2 way bus ticket + Tent</b><br>
|
10
|
+
# <i>š Distance: 5km, Tent: tent (1 people), and T-shirt: S</i><br>
|
11
|
+
# <i>šļø May 30, 2025 -> Jun 30, 2025</i></p>
|
12
|
+
|
13
|
+
# <p><b>š Order Number:</b><br>
|
14
|
+
# <code>R172627517</code></p>
|
24
15
|
|
25
16
|
module SpreeCmCommissioner
|
26
17
|
class InviteGuestClaimedTelegramMessageFactory < TelegramMessageFactory
|
@@ -44,77 +35,39 @@ module SpreeCmCommissioner
|
|
44
35
|
# override
|
45
36
|
def body
|
46
37
|
text = []
|
47
|
-
text <<
|
48
|
-
text <<
|
49
|
-
text <<
|
50
|
-
text.
|
38
|
+
text << '<p>š£ --- <b>[NEW GUEST CLAIMED INVITATION]</b> ---</p>'
|
39
|
+
text << '<p>⨠<b>Ticket Successfully Claimed!</b> āØ</p>'
|
40
|
+
text << '<p><b>š Claimed By</b><br>'
|
41
|
+
text << "Name: #{guest.first_name} #{guest.last_name}<br>"
|
42
|
+
text << "Tel: <code>#{guest.phone_number}</code></p>"
|
43
|
+
|
44
|
+
selected_line_items.each do |item|
|
45
|
+
text << line_item_block(item)
|
46
|
+
end
|
47
|
+
|
48
|
+
text << "<p><b>š Order Number:</b><br><code>#{order.number}</code></p>"
|
49
|
+
|
50
|
+
text.join("\n")
|
51
51
|
end
|
52
52
|
|
53
|
-
def
|
54
|
-
|
53
|
+
def line_item_block(item)
|
54
|
+
parts = []
|
55
|
+
parts << "<p><b>#{item.product.name}</b><br>"
|
55
56
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
text << italic(pretty_date_for(line_item)) if pretty_date_for(line_item).present?
|
60
|
-
text << italic("šŖ #{line_item.vendor.name}") if line_item.vendor&.name.present? && vendor.blank?
|
57
|
+
details = []
|
58
|
+
details << "š #{item.options_text}" if item.options_text.present?
|
59
|
+
details << pretty_date_for(item) if item.date_present?
|
61
60
|
|
62
|
-
|
61
|
+
parts << details.map { |d| "<i>#{d}</i><br>" }.join
|
62
|
+
parts << '</p>'
|
63
|
+
parts.join("\n")
|
63
64
|
end
|
64
65
|
|
65
66
|
def pretty_date_for(line_item)
|
66
|
-
return nil unless line_item.date_present?
|
67
|
-
|
68
67
|
from_date = pretty_date(line_item.from_date)
|
69
68
|
to_date = pretty_date(line_item.to_date)
|
70
69
|
|
71
|
-
|
72
|
-
"šļø #{from_date}"
|
73
|
-
else
|
74
|
-
"šļø #{from_date} -> #{to_date}"
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
# override
|
79
|
-
def footer
|
80
|
-
text = []
|
81
|
-
|
82
|
-
text << bold('š Claimed By')
|
83
|
-
text << "Name: #{guest.first_name} #{guest.last_name}" if guest.first_name.present? || guest.last_name.present?
|
84
|
-
text << "Tel: #{inline_code(guest.intel_phone_number)}" if guest.intel_phone_number.present?
|
85
|
-
|
86
|
-
if show_details_link && order.guests.any?
|
87
|
-
text << ''
|
88
|
-
text << 'View Tickets:'
|
89
|
-
text += generate_guests_links(order.guests)
|
90
|
-
end
|
91
|
-
|
92
|
-
text.compact.join("\n")
|
93
|
-
end
|
94
|
-
|
95
|
-
# Result:
|
96
|
-
# | No. A24 | No. A24 |
|
97
|
-
# | No. A24 | No. A24 |
|
98
|
-
# | No. A24 | No. A24 |
|
99
|
-
# | No. A24 | No. A24 |
|
100
|
-
# | No. A24 | No. A24 |
|
101
|
-
# | No. A24 |
|
102
|
-
def generate_guests_links(guests, guests_per_row = 2)
|
103
|
-
rows = (guests.size.to_f / guests_per_row).ceil
|
104
|
-
formatted_rows = []
|
105
|
-
|
106
|
-
rows.times do |i|
|
107
|
-
row_guests = guests.slice(i * guests_per_row, guests_per_row)
|
108
|
-
formatted_row = row_guests.map do |guest|
|
109
|
-
button_label = guest.seat_number.present? ? "No. #{guest.seat_number}" : "No. #{guest.formatted_bib_number || 'N/A'}"
|
110
|
-
link = Rails.application.routes.url_helpers.guest_cards_url(guest.token)
|
111
|
-
"| <a href='#{link}'>#{button_label}</a>"
|
112
|
-
end.join(' ')
|
113
|
-
|
114
|
-
formatted_rows << ("#{formatted_row} |")
|
115
|
-
end
|
116
|
-
|
117
|
-
formatted_rows
|
70
|
+
from_date == to_date ? "šļø #{from_date}" : "šļø #{from_date} -> #{to_date}"
|
118
71
|
end
|
119
72
|
end
|
120
73
|
end
|
@@ -42,7 +42,7 @@ module SpreeCmCommissioner
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def sms_options
|
45
|
-
opts = {
|
45
|
+
opts = { to: context.to, body: context.body }
|
46
46
|
opts[:to] = sanitize(opts[:to]) if opts[:to].present?
|
47
47
|
opts[:from] = from_number
|
48
48
|
opts
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module SpreeCmCommissioner
|
2
2
|
class UserIdTokenAuthenticator < BaseInteractor
|
3
|
-
# :id_token
|
3
|
+
# :id_token, :tenant_id (optional)
|
4
4
|
def call
|
5
5
|
context.user = if checker.user.nil?
|
6
6
|
register_user
|
@@ -14,7 +14,11 @@ module SpreeCmCommissioner
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def register_user
|
17
|
-
register_context = SpreeCmCommissioner::UserRegistrationWithIdToken.call(
|
17
|
+
register_context = SpreeCmCommissioner::UserRegistrationWithIdToken.call(
|
18
|
+
id_token: context.id_token,
|
19
|
+
tenant_id: context.tenant_id
|
20
|
+
)
|
21
|
+
|
18
22
|
register_context.user
|
19
23
|
end
|
20
24
|
|
@@ -27,7 +31,7 @@ module SpreeCmCommissioner
|
|
27
31
|
end
|
28
32
|
|
29
33
|
def checker
|
30
|
-
@checker ||= SpreeCmCommissioner::UserIdTokenChecker.call(id_token: context.id_token)
|
34
|
+
@checker ||= SpreeCmCommissioner::UserIdTokenChecker.call(id_token: context.id_token, tenant_id: context.tenant_id)
|
31
35
|
@checker
|
32
36
|
end
|
33
37
|
end
|
@@ -1,6 +1,9 @@
|
|
1
1
|
module SpreeCmCommissioner
|
2
2
|
class UserIdTokenChecker < BaseInteractor
|
3
|
-
# :
|
3
|
+
# expects:
|
4
|
+
# context.id_token
|
5
|
+
# context.tenant_id (optional)
|
6
|
+
|
4
7
|
def call
|
5
8
|
firebase_id_token_context = SpreeCmCommissioner::FirebaseIdTokenProvider.call(id_token: context.id_token)
|
6
9
|
|
@@ -11,9 +14,14 @@ module SpreeCmCommissioner
|
|
11
14
|
end
|
12
15
|
end
|
13
16
|
|
14
|
-
# :identity_type, :sub
|
17
|
+
# :identity_type, :sub, :tenant_id
|
15
18
|
def validate_user_by_provider(provider)
|
16
|
-
identity_checker = SpreeCmCommissioner::UserIdentityChecker.call(
|
19
|
+
identity_checker = SpreeCmCommissioner::UserIdentityChecker.call(
|
20
|
+
identity_type: provider[:identity_type],
|
21
|
+
sub: provider[:sub],
|
22
|
+
tenant_id: context.tenant_id
|
23
|
+
)
|
24
|
+
|
17
25
|
if identity_checker.success?
|
18
26
|
context.user = identity_checker.user
|
19
27
|
else
|
@@ -1,6 +1,10 @@
|
|
1
1
|
module SpreeCmCommissioner
|
2
2
|
class UserIdentityChecker < BaseInteractor
|
3
|
-
# :
|
3
|
+
# expects:
|
4
|
+
# context.identity_type
|
5
|
+
# context.sub
|
6
|
+
# context.tenant_id (optional)
|
7
|
+
|
4
8
|
def call
|
5
9
|
load_user
|
6
10
|
|
@@ -11,12 +15,14 @@ module SpreeCmCommissioner
|
|
11
15
|
end
|
12
16
|
|
13
17
|
def load_user
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
+
return if context.sub.blank? || context.identity_type.blank?
|
19
|
+
|
20
|
+
user_identity_provider = UserIdentityProvider.joins(:user)
|
21
|
+
.where(identity_type: context.identity_type, sub: context.sub)
|
22
|
+
.where(spree_users: { tenant_id: context.tenant_id })
|
23
|
+
.first
|
18
24
|
|
19
|
-
context.user =
|
25
|
+
context.user = user_identity_provider&.user
|
20
26
|
end
|
21
27
|
end
|
22
28
|
end
|
@@ -15,7 +15,13 @@ module SpreeCmCommissioner
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def register_user!(name, email)
|
18
|
-
user = Spree.user_class.new(
|
18
|
+
user = Spree.user_class.new(
|
19
|
+
password: SecureRandom.base64(16),
|
20
|
+
email: email,
|
21
|
+
tenant_id: context.tenant_id,
|
22
|
+
**name_attributes(name)
|
23
|
+
)
|
24
|
+
|
19
25
|
if user.save(validate: false)
|
20
26
|
context.user = user
|
21
27
|
else
|
@@ -3,15 +3,17 @@ module SpreeCmCommissioner
|
|
3
3
|
enum identity_type: { :google => 0, :apple => 1, :facebook => 2, :telegram => 3, :vattanac_bank => 4 }
|
4
4
|
|
5
5
|
belongs_to :user, class_name: Spree.user_class.to_s, optional: false
|
6
|
+
has_one :tenant, through: :user
|
6
7
|
|
7
|
-
|
8
|
-
|
8
|
+
has_many :user_identity_provider_telegram_bots
|
9
|
+
has_many :telegram_bots, through: :user_identity_provider_telegram_bots
|
9
10
|
|
11
|
+
validates :sub, presence: true
|
10
12
|
validates :identity_type, presence: true
|
11
13
|
validates :identity_type, uniqueness: { scope: :user_id }
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
+
# custom validation to ensure that the sub is unique per identity_type and spree_users.tenant
|
16
|
+
validate :unique_sub_per_identity_type_and_tenant
|
15
17
|
|
16
18
|
# sub is a telegram uid, which telegram considered a chatID if
|
17
19
|
# user have /started with bot.
|
@@ -20,5 +22,25 @@ module SpreeCmCommissioner
|
|
20
22
|
|
21
23
|
nil
|
22
24
|
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def unique_sub_per_identity_type_and_tenant
|
29
|
+
return if user.nil? || sub.blank? || identity_type.blank?
|
30
|
+
|
31
|
+
tenant_id = user.tenant_id
|
32
|
+
|
33
|
+
# Check for duplicates in the same tenant
|
34
|
+
scope = self.class
|
35
|
+
.joins(:user)
|
36
|
+
.where(sub: sub, identity_type: identity_type)
|
37
|
+
.where(spree_users: { tenant_id: tenant_id })
|
38
|
+
|
39
|
+
scope = scope.where.not(id: id) if persisted?
|
40
|
+
|
41
|
+
return unless scope.exists?
|
42
|
+
|
43
|
+
errors.add(:sub, 'must be unique per identity_type and tenant')
|
44
|
+
end
|
23
45
|
end
|
24
46
|
end
|
@@ -11,6 +11,7 @@ module Spree
|
|
11
11
|
has_one :profile, serializer: Spree::V2::Tenant::AssetSerializer
|
12
12
|
has_many :device_tokens, serializer: Spree::V2::Tenant::UserDeviceTokenSerializer
|
13
13
|
has_many :spree_roles, serializer: Spree::V2::Tenant::RoleSerializer
|
14
|
+
has_many :user_identity_providers, serializer: Spree::V2::Tenant::UserIdentityProviderSerializer
|
14
15
|
|
15
16
|
attribute :store_credits, &:total_available_store_credit
|
16
17
|
|
@@ -32,7 +32,7 @@ module SpreeCmCommissioner
|
|
32
32
|
options = { login: params[:username], password: params[:password], tenant_id: tenant_id }
|
33
33
|
SpreeCmCommissioner::UserPasswordAuthenticator.call(options)
|
34
34
|
when 'social_auth'
|
35
|
-
options = { id_token: params[:id_token] }
|
35
|
+
options = { id_token: params[:id_token], tenant_id: tenant_id }
|
36
36
|
SpreeCmCommissioner::UserIdTokenAuthenticator.call(options)
|
37
37
|
when 'telegram_web_app_auth'
|
38
38
|
options = { telegram_init_data: params[:telegram_init_data], telegram_bot_username: params[:tg_bot] }
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class RemoveIndexesFromCmUserIdentityProviders < ActiveRecord::Migration[7.0]
|
2
|
+
def change
|
3
|
+
execute <<-SQL
|
4
|
+
ALTER TABLE cm_user_identity_providers
|
5
|
+
DROP CONSTRAINT IF EXISTS index_cm_user_identity_providers_on_identity_type_and_sub;
|
6
|
+
SQL
|
7
|
+
|
8
|
+
execute <<-SQL
|
9
|
+
ALTER TABLE cm_user_identity_providers
|
10
|
+
DROP CONSTRAINT IF EXISTS index_cm_user_identity_providers_on_user_id_and_identity_type;
|
11
|
+
SQL
|
12
|
+
end
|
13
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
FactoryBot.define do
|
2
|
-
factory :
|
2
|
+
factory :cm_user_identity_provider, class: SpreeCmCommissioner::UserIdentityProvider do
|
3
3
|
sequence(:sub) { |n| "sub-#{n}" }
|
4
4
|
identity_type { SpreeCmCommissioner::UserIdentityProvider.identity_types[:google] }
|
5
5
|
email { 'fake@example.com' }
|
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: 1.
|
4
|
+
version: 1.21.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- You
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-07-
|
11
|
+
date: 2025-07-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: spree
|
@@ -2537,6 +2537,7 @@ files:
|
|
2537
2537
|
- db/migrate/20250711093045_add_position_to_cm_dynamic_field_options.rb
|
2538
2538
|
- db/migrate/20250714121508_rename_cm_taxon_blazer_query_to_blazer_queryables.rb
|
2539
2539
|
- db/migrate/20250714124323_make_cm_blazer_queryables_polymorphic.rb
|
2540
|
+
- db/migrate/20250715103333_remove_indexes_from_cm_user_identity_providers.rb
|
2540
2541
|
- docker-compose.yml
|
2541
2542
|
- docs/option_types/attr_types.md
|
2542
2543
|
- docs/private_key.pem
|