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

Some major changes.

This commit is contained in:
José Valim 2009-10-11 22:11:58 -03:00
parent 91a87eed2c
commit bd8f7dc631
28 changed files with 160 additions and 290 deletions

View file

@ -1,5 +1,5 @@
class ConfirmationsController < ApplicationController
skip_before_filter :authenticate!
before_filter :find_resource_class
# GET /confirmation/new
#
@ -9,8 +9,8 @@ class ConfirmationsController < ApplicationController
# POST /confirmation
#
def create
@confirmation = resource_class.send_confirmation_instructions(params[:confirmation])
if @confirmation.errors.empty?
self.resource = resource_class.send_confirmation_instructions(params[:confirmation])
if resource.errors.empty?
flash[:success] = I18n.t(:send_instructions, :scope => [:devise, :confirmations], :default => 'You will receive an email with instructions about how to confirm your account in a few minutes.')
redirect_to new_session_path
else
@ -21,8 +21,8 @@ class ConfirmationsController < ApplicationController
# GET /confirmation?perishable_token=abcdef
#
def show
@confirmation = resource_class.confirm!(:perishable_token => params[:perishable_token])
if @confirmation.errors.empty?
self.resource = resource_class.confirm!(:perishable_token => params[:perishable_token])
if resource.errors.empty?
flash[:success] = I18n.t(:confirm, :scope => [:devise, :confirmations], :default => 'Your account was successfully confirmed!')
redirect_to new_session_path
else

View file

@ -1,6 +1,5 @@
class PasswordsController < ApplicationController
skip_before_filter :authenticate!
before_filter :require_no_authentication
before_filter :find_resource_class, :require_no_authentication
# GET /password/new
#

View file

@ -1,31 +1,28 @@
class SessionsController < ApplicationController
before_filter :authenticate!, :only => :destroy
#before_filter :require_no_authentication, :except => :destroy
before_filter :find_resource_class
# GET /session/new
#
# GET /session/sign_in
# TODO Test me
def new
set_flash_message :failure, params[:message].to_sym, true if params[:message]
end
# POST /session
#
# POST /session/sign_in
def create
self.resource = resource_class.authenticate(params[resource_name])
if resource #authenticate
self.current_user = resource
flash[:success] = I18n.t(:signed_in, :scope => [:devise, :sessions], :default => 'Signed in successfully.')
if warden.authenticate(:scope => resource_name)
set_flash_message :success, :signed_in
redirect_to root_path
else
flash.now[:failure] = I18n.t(:authentication_failed, :scope => [:devise, :sessions], :default => 'Invalid email or password.')
set_flash_message :failure, :unauthenticated, true
render :new
end
end
# DELETE /session
#
# GET /session/sign_out
# DELETE /session/sign_out
def destroy
logout
flash[:success] = I18n.t(:signed_out, :scope => [:devise, :sessions], :default => 'Signed out successfully.')
logout(resource_name)
set_flash_message :success, :signed_out
redirect_to new_session_path
end
end

View file

@ -1,14 +0,0 @@
module DeviseHelper
def link_to_sign_in
link_to I18n.t(:sign_in, :scope => [:devise, :links], :default => 'Sign in'), new_session_path
end
def link_to_new_password
link_to I18n.t(:new_password, :scope => [:devise, :links], :default => 'Forgot password?'), new_password_path
end
def link_to_new_confirmation
link_to I18n.t(:new_confirmation, :scope => [:devise, :links], :default => 'Didn\'t receive confirmation instructions?'), new_confirmation_path
end
end

View file

@ -1,11 +1,13 @@
<h2><%= t '.title', :default => 'Resend confirmation instructions', :scope => :devise %></h2>
<h2>Resend confirmation instructions</h2>
<%= error_messages_for :confirmation %>
<% form_for resource_name, :url => confirmation_path(resource_name) do |f| %>
<%= f.error_messages %>
<% form_for :confirmation, :url => confirmation_path do |f| %>
<p><%= f.label :email %></p>
<p><%= f.text_field :email %></p>
<p class="submit"><%= f.submit t('.submit', :default => 'Resend confirmation instructions', :scope => :devise) %></p>
<p><%= f.submit "Resend confirmation instructions" %></p>
<% end %>
<%= link_to_sign_in %> | <%= link_to_new_password %>
<%= link_to "Sign in", new_session_path(resource_name) %> |
<%= link_to "Forgot password?", new_password_path(resource_name) %>

View file

