2013-02-05 14:16:51 -05:00
require_dependency 'post_creator'
2013-03-18 17:52:29 -04:00
require_dependency 'post_destroyer'
2013-07-29 12:25:19 +10:00
require_dependency 'distributed_memoizer'
2013-02-05 14:16:51 -05:00
class PostsController < ApplicationController
# Need to be logged in for all actions here
2013-12-12 03:41:34 +01:00
before_filter :ensure_logged_in , except : [ :show , :replies , :by_number , :short_link , :reply_history , :revisions ]
2013-02-05 14:16:51 -05:00
2013-04-24 18:05:35 +10:00
skip_before_filter :store_incoming_links , only : [ :short_link ]
2013-04-30 16:29:57 +10:00
skip_before_filter :check_xhr , only : [ :markdown , :short_link ]
def markdown
post = Post . where ( topic_id : params [ :topic_id ] . to_i , post_number : ( params [ :post_number ] || 1 ) . to_i ) . first
if post && guardian . can_see? ( post )
render text : post . raw , content_type : 'text/plain'
else
raise Discourse :: NotFound
end
end
2013-04-24 18:05:35 +10:00
def short_link
post = Post . find ( params [ :post_id ] . to_i )
2013-04-26 16:18:41 +10:00
IncomingLink . add ( request , current_user )
2013-04-24 18:05:35 +10:00
redirect_to post . url
end
2013-02-05 14:16:51 -05:00
def create
2013-07-29 12:25:19 +10:00
params = create_params
2013-05-10 16:58:23 -04:00
2013-07-29 12:25:19 +10:00
key = params_key ( params )
2013-11-26 10:21:41 +11:00
error_json = nil
2013-05-10 16:58:23 -04:00
2013-11-26 10:21:41 +11:00
payload = DistributedMemoizer . memoize ( key , 120 ) do
2013-07-29 12:25:19 +10:00
post_creator = PostCreator . new ( current_user , params )
post = post_creator . create
if post_creator . errors . present?
# If the post was spam, flag all the user's posts as spam
current_user . flag_linked_posts_as_spam if post_creator . spam?
2013-11-26 10:21:41 +11:00
error_json = MultiJson . dump ( errors : post_creator . errors . full_messages )
raise Discourse :: InvalidPost
2013-07-29 12:25:19 +10:00
else
post_serializer = PostSerializer . new ( post , scope : guardian , root : false )
post_serializer . topic_slug = post . topic . slug if post . topic . present?
post_serializer . draft_sequence = DraftSequence . current ( current_user , post . topic . draft_key )
2013-11-26 10:21:41 +11:00
MultiJson . dump ( post_serializer )
2013-07-29 12:25:19 +10:00
end
2013-02-05 14:16:51 -05:00
end
2013-11-26 10:21:41 +11:00
render json : payload
2013-07-29 12:25:19 +10:00
2013-11-26 10:21:41 +11:00
rescue Discourse :: InvalidPost
render json : error_json , status : 422
2013-02-05 14:16:51 -05:00
end
def update
2013-06-06 00:14:32 -07:00
params . require ( :post )
2013-02-07 16:45:24 +01:00
2014-01-06 18:12:51 +11:00
post = Post . where ( id : params [ :id ] )
post = post . with_deleted if guardian . is_staff?
post = post . first
2013-02-21 18:09:56 -05:00
post . image_sizes = params [ :image_sizes ] if params [ :image_sizes ] . present?
2014-01-07 10:32:09 -05:00
2014-02-18 17:19:38 +01:00
if too_late_to ( :edit , post )
2014-01-07 10:32:09 -05:00
render json : { errors : [ I18n . t ( 'too_late_to_edit' ) ] } , status : 422
return
end
2013-02-21 18:09:56 -05:00
guardian . ensure_can_edit! ( post )
2013-04-10 11:00:50 +02:00
# to stay consistent with the create api,
2013-03-26 23:49:23 -07:00
# we should allow for title changes and category changes here
2013-12-12 03:41:34 +01:00
# we should also move all of this to a post updater.
2013-04-10 11:00:50 +02:00
if post . post_number == 1 && ( params [ :title ] || params [ :post ] [ :category ] )
2013-12-12 03:41:34 +01:00
post . topic . acting_user = current_user
2013-03-26 23:49:23 -07:00
post . topic . title = params [ :title ] if params [ :title ]
2013-04-10 11:00:50 +02:00
Topic . transaction do
2013-03-26 23:49:23 -07:00
post . topic . change_category ( params [ :post ] [ :category ] )
post . topic . save
end
if post . topic . errors . present?
render_json_error ( post . topic )
return
end
end
2013-02-21 18:09:56 -05:00
revisor = PostRevisor . new ( post )
2013-11-15 23:28:16 +01:00
if revisor . revise! ( current_user , params [ :post ] [ :raw ] , edit_reason : params [ :post ] [ :edit_reason ] )
2013-02-21 18:09:56 -05:00
TopicLink . extract_from ( post )
2013-02-05 14:16:51 -05:00
end
2013-02-21 18:09:56 -05:00
if post . errors . present?
render_json_error ( post )
2013-02-05 14:16:51 -05:00
return
end
2013-02-21 18:09:56 -05:00
post_serializer = PostSerializer . new ( post , scope : guardian , root : false )
post_serializer . draft_sequence = DraftSequence . current ( current_user , post . topic . draft_key )
2013-06-05 16:10:26 +10:00
link_counts = TopicLink . counts_for ( guardian , post . topic , [ post ] )
2013-02-21 18:09:56 -05:00
post_serializer . single_post_link_counts = link_counts [ post . id ] if link_counts . present?
2013-03-27 22:53:11 -07:00
post_serializer . topic_slug = post . topic . slug if post . topic . present?
2013-02-21 18:09:56 -05:00
result = { post : post_serializer . as_json }
if revisor . category_changed . present?
2013-05-10 16:47:47 +10:00
result [ :category ] = BasicCategorySerializer . new ( revisor . category_changed , scope : guardian , root : false ) . as_json
2013-02-21 18:09:56 -05:00
end
render_json_dump ( result )
2013-02-05 14:16:51 -05:00
end
2013-12-12 03:41:34 +01:00
def show
@post = find_post_from_params
@post . revert_to ( params [ :version ] . to_i ) if params [ :version ] . present?
render_post_json ( @post )
end
2013-02-05 14:16:51 -05:00
def by_number
2014-02-19 17:41:17 +01:00
finder = Post . where ( topic_id : params [ :topic_id ] , post_number : params [ :post_number ] )
finder = finder . with_deleted if current_user . try ( :staff? )
@post = finder . first
2013-02-07 16:45:24 +01:00
guardian . ensure_can_see! ( @post )
2013-02-05 14:16:51 -05:00
@post . revert_to ( params [ :version ] . to_i ) if params [ :version ] . present?
2013-07-22 17:48:24 +10:00
render_post_json ( @post )
2013-02-05 14:16:51 -05:00
end
2013-08-06 17:42:36 -04:00
def reply_history
2014-02-20 17:38:13 +01:00
post = find_post_from_params
render_serialized ( post . reply_history , PostSerializer )
2013-08-06 17:42:36 -04:00
end
2013-02-05 14:16:51 -05:00
def destroy
2013-02-08 17:49:15 -05:00
post = find_post_from_params
2014-01-07 10:32:09 -05:00
2014-02-18 17:19:38 +01:00
if too_late_to ( :delete_post , post )
2014-01-07 10:32:09 -05:00
render json : { errors : [ I18n . t ( 'too_late_to_edit' ) ] } , status : 422
return
end
2013-02-07 15:12:55 -05:00
guardian . ensure_can_delete! ( post )
2013-03-18 17:52:29 -04:00
destroyer = PostDestroyer . new ( current_user , post )
destroyer . destroy
2013-02-07 15:12:55 -05:00
render nothing : true
end
def recover
2013-02-08 17:49:15 -05:00
post = find_post_from_params
2013-02-07 15:12:55 -05:00
guardian . ensure_can_recover_post! ( post )
2013-07-22 17:48:24 +10:00
destroyer = PostDestroyer . new ( current_user , post )
destroyer . recover
post . reload
2013-07-09 12:15:55 -04:00
2013-07-22 17:48:24 +10:00
render_post_json ( post )
2013-02-05 14:16:51 -05:00
end
def destroy_many
2013-06-06 00:14:32 -07:00
params . require ( :post_ids )
2013-02-05 14:16:51 -05:00
2013-09-04 11:53:00 -04:00
posts = Post . where ( id : post_ids_including_replies )
2013-02-05 14:16:51 -05:00
raise Discourse :: InvalidParameters . new ( :post_ids ) if posts . blank?
# Make sure we can delete the posts
posts . each { | p | guardian . ensure_can_delete! ( p ) }
Post . transaction do
2013-09-04 20:50:58 -04:00
posts . each { | p | PostDestroyer . new ( current_user , p ) . destroy }
2013-02-05 14:16:51 -05:00
end
render nothing : true
end
# Direct replies to this post
def replies
2013-02-08 17:49:15 -05:00
post = find_post_from_params
2013-02-05 14:16:51 -05:00
render_serialized ( post . replies , PostSerializer )
end
2013-12-12 03:41:34 +01:00
def revisions
post_revision = find_post_revision_from_params
post_revision_serializer = PostRevisionSerializer . new ( post_revision , scope : guardian , root : false )
render_json_dump ( post_revision_serializer )
end
2013-02-05 14:16:51 -05:00
def bookmark
2013-02-08 17:49:15 -05:00
post = find_post_from_params
2013-02-07 16:45:24 +01:00
if current_user
2013-02-05 14:16:51 -05:00
if params [ :bookmarked ] == " true "
2013-03-01 15:07:44 +03:00
PostAction . act ( current_user , post , PostActionType . types [ :bookmark ] )
2013-02-05 14:16:51 -05:00
else
2013-03-01 15:07:44 +03:00
PostAction . remove_act ( current_user , post , PostActionType . types [ :bookmark ] )
2013-02-05 14:16:51 -05:00
end
end
2013-03-22 14:08:11 -04:00
render nothing : true
2013-02-05 14:16:51 -05:00
end
2013-02-08 17:49:15 -05:00
protected
2013-12-12 03:41:34 +01:00
def find_post_from_params
finder = Post . where ( id : params [ :id ] || params [ :post_id ] )
# Include deleted posts if the user is staff
finder = finder . with_deleted if current_user . try ( :staff? )
2013-02-08 17:49:15 -05:00
2013-12-12 03:41:34 +01:00
post = finder . first
guardian . ensure_can_see! ( post )
post
end
2013-02-08 19:04:14 -05:00
2013-12-12 03:41:34 +01:00
def find_post_revision_from_params
post_id = params [ :id ] || params [ :post_id ]
revision = params [ :revision ] . to_i
raise Discourse :: InvalidParameters . new ( :revision ) if revision < 2
post_revision = PostRevision . where ( post_id : post_id , number : revision ) . first
2014-02-04 20:05:50 +01:00
post_revision . post = find_post_from_params
2013-12-12 03:41:34 +01:00
guardian . ensure_can_see! ( post_revision )
post_revision
end
2013-06-07 00:52:03 -07:00
2013-07-22 17:48:24 +10:00
def render_post_json ( post )
post_serializer = PostSerializer . new ( post , scope : guardian , root : false )
post_serializer . add_raw = true
render_json_dump ( post_serializer )
end
2013-06-07 00:52:03 -07:00
private
2013-12-12 03:41:34 +01:00
def params_key ( params )
" post # # " << Digest :: SHA1 . hexdigest ( params
. to_a
. concat ( [ [ " user " , current_user . id ] ] )
. sort { | x , y | x [ 0 ] < = > y [ 0 ] } . join do | x , y |
" #{ x } : #{ y } "
end )
end
2013-07-29 12:25:19 +10:00
2013-12-12 03:41:34 +01:00
def create_params
permitted = [
:raw ,
:topic_id ,
:title ,
:archetype ,
:category ,
:target_usernames ,
:reply_to_post_number ,
:auto_close_time ,
:auto_track
]
# param munging for WordPress
params [ :auto_track ] = ! ( params [ :auto_track ] . to_s == " false " ) if params [ :auto_track ]
if api_key_valid?
# php seems to be sending this incorrectly, don't fight with it
params [ :skip_validations ] = params [ :skip_validations ] . to_s == " true "
permitted << :skip_validations
end
2013-07-02 12:22:56 +10:00
2013-12-12 03:41:34 +01:00
params . require ( :raw )
params . permit ( * permitted ) . tap do | whitelisted |
whitelisted [ :image_sizes ] = params [ :image_sizes ]
# TODO this does not feel right, we should name what meta_data is allowed
whitelisted [ :meta_data ] = params [ :meta_data ]
2013-06-07 00:52:03 -07:00
end
2013-12-12 03:41:34 +01:00
end
2014-02-18 17:19:38 +01:00
def too_late_to ( action , post )
! guardian . send ( " can_ #{ action } ? " , post ) && post . user_id == current_user . id && post . edit_time_limit_expired?
end
2013-02-05 14:16:51 -05:00
end