Rename the queenbee_id and signal_user_id columns

to be more generic for the open-source release.

Find the signal account via Account#external_account

Find the signal user via User#external_user
This commit is contained in:
Mike Dalessio
2025-09-15 13:05:36 -04:00
parent 60e515e462
commit d5a4239d19
23 changed files with 111 additions and 92 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ class Account < ApplicationRecord
has_many_attached :uploads
def slug
"/#{queenbee_id}"
"/#{tenant_id}"
end
def setup_basic_template
+2 -6
View File
@@ -17,10 +17,6 @@ class NotificationPusher
end
private
def account_prefix
"/#{Account.sole.queenbee_id}"
end
def should_push?
notification.user.push_subscriptions.any? &&
!notification.creator.system? &&
@@ -91,7 +87,7 @@ class NotificationPusher
{
title: "New notification",
body: "You have a new notification",
path: "#{account_prefix}#{notifications_path}"
path: "#{Account.sole.slug}#{notifications_path}"
}
end
@@ -113,6 +109,6 @@ class NotificationPusher
end
def card_path(card)
"#{account_prefix}#{Rails.application.routes.url_helpers.card_path(card)}"
"#{Account.sole.slug}#{Rails.application.routes.url_helpers.card_path(card)}"
end
end
+2 -2
View File
@@ -4,8 +4,8 @@ echo "Login with david@37signals.com / secret123456 to:"
bin/rails runner - <<EOF
ApplicationRecord.with_each_tenant do |tenant|
next unless tenant =~ /\A\d+\z/
if Account.sole.queenbee_id
puts " - #{Account.sole.name}: http://fizzy.localhost:3006/#{Account.sole.queenbee_id}"
if Account.sole.tenant_id
puts " - #{Account.sole.name}: http://fizzy.localhost:3006/#{Account.sole.tenant_id}"
end
end
EOF
@@ -0,0 +1,6 @@
class Rename37idColumns < ActiveRecord::Migration[8.1]
def change
rename_column :users, :signal_user_id, :external_user_id
rename_column :accounts, :queenbee_id, :tenant_id
end
end
Generated
+5 -5
View File
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[8.1].define(version: 2025_09_12_123359) do
ActiveRecord::Schema[8.1].define(version: 2025_09_15_170056) do
create_table "accesses", force: :cascade do |t|
t.datetime "accessed_at"
t.integer "collection_id", null: false
@@ -28,9 +28,9 @@ ActiveRecord::Schema[8.1].define(version: 2025_09_12_123359) do
t.datetime "created_at", null: false
t.string "join_code"
t.string "name", null: false
t.integer "queenbee_id"
t.integer "tenant_id"
t.datetime "updated_at", null: false
t.index ["queenbee_id"], name: "index_accounts_on_queenbee_id", unique: true
t.index ["tenant_id"], name: "index_accounts_on_tenant_id", unique: true
end
create_table "action_text_rich_texts", force: :cascade do |t|
@@ -436,14 +436,14 @@ ActiveRecord::Schema[8.1].define(version: 2025_09_12_123359) do
t.boolean "active", default: true, null: false
t.datetime "created_at", null: false
t.string "email_address"
t.integer "external_user_id"
t.string "name", null: false
t.string "password_digest"
t.string "role", default: "member", null: false
t.integer "signal_user_id"
t.datetime "updated_at", null: false
t.index ["email_address"], name: "index_users_on_email_address", unique: true
t.index ["external_user_id"], name: "index_users_on_external_user_id", unique: true
t.index ["role"], name: "index_users_on_role"
t.index ["signal_user_id"], name: "index_users_on_signal_user_id", unique: true
end
create_table "watches", force: :cascade do |t|
+20 -20
View File
@@ -125,7 +125,7 @@ columns:
comment:
- !ruby/object:ActiveRecord::ConnectionAdapters::SQLite3::Column
auto_increment:
name: queenbee_id
name: tenant_id
cast_type: *3
sql_type_metadata: *4
'null': true
@@ -1269,6 +1269,16 @@ columns:
default_function:
collation:
comment:
- !ruby/object:ActiveRecord::ConnectionAdapters::SQLite3::Column
auto_increment:
name: external_user_id
cast_type: *3
sql_type_metadata: *4
'null': true
default:
default_function:
collation:
comment:
- *6
- *10
- !ruby/object:ActiveRecord::ConnectionAdapters::SQLite3::Column
@@ -1291,16 +1301,6 @@ columns:
default_function:
collation:
comment:
- !ruby/object:ActiveRecord::ConnectionAdapters::SQLite3::Column
auto_increment:
name: signal_user_id
cast_type: *3
sql_type_metadata: *4
'null': true
default:
default_function:
collation:
comment:
- *9
watches:
- *23
@@ -1520,10 +1520,10 @@ indexes:
accounts:
- !ruby/object:ActiveRecord::ConnectionAdapters::IndexDefinition
table: accounts
name: index_accounts_on_queenbee_id
name: index_accounts_on_tenant_id
unique: true
columns:
- queenbee_id
- tenant_id
lengths: {}
orders: {}
opclasses: {}
@@ -2928,10 +2928,10 @@ indexes:
valid: true
- !ruby/object:ActiveRecord::ConnectionAdapters::IndexDefinition
table: users
name: index_users_on_role
unique: false
name: index_users_on_external_user_id
unique: true
columns:
- role
- external_user_id
lengths: {}
orders: {}
opclasses: {}
@@ -2944,10 +2944,10 @@ indexes:
valid: true
- !ruby/object:ActiveRecord::ConnectionAdapters::IndexDefinition
table: users
name: index_users_on_signal_user_id
unique: true
name: index_users_on_role
unique: false
columns:
- signal_user_id
- role
lengths: {}
orders: {}
opclasses: {}
@@ -3009,4 +3009,4 @@ indexes:
comment:
valid: true
workflows: []
version: 20250912123359
version: 20250915170056
+11 -11
View File
@@ -12,18 +12,18 @@ end
def create_tenant(signal_account_name, bare: false)
if bare
queenbee_id = Digest::SHA256.hexdigest(signal_account_name)[0..8].to_i(16)
tenant_id = Digest::SHA256.hexdigest(signal_account_name)[0..8].to_i(16)
elsif Rails.application.config.x.local_authentication
queenbee_id = ActiveRecord::FixtureSet.identify signal_account_name
tenant_id = ActiveRecord::FixtureSet.identify signal_account_name
else
signal_account = SignalId::Account.find_by_product_and_name!("fizzy", signal_account_name)
queenbee_id = signal_account.queenbee_id
tenant_id = signal_account.queenbee_id
end
ApplicationRecord.destroy_tenant queenbee_id
ApplicationRecord.create_tenant(queenbee_id) do
ApplicationRecord.destroy_tenant tenant_id
ApplicationRecord.create_tenant(tenant_id) do
account = if bare || Rails.application.config.x.local_authentication
Account.create(name: signal_account_name, queenbee_id: queenbee_id).tap do
Account.create(name: signal_account_name, tenant_id: tenant_id).tap do
User.create!(
name: "David Heinemeier Hansson",
email_address: "david@37signals.com",
@@ -31,12 +31,12 @@ def create_tenant(signal_account_name, bare: false)
)
end
else
Account.create_with_admin_user(queenbee_id: queenbee_id)
Account.create_with_admin_user(tenant_id: tenant_id)
end
account.setup_basic_template
end
ApplicationRecord.current_tenant = queenbee_id
ApplicationRecord.current_tenant = tenant_id
end
def find_or_create_user(full_name, email_address)
@@ -63,16 +63,16 @@ def find_or_create_user(full_name, email_address)
)
end
signal_account = Account.sole.signal_account
signal_account = Account.sole.external_account
signal_user = SignalId::User.find_or_create_by!(identity: signal_identity, account: signal_account)
if user = User.find_by(signal_user_id: signal_user.id)
if user = User.find_by(external_user_id: signal_user.id)
user.password = "secret123456"
user.save!
user
else
User.create!(
signal_user_id: signal_user.id,
external_user_id: signal_user.id,
name: signal_identity.name,
email_address: signal_identity.email_address,
password: "secret123456"
@@ -7,7 +7,7 @@ class Sessions::LaunchpadController < ApplicationController
end
def update
user = Account.sole.signal_account.authenticate(sig: @sig).try(:peer)
user = Account.sole.external_account.authenticate(sig: @sig).try(:peer)
if user.present? && user.active?
start_new_session_for user
redirect_to after_authentication_url
@@ -30,7 +30,7 @@ class Signup::BaseController < ApplicationController
end
def redirect_to_account(account)
redirect_to account.signal_account.owner.remote_login_url(proceed_to: root_path),
redirect_to account.external_account.owner.remote_login_url(proceed_to: root_path),
allow_other_host: true
end
end
@@ -2,22 +2,27 @@ module Account::SignalAccount
extend ActiveSupport::Concern
prepended do
belongs_to :signal_account, class_name: "SignalId::Account", primary_key: :queenbee_id, foreign_key: :queenbee_id, optional: true
# the tenant_id column is the SignalId::Account's queenbee_id
belongs_to :external_account, class_name: "SignalId::Account", primary_key: :queenbee_id, foreign_key: :tenant_id, optional: true
end
class_methods do
def create_with_admin_user(queenbee_id:)
new(queenbee_id: queenbee_id).tap do |account|
def find_by_queenbee_id(queenbee_id)
find_by(tenant_id: queenbee_id)
end
def create_with_admin_user(tenant_id:)
new(tenant_id:).tap do |account|
SignalId::Database.on_master do
account.name = account.signal_account.name
account.name = account.external_account.name
account.save!
User.create!(
name: account.signal_account.owner.name,
email_address: account.signal_account.owner.email_address,
signal_user_id: account.signal_account.owner.id,
role: "admin",
password: SecureRandom.hex(36) # TODO: remove password column?
name: account.external_account.owner.name,
email_address: account.external_account.owner.email_address,
external_user_id: account.external_account.owner.id,
role: "admin",
password: SecureRandom.hex(36) # TODO: remove password column?
)
end
end
+1 -1
View File
@@ -18,7 +18,7 @@ module Launchpad
def product_account_path(path = nil, product: false, account: nil)
product_path = "/fizzy" if product || account
account_path = "/#{account.signal_account.id}" if account
account_path = "/#{account.external_account.id}" if account
[ product_path, account_path, path ].compact.join
end
end
+1 -1
View File
@@ -85,7 +85,7 @@ class Signup
def create_tenant(destroy_existing_tenant: false, &block)
ApplicationRecord.destroy_tenant(tenant_name) if destroy_existing_tenant
ApplicationRecord.create_tenant(tenant_name) do
@account = Account.create_with_admin_user(queenbee_id: queenbee_account.id)
@account = Account.create_with_admin_user(tenant_id: queenbee_account.id)
@account.setup_basic_template
@user = User.first
end
@@ -2,11 +2,18 @@ module User::SignalUser
extend ActiveSupport::Concern
prepended do
belongs_to :signal_user, dependent: :destroy, class_name: "SignalId::User", optional: true
# the external_user_id is the SignalId::User id
belongs_to :external_user, dependent: :destroy, class_name: "SignalId::User", optional: true
end
class_methods do
def find_by_signal_user_id(signal_user_id)
find_by(external_user_id: signal_user_id)
end
end
def deactivate
super
SignalId::Database.on_master { signal_user&.destroy }
SignalId::Database.on_master { external_user&.destroy }
end
end
@@ -15,7 +15,7 @@ class Sessions::LaunchpadControllerTest < ActionDispatch::IntegrationTest
test "create establishes a session when the sig is valid" do
user = users(:david)
put saas.session_launchpad_path(params: { sig: user.signal_user.perishable_signature })
put saas.session_launchpad_path(params: { sig: user.external_user.perishable_signature })
assert_redirected_to root_url
assert parsed_cookies.signed[:session_token]
@@ -25,7 +25,7 @@ class Sessions::LaunchpadControllerTest < ActionDispatch::IntegrationTest
user = users(:david)
user.update! active: false
put saas.session_launchpad_path(params: { sig: user.signal_user.perishable_signature })
put saas.session_launchpad_path(params: { sig: user.external_user.perishable_signature })
assert_response :unauthorized
end
@@ -26,7 +26,7 @@ class Signup::AccountsControllerTest < ActionDispatch::IntegrationTest
assert_select "div.alert--error", text: /you need to choose a password/i
end
test "create for a new " do
test "create for a new identity" do
integration_session.default_url_options[:script_name] = "" # no tenant
assert_difference -> { SignalId::Identity.count }, +1 do
@@ -9,20 +9,24 @@ class Account::SignalAccountTest < ActiveSupport::TestCase
end
test "belongs to a signal_account via a shared queenbee_id" do
assert_not_nil @account.queenbee_id
assert_equal @account.queenbee_id, Account.new(signal_account: @account.signal_account).queenbee_id
assert_equal @account.signal_account, Account.new(queenbee_id: @account.queenbee_id).signal_account
assert_not_nil @account.tenant_id
assert_equal @account.tenant_id, Account.new(external_account: @account.external_account).tenant_id
assert_equal @account.external_account, Account.new(tenant_id: @account.tenant_id).external_account
end
test "peering" do
assert_equal @account, @account.external_account.peer
end
test ".create_with_admin_user creates a new local account and user peers" do
ApplicationRecord.create_tenant("account-create-with-dependents") do
signal_account = signal_accounts(:honcho_fizzy)
account = Account.create_with_admin_user(queenbee_id: signal_account.queenbee_id)
account = Account.create_with_admin_user(tenant_id: signal_account.queenbee_id)
assert_not_nil account
assert account.persisted?
assert_equal 1, Account.count
assert_equal signal_account.queenbee_id, account.queenbee_id
assert_equal signal_account.queenbee_id, account.tenant_id
assert_equal signal_account.name, account.name
assert_equal account, signal_account.peer
@@ -30,7 +34,7 @@ class Account::SignalAccountTest < ActiveSupport::TestCase
User.first.tap do |user|
assert signal_account.owner.name, user.name
assert signal_account.owner.email_address, user.email_address
assert signal_account.owner.id, user.signal_user_id
assert signal_account.owner.id, user.external_user_id
assert_equal "admin", user.role
assert_equal user, signal_account.owner.peer
end
+2 -2
View File
@@ -42,7 +42,7 @@ class SignupTest < ActiveSupport::TestCase
assert @signup.user
assert @signup.user.persisted?
assert_equal @signup.user.signal_user, @signup.signal_account.owner
assert_equal @signup.user.external_user, @signup.signal_account.owner
assert_equal @signup.queenbee_account.id.to_s, @signup.tenant_name
assert_includes ApplicationRecord.tenants, @signup.tenant_name
@@ -86,7 +86,7 @@ class SignupTest < ActiveSupport::TestCase
assert @signup.user
assert @signup.user.persisted?
assert_equal @signup.user.signal_user, @signup.signal_account.owner
assert_equal @signup.user.external_user, @signup.signal_account.owner
assert_equal @signup.queenbee_account.id.to_s, @signup.tenant_name
assert_includes ApplicationRecord.tenants, @signup.tenant_name
@@ -6,7 +6,17 @@ class User::SignalUserTest < ActiveSupport::TestCase
end
test "belongs to a Signal::User" do
assert_not_nil @user.signal_user_id
assert_equal signal_users("37s_fizzy_david"), @user.signal_user
assert_not_nil @user.external_user_id
assert_equal signal_users("37s_fizzy_david"), @user.external_user
end
test "peering" do
assert_equal @user, @user.external_user.peer
end
test "deactivate clears signal user" do
users(:jz).deactivate
assert_nil users(:jz).reload.external_user
end
end
-9
View File
@@ -1,9 +0,0 @@
require "test_helper"
class UserTest < ActiveSupport::TestCase
test "deactivate clears signal user" do
users(:jz).deactivate
assert_nil users(:jz).reload.signal_user
end
end
+1 -1
View File
@@ -6,7 +6,7 @@ module ActiveSupport
include SignalId::Testing
def saas_extension_sign_in_as(user)
put saas.session_launchpad_path, params: { sig: user.signal_user.perishable_signature }
put saas.session_launchpad_path, params: { sig: user.external_user.perishable_signature }
end
end
end
+2 -2
View File
@@ -1,6 +1,6 @@
37s:
name: 37signals
join_code: "ejpP-THlQ-Cc2f"
<% if Account.reflect_on_association :signal_account %>
queenbee_id: <%= ActiveRecord::FixtureSet.identify :'37s_fizzy' %>
<% if Account.reflect_on_association :external_account %>
tenant_id: <%= ActiveRecord::FixtureSet.identify :'37s_fizzy' %>
<% end %>
+6 -6
View File
@@ -5,8 +5,8 @@ david:
email_address: david@37signals.com
password_digest: <%= digest %>
role: member
<% if User.reflect_on_association :signal_user %>
signal_user: 37s_fizzy_david
<% if User.reflect_on_association :external_user %>
external_user: 37s_fizzy_david
<% end %>
jz:
@@ -14,8 +14,8 @@ jz:
email_address: jz@37signals.com
password_digest: <%= digest %>
role: member
<% if User.reflect_on_association :signal_user %>
signal_user: 37s_fizzy_jzimdars
<% if User.reflect_on_association :external_user %>
external_user: 37s_fizzy_jzimdars
<% end %>
kevin:
@@ -23,8 +23,8 @@ kevin:
email_address: kevin@37signals.com
password_digest: <%= digest %>
role: admin
<% if User.reflect_on_association :signal_user %>
signal_user: 37s_fizzy_kevin
<% if User.reflect_on_association :external_user %>
external_user: 37s_fizzy_kevin
<% end %>
system:
+1 -1
View File
@@ -3,6 +3,6 @@ require "test_helper"
class AccountTest < ActiveSupport::TestCase
test "slug" do
account = Account.sole
assert_equal "/#{account.queenbee_id}", account.slug
assert_equal "/#{account.tenant_id}", account.slug
end
end