@ -1,13 +1,17 @@
<h2><%= t '.title', :default => 'Change your password', :scope => :devise %></h2>
<h2>Change your password</h2>
<% form_for resource_name, :url => password_path, :html => { :method => :put } do |f| %>
<% form_for resource_name, :url => password_path(resource_name), :html => { :method => :put } do |f| %>
<%= f.error_messages %>
<%= f.hidden_field :perishable_token %>
<p><%= f.label :password %></p>
<p><%= f.password_field :password %></p>
<p><%= f.label :password_confirmation %></p>
<p><%= f.password_field :password_confirmation %></p>
<p class="submit"><%= f.submit t('.submit', :default => 'Change my password', :scope => :devise) %></p>
<p><%= f.submit "Change my password" %></p>
<% end %>
<%= link_to_sign_in %> | <%= link_to_new_confirmation %>
<%= link_to "Sign in", new_session_path(resource_name) %> |
<%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %>

View file

@ -1,10 +1,13 @@
<h2><%= t '.title', :default => 'Forgot password', :scope => :devise %></h2>
<h2>Forgot your password?</h2>
<% form_for resource_name, :url => password_path do |f| %>
<% form_for resource_name, :url => password_path(resource_name) do |f| %>
<%= f.error_messages %>
<p><%= f.label :email %></p>
<p><%= f.text_field :email %></p>
<p class="submit"><%= f.submit t('.submit', :default => 'Send me reset password instructions', :scope => :devise) %></p>
<p><%= f.submit "Send me reset password instructions" %></p>
<% end %>
<%= link_to_sign_in %> | <%= link_to_new_confirmation %>
<%= link_to "Sign in", new_session_path(resource_name) %> |
<%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %>

View file

@ -1,11 +1,14 @@
<h2><%= t '.title', :default => 'Sign in', :scope => :devise %></h2>
<h2>Sign in</h2>
<% form_for resource_name, :url => session_path do |f| -%>
<% form_for :session, :url => session_path(resource_name) do |f| -%>
<p><%= f.label :email %></p>
<p><%= f.text_field :email %></p>
<p><%= f.label :password %></p>
<p><%= f.password_field :password %></p>
<p class='submit'><%= f.submit t('.submit', :default => 'Sign in', :scope => :devise) %></p>
<p><%= f.submit "Sign in" %></p>
<% end -%>
<%= link_to_new_password %> | <%= link_to_new_confirmation %>
<%= link_to "Forgot password?", new_password_path(resource_name) %> |
<%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %>

View file

@ -1,35 +1,15 @@
en:
devise:
sessions:
authentication_failed: 'Invalid email or password.'
signed_in: 'Signed in successfully.'
signed_out: 'Signed out successfully.'
new:
title: 'Sign in'
submit: 'Sign in'
unauthenticated: 'Invalid email or password.'
passwords:
send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
update: 'Your password was changed successfully.'
new:
title: 'Forgot password'
submit: 'Send me reset password instructions'
edit:
title: 'Change your password'
submit: 'Change my password'
confirmations:
send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.'
confirm: 'Your account was successfully confirmed!'
new:
title: 'Resend confirmation instructions'
submit: 'Resend confirmation instructions'
links:
sign_in: 'Sign in'
new_password: 'Forgot password?'
new_confirmation: "Didn't receive confirmation instructions?"
routes:
session: 'session'
password: 'password'
confirmation: 'confirmation'
confirmed: 'Your account was successfully confirmed!'
notifier:
confirmation_instructions: 'Confirmation instructions'
reset_password_instructions: 'Reset password instructions'

View file

@ -1,13 +1,9 @@
ActionController::Routing::Routes.draw do |map|
def t(route_name)
I18n.t(route_name, :scope => [:devise, :routes], :default => route_name.to_s)
end
Devise.mappings.each do |resource, mapping|
map.namespace mapping.resource, :namespace => nil, :path_prefix => mapping.as do |devise_map|
devise_map.resource :session, :only => [:new, :create, :destroy], :as => t(:session)
devise_map.resource :password, :only => [:new, :create, :edit, :update], :as => t(:password)
devise_map.resource :confirmation, :only => [:new, :create, :show], :as => t(:confirmation)
map.namespace mapping.name, :namespace => nil, :path_prefix => mapping.as do |devise_map|
devise_map.resource :session, :only => [:new, :create, :destroy]
devise_map.resource :password, :only => [:new, :create, :edit, :update]
devise_map.resource :confirmation, :only => [:new, :create, :show]
end
end
end

View file

