Files
fizzy/app/models/account/export.rb
T
Kevin McConnell e16cc21b0a Add "data export" feature
- Adds a button in Account Settings where you can request a ZIP export of your
  Fizzy data
- Export files are created in the background. When ready, a link to
  download them is sent to the requester.
- Exports expire after 24 hours. And are limited to 10 per day.
2025-12-01 15:23:26 +00:00

76 lines
1.7 KiB
Ruby

class Account::Export < ApplicationRecord
belongs_to :account
belongs_to :user
has_one_attached :file
enum :status, %w[ pending processing completed failed ].index_by(&:itself), default: :pending
scope :current, -> { where(created_at: 24.hours.ago..) }
scope :expired, -> { where(completed_at: ...24.hours.ago) }
def self.cleanup
expired.destroy_all
end
def build_later
ExportAccountDataJob.perform_later(self)
end
def build
processing!
zipfile = generate_zip
file.attach(
io: File.open(zipfile.path),
filename: "export-#{id}.zip",
content_type: "application/zip"
)
mark_completed
ExportMailer.completed(self).deliver_later
rescue => e
update!(status: :failed)
raise
ensure
zipfile&.close
zipfile&.unlink
end
def mark_completed
update!(status: :completed, completed_at: Time.current)
end
private
def generate_zip
Tempfile.new([ "export", ".zip" ]).tap do |tempfile|
Zip::File.open(tempfile.path, create: true) do |zip|
exportable_cards.find_each do |card|
add_card_to_zip(zip, card)
end
end
end
end
def exportable_cards
user.accessible_cards.includes(
:board,
creator: :identity,
comments: { creator: :identity },
rich_text_description: { embeds_attachments: :blob }
)
end
def add_card_to_zip(zip, card)
zip.get_output_stream("#{card.number}.json") do |f|
f.write(card.export_json)
end
card.export_attachments.each do |attachment|
zip.get_output_stream(attachment[:path]) do |f|
attachment[:blob].download { |chunk| f.write(chunk) }
end
end
end
end