1
0
Fork 0
mirror of https://github.com/heartcombo/devise.git synced 2022-11-09 12:18:31 -05:00

Merge pull request #3011 from dwhenry/make-devise-more-engine-friendly

Make devise more engine friendly
This commit is contained in:
José Valim 2014-05-24 20:20:03 +09:00
commit 395b5c4237
15 changed files with 205 additions and 6 deletions

View file

@ -112,7 +112,10 @@ class Devise::RegistrationsController < DeviseController
# The path used after sign up for inactive accounts. You need to overwrite
# this method in your own RegistrationsController.
def after_inactive_sign_up_path_for(resource)
respond_to?(:root_path) ? root_path : "/"
scope = Devise::Mapping.find_scope!(resource)
router_name = Devise.mappings[scope].router_name
context = router_name ? send(router_name) : self
context.respond_to?(:root_path) ? context.root_path : "/"
end
# The default url to be used after updating a resource. You need to overwrite

View file

@ -102,9 +102,16 @@ module Devise
# tries to find a resource_root_path, otherwise it uses the root_path.
def signed_in_root_path(resource_or_scope)
scope = Devise::Mapping.find_scope!(resource_or_scope)
router_name = Devise.mappings[scope].router_name
home_path = "#{scope}_root_path"
if respond_to?(home_path, true)
send(home_path)
context = router_name ? send(router_name) : self
if context.respond_to?(home_path, true)
context.send(home_path)
elsif context.respond_to?(:root_path)
context.root_path
elsif respond_to?(:root_path)
root_path
else
@ -150,7 +157,10 @@ module Devise
#
# By default it is the root_path.
def after_sign_out_path_for(resource_or_scope)
respond_to?(:root_path) ? root_path : "/"
scope = Devise::Mapping.find_scope!(resource_or_scope)
router_name = Devise.mappings[scope].router_name
context = router_name ? send(router_name) : self
context.respond_to?(:root_path) ? context.root_path : "/"
end
# Sign in a user and tries to redirect first to the stored location and

View file

@ -47,7 +47,9 @@ module Devise
class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1
def #{method}(resource_or_scope, *args)
scope = Devise::Mapping.find_scope!(resource_or_scope)
_devise_route_context.send("#{action}\#{scope}_#{module_name}_#{path_or_url}", *args)
router_name = Devise.mappings[scope].router_name
context = router_name ? send(router_name) : _devise_route_context
context.send("#{action}\#{scope}_#{module_name}_#{path_or_url}", *args)
end
URL_HELPERS
end

View file

@ -23,7 +23,8 @@ module Devise
#
class Mapping #:nodoc:
attr_reader :singular, :scoped_path, :path, :controllers, :path_names,
:class_name, :sign_out_via, :format, :used_routes, :used_helpers, :failure_app
:class_name, :sign_out_via, :format, :used_routes, :used_helpers,
:failure_app, :router_name
alias :name :singular
@ -60,6 +61,8 @@ module Devise
@sign_out_via = options[:sign_out_via] || Devise.sign_out_via
@format = options[:format]
@router_name = options[:router_name]
default_failure_app(options)
default_controllers(options)
default_path_names(options)

View file

@ -153,6 +153,8 @@ module ActionDispatch::Routing
#
# * defaults: works the same as Rails' defaults
#
# * router_name: allows application level router name to be overwritten for the current scope
#
# ==== Scoping
#
# Following Rails 3 routes DSL, you can nest devise_for calls inside a scope:

View file

@ -47,6 +47,37 @@ class ConfirmationTest < ActionDispatch::IntegrationTest
assert_have_selector '#error_explanation'
assert_contain /needs to be confirmed within 3 days/
assert_not user.reload.confirmed?
assert_current_url "/users/confirmation?confirmation_token=#{user.raw_confirmation_token}"
end
end
test 'user with valid confirmation token where the token has expired and with application router_name set to a different engine it should raise an error' do
user = create_user(confirm: false, confirmation_sent_at: 4.days.ago)
swap Devise, confirm_within: 3.days, router_name: :fake_engine do
assert_raise ActionView::Template::Error do
visit_user_confirmation_with_token(user.raw_confirmation_token)
end
end
end
test 'user with valid confirmation token where the token has expired and with application router_name set to a different engine and route overrides back to main it shows the path' do
user = create_user(confirm: false, confirmation_sent_at: 4.days.ago)
swap Devise, confirm_within: 3.days, router_name: :fake_engine do
visit user_on_main_app_confirmation_path(confirmation_token: user.raw_confirmation_token)
assert_current_url "/user_on_main_apps/confirmation?confirmation_token=#{user.raw_confirmation_token}"
end
end
test 'user with valid confirmation token where the token has expired with router overrides different engine it shows the path' do
user = create_user(confirm: false, confirmation_sent_at: 4.days.ago)
swap Devise, confirm_within: 3.days do
visit user_on_engine_confirmation_path(confirmation_token: user.raw_confirmation_token)
assert_current_url "/user_on_engines/confirmation?confirmation_token=#{user.raw_confirmation_token}"
end
end

