Compare commits

...

64 Commits

Author SHA1 Message Date
José Valim
ba2e44c6a4 Release 2.1.1 2012-06-16 15:57:17 +02:00
José Valim
4f07ed42e3 Lock warden on sign out 2012-06-16 15:21:48 +02:00
José Valim
66716023e4 Disable storage on CSRF 2012-06-16 14:51:37 +02:00
José Valim
4bc2ff997a Timeout does not explode when reset_authentication_token! is accidentally defined by Active Model 2012-06-16 14:04:34 +02:00
José Valim
b1633f2454 Delegate omniauth_authorize_path to the router, closes #1843 2012-06-16 13:43:11 +02:00
José Valim
41a91188f5 Do not trigger timeout on sign in related actions 2012-06-16 13:24:07 +02:00
José Valim
4def600076 Mark some methods as private 2012-06-16 13:06:52 +02:00
José Valim
18a18e4c72 Provide a send_devise_notification hook 2012-06-16 13:00:51 +02:00
José Valim
85c90671bc Update CHANGELOG 2012-06-16 12:38:02 +02:00
José Valim
16b688eced Merge pull request #1922 from excid3/master
Flexible routing scopes
2012-06-15 11:21:21 -07:00
Chris Oliver
37c55eb192 Added tests for flexible routing constraints 2012-06-15 13:06:29 -05:00
Chris Oliver
2d7dc3e82d Merge branch 'master' of git://github.com/plataformatec/devise 2012-06-15 11:05:58 -05:00
Chris Oliver
e7a8a7247c Switch and, or to &&, || 2012-06-15 08:45:44 -05:00
José Valim
c4818a9fb2 Reorganize tests slightly 2012-06-15 11:15:03 +02:00
Chris Oliver
8c2a7146df Add scope into warden user access 2012-06-15 02:10:42 -05:00
Chris Oliver
311e3206c9 Added block to authenticate route as well 2012-06-15 00:12:09 -05:00
Chris Oliver
6ad6b3d2a6 Allow passing a block to the authenticated route 2012-06-14 23:54:12 -05:00
Carlos Galdino
471a05fd59 Merge pull request #1921 from nashby/data-confirm
use data-confirm option as :confirm was deprecated in rails 3.2.6
2012-06-14 12:50:02 -07:00
Vasiliy Ermolovich
7a12655111 use data-confirm option as :confirm was deprecated in rails 3.2.6
SimpleForm templates
2012-06-14 22:48:37 +03:00
Rafael Mendonça França
1b26869b74 Merge pull request #1920 from nashby/data-confirm
use data-confirm option as :confirm was deprecated in rails 3.2.6
2012-06-14 12:35:30 -07:00
Vasiliy Ermolovich
13f35d80a9 use data-confirm option as :confirm was deprecated in rails 3.2.6 2012-06-14 22:27:40 +03:00
José Valim
1c4faa7d8a Depend on latest orm adapter 2012-06-13 15:07:24 +02:00
José Valim
c26ed53927 Merge pull request #1908 from mhfs/lockable_async_fix
Persist unlock token before triggering mailer
2012-06-11 14:09:24 -07:00
Marcelo Silveira
fe0f6e96b3 Persist unlock token before triggering mailer 2012-06-11 17:52:10 -03:00
José Valim
6dd7ccee68 Add more docs, remove 3.0 related code, update CHANGELOG 2012-06-08 19:22:14 +02:00
José Valim
9327cf8af5 Merge pull request #1903 from zamith/master
Routes for engines
2012-06-08 10:05:56 -07:00
Zamith
512b52e23a Adding option to change omniauth path prefix 2012-06-08 17:50:33 +01:00
José Valim
5df7105301 Merge pull request #1902 from gbataille/master
Redirect to sign_in page when trying to access password#edit without a reset password token
2012-06-08 01:19:05 -07:00
Gregory Bataille
a84fdb771f Merge branches 'master' and 'no_token' 2012-06-08 10:08:50 +02:00
Gregory Bataille
ff75341c75 Redirect to sign in page when trying to access password#edit without a
reset_password_token (i.e. not coming from a reset password email)
2012-06-08 10:08:35 +02:00
Carlos Antonio da Silva
f0d48a96ca Fix rdoc rake task [ci skip] 2012-06-07 22:48:15 -03:00
José Valim
215fdf119e Better error message when mapping can't be found 2012-06-07 14:34:13 +03:00
José Valim
985b646ee1 Update README.md, closes #1895 2012-06-07 14:31:43 +03:00
José Valim
622e480c4b Merge pull request #1892 from clody69/master
Fixed User model generation for Mongoid
2012-06-07 01:09:54 -07:00
José Valim
2e78a46c52 Merge pull request #1896 from Antiarchitect/patch-1
In addition to #1722. expire_auth_token_on_timeout added to Timeoutable configuration block.
2012-06-07 01:09:05 -07:00
Andrey Voronkov
b1b6e53d6f In addition to #1722. expire_auth_token_on_timeout added to Timeoutable configuration block. 2012-06-07 09:32:44 +04:00
José Valim
65325f7f81 Merge pull request #1894 from wtn/master
#update_with_password should use mass assignment options when password is not valid
2012-06-05 01:15:51 -07:00
William T Nelson
9bd82e5a24 use mass assignment options when password is not valid 2012-06-04 22:52:09 -05:00
Claudio Riva
0689b4558e Update master 2012-06-03 22:24:31 +03:00
Rafael Mendonça França
dbea934701 Update README.md [ci skip] 2012-05-29 17:28:57 -03:00
Rafael Mendonça França
8e4d5fb38f Merge pull request #1882 from GeekOnCoffee/patch-1
URLs that aren't links aren't nice
2012-05-29 13:26:56 -07:00
Andrew Hooker
e324ee9823 URLs that aren't links aren't nice 2012-05-29 15:24:34 -05:00
José Valim
54e9cabf5d Update README.md 2012-05-29 16:46:58 +03:00
José Valim
7a3f6fb53d Merge pull request #1880 from brynary/codeclimate-badge
Add Code Climate badge to README
2012-05-29 05:54:49 -07:00
Bryan Helmkamp
59a9576498 Add Code Climate badge to README 2012-05-29 08:46:48 -04:00
José Valim
57eb3886ba Refactor router.rb a bit based on Code Climate feedback: https://codeclimate.com/github/plataformatec/devise/Devise 2012-05-29 11:29:09 +02:00
Rafael Mendonça França
fe9e6db0e2 Merge pull request #1876 from shaliko/master
Remove not used variables
2012-05-26 09:36:30 -07:00
Shaliko Usubov
db8eeb6c6e Remove not used variables 2012-05-26 20:31:42 +04:00
José Valim
2b7328535d Check for the request before checking for the mapping, closes #1859 2012-05-25 09:39:50 +02:00
José Valim
d4e5424360 Simplify validation logic inside strategies 2012-05-22 14:10:06 +02:00
José Valim
d67d992749 Merge pull request #1865 from nirvdrum/patch-1
Simple compose VS comprise grammar fix.
2012-05-21 03:33:57 -07:00
Kevin Menard
b6c7aafe55 Simple compose VS comprise grammar fix. 2012-05-20 23:04:53 -03:00
José Valim
9829384829 Merge pull request #1864 from nashby/update-views
use implicit partials rendering and update simple_form templates
2012-05-20 12:17:19 -07:00
Vasiliy Ermolovich
1d79c1982a use implicit partials rendering
make simple_form templates consistent with templates
that generates by simple_form itself