@ -9,25 +9,25 @@ require 'devise/initializers/warden'
module Devise
class Mapping
attr_accessor :resource, :as, :for
attr_reader :name, :as, :for
def initialize(options={})
@resource = options[:resource]
@to = options[:to]
@for = options[:for]
@as = options[:as] || resource.to_s.pluralize
def initialize(name, options)
@name = name
@for = Array(options[:for])
@klass = (options[:to] || name.to_s.classify).to_s
@as = (options[:as] || name.to_s.pluralize).to_sym
end
# Reload mapped class each time when cache_classes is false
# Reload mapped class each time when cache_classes is false.
#
def to
return @to if @to
to = resource.to_s.classify.constantize
@to = to if Rails.configuration.cache_classes
to
klass = @klass.constantize
@to = klass if Rails.configuration.cache_classes
klass
end
# Acts as hash
# Acts as a hash.
#
def [](key)
send(key)
@ -35,31 +35,24 @@ module Devise
end
mattr_accessor :mappings
self.mappings = {}.with_indifferent_access
self.mappings = {}
def self.map(mapping, options={})
raise ArgumentError, "Need to provide :for option for Devise.map" unless options.key?(:for)
options.assert_valid_keys(:to, :for, :as)
mapping = mapping.to_s.singularize.to_sym
mappings[mapping] = Mapping.new(options.merge(:resource => mapping))
self.mappings[mapping] = Mapping.new(mapping, options)
end
def self.find_mapping(map)
map = map.to_s.split('/').reject(&:blank?).first
map_sym = map.try(:to_sym)
if mappings.key?(map_sym)
mappings[map_sym]
elsif mapping = mappings.detect{|m, options| options[:as] == map}.try(:first)
mappings[mapping]
# TODO Test me
def self.find_mapping_by_path(path)
route = path.split("/")[1]
return nil unless route
route = route.to_sym
mappings.each do |key, map|
return map if map.as == route.to_sym
end
end
def self.resource_name(map)
find_mapping(map).try(:resource).to_s
end
def self.resource_class(map)
find_mapping(map).try(:to)
nil
end
end

View file

@ -3,7 +3,6 @@ module Devise
def self.included(base)
base.class_eval do
include DeviseHelper
include Devise::Controllers::Resources
include Devise::Controllers::UrlHelpers
end

View file

@ -4,6 +4,8 @@ module Devise
# Some helpers taken from RailsWarden.
module Authenticable
protected
def self.included(base)
base.class_eval do
helper_method :warden, :current_user, :signed_in?
@ -39,6 +41,12 @@ module Devise
warden.raw_session.inspect # Without this inspect here. The session does not clear :|
warden.logout(resource_name)
end
# TODO Test me
def set_flash_message(key, kind, now=false)
hash = now ? flash.now : flash
hash[key] = I18n.t(:"#{resource_name}.#{kind}", :scope => [:devise, controller_name.to_sym], :default => kind)
end
end
end
end

View file

