discourse/lib/guardian/post_guardian.rb

238 lines
6.8 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: {}, can_see_post: nil)
return false unless (can_see_post.nil? && can_see_post?(post)) || can_see_post
# no warnings except for staff
return false if (action_key == :notify_user && !is_staff? && opts[:is_warning].present? && opts[:is_warning] == 'true')
taken = opts[:taken_actions].try(:keys).to_a
is_flag = PostActionType.flag_types_without_custom[action_key]
already_taken_this_action = taken.any? && taken.include?(PostActionType.types[action_key])
already_did_flagging = taken.any? && (taken & PostActionType.flag_types_without_custom.values).any?
result = if authenticated? && post && !@user.anonymous?
return false if [:notify_user, :notify_moderators].include?(action_key) &&
!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 or notify_moderators because they are not allowed to send private messages
not((action_key == :notify_user || action_key == :notify_moderators) &&
!@user.has_trust_level?(SiteSetting.min_trust_to_send_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)
can_see_post?(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 false if type_symbol == :notify_user && !is_moderator?
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)
return false if !SiteSetting.enable_system_message_replies? && parent.try(:subtype) == "system_message"
(!SpamRule::AutoSilence.silence?(@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 can_create_post?(post.topic)
end
if @user.trust_level < SiteSetting.min_trust_to_edit_post
return false
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_see_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)
if is_staff?
post.deleted_at && post.user
else
is_my_own?(post) && post.user_deleted && !post.deleted_at
end
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: opts)
end
def can_change_post_owner?
is_admin?
end
def can_change_post_timestamps?
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