diff --git a/app/assets/javascripts/discourse/controllers/topic.js.es6 b/app/assets/javascripts/discourse/controllers/topic.js.es6 index 5300e41c5af..77ef47499a3 100644 --- a/app/assets/javascripts/discourse/controllers/topic.js.es6 +++ b/app/assets/javascripts/discourse/controllers/topic.js.es6 @@ -393,6 +393,10 @@ export default ObjectController.extend(Discourse.SelectedPostsCount, { } else { post.set("post_type", moderator); } + }, + + rebakePost: function (post) { + post.rebake(); } }, diff --git a/app/assets/javascripts/discourse/models/_post.js b/app/assets/javascripts/discourse/models/_post.js index 8ca6f0d7d0f..5afb2491887 100644 --- a/app/assets/javascripts/discourse/models/_post.js +++ b/app/assets/javascripts/discourse/models/_post.js @@ -400,6 +400,10 @@ Discourse.Post = Discourse.Model.extend({ cooked_hidden: false }); }); + }, + + rebake: function () { + return Discourse.ajax("/posts/" + this.get("id") + "/rebake", { type: "PUT" }); } }); diff --git a/app/assets/javascripts/discourse/views/post-menu.js.es6 b/app/assets/javascripts/discourse/views/post-menu.js.es6 index 25c21e53999..f8e66106121 100644 --- a/app/assets/javascripts/discourse/views/post-menu.js.es6 +++ b/app/assets/javascripts/discourse/views/post-menu.js.es6 @@ -284,11 +284,15 @@ export default Discourse.View.extend({ postTypeIcon = '', postTypeText = isModerator ? I18n.t('post.controls.revert_to_regular') : I18n.t('post.controls.convert_to_moderator'); + var rebakePostIcon = '', + rebakePostText = I18n.t('post.controls.rebake'); + var html = '
' + '

' + I18n.t('admin_title') + '

' + '' + '
'; @@ -309,6 +313,10 @@ export default Discourse.View.extend({ this.get("controller").send("togglePostType", this.get("post")); }, + clickRebakePost: function () { + this.get("controller").send("rebakePost", this.get("post")); + }, + buttonForShowMoreActions: function() { return new Button('showMoreActions', 'show_more', 'ellipsis-h'); }, diff --git a/app/assets/javascripts/discourse/views/post_view.js b/app/assets/javascripts/discourse/views/post_view.js index 6c6ac9a818e..87038a02ac3 100644 --- a/app/assets/javascripts/discourse/views/post_view.js +++ b/app/assets/javascripts/discourse/views/post_view.js @@ -54,7 +54,7 @@ Discourse.PostView = Discourse.GroupedView.extend(Ember.Evented, { } var $adminMenu = this.get('adminMenu'); - if ($adminMenu && !$(e.target).is($adminMenu) && $adminMenu.has($(e.target)).length === 0) { + if ($adminMenu && !$(e.target).is($adminMenu)) { $adminMenu.hide(); this.set('adminMenu', null); } diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 0b6684019fc..105623a8d1c 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -252,6 +252,15 @@ class PostsController < ApplicationController render nothing: true end + def rebake + guardian.ensure_can_rebake! + + post = find_post_from_params + post.rebake!(invalidate_oneboxes: true) + + render nothing: true + end + def flagged_posts params.permit(:offset, :limit) guardian.ensure_can_see_flagged_posts! diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 9b32045c61e..89a24cb46e2 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -1111,6 +1111,7 @@ en: unwiki: "Unwiki post" revert_to_regular: "Regular post" convert_to_moderator: "Staff post" + rebake: "Rebake post" actions: flag: 'Flag' diff --git a/config/routes.rb b/config/routes.rb index 5e739e2f59e..13222d2c8b1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -264,6 +264,7 @@ Discourse::Application.routes.draw do put "bookmark" put "wiki" put "post_type" + put "rebake" get "replies" get "revisions/:revision" => "posts#revisions" put "recover" diff --git a/lib/guardian/post_guardian.rb b/lib/guardian/post_guardian.rb index 8218755bf3d..d6af0984234 100644 --- a/lib/guardian/post_guardian.rb +++ b/lib/guardian/post_guardian.rb @@ -169,6 +169,10 @@ module PostGuardian is_staff? end + def can_rebake? + is_staff? + end + def can_see_flagged_posts? is_staff? end diff --git a/spec/controllers/posts_controller_spec.rb b/spec/controllers/posts_controller_spec.rb index cadc660ac03..10e1d3cc257 100644 --- a/spec/controllers/posts_controller_spec.rb +++ b/spec/controllers/posts_controller_spec.rb @@ -327,7 +327,7 @@ describe PostsController do let(:user) {log_in} let(:post) {Fabricate(:post, user: user)} - it "raises an error if the user doesn't have permission to see the post" do + it "raises an error if the user doesn't have permission to wiki the post" do Guardian.any_instance.expects(:can_wiki?).returns(false) xhr :put, :wiki, post_id: post.id, wiki: 'true' @@ -358,6 +358,63 @@ describe PostsController do end + describe "post_type" do + + include_examples "action requires login", :put, :post_type, post_id: 2 + + describe "when logged in" do + let(:user) {log_in} + let(:post) {Fabricate(:post, user: user)} + + it "raises an error if the user doesn't have permission to change the post type" do + Guardian.any_instance.expects(:can_change_post_type?).returns(false) + + xhr :put, :post_type, post_id: post.id, post_type: 2 + + response.should be_forbidden + end + + it "can change the post type" do + Guardian.any_instance.expects(:can_change_post_type?).returns(true) + + xhr :put, :post_type, post_id: post.id, post_type: 2 + + post.reload + post.post_type.should == 2 + end + + end + + end + + describe "rebake" do + + include_examples "action requires login", :put, :rebake, post_id: 2 + + describe "when logged in" do + let(:user) {log_in} + let(:post) {Fabricate(:post, user: user)} + + it "raises an error if the user doesn't have permission to rebake the post" do + Guardian.any_instance.expects(:can_rebake?).returns(false) + + xhr :put, :rebake, post_id: post.id + + response.should be_forbidden + end + + it "can rebake the post" do + Guardian.any_instance.expects(:can_rebake?).returns(true) + + xhr :put, :rebake, post_id: post.id + + response.should be_success + end + + end + + end + describe 'creating a post' do include_examples 'action requires login', :post, :create