Re-introduce a Signup PORO model
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
class Signup
|
||||
include ActiveModel::Model
|
||||
include ActiveModel::Attributes
|
||||
include ActiveModel::Validations
|
||||
|
||||
PERMITTED_KEYS = %i[ full_name email_address password company_name ]
|
||||
|
||||
# Input attributes
|
||||
attr_accessor :company_name, :full_name, :email_address, :password
|
||||
validates_presence_of :company_name, :full_name, :email_address, :password
|
||||
|
||||
# Output attributes
|
||||
attr_reader :tenant, :account, :user, :queenbee_account
|
||||
|
||||
def initialize(...)
|
||||
@company_name = nil
|
||||
@full_name = nil
|
||||
@email_address = nil
|
||||
@password = nil
|
||||
@tenant = nil
|
||||
@account = nil
|
||||
@user = nil
|
||||
@queenbee_account = nil
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
def process
|
||||
return false unless valid?
|
||||
|
||||
create_queenbee_account
|
||||
create_tenant
|
||||
|
||||
true
|
||||
rescue => error
|
||||
destroy_tenant
|
||||
destroy_queenbee_account
|
||||
|
||||
errors.add(:base, "An error occurred during signup: #{error.message}")
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
private
|
||||
def create_queenbee_account
|
||||
@queenbee_account = Queenbee::Remote::Account.create!(queenbee_account_attributes)
|
||||
end
|
||||
|
||||
def destroy_queenbee_account
|
||||
@queenbee_account&.cancel
|
||||
@queenbee_account = nil
|
||||
end
|
||||
|
||||
def create_tenant
|
||||
@tenant = queenbee_account.id.to_s
|
||||
ApplicationRecord.create_tenant(tenant) do
|
||||
@account = Account.create_with_admin_user(
|
||||
account: {
|
||||
external_account_id: tenant,
|
||||
name: company_name
|
||||
},
|
||||
owner: {
|
||||
name: full_name,
|
||||
email_address: email_address,
|
||||
password: password
|
||||
}
|
||||
)
|
||||
@user = User.first
|
||||
@account.setup_basic_template
|
||||
end
|
||||
end
|
||||
|
||||
def destroy_tenant
|
||||
if tenant.present? && ApplicationRecord.tenant_exist?(tenant)
|
||||
ApplicationRecord.destroy_tenant(tenant)
|
||||
end
|
||||
@user = nil
|
||||
@account = nil
|
||||
@tenant = nil
|
||||
end
|
||||
|
||||
def queenbee_account_attributes
|
||||
{}.tap do |attributes|
|
||||
# Tell Queenbee to skip the request to create a local account. We've created it ourselves.
|
||||
attributes[:skip_remote] = true
|
||||
|
||||
# # TODO: once we are doing our own email validation, consider setting this
|
||||
# # Queenbee should not do spam checks on this account, we've done our own.
|
||||
# attributes[:auto_allow] = true
|
||||
|
||||
# # TODO: Terms of Service
|
||||
# attributes[:terms_of_service] = true
|
||||
|
||||
attributes[:product_name] = "fizzy"
|
||||
attributes[:name] = company_name
|
||||
attributes[:owner_name] = full_name
|
||||
attributes[:owner_email] = email_address
|
||||
|
||||
attributes[:trial] = true
|
||||
attributes[:subscription] = subscription_attributes
|
||||
attributes[:remote_request] = request_attributes
|
||||
end
|
||||
end
|
||||
|
||||
def subscription_attributes
|
||||
subscription = FreeV1Subscription
|
||||
|
||||
{}.tap do |attributes|
|
||||
attributes[:name] = subscription.to_param
|
||||
attributes[:price] = subscription.price
|
||||
end
|
||||
end
|
||||
|
||||
def request_attributes
|
||||
{}.tap do |attributes|
|
||||
attributes[:remote_address] = Current.ip_address
|
||||
attributes[:user_agent] = Current.user_agent
|
||||
attributes[:referrer] = Current.referrer
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,94 @@
|
||||
require "test_helper"
|
||||
|
||||
class SignupTest < ActiveSupport::TestCase
|
||||
setup do
|
||||
@starting_tenants = ApplicationRecord.tenants
|
||||
@signup = Signup.new(
|
||||
email_address: "brian@example.com",
|
||||
full_name: "Brian Wilson",
|
||||
company_name: "Beach Boys",
|
||||
password: SecureRandom.hex(16)
|
||||
)
|
||||
end
|
||||
|
||||
test "#process creates all the necessary objects for a new Fizzy account" do
|
||||
Account.any_instance.expects(:setup_basic_template).once
|
||||
|
||||
assert @signup.process, @signup.errors.full_messages.to_sentence(words_connector: ". ")
|
||||
assert_empty @signup.errors
|
||||
|
||||
assert @signup.tenant
|
||||
assert_includes ApplicationRecord.tenants, @signup.tenant
|
||||
|
||||
assert @signup.account
|
||||
assert @signup.account.persisted?
|
||||
assert @signup.account.external_account_id
|
||||
assert_equal @signup.company_name, @signup.account.name
|
||||
assert_equal @signup.tenant, @signup.account.external_account_id.to_s
|
||||
assert_equal @signup.tenant, @signup.account.tenant
|
||||
|
||||
assert @signup.user
|
||||
assert @signup.user.persisted?
|
||||
assert_equal @signup.full_name, @signup.user.name
|
||||
assert_equal @signup.email_address, @signup.user.email_address
|
||||
|
||||
auth_params = { email_address: @signup.email_address, password: @signup.password }
|
||||
user = ApplicationRecord.with_tenant(@signup.tenant) { User.authenticate_by(**auth_params) }
|
||||
|
||||
assert user, "User should be able to authenticate with #{auth_params.inspect}"
|
||||
assert_equal @signup.user, user
|
||||
assert_equal @signup.tenant, @signup.user.tenant
|
||||
end
|
||||
|
||||
test "#process does nothing if a basic validation error occurs" do
|
||||
@signup.password = ""
|
||||
|
||||
assert_not @signup.process
|
||||
assert_not_empty @signup.errors[:password]
|
||||
|
||||
assert_nil @signup.tenant
|
||||
assert_nil @signup.account
|
||||
assert_nil @signup.user
|
||||
assert_equal @starting_tenants, ApplicationRecord.tenants
|
||||
end
|
||||
|
||||
test "#process does nothing if an error occurs creating the queenbee record" do
|
||||
Queenbee::Remote::Account.stubs(:create!).raises(RuntimeError, "Invalid account data")
|
||||
|
||||
assert_not @signup.process
|
||||
assert_not_empty @signup.errors[:base]
|
||||
|
||||
assert_nil @signup.tenant
|
||||
assert_nil @signup.account
|
||||
assert_nil @signup.user
|
||||
assert_equal @starting_tenants, ApplicationRecord.tenants
|
||||
end
|
||||
|
||||
test "#process does nothing if an error occurs creating the tenant" do
|
||||
ApplicationRecord.stubs(:create_tenant).raises(RuntimeError, "Tenant already exists")
|
||||
|
||||
Queenbee::Remote::Account.any_instance.expects(:cancel).once
|
||||
|
||||
assert_not @signup.process
|
||||
assert_not_empty @signup.errors[:base]
|
||||
|
||||
assert_nil @signup.tenant
|
||||
assert_nil @signup.account
|
||||
assert_nil @signup.user
|
||||
assert_equal @starting_tenants, ApplicationRecord.tenants
|
||||
end
|
||||
|
||||
test "#process does nothing if an error occurs creating the tenanted records" do
|
||||
Account.stubs(:create_with_admin_user).raises(ActiveRecord::RecordInvalid, "Validation failed: Name can't be blank")
|
||||
|
||||
Queenbee::Remote::Account.any_instance.expects(:cancel).once
|
||||
|
||||
assert_not @signup.process
|
||||
assert_not_empty @signup.errors[:base]
|
||||
|
||||
assert_nil @signup.tenant
|
||||
assert_nil @signup.account
|
||||
assert_nil @signup.user
|
||||
assert_equal @starting_tenants, ApplicationRecord.tenants
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user