FIX: Clear drafts only when post is created by real user (#15720)

This commits adds a new advance_draft to PostCreator that controls if
the draft sequence will be advanced or not. If the draft sequence is
advanced then the old drafts will be cleared. This used to happen for
posts created by plugins or through the API and cleared user drafts
by mistake.
This commit is contained in:
Bianca Nenciu 2022-02-09 10:37:38 +02:00 committed by GitHub
parent c1ad9c3276
commit f704deca17
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 37 additions and 8 deletions

View File

@ -182,6 +182,7 @@ class PostsController < ApplicationController
def create def create
@manager_params = create_params @manager_params = create_params
@manager_params[:first_post_checks] = !is_api? @manager_params[:first_post_checks] = !is_api?
@manager_params[:advance_draft] = !is_api?
manager = NewPostManager.new(current_user, @manager_params) manager = NewPostManager.new(current_user, @manager_params)

View File

@ -330,6 +330,7 @@ class Topic < ActiveRecord::Base
attr_accessor :ignore_category_auto_close attr_accessor :ignore_category_auto_close
attr_accessor :skip_callbacks attr_accessor :skip_callbacks
attr_accessor :advance_draft
before_create do before_create do
initialize_default_values initialize_default_values
@ -338,7 +339,7 @@ class Topic < ActiveRecord::Base
after_create do after_create do
unless skip_callbacks unless skip_callbacks
changed_to_category(category) changed_to_category(category)
advance_draft_sequence advance_draft_sequence if advance_draft
end end
end end

View File

@ -36,6 +36,7 @@ class PostCreator
# hidden_reason_id - Reason for hiding the post (optional) # hidden_reason_id - Reason for hiding the post (optional)
# skip_validations - Do not validate any of the content in the post # skip_validations - Do not validate any of the content in the post
# draft_key - the key of the draft we are creating (will be deleted on success) # draft_key - the key of the draft we are creating (will be deleted on success)
# advance_draft - Destroy draft after creating post or topic
# silent - Do not update topic stats and fields like last_post_user_id # silent - Do not update topic stats and fields like last_post_user_id
# #
# When replying to a topic: # When replying to a topic:
@ -218,7 +219,7 @@ class PostCreator
delete_owned_bookmarks delete_owned_bookmarks
ensure_in_allowed_users if guardian.is_staff? ensure_in_allowed_users if guardian.is_staff?
unarchive_message if !@opts[:import_mode] unarchive_message if !@opts[:import_mode]
DraftSequence.next!(@user, draft_key) if !@opts[:import_mode] DraftSequence.next!(@user, draft_key) if !@opts[:import_mode] && @opts[:advance_draft]
@post.save_reply_relationships @post.save_reply_relationships
end end
end end

View File

@ -111,7 +111,7 @@ class TopicCreator
visible: @opts[:visible] visible: @opts[:visible]
} }
[:subtype, :archetype, :meta_data, :import_mode].each do |key| [:subtype, :archetype, :meta_data, :import_mode, :advance_draft].each do |key|
topic_params[key] = @opts[key] if @opts[key].present? topic_params[key] = @opts[key] if @opts[key].present?
end end

View File

@ -14,7 +14,7 @@ describe PostCreator do
context "new topic" do context "new topic" do
fab!(:category) { Fabricate(:category, user: user) } fab!(:category) { Fabricate(:category, user: user) }
let(:basic_topic_params) { { title: "hello world topic", raw: "my name is fred", archetype_id: 1 } } let(:basic_topic_params) { { title: "hello world topic", raw: "my name is fred", archetype_id: 1, advance_draft: true } }
let(:image_sizes) { { 'http://an.image.host/image.jpg' => { "width" => 111, "height" => 222 } } } let(:image_sizes) { { 'http://an.image.host/image.jpg' => { "width" => 111, "height" => 222 } } }
let(:creator) { PostCreator.new(user, basic_topic_params) } let(:creator) { PostCreator.new(user, basic_topic_params) }
@ -150,7 +150,7 @@ describe PostCreator do
messages = MessageBus.track_publish do messages = MessageBus.track_publish do
created_post = PostCreator.new(admin, basic_topic_params.merge(category: cat.id)).create created_post = PostCreator.new(admin, basic_topic_params.merge(category: cat.id)).create
_reply = PostCreator.new(admin, raw: "this is my test reply 123 testing", topic_id: created_post.topic_id).create _reply = PostCreator.new(admin, raw: "this is my test reply 123 testing", topic_id: created_post.topic_id, advance_draft: true).create
end end
messages.filter! { |m| m.channel != "/distributed_hash" } messages.filter! { |m| m.channel != "/distributed_hash" }
@ -303,6 +303,20 @@ describe PostCreator do
end end
end end
it 'clears the draft if advanced_draft is true' do
creator = PostCreator.new(user, basic_topic_params.merge(advance_draft: true))
Draft.set(user, Draft::NEW_TOPIC, 0, 'test')
expect(Draft.where(user: user).size).to eq(1)
expect { creator.create }.to change { Draft.count }.by(-1)
end
it 'does not clear the draft if advanced_draft is false' do
creator = PostCreator.new(user, basic_topic_params.merge(advance_draft: false))
Draft.set(user, Draft::NEW_TOPIC, 0, 'test')
expect(Draft.where(user: user).size).to eq(1)
expect { creator.create }.to change { Draft.count }.by(0)
end
it "updates topic stats" do it "updates topic stats" do
first_post = creator.create first_post = creator.create
topic = first_post.topic.reload topic = first_post.topic.reload

