Adding filters generation based on devise mappings.

This commit is contained in:
Carlos A. da Silva 2009-10-11 08:15:48 -03:00
parent 198167d978
commit 62bef5605a
9 changed files with 184 additions and 20 deletions

View File

@ -63,6 +63,12 @@ module Devise
end
end
ActiveRecord::Base.send :extend, Devise::ActiveRecord
ActionController::Base.send :include, Devise::ActionController
ActionView::Base.send :include, Devise::ActionView
# Ensure to include Devise modules only after Rails initialization.
# This way application should have already defined Devise mappings and we are
# able to create default filters.
#
Rails.configuration.after_initialize do
ActiveRecord::Base.send :extend, Devise::ActiveRecord
ActionController::Base.send :include, Devise::ActionController
ActionView::Base.send :include, Devise::ActionView
end

View File

@ -6,6 +6,7 @@ module Devise
include Devise::Controllers::Authenticable
include Devise::Controllers::Resources
include Devise::Controllers::UrlHelpers
include Devise::Controllers::Filters
end
end
end

View File

@ -25,7 +25,7 @@ module Devise
# Proxy to the authenticated? method on warden
#
def authenticated?(scope=resource_name)
warden.authenticated?(scope)
warden.authenticated?(scope.to_sym)
end
alias_method :logged_in?, :authenticated?
@ -47,20 +47,6 @@ module Devise
warden.raw_session.inspect # Without this inspect here. The session does not clear :|
warden.logout(resource_name)
end
# Verify authenticated user and redirect to sign in if no authentication is found
#
def authenticate!
redirect_to new_session_path unless authenticated?
end
# Helper for use in before_filters where no authentication is required:
# Example:
# before_filter :require_no_authentication, :only => :new
#
def require_no_authentication
redirect_to root_path if authenticated?
end
end
end
end

View File

@ -0,0 +1,45 @@
module Devise
module Controllers
module Filters
# Define authentication filters based on mappings. These filters should be
# used inside the controllers as before_filters, so you can control the
# scope of the user who should be signed in to access that specific
# controller/action.
#
# Example:
# Maps:
# Devise.map :users, :for => [:authenticable]
# Devise.map :admin, :for => [:authenticable]
# Generated Filters:
# user_authenticate!
# admin_authenticate!
# Use:
# before_filter :user_authenticate! # Tell devise to use :user map
# before_filter :admin_authenticate! # Tell devise to use :admin map
#
Devise.mappings.each_key do |mapping|
define_method(:"#{mapping}_authenticate!") do
authenticate!(mapping)
end
end
# Verify authenticated user and redirect to sign in if no authentication
# is found
#
def authenticate!(scope)
redirect_to new_session_path(scope) unless authenticated?(scope)
end
# Helper for use in before_filters where no authentication is required:
# Example:
# before_filter :require_no_authentication, :only => :new
#
def require_no_authentication
Devise.mappings.each_key do |map|
redirect_to root_path if authenticated?(map)
end
end
end
end
end

View File

@ -27,7 +27,7 @@ module Devise
private
def resource_name_or_request_path(object=nil)
object ? object.class.name : request.path
object ? (object.is_a?(::ActiveRecord::Base) ? object.class.name : object) : request.path
end
end
end

View File

@ -22,7 +22,9 @@ module Devise
actions.each do |action|
class_eval <<-URL_HELPERS
def #{action}#{module_name}_#{path_or_url}(*args)
resource = args.first.is_a?(::ActiveRecord::Base) ? args.shift : nil
resource = case args.first
when ::ActiveRecord::Base, Symbol, String then args.shift
end
send("#{action}\#{resource_name(resource)}_#{module_name}_#{path_or_url}", *args)
end
URL_HELPERS

View File

