DEV: Move min_trust_to_post_embedded_media to group setting (#25238)

c.f. https://meta.discourse.org/t/we-are-changing-giving-access-to-features/283408
This commit is contained in:
Martin Brennan 2024-01-25 09:50:59 +10:00 committed by GitHub
parent cf25fab9b0
commit 0e50f88212
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 374 additions and 171 deletions

View File

@ -402,7 +402,7 @@ en:
too_many_mentions_newuser:
one: "Sorry, new users can only mention one other user in a post."
other: "Sorry, new users can only mention %{count} users in a post."
no_embedded_media_allowed_trust: "Sorry, you can't embed media items in a post."
no_embedded_media_allowed_group: "Sorry, you can't embed media items in a post."
no_embedded_media_allowed: "Sorry, new users can't embed media items in posts."
too_many_embedded_media:
one: "Sorry, new users can only put one embedded media item in a post."
@ -1986,6 +1986,7 @@ en:
min_trust_to_post_links: "The minimum trust level required to include links in posts"
post_links_allowed_groups: "Groups that are allowed to include links in posts."
min_trust_to_post_embedded_media: "The minimum trust level required to embed media items in a post"
embedded_media_post_allowed_groups: "The users in these groups are allowed to embed media items in a post"
min_trust_level_to_allow_profile_background: "The minimum trust level required to upload a profile background"
min_trust_level_to_allow_user_card_background: "The minimum trust level required to upload a user card background"
user_card_background_allowed_groups: "Groups that are allowed to upload a user card background."
@ -2590,6 +2591,7 @@ en:
create_tag_allowed_groups: "min_trust_to_create_tag"
send_email_messages_allowed_groups: "min_trust_to_send_email_messages"
skip_review_media_groups: "review_media_unless_trust_level"
embedded_media_allowed_groups: "min_trust_to_post_embedded_media"
post_links_allowed_groups: "min_trust_to_post_links"
user_api_key_allowed_groups: "min_trust_level_for_user_api_key"

View File

@ -1767,6 +1767,13 @@ trust:
min_trust_to_post_embedded_media:
default: 0
enum: "TrustLevelSetting"
hidden: true
embedded_media_post_allowed_groups:
default: "10"
type: group_list
allow_any: false
refresh: true
validator: "AtLeastOneGroupValidator"
min_trust_level_to_allow_profile_background:
default: 0
client: true

View File

@ -0,0 +1,24 @@
# frozen_string_literal: true
class FillEmbeddedMediaPostAllowedGroupsBasedOnDeprecatedSetting < ActiveRecord::Migration[7.0]
def up
old_setting_trust_level =
DB.query_single(
"SELECT value FROM site_settings WHERE name = 'min_trust_to_post_embedded_media' LIMIT 1",
).first
if old_setting_trust_level.present?
allowed_groups = "1#{old_setting_trust_level}"
DB.exec(
"INSERT INTO site_settings(name, value, data_type, created_at, updated_at)
VALUES('embedded_media_post_allowed_groups', :setting, '20', NOW(), NOW())",
setting: allowed_groups,
)
end
end
def down
raise ActiveRecord::IrreversibleMigration
end
end

View File

@ -37,6 +37,7 @@ module SiteSettings::DeprecatedSettings
["min_trust_to_create_tag", "create_tag_allowed_groups", false, "3.3"],
["min_trust_to_send_email_messages", "send_email_messages_allowed_groups", false, "3.3"],
["review_media_unless_trust_level", "skip_review_media_groups", false, "3.3"],
["min_trust_to_post_embedded_media", "embedded_media_post_allowed_groups", false, "3.3"],
["min_trust_to_post_links", "post_links_allowed_groups", false, "3.3"],
["min_trust_level_for_user_api_key", "user_api_key_allowed_groups", false, "3.3"],
]
@ -60,6 +61,7 @@ module SiteSettings::DeprecatedSettings
min_trust_to_create_tag
min_trust_to_send_email_messages
review_media_unless_trust_level
min_trust_to_post_embedded_media
min_trust_to_post_links
min_trust_level_for_user_api_key
]

View File

@ -96,11 +96,11 @@ class PostValidator < ActiveModel::Validator
def max_embedded_media_validator(post)
return if post.acting_user.blank? || post.acting_user&.staff?
if post.acting_user.trust_level < TrustLevel[SiteSetting.min_trust_to_post_embedded_media]
if !post.acting_user.in_any_groups?(SiteSetting.embedded_media_post_allowed_groups_map)
add_error_if_count_exceeded(
post,
:no_embedded_media_allowed_trust,
:no_embedded_media_allowed_trust,
:no_embedded_media_allowed_group,
:no_embedded_media_allowed_group,
post.embedded_media_count,
0,
)

View File

