DEV: Add security_last_changed_at and security_last_changed_reason to uploads (#11860)

This PR adds security_last_changed_at and security_last_changed_reason to uploads. This has been done to make it easier to track down why an upload's secure column has changed and when. This necessitated a refactor of the UploadSecurity class to provide reasons why the upload security would have changed.

As well as this, a source is now provided from the location which called for the upload's security status to be updated as they are several (e.g. post creator, topic security updater, rake tasks, manual change).
This commit is contained in:
Martin Brennan
2021-01-29 09:03:44 +10:00
committed by GitHub
parent 0990112d80
commit f49e3e5731
13 changed files with 182 additions and 87 deletions

View File

@@ -951,9 +951,9 @@ class Post < ActiveRecord::Base
end
end
def update_uploads_secure_status
def update_uploads_secure_status(source:)
if Discourse.store.external?
self.uploads.each { |upload| upload.update_secure_status }
self.uploads.each { |upload| upload.update_secure_status(source: source) }
end
end

View File

@@ -865,6 +865,14 @@ class Topic < ActiveRecord::Base
Jobs.enqueue(:notify_category_change, post_id: post.id, notified_user_ids: notified_user_ids)
end
end
# when a topic changes category we may need to make uploads
# linked to posts secure/not secure depending on whether the
# category is private. this is only done if the category
# has actually changed to avoid noise.
DB.after_commit do
Jobs.enqueue(:update_topic_upload_security, topic_id: self.id)
end
end
Category.where(id: new_category.id).update_all("topic_count = topic_count + 1")
@@ -873,13 +881,6 @@ class Topic < ActiveRecord::Base
CategoryFeaturedTopic.feature_topics_for(old_category) unless @import_mode
CategoryFeaturedTopic.feature_topics_for(new_category) unless @import_mode || old_category.try(:id) == new_category.id
end
# when a topic changes category we may need to make uploads
# linked to posts secure/not secure depending on whether the
# category is private
DB.after_commit do
Jobs.enqueue(:update_topic_upload_security, topic_id: self.id)
end
end
true

View File

@@ -311,16 +311,30 @@ class Upload < ActiveRecord::Base
self.posts.where("cooked LIKE '%/_optimized/%'").find_each(&:rebake!)
end
def update_secure_status(secure_override_value: nil)
mark_secure = secure_override_value.nil? ? UploadSecurity.new(self).should_be_secure? : secure_override_value
def update_secure_status(source: "unknown", override: nil)
if override.nil?
mark_secure, reason = UploadSecurity.new(self).should_be_secure_with_reason
else
mark_secure = override
reason = "manually overridden"
end
secure_status_did_change = self.secure? != mark_secure
self.update_column("secure", mark_secure)
self.update(secure_params(mark_secure, reason, source))
Discourse.store.update_upload_ACL(self) if Discourse.store.external?
secure_status_did_change
end
def secure_params(secure, reason, source = "unknown")
{
secure: secure,
security_last_changed_reason: reason + " | source: #{source}",
security_last_changed_at: Time.zone.now
}
end
def self.migrate_to_new_scheme(limit: nil)
problems = []
@@ -451,27 +465,29 @@ end
#
# Table name: uploads
#
# id :integer not null, primary key
# user_id :integer not null
# original_filename :string not null
# filesize :integer not null
# width :integer
# height :integer
# url :string not null
# created_at :datetime not null
# updated_at :datetime not null
# sha1 :string(40)
# origin :string(1000)
# retain_hours :integer
# extension :string(10)
# thumbnail_width :integer
# thumbnail_height :integer
# etag :string
# secure :boolean default(FALSE), not null
# access_control_post_id :bigint
# original_sha1 :string
# verification_status :integer default(1), not null
# animated :boolean
# id :integer not null, primary key
# user_id :integer not null
# original_filename :string not null
# filesize :integer not null
# width :integer
# height :integer
# url :string not null
# created_at :datetime not null
# updated_at :datetime not null
# sha1 :string(40)
# origin :string(1000)
# retain_hours :integer
# extension :string(10)
# thumbnail_width :integer
# thumbnail_height :integer
# etag :string
# secure :boolean default(FALSE), not null
# access_control_post_id :bigint
# original_sha1 :string
# verification_status :integer default(1), not null
# animated :boolean
# security_last_changed_at :datetime
# security_last_changed_reason :string
#
# Indexes
#