mirror of
https://github.com/discourse/discourse.git
synced 2024-11-23 06:04:11 +08:00
8ebd5edd1e
This commit renames all secure_media related settings to secure_uploads_* along with the associated functionality. This is being done because "media" does not really cover it, we aren't just doing this for images and videos etc. but for all uploads in the site. Additionally, in future we want to secure more types of uploads, and enable a kind of "mixed mode" where some uploads are secure and some are not, so keeping media in the name is just confusing. This also keeps compatibility with the `secure-media-uploads` path, and changes new secure URLs to be `secure-uploads`. Deprecated settings: * secure_media -> secure_uploads * secure_media_allow_embed_images_in_emails -> secure_uploads_allow_embed_images_in_emails * secure_media_max_email_embed_image_size_kb -> secure_uploads_max_email_embed_image_size_kb
94 lines
3.6 KiB
Ruby
94 lines
3.6 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
##
|
|
# There are certain conditions with secure uploads when the security of
|
|
# uploads will need to change depending on the context they reside in.
|
|
#
|
|
# For example on these conditions:
|
|
# * Topic category change
|
|
# * Topic switching between PM and public topic
|
|
# * Post moving between topics
|
|
#
|
|
# We need to go through all of the posts in that topic that
|
|
# own uploads via access_control_post_id, then for those uploads determine
|
|
# if they still need to be secure or not. For example an upload could be
|
|
# secure if it is in a PM, and then when the topic gets converted to a public
|
|
# topic the upload no longer needs to remain secure as it is no longer in
|
|
# a secure context.
|
|
class TopicUploadSecurityManager
|
|
def initialize(topic)
|
|
@topic = topic
|
|
end
|
|
|
|
def run
|
|
Rails.logger.debug("Updating upload security in topic #{@topic.id}")
|
|
posts_owning_uploads.each do |post|
|
|
Post.transaction do
|
|
Rails.logger.debug("Updating upload security in topic #{@topic.id} - post #{post.id}")
|
|
post.topic = @topic
|
|
|
|
secure_status_did_change = post.owned_uploads_via_access_control.any? do |upload|
|
|
# we have already got the post preloaded so we may as well
|
|
# attach it here to avoid another load in UploadSecurity
|
|
upload.access_control_post = post
|
|
upload.update_secure_status(source: "topic upload security")
|
|
end
|
|
post.rebake! if secure_status_did_change
|
|
Rails.logger.debug("Security updated & rebake complete in topic #{@topic.id} - post #{post.id}")
|
|
end
|
|
end
|
|
|
|
return if !SiteSetting.secure_uploads
|
|
|
|
# we only want to do this if secure uploads is enabled. if
|
|
# the setting is turned on after a site has been running
|
|
# already, we want to make sure that any post moves after
|
|
# this are handled and upload secure statuses and ACLs
|
|
# are updated appropriately, as well as setting the access control
|
|
# post for secure uploads missing it.
|
|
#
|
|
# examples (all after secure uploads is enabled):
|
|
#
|
|
# -> a public topic is moved to a private category after
|
|
# -> a PM is converted to a public topic
|
|
# -> a public topic is converted to a PM
|
|
# -> a topic is moved from a private to a public category
|
|
posts_with_unowned_uploads.each do |post|
|
|
Post.transaction do
|
|
Rails.logger.debug("Setting upload access control posts in topic #{@topic.id} - post #{post.id}")
|
|
post.topic = @topic
|
|
|
|
secure_status_did_change = post.uploads.any? do |upload|
|
|
first_post_upload_appeared_in = upload.upload_references.where(target_type: 'Post').first.target
|
|
if first_post_upload_appeared_in == post
|
|
upload.update(access_control_post: post)
|
|
upload.update_secure_status(source: "topic upload security")
|
|
else
|
|
false
|
|
end
|
|
end
|
|
|
|
post.rebake! if secure_status_did_change
|
|
Rails.logger.debug("Completed changing access control posts #{secure_status_did_change ? 'and rebaking' : ''} in topic #{@topic.id} - post #{post.id}")
|
|
end
|
|
end
|
|
|
|
Rails.logger.debug("Completed updating upload security in topic #{@topic.id}!")
|
|
end
|
|
|
|
private
|
|
|
|
def posts_owning_uploads
|
|
Post.where(topic_id: @topic.id).joins('INNER JOIN uploads ON access_control_post_id = posts.id')
|
|
end
|
|
|
|
def posts_with_unowned_uploads
|
|
Post
|
|
.where(topic_id: @topic.id)
|
|
.joins("INNER JOIN upload_references ON upload_references.target_type = 'Post' AND upload_references.target_id = posts.id")
|
|
.joins('INNER JOIN uploads ON upload_references.upload_id = uploads.id')
|
|
.where('uploads.access_control_post_id IS NULL')
|
|
.includes(:uploads)
|
|
end
|
|
end
|