discourse/lib/guardian.rb

424 lines
11 KiB
Ruby
Raw Normal View History

require_dependency 'guardian/category_guardian'
require_dependency 'guardian/ensure_magic'
require_dependency 'guardian/post_guardian'
require_dependency 'guardian/topic_guardian'
require_dependency 'guardian/user_guardian'
require_dependency 'guardian/post_revision_guardian'
require_dependency 'guardian/group_guardian'
2016-06-06 14:18:15 -04:00
require_dependency 'guardian/tag_guardian'
# The guardian is responsible for confirming access to various site resources and operations
2013-02-05 14:16:51 -05:00
class Guardian
include EnsureMagic
include CategoryGuardian
include PostGuardian
include TopicGuardian
include UserGuardian
include PostRevisionGuardian
include GroupGuardian
2016-06-06 14:18:15 -04:00
include TagGuardian
class AnonymousUser
def blank?; true; end
def admin?; false; end
def staff?; false; end
def moderator?; false; end
def approved?; false; end
def staged?; false; end
2017-11-10 12:18:08 -05:00
def silenced?; false; end
def secure_category_ids; []; end
def topic_create_allowed_category_ids; []; end
def has_trust_level?(level); false; end
def email; nil; end
end
attr_accessor :can_see_emails
2017-07-27 21:20:09 -04:00
def initialize(user = nil)
@user = user.presence || AnonymousUser.new
end
def user
@user.presence
end
alias :current_user :user
def anonymous?
!authenticated?
2013-02-05 14:16:51 -05:00
end
def authenticated?
@user.present?
2013-02-05 14:16:51 -05:00
end
def is_admin?
@user.admin?
end
def is_staff?
@user.staff?
2013-02-05 14:16:51 -05:00
end
def is_moderator?
@user.moderator?
end
2017-11-10 12:18:08 -05:00
def is_silenced?
@user.silenced?
end
def is_developer?
@user &&
is_admin? &&
(
Rails.env.development? ||
Developer.user_ids.include?(@user.id) ||
(
Rails.configuration.respond_to?(:developer_emails) &&
Rails.configuration.developer_emails.include?(@user.email)
)
)
end
def is_staged?
@user.staged?
end
2013-02-05 14:16:51 -05:00
# Can the user see the object?
def can_see?(obj)
if obj
see_method = method_name_for :see, obj
return (see_method ? send(see_method, obj) : true)
end
2013-02-05 14:16:51 -05:00
end
2017-07-27 21:20:09 -04:00
def can_create?(klass, parent = nil)
return false unless authenticated? && klass
# If no parent is provided, we look for a can_create_klass?
# custom method.
#
# If a parent is provided, we look for a method called
# can_create_klass_on_parent?
target = klass.name.underscore
if parent.present?
return false unless can_see?(parent)
target << "_on_#{parent.class.name.underscore}"
end
create_method = :"can_create_#{target}?"
return send(create_method, parent) if respond_to?(create_method)
true
end
def can_enable_safe_mode?
SiteSetting.enable_safe_mode? || is_staff?
end
2013-02-05 14:16:51 -05:00
# Can the user edit the obj
def can_edit?(obj)
2013-08-16 08:24:29 -04:00
can_do?(:edit, obj)
2013-02-05 14:16:51 -05:00
end
# Can we delete the object
def can_delete?(obj)
2013-08-16 08:24:29 -04:00
can_do?(:delete, obj)
2013-02-05 14:16:51 -05:00
end
def can_moderate?(obj)
2017-11-10 12:18:08 -05:00
obj && authenticated? && !is_silenced? && (is_staff? || (obj.is_a?(Topic) && @user.has_trust_level?(TrustLevel[4])))
2013-02-05 14:16:51 -05:00
end
2013-02-25 11:42:20 -05:00
alias :can_move_posts? :can_moderate?
2013-02-05 14:16:51 -05:00
alias :can_see_flags? :can_moderate?
alias :can_close? :can_moderate?
def can_tag?(topic)
return false if topic.blank?
2018-02-13 15:46:25 -05:00
topic.private_message? ? can_tag_pms? : can_tag_topics?
end
def can_see_tags?(topic)
SiteSetting.tagging_enabled && topic.present? && (!topic.private_message? || can_tag_pms?)
2018-02-13 15:46:25 -05:00
end
def can_send_activation_email?(user)
user && is_staff? && !SiteSetting.must_approve_users?
end
def can_grant_badges?(_user)
SiteSetting.enable_badges && is_staff?
end
2013-02-05 14:16:51 -05:00
def can_see_group?(group)
return false if group.blank?
return true if group.visibility_level == Group.visibility_levels[:public]
return true if is_admin?
return true if is_staff? && group.visibility_level == Group.visibility_levels[:staff]
return false if user.blank?
membership = GroupUser.find_by(group_id: group.id, user_id: user.id)
return false unless membership
if !membership.owner
return false if group.visibility_level == Group.visibility_levels[:owners]
return false if group.visibility_level == Group.visibility_levels[:staff]
end
true
end
2013-02-05 14:16:51 -05:00
# Can we impersonate this user?
def can_impersonate?(target)
target &&
2013-02-05 14:16:51 -05:00
# You must be an admin to impersonate
is_admin? &&
2013-02-05 14:16:51 -05:00
# You may not impersonate other admins unless you are a dev
(!target.admin? || is_developer?)
2013-02-05 14:16:51 -05:00
# Additionally, you may not impersonate yourself;
# but the two tests for different admin statuses
# make it impossible to be the same user.
2013-02-05 14:16:51 -05:00
end
def can_view_action_logs?(target)
target.present? && is_staff?
end
2013-02-05 14:16:51 -05:00
# Can we approve it?
def can_approve?(target)
is_staff? && target && target.active? && not(target.approved?)
2013-02-05 14:16:51 -05:00
end
def can_activate?(target)
is_staff? && target && not(target.active?)
end
2013-02-05 14:16:51 -05:00
def can_suspend?(user)
2013-05-24 12:13:31 -04:00
user && is_staff? && user.regular?
2013-02-05 14:16:51 -05:00
end
alias :can_deactivate? :can_suspend?
2013-02-05 14:16:51 -05:00
def can_revoke_admin?(admin)
can_administer_user?(admin) && admin.admin?
2013-02-05 14:16:51 -05:00
end
def can_grant_admin?(user)
can_administer_user?(user) && !user.admin?
2013-02-05 14:16:51 -05:00
end
def can_revoke_moderation?(moderator)
can_administer?(moderator) && moderator.moderator?
end
def can_grant_moderation?(user)
can_administer?(user) && !user.moderator?
end
def can_grant_title?(user, title = nil)
return true if user && is_staff?
return false if title.nil?
return true if title.empty? # A title set to '(none)' in the UI is an empty string
return false if user != @user
return true if user.badges.where(name: title, allow_title: true).exists?
user.groups.where(title: title).exists?
end
def can_change_primary_group?(user)
user && is_staff?
end
def can_change_trust_level?(user)
2013-07-22 19:13:48 -04:00
user && is_staff?
end
# Support sites that have to approve users
def can_access_forum?
return true unless SiteSetting.must_approve_users?
return false unless @user
# Staff can't lock themselves out of a site
return true if is_staff?
@user.approved?
end
def can_see_invite_details?(user)
is_me?(user)
2013-02-05 14:16:51 -05:00
end
2017-07-27 21:20:09 -04:00
def can_invite_to_forum?(groups = nil)
authenticated? &&
(SiteSetting.max_invites_per_day.to_i > 0 || is_staff?) &&
!SiteSetting.enable_sso &&
SiteSetting.enable_local_logins &&
(
(!SiteSetting.must_approve_users? && @user.has_trust_level?(TrustLevel[2])) ||
is_staff?
) &&
(groups.blank? || is_admin? || groups.all? { |g| can_edit_group?(g) })
2013-02-05 14:16:51 -05:00
end
2017-07-27 21:20:09 -04:00
def can_invite_to?(object, groups = nil)
return false unless authenticated?
return true if is_admin?
return false if (SiteSetting.max_invites_per_day.to_i == 0 && !is_staff?)
return false unless can_see?(object)
return false if groups.present?
if object.is_a?(Topic) && object.private_message?
return false unless SiteSetting.enable_personal_messages?
return false if object.reached_recipients_limit? && !is_staff?
end
if object.is_a?(Topic) && object.category
if object.category.groups.any?
return true if object.category.groups.all? { |g| can_edit_group?(g) }
end
end
user.has_trust_level?(TrustLevel[2])
end
def can_invite_via_email?(object)
return false unless can_invite_to?(object)
!SiteSetting.enable_sso && SiteSetting.enable_local_logins && (!SiteSetting.must_approve_users? || is_staff?)
end
2014-05-27 16:14:37 -04:00
def can_bulk_invite_to_forum?(user)
user.admin?
end
def can_send_multiple_invites?(user)
user.staff?
end
def can_resend_all_invites?(user)
user.staff?
end
def can_rescind_all_invites?(user)
user.staff?
end
2013-02-05 14:16:51 -05:00
def can_see_private_messages?(user_id)
is_admin? || (authenticated? && @user.id == user_id)
2013-02-05 14:16:51 -05:00
end
def can_invite_group_to_private_message?(group, topic)
can_see_topic?(topic) &&
can_send_private_message?(group)
end
def can_send_private_message?(target)
is_user = target.is_a?(User)
is_group = target.is_a?(Group)
(is_group || is_user) &&
2014-02-12 23:08:46 -05:00
# User is authenticated
authenticated? &&
# Have to be a basic level at least
@user.has_trust_level?(SiteSetting.min_trust_to_send_messages) &&
# User disabled private message
(is_staff? || is_group || target.user_option.allow_private_messages) &&
2014-02-12 23:08:46 -05:00
# PMs are enabled
(is_staff? || SiteSetting.enable_personal_messages) &&
# Can't send PMs to suspended users
(is_staff? || is_group || !target.suspended?) &&
# Check group messageable level
(is_staff? || is_user || Group.messageable(@user).where(id: target.id).exists?) &&
2017-11-10 12:18:08 -05:00
# Silenced users can only send PM to staff
(!is_silenced? || target.staff?)
2013-02-05 14:16:51 -05:00
end
def can_send_private_messages_to_email?
# Staged users must be enabled to create a temporary user.
SiteSetting.enable_staged_users &&
# User is authenticated
authenticated? &&
# User is trusted enough
(is_staff? ||
(
# TODO: 2019 evaluate if we need this flexibility
# perhaps we enable this unconditionally to TL4?
@user.has_trust_level?(SiteSetting.min_trust_to_send_email_messages) &&
SiteSetting.enable_personal_email_messages
)
)
end
def can_see_emails?
@can_see_emails
end
def can_export_entity?(entity)
return false unless @user
2014-12-30 07:37:05 -05:00
return true if is_staff?
# Regular users can only export their archives
return false unless entity == "user_archive"
2014-12-30 07:37:05 -05:00
UserExport.where(user_id: @user.id, created_at: (Time.zone.now.beginning_of_day..Time.zone.now.end_of_day)).count == 0
2014-12-22 11:17:04 -05:00
end
def allow_themes?(theme_ids)
return true if theme_ids.blank?
if is_staff? && (theme_ids - Theme.theme_ids).blank?
return true
end
parent = theme_ids.first
components = theme_ids[1..-1] || []
Theme.user_theme_ids.include?(parent) &&
(components - Theme.components_for(parent)).empty?
end
private
def is_my_own?(obj)
unless anonymous?
return obj.user_id == @user.id if obj.respond_to?(:user_id) && obj.user_id && @user.id
return obj.user == @user if obj.respond_to?(:user)
end
false
end
def is_me?(other)
2014-03-26 15:20:41 -04:00
other && authenticated? && other.is_a?(User) && @user == other
end
def is_not_me?(other)
@user.blank? || !is_me?(other)
end
def can_administer?(obj)
is_admin? && obj.present? && obj.id&.positive?
end
def can_administer_user?(other_user)
can_administer?(other_user) && is_not_me?(other_user)
end
def method_name_for(action, obj)
method_name = :"can_#{action}_#{obj.class.name.underscore}?"
return method_name if respond_to?(method_name)
end
2013-08-16 08:24:29 -04:00
def can_do?(action, obj)
if obj && authenticated?
action_method = method_name_for action, obj
return (action_method ? send(action_method, obj) : true)
else
false
2013-08-16 08:24:29 -04:00
end
end
2013-02-05 14:16:51 -05:00
end