mirror of
https://github.com/heartcombo/devise.git
synced 2026-01-09 23:08:05 -05:00
Introducing Registerable module, allowing users to sign up.
This commit is contained in:
@@ -7,11 +7,12 @@ Devise is a flexible authentication solution for Rails based on Warden. It:
|
||||
* Allows you to have multiple roles (or models/scopes) signed in at the same time;
|
||||
* Is based on a modularity concept: use just what you really need.
|
||||
|
||||
Right now it's composed of nine modules:
|
||||
Right now it's composed of ten modules:
|
||||
|
||||
* Authenticatable: responsible for encrypting password and validating authenticity of a user while signing in.
|
||||
* Confirmable: responsible for verifying whether an account is already confirmed to sign in, and to send emails with confirmation instructions.
|
||||
* Recoverable: takes care of reseting the user password and send reset instructions.
|
||||
* Registerable: handles signing up users through a registration process.
|
||||
* Rememberable: manages generating and clearing token for remember the user from a saved cookie.
|
||||
* Trackable: tracks sign in count, timestamps and ip.
|
||||
* Validatable: creates all needed validations for email and password. It's totally optional, so you're able to to customize validations by yourself.
|
||||
@@ -170,7 +171,7 @@ Since devise is an engine, it has all default views inside the gem. They are goo
|
||||
|
||||
ruby script/generate devise_views
|
||||
|
||||
By default Devise will use the same views for all roles you have. But what if you need so different views to each of them? Devise also has an easy way to accomplish it: just setup config.scoped_views to true inside "config/initializers/devise.rb".
|
||||
By default Devise will use the same views for all roles you have. But what if you need so different views to each of them? Devise also has an easy way to accomplish it: just setup config.scoped_views to true inside "config/initializers/devise.rb".
|
||||
|
||||
After doing so you will be able to have views based on the scope like 'sessions/users/new' and 'sessions/admin/new'. If no view is found within the scope, Devise will fallback to the default view.
|
||||
|
||||
|
||||
22
app/controllers/registrations_controller.rb
Normal file
22
app/controllers/registrations_controller.rb
Normal file
@@ -0,0 +1,22 @@
|
||||
class RegistrationsController < ApplicationController
|
||||
include Devise::Controllers::InternalHelpers
|
||||
include Devise::Controllers::Common
|
||||
|
||||
# POST /resource/registration
|
||||
def create
|
||||
self.resource = resource_class.new(params[resource_name])
|
||||
|
||||
if resource.save
|
||||
# Attempt to sign the resource in. When there is no other thing blocking
|
||||
# the resource (ie confirmations), then the resource will be signed in,
|
||||
# otherwise the specific message is shown and the resource will be
|
||||
# redirected to the sign in page.
|
||||
sign_in(resource_name, resource)
|
||||
# At this time the resource has signed in and no hook has signed it out.
|
||||
set_flash_message :notice, :signed_up
|
||||
sign_in_and_redirect(resource_name, resource, true)
|
||||
else
|
||||
render_with_scope :new
|
||||
end
|
||||
end
|
||||
end
|
||||
19
app/views/registrations/new.html.erb
Normal file
19
app/views/registrations/new.html.erb
Normal file
@@ -0,0 +1,19 @@
|
||||
<h2>Sign up</h2>
|
||||
|
||||
<%- if devise_mapping.registerable? %>
|
||||
<% form_for resource_name, resource, :url => registration_path(resource_name) do |f| -%>
|
||||
<%= f.error_messages %>
|
||||
<p><%= f.label :email %></p>
|
||||
<p><%= f.text_field :email %></p>
|
||||
|
||||
<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><%= f.submit "Register" %></p>
|
||||
<% end -%>
|
||||
<% end%>
|
||||
|
||||
<%= render :partial => "shared/devise_links" %>
|
||||
@@ -2,6 +2,10 @@
|
||||
<%= link_to t('devise.sessions.link'), new_session_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
|
||||
<%= link_to t('devise.registrations.link'), new_registration_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.recoverable? && controller_name != 'passwords' %>
|
||||
<%= link_to t('devise.passwords.link'), new_password_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
@@ -12,4 +16,4 @@
|
||||
|
||||
<%- if devise_mapping.lockable? && controller_name != 'unlocks' %>
|
||||
<%= link_to t('devise.unlocks.link'), new_unlock_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
|
||||
@@ -26,14 +26,16 @@ module Devise
|
||||
autoload :MongoMapper, 'devise/orm/mongo_mapper'
|
||||
end
|
||||
|
||||
ALL = [:authenticatable, :activatable, :confirmable, :recoverable,
|
||||
:rememberable, :validatable, :trackable, :timeoutable, :lockable, :token_authenticatable]
|
||||
ALL = [:authenticatable, :activatable, :confirmable, :lockable, :recoverable,
|
||||
:registerable, :rememberable, :timeoutable, :token_authenticatable,
|
||||
:trackable, :validatable]
|
||||
|
||||
# Maps controller names to devise modules
|
||||
CONTROLLERS = {
|
||||
:sessions => [:authenticatable, :token_authenticatable],
|
||||
:passwords => [:recoverable],
|
||||
:confirmations => [:confirmable],
|
||||
:registrations => [:registerable],
|
||||
:unlocks => [:lockable]
|
||||
}
|
||||
|
||||
@@ -231,4 +233,4 @@ rescue
|
||||
end
|
||||
|
||||
require 'devise/mapping'
|
||||
require 'devise/rails'
|
||||
require 'devise/rails'
|
||||
|
||||
@@ -19,7 +19,7 @@ module Devise
|
||||
# Those helpers are added to your ApplicationController.
|
||||
module UrlHelpers
|
||||
|
||||
[:session, :password, :confirmation, :unlock].each do |module_name|
|
||||
[:session, :password, :confirmation, :registration, :unlock].each do |module_name|
|
||||
[:path, :url].each do |path_or_url|
|
||||
actions = [ nil, :new_ ]
|
||||
actions << :edit_ if module_name == :password
|
||||
|
||||
@@ -19,6 +19,9 @@ en:
|
||||
link: "Didn't receive confirmation instructions?"
|
||||
send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.'
|
||||
confirmed: 'Your account was successfully confirmed. You are now signed in.'
|
||||
registrations:
|
||||
link: 'Sign up'
|
||||
signed_up: 'You have signed up successfully.'
|
||||
unlocks:
|
||||
link: "Didn't receive unlock instructions?"
|
||||
send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.'
|
||||
@@ -27,3 +30,4 @@ en:
|
||||
confirmation_instructions: 'Confirmation instructions'
|
||||
reset_password_instructions: 'Reset password instructions'
|
||||
unlock_instructions: 'Unlock Instructions'
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ module Devise
|
||||
# Configure default path names, allowing the user overwrite defaults by
|
||||
# passing a hash in :path_names.
|
||||
def setup_path_names
|
||||
[:sign_in, :sign_out, :password, :confirmation].each do |path_name|
|
||||
[:sign_in, :sign_out, :password, :confirmation, :registration, :unlock].each do |path_name|
|
||||
@path_names[path_name] ||= path_name.to_s
|
||||
end
|
||||
end
|
||||
|
||||
8
lib/devise/models/registerable.rb
Normal file
8
lib/devise/models/registerable.rb
Normal file
@@ -0,0 +1,8 @@
|
||||
module Devise
|
||||
module Models
|
||||
# Registerable is responsible for everything related to registering a new
|
||||
# resource (ie account or sign up).
|
||||
module Registerable
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -105,10 +105,6 @@ module ActionController::Routing
|
||||
end
|
||||
end
|
||||
|
||||
def recoverable(routes, mapping)
|
||||
routes.resource :password, :only => [:new, :create, :edit, :update], :as => mapping.path_names[:password]
|
||||
end
|
||||
|
||||
def confirmable(routes, mapping)
|
||||
routes.resource :confirmation, :only => [:new, :create, :show], :as => mapping.path_names[:confirmation]
|
||||
end
|
||||
@@ -117,6 +113,13 @@ module ActionController::Routing
|
||||
routes.resource :unlock, :only => [:new, :create, :show], :as => mapping.path_names[:unlock]
|
||||
end
|
||||
|
||||
def recoverable(routes, mapping)
|
||||
routes.resource :password, :only => [:new, :create, :edit, :update], :as => mapping.path_names[:password]
|
||||
end
|
||||
|
||||
def registerable(routes, mapping)
|
||||
routes.resource :registration, :only => [:new, :create], :as => mapping.path_names[:registration]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
58
test/integration/registerable_test.rb
Normal file
58
test/integration/registerable_test.rb
Normal file
@@ -0,0 +1,58 @@
|
||||
require 'test/test_helper'
|
||||
|
||||
class RegistrationTest < ActionController::IntegrationTest
|
||||
|
||||
test 'a guest admin should be able to sign in successfully' do
|
||||
visit new_admin_session_path
|
||||
click_link 'Sign up'
|
||||
|
||||
assert_template 'registrations/new'
|
||||
|
||||
fill_in 'email', :with => 'new_user@test.com'
|
||||
fill_in 'password', :with => 'new_user123'
|
||||
fill_in 'password confirmation', :with => 'new_user123'
|
||||
click_button 'Register'
|
||||
|
||||
assert_contain 'You have signed up successfully.'
|
||||
assert warden.authenticated?(:admin)
|
||||
|
||||
admin = Admin.last
|
||||
assert_equal admin.email, 'new_user@test.com'
|
||||
end
|
||||
|
||||
test 'a guest user should be able to sign up successfully and be blocked by confirmation' do
|
||||
visit new_user_session_path
|
||||
click_link 'Sign up'
|
||||
|
||||
assert_template 'registrations/new'
|
||||
|
||||
fill_in 'email', :with => 'new_user@test.com'
|
||||
fill_in 'password', :with => 'new_user123'
|
||||
fill_in 'password confirmation', :with => 'new_user123'
|
||||
click_button 'Register'
|
||||
|
||||
follow_redirect!
|
||||
|
||||
assert_contain 'You have to confirm your account before continuing.'
|
||||
assert_not warden.authenticated?(:user)
|
||||
|
||||
user = User.last
|
||||
assert_equal user.email, 'new_user@test.com'
|
||||
end
|
||||
|
||||
test 'a guest user cannot sign up with invalid information' do
|
||||
visit new_user_session_path
|
||||
click_link 'Sign up'
|
||||
|
||||
fill_in 'email', :with => 'invalid_email'
|
||||
fill_in 'password', :with => 'new_user123'
|
||||
fill_in 'password confirmation', :with => 'new_user321'
|
||||
click_button 'Register'
|
||||
|
||||
assert_template 'registrations/new'
|
||||
assert_have_selector '#errorExplanation'
|
||||
assert_contain "Email is invalid"
|
||||
assert_contain "Password doesn't match confirmation"
|
||||
assert_nil User.first
|
||||
end
|
||||
end
|
||||
@@ -67,6 +67,8 @@ class MappingTest < ActiveSupport::TestCase
|
||||
assert_equal 'sign_out', mapping.path_names[:sign_out]
|
||||
assert_equal 'password', mapping.path_names[:password]
|
||||
assert_equal 'confirmation', mapping.path_names[:confirmation]
|
||||
assert_equal 'registration', mapping.path_names[:registration]
|
||||
assert_equal 'unlock', mapping.path_names[:unlock]
|
||||
end
|
||||
|
||||
test 'allow custom path names to be given' do
|
||||
@@ -75,6 +77,8 @@ class MappingTest < ActiveSupport::TestCase
|
||||
assert_equal 'logout', mapping.path_names[:sign_out]
|
||||
assert_equal 'secret', mapping.path_names[:password]
|
||||
assert_equal 'verification', mapping.path_names[:confirmation]
|
||||
assert_equal 'sign_up', mapping.path_names[:registration]
|
||||
assert_equal 'unblock', mapping.path_names[:unlock]
|
||||
end
|
||||
|
||||
test 'has an empty path as default path prefix' do
|
||||
@@ -86,7 +90,7 @@ class MappingTest < ActiveSupport::TestCase
|
||||
mapping = Devise.mappings[:manager]
|
||||
assert_equal '/:locale/', mapping.path_prefix
|
||||
end
|
||||
|
||||
|
||||
test 'retrieve as from the proper position' do
|
||||
assert_equal 1, Devise.mappings[:user].as_position
|
||||
assert_equal 2, Devise.mappings[:manager].as_position
|
||||
@@ -96,13 +100,13 @@ class MappingTest < ActiveSupport::TestCase
|
||||
assert_equal '/users', Devise.mappings[:user].raw_path
|
||||
assert_equal '/:locale/accounts', Devise.mappings[:manager].raw_path
|
||||
end
|
||||
|
||||
|
||||
test 'raw path ignores the relative_url_root' do
|
||||
swap ActionController::Base, :relative_url_root => "/abc" do
|
||||
assert_equal '/users', Devise.mappings[:user].raw_path
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
test 'parsed path is returned' do
|
||||
begin
|
||||
Devise.default_url_options {{ :locale => I18n.locale }}
|
||||
@@ -112,7 +116,7 @@ class MappingTest < ActiveSupport::TestCase
|
||||
Devise.default_url_options {{ }}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
test 'parsed path adds in the relative_url_root' do
|
||||
swap ActionController::Base, :relative_url_root => '/abc' do
|
||||
assert_equal '/abc/users', Devise.mappings[:user].parsed_path
|
||||
|
||||
@@ -23,7 +23,7 @@ class ActiveRecordTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
test 'add modules cherry pick' do
|
||||
assert_include_modules Admin, :authenticatable, :timeoutable
|
||||
assert_include_modules Admin, :authenticatable, :registerable, :timeoutable
|
||||
end
|
||||
|
||||
test 'set a default value for stretches' do
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class Admin < ActiveRecord::Base
|
||||
devise :authenticatable, :timeoutable
|
||||
devise :authenticatable, :registerable, :timeoutable
|
||||
|
||||
def self.find_for_authentication(conditions)
|
||||
last(:conditions => conditions)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
class User < ActiveRecord::Base
|
||||
devise :authenticatable, :confirmable, :recoverable, :rememberable, :trackable,
|
||||
:validatable, :timeoutable, :lockable, :token_authenticatable
|
||||
devise :authenticatable, :confirmable, :lockable, :recoverable,
|
||||
:registerable, :rememberable, :timeoutable, :token_authenticatable,
|
||||
:trackable, :validatable
|
||||
|
||||
attr_accessible :username, :email, :password, :password_confirmation
|
||||
end
|
||||
|
||||
@@ -3,8 +3,9 @@ ActionController::Routing::Routes.draw do |map|
|
||||
map.devise_for :admin, :as => 'admin_area'
|
||||
map.devise_for :accounts, :scope => 'manager', :path_prefix => ':locale',
|
||||
:class_name => "User", :requirements => { :extra => 'value' }, :path_names => {
|
||||
:sign_in => 'login', :sign_out => 'logout', :password => 'secret',
|
||||
:confirmation => 'verification', :unlock => 'unblock'
|
||||
:sign_in => 'login', :sign_out => 'logout',
|
||||
:password => 'secret', :confirmation => 'verification',
|
||||
:unlock => 'unblock', :registration => 'sign_up'
|
||||
}
|
||||
|
||||
map.resources :users, :only => [:index], :member => { :expire => :get }
|
||||
|
||||
@@ -42,6 +42,26 @@ class MapRoutingTest < ActionController::TestCase
|
||||
assert_recognizes({:controller => 'passwords', :action => 'update'}, {:path => 'users/password', :method => :put})
|
||||
end
|
||||
|
||||
test 'map new user unlock' do
|
||||
assert_recognizes({:controller => 'unlocks', :action => 'new'}, 'users/unlock/new')
|
||||
end
|
||||
|
||||
test 'map create user unlock' do
|
||||
assert_recognizes({:controller => 'unlocks', :action => 'create'}, {:path => 'users/unlock', :method => :post})
|
||||
end
|
||||
|
||||
test 'map show user unlock' do
|
||||
assert_recognizes({:controller => 'unlocks', :action => 'show'}, {:path => 'users/unlock', :method => :get})
|
||||
end
|
||||
|
||||
test 'map new user registration' do
|
||||
assert_recognizes({:controller => 'registrations', :action => 'new'}, 'users/registration/new')
|
||||
end
|
||||
|
||||
test 'map create user registration' do
|
||||
assert_recognizes({:controller => 'registrations', :action => 'create'}, {:path => 'users/registration', :method => :post})
|
||||
end
|
||||
|
||||
test 'map admin session with :as option' do
|
||||
assert_recognizes({:controller => 'sessions', :action => 'new'}, {:path => 'admin_area/sign_in', :method => :get})
|
||||
end
|
||||
@@ -72,4 +92,7 @@ class MapRoutingTest < ActionController::TestCase
|
||||
assert_recognizes({:controller => 'unlocks', :action => 'new', :locale => 'en', :extra => 'value'}, '/en/accounts/unblock/new')
|
||||
end
|
||||
|
||||
test 'map account with custom path name for registration' do
|
||||
assert_recognizes({:controller => 'registrations', :action => 'new', :locale => 'en', :extra => 'value'}, '/en/accounts/sign_up/new')
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user