Files
danbooru/app/policies/post_policy.rb
evazion abdab7a0a8 uploads: rework upload process.
Rework the upload process so that files are saved to Danbooru first
before the user starts tagging the upload.

The main user-visible change is that you have to select the file first
before you can start tagging it. Saving the file first lets us fix a
number of problems:

* We can check for dupes before the user tags the upload.
* We can perform dupe checks and show preview images for users not using the bookmarklet.
* We can show preview images without having to proxy images through Danbooru.
* We can show previews of videos and ugoira files.
* We can reliably show the filesize and resolution of the image.
* We can let the user save files to upload later.
* We can get rid of a lot of spaghetti code related to preprocessing
  uploads. This was the cause of most weird "md5 confirmation doesn't
  match md5" errors.

(Not all of these are implemented yet.)

Internally, uploading is now a two-step process: first we create an upload
object, then we create a post from the upload. This is how it works:

* The user goes to /uploads/new and chooses a file or pastes an URL into
  the file upload component.
* The file upload component calls `POST /uploads` to create an upload.
* `POST /uploads` immediately returns a new upload object in the `pending` state.
* Danbooru starts processing the upload in a background job (downloading,
  resizing, and transferring the image to the image servers).
* The file upload component polls `/uploads/$id.json`, checking the
  upload `status` until it returns `completed` or `error`.
* When the upload status is `completed`, the user is redirected to /uploads/$id.
* On the /uploads/$id page, the user can tag the upload and submit it.
* The upload form calls `POST /posts` to create a new post from the upload.
* The user is redirected to the new post.

This is the data model:

* An upload represents a set of files uploaded to Danbooru by a user.
  Uploaded files don't have to belong to a post. An upload has an
  uploader, a status (pending, processing, completed, or error), a
  source (unless uploading from a file), and a list of media assets
  (image or video files).

* There is a has-and-belongs-to-many relationship between uploads and
  media assets. An upload can have many media assets, and a media asset
  can belong to multiple uploads. Uploads are joined to media assets
  through a upload_media_assets table.

  An upload could potentially have multiple media assets if it's a Pixiv
  or Twitter gallery. This is not yet implemented (at the moment all
  uploads have one media asset).

  A media asset can belong to multiple uploads if multiple people try
  to upload the same file, or if the same user tries to upload the same
  file more than once.

New features:

* On the upload page, you can press Ctrl+V to paste an URL and immediately upload it.
* You can save files for upload later. Your saved files are at /uploads.

Fixes:

* Improved error messages when uploading invalid files, bad URLs, and
  when forgetting the rating.
2022-01-28 04:13:22 -06:00

96 lines
1.7 KiB
Ruby

# frozen_string_literal: true
class PostPolicy < ApplicationPolicy
def show_seq?
true
end
def random?
true
end
def update?
unbanned? && record.visible?
end
def create?
unbanned? && record.uploader == user
end
def revert?
update?
end
def copy_notes?
update?
end
def mark_as_translated?
update?
end
def move_favorites?
user.is_approver? && record.fav_count > 0 && record.parent_id.present?
end
def regenerate?
user.is_moderator?
end
def delete?
user.is_approver? && !record.is_deleted?
end
def destroy?
delete?
end
def ban?
user.is_approver? && !record.is_banned?
end
def unban?
user.is_approver? && record.is_banned?
end
def expunge?
user.is_admin?
end
def visible?
record.visible?(user)
end
def can_use_mode_menu?
user.is_gold?
end
# whether to show the + - links in the tag list.
def show_extra_links?
user.is_gold?
end
def permitted_attributes_for_create
%i[upload_media_asset_id tag_string rating parent_id source is_pending
artist_commentary_desc artist_commentary_title translated_commentary_desc
translated_commentary_title]
end
def permitted_attributes_for_update
%i[tag_string old_tag_string parent_id old_parent_id source old_source rating old_rating has_embedded_notes]
end
def api_attributes
attributes = super
attributes += [:has_large, :has_visible_children]
attributes += TagCategory.categories.map {|x| "tag_string_#{x}".to_sym}
attributes += [:file_url, :large_file_url, :preview_file_url] if visible?
attributes -= [:id, :md5] if !visible?
attributes
end
def html_data_attributes
super + [:has_large?, :current_image_size]
end
end