diff --git a/app/models/account.rb b/app/models/account.rb index 8efc6ae32..dbcd64619 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -1,6 +1,8 @@ class Account < ApplicationRecord include Entropic, Seedeable + has_one :join_code + has_many_attached :uploads after_create :create_join_code @@ -9,9 +11,9 @@ class Account < ApplicationRecord class << self def create_with_admin_user(account:, owner:) - create!(**account).tap do - User.system - User.create!(**owner.reverse_merge(role: "admin")) + create!(**account).tap do |account| + User.create!(account: account, role: :system, name: "System") + User.create!(**owner.reverse_merge(role: "admin", account: account)) end end end @@ -24,9 +26,4 @@ class Account < ApplicationRecord def slug "/#{external_account_id}" end - - private - def create_join_code - Account::JoinCode.create! - end end diff --git a/app/models/account/join_code.rb b/app/models/account/join_code.rb index 69d681197..b647c70ad 100644 --- a/app/models/account/join_code.rb +++ b/app/models/account/join_code.rb @@ -1,6 +1,8 @@ class Account::JoinCode < ApplicationRecord CODE_LENGTH = 12 + belongs_to :account + scope :active, -> { where("usage_count < usage_limit") } before_create :generate_code, if: -> { code.blank? } diff --git a/app/models/board.rb b/app/models/board.rb index 71ff693fb..4b5752604 100644 --- a/app/models/board.rb +++ b/app/models/board.rb @@ -1,6 +1,7 @@ class Board < ApplicationRecord include Accessible, AutoPostponing, Broadcastable, Cards, Entropic, Filterable, Publishable, Triageable + belongs_to :account, default: -> { Current.account } belongs_to :creator, class_name: "User", default: -> { Current.user } has_rich_text :public_description diff --git a/app/models/card.rb b/app/models/card.rb index b609dc029..fb1025d4d 100644 --- a/app/models/card.rb +++ b/app/models/card.rb @@ -3,6 +3,7 @@ class Card < ApplicationRecord Golden, Mentions, Multistep, Pinnable, Postponable, Promptable, Readable, Searchable, Stallable, Statuses, Taggable, Triageable, Watchable + belongs_to :account, default: -> { Current.account } belongs_to :board, touch: true belongs_to :creator, class_name: "User", default: -> { Current.user } diff --git a/app/models/column.rb b/app/models/column.rb index bf136969c..5b3815561 100644 --- a/app/models/column.rb +++ b/app/models/column.rb @@ -1,6 +1,7 @@ class Column < ApplicationRecord include Colored, Positioned + belongs_to :account, default: -> { Current.account } belongs_to :board, touch: true has_many :cards, dependent: :nullify diff --git a/app/models/comment.rb b/app/models/comment.rb index 4428c8e48..d67ef430b 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -1,7 +1,8 @@ class Comment < ApplicationRecord include Attachments, Eventable, Mentions, Promptable, Searchable - belongs_to :card, touch: true + belongs_to :account, default: -> { Current.account } + belongs_to :card, touch: true belongs_to :creator, class_name: "User", default: -> { Current.user } has_many :reactions, dependent: :delete_all diff --git a/app/models/event.rb b/app/models/event.rb index 74a3bb20f..cca00d66f 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -1,6 +1,7 @@ class Event < ApplicationRecord include Notifiable, Particulars, Promptable + belongs_to :account, default: -> { Current.account } belongs_to :board belongs_to :creator, class_name: "User" belongs_to :eventable, polymorphic: true diff --git a/app/models/filter.rb b/app/models/filter.rb index 459d18621..005e04e28 100644 --- a/app/models/filter.rb +++ b/app/models/filter.rb @@ -1,8 +1,8 @@ class Filter < ApplicationRecord include Fields, Params, Resources, Summarized + belongs_to :account, default: -> { Current.account } belongs_to :creator, class_name: "User", default: -> { Current.user } - has_one :account, through: :creator class << self def from_params(params) diff --git a/app/models/mention.rb b/app/models/mention.rb index 54a20e0ce..d4fdd479d 100644 --- a/app/models/mention.rb +++ b/app/models/mention.rb @@ -1,6 +1,7 @@ class Mention < ApplicationRecord include Notifiable + belongs_to :account, default: -> { Current.account } belongs_to :source, polymorphic: true belongs_to :mentioner, class_name: "User" belongs_to :mentionee, class_name: "User", inverse_of: :mentions diff --git a/app/models/notification.rb b/app/models/notification.rb index 0fa2350ee..fa9baaf48 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -1,6 +1,7 @@ class Notification < ApplicationRecord include PushNotifiable + belongs_to :account, default: -> { Current.account } belongs_to :user belongs_to :creator, class_name: "User" belongs_to :source, polymorphic: true diff --git a/app/models/notification/bundle.rb b/app/models/notification/bundle.rb index 93110f87b..ab02fc93d 100644 --- a/app/models/notification/bundle.rb +++ b/app/models/notification/bundle.rb @@ -1,4 +1,5 @@ class Notification::Bundle < ApplicationRecord + belongs_to :account, default: -> { Current.account } belongs_to :user enum :status, %i[ pending processing delivered ] diff --git a/app/models/push/subscription.rb b/app/models/push/subscription.rb index ebc12c70d..5776ef25f 100644 --- a/app/models/push/subscription.rb +++ b/app/models/push/subscription.rb @@ -1,4 +1,5 @@ class Push::Subscription < ApplicationRecord + belongs_to :account, default: -> { Current.account } belongs_to :user def notification(**params) diff --git a/app/models/reaction.rb b/app/models/reaction.rb index d70f8333b..dfb3e3245 100644 --- a/app/models/reaction.rb +++ b/app/models/reaction.rb @@ -1,4 +1,5 @@ class Reaction < ApplicationRecord + belongs_to :account, default: -> { Current.account } belongs_to :comment, touch: true belongs_to :reacter, class_name: "User", default: -> { Current.user } diff --git a/app/models/step.rb b/app/models/step.rb index c2063dfaa..c3cf12378 100644 --- a/app/models/step.rb +++ b/app/models/step.rb @@ -1,4 +1,5 @@ class Step < ApplicationRecord + belongs_to :account, default: -> { Current.account } belongs_to :card, touch: true scope :completed, -> { where(completed: true) } diff --git a/app/models/tag.rb b/app/models/tag.rb index 9c6e6c260..192f0b86e 100644 --- a/app/models/tag.rb +++ b/app/models/tag.rb @@ -1,6 +1,7 @@ class Tag < ApplicationRecord include Attachable, Filterable + belongs_to :account, default: -> { Current.account } has_many :taggings, dependent: :destroy has_many :cards, through: :taggings diff --git a/app/models/user.rb b/app/models/user.rb index fabb0224a..b248b74d8 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -5,6 +5,7 @@ class User < ApplicationRecord has_one_attached :avatar + belongs_to :account, default: -> { Current.account } belongs_to :membership, optional: true has_one :identity, through: :membership, disable_joins: true diff --git a/app/models/webhook.rb b/app/models/webhook.rb index 25249abab..13b92f389 100644 --- a/app/models/webhook.rb +++ b/app/models/webhook.rb @@ -25,6 +25,7 @@ class Webhook < ApplicationRecord has_many :deliveries, dependent: :delete_all has_one :delinquency_tracker, dependent: :delete + belongs_to :account, default: -> { Current.account } belongs_to :board serialize :subscribed_actions, type: Array, coder: JSON diff --git a/db/cable_schema.rb b/db/cable_schema.rb index 310946672..58afcedf5 100644 --- a/db/cable_schema.rb +++ b/db/cable_schema.rb @@ -11,11 +11,11 @@ # It's strongly recommended that you check this file into your version control system. ActiveRecord::Schema[8.2].define(version: 1) do - create_table "solid_cable_messages", force: :cascade do |t| + create_table "solid_cable_messages", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.binary "channel", limit: 1024, null: false - t.integer "channel_hash", limit: 8, null: false + t.bigint "channel_hash", null: false t.datetime "created_at", null: false - t.binary "payload", limit: 536870912, null: false + t.binary "payload", size: :long, null: false t.index ["channel"], name: "index_solid_cable_messages_on_channel" t.index ["channel_hash"], name: "index_solid_cable_messages_on_channel_hash" t.index ["created_at"], name: "index_solid_cable_messages_on_created_at" diff --git a/db/cache_schema.rb b/db/cache_schema.rb index 3af459803..3c8a30bdc 100644 --- a/db/cache_schema.rb +++ b/db/cache_schema.rb @@ -11,12 +11,12 @@ # It's strongly recommended that you check this file into your version control system. ActiveRecord::Schema[8.2].define(version: 1) do - create_table "solid_cache_entries", force: :cascade do |t| - t.integer "byte_size", limit: 4, null: false + create_table "solid_cache_entries", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.integer "byte_size", null: false t.datetime "created_at", null: false t.binary "key", limit: 1024, null: false - t.integer "key_hash", limit: 8, null: false - t.binary "value", limit: 536870912, null: false + t.bigint "key_hash", null: false + t.binary "value", size: :long, null: false t.index ["byte_size"], name: "index_solid_cache_entries_on_byte_size" t.index ["key_hash", "byte_size"], name: "index_solid_cache_entries_on_key_hash_and_byte_size" t.index ["key_hash"], name: "index_solid_cache_entries_on_key_hash", unique: true diff --git a/db/migrate/20251110175021_add_account_id_everywhere.rb b/db/migrate/20251110175021_add_account_id_everywhere.rb new file mode 100644 index 000000000..22d92f846 --- /dev/null +++ b/db/migrate/20251110175021_add_account_id_everywhere.rb @@ -0,0 +1,20 @@ +class AddAccountIdEverywhere < ActiveRecord::Migration[8.2] + def change + add_column :account_join_codes, :account_id, :integer + add_column :users, :account_id, :integer + add_column :boards, :account_id, :integer + add_column :columns, :account_id, :integer + add_column :cards, :account_id, :integer + add_column :steps, :account_id, :integer + add_column :comments, :account_id, :integer + add_column :mentions, :account_id, :integer + add_column :notifications, :account_id, :integer + add_column :notification_bundles, :account_id, :integer + add_column :filters, :account_id, :integer + add_column :events, :account_id, :integer + add_column :reactions, :account_id, :integer + add_column :tags, :account_id, :integer + add_column :webhooks, :account_id, :integer + add_column :push_subscriptions, :account_id, :integer + end +end diff --git a/db/queue_schema.rb b/db/queue_schema.rb index dd046ba9b..c4713f8d1 100644 --- a/db/queue_schema.rb +++ b/db/queue_schema.rb @@ -11,7 +11,7 @@ # It's strongly recommended that you check this file into your version control system. ActiveRecord::Schema[8.2].define(version: 1) do - create_table "solid_queue_blocked_executions", force: :cascade do |t| + create_table "solid_queue_blocked_executions", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.string "concurrency_key", null: false t.datetime "created_at", null: false t.datetime "expires_at", null: false @@ -23,7 +23,7 @@ ActiveRecord::Schema[8.2].define(version: 1) do t.index ["job_id"], name: "index_solid_queue_blocked_executions_on_job_id", unique: true end - create_table "solid_queue_claimed_executions", force: :cascade do |t| + create_table "solid_queue_claimed_executions", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.datetime "created_at", null: false t.bigint "job_id", null: false t.bigint "process_id" @@ -31,14 +31,14 @@ ActiveRecord::Schema[8.2].define(version: 1) do t.index ["process_id", "job_id"], name: "index_solid_queue_claimed_executions_on_process_id_and_job_id" end - create_table "solid_queue_failed_executions", force: :cascade do |t| + create_table "solid_queue_failed_executions", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.datetime "created_at", null: false t.text "error" t.bigint "job_id", null: false t.index ["job_id"], name: "index_solid_queue_failed_executions_on_job_id", unique: true end - create_table "solid_queue_jobs", force: :cascade do |t| + create_table "solid_queue_jobs", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.string "active_job_id" t.text "arguments" t.string "class_name", null: false @@ -56,13 +56,13 @@ ActiveRecord::Schema[8.2].define(version: 1) do t.index ["scheduled_at", "finished_at"], name: "index_solid_queue_jobs_for_alerting" end - create_table "solid_queue_pauses", force: :cascade do |t| + create_table "solid_queue_pauses", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.datetime "created_at", null: false t.string "queue_name", null: false t.index ["queue_name"], name: "index_solid_queue_pauses_on_queue_name", unique: true end - create_table "solid_queue_processes", force: :cascade do |t| + create_table "solid_queue_processes", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.datetime "created_at", null: false t.string "hostname" t.string "kind", null: false @@ -76,7 +76,7 @@ ActiveRecord::Schema[8.2].define(version: 1) do t.index ["supervisor_id"], name: "index_solid_queue_processes_on_supervisor_id" end - create_table "solid_queue_ready_executions", force: :cascade do |t| + create_table "solid_queue_ready_executions", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.datetime "created_at", null: false t.bigint "job_id", null: false t.integer "priority", default: 0, null: false @@ -86,7 +86,7 @@ ActiveRecord::Schema[8.2].define(version: 1) do t.index ["queue_name", "priority", "job_id"], name: "index_solid_queue_poll_by_queue" end - create_table "solid_queue_recurring_executions", force: :cascade do |t| + create_table "solid_queue_recurring_executions", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.datetime "created_at", null: false t.bigint "job_id", null: false t.datetime "run_at", null: false @@ -95,7 +95,7 @@ ActiveRecord::Schema[8.2].define(version: 1) do t.index ["task_key", "run_at"], name: "index_solid_queue_recurring_executions_on_task_key_and_run_at", unique: true end - create_table "solid_queue_recurring_tasks", force: :cascade do |t| + create_table "solid_queue_recurring_tasks", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.text "arguments" t.string "class_name" t.string "command", limit: 2048 @@ -111,7 +111,7 @@ ActiveRecord::Schema[8.2].define(version: 1) do t.index ["static"], name: "index_solid_queue_recurring_tasks_on_static" end - create_table "solid_queue_scheduled_executions", force: :cascade do |t| + create_table "solid_queue_scheduled_executions", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.datetime "created_at", null: false t.bigint "job_id", null: false t.integer "priority", default: 0, null: false @@ -121,7 +121,7 @@ ActiveRecord::Schema[8.2].define(version: 1) do t.index ["scheduled_at", "priority", "job_id"], name: "index_solid_queue_dispatch_all" end - create_table "solid_queue_semaphores", force: :cascade do |t| + create_table "solid_queue_semaphores", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.datetime "created_at", null: false t.datetime "expires_at", null: false t.string "key", null: false diff --git a/db/schema.rb b/db/schema.rb index 8d6a4960d..71e316aec 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do +ActiveRecord::Schema[8.2].define(version: 2025_11_10_175021) do create_table "accesses", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.datetime "accessed_at" t.bigint "board_id", null: false @@ -25,6 +25,7 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do end create_table "account_join_codes", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.integer "account_id" t.string "code", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -113,6 +114,7 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do end create_table "boards", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.integer "account_id" t.boolean "all_access", default: false, null: false t.datetime "created_at", null: false t.bigint "creator_id", null: false @@ -161,6 +163,7 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do end create_table "cards", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.integer "account_id" t.bigint "board_id", null: false t.bigint "column_id" t.datetime "created_at", null: false @@ -193,6 +196,7 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do end create_table "columns", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.integer "account_id" t.bigint "board_id", null: false t.string "color", null: false t.datetime "created_at", null: false @@ -204,6 +208,7 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do end create_table "comments", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.integer "account_id" t.bigint "card_id", null: false t.datetime "created_at", null: false t.integer "creator_id", null: false @@ -229,6 +234,7 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do end create_table "events", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.integer "account_id" t.string "action", null: false t.bigint "board_id", null: false t.datetime "created_at", null: false @@ -245,6 +251,7 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do end create_table "filters", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.integer "account_id" t.datetime "created_at", null: false t.bigint "creator_id", null: false t.json "fields", default: -> { "(json_object())" }, null: false @@ -290,6 +297,7 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do end create_table "mentions", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.integer "account_id" t.datetime "created_at", null: false t.bigint "mentionee_id", null: false t.bigint "mentioner_id", null: false @@ -302,6 +310,7 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do end create_table "notification_bundles", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.integer "account_id" t.datetime "created_at", null: false t.datetime "ends_at", null: false t.datetime "starts_at", null: false @@ -314,6 +323,7 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do end create_table "notifications", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.integer "account_id" t.datetime "created_at", null: false t.bigint "creator_id" t.datetime "read_at" @@ -338,6 +348,7 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do end create_table "push_subscriptions", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.integer "account_id" t.string "auth_key" t.datetime "created_at", null: false t.string "endpoint" @@ -353,6 +364,7 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do end create_table "reactions", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.integer "account_id" t.integer "comment_id", null: false t.string "content", limit: 16, null: false t.datetime "created_at", null: false @@ -387,6 +399,7 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do end create_table "steps", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.integer "account_id" t.bigint "card_id", null: false t.boolean "completed", default: false, null: false t.text "content", null: false @@ -406,6 +419,7 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do end create_table "tags", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.integer "account_id" t.datetime "created_at", null: false t.string "title" t.datetime "updated_at", null: false @@ -423,6 +437,7 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do end create_table "users", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.integer "account_id" t.boolean "active", default: true, null: false t.datetime "created_at", null: false t.integer "membership_id" @@ -466,6 +481,7 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do end create_table "webhooks", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.integer "account_id" t.boolean "active", default: true, null: false t.bigint "board_id", null: false t.datetime "created_at", null: false diff --git a/script/import-sqlite-database.rb b/script/import-sqlite-database.rb index bb6880058..56573ef59 100755 --- a/script/import-sqlite-database.rb +++ b/script/import-sqlite-database.rb @@ -25,17 +25,15 @@ class Import Event.suppress do Current.with(account: account) do Webhook.skip_callback(:create, :after, :create_delinquency_tracker!) - Comment.skip_callback(:create, :after_create_commit, :watch_card_by_creator) - Mention.skip_callback(:create, :after_create_commit, :watch_source_by_mentionee) - Mention.skip_callback(:create, :after_create_commit, :notify_recipients) - Notification.skip_callback(:create, :after_create_commit, :broadcast_unread) + Comment.skip_callback(:commit, :after, :watch_card_by_creator) + Mention.skip_callback(:commit, :after, :watch_source_by_mentionee) + Notification.skip_callback(:commit, :after, :broadcast_unread) Notification.skip_callback(:create, :after, :bundle) - Notification.skip_callback(:create, :after_create_commit, :push_notification) Reaction.skip_callback(:create, :after, :register_card_activity) Card.skip_callback(:save, :before, :set_default_title) Card.skip_callback(:update, :after, :handle_board_change) - copy_entropies + # copy_entropies copy_users copy_boards copy_accesses @@ -54,6 +52,8 @@ class Import copy_notification_bundles copy_filters copy_events + + fix_links end end end @@ -63,6 +63,7 @@ class Import private def setup_account + puts "⏩ Setting up account" oldest_admin = import.users.order(id: :asc).where(role: :admin, active: true).first raise "No admin user found in the database" unless oldest_admin @@ -70,41 +71,46 @@ class Import account = import.accounts.sole new_identity = Identity.find_or_create_by!(email_address: membership.identity.email_address) - new_membership = new_identity.memberships.create!(tenant: account.external_account_id.to_s) + new_membership = new_identity.memberships.find_or_create_by!(tenant: account.external_account_id.to_s) - signup = Signup.new( - email_address: membership.identity.email_address, - full_name: oldest_admin.name, - account_name: account.name, - identity: new_identity, - membership_id: new_membership.signed_id(purpose: Signup::MEMBERSHIP_PURPOSE) - ) - - unless signup.complete - raise "Failed to complete signup: #{signup.errors.full_messages.join(', ')}" + if Account.all.exists?(external_account_id: account.external_account_id) + @account = Account.find_by!(external_account_id: account.external_account_id) + @tenant = @account.external_account_id + else + @account = Account.create_with_admin_user( + account: { + external_account_id: account.external_account_id.to_s, + name: account.name + }, + owner: { + name: oldest_admin.name, + membership_id: new_membership.id + } + ) + @tenant = @account.external_account_id end - @tenant = signup.tenant - @account = signup.account - old_join_code = import.account_join_codes.sole attributes = { usage_count: old_join_code.usage_count, usage_limit: old_join_code.usage_limit } - attributes[:code] = old_join_code.code unless Account::JoinCode.exist?(code: old_join_code.code) + attributes[:code] = old_join_code.code unless Account::JoinCode.all.exists?(code: old_join_code.code) - account.join_code.update_columns(**attributes) + @account.join_code.update_columns(**attributes) + puts "✅ Account set up!" end def copy_users + puts "⏩ Copying users" + mapping[:users] ||= {} import.users.find_each do |old_user| new_membership = nil - if user.active + if old_user.active && old_user.membership_id membership = untenanted.memberships.find(old_user.membership_id) - new_identity = Identity.find_or_create_by!(email_address: identity.email_address) + new_identity = Identity.find_or_create_by!(email_address: membership.identity.email_address) new_membership = new_identity.memberships.find_or_create_by!(tenant: tenant) end @@ -122,12 +128,14 @@ class Import end end - mapping[:users] ||= {} mapping[:users][old_user.id] = new_user.id end + puts "✅ Copied #{mapping[:users].size} users" end def copy_boards + puts "⏩ Copying boards" + mapping[:boards] ||= {} import.boards.find_each do |old_board| new_board = Board.create!( account_id: account.id, @@ -148,12 +156,15 @@ class Import ) end - mapping[:boards] ||= {} mapping[:boards][old_board.id] = new_board.id end + puts "✅ Copied #{mapping[:boards].size} boards" end def copy_columns + puts "⏩ Copying columns" + mapping[:columns] ||= {} + import.columns.find_each do |old_column| new_column = Column.create!( account_id: account.id, @@ -165,12 +176,14 @@ class Import updated_at: old_column.updated_at ) - mapping[:columns] ||= {} mapping[:columns][old_column.id] = new_column.id end + puts "✅ Copied #{mapping[:columns].size} columns" end def copy_cards + puts "⏩ Copying cards" + mapping[:cards] ||= {} import.cards.find_each do |old_card| new_card = Card.create!( account_id: account.id, @@ -228,7 +241,6 @@ class Import old_card.assignments.each do |old_assignment| Assignment.create!( - account_id: account.id, card_id: new_card.id, assignee_id: mapping[:users][old_assignment.assignee_id], assigner_id: mapping[:users][old_assignment.assigner_id], @@ -240,7 +252,6 @@ class Import old_closure = old_card.closure if old_closure Closure.create!( - account_id: account.id, card_id: new_card.id, user_id: old_closure.user_id ? mapping[:users][old_closure.user_id] : nil, created_at: old_closure.created_at, @@ -248,12 +259,13 @@ class Import ) end - mapping[:cards] ||= {} mapping[:cards][old_card.id] = new_card.id end + puts "✅ Copied #{mapping[:cards].size} cards" end def copy_steps + puts "⏩ Copying steps" import.steps.find_each do |old_step| Step.create!( account_id: account.id, @@ -264,9 +276,12 @@ class Import updated_at: old_step.updated_at ) end + puts "✅ Copied steps" end def copy_comments + puts "⏩ Copying comments" + mapping[:comments] ||= {} import.comments.find_each do |old_comment| new_comment = Comment.create!( account_id: account.id, @@ -278,12 +293,14 @@ class Import copy_rich_text(old_comment, new_comment, "Comment", "body") - mapping[:comments] ||= {} mapping[:comments][old_comment.id] = new_comment.id end + puts "✅ Copied #{mapping[:comments].size} comments" end def copy_mentions + puts "⏩ Copying mentions" + mapping[:mentions] ||= {} import.mentions.find_each do |old_mention| new_mention = Mention.create!( account_id: account.id, @@ -295,29 +312,34 @@ class Import updated_at: old_mention.updated_at ) - mapping[:mentions] ||= {} mapping[:mentions][old_mention.id] = new_mention.id end + puts "✅ Copied #{mapping[:mentions].size} mentions" end def copy_accesses + puts "⏩ Copying accesses" import.accesses.find_each do |old_access| - new_access = Access.create!( - account_id: account.id, + new_access = Access.find_or_create_by!( board_id: mapping[:boards][old_access.board_id], - user_id: mapping[:users][old_access.user_id], - involvement: old_access.involvement, - accessed_at: old_access.accessed_at, - created_at: old_access.created_at, - updated_at: old_access.updated_at - ) + user_id: mapping[:users][old_access.user_id] + ) do |access| + access.involvement = old_access.involvement + access.accessed_at = old_access.accessed_at + access.created_at = old_access.created_at + access.updated_at = old_access.updated_at + end mapping[:accesses] ||= {} mapping[:accesses][old_access.id] = new_access.id end + puts "✅ Copied #{mapping[:accesses].size} accesses" end def copy_notifications + puts "⏩ Copying notifications" + mapping[:notifications] ||= {} + import.notifications.find_each do |old_notification| new_notification = Notification.create!( account_id: account.id, @@ -330,12 +352,15 @@ class Import updated_at: old_notification.updated_at ) - mapping[:notifications] ||= {} mapping[:notifications][old_notification.id] = new_notification.id end + puts "✅ Copied #{mapping[:notifications].size} notifications" end def copy_notification_bundles + puts "⏩ Copying notification bundles" + mapping[:notification_bundles] ||= {} + import.notification_bundles.find_each do |old_bundle| new_bundle = Notification::Bundle.create!( account_id: account.id, @@ -347,12 +372,13 @@ class Import updated_at: old_bundle.updated_at ) - mapping[:notification_bundles] ||= {} mapping[:notification_bundles][old_bundle.id] = new_bundle.id end + puts "✅ Copied #{mapping[:notification_bundles].size} notification bundles" end def copy_entropies + puts "⏩ Copying entropies" import.entropies.find_each do |old_entropy| container_id = case old_entropy.container_type when "Account" then account.id @@ -369,9 +395,13 @@ class Import updated_at: old_entropy.updated_at ) end + puts "✅ Copied entropies" end def copy_filters + puts "⏩ Copying filters" + mapping[:filters] ||= {} + import.filters.find_each do |old_filter| new_filter = Filter.create!( account_id: account.id, @@ -406,12 +436,13 @@ class Import FiltersTag.find_or_create_by!(filter_id: new_filter.id, tag_id: mapping[:tags][join.tag_id]) end - mapping[:filters] ||= {} mapping[:filters][old_filter.id] = new_filter.id end + puts "✅ Copied #{mapping[:filters].size} filters" end def copy_events + puts "⏩ Copying events" import.events.find_each do |old_event| new_event = Event.create!( account_id: account.id, @@ -428,6 +459,7 @@ class Import mapping[:events] ||= {} mapping[:events][old_event.id] = new_event.id end + puts "✅ Copied #{mapping[:events].size} events" end def copy_rich_text(old_record, new_record, record_type, name) @@ -478,6 +510,8 @@ class Import end def copy_reactions + puts "⏩ Copying reactions" + mapping[:reactions] ||= {} import.reactions.find_each do |old_reaction| new_reaction = Reaction.create!( account_id: account.id, @@ -488,12 +522,16 @@ class Import updated_at: old_reaction.updated_at ) - mapping[:reactions] ||= {} mapping[:reactions][old_reaction.id] = new_reaction.id end + puts "✅ Copied #{mapping[:reactions].size} reactions" end def copy_tags + puts "⏩ Copying tags" + mapping[:tags] ||= {} + mapping[:taggings] ||= {} + import.tags.find_each do |old_tag| new_tag = Tag.find_or_create_by!(title: old_tag.title) do |t| t.account_id = account.id @@ -501,28 +539,28 @@ class Import t.updated_at = old_tag.updated_at end - mapping[:tags] ||= {} mapping[:tags][old_tag.id] = new_tag.id end import.taggings.find_each do |old_tagging| new_tagging = Tagging.create!( - account_id: account.id, tag_id: mapping[:tags][old_tagging.tag_id], card_id: mapping[:cards][old_tagging.card_id], created_at: old_tagging.created_at, updated_at: old_tagging.updated_at ) - mapping[:taggings] ||= {} mapping[:taggings][old_tagging.id] = new_tagging.id end + puts "✅ Copied #{mapping[:tags].size} tags and #{mapping[:taggings].size} taggings" end def copy_watches + puts "⏩ Copying watches" + mapping[:watches] ||= {} + import.watches.find_each do |old_watch| new_watch = Watch.create!( - account_id: account.id, user_id: mapping[:users][old_watch.user_id], card_id: mapping[:cards][old_watch.card_id], watching: old_watch.watching, @@ -530,27 +568,33 @@ class Import updated_at: old_watch.updated_at ) - mapping[:watches] ||= {} mapping[:watches][old_watch.id] = new_watch.id end + puts "✅ Copied #{mapping[:watches].size} watches" end def copy_pins + puts "⏩ Copying pins" + mapping[:pins] ||= {} + import.pins.find_each do |old_pin| new_pin = Pin.create!( - account_id: account.id, user_id: mapping[:users][old_pin.user_id], card_id: mapping[:cards][old_pin.card_id], created_at: old_pin.created_at, updated_at: old_pin.updated_at ) - mapping[:pins] ||= {} mapping[:pins][old_pin.id] = new_pin.id end + puts "✅ Copied #{mapping[:pins].size} pins" end def copy_webhooks + puts "⏩ Copying webhooks" + mapping[:webhooks] ||= {} + mapping[:webhook_deliveries] ||= {} + import.webhooks.find_each do |old_webhook| new_webhook = Webhook.create!( account_id: account.id, @@ -564,7 +608,6 @@ class Import updated_at: old_webhook.updated_at ) - mapping[:webhooks] ||= {} mapping[:webhooks][old_webhook.id] = new_webhook.id old_tracker = import.webhook_delinquency_trackers.find_by(webhook_id: old_webhook.id) @@ -588,12 +631,15 @@ class Import updated_at: old_delivery.updated_at ) - mapping[:webhook_deliveries] ||= {} mapping[:webhook_deliveries][old_delivery.id] = new_delivery.id end + puts "✅ Copied #{mapping[:webhooks].size} webhooks and #{mapping[:webhook_deliveries].size} deliveries" end def copy_push_subscriptions + puts "⏩ Copying push subscriptions" + mapping[:push_subscriptions] ||= {} + import.push_subscriptions.find_each do |old_subscription| new_subscription = Push::Subscription.create!( account_id: account.id, @@ -606,9 +652,14 @@ class Import updated_at: old_subscription.updated_at ) - mapping[:push_subscriptions] ||= {} mapping[:push_subscriptions][old_subscription.id] = new_subscription.id end + puts "✅ Copied #{mapping[:push_subscriptions].size} push subscriptions" + end + + def fix_links + puts "⏩ Fixing links" + puts "✅ Fixed #{mapping[:cards].size} links" end def import