discourse/lib/guardian.rb
Sam 5280b3a01b more group progress, UI getting there, controller mostly done
changed it so notify moderators goes to the moderators group
allow admins to grant self moderation and revoke self moderation
2013-05-09 17:37:34 +10:00

410 lines
9.7 KiB
Ruby

# The guardian is responsible for confirming access to various site resources and operations
class Guardian
attr_reader :user
def initialize(user=nil)
@user = user
end
def current_user
@user
end
def is_admin?
@user && @user.admin?
end
def is_staff?
@user && @user.staff?
end
# Can the user see the object?
def can_see?(obj)
return false if obj.blank?
see_method = :"can_see_#{obj.class.name.underscore}?"
return send(see_method, obj) if respond_to?(see_method)
return true
end
# Can the user edit the obj
def can_edit?(obj)
return false if obj.blank?
return false if @user.blank?
edit_method = :"can_edit_#{obj.class.name.underscore}?"
return send(edit_method, obj) if respond_to?(edit_method)
true
end
# Can we delete the object
def can_delete?(obj)
return false if obj.blank?
return false if @user.blank?
delete_method = :"can_delete_#{obj.class.name.underscore}?"
return send(delete_method, obj) if respond_to?(delete_method)
true
end
def can_moderate?(obj)
return false if obj.blank?
return false if @user.blank?
@user.staff?
end
alias :can_move_posts? :can_moderate?
alias :can_see_flags? :can_moderate?
alias :can_send_activation_email? :can_moderate?
# Can the user create a topic in the forum
def can_create?(klass, parent=nil)
return false if klass.blank?
return false if @user.blank?
# If no parent is provided, we look for a can_i_create_klass?
# custom method.
#
# If a parent is provided, we look for a method called
# can_i_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
# Can we impersonate this user?
def can_impersonate?(target)
return false if target.blank?
return false if @user.blank?
# You must be an admin to impersonate
return false unless @user.admin?
# You may not impersonate other admins
return false if target.admin?
# You may not impersonate yourself
return false if @user == target
true
end
# Can we approve it?
def can_approve?(target)
return false if target.blank?
return false if @user.blank?
return false if target.approved?
@user.staff?
end
alias :can_activate? :can_approve?
def can_ban?(user)
return false if user.blank?
return false unless @user.try(:admin?)
return false if user.admin?
true
end
alias :can_deactivate? :can_ban?
def can_clear_flags?(post)
return false if @user.blank?
return false if post.blank?
@user.staff?
end
def can_revoke_admin?(admin)
return false unless @user.try(:admin?)
return false if admin.blank?
return false if @user.id == admin.id
return false unless admin.admin?
true
end
def can_grant_admin?(user)
return false unless @user.try(:admin?)
return false if user.blank?
return false if @user.id == user.id
return false if user.admin?
true
end
def can_revoke_moderation?(moderator)
return false unless is_admin?
return false if moderator.blank?
return false if @user.id == moderator.id && !is_admin?
return false unless moderator.moderator?
true
end
def can_grant_moderation?(user)
return false unless is_admin?
return false unless user
return false if @user.id == user.id && !is_admin?
return false if user.moderator?
true
end
def can_delete_user?(user_to_delete)
return false unless is_admin?
return false unless user_to_delete
return false if user_to_delete.post_count > 0
true
end
# Can we see who acted on a post in a particular way?
def can_see_post_actors?(topic, post_action_type_id)
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
# 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_pending_invites_from?(user)
return false unless user && @user
return user == @user
end
# For now, can_invite_to is basically can_see?
def can_invite_to?(object)
return false unless @user
return false unless can_see?(object)
return false if SiteSetting.must_approve_users?
@user.has_trust_level?(:regular) || @user.staff?
end
def can_see_deleted_posts?
return true if is_staff?
false
end
def can_see_private_messages?(user_id)
return true if is_staff?
return false unless @user
@user.id == user_id
end
def can_delete_all_posts?(user)
return false unless is_staff?
return false if user.created_at < 7.days.ago
true
end
# Support for ensure_{blah}! methods.
def method_missing(method, *args, &block)
if method.to_s =~ /^ensure_(.*)\!$/
can_method = :"#{Regexp.last_match[1]}?"
if respond_to?(can_method)
raise Discourse::InvalidAccess.new("#{can_method} failed") unless send(can_method, *args, &block)
return
end
end
super.method_missing(method, *args, &block)
end
# Make sure we can see the object. Will raise a NotFound if it's nil
def ensure_can_see!(obj)
raise Discourse::InvalidAccess.new("Can't see #{obj}") unless can_see?(obj)
end
# Creating Methods
def can_create_category?(parent)
is_staff?
end
def can_create_post_on_topic?(topic)
return true if is_staff?
return false if topic.closed?
return false if topic.archived?
true
end
# Editing Methods
def can_edit_category?(category)
is_staff?
end
def can_edit_post?(post)
return true if is_staff?
return false if post.topic.archived?
(post.user == @user)
end
def can_edit_user?(user)
return true if user == @user
is_staff?
end
def can_edit_topic?(topic)
return true if is_staff?
return true if topic.user == @user
false
end
# Deleting Methods
def can_delete_post?(post)
# Can't delete the first post
return false if post.post_number == 1
# You can delete your own posts
return !post.user_deleted? if post.user == @user
is_staff?
end
# Recovery Method
def can_recover_post?(post)
return false unless @user
is_staff?
end
def can_delete_category?(category)
return false unless is_staff?
return category.topic_count == 0
end
def can_delete_topic?(topic)
return false unless is_staff?
return false if Category.exists?(topic_id: topic.id)
true
end
def can_delete_post_action?(post_action)
# You can only undo your own actions
return false unless @user
return false unless post_action.user_id == @user.id
return false if post_action.is_private_message?
# Make sure they want to delete it within the window
return post_action.created_at > SiteSetting.post_undo_action_window_mins.minutes.ago
end
def can_send_private_message?(target)
return false unless User === target || Group === target
return false unless @user
# Can't send message to yourself
return false if User === target && @user.id == target.id
# Have to be a basic level at least
return false unless @user.has_trust_level?(:basic)
SiteSetting.enable_private_messages
end
def can_reply_as_new_topic?(topic)
return false unless @user
return false unless topic
return false if topic.private_message?
@user.has_trust_level?(:basic)
end
def can_see_topic?(topic)
return false unless topic
return true if @user && is_staff?
return false if topic.deleted_at
if topic.category && topic.category.secure
return false unless @user && can_see_category?(topic.category)
end
if topic.private_message?
return false unless @user
return true if topic.all_allowed_users.where(id: @user.id).exists?
return is_admin?
end
true
end
def can_see_post?(post)
return false unless post
return true if @user && is_staff?
return false if post.deleted_at.present?
can_see_topic?(post.topic)
end
def can_see_category?(category)
return true unless category.secure
return false unless @user
@user.secure_category_ids.include?(category.id)
end
def can_vote?(post, opts={})
post_can_act?(post,:vote, opts)
end
# 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={})
return false if @user.blank?
return false if post.blank?
taken = opts[:taken_actions]
taken = taken.keys if taken
# we always allow flagging
if PostActionType.is_flag?(action_key)
return false unless @user.has_trust_level?(:basic)
if taken
return false unless (taken & PostActionType.flag_types.values).empty?
end
else
return false if taken && taken.include?(PostActionType.types[action_key])
end
# nothing else on archived posts
return false if post.topic.archived?
case action_key
when :like
return false if post.user == @user
when :vote then
return false if opts[:voted_in_topic] && post.topic.has_meta_data_boolean?(:single_vote)
end
return true
end
def secure_category_ids
@user ? @user.secure_category_ids : []
end
end