@ -2,6 +2,8 @@ module Devise
module Controllers
module Filters
protected
# 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
@ -19,22 +21,17 @@ module Devise
# 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. By default resource_name is verified, but you can pass in any
# scope to verify whether there is a user authenticated within that scope.
#
def authenticate!(scope=resource_name)
redirect_to new_session_path(scope) unless authenticated?(scope)
class_eval <<-METHOD
def #{mapping}_authenticate!
warden.authenticate!(:devise, :scope => :#{mapping})
end
METHOD
end
# Helper for use in before_filters where no authentication is required.
# Please note that all scopes will be tested within this filter, and if
# one of then is authenticated the filter will redirect.
#
# Example:
# before_filter :require_no_authentication, :only => :new
#
@ -43,6 +40,7 @@ module Devise
redirect_to root_path if authenticated?(map)
end
end
end
end
end

View file

@ -2,27 +2,33 @@ module Devise
module Controllers
module Resources
protected
def resource
@resource ||= instance_variable_get(:"@#{resource_name}")
instance_variable_get(:"@#{resource_name}")
end
def resource=(new_resource)
@resource = instance_variable_set(:"@#{resource_name}", new_resource)
instance_variable_set(:"@#{resource_name}", new_resource)
end
def resource_name(object=nil)
@resource_name ||= Devise.resource_name(resource_name_or_request_path(object))
def resource_name
devise_mapping.name
end
def resource_class
@resource_class ||= Devise.resource_class(resource_name_or_request_path)
devise_mapping.to
end
private
def devise_mapping
@devise_mapping ||= Devise.find_mapping_by_path(request.path)
end
# TODO Test me
def find_resource_class
render :status => :not_found unless devise_mapping
end
def resource_name_or_request_path(object=nil)
object ? (object.is_a?(::ActiveRecord::Base) ? object.class.name.downcase : object) : request.path
end
end
end
end

View file

@ -2,23 +2,32 @@ module Devise
module Controllers
module UrlHelpers
# TODO: refactor url helpers generation
protected
[:session, :password, :confirmation].each do |module_name|
[:path, :url].each do |path_or_url|
actions = ['', 'new_']
actions << 'edit_' if module_name == :password
actions = [ nil, :new_ ]
actions << :edit_ if module_name == :password
actions.each do |action|
class_eval <<-URL_HELPERS
def #{action}#{module_name}_#{path_or_url}(*args)
resource = case args.first
when ::ActiveRecord::Base, Symbol, String then args.shift
def #{action}#{module_name}_#{path_or_url}(resource, *args)
resource = case resource
when Symbol, String
resource
when Class
resource.name.underscore
else
resource.class.name.underscore
end
send("#{action}\#{resource_name(resource)}_#{module_name}_#{path_or_url}", *args)
send("#{action}\#{resource}_#{module_name}_#{path_or_url}", *args)
end
URL_HELPERS
end
end
end
end
end
end

View file

@ -1,4 +1,5 @@
# Taken from RailsWarden, thanks to Hassox. http://github.com/hassox/rails_warden
# Taken from RailsWarden, thanks to Hassox.
# http://github.com/hassox/rails_warden
#
module Warden::Mixins::Common
# Gets the rails request object by default if it's available
@ -21,29 +22,16 @@ module Warden::Mixins::Common
end
end
# Rails needs the action to be passed in with the params
Warden::Manager.before_failure do |env, opts|
env['warden'].request.params['action'] = 'new'
if request = env["action_controller.rescue.request"]
request.params["action"] = 'new'
end
end
# Session Serialization in. This block determines how the user will
# be stored in the session. If you're using a complex object like an
# ActiveRecord model, it is not a good idea to store the complete object.
# An ID is sufficient
# Session Serialization in. This block determines how the user will be stored
# in the session. If you're using a complex object like an ActiveRecord model,
# it is not a good idea to store the complete object. An ID is sufficient.
#
Warden::Manager.serialize_into_session{ |user| [user.class, user.id] }
# Session Serialization out. This block gets the user out of the session.
# Session Serialization out. This block gets the user out of the session.
# It should be the reverse of serializing the object into the session
#
Warden::Manager.serialize_from_session do |klass, id|
klass = case klass
when Class
klass
when String, Symbol
klass.to_s.classify.constantize
end
klass.find(id)
end
@ -52,29 +40,36 @@ end
#
Warden::Strategies.add(:devise) do
# Validate params before authenticating a user. If both email and password are
# not present, no authentication is attempted.
#
# def valid?
# params[:session] ||= {}
# params[:session][:email].present? && params[:session][:password].present?
# end
def valid?
raise "You need to give a scope for Devise authentication" unless scope
raise "You need to give a valid Devise mapping" unless @mapping = Devise.mappings[scope]
true
end
# Authenticate a user based on email and password params, returning to warden
# success and the authenticated user if everything is okay. Otherwise tell
# warden the authentication was failed.
# success and the authenticated user if everything is okay. Otherwise redirect
# to login page.
#
def authenticate!
pass
# if params[:session] && user = Devise.resource_class(request.path).authenticate(params[:session][:email], params[:session][:password])
# success!(user)
# else
# pass
# redirect!('/users/session/new')
# throw :warden
# fail!(I18n.t(:authentication_failed, :scope => [:devise, :sessions], :default => 'Invalid email or password'))
# end
if valid_session? && resource = @mapping.to.authenticate(session)
success!(resource)
else
redirect!("/#{@mapping.as}/session/new?message=unauthenticated")
end
end
# Find the session for the current mapping.
#
def session
@session ||= request.params[:session]
end
# Check for the right keys.
#
def valid_session?
session && session[:email].present? && session[:password].present?
end
end
# Adds Warden Manager to Rails middleware stack, configuring default devise

View file

@ -19,6 +19,7 @@ module Devise
require 'digest/sha1'
mattr_accessor :pepper, :stretches
# Pepper for encrypting password
self.pepper = '23c64df433d9b08e464db5c05d1e6202dd2823f0'
# Encrypt password as many times as possible
@ -87,7 +88,7 @@ module Devise
#
def authenticate(attributes={})
authenticable = self.find_by_email(attributes[:email])
authenticable if authenticable.valid_password?(attributes[:password]) unless authenticable.nil?
authenticable if authenticable.try(:valid_password?, attributes[:password])
end
end
end

View file

@ -1,47 +0,0 @@
require 'test/test_helper'
class DeviseHelperTest < ActionView::TestCase
def store_translations(translations={})
I18n.locale = :'pt-BR'
I18n.backend.store_translations(:'pt-BR', :devise => { :links => translations })
end
def teardown
I18n.locale = :en
I18n.reload!
end
test 'should generate a link to sign in' do
self.stubs(:new_session_path).returns(new_user_session_path)
assert_equal %[<a href="#{new_user_session_path}">Sign in</a>], link_to_sign_in
end
test 'should use i18n to translante sign in link' do
self.stubs(:new_session_path).returns(new_user_session_path)
store_translations(:sign_in => 'Login')
assert_equal %[<a href="#{new_user_session_path}">Login</a>], link_to_sign_in
end
test 'should generate a link to forgot password' do
self.stubs(:new_password_path).returns(new_user_password_path)
assert_equal %[<a href="#{new_user_password_path}">Forgot password?</a>], link_to_new_password
end
test 'should use i18n to translante forgot password link' do
self.stubs(:new_password_path).returns(new_user_password_path)
store_translations(:new_password => 'New password?')
assert_equal %[<a href="#{new_user_password_path}">New password?</a>], link_to_new_password
end
test 'should generate a link to confirmation instructions' do
self.stubs(:new_confirmation_path).returns(new_user_confirmation_path)
assert_equal %[<a href="#{new_user_confirmation_path}">Didn't receive confirmation instructions?</a>], link_to_new_confirmation
end
test 'should use i18n to translante confirmation link' do
self.stubs(:new_confirmation_path).returns(new_user_confirmation_path)
store_translations(:new_confirmation => 'New confirmation?')
assert_equal %[<a href="#{new_user_confirmation_path}">New confirmation?</a>], link_to_new_confirmation
end
end

View file

@ -37,5 +37,5 @@ Rails::Initializer.run do |config|
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}')]
# config.i18n.default_locale = :de
end
# config.i18n.default_locale = :en
end

View file

@ -1,7 +0,0 @@
# Be sure to restart your server when you modify this file.
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
# You can also remove all the silencers if you're trying do debug a problem that might steem from framework code.
# Rails.backtrace_cleaner.remove_silencers!

View file

@ -1,10 +0,0 @@
# Be sure to restart your server when you modify this file.
# Add new inflection rules using the following format
# (all these examples are active by default):
# ActiveSupport::Inflector.inflections do |inflect|
# inflect.plural /^(ox)$/i, '\1en'
# inflect.singular /^(ox)en/i, '\1'
# inflect.irregular 'person', 'people'
# inflect.uncountable %w( fish sheep )
# end

View file

@ -1,5 +0,0 @@
# Be sure to restart your server when you modify this file.
# Add new mime types for use in respond_to blocks:
# Mime::Type.register "text/richtext", :rtf
# Mime::Type.register_alias "text/html", :iphone

View file

@ -1,7 +0,0 @@
# This file should contain all the record creation needed to seed the database with its default values.
# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
#
# Examples:
#
# cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }])
# Major.create(:name => 'Daley', :city => cities.first)

View file

@ -1,7 +0,0 @@
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
# one:
# column: value
#
# two:
# column: value

View file

@ -1,8 +0,0 @@
require 'test_helper'
class UserTest < ActiveSupport::TestCase
# Replace this with your real tests.
test "the truth" do
assert true
end
end

View file

@ -14,12 +14,6 @@ class SessionRoutingTest < ActionController::TestCase
assert_recognizes({:controller => 'sessions', :action => 'destroy'}, {:path => 'users/session', :method => :delete})
end
test 'translate session route' do
translated_route(:session => 'sessao') do
assert_recognizes({:controller => 'sessions', :action => 'new'}, 'users/sessao/new')
end
end
test 'new admin session route' do
assert_recognizes({:controller => 'sessions', :action => 'new'}, 'admin_area/session/new')
end

View file

@ -1,12 +0,0 @@
class ActionController::TestCase
def translated_route(translation={}, &block)
I18n.locale = :'pt-BR'
I18n.backend.store_translations(:'pt-BR', :devise => { :routes => translation })
ActionController::Routing::Routes.reload!
yield
I18n.locale = :en
I18n.reload!
ActionController::Routing::Routes.reload!
end
end