lib/cms/acts/cms_user.rb
module Cms
module Acts
# Allows any ActiveRecord object to behave like a Cms User. This is a bit of an experiment being added to 3.4, so
# so it might be deprecated in a future version if we add something like devise.
#
# The use case would be something like:
#
# class AdminUser < ActiveRecord::Base
# acts_as_cms_user :groups => [Cms::Group.find_by_code('admin')]
# end
#
# where groups could be an array, proc, or instance method (as a symbol).
# Could be used it with authlogic to grant logins and permissions to
# everyone in a custom model. It's not quite a drop in authentication
# schema, but it does make it easier to wire up just about any model to be
# the current_user on CMS pages.
module CmsUser
def self.included(model_class)
model_class.extend(MacroMethods)
end
module MacroMethods
def acts_as_cms_user(options = {})
include InstanceMethods
# Adding a cms_group method to each person object that returns a list of
# CMS Groups the user belongs to. Can be set with an array, proc, or
# instance method on the person. Defaults to Cms::Group.guest
define_method "cms_groups" do
fetch_group_list = Proc.new do
if options[:groups].nil?
[Cms::Group.guest]
elsif options[:groups].kind_of? Array
options[:groups]
elsif options[:groups].is_a? Proc
options[:groups].call(self)
elsif self.respond_to?(options[:groups])
self.send(options[:groups])
else
raise ArgumentError, "acts_as_cms_user :groups option expected to be of type Array, Proc, or instance method - #{options[:groups].class} found instead"
end
end
@cms_groups ||= begin
specified = Array(fetch_group_list.call).select { |x| x.kind_of? Cms::Group }
specified << Cms::Group.guest if specified.empty?
specified
end
end
end
module InstanceMethods
# The following came from Cms::User
def guest?
false
end
# checks for usage
def cms_user_compatible?
true
end
def enable_able?
false
end
def disable_able?
false
end
# Determine if this user has permission to view the specific object. Permissions
# are always tied to a specific section. This method can take different input parameters
# and will attempt to determine the relevant section to check.
# Expects object to be of type:
# 1. Section - Will check the user's groups to see if any of those groups can view this section.
# 2. Path - Will look up the section based on the path, then check it. (Note that section paths are not currently unique, so this will check the first one it finds).
# 3. Other - Assumes it has a section attribute and will call that and check the return value.
#
# Returns: true if the user can view this object, false otherwise.
# Raises: ActiveRecord::RecordNotFound if a path to a not existent section is passed in.
def able_to_view?(object)
section = object
if object.is_a?(String)
section = Cms::Section.find_by_path(object)
raise ActiveRecord::RecordNotFound.new("Could not find section with path = '#{object}'") unless section
elsif !object.is_a?(Cms::Section)
section = object.section
end
viewable_sections.include?(section) || cms_access?
end
# The following came from Cms::GuestUser or Cms::User
# Expects a list of names of Permissions
# true if the user has any of the permissions
def able_to?(*required_permissions)
perms = required_permissions.map(&:to_sym)
permissions.any? do |p|
perms.include?(p.name.to_sym)
end
end
# Guests never get access to the CMS.
def cms_access?
false
end
# Return a list of the sections associated with this user that can be viewed.
# Overridden from user so that able_to_view? will work correctly.
def viewable_sections
@viewable_sections ||= Cms::Section.includes(:groups).where(["#{Cms::Group.table_name}.id in (?)", cms_groups.collect(&:id)])
end
def permissions
@permissions ||= Cms::Permission.includes(:groups).where(["#{Cms::Group.table_name}.id in (?)", cms_groups.collect(&:id)])
end
def able_to_edit?(section)
false
end
end
end
end
end
end