discourse/lib/guardian/post_guardian.rb
Sam Saffron 46b34e3c62 FEATURE: remove user option for edit history public
Users can no longer opt-in for "public" edit history
if site owner disables it.

This feature adds cost and complexity to post rendering since
user options need to be premeptively loaded for every user in the
stream. It is also confusing to explain to communities with private edit
history.
2016-07-16 21:30:00 +10:00

216 lines
6.3 KiB
Ruby

#mixin for all guardian methods dealing with post permissions
module PostGuardian
# Can the user act on the post in a particular way.
# taken_actions = the list of actions the user has already taken
def post_can_act?(post, action_key, opts={})
taken = opts[:taken_actions].try(:keys).to_a
is_flag = PostActionType.is_flag?(action_key)
already_taken_this_action = taken.any? && taken.include?(PostActionType.types[action_key])
already_did_flagging = taken.any? && (taken & PostActionType.flag_types.values).any?
result = if authenticated? && post && !@user.anonymous?
return false if action_key == :notify_moderators && !SiteSetting.enable_private_messages
# we allow flagging for trust level 1 and higher
# always allowed for private messages
(is_flag && not(already_did_flagging) && (@user.has_trust_level?(TrustLevel[1]) || post.topic.private_message?)) ||
# not a flagging action, and haven't done it already
not(is_flag || already_taken_this_action) &&
# nothing except flagging on archived topics
not(post.topic.try(:archived?)) &&
# nothing except flagging on deleted posts
not(post.trashed?) &&
# don't like your own stuff
not(action_key == :like && is_my_own?(post)) &&
# new users can't notify_user because they are not allowed to send private messages
not(action_key == :notify_user && !@user.has_trust_level?(SiteSetting.min_trust_to_send_messages)) &&
# non-staff can't send an official warning
not(action_key == :notify_user && !is_staff? && opts[:is_warning].present? && opts[:is_warning] == 'true') &&
# can't send private messages if they're disabled globally
not(action_key == :notify_user && !SiteSetting.enable_private_messages) &&
# no voting more than once on single vote topics
not(action_key == :vote && opts[:voted_in_topic] && post.topic.has_meta_data_boolean?(:single_vote))
end
!!result
end
def can_defer_flags?(post)
is_staff? && post
end
# Can we see who acted on a post in a particular way?
def can_see_post_actors?(topic, post_action_type_id)
return true if is_admin?
return false unless topic
type_symbol = PostActionType.types[post_action_type_id]
return false if type_symbol == :bookmark
return can_see_flags?(topic) if PostActionType.is_flag?(type_symbol)
if type_symbol == :vote
# We can see votes if the topic allows for public voting
return false if topic.has_meta_data_boolean?(:private_poll)
end
true
end
def can_delete_all_posts?(user)
is_staff? &&
user &&
!user.admin? &&
(user.first_post_created_at.nil? || user.first_post_created_at >= SiteSetting.delete_user_max_post_age.days.ago) &&
user.post_count <= SiteSetting.delete_all_posts_max.to_i
end
# Creating Method
def can_create_post?(parent)
(!SpamRule::AutoBlock.block?(@user) || (!!parent.try(:private_message?) && parent.allowed_users.include?(@user))) && (
!parent ||
!parent.category ||
Category.post_create_allowed(self).where(:id => parent.category.id).count == 1
)
end
# Editing Method
def can_edit_post?(post)
if Discourse.static_doc_topic_ids.include?(post.topic_id) && !is_admin?
return false
end
return true if is_admin?
if is_staff? || @user.has_trust_level?(TrustLevel[4])
return can_create_post?(post.topic)
end
if post.topic.archived? || post.user_deleted || post.deleted_at
return false
end
if post.wiki && (@user.trust_level >= SiteSetting.min_trust_to_edit_wiki_post.to_i)
return true
end
if is_my_own?(post)
if post.hidden?
return false if post.hidden_at.present? &&
post.hidden_at >= SiteSetting.cooldown_minutes_after_hiding_posts.minutes.ago
# If it's your own post and it's hidden, you can still edit it
return true
end
return !post.edit_time_limit_expired?
end
false
end
# Deleting Methods
def can_delete_post?(post)
# Can't delete the first post
return false if post.is_first_post?
# Can't delete after post_edit_time_limit minutes have passed
return false if !is_staff? && post.edit_time_limit_expired?
# Can't delete posts in archived topics unless you are staff
return false if !is_staff? && post.topic.archived?
# You can delete your own posts
return !post.user_deleted? if is_my_own?(post)
is_staff?
end
# Recovery Method
def can_recover_post?(post)
is_staff? || (is_my_own?(post) && post.user_deleted && !post.deleted_at)
end
def can_delete_post_action?(post_action)
# You can only undo your own actions
is_my_own?(post_action) && not(post_action.is_private_message?) &&
# Make sure they want to delete it within the window
post_action.created_at > SiteSetting.post_undo_action_window_mins.minutes.ago
end
def can_see_post?(post)
return false if post.blank?
return true if is_admin?
return false unless can_see_topic?(post.topic)
return false unless post.user == @user || Topic.visible_post_types(@user).include?(post.post_type)
return false if !is_moderator? && post.deleted_at.present?
true
end
def can_view_edit_history?(post)
return false unless post
if !post.hidden
return true if post.wiki || SiteSetting.edit_history_visible_to_public
end
authenticated? &&
(is_staff? || @user.has_trust_level?(TrustLevel[4]) || @user.id == post.user_id) &&
can_see_post?(post)
end
def can_vote?(post, opts={})
post_can_act?(post,:vote, opts)
end
def can_change_post_owner?
is_admin?
end
def can_wiki?(post)
return false unless authenticated?
return true if is_staff? || @user.has_trust_level?(TrustLevel[4])
if @user.has_trust_level?(SiteSetting.min_trust_to_allow_self_wiki) && is_my_own?(post)
return false if post.hidden?
return !post.edit_time_limit_expired?
end
false
end
def can_change_post_type?
is_staff?
end
def can_rebake?
is_staff? || @user.has_trust_level?(TrustLevel[4])
end
def can_see_flagged_posts?
is_staff?
end
def can_see_deleted_posts?
is_staff?
end
def can_view_raw_email?(post)
post && (is_staff? || post.user_id == @user.id)
end
def can_unhide?(post)
post.try(:hidden) && is_staff?
end
end