View File

@ -227,7 +227,7 @@ describe Draft do
context 'key expiry' do context 'key expiry' do
it 'nukes new topic draft after a topic is created' do it 'nukes new topic draft after a topic is created' do
Draft.set(user, Draft::NEW_TOPIC, 0, 'my draft') Draft.set(user, Draft::NEW_TOPIC, 0, 'my draft')
_t = Fabricate(:topic, user: user) _t = Fabricate(:topic, user: user, advance_draft: true)
s = DraftSequence.current(user, Draft::NEW_TOPIC) s = DraftSequence.current(user, Draft::NEW_TOPIC)
expect(Draft.get(user, Draft::NEW_TOPIC, s)).to eq nil expect(Draft.get(user, Draft::NEW_TOPIC, s)).to eq nil
expect(Draft.count).to eq 0 expect(Draft.count).to eq 0
@ -235,7 +235,7 @@ describe Draft do
it 'nukes new pm draft after a pm is created' do it 'nukes new pm draft after a pm is created' do
Draft.set(user, Draft::NEW_PRIVATE_MESSAGE, 0, 'my draft') Draft.set(user, Draft::NEW_PRIVATE_MESSAGE, 0, 'my draft')
t = Fabricate(:topic, user: user, archetype: Archetype.private_message, category_id: nil) t = Fabricate(:topic, user: user, archetype: Archetype.private_message, category_id: nil, advance_draft: true)
s = DraftSequence.current(t.user, Draft::NEW_PRIVATE_MESSAGE) s = DraftSequence.current(t.user, Draft::NEW_PRIVATE_MESSAGE)
expect(Draft.get(user, Draft::NEW_PRIVATE_MESSAGE, s)).to eq nil expect(Draft.get(user, Draft::NEW_PRIVATE_MESSAGE, s)).to eq nil
end end
@ -252,7 +252,7 @@ describe Draft do
Draft.set(user, topic.draft_key, 0, 'hello') Draft.set(user, topic.draft_key, 0, 'hello')
p = PostCreator.new(user, raw: Fabricate.build(:post).raw, topic_id: topic.id).create p = PostCreator.new(user, raw: Fabricate.build(:post).raw, topic_id: topic.id, advance_draft: true).create
expect(Draft.get(p.user, p.topic.draft_key, DraftSequence.current(p.user, p.topic.draft_key))).to eq nil expect(Draft.get(p.user, p.topic.draft_key, DraftSequence.current(p.user, p.topic.draft_key))).to eq nil
end end

View File

@ -861,6 +861,18 @@ describe PostsController do
expect(response.status).to eq(403) expect(response.status).to eq(403)
end end
it 'does not advance draft' do
Draft.set(user, Draft::NEW_TOPIC, 0, "test")
user_key = ApiKey.create!(user: user).key
post "/posts.json",
params: { title: 'this is a test topic', raw: 'this is test whisper' },
headers: { HTTP_API_USERNAME: user.username, HTTP_API_KEY: user_key }
expect(response.status).to eq(200)
expect(Draft.get(user, Draft::NEW_TOPIC, 0)).to eq("test")
end
it 'will raise an error if specified category cannot be found' do it 'will raise an error if specified category cannot be found' do
user = Fabricate(:admin) user = Fabricate(:admin)
master_key = Fabricate(:api_key).key master_key = Fabricate(:api_key).key