diff --git a/forms/registration/activate.rb b/forms/registration/activate.rb
index 95886767e9ebc5ef6d5d57ce7a59a752fa43d813..ff29bcd0085d20965f280b4e4cdd67e75a7f4581 100644
--- a/forms/registration/activate.rb
+++ b/forms/registration/activate.rb
@@ -5,6 +5,8 @@ instructions <<~I
You've selected #{@tel} as your JMP number.
To activate your account, you can either deposit $#{'%.2f' % (CONFIG[:activation_amount] + @tel.price)} to your balance or enter your referral code if you have one.
(If you'd like to pay in another cryptocurrency, currently we recommend using a service like simpleswap.io, morphtoken.com, changenow.io, or godex.io.)
+
+ After payment is complete, your number will be activated for inbound calls and texts. Calling out, or sending a text, will often be restricted until you receive at least one text from a person or port in a number.
I
field(
diff --git a/lib/invites_repo.rb b/lib/invites_repo.rb
index f5713f17333c8e4dc19b497d10b986e571d40315..eb12a77ffd1d37ded2ded5ee1f3ac3b41ee426c1 100644
--- a/lib/invites_repo.rb
+++ b/lib/invites_repo.rb
@@ -3,19 +3,25 @@
require "multibases"
require "securerandom"
+require_relative "trust_level_repo"
+
class InvitesRepo
class Invalid < StandardError; end
def initialize(db=DB, redis=REDIS)
@db = db
@redis = redis
+ @trust_level_repo = TrustLevelRepo.new(db: db, redis: redis)
end
- def unused_invites(customer_id)
- promise = @db.query_defer(<<~SQL, [customer_id])
- SELECT code FROM unused_invites WHERE creator_id=$1
- SQL
- promise.then { |result| result.map { |row| row["code"] } }
+ def unused_invites(customer)
+ @trust_level_repo.find(customer).then { |tl|
+ next [] unless tl.invite?
+
+ @db.query_defer(<<~SQL, [customer_id])
+ SELECT code FROM unused_invites WHERE creator_id=$1
+ SQL
+ }.then { |result| result.map { |row| row["code"] } }
end
def find_or_create_group_code(customer_id)
@@ -44,7 +50,7 @@ class InvitesRepo
]).then do |(_, credit_to)|
next false if credit_to.to_s.strip == ""
- create_claimed_code(credit_to, customer_id)
+ create_claimed_code(credit_to, customer_id, trusted: false)
credit_to
end
end
@@ -69,10 +75,10 @@ class InvitesRepo
end
end
- def create_claimed_code(creator_id, used_by_id)
- @db.exec(<<~SQL, [creator_id, used_by_id])
- INSERT INTO invites (creator_id, used_by_id, used_at)
- VALUES ($1, $2, LOCALTIMESTAMP)
+ def create_claimed_code(creator_id, used_by_id, trusted: true)
+ @db.exec(<<~SQL, [creator_id, used_by_id, trusted])
+ INSERT INTO invites (creator_id, used_by_id, used_at, trusted)
+ VALUES ($1, $2, LOCALTIMESTAMP, $3)
SQL
end
diff --git a/lib/registration.rb b/lib/registration.rb
index 928442d70bd060bd75b12abd7b48e71612767eda..086bc6094f1d94355d87e671aabc2a3ac9b08db1 100644
--- a/lib/registration.rb
+++ b/lib/registration.rb
@@ -718,10 +718,17 @@ class Registration
class Finish
TN_UNAVAILABLE = "The JMP number %s is no longer available."
- def initialize(customer, tel)
+ def initialize(
+ customer, tel,
+ trust_level_repo: TrustLevelRepo.new(
+ db: LazyObject.new { DB },
+ redis: LazyObject.new { REDIS }
+ )
+ )
@customer = customer
@tel = tel
@invites = InvitesRepo.new(DB, REDIS)
+ @trust_level_repo = trust_level_repo
end
def write
@@ -796,18 +803,27 @@ class Registration
@tel.charge(customer)
])
}.then do
- FinishOnboarding.for(customer, @tel).then(&:write)
+ FinishOnboarding.for(
+ customer, @tel, trust_level_repo: @trust_level_repo
+ ).then(&:write)
end
end
end
module FinishOnboarding
- def self.for(customer, tel, db: LazyObject.new { DB })
+ def self.for(
+ customer, tel,
+ db: LazyObject.new { DB },
+ trust_level_repo: TrustLevelRepo.new(
+ db: LazyObject.new { DB },
+ redis: LazyObject.new { REDIS }
+ )
+ )
jid = ProxiedJID.new(customer.jid).unproxied
if jid.domain == CONFIG[:onboarding_domain]
Snikket.for(customer, tel, db: db)
else
- NotOnboarding.new(customer, tel)
+ NotOnboarding.new(customer, tel, trust_level_repo: trust_level_repo)
end
end
@@ -1006,13 +1022,17 @@ class Registration
end
class NotOnboarding
- def initialize(customer, tel)
+ def initialize(customer, tel, trust_level_repo:)
@customer = customer
@tel = tel
+ @trust_level_repo = trust_level_repo
end
def write
- WelcomeMessage.new(@customer, @tel).welcome
+ WelcomeMessage.for(
+ @customer, @tel,
+ trust_level_repo: @trust_level_repo
+ ).then(&:welcome)
Command.finish("Your JMP account has been activated as #{@tel}")
end
end
diff --git a/lib/trust_level.rb b/lib/trust_level.rb
index 10668cac7dcc5116b887f91be939dee7488078cf..b54112c1baf67b85108665e370deba6966c9e5b3 100644
--- a/lib/trust_level.rb
+++ b/lib/trust_level.rb
@@ -3,12 +3,15 @@
require "delegate"
module TrustLevel
- def self.for(plan_name:, settled_amount: 0, manual: nil)
+ def self.for(
+ customer:, settled_amount: 0, manual: nil,
+ activated: nil, invited: false, activater: nil
+ )
@levels.each do |level|
tl = level.call(
- plan_name: plan_name,
- settled_amount: settled_amount,
- manual: manual
+ customer: customer,
+ settled_amount: settled_amount, activated: activated,
+ manual: manual, invited: invited, activater: activater
)
return manual ? Manual.new(tl) : tl if tl
end
@@ -32,6 +35,10 @@ module TrustLevel
new if manual == "Tomb"
end
+ def invite?
+ false
+ end
+
def write_cdr?
false
end
@@ -70,8 +77,13 @@ module TrustLevel
end
class Cellar
- TrustLevel.register do |manual:, **|
- new if manual == "Cellar"
+ TrustLevel.register do |manual:, activated:, invited:, activater:, **|
+ new if manual == "Cellar" || (!manual && !activater && !invited && \
+ (!activated || activated > Time.parse("2026-02-26")))
+ end
+
+ def invite?
+ false
end
def write_cdr?
@@ -117,6 +129,10 @@ module TrustLevel
new if manual == "Basement" || (!manual && settled_amount < 10)
end
+ def invite?
+ true
+ end
+
def write_cdr?
true
end
@@ -171,6 +187,10 @@ module TrustLevel
new if manual == "Paragon" || (!manual && settled_amount > 60)
end
+ def invite?
+ true
+ end
+
def write_cdr?
true
end
@@ -225,6 +245,10 @@ module TrustLevel
new if manual == "Olympias"
end
+ def invite?
+ true
+ end
+
def write_cdr?
true
end
@@ -253,12 +277,12 @@ module TrustLevel
end
class Customer
- TrustLevel.register do |manual:, plan_name:, **|
+ TrustLevel.register do |manual:, customer:, **|
if manual && manual != "Customer"
Sentry.capture_message("Unknown TrustLevel: #{manual}")
end
- new(plan_name)
+ new(customer.plan_name)
end
EXPENSIVE_ROUTE = {
@@ -272,6 +296,10 @@ module TrustLevel
@max_rate = EXPENSIVE_ROUTE.fetch(plan_name, 0.1)
end
+ def invite?
+ true
+ end
+
def write_cdr?
true
end
diff --git a/lib/trust_level_repo.rb b/lib/trust_level_repo.rb
index 4cad9ba90cfa4648a71412e748e6056509c2366f..e7b0b30eaac9dc0c72889e44bb4bddd297cb9526 100644
--- a/lib/trust_level_repo.rb
+++ b/lib/trust_level_repo.rb
@@ -14,11 +14,17 @@ class TrustLevelRepo
def find(customer)
EMPromise.all([
find_manual(customer.customer_id),
+ redis.get("jmp_customer_activater-#{customer.customer_id}"),
+ customer.activation_date,
+ fetch_was_invited(customer.customer_id),
fetch_settled_amount(customer.billing_customer_id)
- ]).then do |(manual, row)|
+ ]).then do |(manual, activater, activated, invited, row)|
TrustLevel.for(
+ customer: customer,
manual: manual,
- plan_name: customer.plan_name,
+ activated: activated,
+ invited: invited[:used_at],
+ activater: activater,
**row
)
end
@@ -36,6 +42,22 @@ class TrustLevelRepo
end
end
+ def incoming_message(customer, stanza)
+ from = stanza.from.node.to_s
+ return if from =~ /^$|^[^+]/ # don't count short codes
+
+ body = m.body.to_s
+ return if body =~ /^$|http|code/i
+
+ redis.sismember("jmp_blocked_activation_source", from).then do |blocked|
+ next if blocked
+
+ redis.set(
+ "jmp_customer_activater-#{customer.customer_id}", stanza.from.node, "NX"
+ )
+ end
+ end
+
protected
def fetch_settled_amount(customer_id)
@@ -44,4 +66,10 @@ protected
WHERE customer_id=$1 AND settled_after < LOCALTIMESTAMP AND amount > 0
SQL
end
+
+ def fetch_was_invited(customer_id)
+ db.query_one(<<~SQL, customer_id, default: {})
+ SELECT used_at FROM invites WHERE used_by_id=$1 AND trusted LIMIT 1
+ SQL
+ end
end
diff --git a/lib/welcome_message.rb b/lib/welcome_message.rb
index 00fbd918509dc0e15db3a8b685f5a3e6d4bade36..ca5690ef5dfd7547b976e4126fa0595dd5e5097d 100644
--- a/lib/welcome_message.rb
+++ b/lib/welcome_message.rb
@@ -1,9 +1,18 @@
# frozen_string_literal: true
+require_relative "trust_level_repo"
+
class WelcomeMessage
- def initialize(customer, tel)
+ def self.for(customer, tel, trust_level_repo: TrustLevelRepo.new)
+ trust_level_repo.find(customer).then do |tl|
+ new(customer, tel, tl)
+ end
+ end
+
+ def initialize(customer, tel, trust_level)
@customer = customer
@tel = tel
+ @trust_level = trust_level
end
def welcome
@@ -13,15 +22,24 @@ class WelcomeMessage
end
end
+ def warning
+ return if @trust_level.support_call?(0, 0) && @trust_level.send_message?(0)
+
+ "\n\nYour account is activated for inbound calls and texts, but you " \
+ "won't be able to call out or send a text until you receive at least " \
+ "one text from a person at your new number, or port in a number from " \
+ "outside."
+ end
+
def message
m = Blather::Stanza::Message.new
m.from = CONFIG[:notify_from]
m.body =
- "Welcome to JMP! Your JMP number is #{@tel}. This is an automated " \
- "message, but anything you send here will go direct to real humans " \
- "who will be happy to help you. Such support requests will get a " \
- "reply within 8 business hours.\n\n" \
- "FAQ: https://jmp.chat/faq\n\n" \
+ "Welcome to JMP! Your JMP number is #{@tel}.#{warning}\n\nThis is an " \
+ "automated message, but anything you send here will go direct to real " \
+ "humans who will be happy to help you. Such support requests will " \
+ "get a reply within 8 business hours.\n\n" \
+ "FAQ: https://jmp.chat/faq\n" \
"Account Settings: xmpp:cheogram.com?command"
m
end
diff --git a/sgx_jmp.rb b/sgx_jmp.rb
index 7aaef894ec29d0195356f2e4776aa6294c80cf45..c4acf4f3932b1159a27db536a256f76e633ece62 100644
--- a/sgx_jmp.rb
+++ b/sgx_jmp.rb
@@ -276,6 +276,8 @@ before nil, to: /\Acustomer_/, from: /(\A|@)#{FROM_BACKEND}(\/|\Z)/ do |s|
CustomerRepo.new(set_user: Sentry.method(:set_user)).find(
s.to.node.delete_prefix("customer_")
).then do |customer|
+ # Intentionally called outside filter so ported-in numbers activate here
+ TrustLevelRepo.new.incoming_message(customer, s)
ReachabilityRepo::SMS.new
.find(customer, s.from.node, stanza: s).then do |reach|
reach.filter do
@@ -304,6 +306,7 @@ message(
CustomerRepo
.new(set_user: Sentry.method(:set_user))
.find_by_jid(address["jid"]).then { |customer|
+ TrustLevelRepo.new.incoming_message(customer, s)
m.from = m.from.with(domain: CONFIG[:component][:jid])
m.to = m.to.with(domain: customer.jid.domain)
address["jid"] = customer.jid.to_s
@@ -716,7 +719,7 @@ Command.new(
Command.customer.then { |customer|
EMPromise.all([
repo.find_or_create_group_code(customer.customer_id),
- repo.unused_invites(customer.customer_id)
+ repo.unused_invites(customer)
])
}.then do |(group_code, invites)|
if invites.empty?
@@ -1092,7 +1095,7 @@ Command.new(
jid = ProxiedJID.new(customer.jid).unproxied
if jid.domain == CONFIG[:onboarding_domain]
CustomerRepo.new.find(customer.customer_id).then do |cust|
- WelcomeMessage.new(cust, customer.registered?.phone).welcome
+ WelcomeMessage.for(cust, customer.registered?.phone).then(&:welcome)
end
end
Command.finish { |reply|
diff --git a/test/test_admin_command.rb b/test/test_admin_command.rb
index 7534c5c5b4c07c3d2f9d869ad76e0b7b99125c0b..040805082ebf0c7f5b0f8a2a772e3aa2acf74984 100644
--- a/test/test_admin_command.rb
+++ b/test/test_admin_command.rb
@@ -164,6 +164,18 @@ class AdminCommandTest < Minitest::Test
["jmp_customer_trust_level-testuser"]
)
+ TrustLevelRepo::REDIS.expect(
+ :get,
+ EMPromise.resolve(nil),
+ ["jmp_customer_activater-testuser"]
+ )
+
+ TrustLevelRepo::DB.expect(
+ :query_one,
+ EMPromise.resolve({}),
+ [String, "testuser"], default: {}
+ )
+
TrustLevelRepo::DB.expect(
:query_one,
EMPromise.resolve({ settled_amount: 0 }),
diff --git a/test/test_buy_account_credit_form.rb b/test/test_buy_account_credit_form.rb
index 8fc84c67a18f800040072b5b8c4b0ac81b7c181b..2573db8ae19d142fc3c267ecd42bc79d9a725580 100644
--- a/test/test_buy_account_credit_form.rb
+++ b/test/test_buy_account_credit_form.rb
@@ -36,6 +36,19 @@ class BuyAccountCreditFormTest < Minitest::Test
EMPromise.resolve("Customer"),
["jmp_customer_trust_level-test"]
)
+ TrustLevelRepo::REDIS.expect(
+ :get,
+ EMPromise.resolve(nil),
+ ["jmp_customer_activater-test"]
+ )
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "test"]
+ )
+ TrustLevelRepo::DB.expect(
+ :query_one,
+ EMPromise.resolve({}),
+ [String, "test"], default: {}
+ )
TrustLevelRepo::DB.expect(
:query_one,
EMPromise.resolve({}),
@@ -47,6 +60,7 @@ class BuyAccountCreditFormTest < Minitest::Test
BuyAccountCreditForm.for(customer).sync
)
+ assert_mock CustomerPlan::DB
assert_mock TrustLevelRepo::REDIS
assert_mock TrustLevelRepo::DB
end
diff --git a/test/test_credit_card_sale.rb b/test/test_credit_card_sale.rb
index 2d460da513e4c39af7c23f5edc2776ec4c8462f8..a39123f9191666b9343852ad3c159fc33373edec 100644
--- a/test/test_credit_card_sale.rb
+++ b/test/test_credit_card_sale.rb
@@ -32,6 +32,19 @@ class CreditCardSaleTest < Minitest::Test
EMPromise.resolve("Customer"),
["jmp_customer_trust_level-test"]
)
+ TrustLevelRepo::REDIS.expect(
+ :get,
+ EMPromise.resolve(nil),
+ ["jmp_customer_activater-test"]
+ )
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "test"]
+ )
+ TrustLevelRepo::DB.expect(
+ :query_one,
+ EMPromise.resolve({}),
+ [String, "test"], default: {}
+ )
TrustLevelRepo::DB.expect(
:query_one,
EMPromise.resolve({}),
@@ -72,6 +85,7 @@ class CreditCardSaleTest < Minitest::Test
).sale.sync
end
assert_mock CustomerFinancials::REDIS
+ assert_mock CustomerPlan::DB
assert_mock CreditCardSale::REDIS
assert_mock TrustLevelRepo::REDIS
assert_mock TrustLevelRepo::DB
@@ -89,6 +103,19 @@ class CreditCardSaleTest < Minitest::Test
EMPromise.resolve("Customer"),
["jmp_customer_trust_level-test"]
)
+ TrustLevelRepo::REDIS.expect(
+ :get,
+ EMPromise.resolve(nil),
+ ["jmp_customer_activater-test"]
+ )
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "test"]
+ )
+ TrustLevelRepo::DB.expect(
+ :query_one,
+ EMPromise.resolve({}),
+ [String, "test"], default: {}
+ )
TrustLevelRepo::DB.expect(
:query_one,
EMPromise.resolve({}),
@@ -107,6 +134,7 @@ class CreditCardSaleTest < Minitest::Test
).sale.sync
end
assert_mock CustomerFinancials::REDIS
+ assert_mock CustomerPlan::DB
assert_mock CreditCardSale::REDIS
assert_mock TrustLevelRepo::REDIS
assert_mock TrustLevelRepo::DB
@@ -124,6 +152,19 @@ class CreditCardSaleTest < Minitest::Test
EMPromise.resolve("Customer"),
["jmp_customer_trust_level-test"]
)
+ TrustLevelRepo::REDIS.expect(
+ :get,
+ EMPromise.resolve(nil),
+ ["jmp_customer_activater-test"]
+ )
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "test"]
+ )
+ TrustLevelRepo::DB.expect(
+ :query_one,
+ EMPromise.resolve({}),
+ [String, "test"], default: {}
+ )
TrustLevelRepo::DB.expect(
:query_one,
EMPromise.resolve({}),
@@ -144,6 +185,7 @@ class CreditCardSaleTest < Minitest::Test
end
assert_mock CustomerFinancials::REDIS
+ assert_mock CustomerPlan::DB
assert_mock CreditCardSale::REDIS
assert_mock TrustLevelRepo::REDIS
assert_mock TrustLevelRepo::DB
@@ -161,6 +203,19 @@ class CreditCardSaleTest < Minitest::Test
EMPromise.resolve("Customer"),
["jmp_customer_trust_level-test"]
)
+ TrustLevelRepo::REDIS.expect(
+ :get,
+ EMPromise.resolve("Customer"),
+ ["jmp_customer_activater-test"]
+ )
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "test"]
+ )
+ TrustLevelRepo::DB.expect(
+ :query_one,
+ EMPromise.resolve({}),
+ [String, "test"], default: {}
+ )
TrustLevelRepo::DB.expect(
:query_one,
EMPromise.resolve({}),
@@ -181,6 +236,7 @@ class CreditCardSaleTest < Minitest::Test
end
assert_mock CustomerFinancials::REDIS
+ assert_mock CustomerPlan::DB
assert_mock CreditCardSale::REDIS
assert_mock TrustLevelRepo::REDIS
assert_mock TrustLevelRepo::DB
@@ -218,6 +274,19 @@ class CreditCardSaleTest < Minitest::Test
EMPromise.resolve("Customer"),
["jmp_customer_trust_level-test"]
)
+ TrustLevelRepo::REDIS.expect(
+ :get,
+ EMPromise.resolve(nil),
+ ["jmp_customer_activater-test"]
+ )
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "test"]
+ )
+ TrustLevelRepo::DB.expect(
+ :query_one,
+ EMPromise.resolve({}),
+ [String, "test"], default: {}
+ )
TrustLevelRepo::DB.expect(
:query_one,
EMPromise.resolve({}),
@@ -255,6 +324,7 @@ class CreditCardSaleTest < Minitest::Test
).sale.sync
assert_equal FAKE_BRAINTREE_TRANSACTION, result
assert_mock CustomerFinancials::REDIS
+ assert_mock CustomerPlan::DB
assert_mock CreditCardSale::REDIS
assert_mock TrustLevelRepo::REDIS
assert_mock TrustLevelRepo::DB
@@ -309,6 +379,19 @@ class CreditCardSaleTest < Minitest::Test
EMPromise.resolve("Customer"),
["jmp_customer_trust_level-test"]
)
+ TrustLevelRepo::REDIS.expect(
+ :get,
+ EMPromise.resolve(nil),
+ ["jmp_customer_activater-test"]
+ )
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "test"]
+ )
+ TrustLevelRepo::DB.expect(
+ :query_one,
+ EMPromise.resolve({}),
+ [String, "test"], default: {}
+ )
TrustLevelRepo::DB.expect(
:query_one,
EMPromise.resolve({}),
@@ -367,6 +450,7 @@ class CreditCardSaleTest < Minitest::Test
assert_mock transaction_class
assert_mock transaction
assert_mock CustomerFinancials::REDIS
+ assert_mock CustomerPlan::DB
assert_mock CreditCardSale::REDIS
assert_mock TrustLevelRepo::REDIS
assert_mock TrustLevelRepo::DB
diff --git a/test/test_helper.rb b/test/test_helper.rb
index ac1946ed4319cf25f95108c611b623f764864a5f..91c9b5b03e15f23de26405803034858e6e1bd934 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -478,6 +478,16 @@ class FakeIBRRepo
end
end
+class FakeTrustLevelRepo
+ def initialize(levels)
+ @levels = levels
+ end
+
+ def find(customer)
+ TrustLevel.for(customer: customer, manual: @levels[customer.customer_id])
+ end
+end
+
module EventMachine
class << self
# Patch EM.add_timer to be instant in tests
diff --git a/test/test_registration.rb b/test/test_registration.rb
index 264e1ddfdce3ce4713411812b425426a5e969831..f84c721c75e1b1a82a4b06a276df95bb62cb5acc 100644
--- a/test/test_registration.rb
+++ b/test/test_registration.rb
@@ -220,6 +220,7 @@ class RegistrationTest < Minitest::Test
"PARENT_TOMB" => "2",
"PARENT_MANY_SUBACCOUNTS" => "many_subaccounts"
},
+ "jmp_customer_trust_level-1" => "Basement",
"jmp_customer_trust_level-2" => "Tomb"
)
Registration::Activation::Payment = Minitest::Mock.new
@@ -436,6 +437,12 @@ class RegistrationTest < Minitest::Test
)
end]
)
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "1"]
+ )
+ Registration::Activation::DB.expect(
+ :query_one, {}, [String, "1"], default: {}
+ )
Registration::Activation::DB.expect(
:query_one, {}, [String, "1"], default: {}
)
@@ -466,6 +473,7 @@ class RegistrationTest < Minitest::Test
)
end
assert_mock Command::COMMAND_MANAGER
+ assert_mock CustomerPlan::DB
assert_mock @customer
assert_mock Registration::Activation::Payment
assert_mock Registration::Activation::DB
@@ -490,6 +498,12 @@ class RegistrationTest < Minitest::Test
)
end]
)
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "1"]
+ )
+ Registration::Activation::DB.expect(
+ :query_one, {}, [String, "1"], default: {}
+ )
Registration::Activation::DB.expect(
:query_one, {}, [String, "1"], default: {}
)
@@ -531,6 +545,12 @@ class RegistrationTest < Minitest::Test
)
end]
)
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "2"]
+ )
+ Registration::Activation::DB.expect(
+ :query_one, {}, [String, "2"], default: {}
+ )
Registration::Activation::DB.expect(
:query_one, {}, [String, "2"], default: {}
)
@@ -542,6 +562,7 @@ class RegistrationTest < Minitest::Test
execute_command { @activation.write.catch(&:to_s) }
)
assert_mock Command::COMMAND_MANAGER
+ assert_mock CustomerPlan::DB
assert_mock @customer
assert_mock Registration::Activation::Payment
assert_mock Registration::Activation::DB
@@ -565,6 +586,12 @@ class RegistrationTest < Minitest::Test
)
end]
)
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "many_subaccounts"]
+ )
+ Registration::Activation::DB.expect(
+ :query_one, {}, [String, "many_subaccounts"], default: {}
+ )
Registration::Activation::DB.expect(
:query_one, {}, [String, "many_subaccounts"], default: {}
)
@@ -576,6 +603,7 @@ class RegistrationTest < Minitest::Test
execute_command { @activation.write.catch(&:to_s) }
)
assert_mock Command::COMMAND_MANAGER
+ assert_mock CustomerPlan::DB
assert_mock @customer
assert_mock Registration::Activation::Payment
assert_mock Registration::Activation::DB
@@ -654,7 +682,7 @@ class RegistrationTest < Minitest::Test
Registration::Activation::Allow::DB.expect(
:exec,
nil,
- [String, ["refercust", "test"]]
+ [String, ["refercust", "test", true]]
)
cust.expect(:with_plan, cust, ["test_usd"])
cust.expect(:activate_plan_starting_now, nil)
@@ -1039,6 +1067,12 @@ class RegistrationTest < Minitest::Test
:new,
OpenStruct.new(write: nil)
) { |*| true }
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "parent_customer"]
+ )
+ Registration::Payment::InviteCode::DB.expect(
+ :query_one, {}, [String, "parent_customer"], default: {}
+ )
Registration::Payment::InviteCode::DB.expect(
:query_one, {}, [String, "parent_customer"], default: {}
)
@@ -1053,9 +1087,14 @@ class RegistrationTest < Minitest::Test
)
Registration::Payment::InviteCode::REDIS.expect(
:get,
- EMPromise.resolve(nil),
+ EMPromise.resolve("Basement"),
["jmp_customer_trust_level-parent_customer"]
)
+ Registration::Payment::InviteCode::REDIS.expect(
+ :get,
+ EMPromise.resolve(nil),
+ ["jmp_customer_activater-parent_customer"]
+ )
CustomerPlan::DB.expect(
:query,
[{ "plan_name" => "test_usd" }],
@@ -1090,6 +1129,7 @@ class RegistrationTest < Minitest::Test
).write
end
assert_mock Command::COMMAND_MANAGER
+ assert_mock CustomerPlan::DB
assert_mock Registration::Payment::InviteCode::DB
assert_mock Registration::Payment::InviteCode::REDIS
assert_mock Registration::Payment::MaybeBill::BillPlan
@@ -1314,7 +1354,8 @@ class RegistrationTest < Minitest::Test
iq.from = "test\\40example.com@cheogram.com"
@finish = Registration::Finish.new(
customer(sgx: @sgx, plan_name: "test_usd"),
- TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
+ TelSelections::ChooseTel::Tn.for_pending_value("+15555550000"),
+ trust_level_repo: FakeTrustLevelRepo.new("test" => "Cellar")
)
end
@@ -1468,7 +1509,7 @@ class RegistrationTest < Minitest::Test
Registration::Finish::DB.expect(
:exec,
EMPromise.resolve(nil),
- [String, ["test-inviter", "test"]]
+ [String, ["test-inviter", "test", false]]
)
Transaction::DB.expect(:transaction, nil) do |&blk|
blk.call
diff --git a/test/test_trust_level_repo.rb b/test/test_trust_level_repo.rb
index b8e7b86063e8118274fcee96f01df3f02d2dc478..9b7bed6e19c631ca81173cbb5361dd7302fa67d7 100644
--- a/test/test_trust_level_repo.rb
+++ b/test/test_trust_level_repo.rb
@@ -3,6 +3,16 @@
require "trust_level_repo"
class TrustLevelRepoTest < Minitest::Test
+ def setup
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "test"]
+ )
+ end
+
+ def teardown
+ assert_mock CustomerPlan::DB
+ end
+
def test_manual_tomb
trust_level = TrustLevelRepo.new(
db: FakeDB.new,
@@ -14,6 +24,17 @@ class TrustLevelRepoTest < Minitest::Test
end
em :test_manual_tomb
+ def test_manual_cellar
+ trust_level = TrustLevelRepo.new(
+ db: FakeDB.new,
+ redis: FakeRedis.new(
+ "jmp_customer_trust_level-test" => "Cellar"
+ )
+ ).find(customer(plan_name: "test_usd")).sync
+ assert_equal "Manual(Cellar)", trust_level.to_s
+ end
+ em :test_manual_cellar
+
def test_manual_basement
trust_level = TrustLevelRepo.new(
db: FakeDB.new,
@@ -63,14 +84,51 @@ class TrustLevelRepoTest < Minitest::Test
db: FakeDB.new,
redis: FakeRedis.new
).find(customer(plan_name: "test_usd")).sync
- assert_kind_of TrustLevel::Basement, trust_level
+ assert_kind_of TrustLevel::Cellar, trust_level
end
em :test_new_customer
+ def test_new_customer_with_activater
+ trust_level = TrustLevelRepo.new(
+ db: FakeDB.new,
+ redis: FakeRedis.new(
+ "jmp_customer_activater-test" => "+15551234567"
+ )
+ ).find(customer(plan_name: "test_usd")).sync
+ assert_kind_of TrustLevel::Basement, trust_level
+ end
+ em :test_new_customer_with_activater
+
+ def test_invited_customer
+ trust_level = TrustLevelRepo.new(
+ db: FakeDB.new(
+ ["test"] => FakeDB::MultiResult.new([{ used_at: Time.now }], [])
+ ),
+ redis: FakeRedis.new
+ ).find(customer(plan_name: "test_usd")).sync
+ assert_kind_of TrustLevel::Basement, trust_level
+ end
+ em :test_invited_customer
+
+ def test_old_customer
+ CustomerPlan::DB.query_one("", "test")
+ CustomerPlan::DB.expect(
+ :query_one, { start_date: Time.parse("2026-02-25") }, [String, "test"]
+ )
+ trust_level = TrustLevelRepo.new(
+ db: FakeDB.new,
+ redis: FakeRedis.new
+ ).find(customer(plan_name: "test_usd")).sync
+ assert_kind_of TrustLevel::Basement, trust_level
+ end
+ em :test_old_customer
+
def test_regular_customer
trust_level = TrustLevelRepo.new(
db: FakeDB.new(["test"] => [{ "settled_amount" => 15 }]),
- redis: FakeRedis.new
+ redis: FakeRedis.new(
+ "jmp_customer_activater-test" => "+15551234567"
+ )
).find(customer(plan_name: "test_usd")).sync
assert_kind_of TrustLevel::Customer, trust_level
end
@@ -79,7 +137,9 @@ class TrustLevelRepoTest < Minitest::Test
def test_settled_customer
trust_level = TrustLevelRepo.new(
db: FakeDB.new(["test"] => [{ "settled_amount" => 61 }]),
- redis: FakeRedis.new
+ redis: FakeRedis.new(
+ "jmp_customer_activater-test" => "+15551234567"
+ )
).find(customer(plan_name: "test_usd")).sync
assert_kind_of TrustLevel::Paragon, trust_level
end
diff --git a/test/test_web.rb b/test/test_web.rb
index 8bc2cc36a2a44489fbb0b56437dbb303566b87e3..8677f382159312555b27ef12e1dfd714a9a63deb 100644
--- a/test/test_web.rb
+++ b/test/test_web.rb
@@ -124,7 +124,13 @@ class WebTest < Minitest::Test
)
)
Web.opts[:call_attempt_repo] = CallAttemptRepo.new(
- redis: FakeRedis.new,
+ redis: FakeRedis.new(
+ "jmp_customer_activater-customerid" => "+15551234567",
+ "jmp_customer_activater-customerid2" => "+15551234567",
+ "jmp_customer_activater-customerid_limit" => "+15551234567",
+ "jmp_customer_activater-customerid_low" => "+15551234567",
+ "jmp_customer_activater-customerid_topup" => "+15551234567"
+ ),
db: FakeDB.new(
["test_usd", "+15557654321", :outbound] => [{ "rate" => 0.01 }],
["test_usd", "+1911", :outbound] => [{ "rate" => 0.01 }],
@@ -134,14 +140,17 @@ class WebTest < Minitest::Test
["test_usd", "+18001234567", :outbound] => [{ "rate" => 0.00 }],
["customerid_limit"] => FakeDB::MultiResult.new(
[{ "a" => 1000 }],
+ [],
[{ "settled_amount" => 15 }]
),
["customerid_low"] => FakeDB::MultiResult.new(
[{ "a" => 1000 }],
+ [],
[{ "settled_amount" => 15 }]
),
["customerid_topup"] => FakeDB::MultiResult.new(
[{ "a" => 1000 }],
+ [],
[{ "settled_amount" => 15 }]
)
)
@@ -163,6 +172,10 @@ class WebTest < Minitest::Test
end
def test_outbound_forwards
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "customerid"]
+ )
+
post(
"/outbound/calls",
{
@@ -180,10 +193,15 @@ class WebTest < Minitest::Test
"+15557654321",
last_response.body
)
+ assert_mock CustomerPlan::DB
end
em :test_outbound_forwards
def test_outbound_low_balance
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "customerid_low"]
+ )
+
ExpiringLock::REDIS.expect(
:set,
EMPromise.resolve(nil),
@@ -208,10 +226,15 @@ class WebTest < Minitest::Test
last_response.body
)
assert_mock ExpiringLock::REDIS
+ assert_mock CustomerPlan::DB
end
em :test_outbound_low_balance
def test_outbound_low_balance_top_up
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "customerid_topup"]
+ )
+
LowBalance::AutoTopUp::CreditCardSale.expect(
:create,
EMPromise.resolve(
@@ -273,10 +296,15 @@ class WebTest < Minitest::Test
assert_mock ExpiringLock::REDIS
assert_mock Customer::BLATHER
assert_mock LowBalance::AutoTopUp::CreditCardSale
+ assert_mock CustomerPlan::DB
end
em :test_outbound_low_balance_top_up
def test_outbound_unsupported
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "customerid"]
+ )
+
post(
"/outbound/calls",
{
@@ -294,10 +322,15 @@ class WebTest < Minitest::Test
"supported on your account.",
last_response.body
)
+ assert_mock CustomerPlan::DB
end
em :test_outbound_unsupported
def test_outbound_unsupported_short_numbers_911
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "customerid"]
+ )
+
post(
"/outbound/calls",
{
@@ -315,10 +348,15 @@ class WebTest < Minitest::Test
"supported on your account.",
last_response.body
)
+ assert_mock CustomerPlan::DB
end
em :test_outbound_unsupported_short_numbers_911
def test_outbound_supported_9116
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "customerid"]
+ )
+
post(
"/outbound/calls",
{
@@ -336,10 +374,15 @@ class WebTest < Minitest::Test
"+19116",
last_response.body
)
+ assert_mock CustomerPlan::DB
end
em :test_outbound_supported_9116
def test_outbound_atlimit
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "customerid_limit"]
+ )
+
post(
"/outbound/calls",
{
@@ -360,6 +403,7 @@ class WebTest < Minitest::Test
"charges. You can hang up to cancel.",
last_response.body
)
+ assert_mock CustomerPlan::DB
end
em :test_outbound_atlimit
@@ -385,6 +429,10 @@ class WebTest < Minitest::Test
em :test_outbound_no_customer
def test_outbound_atlimit_digits
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "customerid_limit"]
+ )
+
post(
"/outbound/calls",
{
@@ -403,10 +451,15 @@ class WebTest < Minitest::Test
"+15557654321",
last_response.body
)
+ assert_mock CustomerPlan::DB
end
em :test_outbound_atlimit_digits
def test_outbound_toll_free
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "customerid"]
+ )
+
post(
"/outbound/calls",
{
@@ -424,10 +477,15 @@ class WebTest < Minitest::Test
"+18001234567",
last_response.body
)
+ assert_mock CustomerPlan::DB
end
em :test_outbound_toll_free
def test_outbound_disconnect
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "customerid"]
+ )
+
post(
"/outbound/calls/status",
{
@@ -444,10 +502,15 @@ class WebTest < Minitest::Test
assert last_response.ok?
assert_equal("OK", last_response.body)
+ assert_mock CustomerPlan::DB
end
em :test_outbound_disconnect
def test_outbound_disconnect_tombed
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "customerid_tombed"]
+ )
+
@cdr_repo.stub(:put, ->(*) { raise "put called" }) do
post(
"/outbound/calls/status",
@@ -466,10 +529,14 @@ class WebTest < Minitest::Test
assert last_response.ok?
assert_equal("OK", last_response.body)
+ assert_mock CustomerPlan::DB
end
em :test_outbound_disconnect_tombed
def test_inbound
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "customerid"]
+ )
CustomerFwd::BANDWIDTH_VOICE.expect(
:create_call,
OpenStruct.new(data: OpenStruct.new(call_id: "ocall")),
@@ -500,10 +567,14 @@ class WebTest < Minitest::Test
last_response.body
)
assert_mock CustomerFwd::BANDWIDTH_VOICE
+ assert_mock CustomerPlan::DB
end
em :test_inbound
def test_inbound_from_reachability
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "customerid"]
+ )
CustomerFwd::BANDWIDTH_VOICE.expect(
:create_call,
OpenStruct.new(data: OpenStruct.new(call_id: "ocall")),
@@ -541,10 +612,14 @@ class WebTest < Minitest::Test
)
assert_mock CustomerFwd::BANDWIDTH_VOICE
assert_mock ReachableRedis
+ assert_mock CustomerPlan::DB
end
em :test_inbound_from_reachability
def test_inbound_no_bwmsgsv2
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "customerid2"]
+ )
CustomerFwd::BANDWIDTH_VOICE.expect(
:create_call,
OpenStruct.new(data: OpenStruct.new(call_id: "ocall")),
@@ -575,10 +650,15 @@ class WebTest < Minitest::Test
last_response.body
)
assert_mock CustomerFwd::BANDWIDTH_VOICE
+ assert_mock CustomerPlan::DB
end
em :test_inbound_no_bwmsgsv2
def test_inbound_low
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "customerid_low"]
+ )
+
ExpiringLock::REDIS.expect(
:set,
EMPromise.resolve(nil),
@@ -604,10 +684,15 @@ class WebTest < Minitest::Test
)
assert_mock CustomerFwd::BANDWIDTH_VOICE
assert_mock ExpiringLock::REDIS
+ assert_mock CustomerPlan::DB
end
em :test_inbound_low
def test_inbound_leg2
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "customerid"]
+ )
+
post(
"/inbound/calls/acall?customer_id=customerid",
{
@@ -625,10 +710,15 @@ class WebTest < Minitest::Test
"",
last_response.body
)
+ assert_mock CustomerPlan::DB
end
em :test_inbound_leg2
def test_inbound_limit_leg2
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "customerid_limit"]
+ )
+
path = "/inbound/calls/acall?customer_id=customerid_limit"
post(
@@ -652,10 +742,15 @@ class WebTest < Minitest::Test
"",
last_response.body
)
+ assert_mock CustomerPlan::DB
end
em :test_inbound_limit_leg2
def test_inbound_limit_digits_leg2
+ CustomerPlan::DB.expect(
+ :query_one, {}, [String, "customerid_limit"]
+ )
+
post(
"/inbound/calls/acall?customer_id=customerid_limit",
{
@@ -674,6 +769,7 @@ class WebTest < Minitest::Test
"",
last_response.body
)
+ assert_mock CustomerPlan::DB
end
em :test_inbound_limit_digits_leg2