@ -0,0 +1,111 @@
require 'test/test_helper'
class FiltersController < ApplicationController
before_filter :user_authenticate!, :only => :user_action
before_filter :admin_authenticate!, :only => :admin_action
before_filter :require_no_authentication, :only => :not_authenticated_action
def public_action
render :text => 'public'
end
def not_authenticated_action
render :text => 'not_authenticated'
end
def user_action
render :text => 'user'
end
def admin_action
render :text => 'admin'
end
end
class FiltersTest < ActionController::TestCase
tests FiltersController
test 'generate user_authenticate! filter' do
assert @controller.respond_to?(:user_authenticate!)
end
test 'proxy user_authenticate! to authenticate with user scope' do
@controller.expects(:authenticate!).with('user')
@controller.user_authenticate!
end
test 'generate admin_authenticate! filter' do
assert @controller.respond_to?(:admin_authenticate!)
end
test 'proxy admin_authenticate! to authenticate with user scope' do
@controller.expects(:authenticate!).with('admin')
@controller.admin_authenticate!
end
test 'not authenticated user should be able to access public action' do
get :public_action
assert_response :success
assert_equal 'public', @response.body
end
test 'not authenticated as user should not be able to access user action' do
@controller.expects(:authenticated?).with('user').returns(false)
get :user_action
assert_response :redirect
assert_redirected_to new_user_session_path
end
test 'authenticated as user should be able to access user action' do
@controller.expects(:authenticated?).with('user').returns(true)
get :user_action
assert_response :success
assert_equal 'user', @response.body
end
test 'not authenticated as admin should not be able to access admin action' do
@controller.expects(:authenticated?).with('admin').returns(false)
get :admin_action
assert_response :redirect
assert_redirected_to new_admin_session_path
end
test 'authenticated as admin should be able to access admin action' do
@controller.expects(:authenticated?).with('admin').returns(true)
get :admin_action
assert_response :success
assert_equal 'admin', @response.body
end
test 'authenticated as user should not be able to access not authenticated action' do
@controller.expects(:authenticated?).with('user').returns(true)
@controller.expects(:authenticated?).with('admin').returns(false)
get :not_authenticated_action
assert_response :redirect
assert_redirected_to root_path
end
test 'authenticated as admin should not be able to access not authenticated action' do
@controller.expects(:authenticated?).with('user').returns(false)
@controller.expects(:authenticated?).with('admin').returns(true)
get :not_authenticated_action
assert_response :redirect
assert_redirected_to root_path
end
test 'not authenticated should access not_authenticated_action' do
@controller.expects(:authenticated?).with('user').returns(false)
@controller.expects(:authenticated?).with('admin').returns(false)
get :not_authenticated_action
assert_response :success
assert_equal 'not_authenticated', @response.body
end
end

View File

@ -6,21 +6,31 @@ class RoutesTest < ActionController::TestCase
def test_path_and_url(name, prepend_path=nil)
@request.path = '/users/session'
prepend_path = "#{prepend_path}_" if prepend_path
# No params
assert_equal @controller.send(:"#{prepend_path}#{name}_path"),
send(:"#{prepend_path}user_#{name}_path")
assert_equal @controller.send(:"#{prepend_path}#{name}_url"),
send(:"#{prepend_path}user_#{name}_url")
# Default url params
assert_equal @controller.send(:"#{prepend_path}#{name}_path", :param => 123),
send(:"#{prepend_path}user_#{name}_path", :param => 123)
assert_equal @controller.send(:"#{prepend_path}#{name}_url", :param => 123),
send(:"#{prepend_path}user_#{name}_url", :param => 123)
@request.path = nil
# With an AR object
assert_equal @controller.send(:"#{prepend_path}#{name}_path", User.new),
send(:"#{prepend_path}user_#{name}_path")
assert_equal @controller.send(:"#{prepend_path}#{name}_url", User.new),
send(:"#{prepend_path}user_#{name}_url")
# Using a symbol
assert_equal @controller.send(:"#{prepend_path}#{name}_path", :user),
send(:"#{prepend_path}user_#{name}_path")
assert_equal @controller.send(:"#{prepend_path}#{name}_url", :user),
send(:"#{prepend_path}user_#{name}_url")
end

View File

@ -2,4 +2,7 @@ ActionController::Routing::Routes.draw do |map|
map.resources :users, :only => :index
map.resources :admins, :only => :index
map.root :controller => :home
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
end