mirror of
https://github.com/we-promise/sure.git
synced 2026-04-19 12:04:08 +00:00
Family sharing (#1272)
* Initial account sharing changes * Update schema.rb * Update schema.rb * Change sharing UI to modal * UX fixes and sharing controls * Scope include in finances better * Update totals.rb * Update totals.rb * Scope reports to finance account scope * Update impersonation_sessions_controller_test.rb * Review fixes * Update schema.rb * Update show.html.erb * FIX db validation * Refine edit permissions * Review items * Review * Review * Add application level helper * Critical review * Address remaining review items * Fix modals * more scoping * linter * small UI fix * Fix: Sync broadcasts push unscoped balance sheet to all users * Update sync_complete_event.rb The fix removes the sidebar broadcasts (which rendered unscoped account groups using family.balance_sheet without user context) along with the now-unused sidebar_targets, account_group, and family_balance_sheet private methods. The sidebar will still update correctly — when the sync completes, Family::SyncCompleteEvent#broadcast fires family.broadcast_refresh, which triggers a morph-based page refresh for each user with their own authenticated session, rendering properly scoped sidebar content.
This commit is contained in:
21
db/migrate/20260324100000_add_account_sharing_support.rb
Normal file
21
db/migrate/20260324100000_add_account_sharing_support.rb
Normal file
@@ -0,0 +1,21 @@
|
||||
class AddAccountSharingSupport < ActiveRecord::Migration[7.2]
|
||||
def change
|
||||
# Family-level default: whether new accounts are shared with all members by default
|
||||
add_column :families, :default_account_sharing, :string, default: "shared", null: false
|
||||
|
||||
# Account ownership: who created/owns the account
|
||||
add_reference :accounts, :owner, type: :uuid, foreign_key: { to_table: :users }, null: true, index: true
|
||||
|
||||
# Sharing join table: per-user access to accounts they don't own
|
||||
create_table :account_shares, id: :uuid, default: -> { "gen_random_uuid()" } do |t|
|
||||
t.references :account, type: :uuid, null: false, foreign_key: true
|
||||
t.references :user, type: :uuid, null: false, foreign_key: true
|
||||
t.string :permission, null: false, default: "read_only"
|
||||
t.boolean :include_in_finances, null: false, default: true
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
add_index :account_shares, [ :account_id, :user_id ], unique: true
|
||||
add_index :account_shares, [ :user_id, :include_in_finances ]
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,34 @@
|
||||
class BackfillAccountOwnersAndShares < ActiveRecord::Migration[7.2]
|
||||
def up
|
||||
# Existing families keep current behavior: all accounts shared
|
||||
Family.update_all(default_account_sharing: "shared")
|
||||
|
||||
# For each family, assign all accounts to the admin (or first user)
|
||||
Family.find_each do |family|
|
||||
admin = family.users.find_by(role: %w[admin super_admin]) || family.users.order(:created_at).first
|
||||
next unless admin
|
||||
|
||||
family.accounts.where(owner_id: nil).update_all(owner_id: admin.id)
|
||||
|
||||
# Create shares for non-owner members (preserves current full-access behavior)
|
||||
member_ids = family.users.where.not(id: admin.id).pluck(:id)
|
||||
account_ids = family.accounts.pluck(:id)
|
||||
|
||||
if member_ids.any? && account_ids.any?
|
||||
records = member_ids.product(account_ids).map do |user_id, account_id|
|
||||
{ user_id: user_id, account_id: account_id, permission: "full_control",
|
||||
include_in_finances: true, created_at: Time.current, updated_at: Time.current }
|
||||
end
|
||||
|
||||
AccountShare.upsert_all(records, unique_by: %i[account_id user_id])
|
||||
end
|
||||
end
|
||||
|
||||
# Owner is enforced at the model level via before_validation callback
|
||||
# Keeping nullable at DB level for backward compatibility with tests/seeds
|
||||
end
|
||||
|
||||
def down
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,6 @@
|
||||
class AddCheckConstraintsToSharingColumns < ActiveRecord::Migration[7.2]
|
||||
def change
|
||||
add_check_constraint :families, "default_account_sharing IN ('shared', 'private')", name: "chk_families_default_account_sharing"
|
||||
add_check_constraint :account_shares, "permission IN ('full_control', 'read_write', 'read_only')", name: "chk_account_shares_permission"
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,11 @@
|
||||
class ChangeAccountsOwnerFkToNullify < ActiveRecord::Migration[7.2]
|
||||
def up
|
||||
remove_foreign_key :accounts, :users, column: :owner_id
|
||||
add_foreign_key :accounts, :users, column: :owner_id, on_delete: :nullify
|
||||
end
|
||||
|
||||
def down
|
||||
remove_foreign_key :accounts, :users, column: :owner_id
|
||||
add_foreign_key :accounts, :users, column: :owner_id
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user