612c0067cf
2012-05-20 22:01:11 +03:00
José Valim
f6259531c3 Update CHANGELOG.rdoc 2012-05-17 13:25:07 +03:00
José Valim
ed03039d19 Merge pull request #1857 from pomnikita/master
Remove devise/schema from autoloads
2012-05-17 02:27:30 -07:00
Nikita Pomyashchiy
b6abc4623b Remove autoload of deprecated devise/schema 2012-05-17 13:13:19 +04:00
Carlos Antonio da Silva
d1949b7b42 Fix indent, remove not used variable 2012-05-15 17:22:52 -03:00
Carlos Antonio da Silva
b6e30427a3 Pass the block argument straight to the assertion methods in test helpers 2012-05-15 17:19:21 -03:00
Carlos Antonio da Silva
96e0dcf5d5 Remove not used variable, fix indent 2012-05-15 17:14:05 -03:00
Carlos Antonio da Silva
ab48435211 Remove warning with shadowing variable 2012-05-15 15:27:46 -03:00
Carlos Antonio da Silva
8bcb05d6c0 Cache constant on check fields 2012-05-15 15:20:01 -03:00
Carlos Antonio da Silva
6b363d6af9 Build only one model instance for checking fields 2012-05-15 15:12:18 -03:00
Carlos Antonio da Silva
2fd2a8662d Define the accessor right away instead of open + send 2012-05-15 15:05:21 -03:00
58 changed files with 578 additions and 334 deletions

View File

