module Zuul module RestrictAccess def self.included(controller) controller.extend(ClassMethods) end module ClassMethods def self.extended(klass) klass.cattr_accessor :access_denied_message klass.cattr_accessor :require_no_user_message klass.cattr_accessor :unauthorized_redirect_path end # Meant to be called from your controllers. This is # where you define which roles have access to which actions in the # controller. Examples: # * require_user :admin: Restrict access to all actions for a specific role. # * require_user :guest, :admin, :only => :index, :show: Restrict access to specific actions for specific roles. # * require_user :only => :show: Require a user but don't care about the role. def require_user(*roles) options = roles.extract_options! self.before_filter options do |controller| controller.send(:require_user, roles) end end # Tells its controller to check that there is no user # before allowing someone into an action. For example: # * require_no_user :only => :edit, :update: Don't allow access to the edit action # if there is a user. def require_no_user(options = {}) self.before_filter options do |controller| controller.send(:require_no_user) end end # Intended to be called by ApplicationController. It mixes # in a set of instance methods that manage conferring or denying access to actions. # You can customize the behavior when a user is denied access with these # options: # * +access_denied_message+: The string that will be added to the # flash[:notice] if the user has been denied access to an action. # Defaults to "You must be logged in to access this page". # * +require_no_user_message+: The string that will be added to the # flash[:notice] if the requested action requires there be NO user signed # in and there is one. Defaults to "You must be logged out to access this # page.". # * +unauthorized_redirect_path+: The name of a method, as a symbol, that # will be called to determine where to redirect someone when they have # been denied access. The method is expected to return a string. The # default is :unauthorized_path which returns "/". def restrict_access(options = {}) self.access_denied_message = options[:access_denied_message] || "You must be logged in to access this page" self.require_no_user_message = options[:require_no_user_message] || "You must be logged out to access this page" self.unauthorized_redirect_path = options[:unauthorized_redirect_path] || :unauthorized_path include InstanceMethods end end module InstanceMethods def require_user(*roles) roles.flatten! return true if current_user && roles.empty? deny_access unless roles.any? do |role| method = (role.to_s + "?").to_sym if current_user && current_user.respond_to?(method) current_user.send(method) else false end end end private :require_user def require_no_user if current_user store_location flash[:notice] = self.class.require_no_user_message redirect_to send(self.class.unauthorized_redirect_path) return false end end private :require_no_user def deny_access store_location flash[:notice] = self.class.access_denied_message redirect_to send(self.class.unauthorized_redirect_path) return false end private :deny_access def store_location session[:return_to] = request.request_uri end private :store_location def unauthorized_path "/" end private :unauthorized_path end end end