mirror of
https://github.com/heartcombo/devise.git
synced 2026-01-12 00:08:34 -05:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b78519e154 | ||
|
|
0430689b01 | ||
|
|
bc82165ee3 | ||
|
|
eecb2c1695 | ||
|
|
8fc18b49eb | ||
|
|
b4af49cc38 | ||
|
|
4c654e71be |
@@ -1,4 +1,5 @@
|
||||
script: "bundle exec rake test"
|
||||
before_install: gem update --system
|
||||
rvm:
|
||||
- 1.8.7
|
||||
- 1.9.2
|
||||
|
||||
@@ -1,43 +1,16 @@
|
||||
== trunk (2.1.0.rc2)
|
||||
|
||||
* enhancements
|
||||
* Devise model generator now works with engines
|
||||
* Devise encryptable was moved to its new gem (http://github.com/plataformatec/devise-encryptable)
|
||||
|
||||
* deprecations
|
||||
* Deprecations warnings added on Devise 2.0 are now removed with their features
|
||||
* use_salt_as_remember_token and apply_schema does not have any effect since 2.0 and are now deprecated
|
||||
* valid_for_authentication? must now return a boolean
|
||||
== 2.0.6
|
||||
|
||||
* bug fix
|
||||
* Ensure the failure app still respects config.relative_url_root
|
||||
* `/users/sign_in` doesn't choke on protected attributes used to select sign in scope (by @Paymium)
|
||||
* `failed_attempts` is set to zero after any sign in (including via reset password) (by @rodrigoflores)
|
||||
* Added token expiration on timeout (by @antiarchitect)
|
||||
* Do not accidentally mark `_prefixes` as private
|
||||
* Better support for custom strategies on test helpers (by @mattconnolly)
|
||||
* Return `head :no_content` in SessionsController now that most JS libraries handle it (by @julianvargasalvarez)
|
||||
* Do not confirm account after reset password
|
||||
|
||||
== 2.1.0.rc
|
||||
|
||||
* enhancements
|
||||
* Add check_fields! method on Devise::Models to check if the model includes the fields that Devise uses
|
||||
* Add `skip_reconfirmation!` to skip reconfirmation
|
||||
== 2.0.5
|
||||
|
||||
* bug fix
|
||||
* Ensure after sign in hook is not called without a resource
|
||||
* Fix a term: now on Omniauth related flash messages, we say that we're authenticating from an omniauth provider instead of authorizing
|
||||
* Fixed redirect when authenticated mounted apps (by @hakanensari)
|
||||
|
||||
* deprecation
|
||||
* All devise modules should have a required_fields(klass) module method to help gathering missing attributes
|
||||
* Require string conversion for all values
|
||||
|
||||
== 2.0.4
|
||||
|
||||
Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.0
|
||||
|
||||
* bug fix
|
||||
* Fix when :host is used with devise_for (by @mreinsch)
|
||||
* Fix a regression that caused Warden to be initialized too late
|
||||
|
||||
== 2.0.3 (yanked)
|
||||
@@ -93,7 +66,6 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
|
||||
* Move devise/shared/_links.erb to devise/_links.erb
|
||||
* Deprecated support of nested devise_for blocks
|
||||
* Deprecated support to devise.registrations.reasons and devise.registrations.inactive_signed_up in favor of devise.registrations.signed_up_but_*
|
||||
* Protected method render_with_scope was removed.
|
||||
|
||||
== 1.5.3
|
||||
|
||||
|
||||
2
Gemfile
2
Gemfile
@@ -25,7 +25,7 @@ platforms :jruby do
|
||||
end
|
||||
|
||||
platforms :ruby do
|
||||
gem "sqlite3"
|
||||
gem "sqlite3-ruby"
|
||||
|
||||
group :mongoid do
|
||||
gem "mongo", "~> 1.3.0"
|
||||
|
||||
10
Gemfile.lock
10
Gemfile.lock
@@ -1,9 +1,9 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
devise (2.1.0)
|
||||
devise (2.0.6)
|
||||
bcrypt-ruby (~> 3.0)
|
||||
orm_adapter (~> 0.0.7)
|
||||
orm_adapter (~> 0.0.3)
|
||||
railties (~> 3.1)
|
||||
warden (~> 1.1.1)
|
||||
|
||||
@@ -39,7 +39,7 @@ GEM
|
||||
multi_json (~> 1.0)
|
||||
addressable (2.2.6)
|
||||
arel (3.0.0)
|
||||
bcrypt-ruby (3.0.1)
|
||||
bcrypt-ruby (3.1.1)
|
||||
bson (1.5.1)
|
||||
bson_ext (1.3.1)
|
||||
builder (3.0.0)
|
||||
@@ -129,6 +129,8 @@ GEM
|
||||
rack (~> 1.0)
|
||||
tilt (~> 1.1, != 1.3.0)
|
||||
sqlite3 (1.3.5)
|
||||
sqlite3-ruby (1.3.3)
|
||||
sqlite3 (>= 1.3.3)
|
||||
thor (0.14.6)
|
||||
tilt (1.3.3)
|
||||
treetop (1.4.10)
|
||||
@@ -161,5 +163,5 @@ DEPENDENCIES
|
||||
rails (~> 3.2.0)
|
||||
rdoc
|
||||
ruby-debug (>= 0.10.3)
|
||||
sqlite3
|
||||
sqlite3-ruby
|
||||
webrat (= 0.7.2)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright 2009-2012 Plataformatec. http://plataformatec.com.br
|
||||
Copyright 2009-2012 Plataforma Tecnologia. http://blog.plataformatec.com.br
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
57
README.md
57
README.md
@@ -1,6 +1,4 @@
|
||||
*IMPORTANT:* Devise 2.1 is out. If you are upgrading, please read: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.1
|
||||
|
||||
*IMPORTANT:* Devise 2.0 is out. If you are upgrading, please read: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.0
|
||||
*IMPORTANT:* Devise 2.0.0 is out. If you are upgrading, please read: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.0
|
||||
|
||||
## Devise
|
||||
|
||||
@@ -17,17 +15,18 @@ Devise is a flexible authentication solution for Rails based on Warden. It:
|
||||
|
||||
It's comprised of 12 modules:
|
||||
|
||||
* [Database Authenticatable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/DatabaseAuthenticatable): encrypts and stores a password in the database to validate the authenticity of a user while signing in. The authentication can be done both through POST requests or HTTP Basic Authentication.
|
||||
* [Token Authenticatable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/TokenAuthenticatable): signs in a user based on an authentication token (also known as "single access token"). The token can be given both through query string or HTTP Basic Authentication.
|
||||
* [Omniauthable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Omniauthable): adds Omniauth (github.com/intridea/omniauth) support;
|
||||
* [Confirmable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Confirmable): sends emails with confirmation instructions and verifies whether an account is already confirmed during sign in.
|
||||
* [Recoverable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Recoverable): resets the user password and sends reset instructions.
|
||||
* [Registerable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Registerable): handles signing up users through a registration process, also allowing them to edit and destroy their account.
|
||||
* [Rememberable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Rememberable): manages generating and clearing a token for remembering the user from a saved cookie.
|
||||
* [Trackable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Trackable): tracks sign in count, timestamps and IP address.
|
||||
* [Timeoutable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Timeoutable): expires sessions that have no activity in a specified period of time.
|
||||
* [Validatable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Validatable): provides validations of email and password. It's optional and can be customized, so you're able to define your own validations.
|
||||
* [Lockable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Lockable): locks an account after a specified number of failed sign-in attempts. Can unlock via email or after a specified time period.
|
||||
* Database Authenticatable: encrypts and stores a password in the database to validate the authenticity of a user while signing in. The authentication can be done both through POST requests or HTTP Basic Authentication.
|
||||
* Token Authenticatable: signs in a user based on an authentication token (also known as "single access token"). The token can be given both through query string or HTTP Basic Authentication.
|
||||
* Omniauthable: adds Omniauth (github.com/intridea/omniauth) support;
|
||||
* Confirmable: sends emails with confirmation instructions and verifies whether an account is already confirmed during sign in.
|
||||
* Recoverable: resets the user password and sends reset instructions.
|
||||
* Registerable: handles signing up users through a registration process, also allowing them to edit and destroy their account.
|
||||
* Rememberable: manages generating and clearing a token for remembering the user from a saved cookie.
|
||||
* Trackable: tracks sign in count, timestamps and IP address.
|
||||
* Timeoutable: expires sessions that have no activity in a specified period of time.
|
||||
* Validatable: provides validations of email and password. It's optional and can be customized, so you're able to define your own validations.
|
||||
* Lockable: locks an account after a specified number of failed sign-in attempts. Can unlock via email or after a specified time period.
|
||||
* Encryptable: adds support of other authentication mechanisms besides the built-in Bcrypt (the default).
|
||||
|
||||
## Information
|
||||
|
||||
@@ -43,7 +42,7 @@ If you discover a problem with Devise, we would like to know about it. However,
|
||||
|
||||
https://github.com/plataformatec/devise/wiki/Bug-reports
|
||||
|
||||
If you found a security bug, do *NOT* use the GitHub issue tracker. Send an email to the maintainers listed at the bottom of the README.
|
||||
If you found a security bug, do *NOT* use the GitHub issue tracker. Send email or a private GitHub message to the maintainers listed at the bottom of the README.
|
||||
|
||||
### Mailing list
|
||||
|
||||
@@ -92,9 +91,7 @@ Once you have solidified your understanding of Rails and authentication mechanis
|
||||
|
||||
Devise 2.0 works with Rails 3.1 onwards. You can add it to your Gemfile with:
|
||||
|
||||
```ruby
|
||||
gem 'devise'
|
||||
```
|
||||
gem 'devise'
|
||||
|
||||
Run the bundle command to install it.
|
||||
|
||||
@@ -112,8 +109,6 @@ rails generate devise MODEL
|
||||
|
||||
Replace MODEL by the class name used for the applications users, it's frequently 'User' but could also be 'Admin'. This will create a model (if one does not exist) and configure it with default Devise modules. Next, you'll usually run "rake db:migrate" as the generator will have created a migration file (if your ORM supports them). This generator also configures your config/routes.rb file to point to Devise controller.
|
||||
|
||||
Note that you should re-start your app here if you've already started it. Otherwise you'll run into strange errors like users being unable to login and the route helpers being undefined.
|
||||
|
||||
### Controller filters and helpers
|
||||
|
||||
Devise will create some helpers to use inside your controllers and views. To set up a controller with user authentication, just add this before_filter:
|
||||
@@ -140,13 +135,13 @@ You can access the session for this scope:
|
||||
user_session
|
||||
```
|
||||
|
||||
After signing in a user, confirming the account or updating the password, Devise will look for a scoped root path to redirect. Example: For a :user resource, it will use `user_root_path` if it exists, otherwise default `root_path` will be used. This means that you need to set the root inside your routes:
|
||||
After signing in a user, confirming the account or updating the password, Devise will look for a scoped root path to redirect. Example: For a :user resource, it will use +user_root_path+ if it exists, otherwise default +root_path+ will be used. This means that you need to set the root inside your routes:
|
||||
|
||||
```ruby
|
||||
root :to => "home#index"
|
||||
```
|
||||
|
||||
You can also overwrite `after_sign_in_path_for` and `after_sign_out_path_for` to customize your redirect hooks.
|
||||
You can also overwrite +after_sign_in_path_for+ and +after_sign_out_path_for+ to customize your redirect hooks.
|
||||
|
||||
Finally, you need to set up default url options for the mailer in each environment. Here is the configuration for "config/environments/development.rb":
|
||||
|
||||
@@ -252,9 +247,9 @@ Devise also ships with default routes. If you need to customize them, you should
|
||||
devise_for :users, :path => "usuarios", :path_names => { :sign_in => 'login', :sign_out => 'logout', :password => 'secret', :confirmation => 'verification', :unlock => 'unblock', :registration => 'register', :sign_up => 'cmon_let_me_in' }
|
||||
```
|
||||
|
||||
Be sure to check `devise_for` documentation for details.
|
||||
Be sure to check +devise_for+ documentation for details.
|
||||
|
||||
If you have the need for more deep customization, for instance to also allow "/sign_in" besides "/users/sign_in", all you need to do is to create your routes normally and wrap them in a `devise_scope` block in the router:
|
||||
If you have the need for more deep customization, for instance to also allow "/sign_in" besides "/users/sign_in", all you need to do is to create your routes normally and wrap them in a +devise_scope+ block in the router:
|
||||
|
||||
```ruby
|
||||
devise_scope :user do
|
||||
@@ -262,7 +257,15 @@ devise_scope :user do
|
||||
end
|
||||
```
|
||||
|
||||
This way you tell devise to use the scope :user when "/sign_in" is accessed. Notice `devise_scope` is also aliased as `as` in your router.
|
||||
This way you tell devise to use the scope :user when "/sign_in" is accessed. Notice +devise_scope+ is also aliased as +as+ and you can also give a block to +devise_for+, resulting in the same behavior:
|
||||
|
||||
```ruby
|
||||
devise_for :users do
|
||||
get "sign_in", :to => "devise/sessions#new"
|
||||
end
|
||||
```
|
||||
|
||||
Feel free to choose the one you prefer!
|
||||
|
||||
### I18n
|
||||
|
||||
@@ -324,7 +327,7 @@ class ActionController::TestCase
|
||||
end
|
||||
```
|
||||
|
||||
If you're using RSpec and want the helpers automatically included within all `describe` blocks, add a file called spec/support/devise.rb with the following contents:
|
||||
If you're using RSpec and want the helpers automatically included within all +describe+ blocks, add a file called spec/support/devise.rb with the following contents:
|
||||
|
||||
```ruby
|
||||
RSpec.configure do |config|
|
||||
@@ -382,4 +385,4 @@ https://github.com/plataformatec/devise/contributors
|
||||
|
||||
## License
|
||||
|
||||
MIT License. Copyright 2012 Plataformatec. http://plataformatec.com.br
|
||||
MIT License. Copyright 2012 Plataforma Tecnologia. http://blog.plataformatec.com.br
|
||||
|
||||
2
Rakefile
2
Rakefile
@@ -1,5 +1,5 @@
|
||||
# encoding: UTF-8
|
||||
require "bundler/gem_tasks"
|
||||
|
||||
require 'rake/testtask'
|
||||
require 'rdoc/task'
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ class Devise::ConfirmationsController < DeviseController
|
||||
|
||||
# POST /resource/confirmation
|
||||
def create
|
||||
self.resource = resource_class.send_confirmation_instructions(resource_params)
|
||||
self.resource = resource_class.send_confirmation_instructions(params[resource_name])
|
||||
|
||||
if successfully_sent?(resource)
|
||||
respond_with({}, :location => after_resending_confirmation_instructions_path_for(resource_name))
|
||||
|
||||
@@ -8,7 +8,7 @@ class Devise::PasswordsController < DeviseController
|
||||
|
||||
# POST /resource/password
|
||||
def create
|
||||
self.resource = resource_class.send_reset_password_instructions(resource_params)
|
||||
self.resource = resource_class.send_reset_password_instructions(params[resource_name])
|
||||
|
||||
if successfully_sent?(resource)
|
||||
respond_with({}, :location => after_sending_reset_password_instructions_path_for(resource_name))
|
||||
@@ -25,7 +25,7 @@ class Devise::PasswordsController < DeviseController
|
||||
|
||||
# PUT /resource/password
|
||||
def update
|
||||
self.resource = resource_class.reset_password_by_token(resource_params)
|
||||
self.resource = resource_class.reset_password_by_token(params[resource_name])
|
||||
|
||||
if resource.errors.empty?
|
||||
flash_message = resource.active_for_authentication? ? :updated : :updated_not_active
|
||||
|
||||
@@ -39,7 +39,7 @@ class Devise::RegistrationsController < DeviseController
|
||||
def update
|
||||
self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
|
||||
|
||||
if resource.update_with_password(resource_params)
|
||||
if resource.update_with_password(params[resource_name])
|
||||
if is_navigational_format?
|
||||
if resource.respond_to?(:pending_reconfirmation?) && resource.pending_reconfirmation?
|
||||
flash_key = :update_needs_confirmation
|
||||
@@ -77,7 +77,7 @@ class Devise::RegistrationsController < DeviseController
|
||||
# Build a devise resource passing in the session. Useful to move
|
||||
# temporary session data to the newly created user.
|
||||
def build_resource(hash=nil)
|
||||
hash ||= resource_params || {}
|
||||
hash ||= params[resource_name] || {}
|
||||
self.resource = resource_class.new_with_session(hash, session)
|
||||
end
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ class Devise::SessionsController < DeviseController
|
||||
|
||||
# GET /resource/sign_in
|
||||
def new
|
||||
resource = build_resource(nil, :unsafe => true)
|
||||
resource = build_resource
|
||||
clean_up_passwords(resource)
|
||||
respond_with(resource, serialize_options(resource))
|
||||
end
|
||||
@@ -28,7 +28,9 @@ class Devise::SessionsController < DeviseController
|
||||
respond_to do |format|
|
||||
format.any(*navigational_formats) { redirect_to redirect_path }
|
||||
format.all do
|
||||
head :no_content
|
||||
method = "to_#{request_format}"
|
||||
text = {}.respond_to?(method) ? {}.send(method) : ""
|
||||
render :text => text, :status => :ok
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,10 +8,10 @@ class Devise::UnlocksController < DeviseController
|
||||
|
||||
# POST /resource/unlock
|
||||
def create
|
||||
self.resource = resource_class.send_unlock_instructions(resource_params)
|
||||
self.resource = resource_class.send_unlock_instructions(params[resource_name])
|
||||
|
||||
if successfully_sent?(resource)
|
||||
respond_with({}, :location => after_sending_unlock_instructions_path_for(resource))
|
||||
respond_with({}, :location => new_session_path(resource_name))
|
||||
else
|
||||
respond_with(resource)
|
||||
end
|
||||
@@ -23,22 +23,9 @@ class Devise::UnlocksController < DeviseController
|
||||
|
||||
if resource.errors.empty?
|
||||
set_flash_message :notice, :unlocked if is_navigational_format?
|
||||
respond_with_navigational(resource){ redirect_to after_unlock_path_for(resource) }
|
||||
respond_with_navigational(resource){ redirect_to new_session_path(resource) }
|
||||
else
|
||||
respond_with_navigational(resource.errors, :status => :unprocessable_entity){ render :new }
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# The path used after sending unlock password instructions
|
||||
def after_sending_unlock_instructions_path_for(resource)
|
||||
new_session_path(resource)
|
||||
end
|
||||
|
||||
# The path used after unlocking the resource
|
||||
def after_unlock_path_for(resource)
|
||||
new_session_path(resource)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -5,7 +5,7 @@ class DeviseController < Devise.parent_controller.constantize
|
||||
helper DeviseHelper
|
||||
|
||||
helpers = %w(resource scope_name resource_name signed_in_resource
|
||||
resource_class resource_params devise_mapping)
|
||||
resource_class devise_mapping)
|
||||
hide_action *helpers
|
||||
helper_method *helpers
|
||||
|
||||
@@ -28,10 +28,6 @@ class DeviseController < Devise.parent_controller.constantize
|
||||
devise_mapping.to
|
||||
end
|
||||
|
||||
def resource_params
|
||||
params[resource_name]
|
||||
end
|
||||
|
||||
# Returns a signed in resource from session (if one exists)
|
||||
def signed_in_resource
|
||||
warden.authenticate(:scope => resource_name)
|
||||
@@ -42,17 +38,6 @@ class DeviseController < Devise.parent_controller.constantize
|
||||
@devise_mapping ||= request.env["devise.mapping"]
|
||||
end
|
||||
|
||||
# Override prefixes to consider the scoped view.
|
||||
def _prefixes #:nodoc:
|
||||
@_prefixes ||= if self.class.scoped_views? && devise_mapping
|
||||
super.unshift("#{devise_mapping.scoped_path}/#{controller_name}")
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
hide_action :_prefixes
|
||||
|
||||
protected
|
||||
|
||||
# Checks whether it's a devise mapped resource or not.
|
||||
@@ -83,20 +68,9 @@ MESSAGE
|
||||
end
|
||||
|
||||
# Build a devise resource.
|
||||
# Assignment bypasses attribute protection when :unsafe option is passed
|
||||
def build_resource(hash = nil, options = {})
|
||||
hash ||= resource_params || {}
|
||||
|
||||
if options[:unsafe]
|
||||
self.resource = resource_class.new.tap do |resource|
|
||||
hash.each do |key, value|
|
||||
setter = :"#{key}="
|
||||
resource.send(setter, value) if resource.respond_to?(setter)
|
||||
end
|
||||
end
|
||||
else
|
||||
self.resource = resource_class.new(hash)
|
||||
end
|
||||
def build_resource(hash=nil)
|
||||
hash ||= params[resource_name] || {}
|
||||
self.resource = resource_class.new(hash)
|
||||
end
|
||||
|
||||
# Helper for use in before_filters where no authentication is required.
|
||||
@@ -115,7 +89,8 @@ MESSAGE
|
||||
warden.authenticated?(resource_name)
|
||||
end
|
||||
|
||||
if authenticated && resource = warden.user(resource_name)
|
||||
if authenticated
|
||||
resource = warden.user(resource_name)
|
||||
flash[:alert] = I18n.t("devise.failure.already_authenticated")
|
||||
redirect_to after_sign_in_path_for(resource)
|
||||
end
|
||||
@@ -178,4 +153,13 @@ MESSAGE
|
||||
def is_navigational_format?
|
||||
Devise.navigational_formats.include?(request.format.try(:ref))
|
||||
end
|
||||
end
|
||||
|
||||
# Override prefixes to consider the scoped view.
|
||||
def _prefixes #:nodoc:
|
||||
@_prefixes ||= if self.class.scoped_views? && devise_mapping
|
||||
super.unshift("#{devise_mapping.scoped_path}/#{controller_name}")
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,3 +1,25 @@
|
||||
<% ActiveSupport::Deprecation.warn "Rendering partials devise/_links.erb is deprecated" \
|
||||
"please use devise/shared/_links.erb instead."%>
|
||||
<%= render "shared/links" %>
|
||||
<%- if controller_name != 'sessions' %>
|
||||
<%= link_to "Sign in", new_session_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
|
||||
<%= link_to "Sign up", new_registration_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.recoverable? && controller_name != 'passwords' %>
|
||||
<%= link_to "Forgot your password?", new_password_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
|
||||
<%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
|
||||
<%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.omniauthable? %>
|
||||
<%- resource_class.omniauth_providers.each do |provider| %>
|
||||
<%= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider) %><br />
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
@@ -9,4 +9,4 @@
|
||||
<div><%= f.submit "Resend confirmation instructions" %></div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
<%= render "links" %>
|
||||
@@ -13,4 +13,4 @@
|
||||
<div><%= f.submit "Change my password" %></div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
<%= render "links" %>
|
||||
@@ -9,4 +9,4 @@
|
||||
<div><%= f.submit "Send me reset password instructions" %></div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
<%= render "links" %>
|
||||
@@ -15,4 +15,4 @@
|
||||
<div><%= f.submit "Sign up" %></div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
<%= render "links" %>
|
||||
|
||||
@@ -14,4 +14,4 @@
|
||||
<div><%= f.submit "Sign in" %></div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
<%= render "links" %>
|
||||
@@ -1,25 +1,3 @@
|
||||
<%- if controller_name != 'sessions' %>
|
||||
<%= link_to "Sign in", new_session_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
|
||||
<%= link_to "Sign up", new_registration_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.recoverable? && controller_name != 'passwords' %>
|
||||
<%= link_to "Forgot your password?", new_password_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
|
||||
<%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
|
||||
<%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.omniauthable? %>
|
||||
<%- resource_class.omniauth_providers.each do |provider| %>
|
||||
<%= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider) %><br />
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
<% ActiveSupport::Deprecation.warn "Rendering partials devise/shared/_links.erb is deprecated" \
|
||||
"please use devise/_links.erb instead." %>
|
||||
<%= render "links" %>
|
||||
@@ -9,4 +9,4 @@
|
||||
<div><%= f.submit "Resend unlock instructions" %></div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
<%= render "links" %>
|
||||
@@ -28,10 +28,10 @@ en:
|
||||
send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
|
||||
updated: 'Your password was changed successfully. You are now signed in.'
|
||||
updated_not_active: 'Your password was changed successfully.'
|
||||
send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
|
||||
send_paranoid_instructions: "If your e-mail exists on our database, you will receive a password recovery link on your e-mail"
|
||||
confirmations:
|
||||
send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.'
|
||||
send_paranoid_instructions: 'If your email address exists in our database, you will receive an email with instructions about how to confirm your account in a few minutes.'
|
||||
send_paranoid_instructions: 'If your e-mail exists on our database, 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:
|
||||
signed_up: 'Welcome! You have signed up successfully.'
|
||||
@@ -46,8 +46,8 @@ en:
|
||||
unlocked: 'Your account has been unlocked successfully. Please sign in to continue.'
|
||||
send_paranoid_instructions: 'If your account exists, you will receive an email with instructions about how to unlock it in a few minutes.'
|
||||
omniauth_callbacks:
|
||||
success: 'Successfully authenticated from %{kind} account.'
|
||||
failure: 'Could not authenticate you from %{kind} because "%{reason}".'
|
||||
success: 'Successfully authorized from %{kind} account.'
|
||||
failure: 'Could not authorize you from %{kind} because "%{reason}".'
|
||||
mailer:
|
||||
confirmation_instructions:
|
||||
subject: 'Confirmation instructions'
|
||||
|
||||
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
|
||||
s.require_paths = ["lib"]
|
||||
|
||||
s.add_dependency("warden", "~> 1.1.1")
|
||||
s.add_dependency("orm_adapter", "~> 0.0.7")
|
||||
s.add_dependency("orm_adapter", "~> 0.0.3")
|
||||
s.add_dependency("bcrypt-ruby", "~> 3.0")
|
||||
s.add_dependency("railties", "~> 3.1")
|
||||
end
|
||||
|
||||
@@ -25,7 +25,7 @@ platforms :jruby do
|
||||
end
|
||||
|
||||
platforms :ruby do
|
||||
gem "sqlite3"
|
||||
gem "sqlite3-ruby"
|
||||
|
||||
group :mongoid do
|
||||
gem "mongo", "~> 1.3.0"
|
||||
|
||||
@@ -1,46 +1,46 @@
|
||||
PATH
|
||||
remote: ..
|
||||
specs:
|
||||
devise (2.1.0.rc2)
|
||||
devise (2.0.6)
|
||||
bcrypt-ruby (~> 3.0)
|
||||
orm_adapter (~> 0.0.7)
|
||||
orm_adapter (~> 0.0.3)
|
||||
railties (~> 3.1)
|
||||
warden (~> 1.1.1)
|
||||
|
||||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
actionmailer (3.1.4)
|
||||
actionpack (= 3.1.4)
|
||||
actionmailer (3.1.3)
|
||||
actionpack (= 3.1.3)
|
||||
mail (~> 2.3.0)
|
||||
actionpack (3.1.4)
|
||||
activemodel (= 3.1.4)
|
||||
activesupport (= 3.1.4)
|
||||
actionpack (3.1.3)
|
||||
activemodel (= 3.1.3)
|
||||
activesupport (= 3.1.3)
|
||||
builder (~> 3.0.0)
|
||||
erubis (~> 2.7.0)
|
||||
i18n (~> 0.6)
|
||||
rack (~> 1.3.6)
|
||||
rack (~> 1.3.5)
|
||||
rack-cache (~> 1.1)
|
||||
rack-mount (~> 0.8.2)
|
||||
rack-test (~> 0.6.1)
|
||||
sprockets (~> 2.0.3)
|
||||
activemodel (3.1.4)
|
||||
activesupport (= 3.1.4)
|
||||
activemodel (3.1.3)
|
||||
activesupport (= 3.1.3)
|
||||
builder (~> 3.0.0)
|
||||
i18n (~> 0.6)
|
||||
activerecord (3.1.4)
|
||||
activemodel (= 3.1.4)
|
||||
activesupport (= 3.1.4)
|
||||
arel (~> 2.2.3)
|
||||
activerecord (3.1.3)
|
||||
activemodel (= 3.1.3)
|
||||
activesupport (= 3.1.3)
|
||||
arel (~> 2.2.1)
|
||||
tzinfo (~> 0.3.29)
|
||||
activeresource (3.1.4)
|
||||
activemodel (= 3.1.4)
|
||||
activesupport (= 3.1.4)
|
||||
activesupport (3.1.4)
|
||||
activeresource (3.1.3)
|
||||
activemodel (= 3.1.3)
|
||||
activesupport (= 3.1.3)
|
||||
activesupport (3.1.3)
|
||||
multi_json (~> 1.0)
|
||||
addressable (2.2.7)
|
||||
arel (2.2.3)
|
||||
bcrypt-ruby (3.0.1)
|
||||
arel (2.2.1)
|
||||
bcrypt-ruby (3.1.1)
|
||||
bson (1.5.2)
|
||||
bson_ext (1.3.1)
|
||||
builder (3.0.0)
|
||||
@@ -53,15 +53,15 @@ GEM
|
||||
hashie (1.2.0)
|
||||
hike (1.2.1)
|
||||
i18n (0.6.0)
|
||||
json (1.7.0)
|
||||
json (1.6.5)
|
||||
linecache (0.46)
|
||||
rbx-require-relative (> 0.0.4)
|
||||
mail (2.3.3)
|
||||
mail (2.3.0)
|
||||
i18n (>= 0.4.0)
|
||||
mime-types (~> 1.16)
|
||||
treetop (~> 1.4.8)
|
||||
metaclass (0.0.1)
|
||||
mime-types (1.18)
|
||||
mime-types (1.17.2)
|
||||
mocha (0.10.4)
|
||||
metaclass (~> 0.0.1)
|
||||
mongo (1.3.1)
|
||||
@@ -70,7 +70,7 @@ GEM
|
||||
activemodel (~> 3.1)
|
||||
mongo (~> 1.3)
|
||||
tzinfo (~> 0.3.22)
|
||||
multi_json (1.3.4)
|
||||
multi_json (1.0.4)
|
||||
multipart-post (1.1.5)
|
||||
nokogiri (1.5.0)
|
||||
oauth2 (0.5.2)
|
||||
@@ -90,7 +90,7 @@ GEM
|
||||
orm_adapter (0.0.7)
|
||||
polyglot (0.3.3)
|
||||
rack (1.3.6)
|
||||
rack-cache (1.2)
|
||||
rack-cache (1.1)
|
||||
rack (>= 0.4)
|
||||
rack-mount (0.8.3)
|
||||
rack (>= 1.0.0)
|
||||
@@ -101,17 +101,17 @@ GEM
|
||||
rack
|
||||
rack-test (0.6.1)
|
||||
rack (>= 1.0)
|
||||
rails (3.1.4)
|
||||
actionmailer (= 3.1.4)
|
||||
actionpack (= 3.1.4)
|
||||
activerecord (= 3.1.4)
|
||||
activeresource (= 3.1.4)
|
||||
activesupport (= 3.1.4)
|
||||
rails (3.1.3)
|
||||
actionmailer (= 3.1.3)
|
||||
actionpack (= 3.1.3)
|
||||
activerecord (= 3.1.3)
|
||||
activeresource (= 3.1.3)
|
||||
activesupport (= 3.1.3)
|
||||
bundler (~> 1.0)
|
||||
railties (= 3.1.4)
|
||||
railties (3.1.4)
|
||||
actionpack (= 3.1.4)
|
||||
activesupport (= 3.1.4)
|
||||
railties (= 3.1.3)
|
||||
railties (3.1.3)
|
||||
actionpack (= 3.1.3)
|
||||
activesupport (= 3.1.3)
|
||||
rack-ssl (~> 1.3.2)
|
||||
rake (>= 0.8.7)
|
||||
rdoc (~> 3.4)
|
||||
@@ -126,17 +126,19 @@ GEM
|
||||
ruby-debug-base (0.10.4)
|
||||
linecache (>= 0.3)
|
||||
ruby-openid (2.1.8)
|
||||
sprockets (2.0.4)
|
||||
sprockets (2.0.3)
|
||||
hike (~> 1.2)
|
||||
rack (~> 1.0)
|
||||
tilt (~> 1.1, != 1.3.0)
|
||||
sqlite3 (1.3.5)
|
||||
sqlite3-ruby (1.3.3)
|
||||
sqlite3 (>= 1.3.3)
|
||||
thor (0.14.6)
|
||||
tilt (1.3.3)
|
||||
treetop (1.4.10)
|
||||
polyglot
|
||||
polyglot (>= 0.3.1)
|
||||
tzinfo (0.3.33)
|
||||
tzinfo (0.3.31)
|
||||
warden (1.1.1)
|
||||
rack (>= 1.0)
|
||||
webrat (0.7.2)
|
||||
@@ -163,5 +165,5 @@ DEPENDENCIES
|
||||
rails (~> 3.1.0)
|
||||
rdoc
|
||||
ruby-debug (>= 0.10.3)
|
||||
sqlite3
|
||||
sqlite3-ruby
|
||||
webrat (= 0.7.2)
|
||||
|
||||
@@ -20,6 +20,15 @@ module Devise
|
||||
autoload :UrlHelpers, 'devise/controllers/url_helpers'
|
||||
end
|
||||
|
||||
module Encryptors
|
||||
autoload :Base, 'devise/encryptors/base'
|
||||
autoload :AuthlogicSha512, 'devise/encryptors/authlogic_sha512'
|
||||
autoload :ClearanceSha1, 'devise/encryptors/clearance_sha1'
|
||||
autoload :RestfulAuthenticationSha1, 'devise/encryptors/restful_authentication_sha1'
|
||||
autoload :Sha512, 'devise/encryptors/sha512'
|
||||
autoload :Sha1, 'devise/encryptors/sha1'
|
||||
end
|
||||
|
||||
module Mailers
|
||||
autoload :Helpers, 'devise/mailers/helpers'
|
||||
end
|
||||
@@ -43,6 +52,15 @@ module Devise
|
||||
# True values used to check params
|
||||
TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE']
|
||||
|
||||
# Declare encryptors length which are used in migrations.
|
||||
ENCRYPTORS_LENGTH = {
|
||||
:sha1 => 40,
|
||||
:sha512 => 128,
|
||||
:clearance_sha1 => 40,
|
||||
:restful_authentication_sha1 => 40,
|
||||
:authlogic_sha512 => 128
|
||||
}
|
||||
|
||||
# Custom domain for cookies. Not set by default
|
||||
mattr_accessor :rememberable_options
|
||||
@@rememberable_options = {}
|
||||
@@ -60,12 +78,14 @@ module Devise
|
||||
@@request_keys = []
|
||||
|
||||
# Keys that should be case-insensitive.
|
||||
# False by default for backwards compatibility.
|
||||
mattr_accessor :case_insensitive_keys
|
||||
@@case_insensitive_keys = [ :email ]
|
||||
@@case_insensitive_keys = false
|
||||
|
||||
# Keys that should have whitespace stripped.
|
||||
# False by default for backwards compatibility.
|
||||
mattr_accessor :strip_whitespace_keys
|
||||
@@strip_whitespace_keys = []
|
||||
@@strip_whitespace_keys = false
|
||||
|
||||
# If http authentication is enabled by default.
|
||||
mattr_accessor :http_authenticatable
|
||||
@@ -118,14 +138,14 @@ module Devise
|
||||
mattr_accessor :timeout_in
|
||||
@@timeout_in = 30.minutes
|
||||
|
||||
# Authentication token expiration on timeout
|
||||
mattr_accessor :expire_auth_token_on_timeout
|
||||
@@expire_auth_token_on_timeout = false
|
||||
|
||||
# Used to encrypt password. Please generate one with rake secret.
|
||||
mattr_accessor :pepper
|
||||
@@pepper = nil
|
||||
|
||||
# Used to define the password encryption algorithm.
|
||||
mattr_accessor :encryptor
|
||||
@@encryptor = nil
|
||||
|
||||
# Scoped views. Since it relies on fallbacks to render default views, it's
|
||||
# turned off by default.
|
||||
mattr_accessor :scoped_views
|
||||
@@ -158,8 +178,9 @@ module Devise
|
||||
@@reset_password_keys = [ :email ]
|
||||
|
||||
# Time interval you can reset your password with a reset password key
|
||||
# Nil by default for backwards compatibility.
|
||||
mattr_accessor :reset_password_within
|
||||
@@reset_password_within = 6.hours
|
||||
@@reset_password_within = nil
|
||||
|
||||
# The default scope which is used by warden.
|
||||
mattr_accessor :default_scope
|
||||
@@ -201,16 +222,36 @@ module Devise
|
||||
mattr_accessor :router_name
|
||||
@@router_name = nil
|
||||
|
||||
def self.encryptor=(value)
|
||||
warn "\n[DEVISE] To select a encryption which isn't bcrypt, you should use devise-encryptable gem.\n"
|
||||
# DEPRECATED CONFIG
|
||||
|
||||
# If true, uses salt as remember token and does not create it in the database.
|
||||
# By default is false for backwards compatibility.
|
||||
mattr_accessor :use_salt_as_remember_token
|
||||
@@use_salt_as_remember_token = false
|
||||
|
||||
# Tells if devise should apply the schema in ORMs where devise declaration
|
||||
# and schema belongs to the same class (as Datamapper and Mongoid).
|
||||
mattr_accessor :apply_schema
|
||||
@@apply_schema = true
|
||||
|
||||
def self.remember_across_browsers=(value)
|
||||
warn "\n[DEVISE] Devise.remember_across_browsers is deprecated and has no effect. Please remove it.\n"
|
||||
end
|
||||
|
||||
def self.use_salt_as_remember_token=(value)
|
||||
warn "\n[DEVISE] Devise.use_salt_as_remember_token is deprecated and has no effect. Please remove it.\n"
|
||||
def self.confirm_within=(value)
|
||||
warn "\n[DEVISE] Devise.confirm_within= is deprecated. Please set Devise.allow_unconfirmed_access_for= instead.\n"
|
||||
Devise.allow_unconfirmed_access_for = value
|
||||
end
|
||||
|
||||
def self.apply_schema=(value)
|
||||
warn "\n[DEVISE] Devise.apply_schema is deprecated and has no effect. Please remove it.\n"
|
||||
def self.cookie_options=(value)
|
||||
warn "\n[DEVISE] Devise.cookie_options= is deprecated. Please set Devise.rememberable_options= instead.\n"
|
||||
Devise.rememberable_options = value
|
||||
end
|
||||
|
||||
def self.stateless_token=(value)
|
||||
warn "\n[DEVISE] Devise.stateless_token= is deprecated. Please append :token_auth to Devise.skip_session_storage " \
|
||||
"instead, for example: Devise.skip_session_storage << :token_auth\n"
|
||||
Devise.skip_session_storage << :token_auth
|
||||
end
|
||||
|
||||
# PRIVATE CONFIGURATION
|
||||
|
||||
@@ -208,7 +208,7 @@ module Devise
|
||||
# if resource.is_a?(User) && resource.can_publish?
|
||||
# publisher_url
|
||||
# else
|
||||
# super
|
||||
# signed_in_root_path(resource)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
@@ -237,6 +237,11 @@ module Devise
|
||||
redirect_to after_sign_in_path_for(resource)
|
||||
end
|
||||
|
||||
def redirect_location(scope, resource) #:nodoc:
|
||||
ActiveSupport::Deprecation.warn "redirect_location in Devise is deprecated. Please use after_sign_in_path_for instead.", caller
|
||||
after_sign_in_path_for(resource)
|
||||
end
|
||||
|
||||
def expire_session_data_after_sign_in!
|
||||
session.keys.grep(/^devise\./).each { |k| session.delete(k) }
|
||||
end
|
||||
|
||||
19
lib/devise/encryptors/authlogic_sha512.rb
Normal file
19
lib/devise/encryptors/authlogic_sha512.rb
Normal file
@@ -0,0 +1,19 @@
|
||||
require "digest/sha2"
|
||||
|
||||
module Devise
|
||||
module Encryptors
|
||||
# = AuthlogicSha512
|
||||
# Simulates Authlogic's default encryption mechanism.
|
||||
# Warning: it uses Devise's stretches configuration to port Authlogic's one. Should be set to 20 in the initializer to simulate
|
||||
# the default behavior.
|
||||
class AuthlogicSha512 < Base
|
||||
# Generates a default password digest based on salt, pepper and the
|
||||
# incoming password.
|
||||
def self.digest(password, stretches, salt, pepper)
|
||||
digest = [password, salt].flatten.join('')
|
||||
stretches.times { digest = Digest::SHA512.hexdigest(digest) }
|
||||
digest
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
20
lib/devise/encryptors/base.rb
Normal file
20
lib/devise/encryptors/base.rb
Normal file
@@ -0,0 +1,20 @@
|
||||
module Devise
|
||||
# Implements a way of adding different encryptions.
|
||||
# The class should implement a self.digest method that taks the following params:
|
||||
# - password
|
||||
# - stretches: the number of times the encryption will be applied
|
||||
# - salt: the password salt as defined by devise
|
||||
# - pepper: Devise config option
|
||||
#
|
||||
module Encryptors
|
||||
class Base
|
||||
def self.digest
|
||||
raise NotImplemented
|
||||
end
|
||||
|
||||
def self.salt(stretches)
|
||||
Devise.friendly_token[0,20]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
17
lib/devise/encryptors/clearance_sha1.rb
Normal file
17
lib/devise/encryptors/clearance_sha1.rb
Normal file
@@ -0,0 +1,17 @@
|
||||
require "digest/sha1"
|
||||
|
||||
module Devise
|
||||
module Encryptors
|
||||
# = ClearanceSha1
|
||||
# Simulates Clearance's default encryption mechanism.
|
||||
# Warning: it uses Devise's pepper to port the concept of REST_AUTH_SITE_KEY
|
||||
# Warning: it uses Devise's stretches configuration to port the concept of REST_AUTH_DIGEST_STRETCHES
|
||||
class ClearanceSha1 < Base
|
||||
# Generates a default password digest based on salt, pepper and the
|
||||
# incoming password.
|
||||
def self.digest(password, stretches, salt, pepper)
|
||||
Digest::SHA1.hexdigest("--#{salt}--#{password}--")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
22
lib/devise/encryptors/restful_authentication_sha1.rb
Normal file
22
lib/devise/encryptors/restful_authentication_sha1.rb
Normal file
@@ -0,0 +1,22 @@
|
||||
require "digest/sha1"
|
||||
|
||||
module Devise
|
||||
module Encryptors
|
||||
# = RestfulAuthenticationSha1
|
||||
# Simulates Restful Authentication's default encryption mechanism.
|
||||
# Warning: it uses Devise's pepper to port the concept of REST_AUTH_SITE_KEY
|
||||
# Warning: it uses Devise's stretches configuration to port the concept of REST_AUTH_DIGEST_STRETCHES. Should be set to 10 in
|
||||
# the initializer to simulate the default behavior.
|
||||
class RestfulAuthenticationSha1 < Base
|
||||
|
||||
# Generates a default password digest based on salt, pepper and the
|
||||
# incoming password.
|
||||
def self.digest(password, stretches, salt, pepper)
|
||||
digest = pepper
|
||||
stretches.times { digest = Digest::SHA1.hexdigest([digest, salt, password, pepper].flatten.join('--')) }
|
||||
digest
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
25
lib/devise/encryptors/sha1.rb
Normal file
25
lib/devise/encryptors/sha1.rb
Normal file
@@ -0,0 +1,25 @@
|
||||
require "digest/sha1"
|
||||
|
||||
module Devise
|
||||
module Encryptors
|
||||
# = Sha1
|
||||
# Uses the Sha1 hash algorithm to encrypt passwords.
|
||||
class Sha1 < Base
|
||||
# Generates a default password digest based on stretches, salt, pepper and the
|
||||
# incoming password.
|
||||
def self.digest(password, stretches, salt, pepper)
|
||||
digest = pepper
|
||||
stretches.times { digest = self.secure_digest(salt, digest, password, pepper) }
|
||||
digest
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Generate a SHA1 digest joining args. Generated token is something like
|
||||
# --arg1--arg2--arg3--argN--
|
||||
def self.secure_digest(*tokens)
|
||||
::Digest::SHA1.hexdigest('--' << tokens.flatten.join('--') << '--')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
25
lib/devise/encryptors/sha512.rb
Normal file
25
lib/devise/encryptors/sha512.rb
Normal file
@@ -0,0 +1,25 @@
|
||||
require "digest/sha2"
|
||||
|
||||
module Devise
|
||||
module Encryptors
|
||||
# = Sha512
|
||||
# Uses the Sha512 hash algorithm to encrypt passwords.
|
||||
class Sha512 < Base
|
||||
# Generates a default password digest based on salt, pepper and the
|
||||
# incoming password.
|
||||
def self.digest(password, stretches, salt, pepper)
|
||||
digest = pepper
|
||||
stretches.times { digest = self.secure_digest(salt, digest, password, pepper) }
|
||||
digest
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Generate a Sha512 digest joining args. Generated token is something like
|
||||
# --arg1--arg2--arg3--argN--
|
||||
def self.secure_digest(*tokens)
|
||||
::Digest::SHA512.hexdigest('--' << tokens.flatten.join('--') << '--')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -89,9 +89,6 @@ module Devise
|
||||
route = :"new_#{scope}_session_path"
|
||||
opts[:format] = request_format unless skip_format?
|
||||
|
||||
config = Rails.application.config
|
||||
opts[:script_name] = (config.relative_url_root if config.respond_to?(:relative_url_root))
|
||||
|
||||
context = send(Devise.available_router_name)
|
||||
|
||||
if context.respond_to?(route)
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
# After each sign in, if resource responds to failed_attempts, sets it to 0
|
||||
# This is only triggered when the user is explicitly set (with set_user)
|
||||
Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
|
||||
if record.respond_to?(:failed_attempts) && warden.authenticated?(options[:scope])
|
||||
record.update_attribute(:failed_attempts, 0)
|
||||
end
|
||||
end
|
||||
@@ -11,7 +11,6 @@ Warden::Manager.after_set_user do |record, warden, options|
|
||||
|
||||
if record.timedout?(last_request_at)
|
||||
warden.logout(scope)
|
||||
record.reset_authentication_token! if record.respond_to?(:reset_authentication_token!) && record.expire_auth_token_on_timeout
|
||||
throw :warden, :scope => scope, :message => :timeout
|
||||
end
|
||||
|
||||
|
||||
@@ -1,15 +1,5 @@
|
||||
module Devise
|
||||
module Models
|
||||
class MissingAttribute < StandardError
|
||||
def initialize(attributes)
|
||||
@attributes = attributes
|
||||
end
|
||||
|
||||
def message
|
||||
"The following attribute(s) is (are) missing on your model: #{@attributes.join(", ")}"
|
||||
end
|
||||
end
|
||||
|
||||
# Creates configuration values for Devise and for the given module.
|
||||
#
|
||||
# Devise::Models.config(Devise::Authenticatable, :stretches, 10)
|
||||
@@ -49,28 +39,6 @@ module Devise
|
||||
end
|
||||
end
|
||||
|
||||
def self.check_fields!(klass)
|
||||
failed_attributes = []
|
||||
|
||||
klass.devise_modules.each do |mod|
|
||||
instance = klass.new
|
||||
|
||||
if const_get(mod.to_s.classify).respond_to?(:required_fields)
|
||||
const_get(mod.to_s.classify).required_fields(klass).each do |field|
|
||||
failed_attributes << field unless instance.respond_to?(field)
|
||||
end
|
||||
else
|
||||
ActiveSupport::Deprecation.warn "The module #{mod} doesn't implement self.required_fields(klass). " \
|
||||
"Devise uses required_fields to warn developers of any missing fields in their models. " \
|
||||
"Please implement #{mod}.required_fields(klass) that returns an array of symbols with the required fields."
|
||||
end
|
||||
end
|
||||
|
||||
if failed_attributes.any?
|
||||
fail Devise::Models::MissingAttribute.new(failed_attributes)
|
||||
end
|
||||
end
|
||||
|
||||
# Include the chosen devise modules in your model:
|
||||
#
|
||||
# devise :database_authenticatable, :confirmable, :recoverable
|
||||
@@ -89,10 +57,6 @@ module Devise
|
||||
devise_modules_hook! do
|
||||
include Devise::Models::Authenticatable
|
||||
selected_modules.each do |m|
|
||||
if m == :encryptable && !(defined?(Devise::Models::Encryptable))
|
||||
warn "[DEVISE] You're trying to include :encryptable in your model but it is not bundled with the Devise gem anymore. Please add `devise-encryptable` to your Gemfile to proceed.\n"
|
||||
end
|
||||
|
||||
mod = Devise::Models.const_get(m.to_s.classify)
|
||||
|
||||
if mod.const_defined?("ClassMethods")
|
||||
@@ -102,7 +66,7 @@ module Devise
|
||||
if class_mod.respond_to?(:available_configs)
|
||||
available_configs = class_mod.available_configs
|
||||
available_configs.each do |config|
|
||||
next unless options.key?(config)
|
||||
next unless options.key?(config)
|
||||
send(:"#{config}=", options.delete(config))
|
||||
end
|
||||
end
|
||||
@@ -116,12 +80,12 @@ module Devise
|
||||
end
|
||||
end
|
||||
|
||||
# The hook which is called inside devise.
|
||||
# So your ORM can include devise compatibility stuff.
|
||||
# The hook which is called inside devise. So your ORM can include devise
|
||||
# compatibility stuff.
|
||||
def devise_modules_hook!
|
||||
yield
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require 'devise/models/authenticatable'
|
||||
require 'devise/models/authenticatable'
|
||||
@@ -54,7 +54,7 @@ module Devise
|
||||
BLACKLIST_FOR_SERIALIZATION = [:encrypted_password, :reset_password_token, :reset_password_sent_at,
|
||||
:remember_created_at, :sign_in_count, :current_sign_in_at, :last_sign_in_at, :current_sign_in_ip,
|
||||
:last_sign_in_ip, :password_salt, :confirmation_token, :confirmed_at, :confirmation_sent_at,
|
||||
:remember_token, :unconfirmed_email, :failed_attempts, :unlock_token, :locked_at, :authentication_token]
|
||||
:unconfirmed_email, :failed_attempts, :unlock_token, :locked_at, :authentication_token]
|
||||
|
||||
included do
|
||||
class_attribute :devise_modules, :instance_writer => false
|
||||
@@ -64,10 +64,6 @@ module Devise
|
||||
before_validation :strip_whitespace
|
||||
end
|
||||
|
||||
def self.required_fields(klass)
|
||||
[]
|
||||
end
|
||||
|
||||
# Check if the current object is valid for authentication. This method and
|
||||
# find_for_authentication are the methods used in a Warden::Strategy to check
|
||||
# if a model should be signed in or not.
|
||||
@@ -78,10 +74,6 @@ module Devise
|
||||
block_given? ? yield : true
|
||||
end
|
||||
|
||||
def unauthenticated_message
|
||||
:invalid
|
||||
end
|
||||
|
||||
def active_for_authentication?
|
||||
true
|
||||
end
|
||||
@@ -102,11 +94,11 @@ module Devise
|
||||
end
|
||||
|
||||
def downcase_keys
|
||||
self.class.case_insensitive_keys.each { |k| self[k].try(:downcase!) }
|
||||
(self.class.case_insensitive_keys || []).each { |k| self[k].try(:downcase!) }
|
||||
end
|
||||
|
||||
def strip_whitespace
|
||||
self.class.strip_whitespace_keys.each { |k| self[k].try(:strip!) }
|
||||
(self.class.strip_whitespace_keys || []).each { |k| self[k].try(:strip!) }
|
||||
end
|
||||
|
||||
array = %w(serializable_hash)
|
||||
@@ -158,31 +150,24 @@ module Devise
|
||||
end
|
||||
|
||||
# Find first record based on conditions given (ie by the sign in form).
|
||||
# This method is always called during an authentication process but
|
||||
# it may be wrapped as well. For instance, database authenticatable
|
||||
# provides a `find_for_database_authentication` that wraps a call to
|
||||
# this method. This allows you to customize both database authenticatable
|
||||
# or the whole authenticate stack by customize `find_for_authentication.`
|
||||
#
|
||||
# Overwrite to add customized conditions, create a join, or maybe use a
|
||||
# namedscope to filter records while authenticating.
|
||||
# Example:
|
||||
#
|
||||
# def self.find_for_authentication(conditions={})
|
||||
# conditions[:active] = true
|
||||
# super
|
||||
# def self.find_for_authentication(tainted_conditions)
|
||||
# find_first_by_auth_conditions(tainted_conditions, :active => true)
|
||||
# end
|
||||
#
|
||||
# Finally, notice that Devise also queries for users in other scenarios
|
||||
# besides authentication, for example when retrieving an user to send
|
||||
# an e-mail for password reset. In such cases, find_for_authentication
|
||||
# is not called.
|
||||
def find_for_authentication(conditions)
|
||||
find_first_by_auth_conditions(conditions)
|
||||
def find_for_authentication(tainted_conditions)
|
||||
find_first_by_auth_conditions(tainted_conditions)
|
||||
end
|
||||
|
||||
def find_first_by_auth_conditions(conditions)
|
||||
to_adapter.find_first devise_param_filter.filter(conditions)
|
||||
def find_first_by_auth_conditions(tainted_conditions, opts={})
|
||||
to_adapter.find_first(devise_param_filter.filter(tainted_conditions).merge(opts))
|
||||
end
|
||||
|
||||
# Find an initialize a record setting an error if it can't be found.
|
||||
|
||||
@@ -33,13 +33,7 @@ module Devise
|
||||
before_create :generate_confirmation_token, :if => :confirmation_required?
|
||||
after_create :send_on_create_confirmation_instructions, :if => :confirmation_required?
|
||||
before_update :postpone_email_change_until_confirmation, :if => :postpone_email_change?
|
||||
after_update :send_confirmation_instructions, :if => :reconfirmation_required?
|
||||
end
|
||||
|
||||
def self.required_fields(klass)
|
||||
required_methods = [:confirmation_token, :confirmed_at, :confirmation_sent_at]
|
||||
required_methods << :unconfirmed_email if klass.reconfirmable
|
||||
required_methods
|
||||
after_update :send_confirmation_instructions, :if => :reconfirmation_required?
|
||||
end
|
||||
|
||||
# Confirm a user by setting it's confirmed_at to actual time. If the user
|
||||
@@ -51,7 +45,7 @@ module Devise
|
||||
self.confirmed_at = Time.now.utc
|
||||
|
||||
if self.class.reconfirmable && unconfirmed_email.present?
|
||||
skip_reconfirmation!
|
||||
@bypass_postpone = true
|
||||
self.email = unconfirmed_email
|
||||
self.unconfirmed_email = nil
|
||||
|
||||
@@ -105,12 +99,6 @@ module Devise
|
||||
self.confirmed_at = Time.now.utc
|
||||
end
|
||||
|
||||
# If you don't want reconfirmation to be sent, neither a code
|
||||
# to be generated, call skip_reconfirmation!
|
||||
def skip_reconfirmation!
|
||||
@bypass_postpone = true
|
||||
end
|
||||
|
||||
def headers_for(action)
|
||||
headers = super
|
||||
if action == :confirmation_instructions && pending_reconfirmation?
|
||||
@@ -177,11 +165,6 @@ module Devise
|
||||
generate_confirmation_token && save(:validate => false)
|
||||
end
|
||||
|
||||
def after_password_reset
|
||||
super
|
||||
confirm! unless confirmed?
|
||||
end
|
||||
|
||||
def postpone_email_change_until_confirmation
|
||||
@reconfirmation_required = true
|
||||
self.unconfirmed_email = self.email
|
||||
|
||||
@@ -27,10 +27,6 @@ module Devise
|
||||
attr_accessor :password_confirmation
|
||||
end
|
||||
|
||||
def self.required_fields(klass)
|
||||
[:encrypted_password] + klass.authentication_keys
|
||||
end
|
||||
|
||||
# Generates password encryption based on the given value.
|
||||
def password=(new_password)
|
||||
@password = new_password
|
||||
@@ -40,9 +36,9 @@ module Devise
|
||||
# Verifies whether an password (ie from sign in) is the user password.
|
||||
def valid_password?(password)
|
||||
return false if encrypted_password.blank?
|
||||
bcrypt = ::BCrypt::Password.new(encrypted_password)
|
||||
bcrypt = ::BCrypt::Password.new(self.encrypted_password)
|
||||
password = ::BCrypt::Engine.hash_secret("#{password}#{self.class.pepper}", bcrypt.salt)
|
||||
Devise.secure_compare(password, encrypted_password)
|
||||
Devise.secure_compare(password, self.encrypted_password)
|
||||
end
|
||||
|
||||
# Set password and password confirmation to nil
|
||||
@@ -100,7 +96,7 @@ module Devise
|
||||
|
||||
# A reliable way to expose the salt regardless of the implementation.
|
||||
def authenticatable_salt
|
||||
encrypted_password[0,29] if encrypted_password
|
||||
self.encrypted_password[0,29] if self.encrypted_password
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
72
lib/devise/models/encryptable.rb
Normal file
72
lib/devise/models/encryptable.rb
Normal file
@@ -0,0 +1,72 @@
|
||||
require 'devise/strategies/database_authenticatable'
|
||||
|
||||
module Devise
|
||||
module Models
|
||||
# Encryptable Module adds support to several encryptors.
|
||||
#
|
||||
# == Options
|
||||
#
|
||||
# Encryptable adds the following options to devise_for:
|
||||
#
|
||||
# * +pepper+: a random string used to provide a more secure hash.
|
||||
#
|
||||
# * +encryptor+: the encryptor going to be used. By default is nil.
|
||||
#
|
||||
# == Examples
|
||||
#
|
||||
# User.find(1).valid_password?('password123') # returns true/false
|
||||
#
|
||||
module Encryptable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
attr_reader :password, :current_password
|
||||
attr_accessor :password_confirmation
|
||||
end
|
||||
|
||||
# Generates password salt.
|
||||
def password=(new_password)
|
||||
self.password_salt = self.class.password_salt if new_password.present?
|
||||
super
|
||||
end
|
||||
|
||||
def authenticatable_salt
|
||||
self.password_salt
|
||||
end
|
||||
|
||||
# Verifies whether an incoming_password (ie from sign in) is the user password.
|
||||
def valid_password?(incoming_password)
|
||||
Devise.secure_compare(password_digest(incoming_password), self.encrypted_password)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Digests the password using the configured encryptor.
|
||||
def password_digest(password)
|
||||
if self.password_salt.present?
|
||||
self.class.encryptor_class.digest(password, self.class.stretches, self.password_salt, self.class.pepper)
|
||||
end
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
Devise::Models.config(self, :encryptor)
|
||||
|
||||
# Returns the class for the configured encryptor.
|
||||
def encryptor_class
|
||||
@encryptor_class ||= case encryptor
|
||||
when :bcrypt
|
||||
raise "In order to use bcrypt as encryptor, simply remove :encryptable from your devise model"
|
||||
when nil
|
||||
raise "You need to give an :encryptor as option in order to use :encryptable"
|
||||
else
|
||||
::Devise::Encryptors.const_get(encryptor.to_s.classify)
|
||||
end
|
||||
end
|
||||
|
||||
def password_salt
|
||||
self.encryptor_class.salt(self.stretches)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,5 +1,3 @@
|
||||
require "devise/hooks/lockable"
|
||||
|
||||
module Devise
|
||||
module Models
|
||||
# Handles blocking a user access after a certain number of attempts.
|
||||
@@ -24,15 +22,6 @@ module Devise
|
||||
|
||||
delegate :lock_strategy_enabled?, :unlock_strategy_enabled?, :to => "self.class"
|
||||
|
||||
def self.required_fields(klass)
|
||||
attributes = []
|
||||
attributes << :failed_attempts if klass.lock_strategy_enabled?(:failed_attempts)
|
||||
attributes << :unlock_at if klass.unlock_strategy_enabled?(:time)
|
||||
attributes << :unlock_token if klass.unlock_strategy_enabled?(:email)
|
||||
|
||||
attributes
|
||||
end
|
||||
|
||||
# Lock a user setting its locked_at to actual time.
|
||||
def lock_access!
|
||||
self.locked_at = Time.now.utc
|
||||
@@ -45,7 +34,7 @@ module Devise
|
||||
save(:validate => false)
|
||||
end
|
||||
|
||||
# Unlock a user by cleaning locked_at and failed_attempts.
|
||||
# Unlock a user by cleaning locket_at and failed_attempts.
|
||||
def unlock_access!
|
||||
self.locked_at = nil
|
||||
self.failed_attempts = 0 if respond_to?(:failed_attempts=)
|
||||
@@ -91,12 +80,15 @@ module Devise
|
||||
unlock_access! if lock_expired?
|
||||
|
||||
if super && !access_locked?
|
||||
self.failed_attempts = 0
|
||||
save(:validate => false)
|
||||
true
|
||||
else
|
||||
self.failed_attempts ||= 0
|
||||
self.failed_attempts += 1
|
||||
if attempts_exceeded?
|
||||
lock_access! unless access_locked?
|
||||
return :locked
|
||||
else
|
||||
save(:validate => false)
|
||||
end
|
||||
@@ -104,14 +96,6 @@ module Devise
|
||||
end
|
||||
end
|
||||
|
||||
def unauthenticated_message
|
||||
if lock_strategy_enabled?(:failed_attempts) && attempts_exceeded?
|
||||
:locked
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def attempts_exceeded?
|
||||
@@ -149,9 +133,9 @@ module Devise
|
||||
# with an email not found error.
|
||||
# Options must contain the user email
|
||||
def send_unlock_instructions(attributes={})
|
||||
lockable = find_or_initialize_with_errors(unlock_keys, attributes, :not_found)
|
||||
lockable.resend_unlock_token if lockable.persisted?
|
||||
lockable
|
||||
lockable = find_or_initialize_with_errors(unlock_keys, attributes, :not_found)
|
||||
lockable.resend_unlock_token if lockable.persisted?
|
||||
lockable
|
||||
end
|
||||
|
||||
# Find a user by its unlock token and try to unlock it.
|
||||
|
||||
@@ -15,10 +15,6 @@ module Devise
|
||||
module Omniauthable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def self.required_fields(klass)
|
||||
[]
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
Devise::Models.config(self, :omniauth_providers)
|
||||
end
|
||||
|
||||
@@ -24,10 +24,6 @@ module Devise
|
||||
module Recoverable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def self.required_fields(klass)
|
||||
[:reset_password_sent_at, :reset_password_token]
|
||||
end
|
||||
|
||||
# Update password saving the record and clearing token. Returns true if
|
||||
# the passwords are valid and the record was saved, false otherwise.
|
||||
def reset_password!(new_password, new_password_confirmation)
|
||||
|
||||
@@ -5,10 +5,6 @@ module Devise
|
||||
module Registerable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def self.required_fields(klass)
|
||||
[]
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
# A convenience method that receives both parameters and session to
|
||||
# initialize a user. This can be used by OAuth, for example, to send
|
||||
|
||||
@@ -24,7 +24,7 @@ module Devise
|
||||
# * +extend_remember_period+: if true, extends the user's remember period
|
||||
# when remembered via cookie. False by default.
|
||||
#
|
||||
# * +rememberable_options+: configuration options passed to the created cookie.
|
||||
# * +cookie_options+: configuration options passed to the created cookie.
|
||||
#
|
||||
# == Examples
|
||||
#
|
||||
@@ -41,10 +41,6 @@ module Devise
|
||||
|
||||
attr_accessor :remember_me, :extend_remember_period
|
||||
|
||||
def self.required_fields(klass)
|
||||
[:remember_created_at]
|
||||
end
|
||||
|
||||
# Generate a new remember token and save the record without validations
|
||||
# unless remember_across_browsers is true and the user already has a valid token.
|
||||
def remember_me!(extend_period=false)
|
||||
@@ -75,7 +71,7 @@ module Devise
|
||||
def rememberable_value
|
||||
if respond_to?(:remember_token)
|
||||
remember_token
|
||||
elsif respond_to?(:authenticatable_salt) && (salt = authenticatable_salt)
|
||||
elsif salt = authenticatable_salt
|
||||
salt
|
||||
else
|
||||
raise "authenticable_salt returned nil for the #{self.class.name} model. " \
|
||||
@@ -91,7 +87,7 @@ module Devise
|
||||
|
||||
protected
|
||||
|
||||
def generate_remember_token? #:nodoc:
|
||||
def generate_remember_token?
|
||||
respond_to?(:remember_token) && remember_expired?
|
||||
end
|
||||
|
||||
@@ -114,7 +110,7 @@ module Devise
|
||||
end
|
||||
|
||||
# Generate a token checking if one does not already exist in the database.
|
||||
def remember_token #:nodoc:
|
||||
def remember_token
|
||||
generate_token(:remember_token)
|
||||
end
|
||||
|
||||
|
||||
@@ -20,10 +20,6 @@ module Devise
|
||||
module Timeoutable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def self.required_fields(klass)
|
||||
[]
|
||||
end
|
||||
|
||||
# Checks whether the user session has expired based on configured time.
|
||||
def timedout?(last_access)
|
||||
return false if remember_exists_and_not_expired?
|
||||
|
||||
@@ -27,10 +27,6 @@ module Devise
|
||||
module TokenAuthenticatable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def self.required_fields(klass)
|
||||
[:authentication_token]
|
||||
end
|
||||
|
||||
# Generate new authentication token (a.k.a. "single access token").
|
||||
def reset_authentication_token
|
||||
self.authentication_token = self.class.authentication_token
|
||||
@@ -56,10 +52,6 @@ module Devise
|
||||
def after_token_authentication
|
||||
end
|
||||
|
||||
def expire_auth_token_on_timeout
|
||||
self.class.expire_auth_token_on_timeout
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
def find_for_token_authentication(conditions)
|
||||
find_for_authentication(:authentication_token => conditions[token_authentication_key])
|
||||
@@ -70,7 +62,7 @@ module Devise
|
||||
generate_token(:authentication_token)
|
||||
end
|
||||
|
||||
Devise::Models.config(self, :token_authentication_key, :expire_auth_token_on_timeout)
|
||||
::Devise::Models.config(self, :token_authentication_key)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -11,10 +11,6 @@ module Devise
|
||||
# * last_sign_in_ip - Holds the remote ip of the previous sign in
|
||||
#
|
||||
module Trackable
|
||||
def self.required_fields(klass)
|
||||
[:current_sign_in_at, :current_sign_in_ip, :last_sign_in_at, :last_sign_in_ip, :sign_in_count]
|
||||
end
|
||||
|
||||
def update_tracked_fields!(request)
|
||||
old_current, new_current = self.current_sign_in_at, Time.now.utc
|
||||
self.last_sign_in_at = old_current || new_current
|
||||
|
||||
@@ -17,10 +17,6 @@ module Devise
|
||||
VALIDATIONS = [ :validates_presence_of, :validates_uniqueness_of, :validates_format_of,
|
||||
:validates_confirmation_of, :validates_length_of ].freeze
|
||||
|
||||
def self.required_fields(klass)
|
||||
[]
|
||||
end
|
||||
|
||||
def self.included(base)
|
||||
base.extend ClassMethods
|
||||
assert_validations_api!(base)
|
||||
|
||||
@@ -10,6 +10,7 @@ Devise.with_options :model => true do |d|
|
||||
end
|
||||
|
||||
# Other authentications
|
||||
d.add_module :encryptable
|
||||
d.add_module :omniauthable, :controller => :omniauth_callbacks, :route => :omniauth_callback
|
||||
|
||||
# Misc after
|
||||
|
||||
@@ -1,3 +1,44 @@
|
||||
require 'orm_adapter/adapters/active_record'
|
||||
|
||||
ActiveRecord::Base.extend Devise::Models
|
||||
module Devise
|
||||
module Orm
|
||||
# This module contains some helpers and handle schema (migrations):
|
||||
#
|
||||
# create_table :accounts do |t|
|
||||
# t.database_authenticatable
|
||||
# t.confirmable
|
||||
# t.recoverable
|
||||
# t.rememberable
|
||||
# t.trackable
|
||||
# t.lockable
|
||||
# t.timestamps
|
||||
# end
|
||||
#
|
||||
# However this method does not add indexes. If you need them, here is the declaration:
|
||||
#
|
||||
# add_index "accounts", ["email"], :name => "email", :unique => true
|
||||
# add_index "accounts", ["confirmation_token"], :name => "confirmation_token", :unique => true
|
||||
# add_index "accounts", ["reset_password_token"], :name => "reset_password_token", :unique => true
|
||||
#
|
||||
module ActiveRecord
|
||||
module Schema
|
||||
include Devise::Schema
|
||||
|
||||
# Tell how to apply schema methods.
|
||||
def apply_devise_schema(name, type, options={})
|
||||
@__devise_warning_raised ||= begin
|
||||
$stderr.puts "\n[DEVISE] You are using t.database_authenticatable and others in your migration " \
|
||||
"and this feature is deprecated. Please simply use Rails helpers instead as mentioned here:\n" \
|
||||
"https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.0-migration-schema-style\n\n"
|
||||
true
|
||||
end
|
||||
column name, type.to_s.downcase.to_sym, options
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ActiveRecord::Base.extend Devise::Models
|
||||
ActiveRecord::ConnectionAdapters::Table.send :include, Devise::Orm::ActiveRecord::Schema
|
||||
ActiveRecord::ConnectionAdapters::TableDefinition.send :include, Devise::Orm::ActiveRecord::Schema
|
||||
@@ -1,3 +1,31 @@
|
||||
require 'orm_adapter/adapters/mongoid'
|
||||
|
||||
Mongoid::Document::ClassMethods.send :include, Devise::Models
|
||||
module Devise
|
||||
module Orm
|
||||
module Mongoid
|
||||
module Hook
|
||||
def devise_modules_hook!
|
||||
extend Schema
|
||||
yield
|
||||
return unless Devise.apply_schema
|
||||
devise_modules.each { |m| send(m) if respond_to?(m, true) }
|
||||
end
|
||||
end
|
||||
|
||||
module Schema
|
||||
include Devise::Schema
|
||||
|
||||
# Tell how to apply schema methods
|
||||
def apply_devise_schema(name, type, options={})
|
||||
type = Time if type == DateTime
|
||||
field name, { :type => type }.merge!(options)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Mongoid::Document::ClassMethods.class_eval do
|
||||
include Devise::Models
|
||||
include Devise::Orm::Mongoid::Hook
|
||||
end
|
||||
|
||||
@@ -33,9 +33,8 @@ module Devise
|
||||
|
||||
private
|
||||
|
||||
# Determine which values should be transformed to string or passed as-is to the query builder underneath
|
||||
def param_requires_string_conversion?(value)
|
||||
[Fixnum, TrueClass, FalseClass, Regexp].none? {|clz| value.is_a? clz }
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -43,12 +43,69 @@ module Devise
|
||||
end
|
||||
|
||||
initializer "devise.fix_routes_proxy_missing_respond_to_bug" do
|
||||
# We can get rid of this once we support only Rails > 3.2
|
||||
# We can get rid of this once we support Rails > 3.2
|
||||
ActionDispatch::Routing::RoutesProxy.class_eval do
|
||||
def respond_to?(method, include_private = false)
|
||||
super || routes.url_helpers.respond_to?(method)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
initializer "devise.deprecations" do
|
||||
unless defined?(Rails::Generators)
|
||||
if Devise.case_insensitive_keys == false
|
||||
warn "\n[DEVISE] Devise.case_insensitive_keys is false which is no longer " \
|
||||
"supported. Recent Devise versions automatically downcase the e-mail before " \
|
||||
"saving it to the database but your app isn't using this feature. You can solve " \
|
||||
"this issue by either:\n\n" \
|
||||
"1) Setting config.case_insensitive_keys = [:email] in your Devise initializer and " \
|
||||
"running a migration that will downcase all emails already in the database;\n\n" \
|
||||
"2) Setting config.case_insensitive_keys = [] (so nothing will be downcased) and " \
|
||||
"making sure you are not using Devise :validatable (since validatable assumes case" \
|
||||
"insensitivity)\n"
|
||||
end
|
||||
|
||||
if Devise.apply_schema && defined?(Mongoid)
|
||||
warn "\n[DEVISE] Devise.apply_schema is true. This means Devise was " \
|
||||
"automatically configuring your DB. This no longer happens. You should " \
|
||||
"set Devise.apply_schema to false and manually set the fields used by Devise as shown here: " \
|
||||
"https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.0-migration-schema-style\n"
|
||||
end
|
||||
|
||||
# TODO: Deprecate the true value of this option as well
|
||||
if Devise.use_salt_as_remember_token == false
|
||||
warn "\n[DEVISE] Devise.use_salt_as_remember_token is false which is no longer " \
|
||||
"supported. Devise now only uses the salt as remember token and the remember_token " \
|
||||
"column can be removed from your models.\n"
|
||||
end
|
||||
|
||||
if Devise.reset_password_within.nil?
|
||||
warn "\n[DEVISE] Devise.reset_password_within is nil. Please set this value to " \
|
||||
"an interval (for example, 6.hours) and add a reset_password_sent_at field to " \
|
||||
"your Devise models (if they don't have one already).\n"
|
||||
end
|
||||
end
|
||||
|
||||
config.after_initialize do
|
||||
example = <<-YAML
|
||||
en:
|
||||
devise:
|
||||
registrations:
|
||||
signed_up_but_unconfirmed: 'A message with a confirmation link has been sent to your email address. Please open the link to activate your account.'
|
||||
signed_up_but_inactive: 'You have signed up successfully. However, we could not sign you in because your account is not yet activated.'
|
||||
signed_up_but_locked: 'You have signed up successfully. However, we could not sign you in because your account is locked.'
|
||||
YAML
|
||||
|
||||
if I18n.t(:"devise.registrations.reasons", :default => {}).present?
|
||||
warn "\n[DEVISE] devise.registrations.reasons in yml files is deprecated, " \
|
||||
"please use devise.registrations.signed_up_but_REASON instead. The default values are:\n\n#{example}\n"
|
||||
end
|
||||
|
||||
if I18n.t(:"devise.registrations.inactive_signed_up", :default => "").present?
|
||||
warn "\n[DEVISE] devise.registrations.inactive_signed_up in yml files is deprecated, " \
|
||||
"please use devise.registrations.signed_up_but_REASON instead. The default values are:\n\n#{example}\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -136,7 +136,7 @@ module ActionDispatch::Routing
|
||||
#
|
||||
# devise_for :users, :format => false
|
||||
#
|
||||
# * :constraints => works the same as Rails' constraints
|
||||
# * :constraints => works the same as Rails' contraints
|
||||
#
|
||||
# * :defaults => works the same as Rails' defaults
|
||||
#
|
||||
@@ -184,7 +184,7 @@ module ActionDispatch::Routing
|
||||
#
|
||||
# In order to get Devise to recognize the deactivate action, your devise_for entry should look like this,
|
||||
#
|
||||
# devise_scope :owner do
|
||||
# devise_for :owners, :controllers => { :registrations => "registrations" } do
|
||||
# post "deactivate", :to => "registrations#deactivate", :as => "deactivate_registration"
|
||||
# end
|
||||
#
|
||||
@@ -198,8 +198,7 @@ module ActionDispatch::Routing
|
||||
options[:path_names] = (@scope[:path_names] || {}).merge(options[:path_names] || {})
|
||||
options[:constraints] = (@scope[:constraints] || {}).merge(options[:constraints] || {})
|
||||
options[:defaults] = (@scope[:defaults] || {}).merge(options[:defaults] || {})
|
||||
options[:options] = @scope[:options] || {}
|
||||
options[:options][:format] = false if options[:format] == false
|
||||
options[:options] = (@scope[:options] || {}).merge({:format => false}) if options[:format] == false
|
||||
|
||||
resources.map!(&:to_sym)
|
||||
|
||||
|
||||
@@ -21,23 +21,17 @@ class Warden::SessionSerializer
|
||||
end
|
||||
|
||||
def deserialize(keys)
|
||||
klass_name, *args = keys
|
||||
klass, *args = keys
|
||||
|
||||
begin
|
||||
klass = ActiveSupport::Inflector.constantize(klass_name)
|
||||
if klass.respond_to? :serialize_from_session
|
||||
klass.serialize_from_session(*args)
|
||||
else
|
||||
Rails.logger.warn "[Devise] Stored serialized class #{klass_name} seems not to be Devise enabled anymore. Did you do that on purpose?"
|
||||
nil
|
||||
end
|
||||
ActiveSupport::Inflector.constantize(klass).serialize_from_session(*args)
|
||||
rescue NameError => e
|
||||
if e.message =~ /uninitialized constant/
|
||||
Rails.logger.debug "[Devise] Trying to deserialize invalid class #{klass_name}"
|
||||
Rails.logger.debug "[Devise] Trying to deserialize invalid class #{klass}"
|
||||
nil
|
||||
else
|
||||
raise
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
109
lib/devise/schema.rb
Normal file
109
lib/devise/schema.rb
Normal file
@@ -0,0 +1,109 @@
|
||||
module Devise
|
||||
# Holds devise schema information. To use it, just include its methods
|
||||
# and overwrite the apply_schema method.
|
||||
module Schema
|
||||
|
||||
# Creates encrypted_password, and email when it is used as an authentication
|
||||
# key (default).
|
||||
#
|
||||
# == Options
|
||||
# * :null - When true, allow columns to be null.
|
||||
# * :default - Set to "" when :null is false, unless overridden.
|
||||
#
|
||||
# == Notes
|
||||
# For Datamapper compatibility, we explicitly hardcode the limit for the
|
||||
# encrypter password field in 128 characters.
|
||||
def database_authenticatable(options={})
|
||||
null = options[:null] || false
|
||||
default = options.key?(:default) ? options[:default] : ("" if null == false)
|
||||
include_email = !respond_to?(:authentication_keys) || self.authentication_keys.include?(:email)
|
||||
|
||||
apply_devise_schema :email, String, :null => null, :default => default if include_email
|
||||
apply_devise_schema :encrypted_password, String, :null => null, :default => default, :limit => 128
|
||||
end
|
||||
|
||||
# Creates password salt for encryption support when using encryptors other
|
||||
# than the database_authenticable default of bcrypt.
|
||||
def encryptable
|
||||
apply_devise_schema :password_salt, String
|
||||
end
|
||||
|
||||
# Creates authentication_token.
|
||||
def token_authenticatable
|
||||
apply_devise_schema :authentication_token, String
|
||||
end
|
||||
|
||||
# Creates confirmation_token, confirmed_at and confirmation_sent_at.
|
||||
def confirmable
|
||||
apply_devise_schema :confirmation_token, String
|
||||
apply_devise_schema :confirmed_at, DateTime
|
||||
apply_devise_schema :confirmation_sent_at, DateTime
|
||||
end
|
||||
|
||||
# Creates unconfirmed_email
|
||||
def reconfirmable
|
||||
apply_devise_schema :unconfirmed_email, String
|
||||
end
|
||||
|
||||
# Creates reset_password_token and reset_password_sent_at.
|
||||
#
|
||||
# == Options
|
||||
# * :reset_within - When true, adds a column that reset passwords within some date
|
||||
def recoverable(options={})
|
||||
use_within = options.fetch(:reset_within, Devise.reset_password_within.present?)
|
||||
apply_devise_schema :reset_password_token, String
|
||||
apply_devise_schema :reset_password_sent_at, DateTime if use_within
|
||||
end
|
||||
|
||||
# Creates remember_token and remember_created_at.
|
||||
#
|
||||
# == Options
|
||||
# * :use_salt - When true, does not create a remember_token and use password_salt instead.
|
||||
def rememberable(options={})
|
||||
use_salt = options.fetch(:use_salt, Devise.use_salt_as_remember_token)
|
||||
apply_devise_schema :remember_token, String unless use_salt
|
||||
apply_devise_schema :remember_created_at, DateTime
|
||||
end
|
||||
|
||||
# Creates sign_in_count, current_sign_in_at, last_sign_in_at,
|
||||
# current_sign_in_ip, last_sign_in_ip.
|
||||
def trackable
|
||||
apply_devise_schema :sign_in_count, Integer, :default => 0
|
||||
apply_devise_schema :current_sign_in_at, DateTime
|
||||
apply_devise_schema :last_sign_in_at, DateTime
|
||||
apply_devise_schema :current_sign_in_ip, String
|
||||
apply_devise_schema :last_sign_in_ip, String
|
||||
end
|
||||
|
||||
# Creates failed_attempts, unlock_token and locked_at depending on the options given.
|
||||
#
|
||||
# == Options
|
||||
# * :unlock_strategy - The strategy used for unlock. Can be :time, :email, :both (default), :none.
|
||||
# If :email or :both, creates a unlock_token field.
|
||||
# * :lock_strategy - The strategy used for locking. Can be :failed_attempts (default) or :none.
|
||||
def lockable(options={})
|
||||
unlock_strategy = options[:unlock_strategy]
|
||||
unlock_strategy ||= self.unlock_strategy if respond_to?(:unlock_strategy)
|
||||
unlock_strategy ||= :both
|
||||
|
||||
lock_strategy = options[:lock_strategy]
|
||||
lock_strategy ||= self.lock_strategy if respond_to?(:lock_strategy)
|
||||
lock_strategy ||= :failed_attempts
|
||||
|
||||
if lock_strategy == :failed_attempts
|
||||
apply_devise_schema :failed_attempts, Integer, :default => 0
|
||||
end
|
||||
|
||||
if [:both, :email].include?(unlock_strategy)
|
||||
apply_devise_schema :unlock_token, String
|
||||
end
|
||||
|
||||
apply_devise_schema :locked_at, DateTime
|
||||
end
|
||||
|
||||
# Overwrite with specific modification to create your own schema.
|
||||
def apply_devise_schema(name, type, options={})
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -23,20 +23,14 @@ module Devise
|
||||
result = resource && resource.valid_for_authentication?(&block)
|
||||
|
||||
case result
|
||||
when Symbol, String
|
||||
ActiveSupport::Deprecation.warn "valid_for_authentication should return a boolean value"
|
||||
when String, Symbol
|
||||
fail!(result)
|
||||
return false
|
||||
end
|
||||
|
||||
if result
|
||||
false
|
||||
when TrueClass
|
||||
decorate(resource)
|
||||
true
|
||||
else
|
||||
if resource
|
||||
fail!(resource.unauthenticated_message)
|
||||
end
|
||||
false
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'devise/strategies/authenticatable'
|
||||
require 'devise/strategies/base'
|
||||
|
||||
module Devise
|
||||
module Strategies
|
||||
|
||||
@@ -70,61 +70,22 @@ module Devise
|
||||
def _catch_warden(&block)
|
||||
result = catch(:warden, &block)
|
||||
|
||||
env = @controller.request.env
|
||||
if result.is_a?(Hash) && !warden.custom_failure? && !@controller.send(:performed?)
|
||||
result[:action] ||= :unauthenticated
|
||||
|
||||
result ||= {}
|
||||
|
||||
# Set the response. In production, the rack result is returned
|
||||
# from Warden::Manager#call, which the following is modelled on.
|
||||
case result
|
||||
when Array
|
||||
if result.first == 401 && intercept_401?(env) # does this happen during testing?
|
||||
_process_unauthenticated(env)
|
||||
else
|
||||
result
|
||||
end
|
||||
when Hash
|
||||
_process_unauthenticated(env, result)
|
||||
else
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
def _process_unauthenticated(env, options = {})
|
||||
options[:action] ||= :unauthenticated
|
||||
proxy = env['warden']
|
||||
result = options[:result] || proxy.result
|
||||
|
||||
ret = case result
|
||||
when :redirect
|
||||
body = proxy.message || "You are being redirected to #{proxy.headers['Location']}"
|
||||
[proxy.status, proxy.headers, [body]]
|
||||
when :custom
|
||||
proxy.custom_response
|
||||
else
|
||||
env["PATH_INFO"] = "/#{options[:action]}"
|
||||
env["warden.options"] = options
|
||||
Warden::Manager._run_callbacks(:before_failure, env, options)
|
||||
env = @controller.request.env
|
||||
env["PATH_INFO"] = "/#{result[:action]}"
|
||||
env["warden.options"] = result
|
||||
Warden::Manager._run_callbacks(:before_failure, env, result)
|
||||
|
||||
status, headers, body = Devise.warden_config[:failure_app].call(env).to_a
|
||||
@controller.send :render, :status => status, :text => body,
|
||||
:content_type => headers["Content-Type"], :location => headers["Location"]
|
||||
nil # causes process return @response
|
||||
end
|
||||
|
||||
# ensure that the controller response is set up. In production, this is
|
||||
# not necessary since warden returns the results to rack. However, at
|
||||
# testing time, we want the response to be available to the testing
|
||||
# framework to verify what would be returned to rack.
|
||||
if ret.is_a?(Array)
|
||||
# ensure the controller response is set to our response.
|
||||
@controller.response ||= @response
|
||||
@response.status = ret.first
|
||||
@response.headers = ret.second
|
||||
@response.body = ret.third
|
||||
nil
|
||||
else
|
||||
result
|
||||
end
|
||||
|
||||
ret
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
module Devise
|
||||
VERSION = "2.1.0".freeze
|
||||
VERSION = "2.0.6".freeze
|
||||
end
|
||||
|
||||
@@ -22,17 +22,10 @@ module ActiveRecord
|
||||
end
|
||||
|
||||
def inject_devise_content
|
||||
content = model_contents + <<CONTENT
|
||||
inject_into_class(model_path, class_name, model_contents + <<CONTENT) if model_exists?
|
||||
# Setup accessible (or protected) attributes for your model
|
||||
attr_accessible :email, :password, :password_confirmation, :remember_me
|
||||
CONTENT
|
||||
|
||||
class_path = class_name.to_s.split("::")
|
||||
|
||||
indent_depth = class_path.size - 1
|
||||
content = content.split("\n").map { |line| " " * indent_depth + line } .join("\n") << "\n"
|
||||
|
||||
inject_into_class(model_path, class_path.last, content) if model_exists?
|
||||
end
|
||||
|
||||
def migration_data
|
||||
@@ -55,6 +48,9 @@ CONTENT
|
||||
t.string :current_sign_in_ip
|
||||
t.string :last_sign_in_ip
|
||||
|
||||
## Encryptable
|
||||
# t.string :password_salt
|
||||
|
||||
## Confirmable
|
||||
# t.string :confirmation_token
|
||||
# t.datetime :confirmed_at
|
||||
|
||||
@@ -4,8 +4,7 @@ module Devise
|
||||
def model_contents
|
||||
<<-CONTENT
|
||||
# Include default devise modules. Others available are:
|
||||
# :token_authenticatable, :confirmable,
|
||||
# :lockable, :timeoutable and :omniauthable
|
||||
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
|
||||
devise :database_authenticatable, :registerable,
|
||||
:recoverable, :rememberable, :trackable, :validatable
|
||||
|
||||
|
||||
@@ -39,18 +39,6 @@ module Devise
|
||||
end
|
||||
end
|
||||
|
||||
class SharedViewsGenerator < Rails::Generators::Base #:nodoc:
|
||||
include ViewPathTemplates
|
||||
source_root File.expand_path("../../../../app/views/devise", __FILE__)
|
||||
desc "Copies shared Devise views to your application."
|
||||
hide!
|
||||
|
||||
# Override copy_views to just copy mailer and shared.
|
||||
def copy_views
|
||||
view_directory :shared
|
||||
end
|
||||
end
|
||||
|
||||
class FormForGenerator < Rails::Generators::Base #:nodoc:
|
||||
include ViewPathTemplates
|
||||
source_root File.expand_path("../../../../app/views/devise", __FILE__)
|
||||
@@ -92,12 +80,15 @@ module Devise
|
||||
end
|
||||
|
||||
class ViewsGenerator < Rails::Generators::Base
|
||||
include ViewPathTemplates
|
||||
|
||||
source_root File.expand_path("../../../../app/views/devise", __FILE__)
|
||||
desc "Copies Devise views to your application."
|
||||
|
||||
argument :scope, :required => false, :default => nil,
|
||||
:desc => "The scope to copy views to"
|
||||
def copy_views
|
||||
copy_file "_links.erb", "#{target_path}/_links.erb"
|
||||
end
|
||||
|
||||
invoke SharedViewsGenerator
|
||||
hook_for :form_builder, :aliases => "-b",
|
||||
:desc => "Form builder to be used",
|
||||
:default => defined?(SimpleForm) ? "simple_form_for" : "form_for"
|
||||
|
||||
@@ -37,6 +37,9 @@ module Mongoid
|
||||
field :current_sign_in_ip, :type => String
|
||||
field :last_sign_in_ip, :type => String
|
||||
|
||||
## Encryptable
|
||||
# field :password_salt, :type => String
|
||||
|
||||
## Confirmable
|
||||
# field :confirmation_token, :type => String
|
||||
# field :confirmed_at, :type => Time
|
||||
|
||||
@@ -9,6 +9,9 @@ Devise.setup do |config|
|
||||
# Configure the class responsible to send e-mails.
|
||||
# config.mailer = "Devise::Mailer"
|
||||
|
||||
# Automatically apply schema changes in tableless databases
|
||||
config.apply_schema = false
|
||||
|
||||
# ==> ORM configuration
|
||||
# Load and configure the ORM. Supports :active_record (default) and
|
||||
# :mongoid (bson_ext recommended) by default. Other ORMs may be
|
||||
@@ -92,7 +95,7 @@ Devise.setup do |config|
|
||||
# the user cannot access the website without confirming his account.
|
||||
# config.allow_unconfirmed_access_for = 2.days
|
||||
|
||||
# If true, requires any email changes to be confirmed (exactly the same way as
|
||||
# If true, requires any email changes to be confirmed (exctly the same way as
|
||||
# initial account confirmation) to be applied. Requires additional unconfirmed_email
|
||||
# db field (see migrations). Until confirmed new email is stored in
|
||||
# unconfirmed email column, and copied to email column on successful confirmation.
|
||||
@@ -108,9 +111,13 @@ Devise.setup do |config|
|
||||
# If true, extends the user's remember period when remembered via cookie.
|
||||
# config.extend_remember_period = false
|
||||
|
||||
# If true, uses the password salt as remember token. This should be turned
|
||||
# to false if you are not using database authenticatable.
|
||||
config.use_salt_as_remember_token = true
|
||||
|
||||
# Options to be passed to the created cookie. For instance, you can set
|
||||
# :secure => true in order to force SSL only cookies.
|
||||
# config.rememberable_options = {}
|
||||
# config.cookie_options = {}
|
||||
|
||||
# ==> Configuration for :validatable
|
||||
# Range for password length. Default is 6..128.
|
||||
|
||||
@@ -12,4 +12,4 @@
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
<%= render "links" %>
|
||||
@@ -16,4 +16,4 @@
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
<%= render "links" %>
|
||||
@@ -12,4 +12,4 @@
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
<%= render "links" %>
|
||||
@@ -14,4 +14,4 @@
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
<%= render "links" %>
|
||||
|
||||
@@ -12,4 +12,4 @@
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
<%= render "links" %>
|
||||
@@ -12,4 +12,4 @@
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
<%= render "links" %>
|
||||
@@ -1,62 +0,0 @@
|
||||
require 'test_helper'
|
||||
require 'ostruct'
|
||||
require 'warden/strategies/base'
|
||||
require 'devise/test_helpers'
|
||||
|
||||
class CustomStrategyController < ActionController::Base
|
||||
def new
|
||||
warden.authenticate!(:custom_strategy)
|
||||
end
|
||||
end
|
||||
|
||||
# These tests are to prove that a warden strategy can successfully
|
||||
# return a custom response, including a specific status code and
|
||||
# custom http response headers. This does work in production,
|
||||
# however, at the time of writing this, the Devise test helpers do
|
||||
# not recognise the custom response and proceed to calling the
|
||||
# Failure App. This makes it impossible to write tests for a
|
||||
# strategy that return a custom response with Devise.
|
||||
class CustomStrategy < Warden::Strategies::Base
|
||||
def authenticate!
|
||||
custom_headers = { "X-FOO" => "BAR" }
|
||||
response = Rack::Response.new("BAD REQUEST", 400, custom_headers)
|
||||
custom! response.finish
|
||||
end
|
||||
end
|
||||
|
||||
class CustomStrategyTest < ActionController::TestCase
|
||||
tests CustomStrategyController
|
||||
|
||||
include Devise::TestHelpers
|
||||
|
||||
setup do
|
||||
Warden::Strategies.add(:custom_strategy, CustomStrategy)
|
||||
end
|
||||
|
||||
teardown do
|
||||
Warden::Strategies._strategies.delete(:custom_strategy)
|
||||
end
|
||||
|
||||
test "custom strategy can return its own status code" do
|
||||
ret = get :new
|
||||
|
||||
# check the returned rack array
|
||||
assert ret.is_a?(Array)
|
||||
assert_equal 400, ret.first
|
||||
|
||||
# check the saved response as well. This is purely so that the response is available to the testing framework
|
||||
# for verification. In production, the above array would be delivered directly to Rack.
|
||||
assert_response 400
|
||||
end
|
||||
|
||||
test "custom strategy can return custom headers" do
|
||||
ret = get :new
|
||||
|
||||
# check the returned rack array
|
||||
assert ret.is_a?(Array)
|
||||
assert_equal ret.third['X-FOO'], 'BAR'
|
||||
|
||||
# check the saved response headers as well.
|
||||
assert_equal response.headers['X-FOO'], 'BAR'
|
||||
end
|
||||
end
|
||||
@@ -33,13 +33,6 @@ class HelpersTest < ActionController::TestCase
|
||||
assert_equal user, @controller.instance_variable_get(:@user)
|
||||
end
|
||||
|
||||
test 'get resource params from request params using resource name as key' do
|
||||
user_params = {'name' => 'Shirley Templar'}
|
||||
@controller.stubs(:params).returns(HashWithIndifferentAccess.new({'user' => user_params}))
|
||||
|
||||
assert_equal user_params, @controller.resource_params
|
||||
end
|
||||
|
||||
test 'resources methods are not controller actions' do
|
||||
assert @controller.class.action_methods.empty?
|
||||
end
|
||||
|
||||
@@ -13,24 +13,4 @@ class SessionsControllerTest < ActionController::TestCase
|
||||
assert_equal 200, @response.status
|
||||
assert_template "devise/sessions/new"
|
||||
end
|
||||
|
||||
if defined?(ActiveRecord)
|
||||
if ActiveRecord::Base.respond_to?(:mass_assignment_sanitizer)
|
||||
test "#new doesn't raise mass-assignment exception even if sign-in key is attr_protected" do
|
||||
request.env["devise.mapping"] = Devise.mappings[:user]
|
||||
|
||||
ActiveRecord::Base.mass_assignment_sanitizer = :strict
|
||||
User.class_eval { attr_protected :email }
|
||||
|
||||
begin
|
||||
assert_nothing_raised ActiveModel::MassAssignmentSecurity::Error do
|
||||
get :new, :user => { :email => "allez viens!" }
|
||||
end
|
||||
ensure
|
||||
ActiveRecord::Base.mass_assignment_sanitizer = :logger
|
||||
User.class_eval { attr_accessible :email }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
30
test/encryptors_test.rb
Normal file
30
test/encryptors_test.rb
Normal file
@@ -0,0 +1,30 @@
|
||||
require 'test_helper'
|
||||
|
||||
class Encryptors < ActiveSupport::TestCase
|
||||
test 'should match a password created by authlogic' do
|
||||
authlogic = "b623c3bc9c775b0eb8edb218a382453396fec4146422853e66ecc4b6bc32d7162ee42074dcb5f180a770dc38b5df15812f09bbf497a4a1b95fe5e7d2b8eb7eb4"
|
||||
encryptor = Devise::Encryptors::AuthlogicSha512.digest('123mudar', 20, 'usZK_z_EAaF61Gwkw-ed', '')
|
||||
assert_equal authlogic, encryptor
|
||||
end
|
||||
|
||||
test 'should match a password created by restful_authentication' do
|
||||
restful_authentication = "93110f71309ce91366375ea44e2a6f5cc73fa8d4"
|
||||
encryptor = Devise::Encryptors::RestfulAuthenticationSha1.digest('123mudar', 10, '48901d2b247a54088acb7f8ea3e695e50fe6791b', 'fee9a51ec0a28d11be380ca6dee6b4b760c1a3bf')
|
||||
assert_equal restful_authentication, encryptor
|
||||
end
|
||||
|
||||
test 'should match a password created by clearance' do
|
||||
clearance = "0f40bbae18ddefd7066276c3ef209d40729b0378"
|
||||
encryptor = Devise::Encryptors::ClearanceSha1.digest('123mudar', nil, '65c58472c207c829f28c68619d3e3aefed18ab3f', nil)
|
||||
assert_equal clearance, encryptor
|
||||
end
|
||||
|
||||
Devise::ENCRYPTORS_LENGTH.each do |key, value|
|
||||
test "should have length #{value} for #{key.inspect}" do
|
||||
swap Devise, :encryptor => key do
|
||||
encryptor = Devise::Encryptors.const_get(key.to_s.classify)
|
||||
assert_equal value, encryptor.digest('a', 4, encryptor.salt(4), nil).size
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -29,20 +29,20 @@ class FailureTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
context 'When redirecting' do
|
||||
test 'returns to the default redirect location' do
|
||||
test 'return to the default redirect location' do
|
||||
call_failure
|
||||
assert_equal 302, @response.first
|
||||
assert_equal 'You need to sign in or sign up before continuing.', @request.flash[:alert]
|
||||
assert_equal 'http://test.host/users/sign_in', @response.second['Location']
|
||||
end
|
||||
|
||||
test 'returns to the default redirect location for wildcard requests' do
|
||||
test 'return to the default redirect location for wildcard requests' do
|
||||
call_failure 'action_dispatch.request.formats' => nil, 'HTTP_ACCEPT' => '*/*'
|
||||
assert_equal 302, @response.first
|
||||
assert_equal 'http://test.host/users/sign_in', @response.second['Location']
|
||||
end
|
||||
|
||||
test 'returns to the root path if no session path is available' do
|
||||
test 'return to the root path if no session path is available' do
|
||||
swap Devise, :router_name => :fake_app do
|
||||
call_failure :app => RootFailureApp
|
||||
assert_equal 302, @response.first
|
||||
@@ -51,16 +51,6 @@ class FailureTest < ActiveSupport::TestCase
|
||||
end
|
||||
end
|
||||
|
||||
if Rails.application.config.respond_to?(:relative_url_root)
|
||||
test 'returns to the default redirect location considering the relative url root' do
|
||||
swap Rails.application.config, :relative_url_root => "/sample" do
|
||||
call_failure
|
||||
assert_equal 302, @response.first
|
||||
assert_equal 'http://test.host/sample/users/sign_in', @response.second['Location']
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test 'uses the proxy failure message as symbol' do
|
||||
call_failure('warden' => OpenStruct.new(:message => :invalid))
|
||||
assert_equal 'Invalid email or password.', @request.flash[:alert]
|
||||
|
||||
@@ -34,36 +34,4 @@ if DEVISE_ORM == :active_record
|
||||
assert_no_migration "db/migrate/devise_create_monsters.rb"
|
||||
end
|
||||
end
|
||||
|
||||
module RailsEngine
|
||||
class Engine < Rails::Engine
|
||||
isolate_namespace RailsEngine
|
||||
end
|
||||
end
|
||||
|
||||
def simulate_inside_engine(engine, namespace)
|
||||
if Rails::Generators.respond_to?(:namespace=)
|
||||
swap Rails::Generators, :namespace => namespace do
|
||||
yield
|
||||
end
|
||||
else
|
||||
swap Rails, :application => engine.instance do
|
||||
yield
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class ActiveRecordEngineGeneratorTest < Rails::Generators::TestCase
|
||||
tests ActiveRecord::Generators::DeviseGenerator
|
||||
destination File.expand_path("../../tmp", __FILE__)
|
||||
setup :prepare_destination
|
||||
|
||||
test "all files are properly created" do
|
||||
simulate_inside_engine(RailsEngine::Engine, RailsEngine) do
|
||||
run_generator ["monster"]
|
||||
|
||||
assert_file "app/models/rails_engine/monster.rb", /devise/,/attr_accessible (:[a-z_]+(, )?)+/
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -46,7 +46,7 @@ class ViewsGeneratorTest < Rails::Generators::TestCase
|
||||
assert_file "app/views/#{scope}/registrations/new.html.erb"
|
||||
assert_file "app/views/#{scope}/registrations/edit.html.erb"
|
||||
assert_file "app/views/#{scope}/sessions/new.html.erb"
|
||||
assert_file "app/views/#{scope}/shared/_links.erb"
|
||||
assert_file "app/views/#{scope}/unlocks/new.html.erb"
|
||||
assert_file "app/views/#{scope}/_links.erb"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -461,14 +461,14 @@ class AuthenticationOthersTest < ActionController::IntegrationTest
|
||||
test 'sign out with xml format returns ok response' do
|
||||
sign_in_as_user
|
||||
get destroy_user_session_path(:format => 'xml')
|
||||
assert_response :no_content
|
||||
assert_response :ok
|
||||
assert_not warden.authenticated?(:user)
|
||||
end
|
||||
|
||||
test 'sign out with json format returns empty json response' do
|
||||
sign_in_as_user
|
||||
get destroy_user_session_path(:format => 'json')
|
||||
assert_response :no_content
|
||||
assert_response :ok
|
||||
assert_not warden.authenticated?(:user)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -180,7 +180,7 @@ class ConfirmationTest < ActionController::IntegrationTest
|
||||
fill_in 'email', :with => user.email
|
||||
click_button 'Resend confirmation instructions'
|
||||
|
||||
assert_contain "If your email address exists in our database, you will receive an email with instructions about how to confirm your account in a few minutes."
|
||||
assert_contain "If your e-mail exists on our database, you will receive an email with instructions about how to confirm your account in a few minutes."
|
||||
assert_current_url "/users/sign_in"
|
||||
end
|
||||
end
|
||||
@@ -196,7 +196,7 @@ class ConfirmationTest < ActionController::IntegrationTest
|
||||
assert_not_contain "1 error prohibited this user from being saved:"
|
||||
assert_not_contain "Email not found"
|
||||
|
||||
assert_contain "If your email address exists in our database, you will receive an email with instructions about how to confirm your account in a few minutes."
|
||||
assert_contain "If your e-mail exists on our database, you will receive an email with instructions about how to confirm your account in a few minutes."
|
||||
assert_current_url "/users/sign_in"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -118,7 +118,7 @@ class OmniauthableIntegrationTest < ActionController::IntegrationTest
|
||||
OmniAuth.config.mock_auth[:facebook] = :access_denied
|
||||
visit "/users/auth/facebook/callback?error=access_denied"
|
||||
assert_current_url "/users/sign_in"
|
||||
assert_contain 'Could not authenticate you from Facebook because "Access denied".'
|
||||
assert_contain 'Could not authorize you from Facebook because "Access denied".'
|
||||
end
|
||||
|
||||
test "handles other exceptions from omniauth" do
|
||||
@@ -128,6 +128,6 @@ class OmniauthableIntegrationTest < ActionController::IntegrationTest
|
||||
click_link "Sign in with Facebook"
|
||||
|
||||
assert_current_url "/users/sign_in"
|
||||
assert_contain 'Could not authenticate you from Facebook because "Invalid credentials".'
|
||||
assert_contain 'Could not authorize you from Facebook because "Invalid credentials".'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -195,15 +195,6 @@ class PasswordTest < ActionController::IntegrationTest
|
||||
assert !warden.authenticated?(:user)
|
||||
end
|
||||
|
||||
test 'sign in user automatically and confirm after changing its password if it\'s not confirmed' do
|
||||
user = create_user(:confirm => false)
|
||||
request_forgot_password
|
||||
reset_password :reset_password_token => user.reload.reset_password_token
|
||||
|
||||
assert warden.authenticated?(:user)
|
||||
assert user.reload.confirmed?
|
||||
end
|
||||
|
||||
test 'reset password request with valid E-Mail in XML format should return valid response' do
|
||||
create_user
|
||||
post user_password_path(:format => 'xml'), :user => {:email => "user@test.com"}
|
||||
@@ -268,7 +259,7 @@ class PasswordTest < ActionController::IntegrationTest
|
||||
|
||||
assert_not_contain "1 error prohibited this user from being saved:"
|
||||
assert_not_contain "Email not found"
|
||||
assert_contain "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
|
||||
assert_contain "If your e-mail exists on our database, you will receive a password recovery link on your e-mail"
|
||||
assert_current_url "/users/sign_in"
|
||||
end
|
||||
end
|
||||
@@ -280,21 +271,8 @@ class PasswordTest < ActionController::IntegrationTest
|
||||
fill_in 'email', :with => user.email
|
||||
click_button 'Send me reset password instructions'
|
||||
|
||||
assert_contain "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
|
||||
assert_contain "If your e-mail exists on our database, you will receive a password recovery link on your e-mail"
|
||||
assert_current_url "/users/sign_in"
|
||||
end
|
||||
end
|
||||
|
||||
test "after recovering a password, should set failed attempts to 0" do
|
||||
user = create_user
|
||||
user.update_attribute(:failed_attempts, 10)
|
||||
|
||||
assert_equal 10, user.failed_attempts
|
||||
request_forgot_password
|
||||
reset_password :reset_password_token => user.reload.reset_password_token
|
||||
|
||||
assert warden.authenticated?(:user)
|
||||
user.reload
|
||||
assert_equal 0, user.failed_attempts
|
||||
end
|
||||
end
|
||||
|
||||
@@ -100,19 +100,6 @@ class TokenAuthenticationTest < ActionController::IntegrationTest
|
||||
end
|
||||
end
|
||||
|
||||
test 'should reset token and not authenticate when expire_auth_token_on_timeout is set to true, timeoutable is enabled and we have a timed out session' do
|
||||
swap Devise, :token_authentication_key => :secret_token, :expire_auth_token_on_timeout => true, :timeout_in => (-1).minute do
|
||||
user = sign_in_as_new_user_with_token
|
||||
assert warden.authenticated?(:user)
|
||||
token = user.authentication_token
|
||||
|
||||
get_users_path_as_existing_user(user)
|
||||
assert_not warden.authenticated?(:user)
|
||||
user.reload
|
||||
assert_not_equal token, user.authentication_token
|
||||
end
|
||||
end
|
||||
|
||||
test 'should not be subject to injection' do
|
||||
swap Devise, :token_authentication_key => :secret_token do
|
||||
user1 = create_user_with_authentication_token()
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
require 'test_helper'
|
||||
|
||||
class AuthenticatableTest < ActiveSupport::TestCase
|
||||
test 'required_fields should be an empty array' do
|
||||
assert_equal Devise::Models::Validatable.required_fields(User), []
|
||||
test 'find_first_by_auth_conditions allows custom filtering parameters' do
|
||||
user = User.create!(:email => "example@example.com", :password => "123456")
|
||||
assert_equal User.find_first_by_auth_conditions({ :email => "example@example.com" }), user
|
||||
assert_equal User.find_first_by_auth_conditions({ :email => "example@example.com" }, :id => user.id + 1), nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -252,15 +252,6 @@ class ReconfirmableTest < ActiveSupport::TestCase
|
||||
assert_not_nil admin.confirmation_token
|
||||
end
|
||||
|
||||
test 'should not generate confirmation token if skipping reconfirmation after changing email' do
|
||||
admin = create_admin
|
||||
assert admin.confirm!
|
||||
admin.skip_reconfirmation!
|
||||
assert admin.update_attributes(:email => 'new_test@example.com')
|
||||
assert_nil admin.confirmation_token
|
||||
end
|
||||
|
||||
|
||||
test 'should regenerate confirmation token after changing email' do
|
||||
admin = create_admin
|
||||
assert admin.confirm!
|
||||
@@ -337,21 +328,4 @@ class ReconfirmableTest < ActiveSupport::TestCase
|
||||
admin = Admin.find_by_unconfirmed_email_with_errors(:email => "new_test@email.com")
|
||||
assert admin.persisted?
|
||||
end
|
||||
|
||||
test 'required_fields should contain the fields that Devise uses' do
|
||||
assert_same_content Devise::Models::Confirmable.required_fields(User), [
|
||||
:confirmation_sent_at,
|
||||
:confirmation_token,
|
||||
:confirmed_at
|
||||
]
|
||||
end
|
||||
|
||||
test 'required_fields should also contain unconfirmable when reconfirmable_email is true' do
|
||||
assert_same_content Devise::Models::Confirmable.required_fields(Admin), [
|
||||
:confirmation_sent_at,
|
||||
:confirmation_token,
|
||||
:confirmed_at,
|
||||
:unconfirmed_email
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -11,7 +11,7 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
|
||||
user.save!
|
||||
assert_equal email.downcase, user.email
|
||||
end
|
||||
|
||||
|
||||
test 'should remove whitespace from strip whitespace keys when saving' do
|
||||
# strip_whitespace_keys is set to :email by default.
|
||||
email = ' foo@bar.com '
|
||||
@@ -23,15 +23,9 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
test "param filter should not convert booleans and integer to strings" do
|
||||
conditions = { 'login' => 'foo@bar.com', "bool1" => true, "bool2" => false, "fixnum" => 123, "will_be_converted" => (1..10) }
|
||||
conditions = { "login" => "foo@bar.com", "bool1" => true, "bool2" => false, "fixnum" => 123, "will_be_converted" => (1..10) }
|
||||
conditions = Devise::ParamFilter.new([], []).filter(conditions)
|
||||
assert_equal( { 'login' => 'foo@bar.com', "bool1" => true, "bool2" => false, "fixnum" => 123, "will_be_converted" => "1..10" }, conditions)
|
||||
end
|
||||
|
||||
test "param filter should not convert regular expressions to strings" do
|
||||
conditions = { "regexp" => /expression/ }
|
||||
conditions = Devise::ParamFilter.new([], []).filter(conditions)
|
||||
assert_equal( { "regexp" => /expression/ }, conditions)
|
||||
assert_equal( { "login" => "foo@bar.com", "bool1" => "true", "bool2" => "false", "fixnum" => "123", "will_be_converted" => "1..10" }, conditions)
|
||||
end
|
||||
|
||||
test 'should respond to password and password confirmation' do
|
||||
@@ -92,14 +86,14 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
|
||||
:password => 'pass321', :password_confirmation => 'pass321')
|
||||
assert user.reload.valid_password?('pass321')
|
||||
end
|
||||
|
||||
|
||||
test 'should update password with valid current password and :as option' do
|
||||
user = create_user
|
||||
assert user.update_with_password(:current_password => '123456',
|
||||
:password => 'pass321', :password_confirmation => 'pass321', :as => :admin)
|
||||
assert user.reload.valid_password?('pass321')
|
||||
end
|
||||
|
||||
|
||||
test 'should add an error to current password when it is invalid' do
|
||||
user = create_user
|
||||
assert_not user.update_with_password(:current_password => 'other',
|
||||
@@ -151,7 +145,7 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
|
||||
user.update_without_password(:email => 'new@example.com')
|
||||
assert_equal 'new@example.com', user.email
|
||||
end
|
||||
|
||||
|
||||
test 'should update the user without password with :as option' do
|
||||
user = create_user
|
||||
user.update_without_password(:email => 'new@example.com', :as => :admin)
|
||||
@@ -170,20 +164,4 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
|
||||
user = User.create(:email => "HEllO@example.com", :password => "123456")
|
||||
assert !user.valid?
|
||||
end
|
||||
|
||||
test 'required_fiels should be encryptable_password and the email field by default' do
|
||||
assert_same_content Devise::Models::DatabaseAuthenticatable.required_fields(User), [
|
||||
:email,
|
||||
:encrypted_password
|
||||
]
|
||||
end
|
||||
|
||||
test 'required_fields should be encryptable_password and the login when the login is on authentication_keys' do
|
||||
swap Devise, :authentication_keys => [:login] do
|
||||
assert_same_content Devise::Models::DatabaseAuthenticatable.required_fields(User), [
|
||||
:encrypted_password,
|
||||
:login
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
67
test/models/encryptable_test.rb
Normal file
67
test/models/encryptable_test.rb
Normal file
@@ -0,0 +1,67 @@
|
||||
require 'test_helper'
|
||||
|
||||
class EncryptableTest < ActiveSupport::TestCase
|
||||
def encrypt_password(admin, pepper=Admin.pepper, stretches=Admin.stretches, encryptor=Admin.encryptor_class)
|
||||
encryptor.digest('123456', stretches, admin.password_salt, pepper)
|
||||
end
|
||||
|
||||
def swap_with_encryptor(klass, encryptor, options={})
|
||||
klass.instance_variable_set(:@encryptor_class, nil)
|
||||
|
||||
swap klass, options.merge(:encryptor => encryptor) do
|
||||
begin
|
||||
yield
|
||||
ensure
|
||||
klass.instance_variable_set(:@encryptor_class, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test 'should generate salt while setting password' do
|
||||
assert_present create_admin.password_salt
|
||||
end
|
||||
|
||||
test 'should not change password salt when updating' do
|
||||
admin = create_admin
|
||||
salt = admin.password_salt
|
||||
admin.expects(:password_salt=).never
|
||||
admin.save!
|
||||
assert_equal salt, admin.password_salt
|
||||
end
|
||||
|
||||
test 'should generate a base64 hash using SecureRandom for password salt' do
|
||||
swap_with_encryptor Admin, :sha1 do
|
||||
SecureRandom.expects(:base64).with(15).returns('01lI').twice
|
||||
salt = create_admin.password_salt
|
||||
assert_not_equal '01lI', salt
|
||||
assert_equal 4, salt.size
|
||||
end
|
||||
end
|
||||
|
||||
test 'should not generate salt if password is blank' do
|
||||
assert_blank create_admin(:password => nil).password_salt
|
||||
assert_blank create_admin(:password => '').password_salt
|
||||
end
|
||||
|
||||
test 'should encrypt password again if password has changed' do
|
||||
admin = create_admin
|
||||
encrypted_password = admin.encrypted_password
|
||||
admin.password = admin.password_confirmation = 'new_password'
|
||||
admin.save!
|
||||
assert_not_equal encrypted_password, admin.encrypted_password
|
||||
end
|
||||
|
||||
test 'should respect encryptor configuration' do
|
||||
swap_with_encryptor Admin, :sha512 do
|
||||
admin = create_admin
|
||||
assert_equal admin.encrypted_password, encrypt_password(admin, Admin.pepper, Admin.stretches, ::Devise::Encryptors::Sha512)
|
||||
end
|
||||
end
|
||||
|
||||
test 'should not validate password when salt is nil' do
|
||||
admin = create_admin
|
||||
admin.password_salt = nil
|
||||
admin.save
|
||||
assert_not admin.valid_password?('123456')
|
||||
end
|
||||
end
|
||||
@@ -14,6 +14,15 @@ class LockableTest < ActiveSupport::TestCase
|
||||
end
|
||||
end
|
||||
|
||||
test "should clear failed_attempts on successfull validation" do
|
||||
user = create_user
|
||||
user.confirm!
|
||||
user.valid_for_authentication?{ false }
|
||||
assert_equal 1, user.reload.failed_attempts
|
||||
user.valid_for_authentication?{ true }
|
||||
assert_equal 0, user.reload.failed_attempts
|
||||
end
|
||||
|
||||
test "should increment failed_attempts on successfull validation if the user is already locked" do
|
||||
user = create_user
|
||||
user.confirm!
|
||||
@@ -226,38 +235,4 @@ class LockableTest < ActiveSupport::TestCase
|
||||
assert_nil user.locked_at
|
||||
end
|
||||
end
|
||||
|
||||
test 'required_fields should contain the all the fields when all the strategies are enabled' do
|
||||
swap Devise, :unlock_strategy => :both do
|
||||
swap Devise, :lock_strategy => :failed_attempts do
|
||||
assert_same_content Devise::Models::Lockable.required_fields(User), [
|
||||
:failed_attempts,
|
||||
:unlock_at,
|
||||
:unlock_token
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test 'required_fields should contain only failed_attempts and unlock_at when the strategies are time and failed_attempts are enabled' do
|
||||
swap Devise, :unlock_strategy => :time do
|
||||
swap Devise, :lock_strategy => :failed_attempts do
|
||||
assert_same_content Devise::Models::Lockable.required_fields(User), [
|
||||
:failed_attempts,
|
||||
:unlock_at
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test 'required_fields should contain only failed_attempts and unlock_token when the strategies are token and failed_attempts are enabled' do
|
||||
swap Devise, :unlock_strategy => :email do
|
||||
swap Devise, :lock_strategy => :failed_attempts do
|
||||
assert_same_content Devise::Models::Lockable.required_fields(User), [
|
||||
:failed_attempts,
|
||||
:unlock_token
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
require 'test_helper'
|
||||
|
||||
class OmniauthableTest < ActiveSupport::TestCase
|
||||
test 'required_fields should contain the fields that Devise uses' do
|
||||
assert_same_content Devise::Models::Omniauthable.required_fields(User), []
|
||||
end
|
||||
end
|
||||
@@ -195,11 +195,4 @@ class RecoverableTest < ActiveSupport::TestCase
|
||||
assert_equal "has expired, please request a new one", reset_password_user.errors[:reset_password_token].join
|
||||
end
|
||||
end
|
||||
|
||||
test 'required_fields should contain the fields that Devise uses' do
|
||||
assert_same_content Devise::Models::Recoverable.required_fields(User), [
|
||||
:reset_password_sent_at,
|
||||
:reset_password_token
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
require 'test_helper'
|
||||
|
||||
class RegisterableTest < ActiveSupport::TestCase
|
||||
test 'required_fields should contain the fields that Devise uses' do
|
||||
assert_same_content Devise::Models::Registerable.required_fields(User), []
|
||||
end
|
||||
end
|
||||
@@ -54,7 +54,7 @@ class RememberableTest < ActiveSupport::TestCase
|
||||
resource.forget_me!
|
||||
assert resource.remember_created_at.nil?
|
||||
end
|
||||
|
||||
|
||||
test 'forget_me should not try to update resource if it has been destroyed' do
|
||||
resource = create_resource
|
||||
resource.destroy
|
||||
@@ -165,10 +165,4 @@ class RememberableTest < ActiveSupport::TestCase
|
||||
assert_not_equal old, resource.remember_created_at
|
||||
end
|
||||
end
|
||||
|
||||
test 'should have the required_fiels array' do
|
||||
assert_same_content Devise::Models::Rememberable.required_fields(User), [
|
||||
:remember_created_at
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -39,8 +39,4 @@ class TimeoutableTest < ActiveSupport::TestCase
|
||||
assert user.timedout?(6.minutes.ago)
|
||||
end
|
||||
end
|
||||
|
||||
test 'required_fields should contain the fields that Devise uses' do
|
||||
assert_same_content Devise::Models::Timeoutable.required_fields(User), []
|
||||
end
|
||||
end
|
||||
|
||||
@@ -46,10 +46,4 @@ class TokenAuthenticatableTest < ActiveSupport::TestCase
|
||||
user = User.find_for_token_authentication(:auth_token => {'$ne' => user1.authentication_token})
|
||||
assert_nil user
|
||||
end
|
||||
|
||||
test 'required_fields should contain the fields that Devise uses' do
|
||||
assert_same_content Devise::Models::TokenAuthenticatable.required_fields(User), [
|
||||
:authentication_token
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
require 'test_helper'
|
||||
|
||||
class TrackableTest < ActiveSupport::TestCase
|
||||
test 'required_fields should contain the fields that Devise uses' do
|
||||
assert_same_content Devise::Models::Trackable.required_fields(User), [
|
||||
:current_sign_in_at,
|
||||
:current_sign_in_ip,
|
||||
:last_sign_in_at,
|
||||
:last_sign_in_ip,
|
||||
:sign_in_count
|
||||
]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -105,13 +105,9 @@ class ValidatableTest < ActiveSupport::TestCase
|
||||
assert_equal 'is too long (maximum is 128 characters)', user.errors[:password].join
|
||||
end
|
||||
|
||||
test 'should not be included in objects with invalid API' do
|
||||
test 'shuold not be included in objects with invalid API' do
|
||||
assert_raise RuntimeError do
|
||||
Class.new.send :include, Devise::Models::Validatable
|
||||
end
|
||||
end
|
||||
|
||||
test 'required_fields should be an empty array' do
|
||||
assert_equal Devise::Models::Validatable.required_fields(User), []
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
require 'test_helper'
|
||||
|
||||
class Configurable < User
|
||||
devise :database_authenticatable, :confirmable, :rememberable, :timeoutable, :lockable,
|
||||
devise :database_authenticatable, :encryptable, :confirmable, :rememberable, :timeoutable, :lockable,
|
||||
:stretches => 15, :pepper => 'abcdef', :allow_unconfirmed_access_for => 5.days,
|
||||
:remember_for => 7.days, :timeout_in => 15.minutes, :unlock_in => 10.days
|
||||
end
|
||||
@@ -39,7 +39,7 @@ class ActiveRecordTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
test 'can cherry pick modules' do
|
||||
assert_include_modules Admin, :database_authenticatable, :registerable, :timeoutable, :recoverable, :lockable, :confirmable
|
||||
assert_include_modules Admin, :database_authenticatable, :registerable, :timeoutable, :recoverable, :lockable, :encryptable, :confirmable
|
||||
end
|
||||
|
||||
test 'validations options are not applied too late' do
|
||||
@@ -55,12 +55,12 @@ class ActiveRecordTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
test 'chosen modules are inheritable' do
|
||||
assert_include_modules Inheritable, :database_authenticatable, :registerable, :timeoutable, :recoverable, :lockable, :confirmable
|
||||
assert_include_modules Inheritable, :database_authenticatable, :registerable, :timeoutable, :recoverable, :lockable, :encryptable, :confirmable
|
||||
end
|
||||
|
||||
test 'order of module inclusion' do
|
||||
correct_module_order = [:database_authenticatable, :recoverable, :registerable, :confirmable, :lockable, :timeoutable]
|
||||
incorrect_module_order = [:database_authenticatable, :timeoutable, :registerable, :recoverable, :lockable, :confirmable]
|
||||
correct_module_order = [:database_authenticatable, :encryptable, :recoverable, :registerable, :confirmable, :lockable, :timeoutable]
|
||||
incorrect_module_order = [:database_authenticatable, :timeoutable, :registerable, :recoverable, :lockable, :encryptable, :confirmable]
|
||||
|
||||
assert_include_modules Admin, *incorrect_module_order
|
||||
|
||||
@@ -107,73 +107,3 @@ class ActiveRecordTest < ActiveSupport::TestCase
|
||||
Admin.create!
|
||||
end
|
||||
end
|
||||
|
||||
class CheckFieldsTest < ActiveSupport::TestCase
|
||||
test 'checks if the class respond_to the required fields' do
|
||||
Player = Class.new do
|
||||
extend Devise::Models
|
||||
|
||||
def self.before_validation(instance)
|
||||
end
|
||||
|
||||
devise :database_authenticatable
|
||||
|
||||
attr_accessor :encrypted_password, :email
|
||||
end
|
||||
|
||||
assert_nothing_raised Devise::Models::MissingAttribute do
|
||||
Devise::Models.check_fields!(Player)
|
||||
end
|
||||
end
|
||||
|
||||
test 'raises Devise::Models::MissingAtrribute and shows the missing attribute if the class doesn\'t respond_to one of the attributes' do
|
||||
Clown = Class.new do
|
||||
extend Devise::Models
|
||||
|
||||
def self.before_validation(instance)
|
||||
end
|
||||
|
||||
devise :database_authenticatable
|
||||
|
||||
attr_accessor :encrypted_password
|
||||
end
|
||||
|
||||
assert_raise_with_message Devise::Models::MissingAttribute, "The following attribute(s) is (are) missing on your model: email" do
|
||||
Devise::Models.check_fields!(Clown)
|
||||
end
|
||||
end
|
||||
|
||||
test 'raises Devise::Models::MissingAtrribute with all the missing attributes if there is more than one' do
|
||||
Magician = Class.new do
|
||||
extend Devise::Models
|
||||
|
||||
def self.before_validation(instance)
|
||||
end
|
||||
|
||||
devise :database_authenticatable
|
||||
end
|
||||
|
||||
exception = assert_raise_with_message Devise::Models::MissingAttribute, "The following attribute(s) is (are) missing on your model: encrypted_password, email" do
|
||||
Devise::Models.check_fields!(Magician)
|
||||
end
|
||||
end
|
||||
|
||||
test "doesn't raise a NoMethodError exception when the module doesn't have a required_field(klass) class method" do
|
||||
driver = Class.new do
|
||||
extend Devise::Models
|
||||
|
||||
def self.before_validation(instance)
|
||||
end
|
||||
|
||||
attr_accessor :encrypted_password, :email
|
||||
|
||||
devise :database_authenticatable
|
||||
end
|
||||
|
||||
swap_module_method_existence Devise::Models::DatabaseAuthenticatable, :required_fields do
|
||||
assert_deprecated do
|
||||
Devise::Models.check_fields!(driver)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -22,6 +22,9 @@ class Admin
|
||||
field :confirmation_sent_at, :type => Time
|
||||
field :unconfirmed_email, :type => String # Only if using reconfirmable
|
||||
|
||||
## Encryptable
|
||||
field :password_salt, :type => String
|
||||
|
||||
## Lockable
|
||||
field :locked_at, :type => Time
|
||||
end
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user