View file

@ -0,0 +1,7 @@
require 'shared_user_without_omniauth'
class UserOnEngine < ActiveRecord::Base
self.table_name = 'users'
include Shim
include SharedUserWithoutOmniauth
end

View file

@ -0,0 +1,7 @@
require 'shared_user_without_omniauth'
class UserOnMainApp < ActiveRecord::Base
self.table_name = 'users'
include Shim
include SharedUserWithoutOmniauth
end

View file

@ -7,3 +7,4 @@ class ApplicationController < ActionController::Base
before_filter :authenticate_user!, if: :devise_controller?
respond_to *Mime::SET.map(&:to_sym)
end

View file

@ -0,0 +1,30 @@
class ApplicationWithFakeEngine < ApplicationController
private
helper_method :fake_engine
def fake_engine
@fake_engine ||= FakeEngine.new
end
end
class FakeEngine
def user_on_engine_confirmation_path
'/user_on_engine/confirmation'
end
def new_user_on_engine_session_path
'/user_on_engine/confirmation/new'
end
def new_user_on_engine_registration_path
'/user_on_engine/registration/new'
end
def new_user_on_engine_password_path
'/user_on_engine/password/new'
end
def new_user_on_engine_unlock_path
'/user_on_engine/unlock/new'
end
end

View file

@ -0,0 +1,39 @@
require 'shared_user_without_omniauth'
class UserOnEngine
include Mongoid::Document
include Shim
include SharedUserWithoutOmniauth
field :username, type: String
field :facebook_token, type: String
## Database authenticatable
field :email, type: String, default: ""
field :encrypted_password, type: String, default: ""
## Recoverable
field :reset_password_token, type: String
field :reset_password_sent_at, type: Time
## Rememberable
field :remember_created_at, type: Time
## Trackable
field :sign_in_count, type: Integer, default: 0
field :current_sign_in_at, type: Time
field :last_sign_in_at, type: Time
field :current_sign_in_ip, type: String
field :last_sign_in_ip, type: String
## Confirmable
field :confirmation_token, type: String
field :confirmed_at, type: Time
field :confirmation_sent_at, type: Time
# field :unconfirmed_email, type: String # Only if using reconfirmable
## Lockable
field :failed_attempts, type: Integer, default: 0 # Only if lock strategy is :failed_attempts
field :unlock_token, type: String # Only if unlock strategy is :email or :both
field :locked_at, type: Time
end

View file

@ -0,0 +1,39 @@
require 'shared_user_without_omniauth'
class UserOnMainApp
include Mongoid::Document
include Shim
include SharedUserWithoutOmniauth
field :username, type: String
field :facebook_token, type: String
## Database authenticatable
field :email, type: String, default: ""
field :encrypted_password, type: String, default: ""
## Recoverable
field :reset_password_token, type: String
field :reset_password_sent_at, type: Time
## Rememberable
field :remember_created_at, type: Time
## Trackable
field :sign_in_count, type: Integer, default: 0
field :current_sign_in_at, type: Time
field :last_sign_in_at, type: Time
field :current_sign_in_ip, type: String
field :last_sign_in_ip, type: String
## Confirmable
field :confirmation_token, type: String
field :confirmed_at, type: Time
field :confirmation_sent_at, type: Time
# field :unconfirmed_email, type: String # Only if using reconfirmable
## Lockable
field :failed_attempts, type: Integer, default: 0 # Only if lock strategy is :failed_attempts
field :unlock_token, type: String # Only if unlock strategy is :email or :both
field :locked_at, type: Time
end

View file

@ -12,6 +12,8 @@ Devise.setup do |config|
# note that it will be overwritten if you use your own mailer class with default "from" parameter.
config.mailer_sender = "please-change-me@config-initializers-devise.com"
config.parent_controller = "ApplicationWithFakeEngine"
# Configure the class responsible to send e-mails.
# config.mailer = "Devise::Mailer"

View file

@ -20,6 +20,16 @@ Rails.application.routes.draw do
# Users scope
devise_for :users, controllers: { omniauth_callbacks: "users/omniauth_callbacks" }
devise_for :user_on_main_apps,
class_name: 'UserOnMainApp',
router_name: :main_app,
module: :devise
devise_for :user_on_engines,
class_name: 'UserOnEngine',
router_name: :fake_engine,
module: :devise
as :user do
get "/as/sign_in", to: "devise/sessions#new"
end

View file

@ -0,0 +1,13 @@
module SharedUserWithoutOmniauth
extend ActiveSupport::Concern
included do
devise :database_authenticatable, :confirmable, :lockable, :recoverable,
:registerable, :rememberable, :timeoutable,
:trackable, :validatable
end
def raw_confirmation_token
@raw_confirmation_token
end
end