From 3d849a202acd4960f2eb05a0671e58efe39130c4 Mon Sep 17 00:00:00 2001 From: Jorge Manrubia Date: Thu, 27 Nov 2025 12:52:12 +0100 Subject: [PATCH] Move signup code back to the app, leave only queenbee hooks --- .../signup/completions_controller.rb | 24 -------- saas/config/routes.rb | 4 -- saas/lib/fizzy/saas/engine.rb | 3 + saas/lib/fizzy/saas/signup.rb | 44 +++++++++++++ ...er_test.rb => sessions_controller_test.rb} | 10 +-- .../signups/completions_controller_test.rb | 43 ------------- saas/test/models/.keep | 0 .../signup/account_name_generator_test.rb | 61 ------------------- saas/test/models/signup_test.rb | 60 ++++++++---------- 9 files changed, 73 insertions(+), 176 deletions(-) delete mode 100644 saas/app/controllers/signup/completions_controller.rb create mode 100644 saas/lib/fizzy/saas/signup.rb rename saas/test/controllers/{saas_sessions_controller_test.rb => sessions_controller_test.rb} (52%) delete mode 100644 saas/test/controllers/signups/completions_controller_test.rb delete mode 100644 saas/test/models/.keep delete mode 100644 saas/test/models/signup/account_name_generator_test.rb diff --git a/saas/app/controllers/signup/completions_controller.rb b/saas/app/controllers/signup/completions_controller.rb deleted file mode 100644 index d7f09c086..000000000 --- a/saas/app/controllers/signup/completions_controller.rb +++ /dev/null @@ -1,24 +0,0 @@ -class Signup::CompletionsController < ApplicationController - layout "public" - - disallow_account_scope - - def new - @signup = Signup.new(identity: Current.identity) - end - - def create - @signup = Signup.new(signup_params) - - if @signup.complete - redirect_to landing_url(script_name: @signup.account.slug) - else - render :new, status: :unprocessable_entity - end - end - - private - def signup_params - params.expect(signup: %i[ full_name ]).with_defaults(identity: Current.identity) - end -end diff --git a/saas/config/routes.rb b/saas/config/routes.rb index 2b9639edb..1f720e87d 100644 --- a/saas/config/routes.rb +++ b/saas/config/routes.rb @@ -1,9 +1,5 @@ Fizzy::Saas::Engine.routes.draw do get "/signup/new", to: redirect("/session/new") - namespace :signup do - resource :completion, only: %i[ new create ] - end - Queenbee.routes(self) end diff --git a/saas/lib/fizzy/saas/engine.rb b/saas/lib/fizzy/saas/engine.rb index 3c8db7670..c0941f84e 100644 --- a/saas/lib/fizzy/saas/engine.rb +++ b/saas/lib/fizzy/saas/engine.rb @@ -1,5 +1,6 @@ require_relative "metrics" require_relative "transaction_pinning" +require_relative "signup" module Fizzy module Saas @@ -50,6 +51,8 @@ module Fizzy end config.to_prepare do + ::Signup.prepend(Fizzy::Saas::Signup) + Queenbee::Subscription.short_names = Subscription::SHORT_NAMES # Default to local dev QB token if not set diff --git a/saas/lib/fizzy/saas/signup.rb b/saas/lib/fizzy/saas/signup.rb new file mode 100644 index 000000000..e414d63f8 --- /dev/null +++ b/saas/lib/fizzy/saas/signup.rb @@ -0,0 +1,44 @@ +module Fizzy + module Saas + module Signup + extend ActiveSupport::Concern + + included do + attr_reader :queenbee_account + end + + private + def create_tenant + @queenbee_account = Queenbee::Remote::Account.create!(queenbee_account_attributes) + @queenbee_account.id.to_s + end + + def handle_account_creation_error(error) + @queenbee_account&.cancel + @queenbee_account = nil + end + + def queenbee_account_attributes + {}.tap do |attributes| + attributes[:product_name] = "fizzy" + attributes[:name] = generate_account_name + attributes[:owner_name] = full_name + attributes[:owner_email] = email_address + + attributes[:trial] = true + attributes[:subscription] = subscription_attributes + attributes[:remote_request] = request_attributes + + # # TODO: Terms of Service + # attributes[:terms_of_service] = true + + # We've confirmed the email + attributes[:auto_allow] = true + + # Tell Queenbee to skip the request to create a local account. We've created it ourselves. + attributes[:skip_remote] = true + end + end + end + end +end diff --git a/saas/test/controllers/saas_sessions_controller_test.rb b/saas/test/controllers/sessions_controller_test.rb similarity index 52% rename from saas/test/controllers/saas_sessions_controller_test.rb rename to saas/test/controllers/sessions_controller_test.rb index 639d6353e..6af58e63e 100644 --- a/saas/test/controllers/saas_sessions_controller_test.rb +++ b/saas/test/controllers/sessions_controller_test.rb @@ -1,23 +1,17 @@ require "test_helper" -class SaasSessionsControllerTest < ActionDispatch::IntegrationTest +class Fizzy::Saas::SessionsControllerTest < ActionDispatch::IntegrationTest test "create for a new user" do untenanted do assert_difference -> { Identity.count }, +1 do assert_difference -> { MagicLink.count }, +1 do post session_path, - params: { email_address: "nonexistent-#{SecureRandom.hex(6)}@example.com" }, - headers: http_basic_auth_headers("testname", "testpassword") + params: { email_address: "nonexistent-#{SecureRandom.hex(6)}@example.com" } end end assert_redirected_to session_magic_link_path end end - - private - def http_basic_auth_headers(user, password) - { "Authorization" => ActionController::HttpAuthentication::Basic.encode_credentials(user, password) } - end end diff --git a/saas/test/controllers/signups/completions_controller_test.rb b/saas/test/controllers/signups/completions_controller_test.rb deleted file mode 100644 index 49628a188..000000000 --- a/saas/test/controllers/signups/completions_controller_test.rb +++ /dev/null @@ -1,43 +0,0 @@ -require "test_helper" - -class Signup::CompletionsControllerTest < ActionDispatch::IntegrationTest - setup do - @signup = Signup.new(email_address: "newuser@example.com", full_name: "New User") - - @signup.create_identity || raise("Failed to create identity") - - sign_in_as @signup.identity - end - - test "new" do - untenanted do - get saas.new_signup_completion_path - end - - assert_response :success - end - - test "create" do - untenanted do - post saas.signup_completion_path, params: { - signup: { - full_name: @signup.full_name - } - } - end - - assert_response :redirect, "Valid params should redirect" - end - - test "create with invalid params" do - untenanted do - post saas.signup_completion_path, params: { - signup: { - full_name: "" - } - } - end - - assert_response :unprocessable_entity, "Invalid params should return unprocessable entity" - end -end diff --git a/saas/test/models/.keep b/saas/test/models/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/saas/test/models/signup/account_name_generator_test.rb b/saas/test/models/signup/account_name_generator_test.rb deleted file mode 100644 index e4d8e0d80..000000000 --- a/saas/test/models/signup/account_name_generator_test.rb +++ /dev/null @@ -1,61 +0,0 @@ -require "test_helper" - -class Signup::AccountNameGeneratorTest < ActiveSupport::TestCase - setup do - @identity = ::Identity.create!(email_address: "newart.userbaum@example.com") - @name = "Newart userbaum" - @generator = Signup::AccountNameGenerator.new(identity: @identity, name: @name) - end - - test "generate" do - account_name = @generator.generate - assert_equal "Newart's Fizzy", account_name, "The 1st account doesn't have 1st in the name" - - first_account = ::Account.create!(external_account_id: "1st", name: account_name) - ::Current.without_account do - @identity.users.create!(account: first_account, name: @name) - @identity.reload - end - - account_name = @generator.generate - assert_equal "Newart's 2nd Fizzy", account_name - - second_account = ::Account.create!(external_account_id: "2nd", name: account_name) - ::Current.without_account do - @identity.users.create!(account: second_account, name: @name) - @identity.reload - end - - account_name = @generator.generate - assert_equal "Newart's 3rd Fizzy", account_name - - third_account = ::Account.create!(external_account_id: "3rd", name: account_name) - ::Current.without_account do - @identity.users.create!(account: third_account, name: @name) - @identity.reload - end - - account_name = @generator.generate - assert_equal "Newart's 4th Fizzy", account_name - - fourth_account = ::Account.create!(external_account_id: "4th", name: account_name) - ::Current.without_account do - @identity.users.create!(account: fourth_account, name: @name) - @identity.reload - end - - account_name = @generator.generate - assert_equal "Newart's 5th Fizzy", account_name - end - - test "generate continues from the previous highest index" do - account = ::Account.create!(external_account_id: "12th", name: "Newart's 12th Fizzy") - ::Current.without_account do - @identity.users.create!(account: account, name: @name) - @identity.reload - end - - account_name = @generator.generate - assert_equal "Newart's 13th Fizzy", account_name - end -end diff --git a/saas/test/models/signup_test.rb b/saas/test/models/signup_test.rb index 0751f4c91..3754906af 100644 --- a/saas/test/models/signup_test.rb +++ b/saas/test/models/signup_test.rb @@ -1,37 +1,14 @@ require "test_helper" -class SignupTest < ActiveSupport::TestCase - test "#create_identity" do - signup = Signup.new(email_address: "brian@example.com") +class Fizzy::Saas::SignupTest < ActiveSupport::TestCase + test "#complete creates queenbee account and uses its id as tenant" do + queenbee_account = mock("queenbee_account") + queenbee_account.stubs(:id).returns(123456) - assert_difference -> { ::Identity.count }, 1 do - assert_difference -> { ::MagicLink.count }, 1 do - assert signup.create_identity - end - end + Queenbee::Remote::Account.expects(:create!).once.returns(queenbee_account) + Account.any_instance.expects(:setup_customer_template).once - assert_empty signup.errors - assert signup.identity - assert signup.identity.persisted? - - signup_existing = Signup.new(email_address: "brian@example.com") - - assert_no_difference -> { ::Identity.count } do - assert_difference -> { ::MagicLink.count }, 1 do - assert signup_existing.create_identity, "Should send magic link for existing identity" - end - end - - signup_invalid = Signup.new(email_address: "") - assert_raises do - signup_invalid.create_identity - end - end - - test "#complete" do - ::Account.any_instance.expects(:setup_customer_template).once - - ::Current.without_account do + Current.without_account do signup = Signup.new( full_name: "Kevin", identity: identities(:kevin) @@ -40,15 +17,26 @@ class SignupTest < ActiveSupport::TestCase assert signup.complete assert signup.account - assert signup.user - assert_equal "Kevin", signup.user.name + assert_equal "123456", signup.account.external_account_id.to_s + end + end - signup_invalid = Signup.new( - full_name: "", + test "#complete calls cancel on queenbee account when account creation fails" do + queenbee_account = mock("queenbee_account") + queenbee_account.stubs(:id).returns(789012) + queenbee_account.expects(:cancel).once + + Queenbee::Remote::Account.expects(:create!).once.returns(queenbee_account) + Account.any_instance.stubs(:setup_customer_template).raises(StandardError.new("Account setup failed")) + + Current.without_account do + signup = Signup.new( + full_name: "Kevin", identity: identities(:kevin) ) - assert_not signup_invalid.complete - assert_not_empty signup_invalid.errors[:full_name] + + assert_not signup.complete + assert_includes signup.errors[:base], "Something went wrong, and we couldn't create your account. Please give it another try." end end end