media assets: add file_key, is_public columns.
`file_key` is a random 9-character base-62 string that will be used as the image filename in the future. `is_public` is whether the image can be viewed without authentication or not. Users running downstream boorus must run `bin/rails db:migrate` and `script/fixes/109_generate_media_asset_file_keys.rb` after this commit.
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
class MediaAsset < ApplicationRecord
|
||||
class Error < StandardError; end
|
||||
|
||||
FILE_KEY_LENGTH = 9
|
||||
VARIANTS = %i[preview 180x180 360x360 720x720 sample original]
|
||||
MAX_VIDEO_DURATION = Danbooru.config.max_video_duration.to_i
|
||||
MAX_IMAGE_RESOLUTION = Danbooru.config.max_image_resolution
|
||||
@@ -22,6 +23,9 @@ class MediaAsset < ApplicationRecord
|
||||
delegate :metadata, to: :media_metadata
|
||||
delegate :is_non_repeating_animation?, :is_greyscale?, :is_rotated?, to: :metadata
|
||||
|
||||
scope :public_only, -> { where(is_public: true) }
|
||||
scope :private_only, -> { where(is_public: false) }
|
||||
|
||||
# Processing: The asset's files are currently being resized and distributed to the backend servers.
|
||||
# Active: The asset has been successfully uploaded and is ready to use.
|
||||
# Deleted: The asset's files have been deleted by moving them to a trash folder. They can be undeleted by moving them out of the trash folder.
|
||||
@@ -39,9 +43,12 @@ class MediaAsset < ApplicationRecord
|
||||
validates :md5, uniqueness: { conditions: -> { where(status: [:processing, :active]) } }
|
||||
validates :file_ext, inclusion: { in: %w[jpg png gif mp4 webm swf zip], message: "File is not an image or video" }
|
||||
validates :file_size, numericality: { less_than_or_equal_to: Danbooru.config.max_file_size, message: ->(asset, _) { "too large (size: #{asset.file_size.to_formatted_s(:human_size)}; max size: #{Danbooru.config.max_file_size.to_formatted_s(:human_size)})" } }
|
||||
validates :file_key, length: { is: FILE_KEY_LENGTH }, uniqueness: true, if: :file_key_changed?
|
||||
validates :duration, numericality: { less_than_or_equal_to: MAX_VIDEO_DURATION, message: "must be less than #{MAX_VIDEO_DURATION} seconds", allow_nil: true }, on: :create # XXX should allow admins to bypass
|
||||
validate :validate_resolution, on: :create
|
||||
|
||||
before_create :initialize_file_key
|
||||
|
||||
class Variant
|
||||
extend Memoist
|
||||
|
||||
@@ -186,7 +193,7 @@ class MediaAsset < ApplicationRecord
|
||||
concerning :SearchMethods do
|
||||
class_methods do
|
||||
def search(params)
|
||||
q = search_attributes(params, :id, :created_at, :updated_at, :md5, :file_ext, :file_size, :image_width, :image_height)
|
||||
q = search_attributes(params, :id, :created_at, :updated_at, :md5, :file_ext, :file_size, :image_width, :image_height, :file_key, :is_public)
|
||||
|
||||
if params[:metadata].present?
|
||||
q = q.joins(:media_metadata).merge(MediaMetadata.search(metadata: params[:metadata]))
|
||||
@@ -368,4 +375,15 @@ class MediaAsset < ApplicationRecord
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.generate_file_key
|
||||
loop do
|
||||
key = SecureRandom.send(:choose, [*"0".."9", *"A".."Z", *"a".."z"], FILE_KEY_LENGTH) # base62
|
||||
return key unless MediaAsset.exists?(file_key: key)
|
||||
end
|
||||
end
|
||||
|
||||
def initialize_file_key
|
||||
self.file_key = MediaAsset.generate_file_key
|
||||
end
|
||||
end
|
||||
|
||||
@@ -13,7 +13,7 @@ class MediaAssetPolicy < ApplicationPolicy
|
||||
if can_see_image?
|
||||
super
|
||||
else
|
||||
super.excluding(:md5)
|
||||
super.excluding(:md5, :file_key)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
class AddFileKeyToMediaAssets < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
add_column :media_assets, :file_key, :string, null: true
|
||||
add_column :media_assets, :is_public, :boolean, default: true, null: false
|
||||
|
||||
add_index :media_assets, :file_key, unique: true
|
||||
add_index :media_assets, :is_public, where: "is_public = FALSE"
|
||||
end
|
||||
end
|
||||
@@ -1102,7 +1102,9 @@ CREATE TABLE public.media_assets (
|
||||
image_width integer NOT NULL,
|
||||
image_height integer NOT NULL,
|
||||
duration double precision,
|
||||
status integer DEFAULT 200 NOT NULL
|
||||
status integer DEFAULT 200 NOT NULL,
|
||||
file_key character varying,
|
||||
is_public boolean DEFAULT true NOT NULL
|
||||
);
|
||||
|
||||
|
||||
@@ -3805,6 +3807,13 @@ CREATE INDEX index_media_assets_on_duration ON public.media_assets USING btree (
|
||||
CREATE INDEX index_media_assets_on_file_ext ON public.media_assets USING btree (file_ext);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_media_assets_on_file_key; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE UNIQUE INDEX index_media_assets_on_file_key ON public.media_assets USING btree (file_key);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_media_assets_on_file_size; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
@@ -3826,6 +3835,13 @@ CREATE INDEX index_media_assets_on_image_height ON public.media_assets USING btr
|
||||
CREATE INDEX index_media_assets_on_image_width ON public.media_assets USING btree (image_width);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_media_assets_on_is_public; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_media_assets_on_is_public ON public.media_assets USING btree (is_public) WHERE (is_public = false);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_media_assets_on_md5; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
@@ -5806,6 +5822,7 @@ INSERT INTO "schema_migrations" (version) VALUES
|
||||
('20220403042706'),
|
||||
('20220403220558'),
|
||||
('20220407203236'),
|
||||
('20220410050628');
|
||||
('20220410050628'),
|
||||
('20220504235329');
|
||||
|
||||
|
||||
|
||||
8
script/fixes/109_generate_media_asset_file_keys.rb
Executable file
8
script/fixes/109_generate_media_asset_file_keys.rb
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
require_relative "base"
|
||||
|
||||
MediaAsset.where(file_key: nil).parallel_each do |asset|
|
||||
asset.update_columns(file_key: MediaAsset.generate_file_key)
|
||||
puts "id=#{asset.id} file_key=#{asset.file_key}"
|
||||
end
|
||||
Reference in New Issue
Block a user