mirror of
https://github.com/heartcombo/devise.git
synced 2026-01-09 23:58:06 -05:00
Compare commits
129 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ce5843888 | ||
|
|
1210fd4b77 | ||
|
|
da510508bb | ||
|
|
02ae0c22ef | ||
|
|
edee511cd1 | ||
|
|
fbd35ec332 | ||
|
|
30b35e3727 | ||
|
|
330cafd3d2 | ||
|
|
fe9024218c | ||
|
|
0c9bd3259e | ||
|
|
b23e2e807a | ||
|
|
7876acf960 | ||
|
|
74166e224b | ||
|
|
cb778d033f | ||
|
|
1bf7da148a | ||
|
|
d58a72ee32 | ||
|
|
15d195d2f0 | ||
|
|
4f093574da | ||
|
|
64457e2c1f | ||
|
|
3f4fb1a769 | ||
|
|
1982ad9f57 | ||
|
|
569d205ca7 | ||
|
|
63b72cd512 | ||
|
|
bb89ca4865 | ||
|
|
307fe6cb60 | ||
|
|
fe2d7b5ffe | ||
|
|
d445db9e5e | ||
|
|
e4cae200f4 | ||
|
|
a535b047ff | ||
|
|
aa81df261c | ||
|
|
0cc900e7cf | ||
|
|
9bff1cf658 | ||
|
|
305059f573 | ||
|
|
392e664036 | ||
|
|
43a3431c3e | ||
|
|
930d5874ca | ||
|
|
3375985ab8 | ||
|
|
2e43944567 | ||
|
|
352edc024b | ||
|
|
b5e289c9a8 | ||
|
|
42d002702c | ||
|
|
6bd65209d5 | ||
|
|
970457f2c2 | ||
|
|
bbaaefa995 | ||
|
|
fdf6a48a7e | ||
|
|
7113beac81 | ||
|
|
0c5acc6f38 | ||
|
|
dd721f1857 | ||
|
|
ae75186c52 | ||
|
|
ca293d17ba | ||
|
|
add8f8a203 | ||
|
|
6a6ed6702e | ||
|
|
2d0f887ba7 | ||
|
|
3109b0924b | ||
|
|
bbafb70655 | ||
|
|
aac9c40cba | ||
|
|
f964ea526b | ||
|
|
bca43a7576 | ||
|
|
8440ed0101 | ||
|
|
cb5e0c4a7b | ||
|
|
0287d8cc80 | ||
|
|
a48c815dc8 | ||
|
|
f332d7e932 | ||
|
|
a14b833581 | ||
|
|
c9fe8885f9 | ||
|
|
e1c3b915e7 | ||
|
|
f06bed279a | ||
|
|
3fd206c591 | ||
|
|
7a1852e9f5 | ||
|
|
76a4800446 | ||
|
|
5f93d8355c | ||
|
|
1f8909458f | ||
|
|
68f699bfd4 | ||
|
|
0615c0a0a4 | ||
|
|
c78bb68c66 | ||
|
|
d018970c4b | ||
|
|
971f68f97d | ||
|
|
4207c2321f | ||
|
|
54dc82ad25 | ||
|
|
fa239b984a | ||
|
|
692f7b27ff | ||
|
|
258eb1c7e6 | ||
|
|
aa61034d40 | ||
|
|
42f2196d01 | ||
|
|
d87521723d | ||
|
|
6e91edd5e3 | ||
|
|
fb4ec6e9da | ||
|
|
7ff0231ab7 | ||
|
|
3f086656aa | ||
|
|
55cb7195b8 | ||
|
|
555435e6fe | ||
|
|
88d4aca2c4 | ||
|
|
038eb321d4 | ||
|
|
c8c84c77c6 | ||
|
|
8f20b13f84 | ||
|
|
af1295284c | ||
|
|
1b43cb5203 | ||
|
|
b34f456096 | ||
|
|
e95eb93eb7 | ||
|
|
1a2590dc08 | ||
|
|
1cdb02bd54 | ||
|
|
7759c8b3f3 | ||
|
|
b32883a7c5 | ||
|
|
27051cb2fe | ||
|
|
e8e3df3891 | ||
|
|
2561cd4eac | ||
|
|
146090f86e | ||
|
|
4519364eaf | ||
|
|
f56c588a6a | ||
|
|
379d8c69a5 | ||
|
|
13e8bc22e3 | ||
|
|
c27bc21af9 | ||
|
|
a156576ce9 | ||
|
|
b942520dc4 | ||
|
|
a2e92a2ef2 | ||
|
|
60be68436b | ||
|
|
fe4eaf2d12 | ||
|
|
845c186f48 | ||
|
|
9f832d2cb2 | ||
|
|
a23a52b2f7 | ||
|
|
7ed1fb116f | ||
|
|
b50fd1a72e | ||
|
|
2305e8f8cf | ||
|
|
f2f9232b89 | ||
|
|
cb62597afa | ||
|
|
089c316f37 | ||
|
|
ec5bfe9119 | ||
|
|
912969b5a0 | ||
|
|
fe5ef25614 |
1
.travis.yml
Normal file
1
.travis.yml
Normal file
@@ -0,0 +1 @@
|
||||
script: "rake test"
|
||||
@@ -1,3 +1,45 @@
|
||||
== 1.2.1
|
||||
|
||||
* enhancements
|
||||
* better upgrade steps
|
||||
|
||||
== 1.2.0
|
||||
|
||||
* bug fix
|
||||
* Properly ignore path prefix on omniauthable
|
||||
* Faster uniqueness queries
|
||||
* Rename active? to active_for_authentication? to avoid conflicts
|
||||
|
||||
== 1.2.rc2
|
||||
|
||||
* enhancements
|
||||
* Make friendly_token 20 chars long
|
||||
* Use secure_compare
|
||||
|
||||
* bug fix
|
||||
* Fix an issue causing infinite redirects in production
|
||||
* rails g destroy works properly with devise generators (by github.com/andmej)
|
||||
* before_failure callbacks should work on test helpers (by github.com/twinge)
|
||||
* rememberable cookie now is httponly by default (by github.com/JamesFerguson)
|
||||
* Add missing confirmation_keys (by github.com/JohnPlummer)
|
||||
* Ensure after_* hooks are called on RegistrationsController
|
||||
* When using database_authenticatable Devise will now only create an email field when appropriate (if using default authentication_keys or custom authentication_keys with email included)
|
||||
* Ensure stateless token does not trigger timeout (by github.com/pixelauthority)
|
||||
* Implement handle_unverified_request for Rails 3.0.4 compatibility and improve FailureApp reliance on symbols
|
||||
* Consider namespaces while generating routes
|
||||
* Custom failure apps no longer ignored in test mode (by github.com/jaghion)
|
||||
* Do not depend on ActiveModel::Dirty
|
||||
* Manual sign_in now triggers remember token
|
||||
* Be sure to halt strategies on failures
|
||||
* Consider SCRIPT_NAME on Omniauth paths
|
||||
* Reset failed attempts when lock is expired
|
||||
* Ensure there is no Mongoid injection
|
||||
|
||||
* deprecations
|
||||
* Deprecated anybody_signed_in? in favor of signed_in? (by github.com/gavinhughes)
|
||||
* Removed --haml and --slim view templates
|
||||
* Devise::OmniAuth helpers were deprecated and removed in favor of Omniauth.config.test_mode
|
||||
|
||||
== 1.2.rc
|
||||
|
||||
* deprecations
|
||||
@@ -30,12 +72,26 @@
|
||||
* bugfix
|
||||
* after_sign_in_path_for always receives a resource
|
||||
* Do not execute Warden::Callbacks on Devise::TestHelpers (by github.com/sgronblo)
|
||||
* Password recovery and account unlocking takes into account authentication keys (by github.com/RStankov)
|
||||
* Allow password recovery and account unlocking to change used keys (by github.com/RStankov)
|
||||
* FailureApp now properly handles nil request.format
|
||||
* Fix a bug causing FailureApp to return with HTTP Auth Headers for IE7
|
||||
* Ensure namespaces has proper scoped views
|
||||
* Ensure Devise does not set empty flash messages (by github.com/sxross)
|
||||
|
||||
== 1.1.6
|
||||
|
||||
* Use a more secure e-mail regexp
|
||||
* Implement Rails 3.0.4 handle unverified request
|
||||
* Use secure_compare to compare passwords
|
||||
|
||||
== 1.1.5
|
||||
|
||||
* bugfix
|
||||
* Ensure to convert keys on indifferent hash
|
||||
|
||||
* defaults
|
||||
* Set config.http_authenticatable to false to avoid confusion
|
||||
|
||||
== 1.1.4
|
||||
|
||||
* bugfix
|
||||
|
||||
8
Gemfile
8
Gemfile
@@ -2,9 +2,9 @@ source "http://rubygems.org"
|
||||
|
||||
gemspec
|
||||
|
||||
gem "rails", "~> 3.0.0"
|
||||
gem "oa-oauth", :require => "omniauth/oauth"
|
||||
gem "oa-openid", :require => "omniauth/openid"
|
||||
gem "rails", "~> 3.0.4"
|
||||
gem "oa-oauth", '~> 0.2.0', :require => "omniauth/oauth"
|
||||
gem "oa-openid", '~> 0.2.0', :require => "omniauth/openid"
|
||||
|
||||
group :test do
|
||||
gem "webrat", "0.7.2", :require => false
|
||||
@@ -24,6 +24,6 @@ platforms :ruby do
|
||||
group :mongoid do
|
||||
gem "mongo", "1.1.2"
|
||||
gem "mongoid", "2.0.0.beta.20"
|
||||
gem "bson_ext", "1.1.2"
|
||||
gem "bson_ext", "1.2.1"
|
||||
end
|
||||
end
|
||||
|
||||
132
Gemfile.lock
132
Gemfile.lock
@@ -1,69 +1,68 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
devise (1.2.rc)
|
||||
devise (1.2.0)
|
||||
bcrypt-ruby (~> 2.1.2)
|
||||
orm_adapter (~> 0.0.2)
|
||||
warden (~> 1.0.2)
|
||||
orm_adapter (~> 0.0.3)
|
||||
warden (~> 1.0.3)
|
||||
|
||||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
abstract (1.0.0)
|
||||
actionmailer (3.0.3)
|
||||
actionpack (= 3.0.3)
|
||||
mail (~> 2.2.9)
|
||||
actionpack (3.0.3)
|
||||
activemodel (= 3.0.3)
|
||||
activesupport (= 3.0.3)
|
||||
actionmailer (3.0.4)
|
||||
actionpack (= 3.0.4)
|
||||
mail (~> 2.2.15)
|
||||
actionpack (3.0.4)
|
||||
activemodel (= 3.0.4)
|
||||
activesupport (= 3.0.4)
|
||||
builder (~> 2.1.2)
|
||||
erubis (~> 2.6.6)
|
||||
i18n (~> 0.4)
|
||||
rack (~> 1.2.1)
|
||||
rack-mount (~> 0.6.13)
|
||||
rack-test (~> 0.5.6)
|
||||
rack-test (~> 0.5.7)
|
||||
tzinfo (~> 0.3.23)
|
||||
activemodel (3.0.3)
|
||||
activesupport (= 3.0.3)
|
||||
activemodel (3.0.4)
|
||||
activesupport (= 3.0.4)
|
||||
builder (~> 2.1.2)
|
||||
i18n (~> 0.4)
|
||||
activerecord (3.0.3)
|
||||
activemodel (= 3.0.3)
|
||||
activesupport (= 3.0.3)
|
||||
activerecord (3.0.4)
|
||||
activemodel (= 3.0.4)
|
||||
activesupport (= 3.0.4)
|
||||
arel (~> 2.0.2)
|
||||
tzinfo (~> 0.3.23)
|
||||
activerecord-jdbc-adapter (1.0.2-java)
|
||||
activerecord-jdbcsqlite3-adapter (1.0.2-java)
|
||||
activerecord-jdbc-adapter (= 1.0.2)
|
||||
activerecord-jdbc-adapter (1.1.1)
|
||||
activerecord-jdbcsqlite3-adapter (1.1.1)
|
||||
activerecord-jdbc-adapter (= 1.1.1)
|
||||
jdbc-sqlite3 (~> 3.6.0)
|
||||
activeresource (3.0.3)
|
||||
activemodel (= 3.0.3)
|
||||
activesupport (= 3.0.3)
|
||||
activesupport (3.0.3)
|
||||
addressable (2.2.2)
|
||||
arel (2.0.4)
|
||||
bcrypt-ruby (2.1.2)
|
||||
bson (1.1.2)
|
||||
bson_ext (1.1.2)
|
||||
activeresource (3.0.4)
|
||||
activemodel (= 3.0.4)
|
||||
activesupport (= 3.0.4)
|
||||
activesupport (3.0.4)
|
||||
addressable (2.2.4)
|
||||
arel (2.0.8)
|
||||
bcrypt-ruby (2.1.4)
|
||||
bson (1.2.1)
|
||||
bson_ext (1.2.1)
|
||||
builder (2.1.2)
|
||||
columnize (0.3.2)
|
||||
erubis (2.6.6)
|
||||
abstract (>= 1.0.0)
|
||||
faraday (0.5.2)
|
||||
addressable (~> 2.2.2)
|
||||
multipart-post (~> 1.0.1)
|
||||
faraday (0.5.7)
|
||||
addressable (~> 2.2.4)
|
||||
multipart-post (~> 1.1.0)
|
||||
rack (>= 1.1.0, < 2)
|
||||
i18n (0.4.2)
|
||||
i18n (0.5.0)
|
||||
jdbc-sqlite3 (3.6.14.2.056-java)
|
||||
linecache (0.43)
|
||||
mail (2.2.10)
|
||||
mail (2.2.15)
|
||||
activesupport (>= 2.3.6)
|
||||
i18n (~> 0.4.1)
|
||||
i18n (>= 0.4.0)
|
||||
mime-types (~> 1.16)
|
||||
treetop (~> 1.4.8)
|
||||
mime-types (1.16)
|
||||
mocha (0.9.9)
|
||||
rake
|
||||
mocha (0.9.12)
|
||||
mongo (1.1.2)
|
||||
bson (>= 1.1.1)
|
||||
mongoid (2.0.0.beta.20)
|
||||
@@ -72,27 +71,27 @@ GEM
|
||||
tzinfo (~> 0.3.22)
|
||||
will_paginate (~> 3.0.pre)
|
||||
multi_json (0.0.5)
|
||||
multipart-post (1.0.1)
|
||||
nokogiri (1.4.3.1)
|
||||
nokogiri (1.4.3.1-java)
|
||||
multipart-post (1.1.0)
|
||||
nokogiri (1.4.4)
|
||||
nokogiri (1.4.4-java)
|
||||
weakling (>= 0.0.3)
|
||||
oa-core (0.1.6)
|
||||
oa-core (0.2.0)
|
||||
rack (~> 1.1)
|
||||
oa-oauth (0.1.6)
|
||||
oa-oauth (0.2.0)
|
||||
multi_json (~> 0.0.2)
|
||||
nokogiri (~> 1.4.2)
|
||||
oa-core (= 0.1.6)
|
||||
oa-core (= 0.2.0)
|
||||
oauth (~> 0.4.0)
|
||||
oauth2 (~> 0.1.0)
|
||||
oa-openid (0.1.6)
|
||||
oa-core (= 0.1.6)
|
||||
oauth2 (~> 0.1.1)
|
||||
oa-openid (0.2.0)
|
||||
oa-core (= 0.2.0)
|
||||
rack-openid (~> 1.2.0)
|
||||
ruby-openid-apps-discovery
|
||||
oauth (0.4.4)
|
||||
oauth2 (0.1.0)
|
||||
oauth2 (0.1.1)
|
||||
faraday (~> 0.5.0)
|
||||
multi_json (~> 0.0.4)
|
||||
orm_adapter (0.0.3)
|
||||
orm_adapter (0.0.4)
|
||||
polyglot (0.3.1)
|
||||
rack (1.2.1)
|
||||
rack-mount (0.6.13)
|
||||
@@ -100,19 +99,19 @@ GEM
|
||||
rack-openid (1.2.0)
|
||||
rack (>= 1.1.0)
|
||||
ruby-openid (>= 2.1.8)
|
||||
rack-test (0.5.6)
|
||||
rack-test (0.5.7)
|
||||
rack (>= 1.0)
|
||||
rails (3.0.3)
|
||||
actionmailer (= 3.0.3)
|
||||
actionpack (= 3.0.3)
|
||||
activerecord (= 3.0.3)
|
||||
activeresource (= 3.0.3)
|
||||
activesupport (= 3.0.3)
|
||||
rails (3.0.4)
|
||||
actionmailer (= 3.0.4)
|
||||
actionpack (= 3.0.4)
|
||||
activerecord (= 3.0.4)
|
||||
activeresource (= 3.0.4)
|
||||
activesupport (= 3.0.4)
|
||||
bundler (~> 1.0)
|
||||
railties (= 3.0.3)
|
||||
railties (3.0.3)
|
||||
actionpack (= 3.0.3)
|
||||
activesupport (= 3.0.3)
|
||||
railties (= 3.0.4)
|
||||
railties (3.0.4)
|
||||
actionpack (= 3.0.4)
|
||||
activesupport (= 3.0.4)
|
||||
rake (>= 0.8.7)
|
||||
thor (~> 0.14.4)
|
||||
rake (0.8.7)
|
||||
@@ -124,12 +123,14 @@ GEM
|
||||
ruby-openid (2.1.8)
|
||||
ruby-openid-apps-discovery (1.2.0)
|
||||
ruby-openid (>= 2.1.7)
|
||||
sqlite3-ruby (1.3.2)
|
||||
sqlite3 (1.3.3)
|
||||
sqlite3-ruby (1.3.3)
|
||||
sqlite3 (>= 1.3.3)
|
||||
thor (0.14.6)
|
||||
treetop (1.4.9)
|
||||
polyglot (>= 0.3.1)
|
||||
tzinfo (0.3.23)
|
||||
warden (1.0.2)
|
||||
tzinfo (0.3.24)
|
||||
warden (1.0.3)
|
||||
rack (>= 1.0.0)
|
||||
weakling (0.0.4-java)
|
||||
webrat (0.7.2)
|
||||
@@ -144,17 +145,14 @@ PLATFORMS
|
||||
|
||||
DEPENDENCIES
|
||||
activerecord-jdbcsqlite3-adapter
|
||||
bcrypt-ruby (~> 2.1.2)
|
||||
bson_ext (= 1.1.2)
|
||||
bson_ext (= 1.2.1)
|
||||
devise!
|
||||
mocha
|
||||
mongo (= 1.1.2)
|
||||
mongoid (= 2.0.0.beta.20)
|
||||
oa-oauth
|
||||
oa-openid
|
||||
orm_adapter (~> 0.0.2)
|
||||
rails (~> 3.0.0)
|
||||
oa-oauth (~> 0.2.0)
|
||||
oa-openid (~> 0.2.0)
|
||||
rails (~> 3.0.4)
|
||||
ruby-debug (>= 0.10.3)
|
||||
sqlite3-ruby
|
||||
warden (~> 1.0.2)
|
||||
webrat (= 0.7.2)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright 2009 Plataforma Tecnologia. http://blog.plataformatec.com.br
|
||||
Copyright 2009-2011 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
|
||||
|
||||
27
README.rdoc
27
README.rdoc
@@ -9,7 +9,7 @@ Devise is a flexible authentication solution for Rails based on Warden. It:
|
||||
|
||||
It's composed of 12 modules:
|
||||
|
||||
* Database Authenticatable: encrypts and stores a password in the database to validate the authenticity of an user while signing in. The authentication can be done both through POST requests or HTTP Basic Authentication.
|
||||
* 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.
|
||||
@@ -20,11 +20,11 @@ It's composed of 12 modules:
|
||||
* 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: allows support of other authentication mechanisms besides Bcrypt (the default).
|
||||
* Encryptable: adds support of other authentication mechanisms besides the built-in Bcrypt (the default).
|
||||
|
||||
== Information
|
||||
|
||||
=== The Devise Wiki
|
||||
=== The Devise wiki
|
||||
|
||||
The Devise Wiki has lots of additional information about Devise including many "how-to" articles and answers to the most frequently asked questions. Please browse the Wiki after finishing this README:
|
||||
|
||||
@@ -36,11 +36,11 @@ If you discover a problem with Devise, we would like to know about it. However,
|
||||
|
||||
http://github.com/plataformatec/devise/wiki/Bug-reports
|
||||
|
||||
If you found a security bug, do *NOT* use the GitHub Issue tracker. Send private GitHub message or email to the maintainers listed in 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.
|
||||
|
||||
=== Google Group
|
||||
=== Mailing list
|
||||
|
||||
If you have any questions, comments, or concerns please use the Google Group instead of the GitHub Issues tracker:
|
||||
If you have any questions, comments, or concerns, please use the Google Group instead of the GitHub issue tracker:
|
||||
|
||||
http://groups.google.com/group/plataformatec-devise
|
||||
|
||||
@@ -52,7 +52,7 @@ http://rubydoc.info/github/plataformatec/devise/master/frames
|
||||
|
||||
If you need to use Devise with Rails 2.3, you can always run `gem server` from the command line after you install the gem to access the old documentation.
|
||||
|
||||
=== Example Applications
|
||||
=== Example applications
|
||||
|
||||
There are a few example applications available on GitHub that demonstrate various features of Devise with different versions of Rails. You can view them here:
|
||||
|
||||
@@ -70,6 +70,8 @@ We hope that you will consider contributing to Devise. Please read this short ov
|
||||
|
||||
http://github.com/plataformatec/devise/wiki/Contributing
|
||||
|
||||
You will usually want to write tests for your changes. To run the test suite, `cd` into Devise's top-level directory and run `bundle install` and `rake`. For the tests to pass, you will need to have a MongoDB server (version 1.6 or newer) running on your system.
|
||||
|
||||
== Installation
|
||||
|
||||
You can use the latest Rails 3 gem with the latest Devise gem:
|
||||
@@ -88,6 +90,15 @@ Replace MODEL by the class name you want to add devise, like User, Admin, etc. T
|
||||
|
||||
Support for Rails 2.3.x can be found by installing Devise 1.0.x from the v1.0 branch.
|
||||
|
||||
== Starting with Rails?
|
||||
|
||||
If you are building your first Rails application, we recommend you to *not* use Devise. Devise requires a good understanding of the Rails Framework. In such cases, we advise you to start a simple authentication system from scratch, today we have two resources:
|
||||
|
||||
* Michael Hartl's online book: http://railstutorial.org/chapters/modeling-and-viewing-users-two#top
|
||||
* Ryan Bates' Railscast: http://railscasts.com/episodes/250-authentication-from-scratch
|
||||
|
||||
Once you have solidified you understanding of Rails and authentication mechanisms, we assure you Devise will be very pleasant to work with. :)
|
||||
|
||||
== Getting started
|
||||
|
||||
This is a walkthrough with all steps you need to setup a devise resource, including model, migration, route files, and optional configuration.
|
||||
@@ -201,8 +212,6 @@ Since Devise is an engine, all its views are packaged inside the gem. These view
|
||||
|
||||
rails generate devise:views
|
||||
|
||||
If you are using HAML, you will need hpricot installed to convert Devise views to HAML.
|
||||
|
||||
If you have more than one role in your application (such as "User" and "Admin"), you will notice that Devise uses the same views for all roles. Fortunately, Devise offers an easy way to customize views. All you need to do is set "config.scoped_views = true" inside "config/initializers/devise.rb".
|
||||
|
||||
After doing so, you will be able to have views based on the role like "users/sessions/new" and "admins/sessions/new". If no view is found within the scope, Devise will use the default view at "devise/sessions/new". You can also use the generator to generate scoped views:
|
||||
|
||||
29
Rakefile
29
Rakefile
@@ -1,9 +1,7 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'rake'
|
||||
require 'rake/testtask'
|
||||
require 'rake/rdoctask'
|
||||
require File.join(File.dirname(__FILE__), 'lib', 'devise', 'version')
|
||||
|
||||
desc 'Default: run tests for all ORMs.'
|
||||
task :default => :pre_commit
|
||||
@@ -12,7 +10,9 @@ desc 'Run Devise tests for all ORMs.'
|
||||
task :pre_commit do
|
||||
Dir[File.join(File.dirname(__FILE__), 'test', 'orm', '*.rb')].each do |file|
|
||||
orm = File.basename(file).split(".").first
|
||||
system "rake test DEVISE_ORM=#{orm}"
|
||||
# "Some day, my son, rake's inner wisdom will reveal itself. Until then,
|
||||
# take this `system` -- may its brute force protect you well."
|
||||
exit 1 unless system "rake test DEVISE_ORM=#{orm}"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -32,26 +32,3 @@ Rake::RDocTask.new(:rdoc) do |rdoc|
|
||||
rdoc.rdoc_files.include('README.rdoc')
|
||||
rdoc.rdoc_files.include('lib/**/*.rb')
|
||||
end
|
||||
|
||||
begin
|
||||
require 'jeweler'
|
||||
Jeweler::Tasks.new do |s|
|
||||
root_files = FileList["README.rdoc", "MIT-LICENSE", "CHANGELOG.rdoc"]
|
||||
s.name = "devise"
|
||||
s.version = Devise::VERSION.dup
|
||||
s.summary = "Flexible authentication solution for Rails with Warden"
|
||||
s.email = "contact@plataformatec.com.br"
|
||||
s.homepage = "http://github.com/plataformatec/devise"
|
||||
s.description = "Flexible authentication solution for Rails with Warden"
|
||||
s.authors = ['José Valim', 'Carlos Antônio']
|
||||
s.files = root_files + FileList["{app,config,lib}/**/*"]
|
||||
s.extra_rdoc_files = root_files
|
||||
s.add_dependency("warden", "~> 1.0.2")
|
||||
s.add_dependency("orm_adapter", "~> 0.0.2")
|
||||
s.add_dependency("bcrypt-ruby", "~> 2.1.2")
|
||||
end
|
||||
|
||||
Jeweler::GemcutterTasks.new
|
||||
rescue LoadError
|
||||
puts "Jeweler, or one of its dependencies, is not available. Install it with: gem install jeweler"
|
||||
end
|
||||
|
||||
4
TODO
4
TODO
@@ -1,4 +0,0 @@
|
||||
* Move integration tests to Capybara
|
||||
* Better ORM integration
|
||||
* Add support to automatically refresh the access token for OAuth
|
||||
* Add test to generators using the new Rails::Generators::TestCase
|
||||
@@ -9,18 +9,18 @@ class Devise::OmniauthCallbacksController < ApplicationController
|
||||
protected
|
||||
|
||||
def failed_strategy
|
||||
env["omniauth.failed_strategy"]
|
||||
env["omniauth.error.strategy"]
|
||||
end
|
||||
|
||||
def failure_message
|
||||
exception = env["omniauth.error"]
|
||||
error = exception.error_reason if exception.respond_to?(:error_reason)
|
||||
error ||= exception.error if exception.respond_to?(:error)
|
||||
error ||= env["omniauth.failure_key"]
|
||||
error ||= env["omniauth.error.type"].to_s
|
||||
error.to_s.humanize if error
|
||||
end
|
||||
|
||||
def after_omniauth_failure_path_for(scope)
|
||||
new_session_path(scope)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,12 +9,12 @@ class Devise::RegistrationsController < ApplicationController
|
||||
render_with_scope :new
|
||||
end
|
||||
|
||||
# POST /resource/sign_up
|
||||
# POST /resource
|
||||
def create
|
||||
build_resource
|
||||
|
||||
if resource.save
|
||||
if resource.active?
|
||||
if resource.active_for_authentication?
|
||||
set_flash_message :notice, :signed_up
|
||||
sign_in_and_redirect(resource_name, resource)
|
||||
else
|
||||
@@ -78,8 +78,8 @@ class Devise::RegistrationsController < ApplicationController
|
||||
end
|
||||
|
||||
# Overwrite redirect_for_sign_in so it takes uses after_sign_up_path_for.
|
||||
def redirect_for_sign_in(scope, resource) #:nodoc:
|
||||
redirect_to stored_location_for(scope) || after_sign_up_path_for(resource)
|
||||
def redirect_location(scope, resource) #:nodoc:
|
||||
stored_location_for(scope) || after_sign_up_path_for(resource)
|
||||
end
|
||||
|
||||
# The path used after sign up for inactive accounts. You need to overwrite
|
||||
@@ -104,7 +104,7 @@ class Devise::RegistrationsController < ApplicationController
|
||||
# We need to use a copy because we don't want actions like update changing
|
||||
# the current user in place.
|
||||
def authenticate_scope!
|
||||
send(:"authenticate_#{resource_name}!")
|
||||
send(:"authenticate_#{resource_name}!", true)
|
||||
self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -11,8 +11,9 @@ class Devise::SessionsController < ApplicationController
|
||||
# POST /resource/sign_in
|
||||
def create
|
||||
resource = warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#new")
|
||||
set_flash_message :notice, :signed_in
|
||||
sign_in_and_redirect(resource_name, resource)
|
||||
set_flash_message(:notice, :signed_in) if is_navigational_format?
|
||||
sign_in(resource_name, resource)
|
||||
respond_with resource, :location => redirect_location(resource_name, resource)
|
||||
end
|
||||
|
||||
# GET /resource/sign_out
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
module DeviseHelper
|
||||
# A simple way to show error messages for the current devise resource. If you need
|
||||
# to customize this method, you can either overwrite it in your application helpers or
|
||||
# copy the views to your application.
|
||||
#
|
||||
# This method is intended to stay simple and it is unlikely that we are going to change
|
||||
# it to add more behavior or options.
|
||||
def devise_error_messages!
|
||||
return "" if resource.errors.empty?
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# Additional translations at http://github.com/plataformatec/devise/wiki/I18n
|
||||
|
||||
en:
|
||||
errors:
|
||||
messages:
|
||||
|
||||
221
devise.gemspec
221
devise.gemspec
@@ -1,208 +1,25 @@
|
||||
# Generated by jeweler
|
||||
# DO NOT EDIT THIS FILE DIRECTLY
|
||||
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
||||
# -*- encoding: utf-8 -*-
|
||||
$:.push File.expand_path("../lib", __FILE__)
|
||||
require "devise/version"
|
||||
|
||||
Gem::Specification.new do |s|
|
||||
s.name = %q{devise}
|
||||
s.version = "1.2.rc"
|
||||
s.name = "devise"
|
||||
s.version = Devise::VERSION.dup
|
||||
s.platform = Gem::Platform::RUBY
|
||||
s.summary = "Flexible authentication solution for Rails with Warden"
|
||||
s.email = "contact@plataformatec.com.br"
|
||||
s.homepage = "http://github.com/plataformatec/devise"
|
||||
s.description = "Flexible authentication solution for Rails with Warden"
|
||||
s.authors = ['José Valim', 'Carlos Antônio']
|
||||
|
||||
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
|
||||
s.authors = ["Jos\303\251 Valim", "Carlos Ant\303\264nio"]
|
||||
s.date = %q{2010-11-26}
|
||||
s.description = %q{Flexible authentication solution for Rails with Warden}
|
||||
s.email = %q{contact@plataformatec.com.br}
|
||||
s.extra_rdoc_files = [
|
||||
"CHANGELOG.rdoc",
|
||||
"MIT-LICENSE",
|
||||
"README.rdoc"
|
||||
]
|
||||
s.files = [
|
||||
"CHANGELOG.rdoc",
|
||||
"MIT-LICENSE",
|
||||
"README.rdoc",
|
||||
"app/controllers/devise/confirmations_controller.rb",
|
||||
"app/controllers/devise/omniauth_callbacks_controller.rb",
|
||||
"app/controllers/devise/passwords_controller.rb",
|
||||
"app/controllers/devise/registrations_controller.rb",
|
||||
"app/controllers/devise/sessions_controller.rb",
|
||||
"app/controllers/devise/unlocks_controller.rb",
|
||||
"app/helpers/devise_helper.rb",
|
||||
"app/mailers/devise/mailer.rb",
|
||||
"app/views/devise/confirmations/new.html.erb",
|
||||
"app/views/devise/mailer/confirmation_instructions.html.erb",
|
||||
"app/views/devise/mailer/reset_password_instructions.html.erb",
|
||||
"app/views/devise/mailer/unlock_instructions.html.erb",
|
||||
"app/views/devise/passwords/edit.html.erb",
|
||||
"app/views/devise/passwords/new.html.erb",
|
||||
"app/views/devise/registrations/edit.html.erb",
|
||||
"app/views/devise/registrations/new.html.erb",
|
||||
"app/views/devise/sessions/new.html.erb",
|
||||
"app/views/devise/shared/_links.erb",
|
||||
"app/views/devise/unlocks/new.html.erb",
|
||||
"config/locales/en.yml",
|
||||
"lib/devise.rb",
|
||||
"lib/devise/controllers/helpers.rb",
|
||||
"lib/devise/controllers/internal_helpers.rb",
|
||||
"lib/devise/controllers/scoped_views.rb",
|
||||
"lib/devise/controllers/url_helpers.rb",
|
||||
"lib/devise/encryptors/authlogic_sha512.rb",
|
||||
"lib/devise/encryptors/base.rb",
|
||||
"lib/devise/encryptors/clearance_sha1.rb",
|
||||
"lib/devise/encryptors/restful_authentication_sha1.rb",
|
||||
"lib/devise/encryptors/sha1.rb",
|
||||
"lib/devise/encryptors/sha512.rb",
|
||||
"lib/devise/failure_app.rb",
|
||||
"lib/devise/hooks/activatable.rb",
|
||||
"lib/devise/hooks/forgetable.rb",
|
||||
"lib/devise/hooks/rememberable.rb",
|
||||
"lib/devise/hooks/timeoutable.rb",
|
||||
"lib/devise/hooks/trackable.rb",
|
||||
"lib/devise/mapping.rb",
|
||||
"lib/devise/models.rb",
|
||||
"lib/devise/models/authenticatable.rb",
|
||||
"lib/devise/models/confirmable.rb",
|
||||
"lib/devise/models/database_authenticatable.rb",
|
||||
"lib/devise/models/encryptable.rb",
|
||||
"lib/devise/models/lockable.rb",
|
||||
"lib/devise/models/omniauthable.rb",
|
||||
"lib/devise/models/recoverable.rb",
|
||||
"lib/devise/models/registerable.rb",
|
||||
"lib/devise/models/rememberable.rb",
|
||||
"lib/devise/models/timeoutable.rb",
|
||||
"lib/devise/models/token_authenticatable.rb",
|
||||
"lib/devise/models/trackable.rb",
|
||||
"lib/devise/models/validatable.rb",
|
||||
"lib/devise/modules.rb",
|
||||
"lib/devise/omniauth.rb",
|
||||
"lib/devise/omniauth/config.rb",
|
||||
"lib/devise/omniauth/test_helpers.rb",
|
||||
"lib/devise/omniauth/url_helpers.rb",
|
||||
"lib/devise/orm/active_record.rb",
|
||||
"lib/devise/orm/mongoid.rb",
|
||||
"lib/devise/path_checker.rb",
|
||||
"lib/devise/rails.rb",
|
||||
"lib/devise/rails/routes.rb",
|
||||
"lib/devise/rails/warden_compat.rb",
|
||||
"lib/devise/schema.rb",
|
||||
"lib/devise/strategies/authenticatable.rb",
|
||||
"lib/devise/strategies/base.rb",
|
||||
"lib/devise/strategies/database_authenticatable.rb",
|
||||
"lib/devise/strategies/rememberable.rb",
|
||||
"lib/devise/strategies/token_authenticatable.rb",
|
||||
"lib/devise/test_helpers.rb",
|
||||
"lib/devise/version.rb",
|
||||
"lib/generators/active_record/devise_generator.rb",
|
||||
"lib/generators/active_record/templates/migration.rb",
|
||||
"lib/generators/devise/devise_generator.rb",
|
||||
"lib/generators/devise/install_generator.rb",
|
||||
"lib/generators/devise/orm_helpers.rb",
|
||||
"lib/generators/devise/views_generator.rb",
|
||||
"lib/generators/mongoid/devise_generator.rb",
|
||||
"lib/generators/templates/README",
|
||||
"lib/generators/templates/devise.rb"
|
||||
]
|
||||
s.homepage = %q{http://github.com/plataformatec/devise}
|
||||
s.rdoc_options = ["--charset=UTF-8"]
|
||||
s.rubyforge_project = "devise"
|
||||
|
||||
s.files = `git ls-files`.split("\n")
|
||||
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
||||
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
||||
s.require_paths = ["lib"]
|
||||
s.rubygems_version = %q{1.3.7}
|
||||
s.summary = %q{Flexible authentication solution for Rails with Warden}
|
||||
s.test_files = [
|
||||
"test/controllers/helpers_test.rb",
|
||||
"test/controllers/internal_helpers_test.rb",
|
||||
"test/controllers/url_helpers_test.rb",
|
||||
"test/devise_test.rb",
|
||||
"test/encryptors_test.rb",
|
||||
"test/failure_app_test.rb",
|
||||
"test/generators/generators_test_helper.rb",
|
||||
"test/generators/install_generator_test.rb",
|
||||
"test/generators/views_generator_test.rb",
|
||||
"test/integration/authenticatable_test.rb",
|
||||
"test/integration/confirmable_test.rb",
|
||||
"test/integration/database_authenticatable_test.rb",
|
||||
"test/integration/http_authenticatable_test.rb",
|
||||
"test/integration/lockable_test.rb",
|
||||
"test/integration/omniauthable_test.rb",
|
||||
"test/integration/recoverable_test.rb",
|
||||
"test/integration/registerable_test.rb",
|
||||
"test/integration/rememberable_test.rb",
|
||||
"test/integration/timeoutable_test.rb",
|
||||
"test/integration/token_authenticatable_test.rb",
|
||||
"test/integration/trackable_test.rb",
|
||||
"test/mailers/confirmation_instructions_test.rb",
|
||||
"test/mailers/reset_password_instructions_test.rb",
|
||||
"test/mailers/unlock_instructions_test.rb",
|
||||
"test/mapping_test.rb",
|
||||
"test/models/confirmable_test.rb",
|
||||
"test/models/database_authenticatable_test.rb",
|
||||
"test/models/encryptable_test.rb",
|
||||
"test/models/lockable_test.rb",
|
||||
"test/models/recoverable_test.rb",
|
||||
"test/models/rememberable_test.rb",
|
||||
"test/models/timeoutable_test.rb",
|
||||
"test/models/token_authenticatable_test.rb",
|
||||
"test/models/trackable_test.rb",
|
||||
"test/models/validatable_test.rb",
|
||||
"test/models_test.rb",
|
||||
"test/omniauth/url_helpers_test.rb",
|
||||
"test/orm/active_record.rb",
|
||||
"test/orm/mongoid.rb",
|
||||
"test/rails_app/app/active_record/admin.rb",
|
||||
"test/rails_app/app/active_record/shim.rb",
|
||||
"test/rails_app/app/active_record/user.rb",
|
||||
"test/rails_app/app/controllers/admins/sessions_controller.rb",
|
||||
"test/rails_app/app/controllers/admins_controller.rb",
|
||||
"test/rails_app/app/controllers/application_controller.rb",
|
||||
"test/rails_app/app/controllers/home_controller.rb",
|
||||
"test/rails_app/app/controllers/publisher/registrations_controller.rb",
|
||||
"test/rails_app/app/controllers/publisher/sessions_controller.rb",
|
||||
"test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb",
|
||||
"test/rails_app/app/controllers/users_controller.rb",
|
||||
"test/rails_app/app/helpers/application_helper.rb",
|
||||
"test/rails_app/app/mongoid/admin.rb",
|
||||
"test/rails_app/app/mongoid/shim.rb",
|
||||
"test/rails_app/app/mongoid/user.rb",
|
||||
"test/rails_app/config/application.rb",
|
||||
"test/rails_app/config/boot.rb",
|
||||
"test/rails_app/config/environment.rb",
|
||||
"test/rails_app/config/environments/development.rb",
|
||||
"test/rails_app/config/environments/production.rb",
|
||||
"test/rails_app/config/environments/test.rb",
|
||||
"test/rails_app/config/initializers/backtrace_silencers.rb",
|
||||
"test/rails_app/config/initializers/devise.rb",
|
||||
"test/rails_app/config/initializers/inflections.rb",
|
||||
"test/rails_app/config/initializers/secret_token.rb",
|
||||
"test/rails_app/config/routes.rb",
|
||||
"test/rails_app/db/migrate/20100401102949_create_tables.rb",
|
||||
"test/rails_app/db/schema.rb",
|
||||
"test/rails_app/lib/shared_admin.rb",
|
||||
"test/rails_app/lib/shared_user.rb",
|
||||
"test/routes_test.rb",
|
||||
"test/support/assertions.rb",
|
||||
"test/support/helpers.rb",
|
||||
"test/support/integration.rb",
|
||||
"test/support/webrat/integrations/rails.rb",
|
||||
"test/test_helper.rb",
|
||||
"test/test_helpers_test.rb"
|
||||
]
|
||||
|
||||
if s.respond_to? :specification_version then
|
||||
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
||||
s.specification_version = 3
|
||||
|
||||
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
||||
s.add_runtime_dependency(%q<warden>, ["~> 1.0.2"])
|
||||
s.add_runtime_dependency(%q<orm_adapter>, ["~> 0.0.2"])
|
||||
s.add_runtime_dependency(%q<bcrypt-ruby>, ["~> 2.1.2"])
|
||||
else
|
||||
s.add_dependency(%q<warden>, ["~> 1.0.2"])
|
||||
s.add_dependency(%q<orm_adapter>, ["~> 0.0.2"])
|
||||
s.add_dependency(%q<bcrypt-ruby>, ["~> 2.1.2"])
|
||||
end
|
||||
else
|
||||
s.add_dependency(%q<warden>, ["~> 1.0.2"])
|
||||
s.add_dependency(%q<orm_adapter>, ["~> 0.0.2"])
|
||||
s.add_dependency(%q<bcrypt-ruby>, ["~> 2.1.2"])
|
||||
end
|
||||
end
|
||||
|
||||
s.add_dependency("warden", "~> 1.0.3")
|
||||
s.add_dependency("orm_adapter", "~> 0.0.3")
|
||||
s.add_dependency("bcrypt-ruby", "~> 2.1.2")
|
||||
end
|
||||
@@ -1,3 +1,4 @@
|
||||
require 'rails'
|
||||
require 'active_support/core_ext/numeric/time'
|
||||
require 'active_support/dependencies'
|
||||
require 'orm_adapter'
|
||||
@@ -13,6 +14,7 @@ module Devise
|
||||
module Controllers
|
||||
autoload :Helpers, 'devise/controllers/helpers'
|
||||
autoload :InternalHelpers, 'devise/controllers/internal_helpers'
|
||||
autoload :Rememberable, 'devise/controllers/rememberable'
|
||||
autoload :ScopedViews, 'devise/controllers/scoped_views'
|
||||
autoload :UrlHelpers, 'devise/controllers/url_helpers'
|
||||
end
|
||||
@@ -68,8 +70,9 @@ 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
|
||||
|
||||
# If http authentication is enabled by default.
|
||||
mattr_accessor :http_authenticatable
|
||||
@@ -89,7 +92,7 @@ module Devise
|
||||
|
||||
# Email regex used to validate email formats. Adapted from authlogic.
|
||||
mattr_accessor :email_regexp
|
||||
@@email_regexp = /^([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})$/i
|
||||
@@email_regexp = /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\z/i
|
||||
|
||||
# Range validation for password length
|
||||
mattr_accessor :password_length
|
||||
@@ -116,6 +119,10 @@ module Devise
|
||||
mattr_accessor :confirm_within
|
||||
@@confirm_within = 0.days
|
||||
|
||||
# Defines which key will be used when confirming an account
|
||||
mattr_accessor :confirmation_keys
|
||||
@@confirmation_keys = [ :email ]
|
||||
|
||||
# Time interval to timeout the user session without activity.
|
||||
mattr_accessor :timeout_in
|
||||
@@timeout_in = 30.minutes
|
||||
@@ -143,6 +150,10 @@ module Devise
|
||||
mattr_accessor :lock_strategy
|
||||
@@lock_strategy = :failed_attempts
|
||||
|
||||
# Defines which key will be used when locking and unlocking an account
|
||||
mattr_accessor :unlock_keys
|
||||
@@unlock_keys = [ :email ]
|
||||
|
||||
# Defines which strategy can be used to unlock an account.
|
||||
# Values: :email, :time, :both
|
||||
mattr_accessor :unlock_strategy
|
||||
@@ -156,6 +167,10 @@ module Devise
|
||||
mattr_accessor :unlock_in
|
||||
@@unlock_in = 1.hour
|
||||
|
||||
# Defines which key will be used when recovering the password for an account
|
||||
mattr_accessor :reset_password_keys
|
||||
@@reset_password_keys = [ :email ]
|
||||
|
||||
# The default scope which is used by warden.
|
||||
mattr_accessor :default_scope
|
||||
@@default_scope = nil
|
||||
@@ -173,10 +188,11 @@ module Devise
|
||||
@@stateless_token = false
|
||||
|
||||
# Which formats should be treated as navigational.
|
||||
# We need both :"*/*" and "*/*" to work on different Rails versions.
|
||||
mattr_accessor :navigational_formats
|
||||
@@navigational_formats = [:"*/*", :html]
|
||||
@@navigational_formats = [:"*/*", "*/*", :html]
|
||||
|
||||
# When set to true, signing out an user signs out all other scopes.
|
||||
# When set to true, signing out a user signs out all other scopes.
|
||||
mattr_accessor :sign_out_all_scopes
|
||||
@@sign_out_all_scopes = true
|
||||
|
||||
@@ -210,6 +226,14 @@ module Devise
|
||||
yield self
|
||||
end
|
||||
|
||||
def self.ref(arg)
|
||||
if defined?(ActiveSupport::Dependencies::ClassCache)
|
||||
ActiveSupport::Dependencies::Reference.store(arg)
|
||||
else
|
||||
ActiveSupport::Dependencies.ref(arg)
|
||||
end
|
||||
end
|
||||
|
||||
def self.omniauth_providers
|
||||
omniauth_configs.keys
|
||||
end
|
||||
@@ -222,12 +246,16 @@ module Devise
|
||||
|
||||
# Get the mailer class from the mailer reference object.
|
||||
def self.mailer
|
||||
@@mailer_ref.get
|
||||
if defined?(ActiveSupport::Dependencies::ClassCache)
|
||||
@@mailer_ref.get "Devise::Mailer"
|
||||
else
|
||||
@@mailer_ref.get
|
||||
end
|
||||
end
|
||||
|
||||
# Set the mailer reference object to access the mailer.
|
||||
def self.mailer=(class_name)
|
||||
@@mailer_ref = ActiveSupport::Dependencies.ref(class_name)
|
||||
@@mailer_ref = ref(class_name)
|
||||
end
|
||||
self.mailer = "Devise::Mailer"
|
||||
|
||||
@@ -357,7 +385,17 @@ module Devise
|
||||
|
||||
# Generate a friendly string randomically to be used as token.
|
||||
def self.friendly_token
|
||||
ActiveSupport::SecureRandom.base64(44).tr('+/=', 'xyz')
|
||||
ActiveSupport::SecureRandom.base64(15).tr('+/=', 'xyz')
|
||||
end
|
||||
|
||||
# constant-time comparison algorithm to prevent timing attacks
|
||||
def self.secure_compare(a, b)
|
||||
return false if a.blank? || b.blank? || a.bytesize != b.bytesize
|
||||
l = a.unpack "C#{a.bytesize}"
|
||||
|
||||
res = 0
|
||||
b.each_byte { |byte| res |= byte ^ l.shift }
|
||||
res == 0
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ module Devise
|
||||
# Generated methods:
|
||||
# authenticate_user! # Signs user in or redirect
|
||||
# authenticate_admin! # Signs admin in or redirect
|
||||
# user_signed_in? # Checks whether there is an user signed in or not
|
||||
# user_signed_in? # Checks whether there is a user signed in or not
|
||||
# admin_signed_in? # Checks whether there is an admin signed in or not
|
||||
# current_user # Current signed in user
|
||||
# current_admin # Current signed in admin
|
||||
@@ -36,8 +36,8 @@ module Devise
|
||||
mapping = mapping.name
|
||||
|
||||
class_eval <<-METHODS, __FILE__, __LINE__ + 1
|
||||
def authenticate_#{mapping}!
|
||||
warden.authenticate!(:scope => :#{mapping})
|
||||
def authenticate_#{mapping}!(force = false)
|
||||
warden.authenticate!(:scope => :#{mapping}) if !devise_controller? || force
|
||||
end
|
||||
|
||||
def #{mapping}_signed_in?
|
||||
@@ -72,19 +72,21 @@ module Devise
|
||||
false
|
||||
end
|
||||
|
||||
# Check if the given scope is signed in session, without running
|
||||
# authentication hooks.
|
||||
def signed_in?(scope)
|
||||
warden.authenticate?(:scope => scope)
|
||||
# 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)
|
||||
end
|
||||
end
|
||||
|
||||
# Check if the any scope is signed in session, without running
|
||||
# authentication hooks.
|
||||
def anybody_signed_in?
|
||||
Devise.mappings.keys.any? { |scope| signed_in?(scope) }
|
||||
ActiveSupport::Deprecation.warn "Devise#anybody_signed_in? is deprecated. "
|
||||
"Please use Devise#signed_in?(nil) instead."
|
||||
signed_in?
|
||||
end
|
||||
|
||||
# Sign in an user that already was authenticated. This helper is useful for logging
|
||||
# Sign in a user that already was authenticated. This helper is useful for logging
|
||||
# users in after sign up.
|
||||
#
|
||||
# All options given to sign_in is passed forward to the set_user method in warden.
|
||||
@@ -108,12 +110,14 @@ module Devise
|
||||
|
||||
if options[:bypass]
|
||||
warden.session_serializer.store(resource, scope)
|
||||
elsif warden.user(scope) == resource && !options.delete(:force)
|
||||
# Do nothing. User already signed in and we are not forcing it.
|
||||
else
|
||||
warden.set_user(resource, options.merge!(:scope => scope))
|
||||
end
|
||||
end
|
||||
|
||||
# Sign out a given user or scope. This helper is useful for signing out an user
|
||||
# Sign out a given user or scope. This helper is useful for signing out a user
|
||||
# after deleting accounts.
|
||||
#
|
||||
# Examples:
|
||||
@@ -132,6 +136,7 @@ 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.
|
||||
def sign_out_all_scopes
|
||||
Devise.mappings.keys.each { |s| warden.user(s) }
|
||||
warden.raw_session.inspect
|
||||
warden.logout
|
||||
end
|
||||
@@ -180,7 +185,7 @@ module Devise
|
||||
respond_to?(home_path, true) ? send(home_path) : root_path
|
||||
end
|
||||
|
||||
# Method used by sessions controller to sign out an user. You can overwrite
|
||||
# Method used by sessions controller to sign out a user. You can overwrite
|
||||
# it in your ApplicationController to provide a custom hook for a custom
|
||||
# scope. Notice that differently from +after_sign_in_path_for+ this method
|
||||
# receives a symbol with the scope, and not the resource.
|
||||
@@ -190,36 +195,26 @@ module Devise
|
||||
root_path
|
||||
end
|
||||
|
||||
# Sign in an user and tries to redirect first to the stored location and
|
||||
# Sign in a user and tries to redirect first to the stored location and
|
||||
# then to the url specified by after_sign_in_path_for. It accepts the same
|
||||
# parameters as the sign_in method.
|
||||
def sign_in_and_redirect(resource_or_scope, *args)
|
||||
options = args.extract_options!
|
||||
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
||||
resource = args.last || resource_or_scope
|
||||
|
||||
if warden.user(scope) == resource
|
||||
expire_session_data_after_sign_in!
|
||||
else
|
||||
sign_in(scope, resource, options)
|
||||
end
|
||||
|
||||
redirect_for_sign_in(scope, resource)
|
||||
sign_in(scope, resource, options)
|
||||
redirect_to redirect_location(scope, resource)
|
||||
end
|
||||
|
||||
def redirect_for_sign_in(scope, resource) #:nodoc:
|
||||
redirect_to stored_location_for(scope) || after_sign_in_path_for(resource)
|
||||
def redirect_location(scope, resource) #:nodoc:
|
||||
stored_location_for(scope) || after_sign_in_path_for(resource)
|
||||
end
|
||||
|
||||
# Sign out an user and tries to redirect to the url specified by
|
||||
# Sign out a user and tries to redirect to the url specified by
|
||||
# after_sign_out_path_for.
|
||||
def sign_out_and_redirect(resource_or_scope)
|
||||
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
||||
Devise.sign_out_all_scopes ? sign_out : sign_out(scope)
|
||||
redirect_for_sign_out(scope)
|
||||
end
|
||||
|
||||
def redirect_for_sign_out(scope) #:nodoc:
|
||||
redirect_to after_sign_out_path_for(scope)
|
||||
end
|
||||
|
||||
@@ -228,6 +223,12 @@ module Devise
|
||||
def expire_session_data_after_sign_in!
|
||||
session.keys.grep(/^devise\./).each { |k| session.delete(k) }
|
||||
end
|
||||
|
||||
# Overwrite Rails' handle unverified request to sign out all scopes.
|
||||
def handle_unverified_request
|
||||
sign_out_all_scopes
|
||||
super # call the default behaviour which resets the session
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -16,7 +16,7 @@ module Devise
|
||||
helper_method *helpers
|
||||
|
||||
prepend_before_filter :is_devise_resource?
|
||||
skip_before_filter *Devise.mappings.keys.map { |m| :"authenticate_#{m}!" }
|
||||
respond_to *Mime::SET.map(&:to_sym) if mimes_for_respond_to.empty?
|
||||
end
|
||||
|
||||
# Gets the actual resource stored in the instance variable
|
||||
@@ -57,6 +57,11 @@ module Devise
|
||||
unknown_action!("Could not find devise mapping for path #{request.fullpath.inspect}") unless devise_mapping
|
||||
end
|
||||
|
||||
# Check whether it's navigational format, such as :html or :iphone, or not.
|
||||
def is_navigational_format?
|
||||
Devise.navigational_formats.include?(request.format.to_sym)
|
||||
end
|
||||
|
||||
def unknown_action!(msg)
|
||||
logger.debug "[Devise] #{msg}" if logger
|
||||
raise ActionController::UnknownAction, msg
|
||||
|
||||
52
lib/devise/controllers/rememberable.rb
Normal file
52
lib/devise/controllers/rememberable.rb
Normal file
@@ -0,0 +1,52 @@
|
||||
module Devise
|
||||
module Controllers
|
||||
# A module that may be optionally included in a controller in order
|
||||
# to provide remember me behavior.
|
||||
module Rememberable
|
||||
# Return default cookie values retrieved from session options.
|
||||
def self.cookie_values
|
||||
Rails.configuration.session_options.slice(:path, :domain, :secure)
|
||||
end
|
||||
|
||||
# A small warden proxy so we can remember and forget uses from hooks.
|
||||
class Proxy #:nodoc:
|
||||
include Devise::Controllers::Rememberable
|
||||
|
||||
delegate :cookies, :env, :to => :@warden
|
||||
|
||||
def initialize(warden)
|
||||
@warden = warden
|
||||
end
|
||||
end
|
||||
|
||||
# Remembers the given resource by setting up a cookie
|
||||
def remember_me(resource)
|
||||
scope = Devise::Mapping.find_scope!(resource)
|
||||
resource.remember_me!(resource.extend_remember_period)
|
||||
cookies.signed["remember_#{scope}_token"] = remember_cookie_values(resource)
|
||||
end
|
||||
|
||||
# Forgets the given resource by deleting a cookie
|
||||
def forget_me(resource)
|
||||
scope = Devise::Mapping.find_scope!(resource)
|
||||
resource.forget_me! unless resource.frozen?
|
||||
cookies.delete("remember_#{scope}_token", forget_cookie_values(resource))
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def forget_cookie_values(resource)
|
||||
Devise::Controllers::Rememberable.cookie_values.merge!(resource.cookie_options)
|
||||
end
|
||||
|
||||
def remember_cookie_values(resource)
|
||||
options = { :httponly => true }
|
||||
options.merge!(forget_cookie_values(resource))
|
||||
options.merge!(
|
||||
:value => resource.class.serialize_into_cookie(resource),
|
||||
:expires => resource.remember_expires_at
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -4,7 +4,7 @@ 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 silumate
|
||||
# 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
|
||||
# Gererates a default password digest based on salt, pepper and the
|
||||
|
||||
@@ -64,7 +64,11 @@ module Devise
|
||||
end
|
||||
|
||||
def redirect_url
|
||||
send(:"new_#{scope}_session_path")
|
||||
if request_format == :html
|
||||
send(:"new_#{scope}_session_path")
|
||||
else
|
||||
send(:"new_#{scope}_session_path", :format => request_format)
|
||||
end
|
||||
end
|
||||
|
||||
# Choose whether we should respond in a http authentication fashion,
|
||||
@@ -79,7 +83,7 @@ module Devise
|
||||
if request.xhr?
|
||||
Devise.http_authenticatable_on_xhr
|
||||
else
|
||||
!(request.format && Devise.navigational_formats.include?(request.format.to_sym))
|
||||
!(request_format && Devise.navigational_formats.include?(request_format))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -90,8 +94,8 @@ module Devise
|
||||
end
|
||||
|
||||
def http_auth_body
|
||||
return i18n_message unless request.format
|
||||
method = "to_#{request.format.to_sym}"
|
||||
return i18n_message unless request_format
|
||||
method = "to_#{request_format}"
|
||||
{}.respond_to?(method) ? { :error => i18n_message }.send(method) : i18n_message
|
||||
end
|
||||
|
||||
@@ -123,5 +127,17 @@ module Devise
|
||||
def store_location!
|
||||
session["#{scope}_return_to"] = attempted_path if request.get? && !http_auth?
|
||||
end
|
||||
|
||||
MIME_REFERENCES = Mime::HTML.respond_to?(:ref)
|
||||
|
||||
def request_format
|
||||
@request_format ||= if request.format.respond_to?(:ref)
|
||||
request.format.ref
|
||||
elsif MIME_REFERENCES
|
||||
request.format
|
||||
else # Rails < 3.0.4
|
||||
request.format.to_sym
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# Deny user access whenever his account is not active yet. All strategies that inherits from
|
||||
# Devise::Strategies::Authenticatable and uses the validate already check if the user is active?
|
||||
# Devise::Strategies::Authenticatable and uses the validate already check if the user is active_for_authentication?
|
||||
# before actively signing him in. However, we need this as hook to validate the user activity
|
||||
# in each request and in case the user is using other strategies beside Devise ones.
|
||||
Warden::Manager.after_set_user do |record, warden, options|
|
||||
if record && record.respond_to?(:active?) && !record.active?
|
||||
if record && record.respond_to?(:active_for_authentication?) && !record.active_for_authentication?
|
||||
scope = options[:scope]
|
||||
warden.logout(scope)
|
||||
throw :warden, :scope => scope, :message => record.inactive_message
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
# This avoids forgetting deleted users.
|
||||
Warden::Manager.before_logout do |record, warden, options|
|
||||
if record.respond_to?(:forget_me!)
|
||||
record.forget_me! unless record.frozen?
|
||||
cookie_options = Rails.configuration.session_options.slice(:path, :domain, :secure)
|
||||
cookie_options.merge!(record.cookie_options)
|
||||
warden.cookies.delete("remember_#{options[:scope]}_token", cookie_options)
|
||||
Devise::Controllers::Rememberable::Proxy.new(warden).forget_me(record)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,45 +1,6 @@
|
||||
module Devise
|
||||
module Hooks
|
||||
# Overwrite success! in authentication strategies allowing users to be remembered.
|
||||
# We choose to implement this as an strategy hook instead of a warden hook to allow a specific
|
||||
# strategy (like token authenticatable or facebook authenticatable) to turn off remember_me?
|
||||
# cookies.
|
||||
module Rememberable #:nodoc:
|
||||
def success!(resource)
|
||||
super
|
||||
|
||||
if succeeded? && resource.respond_to?(:remember_me!) && remember_me?
|
||||
resource.remember_me!(extend_remember_period?)
|
||||
cookies.signed["remember_#{scope}_token"] = cookie_values(resource)
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def cookie_values(resource)
|
||||
options = Rails.configuration.session_options.slice(:path, :domain, :secure)
|
||||
options.merge!(resource.cookie_options)
|
||||
options.merge!(
|
||||
:value => resource.class.serialize_into_cookie(resource),
|
||||
:expires => resource.remember_expires_at
|
||||
)
|
||||
options
|
||||
end
|
||||
|
||||
def succeeded?
|
||||
@result == :success
|
||||
end
|
||||
|
||||
def extend_remember_period?
|
||||
false
|
||||
end
|
||||
|
||||
def remember_me?
|
||||
valid_params? && Devise::TRUE_VALUES.include?(params_auth_hash[:remember_me])
|
||||
end
|
||||
end
|
||||
Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
|
||||
scope = options[:scope]
|
||||
if record.respond_to?(:remember_me) && record.remember_me && warden.authenticated?(scope)
|
||||
Devise::Controllers::Rememberable::Proxy.new(warden).remember_me(record)
|
||||
end
|
||||
end
|
||||
|
||||
Devise::Strategies::Authenticatable.send :include, Devise::Hooks::Rememberable
|
||||
|
||||
end
|
||||
@@ -6,7 +6,7 @@
|
||||
Warden::Manager.after_set_user do |record, warden, options|
|
||||
scope = options[:scope]
|
||||
|
||||
if record && record.respond_to?(:timedout?) && warden.authenticated?(scope)
|
||||
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)
|
||||
|
||||
@@ -50,7 +50,7 @@ module Devise
|
||||
@singular = (options[:singular] || @scoped_path.tr('/', '_').singularize).to_sym
|
||||
|
||||
@class_name = (options[:class_name] || name.to_s.classify).to_s
|
||||
@ref = ActiveSupport::Dependencies.ref(@class_name)
|
||||
@ref = Devise.ref(@class_name)
|
||||
|
||||
@path = (options[:path] || name).to_s
|
||||
@path_prefix = options[:path_prefix]
|
||||
@@ -73,7 +73,11 @@ module Devise
|
||||
|
||||
# Gives the class the mapping points to.
|
||||
def to
|
||||
@ref.get
|
||||
if defined?(ActiveSupport::Dependencies::ClassCache)
|
||||
@ref.get @class_name
|
||||
else
|
||||
@ref.get
|
||||
end
|
||||
end
|
||||
|
||||
def strategies
|
||||
|
||||
@@ -2,7 +2,7 @@ module Devise
|
||||
module Models
|
||||
# Creates configuration values for Devise and for the given module.
|
||||
#
|
||||
# Devise::Models.config(Devise::Authenticable, :stretches, 10)
|
||||
# Devise::Models.config(Devise::Authenticatable, :stretches, 10)
|
||||
#
|
||||
# The line above creates:
|
||||
#
|
||||
@@ -47,7 +47,9 @@ module Devise
|
||||
def devise(*modules)
|
||||
include Devise::Models::Authenticatable
|
||||
options = modules.extract_options!
|
||||
self.devise_modules += Devise::ALL & modules.map(&:to_sym).uniq
|
||||
self.devise_modules += modules.map(&:to_sym).uniq.sort_by { |s|
|
||||
Devise::ALL.index(s) || -1 # follow Devise::ALL order
|
||||
}
|
||||
|
||||
devise_modules_hook! do
|
||||
devise_modules.each { |m| include Devise::Models.const_get(m.to_s.classify) }
|
||||
|
||||
@@ -2,7 +2,7 @@ require 'devise/hooks/activatable'
|
||||
|
||||
module Devise
|
||||
module Models
|
||||
# Authenticable module. Holds common settings for authentication.
|
||||
# Authenticatable module. Holds common settings for authentication.
|
||||
#
|
||||
# == Options
|
||||
#
|
||||
@@ -24,19 +24,19 @@ module Devise
|
||||
# * +params_authenticatable+: if this model allows authentication through request params. By default true.
|
||||
# It also accepts an array specifying the strategies that should allow params authentication.
|
||||
#
|
||||
# == Active?
|
||||
# == active_for_authentication?
|
||||
#
|
||||
# Before authenticating an user and in each request, Devise checks if your model is active by
|
||||
# calling model.active?. This method is overwriten by other devise modules. For instance,
|
||||
# :confirmable overwrites .active? to only return true if your model was confirmed.
|
||||
# Before authenticating a user and in each request, Devise checks if your model is active by
|
||||
# calling model.active_for_authentication?. This method is overwriten by other devise modules. For instance,
|
||||
# :confirmable overwrites .active_for_authentication? to only return true if your model was confirmed.
|
||||
#
|
||||
# You overwrite this method yourself, but if you do, don't forget to call super:
|
||||
#
|
||||
# def active?
|
||||
# def active_for_authentication?
|
||||
# super && special_condition_is_valid?
|
||||
# end
|
||||
#
|
||||
# Whenever active? returns false, Devise asks the reason why your model is inactive using
|
||||
# Whenever active_for_authentication? returns false, Devise asks the reason why your model is inactive using
|
||||
# the inactive_message method. You can overwrite it as well:
|
||||
#
|
||||
# def inactive_message
|
||||
@@ -55,10 +55,10 @@ module Devise
|
||||
# find_for_authentication are the methods used in a Warden::Strategy to check
|
||||
# if a model should be signed in or not.
|
||||
#
|
||||
# However, you should not overwrite this method, you should overwrite active? and
|
||||
# inactive_message instead.
|
||||
# However, you should not overwrite this method, you should overwrite active_for_authentication?
|
||||
# and inactive_message instead.
|
||||
def valid_for_authentication?
|
||||
if active?
|
||||
if active_for_authentication?
|
||||
block_given? ? yield : true
|
||||
else
|
||||
inactive_message
|
||||
@@ -66,7 +66,19 @@ module Devise
|
||||
end
|
||||
|
||||
def active?
|
||||
true
|
||||
ActiveSupport::Deprecation.warn "[DEVISE] active? is deprecated, please use active_for_authentication? instead.", caller
|
||||
active_for_authentication?
|
||||
end
|
||||
|
||||
def active_for_authentication?
|
||||
my_methods = self.class.instance_methods(false)
|
||||
if my_methods.include?("active?") || my_methods.include?(:active?)
|
||||
ActiveSupport::Deprecation.warn "[DEVISE] Overriding active? is deprecated to avoid conflicts. " \
|
||||
"Please use active_for_authentication? instead.", caller
|
||||
active?
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
def inactive_message
|
||||
@@ -100,7 +112,8 @@ module Devise
|
||||
# end
|
||||
#
|
||||
def find_for_authentication(conditions)
|
||||
case_insensitive_keys.each { |k| conditions[k].try(:downcase!) }
|
||||
filter_auth_params(conditions)
|
||||
(case_insensitive_keys || []).each { |k| conditions[k].try(:downcase!) }
|
||||
to_adapter.find_first(conditions)
|
||||
end
|
||||
|
||||
@@ -111,13 +124,13 @@ module Devise
|
||||
|
||||
# Find an initialize a group of attributes based on a list of required attributes.
|
||||
def find_or_initialize_with_errors(required_attributes, attributes, error=:invalid) #:nodoc:
|
||||
case_insensitive_keys.each { |k| attributes[k].try(:downcase!) }
|
||||
(case_insensitive_keys || []).each { |k| attributes[k].try(:downcase!) }
|
||||
|
||||
attributes = attributes.slice(*required_attributes)
|
||||
attributes.delete_if { |key, value| value.blank? }
|
||||
|
||||
if attributes.size == required_attributes.size
|
||||
record = to_adapter.find_first(attributes)
|
||||
record = to_adapter.find_first(filter_auth_params(attributes))
|
||||
end
|
||||
|
||||
unless record
|
||||
@@ -133,6 +146,15 @@ module Devise
|
||||
record
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Force keys to be string to avoid injection on mongoid related database.
|
||||
def filter_auth_params(conditions)
|
||||
conditions.each do |k, v|
|
||||
conditions[k] = v.to_s
|
||||
end if conditions.is_a?(Hash)
|
||||
end
|
||||
|
||||
# Generate a token by looping and ensuring does not already exist.
|
||||
def generate_token(column)
|
||||
loop do
|
||||
|
||||
@@ -55,11 +55,11 @@ module Devise
|
||||
unless_confirmed { send_confirmation_instructions }
|
||||
end
|
||||
|
||||
# Overwrites active? from Devise::Models::Activatable for confirmation
|
||||
# by verifying whether an user is active to sign in or not. If the user
|
||||
# Overwrites active_for_authentication? for confirmation
|
||||
# by verifying whether a user is active to sign in or not. If the user
|
||||
# is already confirmed, it should never be blocked. Otherwise we need to
|
||||
# calculate if the confirm time has not expired for this user.
|
||||
def active?
|
||||
def active_for_authentication?
|
||||
super && (!confirmation_required? || confirmed? || confirmation_period_valid?)
|
||||
end
|
||||
|
||||
@@ -133,7 +133,7 @@ module Devise
|
||||
# with an email not found error.
|
||||
# Options must contain the user email
|
||||
def send_confirmation_instructions(attributes={})
|
||||
confirmable = find_or_initialize_with_error_by(:email, attributes[:email], :not_found)
|
||||
confirmable = find_or_initialize_with_errors(confirmation_keys, attributes, :not_found)
|
||||
confirmable.resend_confirmation_token if confirmable.persisted?
|
||||
confirmable
|
||||
end
|
||||
@@ -153,7 +153,7 @@ module Devise
|
||||
generate_token(:confirmation_token)
|
||||
end
|
||||
|
||||
Devise::Models.config(self, :confirm_within)
|
||||
Devise::Models.config(self, :confirm_within, :confirmation_keys)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,7 +3,7 @@ require 'bcrypt'
|
||||
|
||||
module Devise
|
||||
module Models
|
||||
# Authenticable Module, responsible for encrypting password and validating
|
||||
# Authenticatable Module, responsible for encrypting password and validating
|
||||
# authenticity of a user while signing in.
|
||||
#
|
||||
# == Options
|
||||
@@ -31,9 +31,11 @@ module Devise
|
||||
self.encrypted_password = password_digest(@password) if @password.present?
|
||||
end
|
||||
|
||||
# Verifies whether an incoming_password (ie from sign in) is the user password.
|
||||
# Verifies whether an password (ie from sign in) is the user password.
|
||||
def valid_password?(password)
|
||||
::BCrypt::Password.new(self.encrypted_password) == "#{password}#{self.class.pepper}"
|
||||
bcrypt = ::BCrypt::Password.new(self.encrypted_password)
|
||||
password = ::BCrypt::Engine.hash_secret("#{password}#{self.class.pepper}", bcrypt.salt)
|
||||
Devise.secure_compare(password, self.encrypted_password)
|
||||
end
|
||||
|
||||
# Set password and password confirmation to nil
|
||||
@@ -76,7 +78,7 @@ module Devise
|
||||
|
||||
# Downcase case-insensitive keys
|
||||
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
|
||||
|
||||
# Digests the password using bcrypt.
|
||||
|
||||
@@ -36,7 +36,7 @@ module Devise
|
||||
|
||||
# Verifies whether an incoming_password (ie from sign in) is the user password.
|
||||
def valid_password?(incoming_password)
|
||||
password_digest(incoming_password) == self.encrypted_password
|
||||
Devise.secure_compare(password_digest(incoming_password), self.encrypted_password)
|
||||
end
|
||||
|
||||
protected
|
||||
@@ -53,7 +53,14 @@ module Devise
|
||||
|
||||
# Returns the class for the configured encryptor.
|
||||
def encryptor_class
|
||||
@encryptor_class ||= ::Devise::Encryptors.const_get(encryptor.to_s.classify)
|
||||
@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
|
||||
|
||||
@@ -15,13 +15,14 @@ module Devise
|
||||
# * +lock_strategy+: lock the user account by :failed_attempts or :none.
|
||||
# * +unlock_strategy+: unlock the user account by :time, :email, :both or :none.
|
||||
# * +unlock_in+: the time you want to lock the user after to lock happens. Only available when unlock_strategy is :time or :both.
|
||||
# * +unlock_keys+: the keys you want to use when locking and unlocking an account
|
||||
#
|
||||
module Lockable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
delegate :lock_strategy_enabled?, :unlock_strategy_enabled?, :to => "self.class"
|
||||
|
||||
# Lock an user setting it's locked_at to actual time.
|
||||
# Lock a user setting it's locked_at to actual time.
|
||||
def lock_access!
|
||||
self.locked_at = Time.now
|
||||
|
||||
@@ -33,14 +34,12 @@ module Devise
|
||||
save(:validate => false)
|
||||
end
|
||||
|
||||
# Unlock an user by cleaning locket_at and failed_attempts.
|
||||
# Unlock a user by cleaning locket_at and failed_attempts.
|
||||
def unlock_access!
|
||||
if_access_locked do
|
||||
self.locked_at = nil
|
||||
self.failed_attempts = 0 if respond_to?(:failed_attempts=)
|
||||
self.unlock_token = nil if respond_to?(:unlock_token=)
|
||||
save(:validate => false)
|
||||
end
|
||||
self.locked_at = nil
|
||||
self.failed_attempts = 0 if respond_to?(:failed_attempts=)
|
||||
self.unlock_token = nil if respond_to?(:unlock_token=)
|
||||
save(:validate => false)
|
||||
end
|
||||
|
||||
# Verifies whether a user is locked or not.
|
||||
@@ -58,9 +57,9 @@ module Devise
|
||||
if_access_locked { send_unlock_instructions }
|
||||
end
|
||||
|
||||
# Overwrites active? from Devise::Models::Activatable for locking purposes
|
||||
# by verifying whether an user is active to sign in or not based on locked?
|
||||
def active?
|
||||
# Overwrites active_for_authentication? from Devise::Models::Activatable for locking purposes
|
||||
# by verifying whether a user is active to sign in or not based on locked?
|
||||
def active_for_authentication?
|
||||
super && !access_locked?
|
||||
end
|
||||
|
||||
@@ -71,16 +70,21 @@ module Devise
|
||||
end
|
||||
|
||||
# Overwrites valid_for_authentication? from Devise::Models::Authenticatable
|
||||
# for verifying whether an user is allowed to sign in or not. If the user
|
||||
# for verifying whether a user is allowed to sign in or not. If the user
|
||||
# is locked, it should never be allowed.
|
||||
def valid_for_authentication?
|
||||
return super unless persisted? && lock_strategy_enabled?(:failed_attempts)
|
||||
|
||||
# Unlock the user if the lock is expired, no matter
|
||||
# if the user can login or not (wrong password, etc)
|
||||
unlock_access! if lock_expired?
|
||||
|
||||
case (result = super)
|
||||
when Symbol
|
||||
return result
|
||||
when TrueClass
|
||||
self.failed_attempts = 0
|
||||
save(:validate => false)
|
||||
when FalseClass
|
||||
# PostgreSQL uses nil as the default value for integer columns set to 0
|
||||
self.failed_attempts ||= 0
|
||||
@@ -88,10 +92,11 @@ module Devise
|
||||
if attempts_exceeded?
|
||||
lock_access!
|
||||
return :locked
|
||||
else
|
||||
save(:validate => false)
|
||||
end
|
||||
end
|
||||
|
||||
save(:validate => false) if changed?
|
||||
result
|
||||
end
|
||||
|
||||
@@ -132,7 +137,7 @@ 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(authentication_keys, attributes, :not_found)
|
||||
lockable = find_or_initialize_with_errors(unlock_keys, attributes, :not_found)
|
||||
lockable.resend_unlock_token if lockable.persisted?
|
||||
lockable
|
||||
end
|
||||
@@ -161,7 +166,7 @@ module Devise
|
||||
Devise.friendly_token
|
||||
end
|
||||
|
||||
Devise::Models.config(self, :maximum_attempts, :lock_strategy, :unlock_strategy, :unlock_in)
|
||||
Devise::Models.config(self, :maximum_attempts, :lock_strategy, :unlock_strategy, :unlock_in, :unlock_keys)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,6 +3,12 @@ module Devise
|
||||
|
||||
# Recoverable takes care of reseting the user password and send reset instructions.
|
||||
#
|
||||
# ==Options
|
||||
#
|
||||
# Recoverable adds the following options to devise_for:
|
||||
#
|
||||
# * +reset_password_keys+: the keys you want to use when recovering the password for an account
|
||||
#
|
||||
# == Examples
|
||||
#
|
||||
# # resets the user password and save the record, true if valid passwords are given, otherwise false
|
||||
@@ -57,7 +63,7 @@ module Devise
|
||||
# with an email not found error.
|
||||
# Attributes must contain the user email
|
||||
def send_reset_password_instructions(attributes={})
|
||||
recoverable = find_or_initialize_with_errors(authentication_keys, attributes, :not_found)
|
||||
recoverable = find_or_initialize_with_errors(reset_password_keys, attributes, :not_found)
|
||||
recoverable.send_reset_password_instructions if recoverable.persisted?
|
||||
recoverable
|
||||
end
|
||||
@@ -77,6 +83,8 @@ module Devise
|
||||
recoverable.reset_password!(attributes[:password], attributes[:password_confirmation]) if recoverable.persisted?
|
||||
recoverable
|
||||
end
|
||||
|
||||
Devise::Models.config(self, :reset_password_keys)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,7 +7,7 @@ module Devise
|
||||
|
||||
module ClassMethods
|
||||
# A convenience method that receives both parameters and session to
|
||||
# initialize an user. This can be used by OAuth, for example, to send
|
||||
# initialize a user. This can be used by OAuth, for example, to send
|
||||
# in the user token and be stored on initialization.
|
||||
#
|
||||
# By default discards all information sent by the session by calling
|
||||
|
||||
@@ -44,10 +44,7 @@ module Devise
|
||||
module Rememberable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
# Remember me option available in after_authentication hook.
|
||||
attr_accessor :remember_me
|
||||
end
|
||||
attr_accessor :remember_me, :extend_remember_period
|
||||
|
||||
# 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.
|
||||
@@ -60,7 +57,7 @@ module Devise
|
||||
# Removes the remember token only if it exists, and save the record
|
||||
# without validations.
|
||||
def forget_me!
|
||||
self.remember_token = nil if respond_to?(:remember_token)
|
||||
self.remember_token = nil if respond_to?(:remember_token=)
|
||||
self.remember_created_at = nil
|
||||
save(:validate => false)
|
||||
end
|
||||
|
||||
@@ -20,7 +20,7 @@ module Devise
|
||||
#
|
||||
# == Options
|
||||
#
|
||||
# TokenAuthenticable adds the following options to devise_for:
|
||||
# TokenAuthenticatable adds the following options to devise_for:
|
||||
#
|
||||
# * +token_authentication_key+: Defines name of the authentication token params key. E.g. /users/sign_in?some_key=...
|
||||
#
|
||||
@@ -38,17 +38,17 @@ module Devise
|
||||
# Generate new authentication token and save the record.
|
||||
def reset_authentication_token!
|
||||
reset_authentication_token
|
||||
self.save(:validate => false)
|
||||
save(:validate => false)
|
||||
end
|
||||
|
||||
# Generate authentication token unless already exists.
|
||||
def ensure_authentication_token
|
||||
self.reset_authentication_token if self.authentication_token.blank?
|
||||
reset_authentication_token if authentication_token.blank?
|
||||
end
|
||||
|
||||
# Generate authentication token unless already exists and save the record.
|
||||
def ensure_authentication_token!
|
||||
self.reset_authentication_token! if self.authentication_token.blank?
|
||||
reset_authentication_token! if authentication_token.blank?
|
||||
end
|
||||
|
||||
# Hook called after token authentication.
|
||||
|
||||
@@ -24,7 +24,7 @@ module Devise
|
||||
base.class_eval do
|
||||
validates_presence_of :email, :if => :email_required?
|
||||
validates_uniqueness_of :email, :scope => authentication_keys[1..-1],
|
||||
:case_sensitive => case_insensitive_keys.exclude?(:email), :allow_blank => true
|
||||
:case_sensitive => (case_insensitive_keys != false), :allow_blank => true
|
||||
validates_format_of :email, :with => email_regexp, :allow_blank => true
|
||||
|
||||
with_options :if => :password_required? do |v|
|
||||
|
||||
@@ -5,29 +5,14 @@ rescue LoadError => e
|
||||
raise
|
||||
end
|
||||
|
||||
module OmniAuth
|
||||
# TODO HAXES Backport to OmniAuth
|
||||
module Strategy #:nodoc:
|
||||
def initialize(app, name, *args)
|
||||
@app = app
|
||||
@name = name.to_sym
|
||||
@options = args.last.is_a?(Hash) ? args.pop : {}
|
||||
yield self if block_given?
|
||||
end
|
||||
|
||||
def fail!(message_key, exception = nil)
|
||||
self.env['omniauth.error'] = exception
|
||||
self.env['omniauth.failure_key'] = message_key
|
||||
self.env['omniauth.failed_strategy'] = self
|
||||
OmniAuth.config.on_failure.call(self.env, message_key.to_sym)
|
||||
end
|
||||
end
|
||||
unless OmniAuth.config.respond_to? :test_mode
|
||||
raise "You are using an old OmniAuth version, please ensure you have 0.2.0.beta version or later installed."
|
||||
end
|
||||
|
||||
# Clean up the default path_prefix. It will be automatically set by Devise.
|
||||
OmniAuth.config.path_prefix = nil
|
||||
|
||||
OmniAuth.config.on_failure = Proc.new do |env, key|
|
||||
OmniAuth.config.on_failure = Proc.new do |env|
|
||||
env['devise.mapping'] = Devise::Mapping.find_by_path!(env['PATH_INFO'], :path)
|
||||
controller_klass = "#{env['devise.mapping'].controllers[:omniauth_callbacks].camelize}Controller"
|
||||
controller_klass.constantize.action(:failure).call(env)
|
||||
|
||||
@@ -13,18 +13,6 @@ module Devise
|
||||
def strategy_class
|
||||
::OmniAuth::Strategies.const_get("#{::OmniAuth::Utils.camelize(@provider.to_s)}")
|
||||
end
|
||||
|
||||
def check_if_allow_stubs!
|
||||
raise "OmniAuth strategy for #{@provider} does not allow stubs, only OAuth2 ones do." unless allow_stubs?
|
||||
end
|
||||
|
||||
def allow_stubs?
|
||||
defined?(::OmniAuth::Strategies::OAuth2) && strategy.is_a?(::OmniAuth::Strategies::OAuth2)
|
||||
end
|
||||
|
||||
def build_connection(&block)
|
||||
strategy.client.connection.build(&block)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,57 +0,0 @@
|
||||
module Devise
|
||||
module OmniAuth
|
||||
module TestHelpers
|
||||
def self.test_mode!
|
||||
Faraday.default_adapter = :test if defined?(Faraday)
|
||||
ActiveSupport.on_load(:action_controller) { include Devise::OmniAuth::TestHelpers }
|
||||
ActiveSupport.on_load(:action_view) { include Devise::OmniAuth::TestHelpers }
|
||||
end
|
||||
|
||||
def self.stub!(provider, stubs=nil, &block)
|
||||
raise "You either need to pass stubs as a block or as a parameter" unless block_given? || stubs
|
||||
|
||||
config = Devise.omniauth_configs[provider]
|
||||
raise "Could not find configuration for #{provider.to_s} omniauth provider" unless config
|
||||
|
||||
config.check_if_allow_stubs!
|
||||
stubs ||= Faraday::Adapter::Test::Stubs.new(&block)
|
||||
|
||||
config.build_connection do |b|
|
||||
b.adapter :test, stubs
|
||||
end
|
||||
end
|
||||
|
||||
def self.reset_stubs!(*providers)
|
||||
target = providers.any? ? Devise.omniauth_configs.slice(*providers) : Devise.omniauth_configs
|
||||
target.each_value do |config|
|
||||
next unless config.allow_stubs?
|
||||
config.build_connection { |b| b.adapter Faraday.default_adapter }
|
||||
end
|
||||
end
|
||||
|
||||
def self.short_circuit_authorizers!
|
||||
module_eval <<-ALIASES, __FILE__, __LINE__ + 1
|
||||
def omniauth_authorize_path(*args)
|
||||
omniauth_callback_path(*args)
|
||||
end
|
||||
ALIASES
|
||||
|
||||
Devise.mappings.each_value do |m|
|
||||
next unless m.omniauthable?
|
||||
|
||||
module_eval <<-ALIASES, __FILE__, __LINE__ + 1
|
||||
def #{m.name}_omniauth_authorize_path(provider)
|
||||
#{m.name}_omniauth_callback_path(provider)
|
||||
end
|
||||
ALIASES
|
||||
end
|
||||
end
|
||||
|
||||
def self.unshort_circuit_authorizers!
|
||||
module_eval do
|
||||
instance_methods.each { |m| remove_method(m) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -7,7 +7,11 @@ module Devise
|
||||
class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1
|
||||
def #{mapping.name}_omniauth_authorize_path(provider, params = {})
|
||||
if Devise.omniauth_configs[provider.to_sym]
|
||||
"/#{mapping.path}/auth/\#{provider}\#{'?'+params.to_param if params.present?}"
|
||||
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
|
||||
@@ -26,4 +30,4 @@ module Devise
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,6 +17,14 @@ module Devise
|
||||
Devise.include_helpers(Devise::Controllers)
|
||||
end
|
||||
|
||||
initializer "devise.navigationals" do
|
||||
formats = Devise.navigational_formats
|
||||
if formats.include?(:"*/*") && formats.exclude?("*/*")
|
||||
puts "[DEVISE] We see the symbol :\"*/*\" in the navigational formats in your initializer " \
|
||||
"but not the string \"*/*\". Due to changes in latest Rails, please include the latter."
|
||||
end
|
||||
end
|
||||
|
||||
initializer "devise.omniauth" do |app|
|
||||
Devise.omniauth_configs.each do |provider, config|
|
||||
app.middleware.use config.strategy_class, *config.args do |strategy|
|
||||
@@ -32,17 +40,20 @@ module Devise
|
||||
initializer "devise.encryptor_check" do
|
||||
case Devise.encryptor
|
||||
when :bcrypt
|
||||
puts "[DEVISE] From version 1.2, there is no need to set your encryptor to bcrypt " <<
|
||||
"since encryptors are only enabled if you include :encryptable in your models. " <<
|
||||
"With this change, we can integrate better with bcrypt and get rid of the " <<
|
||||
"password_salt column (since bcrypt stores the salt with password). " <<
|
||||
"Please comment config.encryptor in your initializer to get rid of this warning."
|
||||
puts "[DEVISE] From version 1.2, there is no need to set your encryptor to bcrypt " \
|
||||
"since encryptors are only enabled if you include :encryptable in your models. " \
|
||||
"To update your app, please:\n\n" \
|
||||
"1) Remove config.encryptor from your initializer;\n" \
|
||||
"2) Add t.encryptable to your old migrations;\n" \
|
||||
"3) [Optional] Remove password_salt in a new recent migration. Bcrypt does not require it anymore.\n"
|
||||
when nil
|
||||
# Nothing to say
|
||||
else
|
||||
puts "[DEVISE] You are using #{Devise.encryptor} as encryptor. From version 1.2, " <<
|
||||
"you need to explicitly add `devise :encryptable, :encryptor => #{Devise.encryptor.to_sym}` " <<
|
||||
"to your models and comment the current value in the config/initializers/devise.rb"
|
||||
puts "[DEVISE] You are using #{Devise.encryptor} as encryptor. From version 1.2, " \
|
||||
"you need to explicitly add encryptable as dependency. To update your app, please:\n\n" \
|
||||
"1) Remove config.encryptor from your initializer;\n" \
|
||||
"2) Add t.encryptable to your old migrations;\n" \
|
||||
"3) Add `devise :encryptable, :encryptor => :#{Devise.encryptor}` to your models.\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -263,7 +263,8 @@ module ActionDispatch::Routing
|
||||
end
|
||||
|
||||
def devise_omniauth_callback(mapping, controllers) #:nodoc:
|
||||
path_prefix = "/#{mapping.path}/auth"
|
||||
path, @scope[:path] = @scope[:path], nil
|
||||
path_prefix = "/#{mapping.path}/auth".squeeze("/")
|
||||
|
||||
if ::OmniAuth.config.path_prefix && ::OmniAuth.config.path_prefix != path_prefix
|
||||
warn "[DEVISE] You can only add :omniauthable behavior to one model."
|
||||
@@ -271,8 +272,10 @@ module ActionDispatch::Routing
|
||||
::OmniAuth.config.path_prefix = path_prefix
|
||||
end
|
||||
|
||||
match "/auth/:action/callback", :action => Regexp.union(mapping.to.omniauth_providers.map(&:to_s)),
|
||||
match "#{path_prefix}/:action/callback", :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) #:nodoc:
|
||||
|
||||
@@ -47,6 +47,10 @@ unless Devise.rack_session?
|
||||
alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
|
||||
alias_method :regular_update, :update unless method_defined?(:regular_update)
|
||||
|
||||
def [](key)
|
||||
super(convert_key(key))
|
||||
end
|
||||
|
||||
def []=(key, value)
|
||||
regular_writer(convert_key(key), value)
|
||||
end
|
||||
@@ -91,6 +95,7 @@ unless Devise.rack_session?
|
||||
def symbolize_keys; to_hash.symbolize_keys end
|
||||
|
||||
def to_options!; self end
|
||||
def to_hash; Hash.new.update(self) end
|
||||
|
||||
protected
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ module Devise
|
||||
# and overwrite the apply_schema method.
|
||||
module Schema
|
||||
|
||||
# Creates email, encrypted_password and password_salt.
|
||||
# Creates email when enabled (on by default), encrypted_password and password_salt.
|
||||
#
|
||||
# == Options
|
||||
# * :null - When true, allow columns to be null.
|
||||
@@ -15,8 +15,9 @@ module Devise
|
||||
def database_authenticatable(options={})
|
||||
null = options[:null] || false
|
||||
default = options.key?(:default) ? options[:default] : ("" if null == false)
|
||||
include_email = !self.respond_to?(:authentication_keys) || self.authentication_keys.include?(:email)
|
||||
|
||||
apply_devise_schema :email, String, :null => null, :default => default
|
||||
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
|
||||
|
||||
|
||||
@@ -19,13 +19,27 @@ module Devise
|
||||
result = resource && resource.valid_for_authentication?(&block)
|
||||
|
||||
case result
|
||||
when Symbol, String
|
||||
when String, Symbol
|
||||
fail!(result)
|
||||
false
|
||||
when TrueClass
|
||||
decorate(resource)
|
||||
true
|
||||
else
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
# Get values from params and set in the resource.
|
||||
def decorate(resource)
|
||||
resource.remember_me = remember_me? if resource.respond_to?(:remember_me=)
|
||||
end
|
||||
|
||||
# Should this resource be marked to be remembered?
|
||||
def remember_me?
|
||||
valid_params? && Devise::TRUE_VALUES.include?(params_auth_hash[:remember_me])
|
||||
end
|
||||
|
||||
# Check if this is strategy is valid for http authentication by:
|
||||
#
|
||||
# * Validating if the model allows params authentication;
|
||||
|
||||
@@ -10,7 +10,7 @@ module Devise
|
||||
if validate(resource){ resource.valid_password?(password) }
|
||||
resource.after_database_authentication
|
||||
success!(resource)
|
||||
else
|
||||
elsif !halted?
|
||||
fail(:invalid)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -20,7 +20,7 @@ module Devise
|
||||
|
||||
if validate(resource)
|
||||
success!(resource)
|
||||
else
|
||||
elsif !halted?
|
||||
cookies.delete(remember_key)
|
||||
pass
|
||||
end
|
||||
@@ -28,6 +28,11 @@ module Devise
|
||||
|
||||
private
|
||||
|
||||
def decorate(resource)
|
||||
super
|
||||
resource.extend_remember_period = mapping.to.extend_remember_period if resource.respond_to?(:extend_remember_period=)
|
||||
end
|
||||
|
||||
def remember_me?
|
||||
true
|
||||
end
|
||||
@@ -36,10 +41,6 @@ module Devise
|
||||
"remember_#{scope}_token"
|
||||
end
|
||||
|
||||
def extend_remember_period?
|
||||
mapping.to.extend_remember_period
|
||||
end
|
||||
|
||||
# Accessor for remember cookie
|
||||
def remember_cookie
|
||||
@remember_cookie ||= cookies.signed[remember_key]
|
||||
|
||||
@@ -20,7 +20,7 @@ module Devise
|
||||
if validate(resource)
|
||||
resource.after_token_authentication
|
||||
success!(resource)
|
||||
else
|
||||
elsif !halted?
|
||||
fail(:invalid_token)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
module Devise
|
||||
# Devise::TestHelpers provides a facility to test controllers in isolation
|
||||
# when using ActionController::TestCase allowing you to quickly sign_in or
|
||||
# sign_out an user. Do not use Devise::TestHelpers in integration tests.
|
||||
# sign_out a user. Do not use Devise::TestHelpers in integration tests.
|
||||
#
|
||||
# Notice you should not test Warden specific behavior (like Warden callbacks)
|
||||
# using Devise::TestHelpers since it is a stub of the actual behavior. Such
|
||||
@@ -44,9 +44,9 @@ module Devise
|
||||
env = @controller.request.env
|
||||
env["PATH_INFO"] = "/#{result[:action]}"
|
||||
env["warden.options"] = result
|
||||
Warden::Manager._before_failure.each{ |hook| hook.call(env, result) }
|
||||
Warden::Manager._run_callbacks(:before_failure, env, result)
|
||||
|
||||
status, headers, body = Devise::FailureApp.call(env).to_a
|
||||
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"]
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
module Devise
|
||||
VERSION = "1.2.rc".freeze
|
||||
VERSION = "1.2.1".freeze
|
||||
end
|
||||
|
||||
@@ -10,7 +10,7 @@ module ActiveRecord
|
||||
source_root File.expand_path("../templates", __FILE__)
|
||||
|
||||
def generate_model
|
||||
invoke "active_record:model", [name], :migration => false unless model_exists?
|
||||
invoke "active_record:model", [name], :migration => false unless model_exists? && behavior == :invoke
|
||||
end
|
||||
|
||||
def copy_devise_migration
|
||||
@@ -18,7 +18,7 @@ module ActiveRecord
|
||||
end
|
||||
|
||||
def inject_devise_content
|
||||
inject_into_class model_path, class_name, 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
|
||||
|
||||
@@ -22,6 +22,7 @@ class DeviseCreate<%= table_name.camelize %> < ActiveRecord::Migration
|
||||
add_index :<%= table_name %>, :reset_password_token, :unique => true
|
||||
# add_index :<%= table_name %>, :confirmation_token, :unique => true
|
||||
# add_index :<%= table_name %>, :unlock_token, :unique => true
|
||||
# add_index :<%= table_name %>, :authentication_token, :unique => true
|
||||
end
|
||||
|
||||
def self.down
|
||||
|
||||
@@ -10,7 +10,9 @@ module Devise
|
||||
hook_for :orm
|
||||
|
||||
def add_devise_routes
|
||||
route "devise_for :#{table_name}"
|
||||
devise_route = "devise_for :#{plural_name}"
|
||||
devise_route += %Q(, :class_name => "#{class_name}") if class_name.include?("::")
|
||||
route devise_route
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -12,8 +12,7 @@ CONTENT
|
||||
end
|
||||
|
||||
def model_exists?
|
||||
return @model_exists if instance_variable_defined?(:@model_exists)
|
||||
@model_exists = File.exists?(File.join(destination_root, model_path))
|
||||
File.exists?(File.join(destination_root, model_path))
|
||||
end
|
||||
|
||||
def model_path
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
require 'tmpdir'
|
||||
|
||||
module Devise
|
||||
module Generators
|
||||
class ViewsGenerator < Rails::Generators::Base
|
||||
@@ -8,56 +10,17 @@ module Devise
|
||||
:desc => "The scope to copy views to"
|
||||
|
||||
class_option :template_engine, :type => :string, :aliases => "-t",
|
||||
:desc => "Template engine for the views. Available options are 'erb' and 'haml'."
|
||||
:desc => "Template engine for the views. Available options are 'erb', 'haml' and 'slim'."
|
||||
|
||||
def copy_views
|
||||
case options[:template_engine].to_s
|
||||
when "haml"
|
||||
verify_haml_existence
|
||||
verify_haml_version
|
||||
create_and_copy_haml_views
|
||||
template = options[:template_engine].to_s
|
||||
case template
|
||||
when "haml", "slim"
|
||||
warn "#{template} templates have been removed from Devise gem"
|
||||
else
|
||||
directory "devise", "app/views/#{scope || :devise}"
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def verify_haml_existence
|
||||
begin
|
||||
require 'haml'
|
||||
rescue LoadError
|
||||
say "HAML is not installed, or it is not specified in your Gemfile."
|
||||
exit
|
||||
end
|
||||
end
|
||||
|
||||
def verify_haml_version
|
||||
unless Haml.version[:major] == 2 and Haml.version[:minor] >= 3 or Haml.version[:major] >= 3
|
||||
say "To generate HAML templates, you need to install HAML 2.3 or above."
|
||||
exit
|
||||
end
|
||||
end
|
||||
|
||||
def create_and_copy_haml_views
|
||||
require 'tmpdir'
|
||||
html_root = "#{self.class.source_root}/devise"
|
||||
|
||||
Dir.mktmpdir("devise-haml.") do |haml_root|
|
||||
Dir["#{html_root}/**/*"].each do |path|
|
||||
relative_path = path.sub(html_root, "")
|
||||
source_path = (haml_root + relative_path).sub(/erb$/, "haml")
|
||||
|
||||
if File.directory?(path)
|
||||
FileUtils.mkdir_p(source_path)
|
||||
else
|
||||
`html2haml -r #{path} #{source_path}`
|
||||
end
|
||||
end
|
||||
|
||||
directory haml_root, "app/views/#{scope || :devise}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -6,11 +6,11 @@ module Mongoid
|
||||
include Devise::Generators::OrmHelpers
|
||||
|
||||
def generate_model
|
||||
invoke "mongoid:model", [name] unless model_exists?
|
||||
invoke "mongoid:model", [name] unless model_exists? && behavior == :invoke
|
||||
end
|
||||
|
||||
def inject_devise_content
|
||||
inject_into_file model_path, model_contents, :after => "include Mongoid::Document\n"
|
||||
inject_into_file model_path, model_contents, :after => "include Mongoid::Document\n" if model_exists?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -34,7 +34,7 @@ Devise.setup do |config|
|
||||
# Configure which authentication keys should be case-insensitive.
|
||||
# These keys will be downcased upon creating or modifying a user and when used
|
||||
# to authenticate or find a user. Default is :email.
|
||||
# config.case_insensitive_keys = [ :email ]
|
||||
config.case_insensitive_keys = [ :email ]
|
||||
|
||||
# Tell if authentication through request.params is enabled. True by default.
|
||||
# config.params_authenticatable = true
|
||||
@@ -53,6 +53,9 @@ Devise.setup do |config|
|
||||
# using other encryptors, it sets how many times you want the password re-encrypted.
|
||||
config.stretches = 10
|
||||
|
||||
# Setup a pepper to generate the encrypted password.
|
||||
# config.pepper = <%= ActiveSupport::SecureRandom.hex(64).inspect %>
|
||||
|
||||
# ==> Configuration for :confirmable
|
||||
# The time you want to give your user to confirm his account. During this time
|
||||
# he will be able to access your application without confirming. Default is 0.days
|
||||
@@ -62,6 +65,9 @@ Devise.setup do |config|
|
||||
# (ie 2 days).
|
||||
# config.confirm_within = 2.days
|
||||
|
||||
# Defines which key will be used when confirming an account
|
||||
# config.confirmation_keys = [ :email ]
|
||||
|
||||
# ==> Configuration for :rememberable
|
||||
# The time the user will be remembered without asking for credentials again.
|
||||
# config.remember_for = 2.weeks
|
||||
@@ -81,7 +87,7 @@ Devise.setup do |config|
|
||||
# config.password_length = 6..20
|
||||
|
||||
# Regex to use to validate the email address
|
||||
# config.email_regexp = /^([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})$/i
|
||||
# config.email_regexp = /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\z/i
|
||||
|
||||
# ==> Configuration for :timeoutable
|
||||
# The time you want to timeout the user session without activity. After this
|
||||
@@ -94,6 +100,9 @@ Devise.setup do |config|
|
||||
# :none = No lock strategy. You should handle locking by yourself.
|
||||
# config.lock_strategy = :failed_attempts
|
||||
|
||||
# Defines which key will be used when locking and unlocking an account
|
||||
# config.unlock_keys = [ :email ]
|
||||
|
||||
# Defines which strategy will be used to unlock an account.
|
||||
# :email = Sends an unlock link to the user email
|
||||
# :time = Re-enables login after a certain amount of time (see :unlock_in below)
|
||||
@@ -108,6 +117,11 @@ Devise.setup do |config|
|
||||
# Time interval to unlock the account if :time is enabled as unlock_strategy.
|
||||
# config.unlock_in = 1.hour
|
||||
|
||||
# ==> Configuration for :recoverable
|
||||
#
|
||||
# Defines which key will be used when recovering the password for an account
|
||||
# config.reset_password_keys = [ :email ]
|
||||
|
||||
# ==> Configuration for :encryptable
|
||||
# Allow you to use another encryption algorithm besides bcrypt (default). You can use
|
||||
# :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1,
|
||||
@@ -116,9 +130,6 @@ Devise.setup do |config|
|
||||
# REST_AUTH_SITE_KEY to pepper)
|
||||
# config.encryptor = :sha512
|
||||
|
||||
# Setup a pepper to generate the encrypted password.
|
||||
# config.pepper = <%= ActiveSupport::SecureRandom.hex(64).inspect %>
|
||||
|
||||
# ==> Configuration for :token_authenticatable
|
||||
# Defines name of the authentication token params key
|
||||
# config.token_authentication_key = :auth_token
|
||||
@@ -150,8 +161,9 @@ Devise.setup do |config|
|
||||
# If you have any extra navigational formats, like :iphone or :mobile, you
|
||||
# should add them to the navigational formats lists.
|
||||
#
|
||||
# The :"*/*" format below is required to match Internet Explorer requests.
|
||||
# config.navigational_formats = [:"*/*", :html]
|
||||
# The :"*/*" and "*/*" formats below is required to match Internet
|
||||
# Explorer requests.
|
||||
# config.navigational_formats = [:"*/*", "*/*", :html]
|
||||
|
||||
# The default HTTP method used to sign out a resource. Default is :get.
|
||||
# config.sign_out_via = :get
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
require 'test_helper'
|
||||
require 'ostruct'
|
||||
|
||||
class ControllerAuthenticableTest < ActionController::TestCase
|
||||
class ControllerAuthenticatableTest < ActionController::TestCase
|
||||
tests ApplicationController
|
||||
|
||||
def setup
|
||||
@@ -13,16 +13,16 @@ class ControllerAuthenticableTest < ActionController::TestCase
|
||||
assert_equal @mock_warden, @controller.warden
|
||||
end
|
||||
|
||||
test 'proxy signed_in? to authenticated' do
|
||||
test 'proxy signed_in?(scope) to authenticate?' do
|
||||
@mock_warden.expects(:authenticate?).with(:scope => :my_scope)
|
||||
@controller.signed_in?(:my_scope)
|
||||
end
|
||||
|
||||
test 'proxy anybody_signed_in? to signed_in?' do
|
||||
test 'proxy signed_in?(nil) to authenticate?' do
|
||||
Devise.mappings.keys.each do |scope| # :user, :admin, :manager
|
||||
@controller.expects(:signed_in?).with(scope)
|
||||
@mock_warden.expects(:authenticate?).with(:scope => scope)
|
||||
end
|
||||
@controller.anybody_signed_in?
|
||||
@controller.signed_in?
|
||||
end
|
||||
|
||||
test 'proxy current_user to authenticate with user scope' do
|
||||
@@ -90,16 +90,32 @@ class ControllerAuthenticableTest < ActionController::TestCase
|
||||
|
||||
test 'sign in proxy to set_user on warden' do
|
||||
user = User.new
|
||||
@mock_warden.expects(:user).returns(nil)
|
||||
@mock_warden.expects(:set_user).with(user, :scope => :user).returns(true)
|
||||
@controller.sign_in(:user, user)
|
||||
end
|
||||
|
||||
test 'sign in accepts a resource as argument' do
|
||||
user = User.new
|
||||
@mock_warden.expects(:user).returns(nil)
|
||||
@mock_warden.expects(:set_user).with(user, :scope => :user).returns(true)
|
||||
@controller.sign_in(user)
|
||||
end
|
||||
|
||||
test 'does not sign in again if the user is already in' do
|
||||
user = User.new
|
||||
@mock_warden.expects(:user).returns(user)
|
||||
@mock_warden.expects(:set_user).never
|
||||
@controller.sign_in(user)
|
||||
end
|
||||
|
||||
test 'sign in again when the user is already in only if force is given' do
|
||||
user = User.new
|
||||
@mock_warden.expects(:user).returns(user)
|
||||
@mock_warden.expects(:set_user).with(user, :scope => :user).returns(true)
|
||||
@controller.sign_in(user, :force => true)
|
||||
end
|
||||
|
||||
test 'sign in accepts bypass as option' do
|
||||
user = User.new
|
||||
@mock_warden.expects(:session_serializer).returns(serializer = mock())
|
||||
@@ -120,11 +136,13 @@ class ControllerAuthenticableTest < ActionController::TestCase
|
||||
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)
|
||||
@controller.sign_out
|
||||
end
|
||||
|
||||
test 'sign out everybody proxy to logout on warden' do
|
||||
@mock_warden.expects(:user).times(Devise.mappings.size)
|
||||
@mock_warden.expects(:logout).with().returns(true)
|
||||
@controller.sign_out_all_scopes
|
||||
end
|
||||
@@ -185,6 +203,17 @@ class ControllerAuthenticableTest < ActionController::TestCase
|
||||
@controller.sign_in_and_redirect(admin)
|
||||
end
|
||||
|
||||
test 'redirect_location returns the stored location if set' do
|
||||
user = User.new
|
||||
@controller.session[:"user_return_to"] = "/foo.bar"
|
||||
assert_equal '/foo.bar', @controller.redirect_location('user', user)
|
||||
end
|
||||
|
||||
test 'redirect_location returns the after sign in path by default' do
|
||||
user = User.new
|
||||
assert_equal @controller.after_sign_in_path_for(:user), @controller.redirect_location('user', user)
|
||||
end
|
||||
|
||||
test 'sign out and redirect uses the configured after sign out path when signing out only the current scope' do
|
||||
swap Devise, :sign_out_all_scopes => false do
|
||||
@mock_warden.expects(:user).with(:admin).returns(true)
|
||||
@@ -197,6 +226,7 @@ class ControllerAuthenticableTest < ActionController::TestCase
|
||||
|
||||
test 'sign out and redirect uses the configured after sign out path when signing out all scopes' do
|
||||
swap Devise, :sign_out_all_scopes => true do
|
||||
@mock_warden.expects(:user).times(Devise.mappings.size)
|
||||
@mock_warden.expects(:logout).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"
|
||||
|
||||
@@ -62,4 +62,14 @@ class DeviseTest < ActiveSupport::TestCase
|
||||
assert_nothing_raised(Exception) { Devise.add_module(:authenticatable_again, :model => 'devise/model/authenticatable') }
|
||||
assert defined?(Devise::Models::AuthenticatableAgain)
|
||||
end
|
||||
|
||||
test 'should complain when comparing empty or different sized passes' do
|
||||
[nil, ""].each do |empty|
|
||||
assert_not Devise.secure_compare(empty, "something")
|
||||
assert_not Devise.secure_compare("something", empty)
|
||||
assert_not Devise.secure_compare(empty, empty)
|
||||
end
|
||||
assert_not Devise.secure_compare("size_1", "size_four")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -13,7 +13,7 @@ class FailureTest < ActiveSupport::TestCase
|
||||
'REQUEST_METHOD' => 'GET',
|
||||
'warden.options' => { :scope => :user },
|
||||
'rack.session' => {},
|
||||
'action_dispatch.request.formats' => Array(env_params.delete('formats') || :html),
|
||||
'action_dispatch.request.formats' => Array(env_params.delete('formats') || Mime::HTML),
|
||||
'rack.input' => "",
|
||||
'warden' => OpenStruct.new(:message => nil)
|
||||
}.merge!(env_params)
|
||||
@@ -69,6 +69,13 @@ class FailureTest < ActiveSupport::TestCase
|
||||
assert_equal 302, @response.first
|
||||
end
|
||||
end
|
||||
|
||||
test 'redirects the correct format if it is a non-html format request' do
|
||||
swap Devise, :navigational_formats => [:js] do
|
||||
call_failure('formats' => :js)
|
||||
assert_equal 'http://test.host/users/sign_in.js', @response.second["Location"]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'For HTTP request' do
|
||||
@@ -120,7 +127,7 @@ class FailureTest < ActiveSupport::TestCase
|
||||
swap Devise, :http_authenticatable_on_xhr => false do
|
||||
call_failure('formats' => :json, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
|
||||
assert_equal 302, @response.first
|
||||
assert_equal 'http://test.host/users/sign_in', @response.second["Location"]
|
||||
assert_equal 'http://test.host/users/sign_in.json', @response.second["Location"]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -144,7 +151,7 @@ class FailureTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
context 'With recall' do
|
||||
test 'calls the original controller' do
|
||||
test 'calls the original controller if invalid email or password' do
|
||||
env = {
|
||||
"warden.options" => { :recall => "devise/sessions#new", :attempted_path => "/users/sign_in" },
|
||||
"devise.mapping" => Devise.mappings[:user],
|
||||
@@ -154,5 +161,27 @@ class FailureTest < ActiveSupport::TestCase
|
||||
assert @response.third.body.include?('<h2>Sign in</h2>')
|
||||
assert @response.third.body.include?('Invalid email or password.')
|
||||
end
|
||||
|
||||
test 'calls the original controller if not confirmed email' do
|
||||
env = {
|
||||
"warden.options" => { :recall => "devise/sessions#new", :attempted_path => "/users/sign_in", :message => :unconfirmed },
|
||||
"devise.mapping" => Devise.mappings[:user],
|
||||
"warden" => stub_everything
|
||||
}
|
||||
call_failure(env)
|
||||
assert @response.third.body.include?('<h2>Sign in</h2>')
|
||||
assert @response.third.body.include?('You have to confirm your account before continuing.')
|
||||
end
|
||||
|
||||
test 'calls the original controller if inactive account' do
|
||||
env = {
|
||||
"warden.options" => { :recall => "devise/sessions#new", :attempted_path => "/users/sign_in", :message => :inactive },
|
||||
"devise.mapping" => Devise.mappings[:user],
|
||||
"warden" => stub_everything
|
||||
}
|
||||
call_failure(env)
|
||||
assert @response.third.body.include?('<h2>Sign in</h2>')
|
||||
assert @response.third.body.include?('Your account was not activated yet.')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
24
test/generators/active_record_generator_test.rb
Normal file
24
test/generators/active_record_generator_test.rb
Normal file
@@ -0,0 +1,24 @@
|
||||
require "test_helper"
|
||||
|
||||
if DEVISE_ORM == :active_record
|
||||
require "generators/active_record/devise_generator"
|
||||
|
||||
class ActiveRecordGeneratorTest < Rails::Generators::TestCase
|
||||
tests ActiveRecord::Generators::DeviseGenerator
|
||||
destination File.expand_path("../../tmp", __FILE__)
|
||||
setup :prepare_destination
|
||||
|
||||
test "all files are properly created" do
|
||||
run_generator %w(monster)
|
||||
assert_file "app/models/monster.rb", /devise/, /attr_accessible (:[a-z_]+(, )?)+/
|
||||
assert_migration "db/migrate/devise_create_monsters.rb"
|
||||
end
|
||||
|
||||
test "all files are properly deleted" do
|
||||
run_generator %w(monster)
|
||||
run_generator %w(monster), :behavior => :revoke
|
||||
assert_no_file "app/models/monster.rb"
|
||||
assert_no_migration "db/migrate/devise_create_monsters.rb"
|
||||
end
|
||||
end
|
||||
end
|
||||
33
test/generators/devise_generator_test.rb
Normal file
33
test/generators/devise_generator_test.rb
Normal file
@@ -0,0 +1,33 @@
|
||||
require 'test_helper'
|
||||
|
||||
require "generators/devise/devise_generator"
|
||||
|
||||
class DeviseGeneratorTest < Rails::Generators::TestCase
|
||||
tests Devise::Generators::DeviseGenerator
|
||||
destination File.expand_path("../../tmp", __FILE__)
|
||||
|
||||
setup do
|
||||
prepare_destination
|
||||
copy_routes
|
||||
end
|
||||
|
||||
test "route generation for simple model names" do
|
||||
run_generator %w(monster name:string)
|
||||
assert_file "config/routes.rb", /devise_for :monsters/
|
||||
end
|
||||
|
||||
test "route generation for namespaced model names" do
|
||||
run_generator %w(monster/goblin name:string)
|
||||
match = /devise_for :goblins, :class_name => "Monster::Goblin"/
|
||||
assert_file "config/routes.rb", match
|
||||
end
|
||||
|
||||
def copy_routes
|
||||
routes = File.expand_path("../../rails_app/config/routes.rb", __FILE__)
|
||||
destination = File.join(destination_root, "config")
|
||||
|
||||
FileUtils.mkdir_p(destination)
|
||||
FileUtils.cp routes, destination
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,4 +0,0 @@
|
||||
require "rubygems"
|
||||
require "rails/generators/test_case"
|
||||
require File.join(File.dirname(__FILE__), "../../lib/generators/devise/install_generator")
|
||||
require File.join(File.dirname(__FILE__), "../../lib/generators/devise/views_generator")
|
||||
@@ -1,14 +1,13 @@
|
||||
require File.join(File.dirname(__FILE__),"generators_test_helper.rb")
|
||||
require "test_helper"
|
||||
|
||||
class InstallGeneratorTest < Rails::Generators::TestCase
|
||||
tests Devise::Generators::InstallGenerator
|
||||
destination File.expand_path("../tmp", File.dirname(__FILE__))
|
||||
destination File.expand_path("../../tmp", __FILE__)
|
||||
setup :prepare_destination
|
||||
|
||||
test "Assert all files are properly created" do
|
||||
run_generator
|
||||
assert_file "config/initializers/devise.rb"
|
||||
assert_file "config/initializers/devise.rb"
|
||||
assert_file "config/locales/devise.en.yml"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
22
test/generators/mongoid_generator_test.rb
Normal file
22
test/generators/mongoid_generator_test.rb
Normal file
@@ -0,0 +1,22 @@
|
||||
require "test_helper"
|
||||
|
||||
if DEVISE_ORM == :mongo_id
|
||||
require "generators/mongo_id/devise_generator"
|
||||
|
||||
class MongoidGeneratorTest < Rails::Generators::TestCase
|
||||
tests Mongoid::Generators::DeviseGenerator
|
||||
destination File.expand_path("../../tmp", __FILE__)
|
||||
setup :prepare_destination
|
||||
|
||||
test "all files are properly created" do
|
||||
run_generator %w(monster)
|
||||
assert_file "app/models/monster.rb", /devise/
|
||||
end
|
||||
|
||||
test "all files are properly deleted" do
|
||||
run_generator %w(monster)
|
||||
run_generator %w(monster), :behavior => :revoke
|
||||
assert_no_file "app/models/monster.rb"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,8 +1,8 @@
|
||||
require File.join(File.dirname(__FILE__),"generators_test_helper.rb")
|
||||
require "test_helper"
|
||||
|
||||
class ViewsGeneratorTest < Rails::Generators::TestCase
|
||||
tests Devise::Generators::ViewsGenerator
|
||||
destination File.expand_path("../tmp", File.dirname(__FILE__))
|
||||
destination File.expand_path("../../tmp", __FILE__)
|
||||
setup :prepare_destination
|
||||
|
||||
test "Assert all views are properly created with no params" do
|
||||
@@ -20,18 +20,16 @@ class ViewsGeneratorTest < Rails::Generators::TestCase
|
||||
|
||||
def assert_files(scope = nil, template_engine = nil)
|
||||
scope = "devise" if scope.nil?
|
||||
assert_file "app/views/#{scope}/confirmations/new.html.erb"
|
||||
assert_file "app/views/#{scope}/mailer/confirmation_instructions.html.erb"
|
||||
assert_file "app/views/#{scope}/mailer/reset_password_instructions.html.erb"
|
||||
assert_file "app/views/#{scope}/mailer/unlock_instructions.html.erb"
|
||||
assert_file "app/views/#{scope}/passwords/edit.html.erb"
|
||||
assert_file "app/views/#{scope}/passwords/new.html.erb"
|
||||
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}/confirmations/new.html.erb"
|
||||
assert_file "app/views/#{scope}/mailer/confirmation_instructions.html.erb"
|
||||
assert_file "app/views/#{scope}/mailer/reset_password_instructions.html.erb"
|
||||
assert_file "app/views/#{scope}/mailer/unlock_instructions.html.erb"
|
||||
assert_file "app/views/#{scope}/passwords/edit.html.erb"
|
||||
assert_file "app/views/#{scope}/passwords/new.html.erb"
|
||||
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"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
33
test/indifferent_hash.rb
Normal file
33
test/indifferent_hash.rb
Normal file
@@ -0,0 +1,33 @@
|
||||
require 'test_helper'
|
||||
|
||||
class IndifferentHashTest < ActiveSupport::TestCase
|
||||
setup do
|
||||
@hash = Devise::IndifferentHash.new
|
||||
end
|
||||
|
||||
test "it overwrites getter and setter" do
|
||||
@hash[:foo] = "bar"
|
||||
assert_equal "bar", @hash["foo"]
|
||||
assert_equal "bar", @hash[:foo]
|
||||
|
||||
@hash["foo"] = "baz"
|
||||
assert_equal "baz", @hash["foo"]
|
||||
assert_equal "baz", @hash[:foo]
|
||||
end
|
||||
|
||||
test "it overwrites update" do
|
||||
@hash.update :foo => "bar"
|
||||
assert_equal "bar", @hash["foo"]
|
||||
assert_equal "bar", @hash[:foo]
|
||||
|
||||
@hash.update "foo" => "baz"
|
||||
assert_equal "baz", @hash["foo"]
|
||||
assert_equal "baz", @hash[:foo]
|
||||
end
|
||||
|
||||
test "it returns a Hash on to_hash" do
|
||||
@hash[:foo] = "bar"
|
||||
assert_equal Hash["foo", "bar"], @hash.to_hash
|
||||
assert_kind_of Hash, @hash.to_hash
|
||||
end
|
||||
end if defined?(Devise::IndifferentHash)
|
||||
@@ -205,6 +205,13 @@ class AuthenticationRedirectTest < ActionController::IntegrationTest
|
||||
assert_nil session[:"user_return_to"]
|
||||
end
|
||||
|
||||
test 'sign in with xml format returns xml response' do
|
||||
create_user
|
||||
post user_session_path(:format => 'xml', :user => {:email => "user@test.com", :password => '123456'})
|
||||
assert_response :success
|
||||
assert_match /<\?xml version="1.0" encoding="UTF-8"\?>/, response.body
|
||||
end
|
||||
|
||||
test 'redirect to configured home path for a given scope after sign in' do
|
||||
sign_in_as_admin
|
||||
assert_equal "/admin_area/home", @request.path
|
||||
|
||||
@@ -2,32 +2,42 @@ require 'test_helper'
|
||||
|
||||
class OmniauthableIntegrationTest < ActionController::IntegrationTest
|
||||
FACEBOOK_INFO = {
|
||||
:id => '12345',
|
||||
:link => 'http://facebook.com/josevalim',
|
||||
:email => 'user@example.com',
|
||||
:first_name => 'Jose',
|
||||
:last_name => 'Valim',
|
||||
:website => 'http://blog.plataformatec.com.br'
|
||||
}
|
||||
|
||||
ACCESS_TOKEN = {
|
||||
:access_token => "plataformatec"
|
||||
"id" => '12345',
|
||||
"link" => 'http://facebook.com/josevalim',
|
||||
"email" => 'user@example.com',
|
||||
"first_name" => 'Jose',
|
||||
"last_name" => 'Valim',
|
||||
"website" => 'http://blog.plataformatec.com.br'
|
||||
}
|
||||
|
||||
setup do
|
||||
OmniAuth.config.test_mode = true
|
||||
stub_facebook!
|
||||
Devise::OmniAuth.short_circuit_authorizers!
|
||||
end
|
||||
|
||||
teardown do
|
||||
Devise::OmniAuth.unshort_circuit_authorizers!
|
||||
Devise::OmniAuth.reset_stubs!
|
||||
OmniAuth.config.test_mode = false
|
||||
end
|
||||
|
||||
def stub_facebook!
|
||||
Devise::OmniAuth.stub!(:facebook) do |b|
|
||||
b.post('/oauth/access_token') { [200, {}, ACCESS_TOKEN.to_json] }
|
||||
b.get('/me?access_token=plataformatec') { [200, {}, FACEBOOK_INFO.to_json] }
|
||||
OmniAuth.config.mock_auth[:facebook] = {
|
||||
"uid" => '12345',
|
||||
"provider" => 'facebook',
|
||||
"user_info" => {"nickname" => 'josevalim'},
|
||||
"credentials" => {"token" => 'plataformatec'},
|
||||
"extra" => {"user_hash" => FACEBOOK_INFO}
|
||||
}
|
||||
end
|
||||
|
||||
def stub_action!(name)
|
||||
Users::OmniauthCallbacksController.class_eval do
|
||||
alias_method :__old_facebook, :facebook
|
||||
alias_method :facebook, name
|
||||
end
|
||||
yield
|
||||
ensure
|
||||
Users::OmniauthCallbacksController.class_eval do
|
||||
alias_method :facebook, :__old_facebook
|
||||
end
|
||||
end
|
||||
|
||||
@@ -40,11 +50,11 @@ class OmniauthableIntegrationTest < ActionController::IntegrationTest
|
||||
assert_equal "12345", json["uid"]
|
||||
assert_equal "facebook", json["provider"]
|
||||
assert_equal "josevalim", json["user_info"]["nickname"]
|
||||
assert_equal FACEBOOK_INFO, json["extra"]["user_hash"].symbolize_keys
|
||||
assert_equal FACEBOOK_INFO, json["extra"]["user_hash"]
|
||||
assert_equal "plataformatec", json["credentials"]["token"]
|
||||
end
|
||||
|
||||
test "cleans up session on sign up" do
|
||||
test "cleans up session on sign up" do
|
||||
assert_no_difference "User.count" do
|
||||
visit "/users/sign_in"
|
||||
click_link "Sign in with Facebook"
|
||||
@@ -65,7 +75,7 @@ class OmniauthableIntegrationTest < ActionController::IntegrationTest
|
||||
assert_not session["devise.facebook_data"]
|
||||
end
|
||||
|
||||
test "cleans up session on cancel" do
|
||||
test "cleans up session on cancel" do
|
||||
assert_no_difference "User.count" do
|
||||
visit "/users/sign_in"
|
||||
click_link "Sign in with Facebook"
|
||||
@@ -76,7 +86,7 @@ class OmniauthableIntegrationTest < ActionController::IntegrationTest
|
||||
assert !session["devise.facebook_data"]
|
||||
end
|
||||
|
||||
test "cleans up session on sign in" do
|
||||
test "cleans up session on sign in" do
|
||||
assert_no_difference "User.count" do
|
||||
visit "/users/sign_in"
|
||||
click_link "Sign in with Facebook"
|
||||
@@ -87,16 +97,37 @@ class OmniauthableIntegrationTest < ActionController::IntegrationTest
|
||||
assert !session["devise.facebook_data"]
|
||||
end
|
||||
|
||||
test "sign in and send remember token if configured" do
|
||||
visit "/users/sign_in"
|
||||
click_link "Sign in with Facebook"
|
||||
assert_nil warden.cookies["remember_user_token"]
|
||||
|
||||
stub_action!(:sign_in_facebook) do
|
||||
create_user
|
||||
visit "/users/sign_in"
|
||||
click_link "Sign in with Facebook"
|
||||
assert warden.authenticated?(:user)
|
||||
assert warden.cookies["remember_user_token"]
|
||||
end
|
||||
end
|
||||
|
||||
test "generates a proper link when SCRIPT_NAME is set" do
|
||||
header 'SCRIPT_NAME', '/q'
|
||||
visit "/users/sign_in"
|
||||
click_link "Sign in with Facebook"
|
||||
|
||||
assert_equal '/q/users/auth/facebook', current_url
|
||||
end
|
||||
|
||||
test "handles callback error parameter according to the specification" do
|
||||
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 authorize you from Facebook because "Access denied".'
|
||||
end
|
||||
|
||||
test "handles other exceptions from omniauth" do
|
||||
Devise::OmniAuth.stub!(:facebook) do |b|
|
||||
b.post('/oauth/access_token') { [401, {}, {}.to_json] }
|
||||
end
|
||||
OmniAuth.config.mock_auth[:facebook] = :invalid_credentials
|
||||
|
||||
visit "/users/sign_in"
|
||||
click_link "Sign in with facebook"
|
||||
@@ -104,4 +135,4 @@ class OmniauthableIntegrationTest < ActionController::IntegrationTest
|
||||
assert_current_url "/users/sign_in"
|
||||
assert_contain 'Could not authorize you from Facebook because "Invalid credentials".'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,11 +15,27 @@ class RegistrationTest < ActionController::IntegrationTest
|
||||
|
||||
assert_contain 'Welcome! You have signed up successfully.'
|
||||
assert warden.authenticated?(:admin)
|
||||
assert_current_url "/admin_area/home"
|
||||
|
||||
admin = Admin.last :order => "id"
|
||||
assert_equal admin.email, 'new_user@test.com'
|
||||
end
|
||||
|
||||
test 'a guest admin should be able to sign in and be redirected to a custom location' do
|
||||
Devise::RegistrationsController.any_instance.stubs(:after_sign_up_path_for).returns("/?custom=1")
|
||||
get new_admin_session_path
|
||||
click_link 'Sign up'
|
||||
|
||||
fill_in 'email', :with => 'new_user@test.com'
|
||||
fill_in 'password', :with => 'new_user123'
|
||||
fill_in 'password confirmation', :with => 'new_user123'
|
||||
click_button 'Sign up'
|
||||
|
||||
assert_contain 'Welcome! You have signed up successfully.'
|
||||
assert warden.authenticated?(:admin)
|
||||
assert_current_url "/?custom=1"
|
||||
end
|
||||
|
||||
test 'a guest user should be able to sign up successfully and be blocked by confirmation' do
|
||||
get new_user_registration_path
|
||||
|
||||
@@ -30,6 +46,7 @@ class RegistrationTest < ActionController::IntegrationTest
|
||||
|
||||
assert_contain 'You have signed up successfully. However, we could not sign you in because your account is unconfirmed.'
|
||||
assert_not_contain 'You have to confirm your account before continuing'
|
||||
assert_current_url "/"
|
||||
|
||||
assert_not warden.authenticated?(:user)
|
||||
|
||||
@@ -38,6 +55,19 @@ class RegistrationTest < ActionController::IntegrationTest
|
||||
assert_not user.confirmed?
|
||||
end
|
||||
|
||||
test 'a guest user should be blocked by confirmation and redirected to a custom path' do
|
||||
Devise::RegistrationsController.any_instance.stubs(:after_inactive_sign_up_path_for).returns("/?custom=1")
|
||||
get new_user_registration_path
|
||||
|
||||
fill_in 'email', :with => 'new_user@test.com'
|
||||
fill_in 'password', :with => 'new_user123'
|
||||
fill_in 'password confirmation', :with => 'new_user123'
|
||||
click_button 'Sign up'
|
||||
|
||||
assert_current_url "/?custom=1"
|
||||
assert_not warden.authenticated?(:user)
|
||||
end
|
||||
|
||||
test 'a guest user cannot sign up with invalid information' do
|
||||
get new_user_registration_path
|
||||
|
||||
|
||||
@@ -28,9 +28,9 @@ class RememberMeTest < ActionController::IntegrationTest
|
||||
end
|
||||
|
||||
def cookie_expires(key)
|
||||
cookie = response.headers["Set-Cookie"].split("\n").grep(/^#{key}/).first
|
||||
cookie.split(";").map(&:strip).grep(/^expires=/)
|
||||
Time.parse($')
|
||||
cookie = response.headers["Set-Cookie"].split("\n").grep(/^#{key}/).first
|
||||
expires = cookie.split(";").map(&:strip).grep(/^expires=/).first
|
||||
Time.parse(expires).utc
|
||||
end
|
||||
|
||||
test 'do not remember the user if he has not checked remember me option' do
|
||||
@@ -69,6 +69,17 @@ class RememberMeTest < ActionController::IntegrationTest
|
||||
assert_response :success
|
||||
assert warden.authenticated?(:user)
|
||||
assert warden.user(:user) == user
|
||||
assert_match /remember_user_token[^\n]*HttpOnly\n/, response.headers["Set-Cookie"], "Expected Set-Cookie header in response to set HttpOnly flag on remember_user_token cookie."
|
||||
end
|
||||
|
||||
test 'cookies are destroyed on unverified requests' do
|
||||
swap ApplicationController, :allow_forgery_protection => true do
|
||||
user = create_user_and_remember
|
||||
get users_path
|
||||
assert warden.authenticated?(:user)
|
||||
post root_path, :authenticity_token => 'INVALID'
|
||||
assert_not warden.authenticated?(:user)
|
||||
end
|
||||
end
|
||||
|
||||
test 'does not extend remember period through sign in' do
|
||||
@@ -150,7 +161,6 @@ class RememberMeTest < ActionController::IntegrationTest
|
||||
|
||||
get users_path
|
||||
assert_not warden.authenticated?(:user)
|
||||
assert_nil warden.cookies['remember_user_token']
|
||||
end
|
||||
|
||||
test 'do not remember the admin anymore after forget' do
|
||||
@@ -160,11 +170,11 @@ class RememberMeTest < ActionController::IntegrationTest
|
||||
|
||||
get destroy_admin_session_path
|
||||
assert_not warden.authenticated?(:admin)
|
||||
assert_nil admin.reload.remember_token
|
||||
assert_nil warden.cookies['remember_admin_token']
|
||||
|
||||
get root_path
|
||||
assert_not warden.authenticated?(:admin)
|
||||
assert_nil warden.cookies['remember_admin_token']
|
||||
end
|
||||
|
||||
test 'changing user password expires remember me token' do
|
||||
@@ -176,4 +186,4 @@ class RememberMeTest < ActionController::IntegrationTest
|
||||
get users_path
|
||||
assert_not warden.authenticated?(:user)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -76,15 +76,42 @@ class TokenAuthenticationTest < ActionController::IntegrationTest
|
||||
end
|
||||
end
|
||||
|
||||
test 'authenticate with valid authentication token key and do not store if stateless and timeoutable are enabled' do
|
||||
swap Devise, :token_authentication_key => :secret_token, :stateless_token => true, :timeout_in => (0.1).second do
|
||||
user = sign_in_as_new_user_with_token
|
||||
assert warden.authenticated?(:user)
|
||||
|
||||
# Expiring does not work because we are setting the session value when accessing it
|
||||
sleep 0.3
|
||||
|
||||
get_users_path_as_existing_user(user)
|
||||
assert warden.authenticated?(:user)
|
||||
end
|
||||
end
|
||||
|
||||
test 'should not be subject to injection' do
|
||||
swap Devise, :token_authentication_key => :secret_token do
|
||||
user1 = create_user_with_authentication_token()
|
||||
|
||||
# Clean up user cache
|
||||
@user = nil
|
||||
|
||||
user2 = create_user_with_authentication_token(:email => "another@test.com")
|
||||
user2.update_attribute(:authentication_token, "ANOTHERTOKEN")
|
||||
|
||||
assert_not_equal user1, user2
|
||||
visit users_path(Devise.token_authentication_key.to_s + '[$ne]' => user1.authentication_token)
|
||||
assert_nil warden.user(:user)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def sign_in_as_new_user_with_token(options = {})
|
||||
options[:auth_token_key] ||= Devise.token_authentication_key
|
||||
options[:auth_token] ||= VALID_AUTHENTICATION_TOKEN
|
||||
user = options.delete(:user) || create_user_with_authentication_token(options)
|
||||
|
||||
user = create_user(options)
|
||||
user.authentication_token = VALID_AUTHENTICATION_TOKEN
|
||||
user.save
|
||||
options[:auth_token_key] ||= Devise.token_authentication_key
|
||||
options[:auth_token] ||= user.authentication_token
|
||||
|
||||
if options[:http_auth]
|
||||
header = "Basic #{ActiveSupport::Base64.encode64("#{VALID_AUTHENTICATION_TOKEN}:X")}"
|
||||
@@ -96,4 +123,15 @@ class TokenAuthenticationTest < ActionController::IntegrationTest
|
||||
user
|
||||
end
|
||||
|
||||
def create_user_with_authentication_token(options={})
|
||||
user = create_user(options)
|
||||
user.authentication_token = VALID_AUTHENTICATION_TOKEN
|
||||
user.save
|
||||
user
|
||||
end
|
||||
|
||||
def get_users_path_as_existing_user(user)
|
||||
sign_in_as_new_user_with_token(:user => user)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -51,7 +51,7 @@ class ConfirmableTest < ActiveSupport::TestCase
|
||||
assert_equal "was already confirmed, please try signing in", user.errors[:email].join
|
||||
end
|
||||
|
||||
test 'should find and confirm an user automatically' do
|
||||
test 'should find and confirm a user automatically' do
|
||||
user = create_user
|
||||
confirmed_user = User.confirm_by_token(user.confirmation_token)
|
||||
assert_equal confirmed_user, user
|
||||
@@ -127,7 +127,7 @@ class ConfirmableTest < ActiveSupport::TestCase
|
||||
User.send_confirmation_instructions(:email => user.email)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
test 'should always have confirmation token when email is sent' do
|
||||
user = new_user
|
||||
user.instance_eval { def confirmation_required?; false end }
|
||||
@@ -167,10 +167,10 @@ class ConfirmableTest < ActiveSupport::TestCase
|
||||
swap Devise, :confirm_within => 1.day do
|
||||
user = new_user
|
||||
user.confirmation_sent_at = 2.days.ago
|
||||
assert_not user.active?
|
||||
assert_not user.active_for_authentication?
|
||||
|
||||
Devise.confirm_within = 3.days
|
||||
assert user.active?
|
||||
assert user.active_for_authentication?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -180,42 +180,59 @@ class ConfirmableTest < ActiveSupport::TestCase
|
||||
user = create_user
|
||||
|
||||
user.confirmation_sent_at = 4.days.ago
|
||||
assert user.active?
|
||||
assert user.active_for_authentication?
|
||||
|
||||
user.confirmation_sent_at = 5.days.ago
|
||||
assert_not user.active?
|
||||
assert_not user.active_for_authentication?
|
||||
end
|
||||
end
|
||||
|
||||
test 'should be active when already confirmed' do
|
||||
user = create_user
|
||||
assert_not user.confirmed?
|
||||
assert_not user.active?
|
||||
assert_not user.active_for_authentication?
|
||||
|
||||
user.confirm!
|
||||
assert user.confirmed?
|
||||
assert user.active?
|
||||
assert user.active_for_authentication?
|
||||
end
|
||||
|
||||
test 'should not be active when confirm in is zero' do
|
||||
Devise.confirm_within = 0.days
|
||||
user = create_user
|
||||
user.confirmation_sent_at = Date.today
|
||||
assert_not user.active?
|
||||
assert_not user.active_for_authentication?
|
||||
end
|
||||
|
||||
test 'should not be active without confirmation' do
|
||||
user = create_user
|
||||
user.confirmation_sent_at = nil
|
||||
user.save
|
||||
assert_not user.reload.active?
|
||||
assert_not user.reload.active_for_authentication?
|
||||
end
|
||||
|
||||
|
||||
test 'should be active without confirmation when confirmation is not required' do
|
||||
user = create_user
|
||||
user.instance_eval { def confirmation_required?; false end }
|
||||
user.confirmation_sent_at = nil
|
||||
user.save
|
||||
assert user.reload.active?
|
||||
assert user.reload.active_for_authentication?
|
||||
end
|
||||
|
||||
test 'should find a user to send email instructions for the user confirm it\'s email by authentication_keys' do
|
||||
swap Devise, :authentication_keys => [:username, :email] do
|
||||
user = create_user
|
||||
confirm_user = User.send_confirmation_instructions(:email => user.email, :username => user.username)
|
||||
assert_equal confirm_user, user
|
||||
end
|
||||
end
|
||||
|
||||
test 'should require all confirmation_keys' do
|
||||
swap Devise, :confirmation_keys => [:username, :email] do
|
||||
user = create_user
|
||||
confirm_user = User.send_confirmation_instructions(:email => user.email)
|
||||
assert_not confirm_user.persisted?
|
||||
assert_equal "can't be blank", confirm_user.errors[:username].join
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -31,7 +31,7 @@ class EncryptableTest < ActiveSupport::TestCase
|
||||
|
||||
test 'should generate a base64 hash using SecureRandom for password salt' do
|
||||
swap_with_encryptor Admin, :sha1 do
|
||||
ActiveSupport::SecureRandom.expects(:base64).with(44).returns('friendly_token')
|
||||
ActiveSupport::SecureRandom.expects(:base64).with(15).returns('friendly_token')
|
||||
assert_equal 'friendly_token', create_admin.password_salt
|
||||
end
|
||||
end
|
||||
|
||||
@@ -47,15 +47,15 @@ class LockableTest < ActiveSupport::TestCase
|
||||
assert user.access_locked?
|
||||
end
|
||||
|
||||
test "active? should be the opposite of locked?" do
|
||||
test "active_for_authentication? should be the opposite of locked?" do
|
||||
user = create_user
|
||||
user.confirm!
|
||||
assert user.active?
|
||||
assert user.active_for_authentication?
|
||||
user.lock_access!
|
||||
assert_not user.active?
|
||||
assert_not user.active_for_authentication?
|
||||
end
|
||||
|
||||
test "should unlock an user by cleaning locked_at, falied_attempts and unlock_token" do
|
||||
test "should unlock a user by cleaning locked_at, falied_attempts and unlock_token" do
|
||||
user = create_user
|
||||
user.lock_access!
|
||||
assert_not_nil user.reload.locked_at
|
||||
@@ -67,12 +67,6 @@ class LockableTest < ActiveSupport::TestCase
|
||||
assert_equal 0, user.reload.failed_attempts
|
||||
end
|
||||
|
||||
test 'should not unlock an unlocked user' do
|
||||
user = create_user
|
||||
assert_not user.unlock_access!
|
||||
assert_match "was not locked", user.errors[:email].join
|
||||
end
|
||||
|
||||
test "new user should not be locked and should have zero failed_attempts" do
|
||||
assert_not new_user.access_locked?
|
||||
assert_equal 0, create_user.failed_attempts
|
||||
@@ -141,7 +135,7 @@ class LockableTest < ActiveSupport::TestCase
|
||||
end
|
||||
end
|
||||
|
||||
test 'should find and unlock an user automatically' do
|
||||
test 'should find and unlock a user automatically' do
|
||||
user = create_user
|
||||
user.lock_access!
|
||||
locked_user = User.unlock_access_by_token(user.unlock_token)
|
||||
@@ -186,13 +180,13 @@ class LockableTest < ActiveSupport::TestCase
|
||||
end
|
||||
end
|
||||
|
||||
test 'should require all authentication_keys' do
|
||||
swap Devise, :authentication_keys => [:username, :email] do
|
||||
user = create_user
|
||||
unlock_user = User.send_unlock_instructions(:email => user.email)
|
||||
assert_not unlock_user.persisted?
|
||||
assert_equal "can't be blank", unlock_user.errors[:username].join
|
||||
end
|
||||
test 'should require all unlock_keys' do
|
||||
swap Devise, :unlock_keys => [:username, :email] do
|
||||
user = create_user
|
||||
unlock_user = User.send_unlock_instructions(:email => user.email)
|
||||
assert_not unlock_user.persisted?
|
||||
assert_equal "can't be blank", unlock_user.errors[:username].join
|
||||
end
|
||||
end
|
||||
|
||||
test 'should not be able to send instructions if the user is not locked' do
|
||||
@@ -201,4 +195,31 @@ class LockableTest < ActiveSupport::TestCase
|
||||
assert_not user.access_locked?
|
||||
assert_equal 'was not locked', user.errors[:email].join
|
||||
end
|
||||
|
||||
test 'should unlock account if lock has expired and increase attempts on failure' do
|
||||
swap Devise, :unlock_in => 1.minute do
|
||||
user = create_user
|
||||
user.confirm!
|
||||
|
||||
user.failed_attempts = 2
|
||||
user.locked_at = 2.minutes.ago
|
||||
|
||||
user.valid_for_authentication? { false }
|
||||
assert_equal 1, user.failed_attempts
|
||||
end
|
||||
end
|
||||
|
||||
test 'should unlock account if lock has expired on success' do
|
||||
swap Devise, :unlock_in => 1.minute do
|
||||
user = create_user
|
||||
user.confirm!
|
||||
|
||||
user.failed_attempts = 2
|
||||
user.locked_at = 2.minutes.ago
|
||||
|
||||
user.valid_for_authentication? { true }
|
||||
assert_equal 0, user.failed_attempts
|
||||
assert_nil user.locked_at
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -85,7 +85,7 @@ class RecoverableTest < ActiveSupport::TestCase
|
||||
assert_not reset_password_user.persisted?
|
||||
assert_equal "not found", reset_password_user.errors[:email].join
|
||||
end
|
||||
|
||||
|
||||
test 'should find a user to send instructions by authentication_keys' do
|
||||
swap Devise, :authentication_keys => [:username, :email] do
|
||||
user = create_user
|
||||
@@ -93,14 +93,14 @@ class RecoverableTest < ActiveSupport::TestCase
|
||||
assert_equal reset_password_user, user
|
||||
end
|
||||
end
|
||||
|
||||
test 'should require all authentication_keys' do
|
||||
swap Devise, :authentication_keys => [:username, :email] do
|
||||
user = create_user
|
||||
reset_password_user = User.send_reset_password_instructions(:email => user.email)
|
||||
assert_not reset_password_user.persisted?
|
||||
assert_equal "can't be blank", reset_password_user.errors[:username].join
|
||||
end
|
||||
|
||||
test 'should require all reset_password_keys' do
|
||||
swap Devise, :reset_password_keys => [:username, :email] do
|
||||
user = create_user
|
||||
reset_password_user = User.send_reset_password_instructions(:email => user.email)
|
||||
assert_not reset_password_user.persisted?
|
||||
assert_equal "can't be blank", reset_password_user.errors[:username].join
|
||||
end
|
||||
end
|
||||
|
||||
test 'should reset reset_password_token before send the reset instructions email' do
|
||||
@@ -125,18 +125,27 @@ class RecoverableTest < ActiveSupport::TestCase
|
||||
assert_equal reset_password_user, user
|
||||
end
|
||||
|
||||
test 'should a new record with errors if no reset_password_token is found' do
|
||||
test 'should return a new record with errors if no reset_password_token is found' do
|
||||
reset_password_user = User.reset_password_by_token(:reset_password_token => 'invalid_token')
|
||||
assert_not reset_password_user.persisted?
|
||||
assert_equal "is invalid", reset_password_user.errors[:reset_password_token].join
|
||||
end
|
||||
|
||||
test 'should a new record with errors if reset_password_token is blank' do
|
||||
test 'should return a new record with errors if reset_password_token is blank' do
|
||||
reset_password_user = User.reset_password_by_token(:reset_password_token => '')
|
||||
assert_not reset_password_user.persisted?
|
||||
assert_match "can't be blank", reset_password_user.errors[:reset_password_token].join
|
||||
end
|
||||
|
||||
test 'should return a new record with errors if password is blank' do
|
||||
user = create_user
|
||||
user.send :generate_reset_password_token!
|
||||
|
||||
reset_password_user = User.reset_password_by_token(:reset_password_token => user.reset_password_token, :password => '')
|
||||
assert_not reset_password_user.errors.empty?
|
||||
assert_match "can't be blank", reset_password_user.errors[:password].join
|
||||
end
|
||||
|
||||
test 'should reset successfully user password given the new password and confirmation' do
|
||||
user = create_user
|
||||
old_password = user.password
|
||||
|
||||
@@ -27,6 +27,12 @@ class TokenAuthenticatableTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
test 'should return nil when authenticating an invalid user by authentication token' do
|
||||
if DEVISE_ORM == :mongoid
|
||||
raise 'There is an incompatibility between Devise and Mongoid' <<
|
||||
' that makes this test break. For more information, check' <<
|
||||
' this issue: https://github.com/mongoid/mongoid/issues/725'
|
||||
end
|
||||
|
||||
user = create_user
|
||||
user.ensure_authentication_token!
|
||||
user.confirm!
|
||||
@@ -34,4 +40,16 @@ class TokenAuthenticatableTest < ActiveSupport::TestCase
|
||||
assert_nil authenticated_user
|
||||
end
|
||||
|
||||
end
|
||||
test 'should not be subject to injection' do
|
||||
user1 = create_user
|
||||
user1.ensure_authentication_token!
|
||||
user1.confirm!
|
||||
|
||||
user2 = create_user
|
||||
user2.ensure_authentication_token!
|
||||
user2.confirm!
|
||||
|
||||
user = User.find_for_token_authentication(:auth_token => {'$ne' => user1.authentication_token})
|
||||
assert_nil user
|
||||
end
|
||||
end
|
||||
|
||||
@@ -47,6 +47,13 @@ class ActiveRecordTest < ActiveSupport::TestCase
|
||||
assert_equal module_constants, (Admin.included_modules & module_constants).reverse
|
||||
end
|
||||
|
||||
test 'raise error on invalid module' do
|
||||
assert_raise NameError do
|
||||
# Mix valid an invalid modules.
|
||||
Configurable.class_eval { devise :database_authenticatable, :doesnotexit }
|
||||
end
|
||||
end
|
||||
|
||||
test 'set a default value for stretches' do
|
||||
assert_equal 15, Configurable.stretches
|
||||
end
|
||||
|
||||
@@ -44,4 +44,11 @@ class OmniAuthRoutesTest < ActionController::TestCase
|
||||
assert_equal "/users/auth/open_id",
|
||||
@controller.omniauth_authorize_path(:user, :open_id)
|
||||
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
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
class ApplicationController < ActionController::Base
|
||||
protect_from_forgery
|
||||
|
||||
before_filter :current_user
|
||||
before_filter :authenticate_user!, :if => :devise_controller?
|
||||
end
|
||||
|
||||
@@ -4,4 +4,11 @@ class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
||||
session["devise.facebook_data"] = data["extra"]["user_hash"]
|
||||
render :json => data
|
||||
end
|
||||
|
||||
def sign_in_facebook
|
||||
user = User.find_by_email('user@test.com')
|
||||
user.remember_me = true
|
||||
sign_in user
|
||||
render :text => ""
|
||||
end
|
||||
end
|
||||
@@ -31,5 +31,10 @@ module RailsApp
|
||||
config.filter_parameters << :password
|
||||
|
||||
config.action_mailer.default_url_options = { :host => "localhost:3000" }
|
||||
|
||||
# This was used to break devise in some situations
|
||||
config.to_prepare do
|
||||
Devise::SessionsController.layout "application"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,9 +15,9 @@ Devise.setup do |config|
|
||||
require "devise/orm/#{DEVISE_ORM}"
|
||||
|
||||
# ==> Configuration for any authentication mechanism
|
||||
# Configure which keys are used when authenticating an user. By default is
|
||||
# Configure which keys are used when authenticating a user. By default is
|
||||
# just :email. You can configure it to use [:username, :subdomain], so for
|
||||
# authenticating an user, both parameters are required. Remember that those
|
||||
# authenticating a user, both parameters are required. Remember that those
|
||||
# parameters are used only when authenticating and not when retrieving from
|
||||
# session. If you need permissions, you should implement that in a before filter.
|
||||
# You can also supply hash where the value is a boolean expliciting if authentication
|
||||
@@ -31,6 +31,11 @@ Devise.setup do |config|
|
||||
# The same considerations mentioned for authentication_keys also apply to request_keys.
|
||||
# config.request_keys = []
|
||||
|
||||
# Configure which authentication keys should be case-insensitive.
|
||||
# These keys will be downcased upon creating or modifying a user and when used
|
||||
# to authenticate or find a user. Default is :email.
|
||||
config.case_insensitive_keys = [ :email ]
|
||||
|
||||
# Tell if authentication through request.params is enabled. True by default.
|
||||
# config.params_authenticatable = true
|
||||
|
||||
@@ -57,6 +62,9 @@ Devise.setup do |config|
|
||||
# (ie 2 days).
|
||||
# config.confirm_within = 2.days
|
||||
|
||||
# Defines which key will be used when confirming an account
|
||||
# config.confirmation_keys = [ :email ]
|
||||
|
||||
# ==> Configuration for :rememberable
|
||||
# The time the user will be remembered without asking for credentials again.
|
||||
# config.remember_for = 2.weeks
|
||||
@@ -89,6 +97,9 @@ Devise.setup do |config|
|
||||
# :none = No lock strategy. You should handle locking by yourself.
|
||||
# config.lock_strategy = :failed_attempts
|
||||
|
||||
# Defines which key will be used when locking and unlocking an account
|
||||
# config.unlock_keys = [ :email ]
|
||||
|
||||
# Defines which strategy will be used to unlock an account.
|
||||
# :email = Sends an unlock link to the user email
|
||||
# :time = Re-enables login after a certain amount of time (see :unlock_in below)
|
||||
@@ -103,6 +114,11 @@ Devise.setup do |config|
|
||||
# Time interval to unlock the account if :time is enabled as unlock_strategy.
|
||||
# config.unlock_in = 1.hour
|
||||
|
||||
# ==> Configuration for :recoverable
|
||||
#
|
||||
# Defines which key will be used when recovering the password for an account
|
||||
# config.reset_password_keys = [ :email ]
|
||||
|
||||
# ==> Configuration for :encryptable
|
||||
# Allow you to use another encryption algorithm besides bcrypt (default). You can use
|
||||
# :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1,
|
||||
|
||||
33
test/schema_test.rb
Normal file
33
test/schema_test.rb
Normal file
@@ -0,0 +1,33 @@
|
||||
if DEVISE_ORM == :mongoid
|
||||
|
||||
require 'test_helper'
|
||||
|
||||
class User2
|
||||
include Mongoid::Document
|
||||
devise :database_authenticatable
|
||||
end
|
||||
|
||||
class User3
|
||||
include Mongoid::Document
|
||||
devise :database_authenticatable, :authentication_keys => [:username, :email]
|
||||
end
|
||||
|
||||
class User4
|
||||
include Mongoid::Document
|
||||
devise :database_authenticatable, :authentication_keys => [:username]
|
||||
end
|
||||
|
||||
class SchemaTest < ActiveSupport::TestCase
|
||||
test 'should create an email field if there are no custom authentication keys' do
|
||||
assert_not_equal User2.fields['email'], nil
|
||||
end
|
||||
|
||||
test 'should create an email field if there are custom authentication keys and they include email' do
|
||||
assert_not_equal User3.fields['email'], nil
|
||||
end
|
||||
|
||||
test 'should not create an email field if there are custom authentication keys they don\'t include email' do
|
||||
assert_equal User4.fields['email'], nil
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -17,8 +17,11 @@ Webrat.configure do |config|
|
||||
config.open_error_files = false
|
||||
end
|
||||
|
||||
Devise::OmniAuth.test_mode!
|
||||
|
||||
# Add support to load paths so we can overwrite broken webrat setup
|
||||
$:.unshift File.expand_path('../support', __FILE__)
|
||||
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
||||
|
||||
# For generators
|
||||
require "rails/generators/test_case"
|
||||
require "generators/devise/install_generator"
|
||||
require "generators/devise/views_generator"
|
||||
|
||||
@@ -4,6 +4,12 @@ class TestHelpersTest < ActionController::TestCase
|
||||
tests UsersController
|
||||
include Devise::TestHelpers
|
||||
|
||||
class CustomFailureApp < Devise::FailureApp
|
||||
def redirect
|
||||
self.status = 306
|
||||
end
|
||||
end
|
||||
|
||||
test "redirects if attempting to access a page unauthenticated" do
|
||||
get :index
|
||||
assert_redirected_to new_user_session_path
|
||||
@@ -13,7 +19,7 @@ class TestHelpersTest < ActionController::TestCase
|
||||
test "redirects if attempting to access a page with an unconfirmed account" do
|
||||
swap Devise, :confirm_within => 0 do
|
||||
user = create_user
|
||||
assert !user.active?
|
||||
assert !user.active_for_authentication?
|
||||
|
||||
sign_in user
|
||||
get :index
|
||||
@@ -24,7 +30,7 @@ class TestHelpersTest < ActionController::TestCase
|
||||
test "returns nil if accessing current_user with an unconfirmed account" do
|
||||
swap Devise, :confirm_within => 0 do
|
||||
user = create_user
|
||||
assert !user.active?
|
||||
assert !user.active_for_authentication?
|
||||
|
||||
sign_in user
|
||||
get :accept, :id => user
|
||||
@@ -52,6 +58,16 @@ class TestHelpersTest < ActionController::TestCase
|
||||
get :index
|
||||
assert_redirected_to new_user_session_path
|
||||
end
|
||||
|
||||
test "respects custom failure app" do
|
||||
begin
|
||||
Devise.warden_config.failure_app = CustomFailureApp
|
||||
get :index
|
||||
assert_response 306
|
||||
ensure
|
||||
Devise.warden_config.failure_app = Devise::FailureApp
|
||||
end
|
||||
end
|
||||
|
||||
test "defined Warden after_authentication callback should not be called when sign_in is called" do
|
||||
begin
|
||||
@@ -82,6 +98,23 @@ class TestHelpersTest < ActionController::TestCase
|
||||
end
|
||||
end
|
||||
|
||||
test "before_failure call should work" do
|
||||
begin
|
||||
executed = false
|
||||
Warden::Manager.before_failure do |env,opts|
|
||||
executed = true
|
||||
end
|
||||
|
||||
user = create_user
|
||||
sign_in user
|
||||
|
||||
get :index
|
||||
assert executed
|
||||
ensure
|
||||
Warden::Manager._before_failure.pop
|
||||
end
|
||||
end
|
||||
|
||||
test "allows to sign in with different users" do
|
||||
first_user = create_user
|
||||
first_user.confirm!
|
||||
|
||||
Reference in New Issue
Block a user