FIX: properly ban non human users from draft system
Previously we had a partial fix in place where non human users were not allowed draft sequences, this left edges around where non human users asked for drafts yet had none. For example system could already have a few drafts in place. This also removes and extensibility point we added that is not in use
This commit is contained in:
parent
979093787f
commit
fc97f7e0e7
|
@ -10,6 +10,8 @@ class Draft < ActiveRecord::Base
|
||||||
class OutOfSequence < StandardError; end
|
class OutOfSequence < StandardError; end
|
||||||
|
|
||||||
def self.set(user, key, sequence, data, owner = nil)
|
def self.set(user, key, sequence, data, owner = nil)
|
||||||
|
return 0 if !User.human_user_id?(user.id)
|
||||||
|
|
||||||
if SiteSetting.backup_drafts_to_pm_length > 0 && SiteSetting.backup_drafts_to_pm_length < data.length
|
if SiteSetting.backup_drafts_to_pm_length > 0 && SiteSetting.backup_drafts_to_pm_length < data.length
|
||||||
backup_draft(user, key, sequence, data)
|
backup_draft(user, key, sequence, data)
|
||||||
end
|
end
|
||||||
|
@ -94,6 +96,7 @@ class Draft < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.get(user, key, sequence)
|
def self.get(user, key, sequence)
|
||||||
|
return if !user || !user.id || !User.human_user_id?(user.id)
|
||||||
|
|
||||||
opts = {
|
opts = {
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
|
@ -128,6 +131,8 @@ class Draft < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.clear(user, key, sequence)
|
def self.clear(user, key, sequence)
|
||||||
|
return if !user || !user.id || !User.human_user_id?(user.id)
|
||||||
|
|
||||||
current_sequence = DraftSequence.current(user, key)
|
current_sequence = DraftSequence.current(user, key)
|
||||||
|
|
||||||
# bad caller is a reason to complain
|
# bad caller is a reason to complain
|
||||||
|
|
|
@ -2,10 +2,12 @@
|
||||||
|
|
||||||
class DraftSequence < ActiveRecord::Base
|
class DraftSequence < ActiveRecord::Base
|
||||||
def self.next!(user, key)
|
def self.next!(user, key)
|
||||||
|
return nil if !user
|
||||||
|
|
||||||
user_id = user
|
user_id = user
|
||||||
user_id = user.id unless user.is_a?(Integer)
|
user_id = user.id unless user.is_a?(Integer)
|
||||||
|
|
||||||
return 0 if invalid_user_id?(user_id)
|
return 0 if !User.human_user_id?(user_id)
|
||||||
|
|
||||||
h = { user_id: user_id, draft_key: key }
|
h = { user_id: user_id, draft_key: key }
|
||||||
c = DraftSequence.find_by(h)
|
c = DraftSequence.find_by(h)
|
||||||
|
@ -18,27 +20,17 @@ class DraftSequence < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.current(user, key)
|
def self.current(user, key)
|
||||||
return nil unless user
|
return nil if !user
|
||||||
|
|
||||||
user_id = user
|
user_id = user
|
||||||
user_id = user.id unless user.is_a?(Integer)
|
user_id = user.id unless user.is_a?(Integer)
|
||||||
|
|
||||||
return 0 if invalid_user_id?(user_id)
|
return 0 if !User.human_user_id?(user_id)
|
||||||
|
|
||||||
# perf critical path
|
# perf critical path
|
||||||
r, _ = DB.query_single('select sequence from draft_sequences where user_id = ? and draft_key = ?', user_id, key)
|
r, _ = DB.query_single('select sequence from draft_sequences where user_id = ? and draft_key = ?', user_id, key)
|
||||||
r.to_i
|
r.to_i
|
||||||
end
|
end
|
||||||
|
|
||||||
cattr_accessor :plugin_ignore_draft_sequence_callbacks
|
|
||||||
self.plugin_ignore_draft_sequence_callbacks = {}
|
|
||||||
|
|
||||||
def self.invalid_user_id?(user_id)
|
|
||||||
user_id < 0 || self.plugin_ignore_draft_sequence_callbacks.any? do |plugin, callback|
|
|
||||||
plugin.enabled? ? callback.call(user_id) : false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
private_class_method :invalid_user_id?
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# == Schema Information
|
# == Schema Information
|
||||||
|
|
|
@ -306,8 +306,12 @@ class User < ActiveRecord::Base
|
||||||
fields.uniq
|
fields.uniq
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.human_user_id?(user_id)
|
||||||
|
user_id > 0
|
||||||
|
end
|
||||||
|
|
||||||
def human?
|
def human?
|
||||||
self.id > 0
|
User.human_user_id?(self.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def bot?
|
def bot?
|
||||||
|
|
|
@ -405,15 +405,6 @@ class Plugin::Instance
|
||||||
SeedFu.fixture_paths.concat(paths)
|
SeedFu.fixture_paths.concat(paths)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Applies to all sites in a multisite environment. Block is not called if
|
|
||||||
# plugin is not enabled. Block is called with `user_id` and has to return a
|
|
||||||
# boolean based on whether the given `user_id` should be ignored.
|
|
||||||
def register_ignore_draft_sequence_callback(&block)
|
|
||||||
reloadable_patch do |plugin|
|
|
||||||
::DraftSequence.plugin_ignore_draft_sequence_callbacks[plugin] = block
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def listen_for(event_name)
|
def listen_for(event_name)
|
||||||
return unless self.respond_to?(event_name)
|
return unless self.respond_to?(event_name)
|
||||||
DiscourseEvent.on(event_name, &self.method(event_name))
|
DiscourseEvent.on(event_name, &self.method(event_name))
|
||||||
|
|
|
@ -12,6 +12,22 @@ describe Draft do
|
||||||
Fabricate(:post)
|
Fabricate(:post)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'system user' do
|
||||||
|
it "can not set drafts" do
|
||||||
|
# fake a sequence
|
||||||
|
DraftSequence.create!(user_id: Discourse.system_user.id, draft_key: "abc", sequence: 10)
|
||||||
|
|
||||||
|
seq = Draft.set(Discourse.system_user, "abc", 0, { reply: 'hi' }.to_json)
|
||||||
|
expect(seq).to eq(0)
|
||||||
|
|
||||||
|
draft = Draft.get(Discourse.system_user, "abc", 0)
|
||||||
|
expect(draft).to eq(nil)
|
||||||
|
|
||||||
|
draft = Draft.get(Discourse.system_user, "abc", 1)
|
||||||
|
expect(draft).to eq(nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'backup_drafts_to_pm_length' do
|
context 'backup_drafts_to_pm_length' do
|
||||||
it "correctly backs up drafts to a personal message" do
|
it "correctly backs up drafts to a personal message" do
|
||||||
SiteSetting.backup_drafts_to_pm_length = 1
|
SiteSetting.backup_drafts_to_pm_length = 1
|
||||||
|
|
Loading…
Reference in New Issue