discourse/lib/guardian/topic_guardian.rb
Roman Rizzi b45a30c40f
FIX: Users without shared drafts access can still have access to the category. (#11476)
This is an edge-case of 9fb3629. An admin could set the shared draft category to one where both TL2 and TL3 users have access but only give shared draft access to TL3 users. If something like this happens, we need to make sure that TL2 users won't be able to see them, and they won't be listed on latest.

Before this change, `SharedDrafts` were lazily created when a destination category was selected. We now create it alongside the topic and set the destination to the same shared draft category.
2020-12-14 16:08:20 -03:00

250 lines
8.0 KiB
Ruby

# frozen_string_literal: true
#mixin for all guardian methods dealing with topic permisions
module TopicGuardian
def can_remove_allowed_users?(topic, target_user = nil)
is_staff? ||
(topic.user == @user && @user.has_trust_level?(TrustLevel[2])) ||
(
topic.allowed_users.count > 1 &&
topic.user != target_user &&
!!(target_user && user == target_user)
)
end
def can_review_topic?(topic)
return false if anonymous? || topic.nil?
return true if is_staff?
is_category_group_moderator?(topic.category)
end
alias :can_moderate_topic? :can_review_topic?
def can_create_shared_draft?
return false unless SiteSetting.shared_drafts_enabled?
return is_admin? if SiteSetting.shared_drafts_min_trust_level.to_s == 'admin'
return is_staff? if SiteSetting.shared_drafts_min_trust_level.to_s == 'staff'
@user.has_trust_level?(SiteSetting.shared_drafts_min_trust_level.to_i)
end
def can_create_whisper?
is_staff? && SiteSetting.enable_whispers?
end
def can_see_whispers?(_topic)
is_staff?
end
def can_publish_topic?(topic, category)
can_create_shared_draft? && can_see?(topic) && can_create_topic_on_category?(category)
end
# Creating Methods
def can_create_topic?(parent)
is_staff? ||
(user &&
user.trust_level >= SiteSetting.min_trust_to_create_topic.to_i &&
can_create_post?(parent) &&
Category.topic_create_allowed(self).limit(1).count == 1)
end
def can_create_topic_on_category?(category)
# allow for category to be a number as well
category_id = Category === category ? category.id : category
can_create_topic?(nil) &&
(!category || Category.topic_create_allowed(self).where(id: category_id).count == 1)
end
def can_move_topic_to_category?(category)
category = Category === category ? category : Category.find(category || SiteSetting.uncategorized_category_id)
is_staff? || (can_create_topic_on_category?(category) && !category.require_topic_approval?)
end
def can_create_post_on_topic?(topic)
# No users can create posts on deleted topics
return false if topic.blank?
return false if topic.trashed?
return true if is_admin?
trusted = (authenticated? && user.has_trust_level?(TrustLevel[4])) || is_moderator? || can_perform_action_available_to_group_moderators?(topic)
(!(topic.closed? || topic.archived?) || trusted) && can_create_post?(topic)
end
# Editing Method
def can_edit_topic?(topic)
return false if Discourse.static_doc_topic_ids.include?(topic.id) && !is_admin?
return false unless can_see?(topic)
return false if topic.first_post&.locked? && !is_staff?
return true if is_admin?
return true if is_moderator? && can_create_post?(topic)
return true if is_category_group_moderator?(topic.category)
# can't edit topics in secured categories where you don't have permission to create topics
# except for a tiny edge case where the topic is uncategorized and you are trying
# to fix it but uncategorized is disabled
if (
SiteSetting.allow_uncategorized_topics ||
topic.category_id != SiteSetting.uncategorized_category_id
)
return false if !can_create_topic_on_category?(topic.category)
end
# Editing a shared draft.
return true if (
!topic.archived &&
!topic.private_message? &&
topic.category_id == SiteSetting.shared_drafts_category.to_i &&
can_see_category?(topic.category) &&
can_create_shared_draft? &&
can_create_post?(topic)
)
# TL4 users can edit archived topics, but can not edit private messages
return true if (
SiteSetting.trusted_users_can_edit_others? &&
topic.archived &&
!topic.private_message? &&
user.has_trust_level?(TrustLevel[4]) &&
can_create_post?(topic)
)
# TL3 users can not edit archived topics and private messages
return true if (
SiteSetting.trusted_users_can_edit_others? &&
!topic.archived &&
!topic.private_message? &&
user.has_trust_level?(TrustLevel[3]) &&
can_create_post?(topic)
)
return false if topic.archived
is_my_own?(topic) &&
!topic.edit_time_limit_expired?(user) &&
!Post.where(topic_id: topic.id, post_number: 1).where.not(locked_by_id: nil).exists?
end
# Recovery Method
def can_recover_topic?(topic)
if is_staff? || (topic&.category && is_category_group_moderator?(topic.category))
!!(topic && topic.deleted_at)
else
topic && can_recover_post?(topic.ordered_posts.first)
end
end
def can_delete_topic?(topic)
!topic.trashed? &&
(is_staff? || (is_my_own?(topic) && topic.posts_count <= 1 && topic.created_at && topic.created_at > 24.hours.ago) || is_category_group_moderator?(topic.category)) &&
!topic.is_category_topic? &&
!Discourse.static_doc_topic_ids.include?(topic.id)
end
def can_toggle_topic_visibility?(topic)
can_moderate?(topic) || can_perform_action_available_to_group_moderators?(topic)
end
def can_convert_topic?(topic)
return false unless SiteSetting.enable_personal_messages?
return false if topic.blank?
return false if topic.trashed?
return false if topic.is_category_topic?
return true if is_admin?
is_moderator? && can_create_post?(topic)
end
def can_reply_as_new_topic?(topic)
authenticated? && topic && @user.has_trust_level?(TrustLevel[1])
end
def can_see_deleted_topics?(category)
is_staff? || is_category_group_moderator?(category)
end
def can_see_topic?(topic, hide_deleted = true)
return false unless topic
return true if is_admin?
return false if hide_deleted && topic.deleted_at && !can_see_deleted_topics?(topic.category)
if topic.private_message?
return authenticated? && topic.all_allowed_users.where(id: @user.id).exists?
end
return false if topic.shared_draft && !can_create_shared_draft?
category = topic.category
can_see_category?(category) &&
(!category.read_restricted || !is_staged? || secure_category_ids.include?(category.id) || topic.user == user)
end
def can_get_access_to_topic?(topic)
topic&.access_topic_via_group.present? && authenticated?
end
def filter_allowed_categories(records)
unless is_admin?
allowed_ids = allowed_category_ids
if allowed_ids.length > 0
records = records.where('topics.category_id IS NULL or topics.category_id IN (?)', allowed_ids)
else
records = records.where('topics.category_id IS NULL')
end
records = records.references(:categories)
end
records
end
def can_edit_featured_link?(category_id)
return false unless SiteSetting.topic_featured_link_enabled
Category.where(id: category_id || SiteSetting.uncategorized_category_id, topic_featured_link_allowed: true).exists?
end
def can_update_bumped_at?
is_staff? || @user.has_trust_level?(TrustLevel[4])
end
def can_banner_topic?(topic)
topic && authenticated? && !topic.private_message? && is_staff?
end
def can_edit_tags?(topic)
return false unless can_tag_topics?
return false if topic.private_message? && !can_tag_pms?
return true if can_edit_topic?(topic)
if topic&.first_post&.wiki && (@user.trust_level >= SiteSetting.min_trust_to_edit_wiki_post.to_i)
return can_create_post?(topic)
end
false
end
def can_perform_action_available_to_group_moderators?(topic)
return false if anonymous? || topic.nil?
return true if is_staff?
return true if @user.has_trust_level?(TrustLevel[4])
is_category_group_moderator?(topic.category)
end
alias :can_archive_topic? :can_perform_action_available_to_group_moderators?
alias :can_close_topic? :can_perform_action_available_to_group_moderators?
alias :can_split_merge_topic? :can_perform_action_available_to_group_moderators?
alias :can_edit_staff_notes? :can_perform_action_available_to_group_moderators?
def can_move_posts?(topic)
return false if is_silenced?
can_perform_action_available_to_group_moderators?(topic)
end
def affected_by_slow_mode?(topic)
topic&.slow_mode_seconds.to_i > 0 && @user.human? && !is_staff?
end
end