@@ -1,15 +1,40 @@
== trunk (2.1.0.rc2)
== 2.1.1
Notes: https://github.com/plataformatec/devise/wiki/How-to:-upgrade-to-devise-2.1
* enhancements
* `sign_out_all_scopes` now locks warden and does not allow new logins in the same action
* `Devise.omniauth_path_prefix` is available to configure omniauth path prefix
* Redirect to sign in page when trying to access password#edit without a token (by @gbataille)
* Allow a lambda in authenticate(d) routes helpers to further select the scope
* Removed warnings on Rails 3.2.6 (by @nashby)
* bug fix
* `update_with_password` now relies on assign_attributes and forwards the :as option (by @wtn)
* Do not trigger timeout on sign in related actions
* Timeout does not explode when reset_authentication_token! is accidentally defined by Active Model (by @remomueller)
* deprecations
* Strategy#validate() no longer validates nil resources
== 2.1.0
* enhancements
* Add `check_fields!(model_class)` method on Devise::Models to check if the model includes the fields that Devise uses
* Add `skip_reconfirmation!` to skip reconfirmation
* 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
* All devise modules should now have a `required_fields(klass)` module method to help gathering missing attributes
* `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
* 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)
* 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)
@@ -18,20 +43,6 @@
* 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)
== 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
* 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
== 2.0.4
Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.0

View File

@@ -2,7 +2,7 @@ source "http://rubygems.org"
gemspec
gem "rails", "~> 3.2.0"
gem "rails", "~> 3.2.3"
gem "omniauth", "~> 1.0.0"
gem "omniauth-oauth2", "~> 1.0.0"
gem "rdoc"

View File

@@ -3,42 +3,42 @@ PATH
specs:
devise (2.1.0)
bcrypt-ruby (~> 3.0)
orm_adapter (~> 0.0.7)
orm_adapter (~> 0.1)
railties (~> 3.1)
warden (~> 1.1.1)
warden (~> 1.2.1)
GEM
remote: http://rubygems.org/
specs:
actionmailer (3.2.0)
actionpack (= 3.2.0)
mail (~> 2.4.0)
actionpack (3.2.0)
activemodel (= 3.2.0)
activesupport (= 3.2.0)
actionmailer (3.2.3)
actionpack (= 3.2.3)
mail (~> 2.4.4)
actionpack (3.2.3)
activemodel (= 3.2.3)
activesupport (= 3.2.3)
builder (~> 3.0.0)
erubis (~> 2.7.0)
journey (~> 1.0.0)
journey (~> 1.0.1)
rack (~> 1.4.0)
rack-cache (~> 1.1)
rack-cache (~> 1.2)
rack-test (~> 0.6.1)
sprockets (~> 2.1.2)
activemodel (3.2.0)
activesupport (= 3.2.0)
activemodel (3.2.3)
activesupport (= 3.2.3)
builder (~> 3.0.0)
activerecord (3.2.0)
activemodel (= 3.2.0)
activesupport (= 3.2.0)
arel (~> 3.0.0)
activerecord (3.2.3)
activemodel (= 3.2.3)
activesupport (= 3.2.3)
arel (~> 3.0.2)
tzinfo (~> 0.3.29)
activeresource (3.2.0)
activemodel (= 3.2.0)
activesupport (= 3.2.0)
activesupport (3.2.0)
activeresource (3.2.3)
activemodel (= 3.2.3)
activesupport (= 3.2.3)
activesupport (3.2.3)
i18n (~> 0.6)
multi_json (~> 1.0)
addressable (2.2.6)
arel (3.0.0)
arel (3.0.2)
bcrypt-ruby (3.0.1)
bson (1.5.1)
bson_ext (1.3.1)
@@ -52,16 +52,16 @@ GEM
hashie (1.2.0)
hike (1.2.1)
i18n (0.6.0)
journey (1.0.0)
json (1.6.5)
journey (1.0.3)
json (1.7.3)
linecache (0.46)
rbx-require-relative (> 0.0.4)
mail (2.4.1)
mail (2.4.4)
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
metaclass (0.0.1)
mime-types (1.17.2)
mime-types (1.18)
mocha (0.10.0)
metaclass (~> 0.0.1)
mongo (1.3.1)
@@ -87,10 +87,10 @@ GEM
omniauth-openid (1.0.1)
omniauth (~> 1.0)
rack-openid (~> 1.3.1)
orm_adapter (0.0.7)
orm_adapter (0.1.0)
polyglot (0.3.3)
rack (1.4.1)
rack-cache (1.1)
rack-cache (1.2)
rack (>= 0.4)
rack-openid (1.3.1)
rack (>= 1.1.0)
@@ -99,17 +99,17 @@ GEM
rack
rack-test (0.6.1)
rack (>= 1.0)
rails (3.2.0)
actionmailer (= 3.2.0)
actionpack (= 3.2.0)
activerecord (= 3.2.0)
activeresource (= 3.2.0)
activesupport (= 3.2.0)
rails (3.2.3)
actionmailer (= 3.2.3)
actionpack (= 3.2.3)
activerecord (= 3.2.3)
activeresource (= 3.2.3)
activesupport (= 3.2.3)
bundler (~> 1.0)
railties (= 3.2.0)
railties (3.2.0)
actionpack (= 3.2.0)
activesupport (= 3.2.0)
railties (= 3.2.3)
railties (3.2.3)
actionpack (= 3.2.3)
activesupport (= 3.2.3)
rack-ssl (~> 1.3.2)
rake (>= 0.8.7)
rdoc (~> 3.4)
@@ -124,7 +124,7 @@ GEM
ruby-debug-base (0.10.4)
linecache (>= 0.3)
ruby-openid (2.1.8)
sprockets (2.1.2)
sprockets (2.1.3)
hike (~> 1.2)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
@@ -134,8 +134,8 @@ GEM
treetop (1.4.10)
polyglot
polyglot (>= 0.3.1)
tzinfo (0.3.31)
warden (1.1.1)
tzinfo (0.3.33)
warden (1.2.1)
rack (>= 1.0)
webrat (0.7.2)
nokogiri (>= 1.2.0)
@@ -158,7 +158,7 @@ DEPENDENCIES
omniauth-facebook
omniauth-oauth2 (~> 1.0.0)
omniauth-openid (~> 1.0.1)
rails (~> 3.2.0)
rails (~> 3.2.3)
rdoc
ruby-debug (>= 0.10.3)
sqlite3

View File

@@ -1,12 +1,10 @@
*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
## Devise
INFO: This README is [also available in a friendly navigable format](http://devise.plataformatec.com.br/).
[![Build Status](https://secure.travis-ci.org/plataformatec/devise.png)](http://travis-ci.org/plataformatec/devise)
[![Build Status](https://secure.travis-ci.org/plataformatec/devise.png)](http://travis-ci.org/plataformatec/devise) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/plataformatec/devise)
Devise is a flexible authentication solution for Rails based on Warden. It:
@@ -15,11 +13,11 @@ Devise is a flexible authentication solution for Rails based on Warden. It:
* Allows you to have multiple roles (or models/scopes) signed in at the same time;
* Is based on a modularity concept: use just what you really need.
It's comprised of 12 modules:
It's composed 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;
* [Omniauthable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Omniauthable): adds Omniauth (https://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.
@@ -306,7 +304,23 @@ https://github.com/plataformatec/devise/wiki/I18n
### Test helpers
Devise includes some tests helpers for functional specs. To use them, you just need to include Devise::TestHelpers in your test class and use the sign_in and sign_out method. Such methods have the same signature as in controllers:
Devise includes some tests helpers for functional specs. In other to use them, you need to include Devise in your functional tests by adding the following to the bottom of your `test/test_helper.rb` file:
```ruby
class ActionController::TestCase
include Devise::TestHelpers
end
```
If you're using RSpec, you can put the following inside a file named `spec/support/devise.rb`:
```ruby
RSpec.configure do |config|
config.include Devise::TestHelpers, :type => :controller
end
```
Now you are ready to use the `sign_in` and `sign_out` methods. Such methods have the same signature as in controllers:
```ruby
sign_in :user, @user # sign_in(scope, resource)
@@ -316,23 +330,14 @@ sign_out :user # sign_out(scope)
sign_out @user # sign_out(resource)
```
You can include the Devise Test Helpers in all of your tests by adding the following to the bottom of your test/test_helper.rb file:
There are two things that is important to keep in mind:
```ruby
class ActionController::TestCase
include Devise::TestHelpers
end
```
1) These helpers are not going to work for integration tests driven by Capybara or Webrat. They are meant to be used with functional tests only. Instead, fill in the form or explicitly set the user in session;
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:
2) If you are testing Devise internal controllers or a controller that inherits from Devise's, you need to tell Devise which mapping should be used before a request. This is necessary because Devise gets this information from router, but since functional tests do not pass through the router, it needs to be told explicitly. For example, if you are testing the user scope, simply do:
```ruby
RSpec.configure do |config|
config.include Devise::TestHelpers, :type => :controller
end
```
Do not use such helpers for integration tests such as Cucumber or Webrat. Instead, fill in the form or explicitly set the user in session. For more tips, check the wiki (https://wiki.github.com/plataformatec/devise).
@request.env["devise.mapping"] = Devise.mappings[:user]
get :new
### Omniauth

View File

@@ -29,6 +29,6 @@ Rake::RDocTask.new(:rdoc) do |rdoc|
rdoc.rdoc_dir = 'rdoc'
rdoc.title = 'Devise'
rdoc.options << '--line-numbers' << '--inline-source'
rdoc.rdoc_files.include('README.rdoc')
rdoc.rdoc_files.include('README.md')
rdoc.rdoc_files.include('lib/**/*.rb')
end

View File

@@ -1,4 +1,10 @@
class Devise::OmniauthCallbacksController < DeviseController
prepend_before_filter { request.env["devise.skip_timeout"] = true }
def passthru
render :status => 404, :text => "Not found. Authentication passthru."
end
def failure
set_flash_message :alert, :failure, :kind => failed_strategy.name.to_s.humanize, :reason => failure_message
redirect_to after_omniauth_failure_path_for(resource_name)

View File

@@ -1,5 +1,7 @@
class Devise::PasswordsController < DeviseController
prepend_before_filter :require_no_authentication
# Render the #edit only if coming from a reset password email link
append_before_filter :assert_reset_token_passed, :only => :edit
# GET /resource/password/new
def new
@@ -44,4 +46,11 @@ class Devise::PasswordsController < DeviseController
new_session_path(resource_name)
end
# Check if a reset_password_token is provided in the request
def assert_reset_token_passed
if params[:reset_password_token].blank?
set_flash_message(:error, :no_token)
redirect_to new_session_path(resource_name)
end
end
end

View File

@@ -1,6 +1,7 @@
class Devise::SessionsController < DeviseController
prepend_before_filter :require_no_authentication, :only => [ :new, :create ]
prepend_before_filter :allow_params_authentication!, :only => :create
prepend_before_filter { request.env["devise.skip_timeout"] = true }
# GET /resource/sign_in
def new

View File

@@ -43,8 +43,11 @@ class DeviseController < Devise.parent_controller.constantize
end
# Override prefixes to consider the scoped view.
# Notice we need to check for the request due to a bug in
# Action Controller tests that forces _prefixes to be
# loaded before even having a request object.
def _prefixes #:nodoc:
@_prefixes ||= if self.class.scoped_views? && devise_mapping
@_prefixes ||= if self.class.scoped_views? && request && devise_mapping
super.unshift("#{devise_mapping.scoped_path}/#{controller_name}")
else
super
@@ -59,11 +62,19 @@ class DeviseController < Devise.parent_controller.constantize
def assert_is_devise_resource! #:nodoc:
unknown_action! <<-MESSAGE unless devise_mapping
Could not find devise mapping for path #{request.fullpath.inspect}.
Maybe you forgot to wrap your route inside the scope block? For example:
This may happen for two reasons:
1) You forgot to wrap your route inside the scope block. For example:
devise_scope :user do
match "/some/route" => "some_devise_controller"
end
2) You are testing a Devise controller bypassing the router.
If so, you can explicitly tell Devise which mapping to use:
@request.env["devise.mapping"] = Devise.mappings[:user]
devise_scope :user do
match "/some/route" => "some_devise_controller"
end
MESSAGE
end

View File

@@ -9,4 +9,4 @@
<div><%= f.submit "Resend confirmation instructions" %></div>
<% end %>
<%= render :partial => "devise/shared/links" %>
<%= render "devise/shared/links" %>

View File

@@ -13,4 +13,4 @@
<div><%= f.submit "Change my password" %></div>
<% end %>
<%= render :partial => "devise/shared/links" %>
<%= render "devise/shared/links" %>

View File

@@ -9,4 +9,4 @@
<div><%= f.submit "Send me reset password instructions" %></div>
<% end %>
<%= render :partial => "devise/shared/links" %>
<%= render "devise/shared/links" %>

View File

@@ -20,6 +20,6 @@
<h3>Cancel my account</h3>
<p>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), :confirm => "Are you sure?", :method => :delete %>.</p>
<p>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), :data => { :confirm => "Are you sure?" }, :method => :delete %>.</p>
<%= link_to "Back", :back %>

View File

@@ -15,4 +15,4 @@
<div><%= f.submit "Sign up" %></div>
<% end %>
<%= render :partial => "devise/shared/links" %>
<%= render "devise/shared/links" %>

View File

@@ -14,4 +14,4 @@
<div><%= f.submit "Sign in" %></div>
<% end %>
<%= render :partial => "devise/shared/links" %>
<%= render "devise/shared/links" %>

View File

@@ -9,4 +9,4 @@
<div><%= f.submit "Resend unlock instructions" %></div>
<% end %>
<%= render :partial => "devise/shared/links" %>
<%= render "devise/shared/links" %>

View File

@@ -29,6 +29,7 @@ en:
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."
no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
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.'

View File

@@ -18,8 +18,8 @@ Gem::Specification.new do |s|
s.test_files = `git ls-files -- test/*`.split("\n")
s.require_paths = ["lib"]
s.add_dependency("warden", "~> 1.1.1")
s.add_dependency("orm_adapter", "~> 0.0.7")
s.add_dependency("warden", "~> 1.2.1")
s.add_dependency("orm_adapter", "~> 0.1")
s.add_dependency("bcrypt-ruby", "~> 3.0")
s.add_dependency("railties", "~> 3.1")
end

View File

@@ -10,7 +10,6 @@ module Devise
autoload :FailureApp, 'devise/failure_app'
autoload :OmniAuth, 'devise/omniauth'
autoload :ParamFilter, 'devise/param_filter'
autoload :Schema, 'devise/schema'
autoload :TestHelpers, 'devise/test_helpers'
module Controllers
@@ -200,6 +199,11 @@ module Devise
# to provide custom routes.
mattr_accessor :router_name
@@router_name = nil
# Set the omniauth path prefix so it can be overriden when
# Devise is used in a mountable engine
mattr_accessor :omniauth_path_prefix
@@omniauth_path_prefix = nil
def self.encryptor=(value)
warn "\n[DEVISE] To select a encryption which isn't bcrypt, you should use devise-encryptable gem.\n"

View File

@@ -88,8 +88,8 @@ module Devise
# Return true if the given scope is signed in session. If no scope given, return
# true if any scope is signed in. Does not run authentication hooks.
def signed_in?(scope=nil)
[ scope || Devise.mappings.keys ].flatten.any? do |scope|
warden.authenticate?(:scope => scope)
[ scope || Devise.mappings.keys ].flatten.any? do |_scope|
warden.authenticate?(:scope => _scope)
end
end
@@ -126,8 +126,8 @@ module Devise
end
# Sign out a given user or scope. This helper is useful for signing out a user
# after deleting accounts. Returns true if there was a logout and false if there is no user logged in
# on the referred scope
# after deleting accounts. Returns true if there was a logout and false if there
# is no user logged in on the referred scope
#
# Examples:
#
@@ -141,6 +141,7 @@ module Devise
warden.raw_session.inspect # Without this inspect here. The session does not clear.
warden.logout(scope)
warden.clear_strategies_cache!(:scope => scope)
instance_variable_set(:"@current_#{scope}", nil)
!!user
@@ -149,13 +150,15 @@ module Devise
# Sign out all active users or scopes. This helper is useful for signing out all roles
# in one click. This signs out ALL scopes in warden. Returns true if there was at least one logout
# and false if there was no user logged in on all scopes.
def sign_out_all_scopes
def sign_out_all_scopes(lock=true)
users = Devise.mappings.keys.map { |s| warden.user(:scope => s, :run_callbacks => false) }
warden.raw_session.inspect
warden.logout
expire_devise_cached_variables!
warden.clear_strategies_cache!
warden.lock! if lock
users.any?
end
@@ -253,8 +256,8 @@ module Devise
# Overwrite Rails' handle unverified request to sign out all scopes,
# clear run strategies and remove cached variables.
def handle_unverified_request
sign_out_all_scopes
warden.clear_strategies_cache!
sign_out_all_scopes(false)
request.env["devise.skip_storage"] = true
expire_devise_cached_variables!
super # call the default behaviour which resets the session
end

View File

@@ -5,17 +5,20 @@
# verify timeout in the following request.
Warden::Manager.after_set_user do |record, warden, options|
scope = options[:scope]
env = warden.request.env
if record && record.respond_to?(:timedout?) && warden.authenticated?(scope) && options[:store] != false
last_request_at = warden.session(scope)['last_request_at']
if record.timedout?(last_request_at)
if record.timedout?(last_request_at) && !env['devise.skip_timeout']
warden.logout(scope)
record.reset_authentication_token! if record.respond_to?(:reset_authentication_token!) && record.expire_auth_token_on_timeout
if record.respond_to?(:expire_auth_token_on_timeout) && record.expire_auth_token_on_timeout
record.reset_authentication_token!
end
throw :warden, :scope => scope, :message => :timeout
end
unless warden.request.env['devise.skip_trackable']
unless env['devise.skip_trackable']
warden.session(scope)['last_request_at'] = Time.now.utc
end
end

View File

@@ -27,7 +27,7 @@ module Devise
# inside the given class.
#
def self.config(mod, *accessors) #:nodoc:
(class << mod; self; end).send :attr_accessor, :available_configs
class << mod; attr_accessor :available_configs; end
mod.available_configs = accessors
accessors.each do |accessor|
@@ -51,12 +51,13 @@ module Devise
def self.check_fields!(klass)
failed_attributes = []
instance = klass.new
klass.devise_modules.each do |mod|
instance = klass.new
constant = const_get(mod.to_s.classify)
if const_get(mod.to_s.classify).respond_to?(:required_fields)
const_get(mod.to_s.classify).required_fields(klass).each do |field|
if constant.respond_to?(:required_fields)
constant.required_fields(klass).each do |field|
failed_attributes << field unless instance.respond_to?(field)
end
else

View File

@@ -93,22 +93,10 @@ module Devise
def authenticatable_salt
end
def devise_mailer
Devise.mailer
end
def headers_for(name)
{}
end
def downcase_keys
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!) }
end
array = %w(serializable_hash)
# to_xml does not call serializable_hash on 3.1
array << "to_xml" if Rails::VERSION::STRING[0,3] == "3.1"
@@ -134,6 +122,55 @@ module Devise
RUBY
end
protected
def devise_mailer
Devise.mailer
end
# This is an internal method called every time Devise needs
# to send a notification/mail. This can be overriden if you
# need to customize the e-mail delivery logic. For instance,
# if you are using a queue to deliver e-mails (delayed job,
# sidekiq, resque, etc), you must add the delivery to the queue
# just after the transaction was committed. To achieve this,
# you can override send_devise_notification to store the
# deliveries until the after_commit callback is triggered:
#
# class User
# devise :database_authenticatable, :confirmable
#
# after_commit :send_pending_notifications
#
# protected
#
# def send_devise_notification(notification)
# pending_notifications << notification
# end
#
# def send_pending_notifications
# pending_notifications.each do |n|
# devise_mailer.send(n, self).deliver
# end
# end
#
# def pending_notifications
# @pending_notifications ||= []
# end
# end
#
def send_devise_notification(notification)
devise_mailer.send(notification, self).deliver
end
def downcase_keys
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!) }
end
module ClassMethods
Devise::Models.config(self, :authentication_keys, :request_keys, :strip_whitespace_keys,
:case_insensitive_keys, :http_authenticatable, :params_authenticatable, :skip_session_storage)

View File

@@ -78,7 +78,7 @@ module Devise
@reconfirmation_required = false
generate_confirmation_token! if self.confirmation_token.blank?
self.devise_mailer.confirmation_instructions(self).deliver
send_devise_notification(:confirmation_instructions)
end
# Resend confirmation token. This method does not need to generate a new token.
@@ -125,7 +125,7 @@ module Devise
# instructions on creation. This can be overriden
# in models to map to a nice sign up e-mail.
def send_on_create_confirmation_instructions
self.devise_mailer.confirmation_instructions(self).deliver
send_devise_notification(:confirmation_instructions)
end
# Callback to overwrite if confirmation is required or not.

View File

@@ -64,7 +64,7 @@ module Devise
result = if valid_password?(current_password)
update_attributes(params, *options)
else
self.attributes = params
self.assign_attributes(params, *options)
self.valid?
self.errors.add(:current_password, current_password.blank? ? :blank : :invalid)
false

View File

@@ -38,11 +38,11 @@ module Devise
self.locked_at = Time.now.utc
if unlock_strategy_enabled?(:email)
generate_unlock_token
generate_unlock_token!
send_unlock_instructions
else
save(:validate => false)
end
save(:validate => false)
end
# Unlock a user by cleaning locked_at and failed_attempts.
@@ -60,7 +60,7 @@ module Devise
# Send unlock instructions by email
def send_unlock_instructions
self.devise_mailer.unlock_instructions(self).deliver
send_devise_notification(:unlock_instructions)
end
# Resend the unlock instructions if the user is locked.
@@ -123,6 +123,10 @@ module Devise
self.unlock_token = self.class.unlock_token
end
def generate_unlock_token!
generate_unlock_token && save(:validate => false)
end
# Tells if the lock is expired if :time unlock strategy is active
def lock_expired?
if unlock_strategy_enabled?(:time)

View File

@@ -45,7 +45,7 @@ module Devise
# Resets reset password token and send reset password instructions by email
def send_reset_password_instructions
generate_reset_password_token! if should_generate_reset_token?
self.devise_mailer.reset_password_instructions(self).deliver
send_devise_notification(:reset_password_instructions)
end
# Checks if the reset password token sent is within the limit time.

View File

@@ -1,7 +1,7 @@
begin
require "omniauth"
require "omniauth/version"
rescue LoadError => e
rescue LoadError
warn "Could not load 'omniauth'. Please ensure you have the omniauth gem >= 1.0.0 installed and listed in your Gemfile."
raise
end

View File

@@ -2,21 +2,6 @@ module Devise
module OmniAuth
module UrlHelpers
def self.define_helpers(mapping)
return unless mapping.omniauthable?
class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1
def #{mapping.name}_omniauth_authorize_path(provider, params = {})
if Devise.omniauth_configs[provider.to_sym]
script_name = request.env["SCRIPT_NAME"]
path = "\#{script_name}/#{mapping.path}/auth/\#{provider}\".squeeze("/")
path << '?' + params.to_param if params.present?
path
else
raise ArgumentError, "Could not find omniauth provider \#{provider.inspect}"
end
end
URL_HELPERS
end
def omniauth_authorize_path(resource_or_scope, *args)

View File

@@ -1,4 +1,5 @@
require "active_support/core_ext/object/try"
require "active_support/core_ext/hash/slice"
module ActionDispatch::Routing
class RouteSet #:nodoc:
@@ -236,7 +237,9 @@ module ActionDispatch::Routing
end
end
# Allow you to add authentication request from the router:
# Allow you to add authentication request from the router.
# Takes an optional scope and block to provide constraints
# on the model instance itself.
#
# authenticate do
# resources :post
@@ -246,9 +249,13 @@ module ActionDispatch::Routing
# resources :users
# end
#
def authenticate(scope=nil)
# authenticate :user, lambda {|u| u.role == "admin"} do
# root :to => "admin/dashboard#show"
# end
#
def authenticate(scope=nil, block=nil)
constraint = lambda do |request|
request.env["warden"].authenticate!(:scope => scope)
request.env["warden"].authenticate!(:scope => scope) && (block.nil? || block.call(request.env["warden"].user(scope)))
end
constraints(constraint) do
@@ -257,7 +264,8 @@ module ActionDispatch::Routing
end
# Allow you to route based on whether a scope is authenticated. You
# can optionally specify which scope.
# can optionally specify which scope and a block. The block accepts
# a model and allows extra constraints to be done on the instance.
#
# authenticated :admin do
# root :to => 'admin/dashboard#show'
@@ -267,11 +275,15 @@ module ActionDispatch::Routing
# root :to => 'dashboard#show'
# end
#
# authenticated :user, lambda {|u| u.role == "admin"} do
# root :to => "admin/dashboard#show"
# end
#
# root :to => 'landing#show'
#
def authenticated(scope=nil)
def authenticated(scope=nil, block=nil)
constraint = lambda do |request|
request.env["warden"].authenticate? :scope => scope
request.env["warden"].authenticate?(:scope => scope) && (block.nil? || block.call(request.env["warden"].user(scope)))
end
constraints(constraint) do
@@ -367,16 +379,54 @@ module ActionDispatch::Routing
:cancel => mapping.path_names[:cancel]
}
resource :registration, :only => [:new, :create, :edit, :update, :destroy], :path => mapping.path_names[:registration],
:path_names => path_names, :controller => controllers[:registrations] do
options = {
:only => [:new, :create, :edit, :update, :destroy],
:path => mapping.path_names[:registration],
:path_names => path_names,
:controller => controllers[:registrations]
}
resource :registration, options do
get :cancel
end
end
def devise_omniauth_callback(mapping, controllers) #:nodoc:
path, @scope[:path] = @scope[:path], nil
path_prefix = "/#{mapping.path}/auth".squeeze("/")
path_prefix = Devise.omniauth_path_prefix || "/#{mapping.path}/auth".squeeze("/")
set_omniauth_path_prefix!(path_prefix)
providers = Regexp.union(mapping.to.omniauth_providers.map(&:to_s))
match "#{path_prefix}/:provider",
:constraints => { :provider => providers },
:to => "#{controllers[:omniauth_callbacks]}#passthru",
:as => :omniauth_authorize
match "#{path_prefix}/:action/callback",
:constraints => { :action => providers },
:to => controllers[:omniauth_callbacks],
:as => :omniauth_callback
ensure
@scope[:path] = path
end
DEVISE_SCOPE_KEYS = [:as, :path, :module, :constraints, :defaults, :options]
def with_devise_exclusive_scope(new_path, new_as, options) #:nodoc:
old = {}
DEVISE_SCOPE_KEYS.each { |k| old[k] = @scope[k] }
new = { :as => new_as, :path => new_path, :module => nil }
new.merge!(options.slice(:constraints, :defaults, :options))
@scope.merge!(new)
yield
ensure
@scope.merge!(old)
end
def set_omniauth_path_prefix!(path_prefix) #:nodoc:
if ::OmniAuth.config.path_prefix && ::OmniAuth.config.path_prefix != path_prefix
raise "Wrong OmniAuth configuration. If you are getting this exception, it means that either:\n\n" \
"1) You are manually setting OmniAuth.config.path_prefix and it doesn't match the Devise one\n" \
@@ -385,22 +435,6 @@ module ActionDispatch::Routing
else
::OmniAuth.config.path_prefix = path_prefix
end
match "#{path_prefix}/:action/callback", :constraints => { :action => Regexp.union(mapping.to.omniauth_providers.map(&:to_s)) },
:to => controllers[:omniauth_callbacks], :as => :omniauth_callback
ensure
@scope[:path] = path
end
def with_devise_exclusive_scope(new_path, new_as, options) #:nodoc:
old_as, old_path, old_module, old_constraints, old_defaults, old_options =
*@scope.values_at(:as, :path, :module, :constraints, :defaults, :options)
@scope[:as], @scope[:path], @scope[:module], @scope[:constraints], @scope[:defaults], @scope[:options] =
new_as, new_path, nil, *options.values_at(:constraints, :defaults, :options)
yield
ensure
@scope[:as], @scope[:path], @scope[:module], @scope[:constraints], @scope[:defaults], @scope[:options] =
old_as, old_path, old_module, old_constraints, old_defaults, old_options
end
def raise_no_devise_method_error!(klass) #:nodoc:

View File

@@ -9,7 +9,7 @@ module Devise
attr_accessor :authentication_hash, :authentication_type, :password
def store?
!mapping.to.skip_session_storage.include?(authentication_type)
super && !mapping.to.skip_session_storage.include?(authentication_type)
end
def valid?
@@ -18,13 +18,24 @@ module Devise
private
# Simply invokes valid_for_authentication? with the given block and deal with the result.
# Receives a resource and check if it is valid by calling valid_for_authentication?
# An optional block that will be triggered while validating can be optionally
# given as parameter. Check Devise::Models::Authenticable.valid_for_authentication?
# for more information.
#
# In case the resource can't be validated, it will fail with the given
# unauthenticated_message.
def validate(resource, &block)
unless resource
ActiveSupport::Depreation.warn "an empty resource was given to #{self.class.name}#validate. " \
"Please ensure the resource is not nil", caller
end
result = resource && resource.valid_for_authentication?(&block)
case result
when Symbol, String
ActiveSupport::Deprecation.warn "valid_for_authentication should return a boolean value"
ActiveSupport::Deprecation.warn "valid_for_authentication? should return a boolean value"
fail!(result)
return false
end
@@ -84,8 +95,8 @@ module Devise
# Extract the appropriate subhash for authentication from params.
def params_auth_hash
params[scope]
end
params[scope]
end
# Extract a hash with attributes:values from the http params.
def http_auth_hash

View File

@@ -2,6 +2,11 @@ module Devise
module Strategies
# Base strategy for Devise. Responsible for verifying correct scope and mapping.
class Base < ::Warden::Strategies::Base
# Whenever CSRF cannot be verified, we turn off any kind of storage
def store?
!env["devise.skip_storage"]
end
# Checks if a valid scope was given for devise and find mapping based on this scope.
def mapping
@mapping ||= begin

View File

@@ -6,12 +6,11 @@ module Devise
class DatabaseAuthenticatable < Authenticatable
def authenticate!
resource = valid_password? && mapping.to.find_for_database_authentication(authentication_hash)
return fail(:invalid) unless resource
if validate(resource){ resource.valid_password?(password) }
resource.after_database_authentication
success!(resource)
elsif !halted?
fail(:invalid)
end
end
end

View File

@@ -19,11 +19,13 @@ module Devise
def authenticate!
resource = mapping.to.serialize_from_cookie(*remember_cookie)
unless resource
cookies.delete(remember_key)
return pass
end
if validate(resource)
success!(resource)
elsif !halted?
cookies.delete(remember_key)
pass
end
end

View File

@@ -16,12 +16,11 @@ module Devise
def authenticate!
resource = mapping.to.find_for_token_authentication(authentication_hash)
return fail(:invalid_token) unless resource
if validate(resource)
resource.after_token_authentication
success!(resource)
elsif !halted?
fail(:invalid_token)
end
end

View File

@@ -1,3 +1,3 @@
module Devise
VERSION = "2.1.0".freeze
VERSION = "2.1.1".freeze
end

View File

@@ -20,9 +20,12 @@ module Mongoid
def migration_data
<<RUBY
## Database authenticatable
field :email, :type => String, :null => false, :default => ""
field :encrypted_password, :type => String, :null => false, :default => ""
field :email, :type => String, :default => ""
field :encrypted_password, :type => String, :default => ""
validates_presence_of :email
validates_presence_of :encrypted_password
## Recoverable
field :reset_password_token, :type => String
field :reset_password_sent_at, :type => Time

View File

@@ -125,6 +125,9 @@ Devise.setup do |config|
# The time you want to timeout the user session without activity. After this
# time the user will be asked for credentials again. Default is 30 minutes.
# config.timeout_in = 30.minutes
# If true, expires auth token on session timeout.
# config.expire_auth_token_on_timeout = false
# ==> Configuration for :lockable
# Defines which strategy will be used to lock an account.
@@ -181,9 +184,8 @@ Devise.setup do |config|
# devise role declared in your routes (usually :user).
# config.default_scope = :user
# Configure sign_out behavior.
# Sign_out action can be scoped (i.e. /users/sign_out affects only :user scope).
# The default is true, which means any logout action will sign out all active scopes.
# Set this configuration to false if you want /users/sign_out to sign out
# only the current scope. By default, Devise signs out all scopes.
# config.sign_out_all_scopes = true
# ==> Navigation configuration
@@ -213,4 +215,18 @@ Devise.setup do |config|
# manager.intercept_401 = false
# manager.default_strategies(:scope => :user).unshift :some_external_strategy
# end
end
# ==> Mountable engine configurations
# When using Devise inside an engine, let's call it `MyEngine`, and this engine
# is mountable, there are some extra configurations to be taken into account.
# The following options are available, assuming the engine is mounted as:
#
# mount MyEngine, at: "/my_engine"
#
# The router that invoked `devise_for`, in the example above, would be:
# config.router_name = :my_engine
#
# When using omniauth, Devise cannot automatically set Omniauth path,
# so you need to do it manually. For the users scope, it would be:
# config.omniauth_path_prefix = "/my_engine/users/auth"
end

View File

@@ -3,13 +3,13 @@
<%= simple_form_for(resource, :as => resource_name, :url => confirmation_path(resource_name), :html => { :method => :post }) do |f| %>
<%= f.error_notification %>
<div class="inputs">
<div class="form-inputs">
<%= f.input :email, :required => true %>
</div>
<div class="actions">
<div class="form-actions">
<%= f.button :submit, "Resend confirmation instructions" %>
</div>
<% end %>
<%= render :partial => "devise/shared/links" %>
<%= render "devise/shared/links" %>

View File

@@ -6,14 +6,14 @@
<%= f.input :reset_password_token, :as => :hidden %>
<%= f.full_error :reset_password_token %>
<div class="inputs">
<div class="form-inputs">
<%= f.input :password, :label => "New password", :required => true %>
<%= f.input :password_confirmation, :label => "Confirm your new password", :required => true %>
</div>
<div class="actions">
<div class="form-actions">
<%= f.button :submit, "Change my password" %>
</div>
<% end %>
<%= render :partial => "devise/shared/links" %>
<%= render "devise/shared/links" %>

View File

@@ -3,13 +3,13 @@
<%= simple_form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :post }) do |f| %>
<%= f.error_notification %>
<div class="inputs">
<div class="form-inputs">
<%= f.input :email, :required => true %>
</div>
<div class="actions">
<div class="form-actions">
<%= f.button :submit, "Send me reset password instructions" %>
</div>
<% end %>
<%= render :partial => "devise/shared/links" %>
<%= render "devise/shared/links" %>

View File

@@ -3,20 +3,20 @@
<%= simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
<%= f.error_notification %>
<div class="inputs">
<div class="form-inputs">
<%= f.input :email, :required => true, :autofocus => true %>
<%= f.input :password, :autocomplete => "off", :hint => "leave it blank if you don't want to change it", :required => false %>
<%= f.input :password_confirmation, :required => false %>
<%= f.input :current_password, :hint => "we need your current password to confirm your changes", :required => true %>
</div>
<div class="actions">
<div class="form-actions">
<%= f.button :submit, "Update" %>
</div>
<% end %>
<h3>Cancel my account</h3>
<p>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), :confirm => "Are you sure?", :method => :delete %>.</p>
<p>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), :data => { :confirm => "Are you sure?" }, :method => :delete %>.</p>
<%= link_to "Back", :back %>

View File

@@ -3,15 +3,15 @@
<%= simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= f.error_notification %>
<div class="inputs">
<div class="form-inputs">
<%= f.input :email, :required => true, :autofocus => true %>
<%= f.input :password, :required => true %>
<%= f.input :password_confirmation, :required => true %>
</div>
<div class="actions">
<div class="form-actions">
<%= f.button :submit, "Sign up" %>
</div>
<% end %>
<%= render :partial => "devise/shared/links" %>
<%= render "devise/shared/links" %>

View File

@@ -1,15 +1,15 @@
<h2>Sign in</h2>
<%= simple_form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
<div class="inputs">
<div class="form-inputs">
<%= f.input :email, :required => false, :autofocus => true %>
<%= f.input :password, :required => false %>
<%= f.input :remember_me, :as => :boolean if devise_mapping.rememberable? %>
</div>
<div class="actions">
<div class="form-actions">
<%= f.button :submit, "Sign in" %>
</div>
<% end %>
<%= render :partial => "devise/shared/links" %>
<%= render "devise/shared/links" %>

View File

@@ -3,13 +3,13 @@
<%= simple_form_for(resource, :as => resource_name, :url => unlock_path(resource_name), :html => { :method => :post }) do |f| %>
<%= f.error_notification %>
<div class="inputs">
<div class="form-inputs">
<%= f.input :email, :required => true %>
</div>
<div class="actions">
<div class="form-actions">
<%= f.button :submit, "Resend unlock instructions" %>
</div>
<% end %>
<%= render :partial => "devise/shared/links" %>
<%= render "devise/shared/links" %>

View File

@@ -139,30 +139,27 @@ class ControllerAuthenticatableTest < ActionController::TestCase
assert_equal nil, @controller.instance_variable_get(:@current_admin)
end
test 'sign out clears up any signed in user by scope' do
test 'sign out logs out and clears up any signed in user by scope' do
user = User.new
@mock_warden.expects(:user).with(:scope => :user, :run_callbacks => false).returns(user)
@mock_warden.expects(:logout).with(:user).returns(true)
@mock_warden.expects(:clear_strategies_cache!).with(:scope => :user).returns(true)
@controller.instance_variable_set(:@current_user, user)
@controller.sign_out(:user)
assert_equal nil, @controller.instance_variable_get(:@current_user)
end
test 'sign out proxy to logout on warden' do
@mock_warden.expects(:user).with(:scope => :user, :run_callbacks => false).returns(true)
@mock_warden.expects(:logout).with(:user).returns(true)
@controller.sign_out(:user)
end
test 'sign out accepts a resource as argument' do
@mock_warden.expects(:user).with(:scope => :user, :run_callbacks => false).returns(true)
@mock_warden.expects(:logout).with(:user).returns(true)
@mock_warden.expects(:clear_strategies_cache!).with(:scope => :user).returns(true)
@controller.sign_out(User.new)
end
test 'sign out without args proxy to sign out all scopes' do
@mock_warden.expects(:user).times(Devise.mappings.size)
@mock_warden.expects(:logout).with().returns(true)
@mock_warden.expects(:clear_strategies_cache!).with().returns(true)
@controller.sign_out
end
@@ -232,6 +229,7 @@ class ControllerAuthenticatableTest < ActionController::TestCase
swap Devise, :sign_out_all_scopes => false do
@mock_warden.expects(:user).with(:scope => :admin, :run_callbacks => false).returns(true)
@mock_warden.expects(:logout).with(:admin).returns(true)
@mock_warden.expects(:clear_strategies_cache!).with(:scope => :admin).returns(true)
@controller.expects(:redirect_to).with(admin_root_path)
@controller.instance_eval "def after_sign_out_path_for(resource); admin_root_path; end"
@controller.sign_out_and_redirect(:admin)
@@ -242,6 +240,7 @@ class ControllerAuthenticatableTest < ActionController::TestCase
swap Devise, :sign_out_all_scopes => true do
@mock_warden.expects(:user).times(Devise.mappings.size)
@mock_warden.expects(:logout).with().returns(true)
@mock_warden.expects(:clear_strategies_cache!).with().returns(true)
@controller.expects(:redirect_to).with(admin_root_path)
@controller.instance_eval "def after_sign_out_path_for(resource); admin_root_path; end"
@controller.sign_out_and_redirect(:admin)

View File

@@ -4,6 +4,15 @@ class SessionsControllerTest < ActionController::TestCase
tests Devise::SessionsController
include Devise::TestHelpers
test "#create works even with scoped views" do
swap Devise, :scoped_views => true do
request.env["devise.mapping"] = Devise.mappings[:user]
post :create
assert_equal 200, @response.status
assert_template "users/sessions/new"
end
end
test "#create doesn't raise exception after Warden authentication fails when TestHelpers included" do
request.env["devise.mapping"] = Devise.mappings[:user]
post :create, :user => {
@@ -13,23 +22,21 @@ 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 }
if defined?(ActiveRecord) && 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

View File

@@ -75,80 +75,6 @@ class AuthenticationSanityTest < ActionController::IntegrationTest
assert_not warden.authenticated?(:admin)
end
test 'not signed in as admin should not be able to access private route restricted to admins' do
get private_path
assert_redirected_to new_admin_session_path
assert_not warden.authenticated?(:admin)
end
test 'signed in as user should not be able to access private route restricted to admins' do
sign_in_as_user
assert warden.authenticated?(:user)
assert_not warden.authenticated?(:admin)
get private_path
assert_redirected_to new_admin_session_path
end
test 'signed in as admin should be able to access private route restricted to admins' do
sign_in_as_admin
assert warden.authenticated?(:admin)
assert_not warden.authenticated?(:user)
get private_path
assert_response :success
assert_template 'home/private'
assert_contain 'Private!'
end
test 'signed in as admin should get admin dashboard' do
sign_in_as_admin
assert warden.authenticated?(:admin)
assert_not warden.authenticated?(:user)
get dashboard_path
assert_response :success
assert_template 'home/admin'
assert_contain 'Admin dashboard'
end
test 'signed in as user should get user dashboard' do
sign_in_as_user
assert warden.authenticated?(:user)
assert_not warden.authenticated?(:admin)
get dashboard_path
assert_response :success
assert_template 'home/user'
assert_contain 'User dashboard'
end
test 'not signed in should get no dashboard' do
assert_raises ActionController::RoutingError do
get dashboard_path
end
end
test 'signed in user should not see unauthenticated page' do
sign_in_as_user
assert warden.authenticated?(:user)
assert_not warden.authenticated?(:admin)
assert_raises ActionController::RoutingError do
get join_path
end
end
test 'not signed in users should see unautheticated page' do
get join_path
assert_response :success
assert_template 'home/join'
assert_contain 'Join'
end
test 'signed in as user should not be able to access admins actions' do
sign_in_as_user
assert warden.authenticated?(:user)
@@ -208,6 +134,126 @@ class AuthenticationSanityTest < ActionController::IntegrationTest
end
end
class AuthenticationRoutesRestrictions < ActionController::IntegrationTest
test 'not signed in should not be able to access private route (authenticate denied)' do
get private_path
assert_redirected_to new_admin_session_path
assert_not warden.authenticated?(:admin)
end
test 'signed in as user should not be able to access private route restricted to admins (authenticate denied)' do
sign_in_as_user
assert warden.authenticated?(:user)
assert_not warden.authenticated?(:admin)
get private_path
assert_redirected_to new_admin_session_path
end
test 'signed in as admin should be able to access private route restricted to admins (authenticate accepted)' do
sign_in_as_admin
assert warden.authenticated?(:admin)
assert_not warden.authenticated?(:user)
get private_path
assert_response :success
assert_template 'home/private'
assert_contain 'Private!'
end
test 'signed in as inactive admin should not be able to access private/active route restricted to active admins (authenticate denied)' do
sign_in_as_admin(:active => false)
assert warden.authenticated?(:admin)
assert_not warden.authenticated?(:user)
assert_raises ActionController::RoutingError do
get "/private/active"
end
end
test 'signed in as active admin should be able to access private/active route restricted to active admins (authenticate accepted)' do
sign_in_as_admin(:active => true)
assert warden.authenticated?(:admin)
assert_not warden.authenticated?(:user)
get private_active_path
assert_response :success
assert_template 'home/private'
assert_contain 'Private!'
end
test 'signed in as admin should get admin dashboard (authenticated accepted)' do
sign_in_as_admin
assert warden.authenticated?(:admin)
assert_not warden.authenticated?(:user)
get dashboard_path
assert_response :success
assert_template 'home/admin'
assert_contain 'Admin dashboard'
end
test 'signed in as user should get user dashboard (authenticated accepted)' do
sign_in_as_user
assert warden.authenticated?(:user)
assert_not warden.authenticated?(:admin)
get dashboard_path
assert_response :success
assert_template 'home/user'
assert_contain 'User dashboard'
end
test 'not signed in should get no dashboard (authenticated denied)' do
assert_raises ActionController::RoutingError do
get dashboard_path
end
end
test 'signed in as inactive admin should not be able to access dashboard/active route restricted to active admins (authenticated denied)' do
sign_in_as_admin(:active => false)
assert warden.authenticated?(:admin)
assert_not warden.authenticated?(:user)
assert_raises ActionController::RoutingError do
get "/dashboard/active"
end
end
test 'signed in as active admin should be able to access dashboard/active route restricted to active admins (authenticated accepted)' do
sign_in_as_admin(:active => true)
assert warden.authenticated?(:admin)
assert_not warden.authenticated?(:user)
get dashboard_active_path
assert_response :success
assert_template 'home/admin_dashboard'
assert_contain 'Admin dashboard'
end
test 'signed in user should not see unauthenticated page (unauthenticated denied)' do
sign_in_as_user
assert warden.authenticated?(:user)
assert_not warden.authenticated?(:admin)
assert_raises ActionController::RoutingError do
get join_path
end
end
test 'not signed in users should see unautheticated page (unauthenticated accepted)' do
get join_path
assert_response :success
assert_template 'home/join'
assert_contain 'Join'
end
end
class AuthenticationRedirectTest < ActionController::IntegrationTest
test 'redirect from warden shows sign in or sign up message' do
get admins_path

View File

@@ -126,6 +126,12 @@ class PasswordTest < ActionController::IntegrationTest
assert warden.authenticated?(:user)
end
test 'not authenticated user without a reset password token should not be able to visit the page' do
get edit_user_password_path
assert_response :redirect
assert_redirected_to "/users/sign_in"
end
test 'not authenticated user with invalid reset password token should not be able to change his password' do
user = create_user
reset_password :reset_password_token => 'invalid_reset_password'

View File

@@ -25,7 +25,7 @@ class SessionTimeoutTest < ActionController::IntegrationTest
assert_equal old_last_request, last_request_at
end
test 'not time out user session before default limit time' do
test 'does not time out user session before default limit time' do
sign_in_as_user
assert_response :success
assert warden.authenticated?(:user)
@@ -53,12 +53,38 @@ class SessionTimeoutTest < ActionController::IntegrationTest
assert_response :redirect
assert_redirected_to root_path
follow_redirect!
assert_contain 'Signed out successfully'
end
test 'time out is not triggered on sign in' do
user = sign_in_as_user
get expire_user_path(user)
post "/users/sign_in", :email => user.email, :password => "123456"
assert_response :redirect
follow_redirect!
assert_contain 'You are signed in'
end
test 'admin does not explode on time out' do
admin = sign_in_as_admin
get expire_admin_path(admin)
Admin.send :define_method, :reset_authentication_token! do
nil
end
begin
get admins_path
assert_redirected_to admins_path
assert_not warden.authenticated?(:admin)
ensure
Admin.send(:remove_method, :reset_authentication_token!)
end
end
test 'user configured timeout limit' do
swap Devise, :timeout_in => 8.minutes do
user = sign_in_as_user

View File

@@ -97,7 +97,7 @@ class RecoverableTest < ActiveSupport::TestCase
test 'should reset reset_password_token before send the reset instructions email' do
user = create_user
token = user.reset_password_token
reset_password_user = User.send_reset_password_instructions(:email => user.email)
User.send_reset_password_instructions(:email => user.email)
assert_not_equal token, user.reload.reset_password_token
end
@@ -142,7 +142,7 @@ class RecoverableTest < ActiveSupport::TestCase
old_password = user.password
user.send :generate_reset_password_token!
reset_password_user = User.reset_password_by_token(
User.reset_password_by_token(
:reset_password_token => user.reset_password_token,
:password => 'new_password',
:password_confirmation => 'new_password'
@@ -202,4 +202,4 @@ class RecoverableTest < ActiveSupport::TestCase
:reset_password_token
]
end
end
end

View File

@@ -25,7 +25,7 @@ end
class ActiveRecordTest < ActiveSupport::TestCase
def include_module?(klass, mod)
klass.devise_modules.include?(mod) &&
klass.included_modules.include?(Devise::Models::const_get(mod.to_s.classify))
klass.included_modules.include?(Devise::Models::const_get(mod.to_s.classify))
end
def assert_include_modules(klass, *modules)
@@ -153,13 +153,13 @@ class CheckFieldsTest < ActiveSupport::TestCase
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
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
driver = Class.new do
extend Devise::Models
def self.before_validation(instance)

View File

@@ -30,7 +30,7 @@ class OmniAuthRoutesTest < ActionController::TestCase
test 'should generate authorization path' do
assert_match "/users/auth/facebook", @controller.omniauth_authorize_path(:user, :facebook)
assert_raise ArgumentError do
assert_raise ActionController::RoutingError do
@controller.omniauth_authorize_path(:user, :github)
end
end
@@ -48,11 +48,4 @@ class OmniAuthRoutesTest < ActionController::TestCase
assert_equal "/users/auth/openid",
@controller.omniauth_authorize_path(:user, :openid)
end
test 'should set script name in the path if present' do
@request.env['SCRIPT_NAME'] = '/q'
assert_equal "/q/users/auth/facebook",
@controller.omniauth_authorize_path(:user, :facebook)
end
end

View File

@@ -3,4 +3,9 @@ class AdminsController < ApplicationController
def index
end
def expire
admin_session['last_request_at'] = 31.minutes.ago.utc
render :text => 'Admin will be expired on next request'
end
end

View File

@@ -9,7 +9,9 @@ Rails.application.routes.draw do
end
end
resources :admins, :only => [:index]
resources :admins, :only => [:index] do
get :expire, :on => :member
end
# Users scope
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
@@ -30,10 +32,18 @@ Rails.application.routes.draw do
match "/private", :to => "home#private", :as => :private
end
authenticate(:admin, lambda { |admin| admin.active? }) do
match "/private/active", :to => "home#private", :as => :private_active
end
authenticated :admin do
match "/dashboard", :to => "home#admin_dashboard"
end
authenticated :admin, lambda { |admin| admin.active? } do
match "/dashboard/active", :to => "home#admin_dashboard"
end
authenticated do
match "/dashboard", :to => "home#user_dashboard"
end

View File

@@ -60,6 +60,9 @@ class CreateTables < ActiveRecord::Migration
## Lockable
t.datetime :locked_at
## Attribute for testing route blocks
t.boolean :active, :default => false
t.timestamps
end
end

View File

@@ -15,14 +15,14 @@ class ActiveSupport::TestCase
alias :assert_present :assert_not_blank
def assert_email_sent(address = nil, &block)
assert_difference('ActionMailer::Base.deliveries.size') { yield }
assert_difference('ActionMailer::Base.deliveries.size', &block)
if address.present?
assert_equal address, ActionMailer::Base.deliveries.last['to'].to_s
end
end
def assert_email_not_sent(&block)
assert_no_difference('ActionMailer::Base.deliveries.size') { yield }
assert_no_difference('ActionMailer::Base.deliveries.size', &block)
end
def assert_same_content(result, expected)
@@ -32,11 +32,9 @@ class ActiveSupport::TestCase
end
end
def assert_raise_with_message(exception_klass, message)
exception = assert_raise exception_klass do
yield
end
assert_equal exception.message, message, "The expected message was #{message} but your exception throwed #{exception.message}"
def assert_raise_with_message(exception_klass, message, &block)
exception = assert_raise exception_klass, &block
assert_equal exception.message, message,
"The expected message was #{message} but your exception throwed #{exception.message}"
end
end

View File

@@ -24,7 +24,8 @@ class ActionDispatch::IntegrationTest
@admin ||= begin
admin = Admin.create!(
:email => options[:email] || 'admin@test.com',
:password => '123456', :password_confirmation => '123456'
:password => '123456', :password_confirmation => '123456',
:active => options[:active]
)
admin.confirm! unless options[:confirm] == false
admin