Merge branch 'master' into master2

This commit is contained in:
edshot99 2024-11-13 11:32:46 -06:00
commit 0d5984af63
24 changed files with 120 additions and 22 deletions

View File

@ -1,6 +1,6 @@
FROM ruby:3.3.1-alpine3.19 as ruby-builder
RUN apk --no-cache add build-base cmake git glib-dev postgresql15-dev
RUN apk --no-cache add build-base cmake git glib-dev postgresql15-dev gcompat
COPY Gemfile Gemfile.lock ./
RUN gem i foreman && BUNDLE_IGNORE_CONFIG=true bundle install -j$(nproc) \
@ -19,7 +19,7 @@ FROM ruby:3.3.1-alpine3.19
RUN apk --no-cache add ffmpeg vips \
postgresql15-client \
git jemalloc tzdata \
sudo
sudo gcompat
WORKDIR /app

View File

@ -16,5 +16,14 @@ module Admin
end
redirect_to admin_danger_zone_index_path
end
def hide_pending_posts
duration = params[:hide_pending_posts][:duration].to_f
if duration >= 0 && duration != DangerZone.hide_pending_posts_for
DangerZone.hide_pending_posts_for = duration
StaffAuditLog.log(:hide_pending_posts_for, CurrentUser.user, { duration: duration })
end
redirect_to admin_danger_zone_index_path
end
end
end

View File

@ -26,6 +26,8 @@ class PostsController < ApplicationController
def show
@post = Post.find(params[:id])
raise User::PrivilegeError.new("Post unavailable") unless DangerZone.post_visible?(@post, CurrentUser.user)
include_deleted = @post.is_deleted? || (@post.parent_id.present? && @post.parent.is_deleted?) || CurrentUser.is_approver?
@parent_post_set = PostSets::PostRelationship.new(@post.parent_id, :include_deleted => include_deleted, want_parent: true)
@children_post_set = PostSets::PostRelationship.new(@post.id, :include_deleted => include_deleted, want_parent: false)

View File