@ -80,7 +80,7 @@ module DiscourseNarrativeBot
# The prerequisites should ensure only one of them is called.
tutorial_images: {
prerequisite:
Proc.new { @user.has_trust_level?(SiteSetting.min_trust_to_post_embedded_media) },
Proc.new { @user.in_any_groups?(SiteSetting.embedded_media_post_allowed_groups_map) },
next_state: :tutorial_likes,
next_instructions:
Proc.new { I18n.t("#{I18N_KEY}.likes.instructions", base_uri: Discourse.base_path) },
@ -93,7 +93,7 @@ module DiscourseNarrativeBot
},
tutorial_likes: {
prerequisite:
Proc.new { !@user.has_trust_level?(SiteSetting.min_trust_to_post_embedded_media) },
Proc.new { !@user.in_any_groups?(SiteSetting.embedded_media_post_allowed_groups_map) },
next_state: :tutorial_flag,
next_instructions:
Proc.new do

View File

@ -31,6 +31,7 @@ RSpec.describe DiscourseNarrativeBot::NewUserNarrative do
stub_image_size
Jobs.run_immediately!
SiteSetting.discourse_narrative_bot_enabled = true
Group.refresh_automatic_groups!
end
describe "#notify_timeout" do
@ -828,8 +829,11 @@ RSpec.describe DiscourseNarrativeBot::NewUserNarrative do
end
end
describe "when min_trust_to_post_embedded_media is too high" do
before { SiteSetting.min_trust_to_post_embedded_media = 4 }
describe "when embedded_media_post_allowed_groups does not include the user" do
before do
SiteSetting.embedded_media_post_allowed_groups = Group::AUTO_GROUPS[:trust_level_4]
Group.refresh_automatic_groups!
end
it "should skip the images tutorial step" do
post.update!(

View File

@ -16,6 +16,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
)
end
let(:upload_path) { Discourse.store.upload_path }
fab!(:user) { Fabricate(:user, refresh_auto_groups: true) }
before do
Jobs.run_immediately!
@ -54,7 +55,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
before { Jobs.run_immediately! }
it "does nothing if topic has been deleted" do
post = Fabricate(:post, raw: "<img src='#{image_url}'>")
post = Fabricate(:post, user: user, raw: "<img src='#{image_url}'>")
post.topic.destroy!
expect do Jobs::PullHotlinkedImages.new.execute(post_id: post.id) end.not_to change {
@ -63,7 +64,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
end
it "does nothing if there are no large images to pull" do
post = Fabricate(:post, raw: "bob bob")
post = Fabricate(:post, user: user, raw: "bob bob")
orig = post.updated_at
freeze_time 1.week.from_now
@ -72,7 +73,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
end
it "replaces images" do
post = Fabricate(:post, raw: "<img src='#{image_url}'>")
post = Fabricate(:post, user: user, raw: "<img src='#{image_url}'>")
stub_image_size
expect { Jobs::PullHotlinkedImages.new.execute(post_id: post.id) }.to change {
@ -85,7 +86,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
it "enqueues raw replacement job with a delay" do
Jobs.run_later!
post = Fabricate(:post, raw: "<img src='#{image_url}'>")
post = Fabricate(:post, user: user, raw: "<img src='#{image_url}'>")
stub_image_size
freeze_time
@ -102,7 +103,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
end
it "removes downloaded images when they are no longer needed" do
post = Fabricate(:post, raw: "<img src='#{image_url}'>")
post = Fabricate(:post, user: user, raw: "<img src='#{image_url}'>")
stub_image_size
post.rebake!
post.reload
@ -115,7 +116,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
end
it "replaces images again after edit" do
post = Fabricate(:post, raw: "<img src='#{image_url}'>")
post = Fabricate(:post, user: user, raw: "<img src='#{image_url}'>")
stub_image_size
expect do post.rebake! end.to change { Upload.count }.by(1)
@ -131,7 +132,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
end
it "replaces encoded image urls" do
post = Fabricate(:post, raw: "<img src='#{encoded_image_url}'>")
post = Fabricate(:post, user: user, raw: "<img src='#{encoded_image_url}'>")
stub_image_size
expect do Jobs::PullHotlinkedImages.new.execute(post_id: post.id) end.to change {
Upload.count
@ -150,7 +151,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
"http://test.localhost/uploads/short-url/z2QSs1KJWoj51uYhDjb6ifCzxH6.gif",
).to_return(status: 200, body: "")
post = Fabricate(:post, raw: <<~MD)
post = Fabricate(:post, user: user, raw: <<~MD)
<h1></h1>
<a href="https://somelink.com">
<img alt="somelink" src="#{image_url}">
@ -173,7 +174,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
it "replaces correct image URL" do
url = image_url.sub("/2e/Longcat1.png", "")
post = Fabricate(:post, raw: "[Images](#{url})\n![](#{image_url})")
post = Fabricate(:post, user: user, raw: "[Images](#{url})\n![](#{image_url})")
stub_image_size
expect do Jobs::PullHotlinkedImages.new.execute(post_id: post.id) end.to change {
@ -184,7 +185,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
end
it "does not replace images in code blocks", skip: "Known issue" do
post = Fabricate(:post, raw: <<~RAW)
post = Fabricate(:post, user: user, raw: <<~RAW)
![realimage](#{image_url})
`![codeblockimage](#{image_url})`
RAW
@ -202,7 +203,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
it "replaces images without protocol" do
url = image_url.sub(/^https?\:/, "")
post = Fabricate(:post, raw: "<img alt='test' src='#{url}'>")
post = Fabricate(:post, user: user, raw: "<img alt='test' src='#{url}'>")
stub_image_size
expect do Jobs::PullHotlinkedImages.new.execute(post_id: post.id) end.to change {
@ -215,7 +216,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
it "replaces images without extension" do
url = image_url.sub(/\.[a-zA-Z0-9]+$/, "")
stub_request(:get, url).to_return(body: png, headers: { "Content-Type" => "image/png" })
post = Fabricate(:post, raw: "<img src='#{url}'>")
post = Fabricate(:post, user: user, raw: "<img src='#{url}'>")
stub_image_size
expect do Jobs::PullHotlinkedImages.new.execute(post_id: post.id) end.to change {
@ -231,7 +232,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
stub_request(:get, url).to_return(status: 200, body: file_from_fixtures("smallest.png"))
post = Fabricate(:post, raw: "<img src='#{url}'>")
post = Fabricate(:post, user: user, raw: "<img src='#{url}'>")
stub_image_size
expect { Jobs::PullHotlinkedImages.new.execute(post_id: post.id) }.to change {
@ -247,7 +248,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
it "skips editing raw for raw_html posts" do
raw = "<img src=\"#{image_url}\">"
post = Fabricate(:post, raw: raw, cook_method: Post.cook_methods[:raw_html])
post = Fabricate(:post, user: user, raw: raw, cook_method: Post.cook_methods[:raw_html])
stub_image_size
expect do
post.rebake!
@ -266,7 +267,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
stub_s3(upload)
url = Upload.secure_uploads_url_from_upload_url(upload.url)
url = Discourse.base_url + url
post = Fabricate(:post, raw: "<img src='#{url}'>")
post = Fabricate(:post, user: user, raw: "<img src='#{url}'>")
upload.update(access_control_post: post)
expect { Jobs::PullHotlinkedImages.new.execute(post_id: post.id) }.not_to change {
Upload.count
@ -283,7 +284,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
Upload.stubs(:signed_url_from_secure_uploads_url).returns(upload.url)
url = Upload.secure_uploads_url_from_upload_url(upload.url)
url = Discourse.base_url + url
post = Fabricate(:post, raw: "<img src='#{url}'>")
post = Fabricate(:post, user: user, raw: "<img src='#{url}'>")
upload.update(access_control_post: post)
FileStore::S3Store.any_instance.stubs(:store_upload).returns(upload.url)
@ -305,7 +306,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
Upload.stubs(:signed_url_from_secure_uploads_url).returns(upload.url)
url = Upload.secure_uploads_url_from_upload_url(upload.url)
url = Discourse.base_url + url
post = Fabricate(:post, raw: "<img src='#{url}'>")
post = Fabricate(:post, user: user, raw: "<img src='#{url}'>")
upload.update(access_control_post: Fabricate(:post))
FileStore::S3Store.any_instance.stubs(:store_upload).returns(upload.url)
@ -321,7 +322,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
end
it "replaces markdown image" do
post = Fabricate(:post, raw: <<~MD)
post = Fabricate(:post, user: user, raw: <<~MD)
[![some test](#{image_url})](https://somelink.com)
![some test](#{image_url})
![](#{image_url})
@ -346,7 +347,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
end
it "works when invalid url in post" do
post = Fabricate(:post, raw: <<~MD)
post = Fabricate(:post, user: user, raw: <<~MD)
![some test](#{image_url})
![some test 2]("#{image_url})
MD
@ -358,7 +359,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
end
it "replaces bbcode images" do
post = Fabricate(:post, raw: <<~MD)
post = Fabricate(:post, user: user, raw: <<~MD)
[img]
#{image_url}
[/img]
@ -414,7 +415,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
end
it "replaces image src" do
post = Fabricate(:post, raw: "#{url}")
post = Fabricate(:post, user: user, raw: "#{url}")
stub_image_size
post.rebake!
@ -425,7 +426,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
end
it "associates uploads correctly" do
post = Fabricate(:post, raw: "#{url}")
post = Fabricate(:post, user: user, raw: "#{url}")
stub_image_size
post.rebake!
post.reload
@ -440,7 +441,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
end
it "all combinations" do
post = Fabricate(:post, raw: <<~MD)
post = Fabricate(:post, user: user, raw: <<~MD)
<img src='#{image_url}'>
#{url}
<img src='#{broken_image_url}'>
@ -468,7 +469,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
end
it "rewrites a lone onebox" do
post = Fabricate(:post, raw: <<~MD)
post = Fabricate(:post, user: user, raw: <<~MD)
Onebox here:
#{image_url}
MD
@ -637,7 +638,7 @@ RSpec.describe Jobs::PullHotlinkedImages do
end
describe "#disable_if_low_on_disk_space" do
fab!(:post) { Fabricate(:post, created_at: 20.days.ago) }
fab!(:post) { Fabricate(:post, user: user, created_at: 20.days.ago) }
let(:job) { Jobs::PullHotlinkedImages.new }
before do

View File

@ -133,7 +133,10 @@ RSpec.describe Jobs::UserEmail do
data: { original_post_id: post.id }.to_json,
)
end
before { user.update_column(:last_seen_at, 9.minutes.ago) }
before do
user.update_column(:last_seen_at, 9.minutes.ago)
Group.refresh_automatic_groups!
end
it "doesn't send an email to a user that's been recently seen" do
Jobs::UserEmail.new.execute(type: :user_replied, user_id: user.id, post_id: post.id)

View File

@ -153,7 +153,12 @@ RSpec.describe BackupRestore::UploadsRestorer do
Fabricate(:optimized_image)
upload = Fabricate(:upload_s3)
post = Fabricate(:post, raw: "![#{upload.original_filename}](#{upload.short_url})")
post =
Fabricate(
:post,
raw: "![#{upload.original_filename}](#{upload.short_url})",
user: Fabricate(:user, refresh_auto_groups: true),
)
post.link_post_uploads
FileHelper.stubs(:download).returns(file_from_fixtures("logo.png"))

View File

@ -6,10 +6,11 @@ require "file_store/s3_store"
RSpec.describe CookedPostProcessor do
fab!(:upload)
fab!(:large_image_upload)
fab!(:user_with_auto_groups) { Fabricate(:user, refresh_auto_groups: true) }
let(:upload_path) { Discourse.store.upload_path }
describe "#post_process" do
fab!(:post) { Fabricate(:post, raw: <<~RAW) }
fab!(:post) { Fabricate(:post, user: user_with_auto_groups, raw: <<~RAW) }
<img src="#{upload.url}">
RAW
@ -34,7 +35,7 @@ RSpec.describe CookedPostProcessor do
let(:title) { "some title" }
let(:post) { Fabricate(:post, raw: <<~RAW) }
let(:post) { Fabricate(:post, user: user_with_auto_groups, raw: <<~RAW) }
#{url}
This is a #{url} with path
@ -126,7 +127,7 @@ RSpec.describe CookedPostProcessor do
describe "internal links" do
fab!(:topic)
fab!(:post) { Fabricate(:post, raw: "Hello #{topic.url}") }
fab!(:post) { Fabricate(:post, user: user_with_auto_groups, raw: "Hello #{topic.url}") }
let(:url) { topic.url }
it "includes the topic title" do
@ -174,7 +175,7 @@ RSpec.describe CookedPostProcessor do
let(:title) { "<b>some title</b>" }
let(:escaped_title) { CGI.escapeHTML(title) }
let(:post) { Fabricate(:post, raw: <<~RAW) }
let(:post) { Fabricate(:post, user: user_with_auto_groups, raw: <<~RAW) }
This is a #{url_with_path} topic
This should not be inline #{url_no_path} oneboxed
@ -259,7 +260,8 @@ RSpec.describe CookedPostProcessor do
it "includes responsive images on demand" do
upload.update!(width: 2000, height: 1500, filesize: 10_000, dominant_color: "FFFFFF")
post = Fabricate(:post, raw: "hello <img src='#{upload.url}'>")
post =
Fabricate(:post, user: user_with_auto_groups, raw: "hello <img src='#{upload.url}'>")
# fake some optimized images
OptimizedImage.create!(
@ -316,7 +318,8 @@ RSpec.describe CookedPostProcessor do
it "doesn't include response images for cropped images" do
upload.update!(width: 200, height: 4000, filesize: 12_345)
post = Fabricate(:post, raw: "hello <img src='#{upload.url}'>")
post =
Fabricate(:post, user: user_with_auto_groups, raw: "hello <img src='#{upload.url}'>")
# fake some optimized images
OptimizedImage.create!(
@ -346,7 +349,7 @@ RSpec.describe CookedPostProcessor do
end
context "with image_sizes" do
fab!(:post) { Fabricate(:post_with_image_urls) }
fab!(:post) { Fabricate(:post_with_image_urls, user: user_with_auto_groups) }
let(:cpp) { CookedPostProcessor.new(post, image_sizes: image_sizes) }
before do
@ -387,7 +390,7 @@ RSpec.describe CookedPostProcessor do
context "with unsized images" do
fab!(:upload) { Fabricate(:image_upload, width: 123, height: 456) }
fab!(:post) { Fabricate(:post, raw: <<~HTML) }
fab!(:post) { Fabricate(:post, user: user_with_auto_groups, raw: <<~HTML) }
<img src="#{upload.url}">
HTML
@ -403,7 +406,7 @@ RSpec.describe CookedPostProcessor do
context "with large images" do
fab!(:upload) { Fabricate(:image_upload, width: 1750, height: 2000) }
fab!(:post) { Fabricate(:post, raw: <<~HTML) }
fab!(:post) { Fabricate(:post, user: user_with_auto_groups, raw: <<~HTML) }
<img src="#{upload.url}">
HTML
@ -426,7 +429,7 @@ RSpec.describe CookedPostProcessor do
context "when image is inside onebox" do
let(:url) { "https://image.com/my-avatar" }
let(:post) { Fabricate(:post, raw: url) }
let(:post) { Fabricate(:post, user: user_with_auto_groups, raw: url) }
before do
Oneboxer
@ -452,6 +455,7 @@ RSpec.describe CookedPostProcessor do
fab!(:post) do
Fabricate(
:post,
user: user_with_auto_groups,
raw: "<img src=\"/#{Discourse.store.upload_path}/original/1X/1234567890123456.svg\">",
)
end
@ -470,6 +474,7 @@ RSpec.describe CookedPostProcessor do
let(:post) do
Fabricate(
:post,
user: user_with_auto_groups,
raw:
"<img src=\"http://test.discourse/#{upload_path}/original/1X/1234567890123456.svg?somepamas\">",
)
@ -507,7 +512,11 @@ RSpec.describe CookedPostProcessor do
let(:optimized_size) { "600x500" }
let(:post) do
Fabricate(:post, raw: "![large.png|#{optimized_size}](#{upload.short_url})")
Fabricate(
:post,
user: user_with_auto_groups,
raw: "![large.png|#{optimized_size}](#{upload.short_url})",
)
end
let(:cooked_html) { <<~HTML }
@ -575,7 +584,10 @@ RSpec.describe CookedPostProcessor do
context "when the upload is attached to a different post" do
before do
FastImage.size(upload.url)
upload.update(secure: true, access_control_post: Fabricate(:post))
upload.update(
secure: true,
access_control_post: Fabricate(:post, user: user_with_auto_groups),
)
end
it "does not create thumbnails or optimize images" do
@ -593,7 +605,7 @@ RSpec.describe CookedPostProcessor do
context "with tall images > default aspect ratio" do
fab!(:upload) { Fabricate(:image_upload, width: 500, height: 2200) }
fab!(:post) { Fabricate(:post, raw: <<~HTML) }
fab!(:post) { Fabricate(:post, user: user_with_auto_groups, raw: <<~HTML) }
<img src="#{upload.url}">
HTML
@ -612,7 +624,7 @@ RSpec.describe CookedPostProcessor do
context "with taller images < default aspect ratio" do
fab!(:upload) { Fabricate(:image_upload, width: 500, height: 2300) }
fab!(:post) { Fabricate(:post, raw: <<~HTML) }
fab!(:post) { Fabricate(:post, user: user_with_auto_groups, raw: <<~HTML) }
<img src="#{upload.url}">
HTML
@ -631,7 +643,7 @@ RSpec.describe CookedPostProcessor do
context "with iPhone X screenshots" do
fab!(:upload) { Fabricate(:image_upload, width: 1125, height: 2436) }
fab!(:post) { Fabricate(:post, raw: <<~HTML) }
fab!(:post) { Fabricate(:post, user: user_with_auto_groups, raw: <<~HTML) }
<img src="#{upload.url}">
HTML
@ -653,7 +665,7 @@ RSpec.describe CookedPostProcessor do
context "with large images when using subfolders" do
fab!(:upload) { Fabricate(:image_upload, width: 1750, height: 2000) }
fab!(:post) { Fabricate(:post, raw: <<~HTML) }
fab!(:post) { Fabricate(:post, user: user_with_auto_groups, raw: <<~HTML) }
<img src="/subfolder#{upload.url}">
HTML
@ -693,7 +705,7 @@ RSpec.describe CookedPostProcessor do
context "with title and alt" do
fab!(:upload) { Fabricate(:image_upload, width: 1750, height: 2000) }
fab!(:post) { Fabricate(:post, raw: <<~HTML) }
fab!(:post) { Fabricate(:post, user: user_with_auto_groups, raw: <<~HTML) }
<img src="#{upload.url}" title="WAT" alt="RED">
HTML
@ -718,7 +730,7 @@ RSpec.describe CookedPostProcessor do
context "with title only" do
fab!(:upload) { Fabricate(:image_upload, width: 1750, height: 2000) }
fab!(:post) { Fabricate(:post, raw: <<~HTML) }
fab!(:post) { Fabricate(:post, user: user_with_auto_groups, raw: <<~HTML) }
<img src="#{upload.url}" title="WAT">
HTML
@ -743,7 +755,7 @@ RSpec.describe CookedPostProcessor do
context "with alt only" do
fab!(:upload) { Fabricate(:image_upload, width: 1750, height: 2000) }
fab!(:post) { Fabricate(:post, raw: <<~HTML) }
fab!(:post) { Fabricate(:post, user: user_with_auto_groups, raw: <<~HTML) }
<img src="#{upload.url}" alt="RED">
HTML
@ -766,7 +778,7 @@ RSpec.describe CookedPostProcessor do
end
context "with topic image" do
fab!(:post) { Fabricate(:post_with_uploaded_image) }
fab!(:post) { Fabricate(:post_with_uploaded_image, user: user_with_auto_groups) }
let(:cpp) { CookedPostProcessor.new(post) }
it "adds a topic image if there's one in the first post" do
@ -801,7 +813,13 @@ RSpec.describe CookedPostProcessor do
expect(topic.image_upload_id).to be_present
expect(post.image_upload_id).to be_present
post = Fabricate(:post, topic: topic, raw: "this post doesn't have an image")
post =
Fabricate(
:post,
user: user_with_auto_groups,
topic: topic,
raw: "this post doesn't have an image",
)
CookedPostProcessor.new(post).post_process
topic.reload
@ -813,7 +831,7 @@ RSpec.describe CookedPostProcessor do
it "prioritizes data-thumbnail images" do
upload1 = Fabricate(:image_upload, width: 1750, height: 2000)
upload2 = Fabricate(:image_upload, width: 1750, height: 2000)
post = Fabricate(:post, raw: <<~MD)
post = Fabricate(:post, user: user_with_auto_groups, raw: <<~MD)
![alttext|1750x2000](#{upload1.url})
![alttext|1750x2000|thumbnail](#{upload2.url})
MD
@ -824,7 +842,9 @@ RSpec.describe CookedPostProcessor do
end
context "with post image" do
let(:reply) { Fabricate(:post_with_uploaded_image, post_number: 2) }
let(:reply) do
Fabricate(:post_with_uploaded_image, user: user_with_auto_groups, post_number: 2)
end
let(:cpp) { CookedPostProcessor.new(reply) }
it "adds a post image if there's one in the post" do
@ -963,7 +983,12 @@ RSpec.describe CookedPostProcessor do
fab!(:thumbnail) { Fabricate(:optimized_image, upload: upload, width: 512, height: 384) }
it "adds lightbox and optimizes images" do
post = Fabricate(:post, raw: "![image|1024x768, 50%](#{large_image_upload.short_url})")
post =
Fabricate(
:post,
user: user_with_auto_groups,
raw: "![image|1024x768, 50%](#{large_image_upload.short_url})",
)
cpp = CookedPostProcessor.new(post, disable_dominant_color: true)
cpp.post_process
@ -978,7 +1003,12 @@ RSpec.describe CookedPostProcessor do
# skips lightboxing
# adds "animated" class to element
upload.update!(animated: true)
post = Fabricate(:post, raw: "![image|1024x768, 50%](#{upload.short_url})")
post =
Fabricate(
:post,
user: user_with_auto_groups,
raw: "![image|1024x768, 50%](#{upload.short_url})",
)
cpp = CookedPostProcessor.new(post, disable_dominant_color: true)
cpp.post_process
@ -1008,6 +1038,7 @@ RSpec.describe CookedPostProcessor do
post =
Fabricate(
:post,
user: user_with_auto_groups,
raw: "![tennis-gif|311x280](https://media2.giphy.com/media/7Oifk90VrCdNe/giphy.webp)",
)
cpp = CookedPostProcessor.new(post, disable_dominant_color: true)
@ -1021,6 +1052,7 @@ RSpec.describe CookedPostProcessor do
post =
Fabricate(
:post,
user: user_with_auto_groups,
raw:
"![cat](https://media1.tenor.com/images/20c7ddd5e84c7427954f430439c5209d/tenor.gif)",
)
@ -1033,7 +1065,7 @@ RSpec.describe CookedPostProcessor do
end
it "optimizes and wraps images in quotes with lightbox wrapper" do
post = Fabricate(:post, raw: <<~MD)
post = Fabricate(:post, user: user_with_auto_groups, raw: <<~MD)
[quote]
![image|1024x768, 50%](#{large_image_upload.short_url})
[/quote]
@ -1055,7 +1087,7 @@ RSpec.describe CookedPostProcessor do
"<aside class='onebox'><img src='#{large_image_upload.url}' width='512' height='384'></aside>",
)
post = Fabricate(:post, raw: "https://discourse.org")
post = Fabricate(:post, user: user_with_auto_groups, raw: "https://discourse.org")
cpp = CookedPostProcessor.new(post, disable_dominant_color: true)
cpp.post_process
@ -1101,7 +1133,7 @@ RSpec.describe CookedPostProcessor do
.with(url, anything)
.returns("<img class='onebox' src='#{image_url}' />")
post = Fabricate(:post, raw: url)
post = Fabricate(:post, user: user_with_auto_groups, raw: url)
upload.update!(url: "https://test.s3.amazonaws.com/something.png", dominant_color: "00ffff")
PostHotlinkedMedia.create!(
@ -1145,7 +1177,7 @@ RSpec.describe CookedPostProcessor do
.with(url, anything)
.returns("<img class='onebox' src='#{image_url}' />")
post = Fabricate(:post, raw: url)
post = Fabricate(:post, user: user_with_auto_groups, raw: url)
upload.update!(
url: "https://test.s3.amazonaws.com/something.png",
dominant_color: "00ffff",
@ -1182,7 +1214,7 @@ RSpec.describe CookedPostProcessor do
</a>
HTML
post = Fabricate(:post, raw: url)
post = Fabricate(:post, user: user_with_auto_groups, raw: url)
PostHotlinkedMedia.create!(url: "//image.com/avatar.png", post: post, status: "too_large")
@ -1212,7 +1244,7 @@ RSpec.describe CookedPostProcessor do
</aside>
HTML
post = Fabricate(:post, raw: url)
post = Fabricate(:post, user: user_with_auto_groups, raw: url)
PostHotlinkedMedia.create!(url: "//example.com/favicon.ico", post: post, status: "too_large")
PostHotlinkedMedia.create!(url: "//example.com/article.jpeg", post: post, status: "too_large")
@ -1242,7 +1274,7 @@ RSpec.describe CookedPostProcessor do
.with(url, anything)
.returns("<img class='onebox' src='#{image_url}' />")
post = Fabricate(:post, raw: url)
post = Fabricate(:post, user: user_with_auto_groups, raw: url)
PostHotlinkedMedia.create!(
url: "//image.com/avatar.png",
@ -1274,7 +1306,7 @@ RSpec.describe CookedPostProcessor do
</aside>
HTML
post = Fabricate(:post, raw: url)
post = Fabricate(:post, user: user_with_auto_groups, raw: url)
PostHotlinkedMedia.create!(
url: "//example.com/favicon.ico",
@ -1537,6 +1569,7 @@ RSpec.describe CookedPostProcessor do
the_post =
Fabricate(
:post,
user: user_with_auto_groups,
raw:
%Q{This post has a local emoji :+1: and an external upload\n\n![smallest.png|10x20](#{upload.short_url})},
)
@ -1560,6 +1593,7 @@ RSpec.describe CookedPostProcessor do
the_post =
Fabricate(
:post,
user: user_with_auto_groups,
raw:
%Q{This post has a local emoji :+1: and an external upload\n\n![smallest.png|10x20](#{upload.short_url})},
)
@ -1581,7 +1615,12 @@ RSpec.describe CookedPostProcessor do
upload.update_column(:url, "#{SiteSetting.Upload.absolute_base_url}/#{stored_path}")
upload.update_column(:secure, true)
the_post = Fabricate(:post, raw: "This post has a custom emoji :trout:")
the_post =
Fabricate(
:post,
user: user_with_auto_groups,
raw: "This post has a custom emoji :trout:",
)
the_post.cook(the_post.raw)
cpp = CookedPostProcessor.new(the_post)
@ -1609,7 +1648,11 @@ RSpec.describe CookedPostProcessor do
SiteSetting.prevent_anons_from_downloading_files = true
the_post =
Fabricate(:post, raw: "This post has an S3 video onebox:\n#{video_upload.url}")
Fabricate(
:post,
user: user_with_auto_groups,
raw: "This post has an S3 video onebox:\n#{video_upload.url}",
)
cpp = CookedPostProcessor.new(the_post.reload)
cpp.post_process_oneboxes
@ -1631,7 +1674,11 @@ RSpec.describe CookedPostProcessor do
video_upload.update_column(:secure, true)
the_post =
Fabricate(:post, raw: "This post has an S3 video onebox:\n#{video_upload.url}")
Fabricate(
:post,
user: user_with_auto_groups,
raw: "This post has an S3 video onebox:\n#{video_upload.url}",
)
cpp = CookedPostProcessor.new(the_post)
cpp.post_process_oneboxes
@ -1679,7 +1726,7 @@ RSpec.describe CookedPostProcessor do
![logo.png](upload://#{image_upload.base62_sha1}.#{image_upload.extension})
RAW
the_post = Fabricate(:post, raw: raw)
the_post = Fabricate(:post, user: user_with_auto_groups, raw: raw)
cpp = CookedPostProcessor.new(the_post)
cpp.post_process_oneboxes
@ -1719,7 +1766,7 @@ RSpec.describe CookedPostProcessor do
describe "#remove_user_ids" do
let(:topic) { Fabricate(:topic) }
let(:post) { Fabricate(:post, raw: <<~RAW) }
let(:post) { Fabricate(:post, user: user_with_auto_groups, raw: <<~RAW) }
link to a topic: #{topic.url}?u=foo
a tricky link to a topic: #{topic.url}?bob=bob;u=sam&jane=jane
@ -1766,7 +1813,11 @@ RSpec.describe CookedPostProcessor do
context "with emoji inside a quote" do
let(:post) do
Fabricate(:post, raw: "time to eat some sweet \n[quote]\n:candy:\n[/quote]\n mmmm")
Fabricate(
:post,
user: user_with_auto_groups,
raw: "time to eat some sweet \n[quote]\n:candy:\n[/quote]\n mmmm",
)
end
it "doesn't award a badge when the emoji is in a quote" do
@ -1776,7 +1827,9 @@ RSpec.describe CookedPostProcessor do
end
context "with emoji in the text" do
let(:post) { Fabricate(:post, raw: "time to eat some sweet :candy: mmmm") }
let(:post) do
Fabricate(:post, user: user_with_auto_groups, raw: "time to eat some sweet :candy: mmmm")
end
it "awards a badge for using an emoji" do
cpp.grant_badges
@ -1794,7 +1847,12 @@ RSpec.describe CookedPostProcessor do
end
it "awards the badge for using an onebox" do
post = Fabricate(:post, raw: "onebox me:\n\nhttps://discourse.org\n")
post =
Fabricate(
:post,
user: user_with_auto_groups,
raw: "onebox me:\n\nhttps://discourse.org\n",
)
cpp = CookedPostProcessor.new(post)
cpp.post_process_oneboxes
cpp.grant_badges
@ -1802,7 +1860,8 @@ RSpec.describe CookedPostProcessor do
end
it "does not award the badge when link is not oneboxed" do
post = Fabricate(:post, raw: "onebox me:\n\nhttp://example.com\n")
post =
Fabricate(:post, user: user_with_auto_groups, raw: "onebox me:\n\nhttp://example.com\n")
cpp = CookedPostProcessor.new(post)
cpp.post_process_oneboxes
cpp.grant_badges
@ -1811,7 +1870,12 @@ RSpec.describe CookedPostProcessor do
it "does not award the badge when the badge is disabled" do
Badge.where(id: Badge::FirstOnebox).update_all(enabled: false)
post = Fabricate(:post, raw: "onebox me:\n\nhttps://discourse.org\n")
post =
Fabricate(
:post,
user: user_with_auto_groups,
raw: "onebox me:\n\nhttps://discourse.org\n",
)
cpp = CookedPostProcessor.new(post)
cpp.post_process_oneboxes
cpp.grant_badges
@ -1821,7 +1885,13 @@ RSpec.describe CookedPostProcessor do
context "with reply_by_email" do
let(:post) do
Fabricate(:post, raw: "This is a **reply** via email ;)", via_email: true, post_number: 2)
Fabricate(
:post,
user: user_with_auto_groups,
raw: "This is a **reply** via email ;)",
via_email: true,
post_number: 2,
)
end
it "awards a badge for replying via email" do
@ -1833,7 +1903,9 @@ RSpec.describe CookedPostProcessor do
describe "quote processing" do
let(:cpp) { CookedPostProcessor.new(cp) }
let(:pp) { Fabricate(:post, raw: "This post is ripe for quoting!") }
let(:pp) do
Fabricate(:post, user: user_with_auto_groups, raw: "This post is ripe for quoting!")
end
context "with an unmodified quote" do
let(:cp) do
@ -1872,7 +1944,7 @@ RSpec.describe CookedPostProcessor do
[/quote]
and this is a reply
RAW
let(:cp) { Fabricate(:post, raw: external_raw) }
let(:cp) { Fabricate(:post, user: user_with_auto_groups, raw: external_raw) }
it "it should be marked as missing" do
cpp.post_process_quotes
@ -1883,7 +1955,9 @@ RSpec.describe CookedPostProcessor do
describe "full quote on direct reply" do
fab!(:topic)
let!(:post) { Fabricate(:post, topic: topic, raw: 'this is the "first" post') }
let!(:post) do
Fabricate(:post, user: user_with_auto_groups, topic: topic, raw: 'this is the "first" post')
end
let(:raw) { <<~RAW.strip }
[quote="#{post.user.username}, post:#{post.post_number}, topic:#{topic.id}"]
@ -1922,9 +1996,22 @@ RSpec.describe CookedPostProcessor do
before { SiteSetting.remove_full_quote = true }
it "works" do
hidden = Fabricate(:post, topic: topic, hidden: true, raw: "this is the second post after")
small_action = Fabricate(:post, topic: topic, post_type: Post.types[:small_action])
reply = Fabricate(:post, topic: topic, raw: raw)
hidden =
Fabricate(
:post,
user: user_with_auto_groups,
topic: topic,
hidden: true,
raw: "this is the second post after",
)
small_action =
Fabricate(
:post,
user: user_with_auto_groups,
topic: topic,
post_type: Post.types[:small_action],
)
reply = Fabricate(:post, user: user_with_auto_groups, topic: topic, raw: raw)
freeze_time do
topic.bumped_at = 1.day.ago
@ -1945,14 +2032,14 @@ RSpec.describe CookedPostProcessor do
end
it "does nothing if there are multiple quotes" do
reply = Fabricate(:post, topic: topic, raw: raw3)
reply = Fabricate(:post, user: user_with_auto_groups, topic: topic, raw: raw3)
CookedPostProcessor.new(reply).remove_full_quote_on_direct_reply
expect(topic.ordered_posts.pluck(:id)).to eq([post.id, reply.id])
expect(reply.raw).to eq(raw3)
end
it "does not delete quote if not first paragraph" do
reply = Fabricate(:post, topic: topic, raw: raw2)
reply = Fabricate(:post, user: user_with_auto_groups, topic: topic, raw: raw2)
CookedPostProcessor.new(reply).remove_full_quote_on_direct_reply
expect(topic.ordered_posts.pluck(:id)).to eq([post.id, reply.id])
expect(reply.raw).to eq(raw2)
@ -1961,22 +2048,33 @@ RSpec.describe CookedPostProcessor do
it "does nothing when 'remove_full_quote' is disabled" do
SiteSetting.remove_full_quote = false
reply = Fabricate(:post, topic: topic, raw: raw)
reply = Fabricate(:post, user: user_with_auto_groups, topic: topic, raw: raw)
CookedPostProcessor.new(reply).remove_full_quote_on_direct_reply
expect(reply.raw).to eq(raw)
end
it "does not generate a blank HTML document" do
post = Fabricate(:post, topic: topic, raw: "<sunday><monday>")
post = Fabricate(:post, user: user_with_auto_groups, topic: topic, raw: "<sunday><monday>")
cp = CookedPostProcessor.new(post)
cp.post_process
expect(cp.html).to eq("<p></p>")
end
it "works only on new posts" do
Fabricate(:post, topic: topic, hidden: true, raw: "this is the second post after")
Fabricate(:post, topic: topic, post_type: Post.types[:small_action])
Fabricate(
:post,
user: user_with_auto_groups,
topic: topic,
hidden: true,
raw: "this is the second post after",
)
Fabricate(
:post,
user: user_with_auto_groups,
topic: topic,
post_type: Post.types[:small_action],
)
reply = PostCreator.create!(topic.user, topic_id: topic.id, raw: raw)
stub_image_size
@ -1995,8 +2093,8 @@ RSpec.describe CookedPostProcessor do
end
it "works with nested quotes" do
reply1 = Fabricate(:post, topic: topic, raw: raw)
reply2 = Fabricate(:post, topic: topic, raw: <<~RAW.strip)
reply1 = Fabricate(:post, user: user_with_auto_groups, topic: topic, raw: raw)
reply2 = Fabricate(:post, user: user_with_auto_groups, topic: topic, raw: <<~RAW.strip)
[quote="#{reply1.user.username}, post:#{reply1.post_number}, topic:#{topic.id}"]
#{raw}
[/quote]
@ -2010,7 +2108,7 @@ RSpec.describe CookedPostProcessor do
end
describe "full quote on direct reply with full name prioritization" do
fab!(:user) { Fabricate(:user, name: "james, john, the third") }
fab!(:user) { Fabricate(:user, name: "james, john, the third", refresh_auto_groups: true) }
fab!(:topic)
let!(:post) { Fabricate(:post, user: user, topic: topic, raw: 'this is the "first" post') }
@ -2055,9 +2153,22 @@ RSpec.describe CookedPostProcessor do
end
it "removes direct reply with full quotes" do
hidden = Fabricate(:post, topic: topic, hidden: true, raw: "this is the second post after")
small_action = Fabricate(:post, topic: topic, post_type: Post.types[:small_action])
reply = Fabricate(:post, topic: topic, raw: raw)
hidden =
Fabricate(
:post,
user: user_with_auto_groups,
topic: topic,
hidden: true,
raw: "this is the second post after",
)
small_action =
Fabricate(
:post,
user: user_with_auto_groups,
topic: topic,
post_type: Post.types[:small_action],
)
reply = Fabricate(:post, user: user_with_auto_groups, topic: topic, raw: raw)
freeze_time do
topic.bumped_at = 1.day.ago
@ -2078,14 +2189,14 @@ RSpec.describe CookedPostProcessor do
end
it "does nothing if there are multiple quotes" do
reply = Fabricate(:post, topic: topic, raw: raw3)
reply = Fabricate(:post, user: user_with_auto_groups, topic: topic, raw: raw3)
CookedPostProcessor.new(reply).remove_full_quote_on_direct_reply
expect(topic.ordered_posts.pluck(:id)).to eq([post.id, reply.id])
expect(reply.raw).to eq(raw3)
end
it "does not delete quote if not first paragraph" do
reply = Fabricate(:post, topic: topic, raw: raw2)
reply = Fabricate(:post, user: user_with_auto_groups, topic: topic, raw: raw2)
CookedPostProcessor.new(reply).remove_full_quote_on_direct_reply
expect(topic.ordered_posts.pluck(:id)).to eq([post.id, reply.id])
expect(reply.raw).to eq(raw2)
@ -2094,22 +2205,33 @@ RSpec.describe CookedPostProcessor do
it "does nothing when 'remove_full_quote' is disabled" do
SiteSetting.remove_full_quote = false
reply = Fabricate(:post, topic: topic, raw: raw)
reply = Fabricate(:post, user: user_with_auto_groups, topic: topic, raw: raw)
CookedPostProcessor.new(reply).remove_full_quote_on_direct_reply
expect(reply.raw).to eq(raw)
end
it "does not generate a blank HTML document" do
post = Fabricate(:post, topic: topic, raw: "<sunday><monday>")
post = Fabricate(:post, user: user_with_auto_groups, topic: topic, raw: "<sunday><monday>")
cp = CookedPostProcessor.new(post)
cp.post_process
expect(cp.html).to eq("<p></p>")
end
it "works only on new posts" do
Fabricate(:post, topic: topic, hidden: true, raw: "this is the second post after")
Fabricate(:post, topic: topic, post_type: Post.types[:small_action])
Fabricate(
:post,
user: user_with_auto_groups,
topic: topic,
hidden: true,
raw: "this is the second post after",
)
Fabricate(
:post,
user: user_with_auto_groups,
topic: topic,
post_type: Post.types[:small_action],
)
reply = PostCreator.create!(topic.user, topic_id: topic.id, raw: raw)
stub_image_size
@ -2129,7 +2251,7 @@ RSpec.describe CookedPostProcessor do
it "works with nested quotes" do
reply1 = Fabricate(:post, user: user, topic: topic, raw: raw)
reply2 = Fabricate(:post, topic: topic, raw: <<~RAW.strip)
reply2 = Fabricate(:post, user: user_with_auto_groups, topic: topic, raw: <<~RAW.strip)
[quote="#{reply1.user.name}, post:#{reply1.post_number}, topic:#{topic.id}, username:#{reply1.user.username}"]
#{raw}
[/quote]
@ -2143,7 +2265,7 @@ RSpec.describe CookedPostProcessor do
end
describe "prioritizes full name in quotes" do
fab!(:user) { Fabricate(:user, name: "james, john, the third") }
fab!(:user) { Fabricate(:user, name: "james, john, the third", refresh_auto_groups: true) }
fab!(:topic)
let!(:post) { Fabricate(:post, user: user, topic: topic, raw: 'this is the "first" post') }
@ -2167,7 +2289,7 @@ RSpec.describe CookedPostProcessor do
describe "#html" do
it "escapes html entities in attributes per html5" do
post = Fabricate(:post, raw: '<img alt="&<something>">')
post = Fabricate(:post, user: user_with_auto_groups, raw: '<img alt="&<something>">')
expect(post.cook(post.raw)).to eq('<p><img alt="&amp;<something>"></p>')
expect(CookedPostProcessor.new(post).html).to eq('<p><img alt="&amp;<something>"></p>')
end

View File

@ -541,7 +541,13 @@ RSpec.describe Email::Sender do
#{UploadMarkdown.new(image).image_markdown}
#{UploadMarkdown.new(csv_file).attachment_markdown}
RAW
reply = Fabricate(:post, raw: raw, topic: post.topic, user: Fabricate(:user))
reply =
Fabricate(
:post,
raw: raw,
topic: post.topic,
user: Fabricate(:user, refresh_auto_groups: true),
)
reply.link_post_uploads
reply
end

View File

@ -290,10 +290,17 @@ RSpec.describe Search do
describe "post indexing" do
fab!(:category) { Fabricate(:category_with_definition, name: "america") }
fab!(:topic) { Fabricate(:topic, title: "sam saffron test topic", category: category) }
fab!(:user) { Fabricate(:user, refresh_auto_groups: true) }
let!(:post) do
Fabricate(:post, topic: topic, raw: 'this <b>fun test</b> <img src="bla" title="my image">')
Fabricate(
:post,
topic: topic,
raw: 'this <b>fun test</b> <img src="bla" title="my image">',
user: user,
)
end
let!(:post2) { Fabricate(:post, topic: topic) }
let!(:post2) { Fabricate(:post, topic: topic, user: user) }
it "should index correctly" do
search_data = post.post_search_data.search_data
@ -1995,8 +2002,9 @@ RSpec.describe Search do
end
it "can find posts with images" do
post_uploaded = Fabricate(:post_with_uploaded_image)
Fabricate(:post)
user = Fabricate(:user, refresh_auto_groups: true)
post_uploaded = Fabricate(:post_with_uploaded_image, user: user)
Fabricate(:post, user: user)
CookedPostProcessor.new(post_uploaded).update_post_image

View File

@ -1,13 +1,20 @@
# frozen_string_literal: true
RSpec.describe ShrinkUploadedImage do
fab!(:user) { Fabricate(:user, refresh_auto_groups: true) }
def create_post_with_upload
post = Fabricate(:post, raw: "<img src='#{upload.url}'>", user: user)
post.link_post_uploads
post
end
context "when local uploads are enabled" do
let(:upload) { Fabricate(:image_upload, width: 200, height: 200) }
it "resizes the image" do
create_post_with_upload
filesize_before = upload.filesize
post = Fabricate(:post, raw: "<img src='#{upload.url}'>")
post.link_post_uploads
result =
ShrinkUploadedImage.new(
@ -32,8 +39,7 @@ RSpec.describe ShrinkUploadedImage do
smaller_sha1 = Upload.generate_digest("/tmp/smaller.png")
smaller_upload = Fabricate(:image_upload, sha1: smaller_sha1)
post = Fabricate(:post, raw: "<img src='#{upload.url}'>")
post.link_post_uploads
post = create_post_with_upload
post_hotlinked_media =
PostHotlinkedMedia.create!(
post: post,
@ -63,8 +69,8 @@ RSpec.describe ShrinkUploadedImage do
end
it "returns false if the image cannot be shrunk more" do
post = Fabricate(:post, raw: "<img src='#{upload.url}'>")
post.link_post_uploads
create_post_with_upload
ShrinkUploadedImage.new(
upload: upload,
path: Discourse.store.path_for(upload),
@ -84,8 +90,7 @@ RSpec.describe ShrinkUploadedImage do
end
it "returns false when the upload is above the size limit" do
post = Fabricate(:post, raw: "<img src='#{upload.url}'>")
post.link_post_uploads
create_post_with_upload
SiteSetting.max_image_size_kb = 0
result =
@ -137,8 +142,7 @@ RSpec.describe ShrinkUploadedImage do
it "resizes the image" do
filesize_before = upload.filesize
post = Fabricate(:post, raw: "<img src='#{upload.url}'>")
post.link_post_uploads
create_post_with_upload
result =
ShrinkUploadedImage.new(

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
RSpec.describe UploadRecovery do
fab!(:user)
fab!(:user) { Fabricate(:user, refresh_auto_groups: true) }
let(:upload) do
UploadCreator.new(file_from_fixtures("smallest.png"), "logo.png").create_for(user.id)

View File

@ -184,42 +184,44 @@ RSpec.describe PostValidator do
end
describe "too_many_embedded_media" do
fab!(:new_user) { Fabricate(:newuser, refresh_auto_groups: true) }
before do
SiteSetting.min_trust_to_post_embedded_media = 0
SiteSetting.embedded_media_post_allowed_groups = Group::AUTO_GROUPS[:trust_level_0]
SiteSetting.newuser_max_embedded_media = 2
end
it "should be invalid when new user exceeds max mentions limit" do
post.acting_user = build(:newuser)
post.acting_user = new_user
post.expects(:embedded_media_count).returns(3)
validator.max_embedded_media_validator(post)
expect(post.errors.count).to be > 0
end
it "should be valid when new user does not exceed max mentions limit" do
post.acting_user = build(:newuser)
post.acting_user = new_user
post.expects(:embedded_media_count).returns(2)
validator.max_embedded_media_validator(post)
expect(post.errors.count).to be(0)
end
it "should be invalid when user trust level is not sufficient" do
SiteSetting.min_trust_to_post_embedded_media = 4
post.acting_user = build(:leader)
SiteSetting.embedded_media_post_allowed_groups = Group::AUTO_GROUPS[:trust_level_4]
post.acting_user = Fabricate(:leader, groups: [])
post.expects(:embedded_media_count).returns(2)
validator.max_embedded_media_validator(post)
expect(post.errors.count).to be > 0
end
it "should be valid for moderator in all cases" do
post.acting_user = build(:moderator)
post.acting_user = Fabricate(:moderator)
post.expects(:embedded_media_count).never
validator.max_embedded_media_validator(post)
expect(post.errors.count).to be(0)
end
it "should be valid for admin in all cases" do
post.acting_user = build(:admin)
post.acting_user = Fabricate(:admin)
post.expects(:embedded_media_count).never
validator.max_embedded_media_validator(post)
expect(post.errors.count).to be(0)

View File

@ -70,7 +70,8 @@ RSpec.describe Post do
it { is_expected.to rate_limit }
let(:topic) { Fabricate(:topic) }
fab!(:user) { Fabricate(:user, refresh_auto_groups: true) }
let(:topic) { Fabricate(:topic, user: user) }
let(:post_args) { { user: topic.user, topic: topic } }
describe "scopes" do
@ -336,36 +337,6 @@ RSpec.describe Post do
expect(post_one_image).to be_valid
end
it "doesn't allow more than `min_trust_to_post_embedded_media`" do
SiteSetting.min_trust_to_post_embedded_media = 4
post_one_image.user.trust_level = 3
expect(post_one_image).not_to be_valid
end
it "doesn't allow more than `min_trust_to_post_embedded_media` in a quote" do
SiteSetting.min_trust_to_post_embedded_media = 4
post_one_image.user.trust_level = 3
expect(post_image_within_quote).not_to be_valid
end
it "doesn't allow more than `min_trust_to_post_embedded_media` in code" do
SiteSetting.min_trust_to_post_embedded_media = 4
post_one_image.user.trust_level = 3
expect(post_image_within_code).not_to be_valid
end
it "doesn't allow more than `min_trust_to_post_embedded_media` in pre" do
SiteSetting.min_trust_to_post_embedded_media = 4
post_one_image.user.trust_level = 3
expect(post_image_within_pre).not_to be_valid
end
it "doesn't allow more than `min_trust_to_post_embedded_media`" do
SiteSetting.min_trust_to_post_embedded_media = 4
post_one_image.user.trust_level = 4
expect(post_one_image).to be_valid
end
it "doesn't count favicons as images" do
PrettyText.stubs(:cook).returns(post_with_favicon.raw)
expect(post_with_favicon.embedded_media_count).to eq(0)
@ -387,6 +358,40 @@ RSpec.describe Post do
expect(post_with_two_embedded_media.embedded_media_count).to eq(2)
end
describe "embedded_media_allowed_groups" do
before { Group.refresh_automatic_groups! }
it "doesn't allow users outside of `embedded_media_post_allowed_groups`" do
SiteSetting.embedded_media_post_allowed_groups = Group::AUTO_GROUPS[:trust_level_4]
post_one_image.user.change_trust_level!(3)
expect(post_one_image).not_to be_valid
end
it "doesn't allow users outside of `embedded_media_post_allowed_groups` in a quote" do
SiteSetting.embedded_media_post_allowed_groups = Group::AUTO_GROUPS[:trust_level_4]
post_one_image.user.change_trust_level!(3)
expect(post_image_within_quote).not_to be_valid
end
it "doesn't allow users outside of `embedded_media_post_allowed_groups` in code" do
SiteSetting.embedded_media_post_allowed_groups = Group::AUTO_GROUPS[:trust_level_4]
post_one_image.user.change_trust_level!(3)
expect(post_image_within_code).not_to be_valid
end
it "doesn't allow users outside of `embedded_media_post_allowed_groups` in pre" do
SiteSetting.embedded_media_post_allowed_groups = Group::AUTO_GROUPS[:trust_level_4]
post_one_image.user.change_trust_level!(3)
expect(post_image_within_pre).not_to be_valid
end
it "allows users who are in a group in `embedded_media_post_allowed_groups`" do
SiteSetting.embedded_media_post_allowed_groups = Group::AUTO_GROUPS[:trust_level_4]
post_one_image.user.change_trust_level!(4)
expect(post_one_image).to be_valid
end
end
context "with validation" do
before { SiteSetting.newuser_max_embedded_media = 1 }
@ -1760,7 +1765,7 @@ RSpec.describe Post do
end
describe "#update_uploads_secure_status" do
fab!(:user) { Fabricate(:user, trust_level: 0) }
fab!(:user) { Fabricate(:user, trust_level: 0, refresh_auto_groups: true) }
let(:raw) { <<~RAW }
<a href="#{attachment_upload.url}">Link</a>

View File

@ -454,14 +454,16 @@ RSpec.describe TrustLevel3Requirements do
end
describe "num_likes_received" do
before { UserActionManager.enable }
before do
UserActionManager.enable
Group.refresh_automatic_groups!
end
let(:topic) { Fabricate(:topic, user: user, created_at: 102.days.ago) }
let(:old_post) { create_post(topic: topic, user: user, created_at: 102.days.ago) }
let(:recent_post1) { create_post(topic: topic, user: user, created_at: 1.hour.ago) }
let(:recent_post2) { create_post(topic: topic, user: user, created_at: 10.days.ago) }
let(:private_post) do
Group.refresh_automatic_groups!
create_post(
user: user,
archetype: Archetype.private_message,

View File

@ -19,7 +19,12 @@ RSpec.describe Upload do
describe ".with_no_non_post_relations" do
it "does not find non-post related uploads" do
post_upload = Fabricate(:upload)
post = Fabricate(:post, raw: "<img src='#{post_upload.url}'>")
post =
Fabricate(
:post,
raw: "<img src='#{post_upload.url}'>",
user: Fabricate(:user, refresh_auto_groups: true),
)
post.link_post_uploads
badge_upload = Fabricate(:upload)

View File

@ -191,7 +191,8 @@ RSpec.describe UserSearch do
end
it "only reveals topic participants to people with permission" do
pm_topic = Fabricate(:private_message_post).topic
pm_topic =
Fabricate(:private_message_post, user: Fabricate(:user, refresh_auto_groups: true)).topic
# Anonymous, does not have access
expect do search_for("", topic_id: pm_topic.id) end.to raise_error(Discourse::InvalidAccess)
@ -201,7 +202,6 @@ RSpec.describe UserSearch do
Discourse::InvalidAccess,
)
Group.refresh_automatic_groups!
pm_topic.invite(pm_topic.user, mr_b.username)
results = search_for("", topic_id: pm_topic.id, searching_user: mr_b)

View File

@ -3194,6 +3194,8 @@ RSpec.describe TopicsController do
end
describe "image only topic" do
before { Group.refresh_automatic_groups! }
it "uses image alt tag for meta description" do
post =
Fabricate(

View File

@ -3,9 +3,9 @@
require "rotp"
RSpec.describe UsersController do
fab!(:user)
fab!(:user1) { Fabricate(:user, username: "someusername") }
fab!(:another_user) { Fabricate(:user) }
fab!(:user) { Fabricate(:user, refresh_auto_groups: true) }
fab!(:user1) { Fabricate(:user, username: "someusername", refresh_auto_groups: true) }
fab!(:another_user) { Fabricate(:user, refresh_auto_groups: true) }
fab!(:invitee) { Fabricate(:user) }
fab!(:inviter) { Fabricate(:user) }
@ -6786,10 +6786,9 @@ RSpec.describe UsersController do
end
describe "#private_message_topic_tracking_state" do
fab!(:user_2) { Fabricate(:user) }
fab!(:user_2) { Fabricate(:user, refresh_auto_groups: true) }
fab!(:private_message) do
Group.refresh_automatic_groups!
create_post(
user: user1,
target_usernames: [user_2.username],