@ -170,7 +170,19 @@ class FilterToken {
];
}
}
} else this.value = FilterUtils.normalizeData(raw, this.type);
} else {
this.value = FilterUtils.normalizeData(raw, this.type);
if (this.comparison === "=" && this.type === "filesize") {
// If the comparison uses direct equality, mirror the fudging behavior of
// the filesize search metatag by changing the comparison to a range of
// the initial value -5% and +5%.
this.comparison = "..";
this.value = [
Math.trunc(this.value * 0.95),
Math.trunc(this.value * 1.05),
];
}
}
}
/**

View File

@ -199,9 +199,8 @@
#posts #posts-container {
width: 100%;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1vw;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-evenly;
}
@ -212,8 +211,7 @@
text-align: center;
vertical-align: middle;
display: inline-block;
width: 100%;
container-type: inline-size;
width: 31vw;
a {
margin: 0 auto;
@ -221,7 +219,7 @@
img {
max-height: 150px;
max-width: 100cqw;
max-width: 31vw;
}
.desc {
@ -231,11 +229,13 @@
.user-disable-cropped-false {
article.post-preview {
width: 31vw;
img {
height: auto;
max-height: none;
max-width: none;
width: 100cqw;
width: 31vw;
&.has-cropped-false {
object-fit: cover;
@ -314,13 +314,6 @@
}
}
}
@media screen and (max-width: 800px) and (horizontal-viewport-segments: 2) {
body.resp {
#posts #posts-container {
grid-template-columns: repeat(4, 1fr);
}
}
}
@media screen and (max-width: 660px) {
body.resp {

View File

@ -6,7 +6,7 @@
article.post-preview {
box-sizing: border-box;
height: auto;
width: 154px;
width: fit-content;
margin: 0 10px 10px 0;
overflow: hidden;
text-align: center;
@ -160,11 +160,10 @@ body[data-user-can-approve-posts="true"] .post-preview {
}
#has-parent-relationship-preview, #has-children-relationship-preview {
overflow-x: auto;
white-space: nowrap;
flex-direction: row;
flex-wrap: wrap;
article.post-preview {
width: auto;
border: none;
margin: 0;
padding: 5px 5px 10px;

View File

@ -160,7 +160,7 @@ div#c-users {
grid-area: p-posts;
display: flex;
overflow: auto;
justify-content: flex-start;
justify-content: center;
flex-wrap: wrap;
gap: 1em;
@ -173,6 +173,7 @@ div#c-users {
@include window-larger-than(800px) {
flex-wrap: nowrap;
border-top-left-radius: 0;
justify-content: flex-start;
}
article.post-preview {

View File

@ -5,6 +5,14 @@ module DangerZone
user.level < min_upload_level
end
def self.post_visible?(post, user)
if hide_pending_posts_for <= 0
return true
end
post.uploader_id == user.id || user.is_staff? || !post.is_pending? || post.created_at.before?(hide_pending_posts_for.hours.ago)
end
def self.min_upload_level
(Cache.redis.get("min_upload_level") || User::Levels::MEMBER).to_i
rescue Redis::CannotConnectError
@ -14,4 +22,14 @@ module DangerZone
def self.min_upload_level=(min_upload_level)
Cache.redis.set("min_upload_level", min_upload_level)
end
def self.hide_pending_posts_for
Cache.redis.get("hide_pending_posts_for").to_f || 0
rescue Redis::CannotConnectError
PostPruner::DELETION_WINDOW * 24
end
def self.hide_pending_posts_for=(duration)
Cache.redis.set("hide_pending_posts_for", duration)
end
end

View File

@ -324,5 +324,37 @@ class ElasticPostQueryBuilder < ElasticQueryBuilder
else
order.push({id: :desc})
end
if !CurrentUser.user.is_staff? && DangerZone.hide_pending_posts_for > 0
should = [
{
range: {
created_at: {
lte: DangerZone.hide_pending_posts_for.hours.ago,
},
},
},
{
term: {
pending: false,
},
}
]
unless CurrentUser.user.id.nil?
should.push({
term: {
uploader: CurrentUser.user.id,
},
})
end
must.push({
bool: {
should: should,
minimum_should_match: 1,
},
})
end
end
end

View File

@ -61,5 +61,7 @@ class ElasticPostVersionQueryBuilder < ElasticQueryBuilder
must.push({ term: { version: 1 } })
end
end
apply_basic_order
end
end

View File

@ -5,6 +5,7 @@ class Blip < ApplicationRecord
simple_versioning
belongs_to_creator
belongs_to_updater optional: true
normalizes :body, with: ->(body) { body.gsub("\r\n", "\n") }
validates :body, presence: true
validates :body, length: { minimum: 5, maximum: Danbooru.config.blip_max_size }
validate :validate_parent_exists, on: :create

View File

@ -6,6 +6,7 @@ class Comment < ApplicationRecord
simple_versioning
belongs_to_creator
belongs_to_updater
normalizes :body, with: ->(body) { body.gsub("\r\n", "\n") }
validate :validate_post_exists, on: :create
validate :validate_creator_is_not_limited, on: :create
validate :post_not_comment_locked, on: :create

View File

@ -1,6 +1,7 @@
# frozen_string_literal: true
class Dmail < ApplicationRecord
normalizes :body, with: ->(body) { body.gsub("\r\n", "\n") }
validates :title, :body, presence: { on: :create }
validates :title, length: { minimum: 1, maximum: 250 }
validates :body, length: { minimum: 1, maximum: Danbooru.config.dmail_max_size }

View File

@ -16,6 +16,7 @@ class ForumPost < ApplicationRecord
before_validation :initialize_is_hidden, :on => :create
after_create :update_topic_updated_at_on_create
after_destroy :update_topic_updated_at_on_destroy
normalizes :body, with: ->(body) { body.gsub("\r\n", "\n") }
validates :body, :creator_id, presence: true
validates :body, length: { minimum: 1, maximum: Danbooru.config.forum_post_max_size }
validate :validate_topic_is_unlocked

View File

@ -7,6 +7,7 @@ class Note < ApplicationRecord
belongs_to :post
belongs_to_creator
has_many :versions, -> {order("note_versions.id ASC")}, :class_name => "NoteVersion", :dependent => :destroy
normalizes :body, with: ->(body) { body.gsub("\r\n", "\n") }
validates :post_id, :creator_id, :x, :y, :width, :height, :body, presence: true
validate :user_not_limited
validate :post_must_exist

View File

@ -7,6 +7,7 @@ class Pool < ApplicationRecord
array_attribute :post_ids, parse: %r{(?:https://(?:e621|e926)\.net/posts/)?(\d+)}i, cast: :to_i
belongs_to_creator
normalizes :description, with: ->(desc) { desc.gsub("\r\n", "\n") }
validates :name, uniqueness: { case_sensitive: false, if: :name_changed? }
validates :name, length: { minimum: 1, maximum: 250 }
validates :description, length: { maximum: Danbooru.config.pool_descr_max_size }

View File

@ -18,6 +18,7 @@ class Post < ApplicationRecord
before_validation :fix_bg_color
before_validation :blank_out_nonexistent_parents
before_validation :remove_parent_loops
normalizes :description, with: ->(desc) { desc.gsub("\r\n", "\n") }
validates :md5, uniqueness: { :on => :create, message: ->(obj, data) {"duplicate: #{Post.find_by_md5(obj.md5).id}"} }
validates :rating, inclusion: { in: %w(s q e), message: "rating must be s, q, or e" }
validates :bg_color, format: { with: /\A[A-Fa-f0-9]{6}\z/ }, allow_nil: true

View File

@ -10,6 +10,7 @@ class Ticket < ApplicationRecord
before_validation :initialize_fields, on: :create
after_initialize :validate_type
after_initialize :classify
normalizes :reason, with: ->(reason) { reason.gsub("\r\n", "\n") }
validates :qtype, presence: true
validates :reason, presence: true
validates :reason, length: { minimum: 2, maximum: Danbooru.config.ticket_max_size }

View File

@ -65,6 +65,7 @@ class User < ApplicationRecord
validates :email, length: { maximum: 100 }
validate :validate_email_address_allowed, on: [:create, :update], if: ->(rec) { (rec.new_record? && rec.email.present?) || (rec.email.present? && rec.email_changed?) }
normalizes :profile_about, :profile_artinfo, with: ->(value) { value.gsub("\r\n", "\n") }
validates :name, user_name: true, on: :create
validates :default_image_size, inclusion: { :in => %w(large fit fitv original) }
validates :per_page, inclusion: { :in => 1..320 }

View File

@ -5,6 +5,7 @@ class UserFeedback < ApplicationRecord
belongs_to :user
belongs_to_creator
belongs_to_updater
normalizes :body, with: ->(body) { body.gsub("\r\n", "\n") }
validates :body, :category, presence: true
validates :category, inclusion: { in: %w[positive negative neutral] }
validates :body, length: { minimum: 1, maximum: Danbooru.config.user_feedback_max_size }

View File

@ -7,6 +7,7 @@ class WikiPage < ApplicationRecord
before_validation :normalize_other_names
before_validation :normalize_parent
after_save :create_version
normalizes :body, with: ->(body) { body.gsub("\r\n", "\n") }
validates :title, uniqueness: { :case_sensitive => false }
validates :title, presence: true
validates :title, tag_name: true, if: :title_changed?

View File

@ -7,6 +7,16 @@
<%= f.input :min_level, collection: User.level_hash.select {|k,v| v >= User::Levels::MEMBER }.to_a, selected: DangerZone.min_upload_level %>
<%= f.button :submit, value: "Submit" %>
<% end %>
<h2>Pending Posts</h2>
<% if DangerZone.hide_pending_posts_for > 0 %>
Unapproved posts are currently only visible to staff for <b><%= DangerZone.hide_pending_posts_for %></b> hours.
<% else %>
Unapproved posts are currently not hidden.
<% end %>
<%= custom_form_for(:hide_pending_posts, url: hide_pending_posts_admin_danger_zone_index_path, method: :put) do |f| %>
<%= f.input :duration, as: :float, hint: "in hours", input_html: { value: DangerZone.hide_pending_posts_for } %>
<%= f.button :submit, value: "Submit" %>
<% end %>
</div>
</div>

View File

@ -29,6 +29,7 @@ Rails.application.routes.draw do
resources :danger_zone, only: [:index] do
collection do
put :uploading_limits
put :hide_pending_posts
end
end
end

View File

@ -10,6 +10,7 @@ class Admin::DangerZoneControllerTest < ActionDispatch::IntegrationTest
teardown do
DangerZone.min_upload_level = User::Levels::MEMBER
DangerZone.hide_pending_posts_for = 0
end
context "index action" do
@ -25,5 +26,12 @@ class Admin::DangerZoneControllerTest < ActionDispatch::IntegrationTest
assert_equal DangerZone.min_upload_level, User::Levels::PRIVILEGED
end
end
context "hide pending posts action" do
should "work" do
put_auth hide_pending_posts_admin_danger_zone_index_path, @admin, params: { hide_pending_posts: { duration: 24 } }
assert_equal DangerZone.hide_pending_posts_for, 24
end
end
end
end