Compare commits

...

134 Commits

Author SHA1 Message Date
José Valim
c698e44d10 Release v1.4.8. 2011-10-10 14:44:07 +02:00
José Valim
3e1b142392 Update docs and CHANGELOG. 2011-10-10 14:43:52 +02:00
José Valim
49807cf0b7 Try to fix the misterious case where some url helpers are not defined. 2011-10-09 17:14:37 +02:00
José Valim
e4902af15a Release 1.4.7 with a backward compatibility fix. 2011-09-22 11:51:58 +02:00
José Valim
ab9d856568 Add a deprecation warning for previous controller authorization style. 2011-09-22 11:51:09 +02:00
José Valim
dd1d128333 Edited lib/generators/templates/devise.rb via GitHub 2011-09-21 12:58:10 -07:00
José Valim
08a8d7bf51 Prepare for 1.4.6 2011-09-14 16:54:15 -07:00
José Valim
335d36088f Instead of depending on mapping.controller[:session], make it explicit when we allow auth from params. 2011-09-14 16:52:28 -07:00
José Valim
0b9a95e294 Allow --skip-routes to devise generator. 2011-09-14 16:52:28 -07:00
José Valim
98acc84111 Allow options to be passed to authenticate_user! 2011-09-14 16:52:28 -07:00
José Valim
261c01dfa3 Allow :skip => :all 2011-09-14 16:52:28 -07:00
José Valim
ea7f15917f Merge pull request #1322 from trollixx/patch-1
Typo
2011-09-09 03:01:54 -07:00
Oleg Shparber
df3e711ee0 Typo 2011-09-09 12:46:35 +03:00
José Valim
263e903046 Release v1.4.5 2011-09-08 23:55:27 +02:00
George Guimarães
f7bbac0ab9 sets travis to report to maintainers 2011-09-08 08:31:34 -03:00
José Valim
9ebcb691b0 Depend on jdbc master. 2011-09-08 09:05:06 +02:00
José Valim
601e1d3dc9 Update CHANGELOG. 2011-09-08 08:36:06 +02:00
José Valim
7b0a8f9bdc Also try the root route for convenience, closes #1312. 2011-09-08 08:32:05 +02:00
José Valim
dd36324756 No need to finalize Devise helpers all the time, closes #1317 2011-09-08 08:31:08 +02:00
José Valim
1b5d0af824 Merge pull request #1313 from jamescook/fix_bug_with_update_with_password
DatabaseAuthenticatable#clean_up_passwords should set accessors to nil
2011-09-02 10:48:47 -07:00
James Cook
edcca8cd3f DatabaseAuthenticatable#clean_up_passwords should set accessors to nil, not empty string. 2011-09-02 13:14:15 -04:00
José Valim
c95ca15b49 Edited lib/devise.rb via GitHub 2011-09-02 13:35:31 +03:00
José Valim
055117e07a Merge pull request #1308 from rymai/conditional_sign_in_after_password_reset
Implement #1306.
2011-09-01 00:19:56 -07:00
Rémy Coutable
ebbabaea5b After a password reset, don't show "You are now signed in." if the user can't be signed-in anyway. 2011-09-01 00:24:10 +02:00
José Valim
eba53f8f94 Test against 3.1.0. 2011-08-31 17:16:56 +02:00
José Valim
071f54ac59 Release v1.4.4 with a fix for those using :skip in routes. 2011-08-31 16:45:12 +02:00
José Valim
8796c1c601 Do not always skip helpers, instead provide :skip_helpers as option to trigger it manually 2011-08-31 12:02:57 +02:00
José Valim
ef4eb47d50 Release v1.4.3 with improve Rails 3.1 compatibility. 2011-08-30 14:35:19 +02:00
José Valim
295088f9e8 Depend on latest Rails. 2011-08-30 14:33:23 +02:00
José Valim
4222afe3c7 Tidy up latest commits, update CHANGELOG. 2011-08-30 10:50:40 +02:00
José Valim
79d89a3c20 Merge pull request #1297 from seanski/master
Patch for Issue 1259 -- New
2011-08-30 01:44:30 -07:00
Sean Hill
8ad414b217 Added a helper to look for an modifying migration. If one is found during :revoke, the modifying migration is deleted. If the modifying migration is not found, the creating migration is deleted. 2011-08-29 17:53:32 -05:00
José Valim
7b1418be3b Improve the regexp a bit more. 2011-08-29 14:55:56 +02:00
José Valim
7396c6911d Quack, quack, quack. Use duck typing instead of hardcoding everything, closes #1281. 2011-08-29 14:40:49 +02:00
José Valim
673c707085 Update CHANGELOG. 2011-08-29 14:31:09 +02:00
José Valim
f21d05a235 Only generate helpers for the used mappings, closes #1288 2011-08-29 14:29:38 +02:00
José Valim
1dd19c1a72 Wrap :actions constraints in the proper hash, closes #1280 2011-08-29 13:29:30 +02:00
José Valim
a8d9695324 Simplify regexp and ensure it runs against UTF8 chars, closes #1235 2011-08-29 13:15:40 +02:00
Sean Hill
99d539b9a7 Chagned the copy_devise_migration method to properly handle the :revoke behavior using @daf's commit: acf7e9e2ad as a guide. 2011-08-28 16:29:06 -05:00
Sean Hill
179cb2c88a Changed the order of the devise_generator methods to create the model after the migration to properly use model_exists?, and I added tests to prove the generator works. 2011-08-28 16:02:58 -05:00
Sean Hill
9629da863d Added a template to create a migration when the model already exists. Changed the generator code to check if model exists, and if it does, call the new template instead of the standard template. 2011-08-25 07:05:19 -05:00
José Valim
4f76e6f577 Depend on latest bcrypt. 2011-08-25 13:22:48 +02:00
José Valim
0f3cef4091 Merge pull request #1282 from apocalyptiq/master
Allow to set default 'from' header of Devise mails in custom mailer class
2011-08-20 13:48:45 -07:00
Szymon Przybył
7665cbf21d Allow to set default 'from' header of Devise mails in custom mailer class 2011-08-20 22:35:47 +02:00
José Valim
b9413ab316 Merge pull request #1275 from bquorning/it's_not_"it's",_it's_"its"
Fix usage of “its” / “it’s” in documentation
2011-08-16 15:20:01 -07:00
Benjamin Quorning
a3bff7d6a2 Fix usage of "its" / "it's" in documentation 2011-08-16 22:15:25 +02:00
José Valim
7e54dc7903 Edited lib/devise/models/lockable.rb via GitHub 2011-08-16 08:00:44 -07:00
José Valim
fb1220af97 Merge pull request #1264 from invisiblefunnel/master
Fixes small typo in routes documentation
2011-08-11 20:40:25 -07:00
Daniel Whalen
282c7e85ec Fix documentation typo 2011-08-11 20:16:20 -07:00
José Valim
bc15bb53dc Merge pull request #1261 from rumblestrut/patch-1
Changed "It's composed of 12 modules:" to "It's comprised of 12 modules .
2011-08-10 22:20:08 -07:00
Eric J. Gruber
a729e059de Changed "It's composed of 12 modules:" to "It's comprised of 12 modules ..." Comprised is the better word choice in this instance, meaning "Consist of; be made up of." 2011-08-10 21:46:52 -05:00
José Valim
7c628f7689 Merge pull request #1237 from novalis/master
friendly_token should be friendlier
2011-08-10 17:25:06 -07:00
David Turner
6d65c28f1f remove hard-to-distinguish characters from friendly_token 2011-08-10 12:44:30 -04:00
José Valim
31e4ef5e4b Merge pull request #1258 from wildchild/master
Don't require explicit scope in authenticate router extension
2011-08-10 05:23:29 -07:00
Alexander Uvarov
d38341b5e0 Don't require explicit scope in authenticate router extension 2011-08-10 15:41:06 +06:00
Rafael Mendonça França
ff90d9da9c Merge pull request #1251 from michaelklishin/patch-1
Re-add JRuby to the build matrix
2011-08-08 08:01:41 -07:00
Michael Klishin
84c62ed034 Re-add JRuby to the build matrix
We hopefully resolved our JRuby woes on travis-ci.org.
2011-08-07 20:55:59 +04:00
José Valim
e76ba05516 Merge pull request #1249 from ches/mongoid-fixes
Tests that should no longer exclude Mongoid
2011-08-06 08:21:48 -07:00
José Valim
90d99b16f1 Merge pull request #1250 from ches/unenforced-auth-keys
Fix optional enforcement of particular authentication keys
2011-08-06 08:20:30 -07:00
Ches Martin
3cedba1de8 Fix optional enforcement of particular authentication keys
Documentation states that authentication_keys should accept a hash with
values indicating whether or not each key is required. This was added in
b2066cc2 but tests only covered request_keys, and 29afe2d2 later broke
it with a << array operator.
2011-08-06 20:07:49 +07:00
Ches Martin
ccbf26be0a Tests that should no longer exclude Mongoid 2011-08-06 19:28:19 +07:00
José Valim
6448490de5 Edited lib/generators/templates/devise.rb via GitHub 2011-08-05 20:45:39 +03:00
José Valim
98651dae9d Merge pull request #1241 from dbloete/patch-1
Speed up tests by defaulting to 1 stretch in test env
2011-08-05 10:43:54 -07:00
José Valim
bf57ef400d Merge pull request #1247 from michaelklishin/patch-1
It is #rbxday, lets test against Rubinius 2.0 preview, too
2011-08-05 09:36:31 -07:00
Michael Klishin
27cae04446 It is #rbxday, lets test against Rubinius 2.0 preview, too 2011-08-05 20:34:33 +04:00
José Valim
430eadc1b2 Merge pull request #1245 from michaelklishin/patch-1
Disable testing against JRuby, it has known issues on travis-ci.org.
2011-08-05 09:31:36 -07:00
Michael Klishin
e954737a92 Disable testing against JRuby, it has known issues on travis-ci.org.
We will figure out JRuby issues with the JRuby core team and let you know
2011-08-05 16:26:11 +04:00
José Valim
191d5222e7 Merge pull request #1244 from ches/docs
Doc tweaks
2011-08-05 05:22:24 -07:00
Ches Martin
e77af4b40f Doc: DB authenticatable schema no longer includes salt 2011-08-05 20:13:01 +08:00
Ches Martin
da3c47259d Doc: DB authenticatable schema no longer includes salt 2011-08-05 17:33:50 +07:00
Ches Martin
c95575b284 Doc: DatabaseAuthenticatable still uses pepper option 2011-08-05 17:08:26 +07:00
José Valim
7a5086a2be Merge pull request #1242 from ches/mongoid-fixes
Fix failing Mongoid tests
2011-08-04 13:38:57 -07:00
Ches Martin
c3a665320e Merge branch 'master' into mongoid-fixes
* master:
  Untrack Gemfile.lock

Conflicts:
	Gemfile.lock
2011-08-05 03:19:05 +07:00
Dennis Reimann
372dfecf05 Added a comment about the stretch change 2011-08-04 23:00:12 +03:00
Dennis Reimann
68bd6809a7 Speed up tests by defaulting to 1 stretch in test env 2011-08-04 22:50:06 +03:00
Ches Martin
7bfdd07a71 Initializer caveats warning for Mongoid < 2.1 2011-08-05 02:41:31 +07:00
Ches Martin
6bc93173f1 Restore forlorn Mongoid generator tests 2011-08-05 02:40:42 +07:00
Ches Martin
55af9f8a40 Fix failing Mongoid tests
- attr_accessible not set for test user model, making Serializable tests
  inaccurate
- Mongoid does not `include_root_in_json` by default, so enable this for
  consistency with AR tests
- Mark tests pending for Mongoid < 2.1 that fail there due to known bugs
- Add `:mongoid` key for i18n model labels
- Remove outdated shim of `update_attribute` that caused mass assignment
  security to be applied (ugh, that took awhile to find)
2011-08-05 01:38:42 +07:00
José Valim
866b35d27c Merge pull request #1239 from ches/gemfile-lock
Untrack Gemfile.lock
2011-08-04 04:16:50 -07:00
Ches Martin
5374119f18 Untrack Gemfile.lock
Gemfile.lock is for app deployment, not public library development:

http://yehudakatz.com/2010/12/16/clarifying-the-roles-of-the-gemspec-and-gemfile/
2011-08-04 11:33:53 +07:00
José Valim
919404df53 Merge pull request #1228 from dasil003/master
Set up Recoverable to automatically confirm! if Comfirmable
2011-08-02 12:41:09 -07:00
Gabe da Silveira
fd07c74578 Refactor to use method and override 2011-08-02 12:08:38 -07:00
José Valim
560961e3fc Merge pull request #1233 from asanghi/master
sign_in should return true and assert that. fixes #1232
2011-08-02 03:04:51 -07:00
Aditya Sanghi
873e49ab66 sign_in should return true in case user is already signed in and assert that. 2011-08-02 14:35:46 +05:30
José Valim
0f8f786f9f Use a default key on inactive reason. 2011-08-02 11:18:23 +03:00
José Valim
7b3e267729 Merge pull request #1231 from hck/master
added I18n support to inactive_message in RegistrationsController
2011-08-02 01:14:16 -07:00
hck
7264bb55b2 added I18n support to inactive_message in RegistrationsController 2011-08-02 08:11:25 +03:00
Gabe da Silveira
ed6dfed67f Resetting password should confirm implicitly 2011-07-29 14:26:19 -07:00
Gabe da Silveira
3488066031 Spelling correction 2011-07-29 14:17:31 -07:00
José Valim
bc9ea93f50 Merge pull request #1224 from gtalton/patch-2
Edited lib/devise/rails/routes.rb via GitHub
2011-07-29 03:18:40 -07:00
Gerald Talton
1920b79a0d Edited lib/devise/rails/routes.rb via GitHub 2011-07-28 15:23:23 -05:00
José Valim
9131570703 Merge pull request #1221 from hazah/master
Change :except to :only for registration routes
2011-07-26 10:45:36 -07:00
=
770c1a973f Changed :except to :only for devise_registration method of the routing mapper. 2011-07-26 13:42:00 -04:00
José Valim
b7b21a0b72 Merge pull request #1211 from mathieuravaux/master
Issue #1206 fix ((TokenAuthenticatable#params_auth_hash behavior)
2011-07-25 05:11:26 -07:00
Mathieu Ravaux
4d91fb4910 Untangled the logic in Devise::Strategies::TokenAuthenticatable#params_auth_hash 2011-07-25 09:10:25 +02:00
Rafael Mendonça França
4ce9d6f29a Merge pull request #1212 from mattupstate/patch-1
Typo in doc comment
2011-07-23 15:06:02 -07:00
Matt Wright
d2a4c503f7 Typo in doc comment 2011-07-23 15:03:10 -07:00
Mathieu Ravaux
a2700bc17f Fixed issue #1206: TokenAuthenticatable#params_auth_hash behaving in an unexpected way for the authentication token lookup 2011-07-23 17:45:45 +02:00
José Valim
0a04d73883 Merge pull request #1198 from andriytyurnikov/issue_1197
div instead of p in forms
2011-07-14 05:47:46 -07:00
Andriy Tyurnikov
502dae3c1f div instead of p in forms 2011-07-14 15:43:10 +03:00
José Valim
e9c766277d Merge pull request #1194 from waynn/patch-1
quick typo fix
2011-07-11 11:37:18 -07:00
Waynn Lue
762f3907fa quick typo fix 2011-07-11 11:30:52 -07:00
José Valim
3698b64a10 Merge pull request #1190 from joliss/whitespace
Remove whitespace from generator template
2011-07-08 11:25:35 -07:00
Jo Liss
2a6c160d39 Remove whitespace from generator template 2011-07-08 18:41:16 +02:00
José Valim
795754cd60 Merge pull request #1189 from netmute/master
Add ability to override redirect_to path after account confirmation.
2011-07-08 03:27:21 -07:00
Simon Ernst
517343ddb5 Add ability to override redirect_to path after account confirmation. 2011-07-08 11:21:01 +02:00
Rodrigo Flores
90a5e2f9af Added rdoc on the Gemfile 2011-07-02 01:33:34 -03:00
Rodrigo Flores
93180fbb6d Removed a rdoc deprecation warning 2011-07-01 20:37:21 -03:00
José Valim
04cb78947a Edited CHANGELOG.rdoc via GitHub 2011-07-01 04:23:31 -07:00
José Valim
5423f2d5cb Properly deprecate setup_mail 2011-07-01 04:23:12 -07:00
José Valim
51d15b7293 Add more missing :require => true 2011-06-30 15:29:35 -03:00
José Valim
7a2e018df8 Release 1.4.2. 2011-06-30 15:20:13 -03:00
José Valim
1fd4beb18a Move simple_form_for directories to a new location. 2011-06-30 15:09:54 -03:00
José Valim
33d7644b4f Provide a more robust behavior to serializers and add :force_except option 2011-06-30 10:43:33 -03:00
José Valim
5a98e4f4e8 Temporary fix for 3-1-stable that does not implement key? on cookie jar, closes #1179 2011-06-30 08:04:32 -03:00
José Valim
82ae53dd75 Released v1.4.1. 2011-06-29 20:26:35 -03:00
José Valim
07db04e773 Work around AR that does not call serializable_hash on to_xml. 2011-06-29 20:18:10 -03:00
José Valim
6a8ee475fd This was fixed in mongoid, closes #770. 2011-06-29 20:18:10 -03:00
José Valim
767a7a7c21 Ensure handle_unverified_request clean up any cached signed-in user 2011-06-29 20:18:10 -03:00
José Valim
a3b56f7eb1 Merge pull request #1175 from jhllnd/patch-1
Added :registerable to the examples
2011-06-28 04:58:51 -07:00
jhllnd
5e1a998cde Added :registerable to the examples 2011-06-28 03:19:00 -07:00
José Valim
219fbc0056 Fix tests, remove whitespace and update CHANGELOG. 2011-06-28 07:05:35 -03:00
José Valim
dcee6413f4 Merge pull request #1173 from zedtux/master
Internationalization of resource_name in DeviseHelper#devise_error_messages!
2011-06-28 02:58:15 -07:00
Guillaume Hain
e2895239d8 Internationalization of resource_name in DeviseHelper#devise_error_messages! 2011-06-27 20:31:03 +02:00
José Valim
c8077c8d9f Add more docs to routes. 2011-06-27 13:04:40 -03:00
José Valim
46c2d5a8f2 Update CHANGELOG. 2011-06-27 12:16:06 -03:00
José Valim
adb127bb3e Default to delete on new templates. 2011-06-27 12:15:23 -03:00
José Valim
42f0285278 Extract mailer functionality, closes #1164 2011-06-27 12:13:00 -03:00
José Valim
13ef23f517 Add simple form generators. 2011-06-27 11:50:28 -03:00
José Valim
0bf28b19ab Simple use hook_for. 2011-06-27 11:31:29 -03:00
José Valim
29a0af78bc Refactor view generators. 2011-06-27 11:22:44 -03:00
José Valim
cf487c771e Merge pull request #1172 from bjnord/format-false
More transparent implementation of :format => false
2011-06-27 05:15:05 -07:00
Brent J. Nordquist
7e711089a8 More transparent implementat'n of :format => false
Per josevalim, by setting {:format => false} in @scope[:options],
Rails will pick it up, without the need to alter each devise_*()
method individually.
2011-06-27 06:51:04 -05:00
Brent J. Nordquist
1c81a40a76 Support options[:defaults] and @scope[:defaults]
similar to support for :constraints
2011-06-26 19:48:20 -05:00
99 changed files with 1153 additions and 523 deletions

4
.gitignore vendored
View File

@@ -7,4 +7,6 @@ coverage/*
rdoc/*
pkg
log
test/tmp/*
test/tmp/*
Gemfile.lock

View File

@@ -3,5 +3,10 @@ rvm:
- 1.8.7
- 1.9.2
- ree
- rbx
- rbx-2.0
- jruby
- rubinius
notifications:
recipients:
- jose.valim@plataformatec.com.br
- carlos@plataformatec.com.br

View File

@@ -1,3 +1,69 @@
== 1.4.8
* enhancements
* Add docs for assets pipeline and Heroku
* bug fix
* confirmation_url was not being set under some circumstances
== 1.4.7
* bug fix
* Fix backward incompatible change from 1.4.6 for those using custom controllers
== 1.4.6
* enhancements
* Allow devise_for :skip => :all
* Allow options to be passed to authenticate_user!
* Allow --skip-routes to devise generator
* Add allow_params_authentication! to make it explicit when params authentication is allowed in a controller
== 1.4.5
* bug fix
* Failure app tries the root path if a session one does not exist
* No need to finalize Devise helpers all the time (by github.com/bradleypriest)
* Reset password shows proper message if user is not active
* `clean_up_passwords` sets the accessors to nil to skip validations
== 1.4.4
* bug fix
* Do not always skip helpers, instead provide :skip_helpers as option to trigger it manually
== 1.4.3
* enhancements
* Improve Rails 3.1 compatibility
* Use serialize_into_session and serialize_from_session in Warden serialize to improve extensibility
* bug fix
* Generator properly generates a change_table migration if a model already exists
* Properly deprecate setup_mail
* Fix encoding issues with email regexp
* Only generate helpers for the used mappings
* Wrap :action constraints in the proper hash
* deprecations
* Loosened the used email regexp to simply assert the existent of "@". If someone relies on a more strict regexp, they may use https://github.com/SixArm/sixarm_ruby_email_address_validation
== 1.4.2
* bug fix
* Provide a more robust behavior to serializers and add :force_except option
== 1.4.1
* enhancements
* Add :defaults and :format support on router
* Add simple form generators
* Better localization for devise_error_messages! (by github.com/zedtux)
* bug fix
* Ensure to_xml is properly white listened
* Ensure handle_unverified_request clean up any cached signed-in user
== 1.4.0
* enhancements

View File

@@ -2,17 +2,21 @@ source "http://rubygems.org"
gemspec
gem "rails", "~> 3.0.7"
gem "rails", "~> 3.1.0"
gem "oa-oauth", '~> 0.2.0', :require => "omniauth/oauth"
gem "oa-openid", '~> 0.2.0', :require => "omniauth/openid"
gem "rdoc"
group :test do
gem "webrat", "0.7.2", :require => false
gem "mocha", :require => false
end
platforms :jruby do
gem 'activerecord-jdbc-adapter', :git => 'https://github.com/nicksieger/activerecord-jdbc-adapter.git'
gem 'activerecord-jdbcsqlite3-adapter'
gem 'jruby-openssl'
end
platforms :mri_18 do
@@ -26,7 +30,7 @@ platforms :ruby do
group :mongoid do
gem "mongo", "~> 1.3.0"
gem "mongoid", "2.0.1"
gem "mongoid", "~> 2.0"
gem "bson_ext", "~> 1.3.0"
end
end

View File

@@ -1,159 +0,0 @@
PATH
remote: .
specs:
devise (1.4.0.dev)
bcrypt-ruby (~> 2.1.2)
orm_adapter (~> 0.0.3)
warden (~> 1.0.3)
GEM
remote: http://rubygems.org/
specs:
abstract (1.0.0)
actionmailer (3.0.7)
actionpack (= 3.0.7)
mail (~> 2.2.15)
actionpack (3.0.7)
activemodel (= 3.0.7)
activesupport (= 3.0.7)
builder (~> 2.1.2)
erubis (~> 2.6.6)
i18n (~> 0.5.0)
rack (~> 1.2.1)
rack-mount (~> 0.6.14)
rack-test (~> 0.5.7)
tzinfo (~> 0.3.23)
activemodel (3.0.7)
activesupport (= 3.0.7)
builder (~> 2.1.2)
i18n (~> 0.5.0)
activerecord (3.0.7)
activemodel (= 3.0.7)
activesupport (= 3.0.7)
arel (~> 2.0.2)
tzinfo (~> 0.3.23)
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.7)
activemodel (= 3.0.7)
activesupport (= 3.0.7)
activesupport (3.0.7)
addressable (2.2.4)
arel (2.0.9)
bcrypt-ruby (2.1.4)
bcrypt-ruby (2.1.4-java)
bson (1.3.0)
bson_ext (1.3.0)
builder (2.1.2)
columnize (0.3.2)
erubis (2.6.6)
abstract (>= 1.0.0)
faraday (0.5.7)
addressable (~> 2.2.4)
multipart-post (~> 1.1.0)
rack (>= 1.1.0, < 2)
i18n (0.5.0)
jdbc-sqlite3 (3.6.14.2.056-java)
linecache (0.43)
mail (2.2.19)
activesupport (>= 2.3.6)
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
mime-types (1.16)
mocha (0.9.12)
mongo (1.3.0)
bson (>= 1.3.0)
mongoid (2.0.1)
activemodel (~> 3.0)
mongo (~> 1.3)
tzinfo (~> 0.3.22)
will_paginate (~> 3.0.pre)
multi_json (0.0.5)
multipart-post (1.1.0)
nokogiri (1.4.3.1)
nokogiri (1.4.3.1-java)
weakling (>= 0.0.3)
oa-core (0.2.0)
rack (~> 1.1)
oa-oauth (0.2.0)
multi_json (~> 0.0.2)
nokogiri (~> 1.4.2)
oa-core (= 0.2.0)
oauth (~> 0.4.0)
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.1)
faraday (~> 0.5.0)
multi_json (~> 0.0.4)
orm_adapter (0.0.4)
polyglot (0.3.1)
rack (1.2.2)
rack-mount (0.6.14)
rack (>= 1.0.0)
rack-openid (1.2.0)
rack (>= 1.1.0)
ruby-openid (>= 2.1.8)
rack-test (0.5.7)
rack (>= 1.0)
rails (3.0.7)
actionmailer (= 3.0.7)
actionpack (= 3.0.7)
activerecord (= 3.0.7)
activeresource (= 3.0.7)
activesupport (= 3.0.7)
bundler (~> 1.0)
railties (= 3.0.7)
railties (3.0.7)
actionpack (= 3.0.7)
activesupport (= 3.0.7)
rake (>= 0.8.7)
thor (~> 0.14.4)
rake (0.8.7)
ruby-debug (0.10.4)
columnize (>= 0.1)
ruby-debug-base (~> 0.10.4.0)
ruby-debug-base (0.10.4)
linecache (>= 0.3)
ruby-openid (2.1.8)
ruby-openid-apps-discovery (1.2.0)
ruby-openid (>= 2.1.7)
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.27)
warden (1.0.3)
rack (>= 1.0.0)
weakling (0.0.4-java)
webrat (0.7.2)
nokogiri (>= 1.2.0)
rack (>= 1.0)
rack-test (>= 0.5.3)
will_paginate (3.0.pre2)
PLATFORMS
java
ruby
DEPENDENCIES
activerecord-jdbcsqlite3-adapter
bson_ext (~> 1.3.0)
devise!
mocha
mongo (~> 1.3.0)
mongoid (= 2.0.1)
oa-oauth (~> 0.2.0)
oa-openid (~> 0.2.0)
rails (~> 3.0.7)
ruby-debug (>= 0.10.3)
sqlite3-ruby
webrat (= 0.7.2)

View File

@@ -7,7 +7,7 @@ Devise is a flexible authentication solution for Rails based on Warden. It:
* Allows you to have multiple roles (or models/scopes) signed in at the same time;
* Is based on a modularity concept: use just what you really need.
It's composed of 12 modules:
It's comprised of 12 modules:
* 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.
@@ -97,7 +97,7 @@ If you are building your first Rails application, we recommend you to *not* use
* 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. :)
Once you have solidified your understanding of Rails and authentication mechanisms, we assure you Devise will be very pleasant to work with. :)
== Getting started
@@ -108,7 +108,7 @@ Devise must be set up within the model (or models) you want to use. Devise route
We're assuming here you want a User model with some Devise modules, as outlined below:
class User < ActiveRecord::Base
devise :database_authenticatable, :confirmable, :recoverable, :rememberable, :trackable, :validatable
devise :database_authenticatable, :registerable, :confirmable, :recoverable, :rememberable, :trackable, :validatable
end
After you choose which modules to use, you need to set up your migrations. Luckily, Devise has some helpers to save you from this boring work:
@@ -174,7 +174,7 @@ Notice that if your devise model is not called "user" but "member", then the hel
The devise method in your models also accepts some options to configure its modules. For example, you can choose which encryptor to use in database_authenticatable:
devise :database_authenticatable, :confirmable, :recoverable, :stretches => 20
devise :database_authenticatable, :registerable, :confirmable, :recoverable, :stretches => 20
Besides :stretches, you can define :pepper, :encryptor, :confirm_within, :remember_for, :timeout_in, :unlock_in and other values. For details, see the initializer file that was created when you invoked the "devise:install" generator described above.

View File

@@ -1,7 +1,7 @@
# encoding: UTF-8
require 'rake/testtask'
require 'rake/rdoctask'
require 'rdoc/task'
desc 'Default: run tests for all ORMs.'
task :default => :test

View File

@@ -26,7 +26,7 @@ class Devise::ConfirmationsController < ApplicationController
if resource.errors.empty?
set_flash_message(:notice, :confirmed) if is_navigational_format?
sign_in(resource_name, resource)
respond_with_navigational(resource){ redirect_to redirect_location(resource_name, resource) }
respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource) }
else
respond_with_navigational(resource.errors, :status => :unprocessable_entity){ render_with_scope :new }
end
@@ -38,4 +38,10 @@ class Devise::ConfirmationsController < ApplicationController
def after_resending_confirmation_instructions_path_for(resource_name)
new_session_path(resource_name)
end
# The path used after confirmation.
def after_confirmation_path_for(resource_name, resource)
redirect_location(resource_name, resource)
end
end

View File

@@ -32,7 +32,8 @@ class Devise::PasswordsController < ApplicationController
self.resource = resource_class.reset_password_by_token(params[resource_name])
if resource.errors.empty?
set_flash_message(:notice, :updated) if is_navigational_format?
flash_message = resource.active_for_authentication? ? :updated : :updated_not_active
set_flash_message(:notice, flash_message) if is_navigational_format?
sign_in(resource_name, resource)
respond_with resource, :location => redirect_location(resource_name, resource)
else

View File

@@ -19,7 +19,7 @@ class Devise::RegistrationsController < ApplicationController
sign_in(resource_name, resource)
respond_with resource, :location => redirect_location(resource_name, resource)
else
set_flash_message :notice, :inactive_signed_up, :reason => resource.inactive_message.to_s if is_navigational_format?
set_flash_message :notice, :inactive_signed_up, :reason => inactive_reason(resource) if is_navigational_format?
expire_session_data_after_sign_in!
respond_with resource, :location => after_inactive_sign_up_path_for(resource)
end
@@ -84,10 +84,16 @@ class Devise::RegistrationsController < ApplicationController
end
# Overwrite redirect_for_sign_in so it takes uses after_sign_up_path_for.
def redirect_location(scope, resource) #:nodoc:
def redirect_location(scope, resource)
stored_location_for(scope) || after_sign_up_path_for(resource)
end
# Returns the inactive reason translated.
def inactive_reason(resource)
reason = resource.inactive_message.to_s
I18n.t("devise.registrations.reasons.#{reason}", :default => reason)
end
# The path used after sign up for inactive accounts. You need to overwrite
# this method in your own RegistrationsController.
def after_inactive_sign_up_path_for(resource)
@@ -108,7 +114,7 @@ class Devise::RegistrationsController < ApplicationController
# Authenticates the current scope and gets the current resource from the session.
def authenticate_scope!
send(:"authenticate_#{resource_name}!", true)
send(:"authenticate_#{resource_name}!", :force => true)
self.resource = send(:"current_#{resource_name}")
end
end

View File

@@ -1,5 +1,6 @@
class Devise::SessionsController < ApplicationController
prepend_before_filter :require_no_authentication, :only => [ :new, :create ]
prepend_before_filter :allow_params_authentication!, :only => :create
include Devise::Controllers::InternalHelpers
# GET /resource/sign_in
@@ -38,8 +39,10 @@ class Devise::SessionsController < ApplicationController
protected
def stub_options(resource)
array = resource_class.authentication_keys.dup
array << :password if resource.respond_to?(:password)
{ :methods => array, :only => [:password] }
methods = resource_class.authentication_keys.dup
methods = methods.keys if methods.is_a?(Hash)
methods << :password if resource.respond_to?(:password)
{ :methods => methods, :only => [:password] }
end
end
end

View File

@@ -11,7 +11,7 @@ module DeviseHelper
messages = resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join
sentence = I18n.t("errors.messages.not_saved",
:count => resource.errors.count,
:resource => resource_name)
:resource => resource.class.model_name.human.downcase)
html = <<-HTML
<div id="error_explanation">

View File

@@ -1,88 +1,15 @@
class Devise::Mailer < ::ActionMailer::Base
include Devise::Controllers::ScopedViews
attr_reader :scope_name, :resource
include Devise::Mailers::Helpers
def confirmation_instructions(record)
setup_mail(record, :confirmation_instructions)
devise_mail(record, :confirmation_instructions)
end
def reset_password_instructions(record)
setup_mail(record, :reset_password_instructions)
devise_mail(record, :reset_password_instructions)
end
def unlock_instructions(record)
setup_mail(record, :unlock_instructions)
end
private
# Configure default email options
def setup_mail(record, action)
initialize_from_record(record)
mail headers_for(action)
end
def initialize_from_record(record)
@scope_name = Devise::Mapping.find_scope!(record)
@resource = instance_variable_set("@#{devise_mapping.name}", record)
end
def devise_mapping
@devise_mapping ||= Devise.mappings[scope_name]
end
def headers_for(action)
headers = {
:subject => translate(devise_mapping, action),
:from => mailer_sender(devise_mapping),
:to => resource.email,
:template_path => template_paths
}
if resource.respond_to?(:headers_for)
headers.merge!(resource.headers_for(action))
end
unless headers.key?(:reply_to)
headers[:reply_to] = headers[:from]
end
headers
end
def mailer_sender(mapping)
if Devise.mailer_sender.is_a?(Proc)
Devise.mailer_sender.call(mapping.name)
else
Devise.mailer_sender
end
end
def template_paths
template_path = [self.class.mailer_name]
template_path.unshift "#{@devise_mapping.scoped_path}/mailer" if self.class.scoped_views?
template_path
end
# Setup a subject doing an I18n lookup. At first, it attemps to set a subject
# based on the current mapping:
#
# en:
# devise:
# mailer:
# confirmation_instructions:
# user_subject: '...'
#
# If one does not exist, it fallbacks to ActionMailer default:
#
# en:
# devise:
# mailer:
# confirmation_instructions:
# subject: '...'
#
def translate(mapping, key)
I18n.t(:"#{mapping.name}_subject", :scope => [:devise, :mailer, key],
:default => [:subject, key.to_s.humanize])
devise_mail(record, :unlock_instructions)
end
end

View File

@@ -3,10 +3,10 @@
<%= form_for(resource, :as => resource_name, :url => confirmation_path(resource_name), :html => { :method => :post }) do |f| %>
<%= devise_error_messages! %>
<p><%= f.label :email %><br />
<%= f.email_field :email %></p>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<p><%= f.submit "Resend confirmation instructions" %></p>
<div><%= f.submit "Resend confirmation instructions" %></div>
<% end %>
<%= render :partial => "devise/shared/links" %>

View File

@@ -4,13 +4,13 @@
<%= devise_error_messages! %>
<%= f.hidden_field :reset_password_token %>
<p><%= f.label :password, "New password" %><br />
<%= f.password_field :password %></p>
<div><%= f.label :password, "New password" %><br />
<%= f.password_field :password %></div>
<p><%= f.label :password_confirmation, "Confirm new password" %><br />
<%= f.password_field :password_confirmation %></p>
<div><%= f.label :password_confirmation, "Confirm new password" %><br />
<%= f.password_field :password_confirmation %></div>
<p><%= f.submit "Change my password" %></p>
<div><%= f.submit "Change my password" %></div>
<% end %>
<%= render :partial => "devise/shared/links" %>

View File

@@ -3,10 +3,10 @@
<%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :post }) do |f| %>
<%= devise_error_messages! %>
<p><%= f.label :email %><br />
<%= f.email_field :email %></p>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<p><%= f.submit "Send me reset password instructions" %></p>
<div><%= f.submit "Send me reset password instructions" %></div>
<% end %>
<%= render :partial => "devise/shared/links" %>

View File

@@ -3,19 +3,19 @@
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
<%= devise_error_messages! %>
<p><%= f.label :email %><br />
<%= f.email_field :email %></p>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<p><%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
<%= f.password_field :password %></p>
<div><%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
<%= f.password_field :password %></div>
<p><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></p>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
<p><%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password %></p>
<div><%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password %></div>
<p><%= f.submit "Update" %></p>
<div><%= f.submit "Update" %></div>
<% end %>
<h3>Cancel my account</h3>

View File

@@ -3,16 +3,16 @@
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<p><%= f.label :email %><br />
<%= f.email_field :email %></p>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<p><%= f.label :password %><br />
<%= f.password_field :password %></p>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<p><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></p>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
<p><%= f.submit "Sign up" %></p>
<div><%= f.submit "Sign up" %></div>
<% end %>
<%= render :partial => "devise/shared/links" %>

View File

@@ -1,17 +1,17 @@
<h2>Sign in</h2>
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
<p><%= f.label :email %><br />
<%= f.email_field :email %></p>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<p><%= f.label :password %><br />
<%= f.password_field :password %></p>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<% if devise_mapping.rememberable? -%>
<p><%= f.check_box :remember_me %> <%= f.label :remember_me %></p>
<div><%= f.check_box :remember_me %> <%= f.label :remember_me %></div>
<% end -%>
<p><%= f.submit "Sign in" %></p>
<div><%= f.submit "Sign in" %></div>
<% end %>
<%= render :partial => "devise/shared/links" %>

View File

@@ -3,10 +3,10 @@
<%= form_for(resource, :as => resource_name, :url => unlock_path(resource_name), :html => { :method => :post }) do |f| %>
<%= devise_error_messages! %>
<p><%= f.label :email %><br />
<%= f.email_field :email %></p>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<p><%= f.submit "Resend unlock instructions" %></p>
<div><%= f.submit "Resend unlock instructions" %></div>
<% end %>
<%= render :partial => "devise/shared/links" %>

View File

@@ -27,6 +27,7 @@ en:
passwords:
send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
updated: 'Your password was changed successfully. You are now signed in.'
updated_not_active: 'Your password was changed successfully.'
send_paranoid_instructions: "If your e-mail exists on our database, you will receive a password recovery link on your e-mail"
confirmations:
send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.'
@@ -37,6 +38,10 @@ en:
inactive_signed_up: 'You have signed up successfully. However, we could not sign you in because your account is %{reason}.'
updated: 'You updated your account successfully.'
destroyed: 'Bye! Your account was successfully cancelled. We hope to see you again soon.'
reasons:
inactive: 'inactive'
unconfirmed: 'unconfirmed'
locked: 'locked'
unlocks:
send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.'
unlocked: 'Your account was successfully unlocked. You are now signed in.'

View File

@@ -21,5 +21,5 @@ Gem::Specification.new do |s|
s.add_dependency("warden", "~> 1.0.3")
s.add_dependency("orm_adapter", "~> 0.0.3")
s.add_dependency("bcrypt-ruby", "~> 2.1.2")
s.add_dependency("bcrypt-ruby", "~> 3.0")
end

View File

@@ -11,7 +11,6 @@ module Devise
autoload :PathChecker, 'devise/path_checker'
autoload :Schema, 'devise/schema'
autoload :TestHelpers, 'devise/test_helpers'
autoload :Email, 'devise/email'
module Controllers
autoload :Helpers, 'devise/controllers/helpers'
@@ -31,6 +30,10 @@ module Devise
autoload :Sha1, 'devise/encryptors/sha1'
end
module Mailers
autoload :Helpers, 'devise/mailers/helpers'
end
module Strategies
autoload :Base, 'devise/strategies/base'
autoload :Authenticatable, 'devise/strategies/authenticatable'
@@ -101,11 +104,11 @@ module Devise
mattr_accessor :http_authentication_realm
@@http_authentication_realm = "Application"
# Email regex used to validate email formats. Based on RFC 822 and
# retrieved from Sixarm email validation gem
# (https://github.com/SixArm/sixarm_ruby_email_address_validation).
# Email regex used to validate email formats. It simply asserts that
# an one (and only one) @ exists in the given string. This is mainly
# to give user feedback and not to assert the e-mail validity.
mattr_accessor :email_regexp
@@email_regexp = Devise::Email::EXACT_PATTERN
@@email_regexp = /\A[^@]+@([^@\.]+\.)+[^@\.]+\z/
# Range validation for password length
mattr_accessor :password_length
@@ -379,13 +382,10 @@ module Devise
# Include helpers in the given scope to AC and AV.
def self.include_helpers(scope)
Rails.application.routes.url_helpers.send :include, scope::UrlHelpers
ActiveSupport.on_load(:action_controller) do
include scope::Helpers if defined?(scope::Helpers)
include scope::UrlHelpers
end
ActiveSupport.on_load(:action_view) do
include scope::UrlHelpers
end
end
@@ -394,6 +394,12 @@ module Devise
Rails::VERSION::STRING[0,3] != "3.0"
end
# Regenerates url helpers considering Devise.mapping
def self.regenerate_helpers!
Devise::Controllers::UrlHelpers.remove_helpers!
Devise::Controllers::UrlHelpers.generate_helpers!
end
# A method used internally to setup warden manager from the Rails initialize
# block.
def self.configure_warden! #:nodoc:
@@ -413,7 +419,7 @@ module Devise
# Generate a friendly string randomically to be used as token.
def self.friendly_token
SecureRandom.base64(15).tr('+/=', 'xyz')
SecureRandom.base64(15).tr('+/=lIO0', 'pqrsxyz')
end
# constant-time comparison algorithm to prevent timing attacks

View File

@@ -36,8 +36,14 @@ module Devise
mapping = mapping.name
class_eval <<-METHODS, __FILE__, __LINE__ + 1
def authenticate_#{mapping}!(force = false)
warden.authenticate!(:scope => :#{mapping}) if !devise_controller? || force
def authenticate_#{mapping}!(opts={})
if !opts.is_a?(Hash)
opts = { :force => opts }
ActiveSupport::Deprecation.warn "Passing a boolean to authenticate_#{mapping}! " \
"is deprecated, please use :force => \#{opts[:force]} instead", caller
end
opts[:scope] = :#{mapping}
warden.authenticate!(opts) if !devise_controller? || opts.delete(:force)
end
def #{mapping}_signed_in?
@@ -72,6 +78,11 @@ module Devise
false
end
# Tell warden that params authentication is allowed for that specific page.
def allow_params_authentication!
request.env["devise.allow_params_authentication"] = true
end
# 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)
@@ -106,6 +117,7 @@ module Devise
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.
true
else
warden.set_user(resource, options.merge!(:scope => scope))
end
@@ -218,9 +230,12 @@ module Devise
session.keys.grep(/^devise\./).each { |k| session.delete(k) }
end
# Overwrite Rails' handle unverified request to sign out all scopes.
# Overwrite Rails' handle unverified request to sign out all scopes,
# clear run strategies and remove cached variables.
def handle_unverified_request
sign_out_all_scopes
warden.clear_strategies_cache!
Devise.mappings.each { |_,m| instance_variable_set("@current_#{m.name}", nil) }
super # call the default behaviour which resets the session
end
end

View File

@@ -18,22 +18,37 @@ module Devise
#
# Those helpers are added to your ApplicationController.
module UrlHelpers
def self.remove_helpers!
self.instance_methods.map(&:to_s).grep(/_(url|path)$/).each do |method|
remove_method method
end
end
Devise::URL_HELPERS.each do |module_name, actions|
[:path, :url].each do |path_or_url|
actions.each do |action|
action = action ? "#{action}_" : ""
def self.generate_helpers!(routes=nil)
routes ||= begin
mappings = Devise.mappings.values.map(&:used_helpers).flatten.uniq
Devise::URL_HELPERS.slice(*mappings)
end
class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1
def #{action}#{module_name}_#{path_or_url}(resource_or_scope, *args)
scope = Devise::Mapping.find_scope!(resource_or_scope)
send("#{action}\#{scope}_#{module_name}_#{path_or_url}", *args)
end
URL_HELPERS
routes.each do |module_name, actions|
[:path, :url].each do |path_or_url|
actions.each do |action|
action = action ? "#{action}_" : ""
method = "#{action}#{module_name}_#{path_or_url}"
class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1
def #{method}(resource_or_scope, *args)
scope = Devise::Mapping.find_scope!(resource_or_scope)
send("#{action}\#{scope}_#{module_name}_#{path_or_url}", *args)
end
protected :#{method}
URL_HELPERS
end
end
end
end
generate_helpers!(Devise::URL_HELPERS)
end
end
end

View File

@@ -1,23 +0,0 @@
# This e-mail validation regexes were retrieved from SixArm Ruby
# e-mail validation gem (https://github.com/SixArm/sixarm_ruby_email_address_validation)
# As said on https://github.com/SixArm/sixarm_ruby_email_address_validation/blob/master/LICENSE.txt,
# we added it using Ruby license terms.
module Devise
module Email
QTEXT = Regexp.new '[^\\x0d\\x22\\x5c\\x80-\\xff]', nil, 'n'
DTEXT = Regexp.new '[^\\x0d\\x5b-\\x5d\\x80-\\xff]', nil, 'n'
ATOM = Regexp.new '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+', nil, 'n'
QUOTED_PAIR = Regexp.new '\\x5c[\\x00-\\x7f]', nil, 'n'
DOMAIN_LITERAL = Regexp.new "\\x5b(?:#{DTEXT}|#{QUOTED_PAIR})*\\x5d", nil, 'n'
QUOTED_STRING = Regexp.new "\\x22(?:#{QTEXT}|#{QUOTED_PAIR})*\\x22", nil, 'n'
DOMAIN_REF = ATOM
SUB_DOMAIN = "(?:#{DOMAIN_REF}|#{DOMAIN_LITERAL})"
WORD = "(?:#{ATOM}|#{QUOTED_STRING})"
DOMAIN = "#{SUB_DOMAIN}(?:\\x2e#{SUB_DOMAIN})*"
LOCAL_PART = "#{WORD}(?:\\x2e#{WORD})*"
SPEC = "#{LOCAL_PART}\\x40#{DOMAIN}"
PATTERN = Regexp.new "#{SPEC}", nil, 'n'
EXACT_PATTERN = Regexp.new "\\A#{SPEC}\\z", nil, 'n'
end
end

View File

@@ -65,10 +65,14 @@ module Devise
end
def redirect_url
if skip_format?
send(:"new_#{scope}_session_path")
opts = {}
route = :"new_#{scope}_session_path"
opts[:format] = request_format unless skip_format?
if respond_to?(route)
send(route, opts)
else
send(:"new_#{scope}_session_path", :format => request_format)
root_path(opts)
end
end

View File

@@ -1,7 +1,7 @@
# Each time a record is set we check whether its session has already timed out
# or not, based on last request time. If so, the record is logged out and
# redirected to the sign in page. Also, each time the request comes and the
# record is set, we set the last request time inside it's scoped session to
# record is set, we set the last request time inside its scoped session to
# verify timeout in the following request.
Warden::Manager.after_set_user do |record, warden, options|
scope = options[:scope]

View File

@@ -0,0 +1,91 @@
module Devise
module Mailers
module Helpers
extend ActiveSupport::Concern
included do
include Devise::Controllers::ScopedViews
attr_reader :scope_name, :resource
end
protected
def setup_mail(*args)
ActiveSupport::Deprecation.warn "setup_mail is deprecated, please use devise_mail instead", caller
devise_mail(*args)
end
# Configure default email options
def devise_mail(record, action)
initialize_from_record(record)
mail headers_for(action)
end
def initialize_from_record(record)
@scope_name = Devise::Mapping.find_scope!(record)
@resource = instance_variable_set("@#{devise_mapping.name}", record)
end
def devise_mapping
@devise_mapping ||= Devise.mappings[scope_name]
end
def headers_for(action)
headers = {
:subject => translate(devise_mapping, action),
:from => mailer_sender(devise_mapping),
:to => resource.email,
:template_path => template_paths
}
if resource.respond_to?(:headers_for)
headers.merge!(resource.headers_for(action))
end
unless headers.key?(:reply_to)
headers[:reply_to] = headers[:from]
end
headers
end
def mailer_sender(mapping)
if default_params[:from].present?
default_params[:from]
elsif Devise.mailer_sender.is_a?(Proc)
Devise.mailer_sender.call(mapping.name)
else
Devise.mailer_sender
end
end
def template_paths
template_path = [self.class.mailer_name]
template_path.unshift "#{@devise_mapping.scoped_path}/mailer" if self.class.scoped_views?
template_path
end
# Setup a subject doing an I18n lookup. At first, it attemps to set a subject
# based on the current mapping:
#
# en:
# devise:
# mailer:
# confirmation_instructions:
# user_subject: '...'
#
# If one does not exist, it fallbacks to ActionMailer default:
#
# en:
# devise:
# mailer:
# confirmation_instructions:
# subject: '...'
#
def translate(mapping, key)
I18n.t(:"#{mapping.name}_subject", :scope => [:devise, :mailer, key],
:default => [:subject, key.to_s.humanize])
end
end
end
end

View File

@@ -22,7 +22,8 @@ module Devise
# # is the modules included in the class
#
class Mapping #:nodoc:
attr_reader :singular, :scoped_path, :path, :controllers, :path_names, :class_name, :sign_out_via
attr_reader :singular, :scoped_path, :path, :controllers, :path_names,
:class_name, :sign_out_via, :format, :used_routes, :used_helpers
alias :name :singular
# Receives an object and find a scope for it. If a scope cannot be found,
@@ -67,7 +68,29 @@ module Devise
@constraints = Hash.new { |h,k| h[k] = k.to_s }
@constraints.merge!(options[:constraints] || {})
@defaults = Hash.new { |h,k| h[k] = k.to_s }
@defaults.merge!(options[:defaults] || {})
@sign_out_via = options[:sign_out_via] || Devise.sign_out_via
@format = options[:format]
singularizer = lambda { |s| s.to_s.singularize.to_sym }
if options.has_key?(:only)
@used_routes = self.routes & Array(options[:only]).map(&singularizer)
elsif options[:skip] == :all
@used_routes = []
else
@used_routes = self.routes - Array(options[:skip]).map(&singularizer)
end
if options[:skip_helpers] == true
@used_helpers = @used_routes
elsif skip = options[:skip_helpers]
@used_helpers = self.routes - Array(skip).map(&singularizer)
else
@used_helpers = self.routes
end
end
# Return modules for the mapping.
@@ -104,6 +127,10 @@ module Devise
@constraints
end
def defaults
@defaults
end
# Create magic predicates for verifying what module is activated by this map.
# Example:
#

View File

@@ -1,4 +1,5 @@
require 'devise/hooks/activatable'
require 'devise/models/serializable'
module Devise
module Models
@@ -46,6 +47,8 @@ module Devise
module Authenticatable
extend ActiveSupport::Concern
include Devise::Models::Serializable
included do
class_attribute :devise_modules, :instance_writer => false
self.devise_modules ||= []
@@ -76,18 +79,18 @@ module Devise
def authenticatable_salt
end
def serializable_hash(options={})
if self.class.respond_to?(:accessible_attributes)
options = { :only => self.class.accessible_attributes.to_a }.merge(options || {})
super(options)
else
super
end
end
module ClassMethods
Devise::Models.config(self, :authentication_keys, :request_keys, :strip_whitespace_keys, :case_insensitive_keys, :http_authenticatable, :params_authenticatable)
def serialize_into_session(record)
[record.to_key, record.authenticatable_salt]
end
def serialize_from_session(key, salt)
record = to_adapter.get(key)
record if record && record.authenticatable_salt == salt
end
def params_authenticatable?(strategy)
params_authenticatable.is_a?(Array) ?
params_authenticatable.include?(strategy) : params_authenticatable

View File

@@ -29,7 +29,7 @@ module Devise
after_create :send_confirmation_instructions, :if => :confirmation_required?
end
# Confirm a user by setting it's confirmed_at to actual time. If the user
# Confirm a user by setting its confirmed_at to actual time. If the user
# is already confirmed, add en error to email field
def confirm!
unless_confirmed do
@@ -127,8 +127,13 @@ module Devise
generate_confirmation_token && save(:validate => false)
end
def after_password_reset
super
confirm! unless confirmed?
end
module ClassMethods
# Attempt to find a user by it's email. If a record is found, send new
# Attempt to find a user by its email. If a record is found, send new
# confirmation instructions to it. If not user is found, returns a new user
# with an email not found error.
# Options must contain the user email
@@ -138,7 +143,7 @@ module Devise
confirmable
end
# Find a user by it's confirmation token and try to confirm it.
# Find a user by its confirmation token and try to confirm it.
# If no user is found, returns a new user with an error.
# If the user is already confirmed, create an error for the user
# Options must have the confirmation_token

View File

@@ -10,6 +10,9 @@ module Devise
#
# DatabaseAuthenticable adds the following options to devise_for:
#
# * +pepper+: a random string used to provide a more secure hash. Use
# `rake secret` to generate new keys.
#
# * +stretches+: the cost given to bcrypt.
#
# == Examples
@@ -42,7 +45,7 @@ module Devise
# Set password and password confirmation to nil
def clean_up_passwords
self.password = self.password_confirmation = ""
self.password = self.password_confirmation = nil
end
# Update record attributes when :current_password matches, otherwise returns

View File

@@ -3,13 +3,13 @@ module Devise
# Handles blocking a user access after a certain number of attempts.
# Lockable accepts two different strategies to unlock a user after it's
# blocked: email and time. The former will send an email to the user when
# the lock happens, containing a link to unlock it's account. The second
# the lock happens, containing a link to unlock its account. The second
# will unlock the user automatically after some configured time (ie 2.hours).
# It's also possible to setup lockable to use both email and time strategies.
#
# == Options
#
# Lockable adds the following options to devise_for:
# Lockable adds the following options to +devise+:
#
# * +maximum_attempts+: how many attempts should be accepted before blocking the user.
# * +lock_strategy+: lock the user account by :failed_attempts or :none.
@@ -22,7 +22,7 @@ module Devise
delegate :lock_strategy_enabled?, :unlock_strategy_enabled?, :to => "self.class"
# Lock a user setting it's locked_at to actual time.
# Lock a user setting its locked_at to actual time.
def lock_access!
self.locked_at = Time.now
@@ -132,7 +132,7 @@ module Devise
end
module ClassMethods
# Attempt to find a user by it's email. If a record is found, send new
# Attempt to find a user by its email. If a record is found, send new
# unlock instructions to it. If not user is found, returns a new user
# with an email not found error.
# Options must contain the user email
@@ -142,7 +142,7 @@ module Devise
lockable
end
# Find a user by it's unlock token and try to unlock it.
# Find a user by its unlock token and try to unlock it.
# If no user is found, returns a new user with an error.
# If the user is not locked, creates an error for the user
# Options must have the unlock_token

View File

@@ -29,7 +29,11 @@ module Devise
def reset_password!(new_password, new_password_confirmation)
self.password = new_password
self.password_confirmation = new_password_confirmation
clear_reset_password_token if valid?
if valid?
clear_reset_password_token
after_password_reset
end
save
end
@@ -89,8 +93,11 @@ module Devise
self.reset_password_sent_at = nil if respond_to?(:reset_password_sent_at=)
end
def after_password_reset
end
module ClassMethods
# Attempt to find a user by it's email. If a record is found, send new
# Attempt to find a user by its email. If a record is found, send new
# password instructions to it. If not user is found, returns a new user
# with an email not found error.
# Attributes must contain the user email
@@ -105,7 +112,7 @@ module Devise
generate_token(:reset_password_token)
end
# Attempt to find a user by it's reset_password_token to reset its
# Attempt to find a user by its reset_password_token to reset its
# password. If a user is found and token is still valid, reset its password and automatically
# try saving the record. If not user is found, returns a new user
# containing an error in reset_password_token attribute.

View File

@@ -0,0 +1,43 @@
module Devise
module Models
# This module redefine to_xml and serializable_hash in models for more
# secure defaults. By default, it removes from the serializable model
# all attributes that are *not* accessible. You can remove this default
# by using :force_except and passing a new list of attributes you want
# to exempt. All attributes given to :except will simply add names to
# exempt to Devise internal list.
module Serializable
extend ActiveSupport::Concern
# TODO: to_xml does not call serializable_hash. Hopefully someone will fix this in AR.
%w(to_xml serializable_hash).each do |method|
class_eval <<-RUBY, __FILE__, __LINE__
def #{method}(options=nil)
options ||= {}
if options.key?(:force_except)
options[:except] = options.delete(:force_except)
super(options)
elsif self.class.blacklist_keys?
except = Array(options[:except])
super(options.merge(:except => except + self.class.blacklist_keys))
else
super
end
end
RUBY
end
module ClassMethods
# Return true if we can retrieve blacklist keys from the record.
def blacklist_keys?
@has_except_keys ||= respond_to?(:accessible_attributes) && !accessible_attributes.to_a.empty?
end
# Returns keys that should be removed when serializing the record.
def blacklist_keys
@blacklist_keys ||= to_adapter.column_names.map(&:to_s) - accessible_attributes.to_a.map(&:to_s)
end
end
end
end
end

View File

@@ -5,10 +5,10 @@ module Devise
# Track information about your user sign in. It tracks the following columns:
#
# * sign_in_count - Increased every time a sign in is made (by form, openid, oauth)
# * current_sign_in_at - A tiemstamp updated when the user signs in
# * current_sign_in_at - A timestamp updated when the user signs in
# * last_sign_in_at - Holds the timestamp of the previous sign in
# * current_sign_in_ip - The remote ip updated when the user sign in
# * last_sign_in_at - Holds the remote ip of the previous sign in
# * last_sign_in_ip - Holds the remote ip of the previous sign in
#
module Trackable
def update_tracked_fields!(request)

View File

@@ -2,7 +2,7 @@ module Devise
module Models
# Validatable creates all needed validations for a user email and password.
# It's optional, given you may want to create the validations by yourself.
# Automatically validate if the email is present, unique and it's format is
# Automatically validate if the email is present, unique and its format is
# valid. Also tests presence of password, confirmation and length.
#
# == Options

View File

@@ -3,9 +3,10 @@ module Devise
module UrlHelpers
def self.define_helpers(mapping)
return unless mapping.omniauthable?
method = "#{mapping.name}_omniauth_authorize_path"
class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1
def #{mapping.name}_omniauth_authorize_path(provider, params = {})
def #{method}(provider, params = {})
if Devise.omniauth_configs[provider.to_sym]
script_name = request.env["SCRIPT_NAME"]
@@ -16,9 +17,12 @@ module Devise
raise ArgumentError, "Could not find omniauth provider \#{provider.inspect}"
end
end
protected :#{method}
URL_HELPERS
end
protected
def omniauth_authorize_path(resource_or_scope, *args)
scope = Devise::Mapping.find_scope!(resource_or_scope)
send("#{scope}_omniauth_authorize_path", *args)

View File

@@ -39,5 +39,18 @@ module Devise
Devise.include_helpers(Devise::OmniAuth)
end
end
initializer "devise.mongoid_version_warning" do
if defined?(Mongoid)
require 'mongoid/version'
if Mongoid::VERSION.to_f < 2.1
puts "\n[DEVISE] Please note that Mongoid versions prior to 2.1 handle dirty model " \
"object attributes in such a way that the Devise `validatable` module will not apply " \
"its usual uniqueness and format validations for the email field. It is recommended " \
"that you upgrade to Mongoid 2.1+ for this and other fixes, but if for some reason you " \
"are unable to do so, you should add these validations manually.\n"
end
end
end
end
end

View File

@@ -4,7 +4,12 @@ module ActionDispatch::Routing
# need devise_for mappings already declared to create filters and helpers.
def finalize_with_devise!
finalize_without_devise!
Devise.configure_warden!
@devise_finalized ||= begin
Devise.configure_warden!
Devise.regenerate_helpers!
true
end
end
alias_method_chain :finalize!, :devise
end
@@ -93,7 +98,7 @@ module ActionDispatch::Routing
#
# Also pay attention that when you use a namespace it will affect all the helpers and methods for controllers
# and views. For example, using the above setup you'll end with following methods:
# current_publisher_account, authenticate_publisher_account!, pusblisher_account_signed_in, etc.
# current_publisher_account, authenticate_publisher_account!, publisher_account_signed_in, etc.
#
# * :skip => tell which controller you want to skip routes from being created:
#
@@ -103,6 +108,21 @@ module ActionDispatch::Routing
#
# devise_for :users, :only => :sessions
#
# * :skip_helpers => skip generating Devise url helpers like new_session_path(@user).
# This is useful to avoid conflicts with previous routes and is false by default.
# It accepts true as option, meaning it will skip all the helpers for the controllers
# given in :skip but it also accepts specific helpers to be skipped:
#
# devise_for :users, :skip => [:registrations, :confirmations], :skip_helpers => true
# devise_for :users, :skip_helpers => [:registrations, :confirmations]
#
# * :format => include "(.:format)" in the generated routes? true by default, set to false to disable:
#
# devise_for :users, :format => false
#
# * :constraints => works the same as Rails' contraints
#
# * :defaults => works the same as Rails' defaults
#
# ==== Scoping
#
@@ -153,6 +173,7 @@ module ActionDispatch::Routing
# end
#
def devise_for(*resources)
@devise_finalized = false
options = resources.extract_options!
options[:as] ||= @scope[:as] if @scope[:as].present?
@@ -160,6 +181,8 @@ module ActionDispatch::Routing
options[:path_prefix] ||= @scope[:path] if @scope[:path].present?
options[:path_names] = (@scope[:path_names] || {}).merge(options[:path_names] || {})
options[:constraints] = (@scope[:constraints] || {}).merge(options[:constraints] || {})
options[:defaults] = (@scope[:defaults] || {}).merge(options[:defaults] || {})
@scope[:options] = (@scope[:options] || {}).merge({:format => false}) if options[:format] == false
resources.map!(&:to_sym)
@@ -178,15 +201,11 @@ module ActionDispatch::Routing
raise_no_devise_method_error!(mapping.class_name)
end
routes = mapping.routes
if options.has_key?(:only)
routes = Array(options.delete(:only)).map { |s| s.to_s.singularize.to_sym } & mapping.routes
end
routes -= Array(options.delete(:skip)).map { |s| s.to_s.singularize.to_sym }
routes = mapping.used_routes
devise_scope mapping.name do
yield if block_given?
with_devise_exclusive_scope mapping.fullpath, mapping.name, mapping.constraints do
with_devise_exclusive_scope mapping.fullpath, mapping.name, mapping.constraints, mapping.defaults do
routes.each { |mod| send("devise_#{mod}", mapping, mapping.controllers) }
end
end
@@ -195,11 +214,15 @@ module ActionDispatch::Routing
# Allow you to add authentication request from the router:
#
# authenticate(:user) do
# authenticate do
# resources :post
# end
#
def authenticate(scope)
# authenticate(:admin) do
# resources :users
# end
#
def authenticate(scope=nil)
constraint = lambda do |request|
request.env["warden"].authenticate!(:scope => scope)
end
@@ -264,6 +287,17 @@ module ActionDispatch::Routing
# Notice you cannot have two scopes mapping to the same URL. And remember, if
# you try to access a devise controller without specifying a scope, it will
# raise ActionNotFound error.
#
# Also be aware of that 'devise_scope' and 'as' use the singular form of the
# noun where other devise route commands expect the plural form. This would be a
# good and working example.
#
# devise_scope :user do
# match "/some/route" => "some_devise_controller"
# end
# devise_for :users
#
# Notice and be aware of the differences above between :user and :users
def devise_scope(scope)
constraint = lambda do |request|
request.env["devise.mapping"] = Devise.mappings[scope]
@@ -309,7 +343,7 @@ module ActionDispatch::Routing
:cancel => mapping.path_names[:cancel]
}
resource :registration, :except => :show, :path => mapping.path_names[:registration],
resource :registration, :only => [:new, :create, :edit, :update, :destroy], :path => mapping.path_names[:registration],
:path_names => path_names, :controller => controllers[:registrations] do
get :cancel
end
@@ -325,23 +359,23 @@ module ActionDispatch::Routing
::OmniAuth.config.path_prefix = path_prefix
end
match "#{path_prefix}/:action/callback", :action => Regexp.union(mapping.to.omniauth_providers.map(&:to_s)),
match "#{path_prefix}/:action/callback", :constraints => { :action => Regexp.union(mapping.to.omniauth_providers.map(&:to_s)) },
:to => controllers[:omniauth_callbacks], :as => :omniauth_callback
ensure
@scope[:path] = path
end
def with_devise_exclusive_scope(new_path, new_as, new_constraints) #:nodoc:
old_as, old_path, old_module, old_constraints = @scope[:as], @scope[:path], @scope[:module], @scope[:constraints]
@scope[:as], @scope[:path], @scope[:module], @scope[:constraints] = new_as, new_path, nil, new_constraints
def with_devise_exclusive_scope(new_path, new_as, new_constraints, new_defaults) #:nodoc:
old_as, old_path, old_module, old_constraints, old_defaults = @scope[:as], @scope[:path], @scope[:module], @scope[:constraints], @scope[:defaults]
@scope[:as], @scope[:path], @scope[:module], @scope[:constraints], @scope[:defaults] = new_as, new_path, nil, new_constraints, new_defaults
yield
ensure
@scope[:as], @scope[:path], @scope[:module], @scope[:constraints] = old_as, old_path, old_module, old_constraints
@scope[:as], @scope[:path], @scope[:module], @scope[:constraints], @scope[:defaults] = old_as, old_path, old_module, old_constraints, old_defaults
end
def raise_no_devise_method_error!(klass) #:nodoc:
raise "#{klass} does not respond to 'devise' method. This usually means you haven't " <<
"loaded your ORM file or it's being loaded too late. To fix it, be sure to require 'devise/orm/YOUR_ORM' " <<
raise "#{klass} does not respond to 'devise' method. This usually means you haven't " \
"loaded your ORM file or it's being loaded too late. To fix it, be sure to require 'devise/orm/YOUR_ORM' " \
"inside 'config/initializers/devise.rb' or before your application definition in 'config/application.rb'"
end
end

View File

@@ -15,21 +15,16 @@ end
class Warden::SessionSerializer
def serialize(record)
[record.class.name, record.to_key, record.authenticatable_salt]
klass = record.class
array = klass.serialize_into_session(record)
array.unshift(klass.name)
end
def deserialize(keys)
if keys.size == 2
raise "Devise changed how it stores objects in session. If you are seeing this message, " <<
"you can fix it by changing one character in your secret_token or cleaning up your " <<
"database sessions if you are using a db store."
end
klass, id, salt = keys
klass, *args = keys
begin
record = ActiveSupport::Inflector.constantize(klass).to_adapter.get(id)
record if record && record.authenticatable_salt == salt
ActiveSupport::Inflector.constantize(klass).serialize_from_session(*args)
rescue NameError => e
if e.message =~ /uninitialized constant/
Rails.logger.debug "[Devise] Trying to deserialize invalid class #{klass}"

View File

@@ -3,11 +3,12 @@ module Devise
# and overwrite the apply_schema method.
module Schema
# Creates email when enabled (on by default), encrypted_password and password_salt.
# Creates encrypted_password, and email when it is used as an authentication
# key (default).
#
# == Options
# * :null - When true, allow columns to be null.
# * :default - Should be set to "" when :null is false.
# * :default - Set to "" when :null is false, unless overridden.
#
# == Notes
# For Datamapper compatibility, we explicitly hardcode the limit for the
@@ -21,7 +22,8 @@ module Devise
apply_devise_schema :encrypted_password, String, :null => null, :default => default, :limit => 128
end
# Creates password salt for encryption support.
# Creates password salt for encryption support when using encryptors other
# than the database_authenticable default of bcrypt.
def encryptable
apply_devise_schema :password_salt, String
end

View File

@@ -85,17 +85,17 @@ module Devise
# By default, a request is valid if the controller is allowed and the VERB is POST.
def valid_request?
valid_controller? && valid_verb?
end
# Check if the controller is the one registered for authentication.
def valid_controller?
mapping.controllers[:sessions] == params[:controller]
end
# Check if it was a POST request.
def valid_verb?
request.post?
if env["devise.allow_params_authentication"]
true
elsif request.post? && mapping.controllers[:sessions] == params[:controller]
ActiveSupport::Deprecation.warn "It seems that you are using a custom SessionsController. " \
"In order for it to work from Devise 1.4.6 forward, you need to add the following:" \
"\n\n prepend_before_filter :allow_params_authentication!, :only => :create\n\n" \
"This will ensure your controller can authenticate from params for the create action.", caller
true
else
false
end
end
# If the request is valid, finally check if params_auth_hash returns a hash.

View File

@@ -9,6 +9,7 @@ module Devise
class Rememberable < Authenticatable
# A valid strategy for rememberable needs a remember token in the cookies.
def valid?
@remember_cookie = nil
remember_cookie.present?
end
@@ -41,10 +42,10 @@ module Devise
"remember_#{scope}_token"
end
# Accessor for remember cookie
def remember_cookie
@remember_cookie ||= cookies.signed[remember_key]
end
end
end
end

View File

@@ -39,7 +39,11 @@ module Devise
# Try both scoped and non scoped keys.
def params_auth_hash
params[scope] || params
if params[scope].kind_of?(Hash) && params[scope].has_key?(authentication_keys.first)
params[scope]
else
params
end
end
# Overwrite authentication keys to use token_authentication_key.

View File

@@ -1,3 +1,3 @@
module Devise
VERSION = "1.4.0".freeze
VERSION = "1.4.8".freeze
end

View File

@@ -1,6 +1,7 @@
require 'rails/generators/active_record'
require 'generators/devise/orm_helpers'
module ActiveRecord
module Generators
class DeviseGenerator < ActiveRecord::Generators::Base
@@ -9,14 +10,18 @@ module ActiveRecord
include Devise::Generators::OrmHelpers
source_root File.expand_path("../templates", __FILE__)
def copy_devise_migration
if (behavior == :invoke && model_exists?) || (behavior == :revoke && migration_exists?(table_name))
migration_template "migration_existing.rb", "db/migrate/add_devise_to_#{table_name}"
else
migration_template "migration.rb", "db/migrate/devise_create_#{table_name}"
end
end
def generate_model
invoke "active_record:model", [name], :migration => false unless model_exists? && behavior == :invoke
end
def copy_devise_migration
migration_template "migration.rb", "db/migrate/devise_create_#{table_name}"
end
def inject_devise_content
inject_into_class(model_path, class_name, model_contents + <<CONTENT) if model_exists?
# Setup accessible (or protected) attributes for your model

View File

@@ -0,0 +1,34 @@
class AddDeviseTo<%= table_name.camelize %> < ActiveRecord::Migration
def self.up
change_table(:<%= table_name %>) do |t|
t.database_authenticatable :null => false
t.recoverable
t.rememberable
t.trackable
# t.encryptable
# t.confirmable
# t.lockable :lock_strategy => :<%= Devise.lock_strategy %>, :unlock_strategy => :<%= Devise.unlock_strategy %>
# t.token_authenticatable
<% for attribute in attributes -%>
t.<%= attribute.type %> :<%= attribute.name %>
<% end -%>
# Uncomment below if timestamps were not included in your original model.
# t.timestamps
end
add_index :<%= table_name %>, :email, :unique => true
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
# By default, we don't want to make any assumption about how to roll back a migration when your
# model already existed. Please edit below which fields you would like to remove in this migration.
raise ActiveRecord::IrreversibleMigration
end
end

View File

@@ -9,9 +9,12 @@ module Devise
hook_for :orm
class_option :routes, :desc => "Generate routes", :type => :boolean, :default => true
def add_devise_routes
devise_route = "devise_for :#{plural_name}"
devise_route += %Q(, :class_name => "#{class_name}") if class_name.include?("::")
devise_route << %Q(, :class_name => "#{class_name}") if class_name.include?("::")
devise_route << %Q(, :skip => :all) unless options.routes?
route devise_route
end
end

View File

@@ -14,6 +14,14 @@ CONTENT
def model_exists?
File.exists?(File.join(destination_root, model_path))
end
def migration_exists?(table_name)
Dir.glob("#{File.join(destination_root, migration_path)}/[0-9]*_*.rb").grep(/\d+_add_devise_to_#{table_name}.rb$/).first
end
def migration_path
@migration_path ||= File.join("db", "migrate")
end
def model_path
@model_path ||= File.join("app", "models", "#{file_path}.rb")

View File

@@ -1,20 +1,72 @@
require 'tmpdir'
module Devise
module Generators
# Include this module in your generator to generate Devise views.
# `copy_views` is the main method and by default copies all views
# with forms.
module ViewPathTemplates #:nodoc:
extend ActiveSupport::Concern
included do
argument :scope, :required => false, :default => nil,
:desc => "The scope to copy views to"
public_task :copy_views
end
def copy_views
view_directory :confirmations
view_directory :passwords
view_directory :registrations
view_directory :sessions
view_directory :unlocks
end
protected
def view_directory(name)
directory name.to_s, "#{target_path}/#{name}"
end
def target_path
@target_path ||= "app/views/#{scope || :devise}"
end
end
class SharedViewsGenerator < Rails::Generators::Base #:nodoc:
include ViewPathTemplates
source_root File.expand_path("../../../../app/views/devise", __FILE__)
desc "Copies shared Devise views to your application."
# Override copy_views to just copy mailer and shared.
def copy_views
view_directory :mailer
view_directory :shared
end
end
class FormForGenerator < Rails::Generators::Base #:nodoc:
include ViewPathTemplates
source_root File.expand_path("../../../../app/views/devise", __FILE__)
desc "Copies default Devise views to your application."
end
class SimpleFormForGenerator < Rails::Generators::Base #:nodoc:
include ViewPathTemplates
source_root File.expand_path("../../templates/simple_form_for", __FILE__)
desc "Copies simple form enabled views to your application."
end
class ViewsGenerator < Rails::Generators::Base
source_root File.expand_path("../../../../app/views", __FILE__)
desc "Copies all Devise views to your application."
desc "Copies Devise views to your application."
argument :scope, :required => false, :default => nil,
: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', 'haml' and 'slim'."
invoke SharedViewsGenerator
def copy_views
directory "devise", "app/views/#{scope || :devise}"
end
hook_for :form_builder, :aliases => "-b",
:desc => "Form builder to be used",
:default => defined?(SimpleForm) ? "simple_form_for" : "form_for"
end
end
end

View File

@@ -22,4 +22,11 @@ Some setup you must do manually if you haven't yet:
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
4. If you are deploying Rails 3.1 on Heroku, you may want to set:
config.assets.initialize_on_precompile = false
On config/application.rb forcing your application to not access the DB
or load models when precompiling your assets.
===============================================================================

View File

@@ -2,7 +2,8 @@
# four configuration values can also be set straight in your models.
Devise.setup do |config|
# ==> Mailer Configuration
# Configure the e-mail address which will be shown in DeviseMailer.
# Configure the e-mail address which will be shown in Devise::Mailer,
# note that it will be overwritten if you use your own mailer class with default "from" parameter.
config.mailer_sender = "please-change-me-at-config-initializers-devise@example.com"
# Configure the class responsible to send e-mails.
@@ -35,7 +36,7 @@ Devise.setup do |config|
# 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 ]
# Configure which authentication keys should have whitespace stripped.
# These keys will have whitespace before and after removed upon creating or
# modifying a user and when used to authenticate or find a user. Default is :email.
@@ -61,18 +62,21 @@ Devise.setup do |config|
# ==> Configuration for :database_authenticatable
# For bcrypt, this is the cost for hashing the password and defaults to 10. If
# using other encryptors, it sets how many times you want the password re-encrypted.
config.stretches = 10
#
# Limiting the stretches to just one in testing will increase the performance of
# your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use
# a value less than 10 in other environments.
config.stretches = Rails.env.test? ? 1 : 10
# Setup a pepper to generate the encrypted password.
# config.pepper = <%= 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
# When confirm_within is zero, the user won't be able to sign in without confirming.
# You can use this to let your user access some features of your application
# without confirming the account, but blocking it after a certain period
# (ie 2 days).
# A period that the user is allowed to access the website even without
# confirming his account. For instance, if set to 2.days, the user will be
# able to access the website for two days without confirming his account,
# access will be blocked just in the third day. Default is 0.days, meaning
# the user cannot access the website without confirming his account.
# config.confirm_within = 2.days
# Defines which key will be used when confirming an account
@@ -100,8 +104,10 @@ Devise.setup do |config|
# Range for password length. Default is 6..128.
# config.password_length = 6..128
# Regex to use to validate the email address
# config.email_regexp = /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\z/i
# Email regex used to validate email formats. It simply asserts that
# an one (and only one) @ exists in the given string. This is mainly
# to give user feedback and not to assert the e-mail validity.
# config.email_regexp = /\A[^@]+@[^@]+\z/
# ==> Configuration for :timeoutable
# The time you want to timeout the user session without activity. After this
@@ -184,8 +190,8 @@ Devise.setup do |config|
# Explorer requests.
# config.navigational_formats = [:"*/*", "*/*", :html]
# The default HTTP method used to sign out a resource. Default is :get.
# config.sign_out_via = :get
# The default HTTP method used to sign out a resource. Default is :delete.
config.sign_out_via = :delete
# ==> OmniAuth
# Add a new OmniAuth provider. Check the wiki for more information on setting

View File

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

View File

@@ -0,0 +1,19 @@
<h2>Change your password</h2>
<%= simple_form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :put }) do |f| %>
<%= f.error_notification %>
<%= f.input :reset_password_token, :as => :hidden %>
<%= f.full_error :reset_password_token %>
<div class="inputs">
<%= f.input :password, :label => "New password", :required => true %>
<%= f.input :password_confirmation, :label => "Confirm your new password", :required => true %>
</div>
<div class="actions">
<%= f.button :submit, "Change my password" %>
</div>
<% end %>
<%= render :partial => "devise/shared/links" %>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -45,6 +45,11 @@ class ControllerAuthenticatableTest < ActionController::TestCase
@controller.authenticate_user!
end
test 'proxy authenticate_user! options to authenticate with user scope' do
@mock_warden.expects(:authenticate!).with(:scope => :user, :recall => "foo")
@controller.authenticate_user!(:recall => "foo")
end
test 'proxy authenticate_admin! to authenticate with admin scope' do
@mock_warden.expects(:authenticate!).with(:scope => :admin)
@controller.authenticate_admin!
@@ -106,7 +111,7 @@ class ControllerAuthenticatableTest < ActionController::TestCase
user = User.new
@mock_warden.expects(:user).returns(user)
@mock_warden.expects(:set_user).never
@controller.sign_in(user)
assert @controller.sign_in(user)
end
test 'sign in again when the user is already in only if force is given' do

View File

@@ -35,7 +35,7 @@ class HelpersTest < ActionController::TestCase
end
test 'resources methods are not controller actions' do
assert @controller.class.action_methods.empty?
assert @controller.class.action_methods.empty?, "Expected empty, got #{@controller.class.action_methods.inspect}"
end
test 'require no authentication tests current mapping' do

View File

@@ -2,6 +2,10 @@ require 'test_helper'
require 'ostruct'
class FailureTest < ActiveSupport::TestCase
class RootFailureApp < Devise::FailureApp
undef_method :new_user_session_path
end
def self.context(name, &block)
instance_eval(&block)
end
@@ -18,32 +22,31 @@ class FailureTest < ActiveSupport::TestCase
'warden' => OpenStruct.new(:message => nil)
}.merge!(env_params)
@response = Devise::FailureApp.call(env).to_a
@response = (env.delete(:app) || Devise::FailureApp).call(env).to_a
@request = ActionDispatch::Request.new(env)
end
context 'When redirecting' do
test 'return 302 status' do
call_failure
assert_equal 302, @response.first
end
test 'return 302 status for wildcard requests' do
call_failure 'action_dispatch.request.formats' => nil, 'HTTP_ACCEPT' => '*/*'
assert_equal 302, @response.first
end
test 'return to the default redirect location' do
call_failure
assert_equal 302, @response.first
assert_equal 'You need to sign in or sign up before continuing.', @request.flash[:alert]
assert_equal 'http://test.host/users/sign_in', @response.second['Location']
end
test 'return to the default redirect location for wildcard requests' do
call_failure 'action_dispatch.request.formats' => nil, 'HTTP_ACCEPT' => '*/*'
assert_equal 302, @response.first
assert_equal 'http://test.host/users/sign_in', @response.second['Location']
end
test 'return to the root path if no session path is available' do
call_failure :app => RootFailureApp
assert_equal 302, @response.first
assert_equal 'You need to sign in or sign up before continuing.', @request.flash[:alert]
assert_equal 'http://test.host/', @response.second['Location']
end
test 'uses the proxy failure message as symbol' do
call_failure('warden' => OpenStruct.new(:message => :test))
assert_equal 'test', @request.flash[:alert]
@@ -74,7 +77,7 @@ 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)
@@ -178,7 +181,7 @@ 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 },
@@ -187,9 +190,9 @@ class FailureTest < ActiveSupport::TestCase
}
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.')
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 },
@@ -198,7 +201,7 @@ class FailureTest < ActiveSupport::TestCase
}
call_failure(env)
assert @response.third.body.include?('<h2>Sign in</h2>')
assert @response.third.body.include?('Your account was not activated yet.')
assert @response.third.body.include?('Your account was not activated yet.')
end
end
end

View File

@@ -13,9 +13,22 @@ if DEVISE_ORM == :active_record
assert_file "app/models/monster.rb", /devise/, /attr_accessible (:[a-z_]+(, )?)+/
assert_migration "db/migrate/devise_create_monsters.rb"
end
test "update model migration when model exists" do
run_generator %w(monster)
assert_file "app/models/monster.rb"
run_generator %w(monster)
assert_migration "db/migrate/add_devise_to_monsters.rb"
end
test "all files are properly deleted" do
run_generator %w(monster)
run_generator %w(monster)
assert_migration "db/migrate/devise_create_monsters.rb"
assert_migration "db/migrate/add_devise_to_monsters.rb"
run_generator %w(monster), :behavior => :revoke
assert_no_migration "db/migrate/add_devise_to_monsters.rb"
assert_migration "db/migrate/devise_create_monsters.rb"
run_generator %w(monster), :behavior => :revoke
assert_no_file "app/models/monster.rb"
assert_no_migration "db/migrate/devise_create_monsters.rb"

View File

@@ -22,6 +22,12 @@ class DeviseGeneratorTest < Rails::Generators::TestCase
assert_file "config/routes.rb", match
end
test "route generation with skip routes" do
run_generator %w(monster name:string --skip-routes)
match = /devise_for :monsters, :skip => :all/
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")

View File

@@ -1,7 +1,7 @@
require "test_helper"
if DEVISE_ORM == :mongo_id
require "generators/mongo_id/devise_generator"
if DEVISE_ORM == :mongoid
require "generators/mongoid/devise_generator"
class MongoidGeneratorTest < Rails::Generators::TestCase
tests Mongoid::Generators::DeviseGenerator
@@ -19,4 +19,5 @@ if DEVISE_ORM == :mongo_id
assert_no_file "app/models/monster.rb"
end
end
end
end

View File

@@ -18,6 +18,16 @@ class ViewsGeneratorTest < Rails::Generators::TestCase
assert_files "admins"
end
test "Assert views with simple form" do
run_generator %w(-b simple_form_for)
assert_files
assert_file "app/views/devise/confirmations/new.html.erb", /simple_form_for/
run_generator %w(users -b simple_form_for)
assert_files "users"
assert_file "app/views/users/confirmations/new.html.erb", /simple_form_for/
end
def assert_files(scope = nil, template_engine = nil)
scope = "devise" if scope.nil?
assert_file "app/views/#{scope}/confirmations/new.html.erb"

View File

@@ -0,0 +1,51 @@
require 'test_helper'
class DeviseHelperTest < ActionController::IntegrationTest
setup do
model_labels = { :models => { :user => "utilisateur" } }
I18n.backend.store_translations :fr,
{
:errors => { :messages => { :not_saved => {
:one => "Erreur lors de l'enregistrement de '%{resource}': 1 erreur.",
:other => "Erreur lors de l'enregistrement de '%{resource}': %{count} erreurs."
} } },
:activerecord => model_labels,
:mongoid => model_labels
}
I18n.locale = 'fr'
end
teardown do
I18n.locale = 'en'
end
test 'test errors.messages.not_saved with single error from i18n' do
get new_user_registration_path
fill_in 'password', :with => 'new_user123'
fill_in 'password confirmation', :with => 'new_user123'
click_button 'Sign up'
assert_have_selector '#error_explanation'
assert_contain "Erreur lors de l'enregistrement de 'utilisateur': 1 erreur"
end
test 'test errors.messages.not_saved with multiple errors from i18n' do
# Dirty tracking behavior prevents email validations from being applied:
# https://github.com/mongoid/mongoid/issues/756
(pending "Fails on Mongoid < 2.1"; break) if defined?(Mongoid) && Mongoid::VERSION.to_f < 2.1
get new_user_registration_path
fill_in 'email', :with => 'invalid_email'
fill_in 'password', :with => 'new_user123'
fill_in 'password confirmation', :with => 'new_user321'
click_button 'Sign up'
assert_have_selector '#error_explanation'
assert_contain "Erreur lors de l'enregistrement de 'utilisateur': 2 erreurs"
end
end

View File

@@ -354,6 +354,20 @@ class AuthenticationWithScopesTest < ActionController::IntegrationTest
end
class AuthenticationOthersTest < ActionController::IntegrationTest
test 'handles unverified requests gets rid of caches' do
swap UsersController, :allow_forgery_protection => true do
post exhibit_user_url(1)
assert_not warden.authenticated?(:user)
sign_in_as_user
assert warden.authenticated?(:user)
post exhibit_user_url(1)
assert_not warden.authenticated?(:user)
assert_equal "User is not authenticated", response.body
end
end
test 'uses the custom controller with the custom controller view' do
get '/admin_area/sign_in'
assert_contain 'Sign in'
@@ -387,14 +401,14 @@ class AuthenticationOthersTest < ActionController::IntegrationTest
test 'sign in stub in xml format' do
get new_user_session_path(:format => 'xml')
assert_equal "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<user>\n <email></email>\n <password></password>\n</user>\n", response.body
assert_equal "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<user>\n <email></email>\n <password nil=\"true\"></password>\n</user>\n", response.body
end
test 'sign in stub in json format' do
get new_user_session_path(:format => 'json')
assert_match '{"user":{', response.body
assert_match '"email":""', response.body
assert_match '"password":""', response.body
assert_match '"password":null', response.body
end
test 'sign in stub in json with non attribute key' do
@@ -402,7 +416,7 @@ class AuthenticationOthersTest < ActionController::IntegrationTest
get new_user_session_path(:format => 'json')
assert_match '{"user":{', response.body
assert_match '"other_key":null', response.body
assert_match '"password":""', response.body
assert_match '"password":null', response.body
end
end
@@ -440,6 +454,23 @@ class AuthenticationOthersTest < ActionController::IntegrationTest
end
end
class AuthenticationKeysTest < ActionController::IntegrationTest
test 'missing authentication keys cause authentication to abort' do
swap Devise, :authentication_keys => [:subdomain] do
sign_in_as_user
assert_contain "Invalid email or password."
assert_not warden.authenticated?(:user)
end
end
test 'missing authentication keys cause authentication to abort unless marked as not required' do
swap Devise, :authentication_keys => { :email => true, :subdomain => false } do
sign_in_as_user
assert warden.authenticated?(:user)
end
end
end
class AuthenticationRequestKeysTest < ActionController::IntegrationTest
test 'request keys are used on authentication' do
host! 'foo.bar.baz'

View File

@@ -37,6 +37,15 @@ class ConfirmationTest < ActionController::IntegrationTest
assert user.reload.confirmed?
end
test 'user should be redirected to a custom path after confirmation' do
Devise::ConfirmationsController.any_instance.stubs(:after_confirmation_path_for).returns("/?custom=1")
user = create_user(:confirm => false)
visit_user_confirmation_with_token(user.confirmation_token)
assert_current_url "/?custom=1"
end
test 'already confirmed user should not be able to confirm the account again' do
user = create_user(:confirm => false)
user.confirmed_at = Time.now
@@ -60,7 +69,7 @@ class ConfirmationTest < ActionController::IntegrationTest
assert_contain 'already confirmed'
end
test 'sign in user automatically after confirming it\'s email' do
test 'sign in user automatically after confirming its email' do
user = create_user(:confirm => false)
visit_user_confirmation_with_token(user.confirmation_token)

View File

@@ -1,6 +1,14 @@
require 'test_helper'
class HttpAuthenticationTest < ActionController::IntegrationTest
test 'handles unverified requests gets rid of caches but continues signed in' do
swap UsersController, :allow_forgery_protection => true do
create_user
post exhibit_user_url(1), {}, "HTTP_AUTHORIZATION" => "Basic #{ActiveSupport::Base64.encode64("user@test.com:123456")}"
assert warden.authenticated?(:user)
assert_equal "User is authenticated", response.body
end
end
test 'sign in should authenticate with http' do
sign_in_as_new_user_with_http

View File

@@ -73,7 +73,7 @@ class LockTest < ActionController::IntegrationTest
assert_not user.reload.access_locked?
end
test "sign in user automatically after unlocking it's account" do
test "sign in user automatically after unlocking its account" do
user = create_user(:locked => true)
visit_user_unlock_with_token(user.unlock_token)
assert warden.authenticated?(:user)

View File

@@ -147,7 +147,7 @@ class PasswordTest < ActionController::IntegrationTest
reset_password :reset_password_token => user.reload.reset_password_token
assert_current_url '/'
assert_contain 'Your password was changed successfully.'
assert_contain 'Your password was changed successfully. You are now signed in.'
assert user.reload.valid_password?('987654321')
end
@@ -166,7 +166,7 @@ class PasswordTest < ActionController::IntegrationTest
assert user.reload.valid_password?('987654321')
end
test 'sign in user automatically after changing it\'s password' do
test 'sign in user automatically after changing its password' do
user = create_user
request_forgot_password
reset_password :reset_password_token => user.reload.reset_password_token
@@ -174,13 +174,24 @@ class PasswordTest < ActionController::IntegrationTest
assert warden.authenticated?(:user)
end
test 'does not sign in user automatically after changing it\'s password if it\'s not active' do
test 'does not sign in user automatically after changing its password if it\'s locked' do
user = create_user(:locked => true)
request_forgot_password
reset_password :reset_password_token => user.reload.reset_password_token
assert_contain 'Your password was changed successfully.'
assert_not_contain 'You are now signed in.'
assert_equal new_user_session_path, @request.path
assert !warden.authenticated?(:user)
end
test 'sign in user automatically and confirm after changing its password if it\'s not confirmed' do
user = create_user(:confirm => false)
request_forgot_password
reset_password :reset_password_token => user.reload.reset_password_token
assert_equal new_user_session_path, @request.path
assert !warden.authenticated?(:user)
assert warden.authenticated?(:user)
assert user.reload.confirmed?
end
test 'reset password request with valid E-Mail in XML format should return valid response' do

View File

@@ -69,6 +69,10 @@ class RegistrationTest < ActionController::IntegrationTest
end
test 'a guest user cannot sign up with invalid information' do
# Dirty tracking behavior prevents email validations from being applied:
# https://github.com/mongoid/mongoid/issues/756
(pending "Fails on Mongoid < 2.1"; break) if defined?(Mongoid) && Mongoid::VERSION.to_f < 2.1
get new_user_registration_path
fill_in 'email', :with => 'invalid_email'
@@ -87,6 +91,10 @@ class RegistrationTest < ActionController::IntegrationTest
end
test 'a guest should not sign up with email/password that already exists' do
# Dirty tracking behavior prevents email validations from being applied:
# https://github.com/mongoid/mongoid/issues/756
(pending "Fails on Mongoid < 2.1"; break) if defined?(Mongoid) && Mongoid::VERSION.to_f < 2.1
user = create_user
get new_user_registration_path
@@ -211,14 +219,14 @@ class RegistrationTest < ActionController::IntegrationTest
get new_user_registration_path(:format => 'xml')
assert_response :success
assert_match %(<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<user>), response.body
assert_no_match(/<confirmation_token>/, response.body) if DEVISE_ORM == :active_record
assert_no_match(/<confirmation-token/, response.body)
end
test 'a user with JSON sign up stub' do
get new_user_registration_path(:format => 'json')
assert_response :success
assert_match %({"user":), response.body
assert_no_match(/"confirmation_token"/, response.body) if DEVISE_ORM == :active_record
assert_no_match(/"confirmation_token"/, response.body)
end
test 'an admin sign up with valid information in XML format should return valid response' do

View File

@@ -38,6 +38,18 @@ class RememberMeTest < ActionController::IntegrationTest
assert_nil request.cookies["remember_user_cookie"]
end
test 'handles unverified requests gets rid of caches' do
swap UsersController, :allow_forgery_protection => true do
post exhibit_user_url(1)
assert_not warden.authenticated?(:user)
create_user_and_remember
post exhibit_user_url(1)
assert_equal "User is not authenticated", response.body
assert_not warden.authenticated?(:user)
end
end
test 'generate remember token after sign in' do
user = sign_in_as_user :remember_me => true
assert request.cookies["remember_user_token"]

View File

@@ -13,6 +13,17 @@ class TokenAuthenticationTest < ActionController::IntegrationTest
end
end
test 'authenticate with valid authentication token key and value through params, when params with the same key as scope exist' do
swap Devise, :token_authentication_key => :secret_token do
user = create_user_with_authentication_token
post exhibit_user_path(user), Devise.token_authentication_key => user.authentication_token, :user => { :some => "data" }
assert_response :success
assert_contain 'User is authenticated'
assert warden.authenticated?(:user)
end
end
test 'authenticate with valid authentication token key but does not store if stateless' do
swap Devise, :token_authentication_key => :secret_token, :stateless_token => true do
sign_in_as_new_user_with_token

View File

@@ -4,6 +4,7 @@ class ConfirmationInstructionsTest < ActionMailer::TestCase
def setup
setup_mailer
Devise.mailer = 'Devise::Mailer'
Devise.mailer_sender = 'test@example.com'
end
@@ -35,6 +36,11 @@ class ConfirmationInstructionsTest < ActionMailer::TestCase
assert_equal ['test@example.com'], mail.from
end
test 'setup sender from custom mailer defaults' do
Devise.mailer = 'Users::Mailer'
assert_equal ['custom@example.com'], mail.from
end
test 'setup reply to as copy from sender' do
assert_equal ['test@example.com'], mail.reply_to
end

View File

@@ -4,6 +4,7 @@ class ResetPasswordInstructionsTest < ActionMailer::TestCase
def setup
setup_mailer
Devise.mailer = 'Devise::Mailer'
Devise.mailer_sender = 'test@example.com'
end
@@ -38,6 +39,11 @@ class ResetPasswordInstructionsTest < ActionMailer::TestCase
assert_equal ['test@example.com'], mail.from
end
test 'setup sender from custom mailer defaults' do
Devise.mailer = 'Users::Mailer'
assert_equal ['custom@example.com'], mail.from
end
test 'setup reply to as copy from sender' do
assert_equal ['test@example.com'], mail.reply_to
end

View File

@@ -4,6 +4,7 @@ class UnlockInstructionsTest < ActionMailer::TestCase
def setup
setup_mailer
Devise.mailer = 'Devise::Mailer'
Devise.mailer_sender = 'test@example.com'
end
@@ -38,6 +39,11 @@ class UnlockInstructionsTest < ActionMailer::TestCase
assert_equal ['test@example.com'], mail.from
end
test 'setup sender from custom mailer defaults' do
Devise.mailer = 'Users::Mailer'
assert_equal ['custom@example.com'], mail.from
end
test 'setup reply to as copy from sender' do
assert_equal ['test@example.com'], mail.reply_to
end

View File

@@ -31,6 +31,10 @@ class MappingTest < ActiveSupport::TestCase
assert_equal "admin_area", Devise.mappings[:admin].path
end
test 'allows to skip all routes' do
assert_equal [], Devise.mappings[:skip_admin].used_routes
end
test 'sign_out_via defaults to :get' do
assert_equal :get, Devise.mappings[:user].sign_out_via
end

View File

@@ -121,7 +121,7 @@ class ConfirmableTest < ActiveSupport::TestCase
assert_equal "not found", confirmation_user.errors[:email].join
end
test 'should send email instructions for the user confirm it\'s email' do
test 'should send email instructions for the user confirm its email' do
user = create_user
assert_email_sent do
User.send_confirmation_instructions(:email => user.email)
@@ -219,7 +219,7 @@ class ConfirmableTest < ActiveSupport::TestCase
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
test 'should find a user to send email instructions for the user confirm its 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)

View File

@@ -31,8 +31,10 @@ class EncryptableTest < ActiveSupport::TestCase
test 'should generate a base64 hash using SecureRandom for password salt' do
swap_with_encryptor Admin, :sha1 do
SecureRandom.expects(:base64).with(15).returns('friendly_token')
assert_equal 'friendly_token', create_admin.password_salt
SecureRandom.expects(:base64).with(15).returns('01lI')
salt = create_admin.password_salt
assert_not_equal '01lI', salt
assert_equal 4, salt.size
end
end

View File

@@ -0,0 +1,38 @@
require 'test_helper'
class SerializableTest < ActiveSupport::TestCase
setup do
@user = create_user
end
test 'should not include unsafe keys on XML' do
assert_match /email/, @user.to_xml
assert_no_match /confirmation-token/, @user.to_xml
end
test 'should not include unsafe keys on XML even if a new except is provided' do
assert_no_match /email/, @user.to_xml(:except => :email)
assert_no_match /confirmation-token/, @user.to_xml(:except => :email)
end
test 'should include unsafe keys on XML if a force_except is provided' do
assert_no_match /email/, @user.to_xml(:force_except => :email)
assert_match /confirmation-token/, @user.to_xml(:force_except => :email)
end
test 'should not include unsafe keys on JSON' do
assert_match /"email":/, @user.to_json
assert_no_match /"confirmation_token":/, @user.to_json
end
test 'should not include unsafe keys on JSON even if a new except is provided' do
assert_no_match /"email":/, @user.to_json(:except => :email)
assert_no_match /"confirmation_token":/, @user.to_json(:except => :email)
end
test 'should include unsafe keys on JSON if a force_except is provided' do
assert_no_match /"email":/, @user.to_json(:force_except => :email)
assert_match /"confirmation_token":/, @user.to_json(:force_except => :email)
end
end

View File

@@ -27,12 +27,6 @@ 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!

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
require 'test_helper'
class ValidatableTest < ActiveSupport::TestCase
@@ -28,7 +29,7 @@ class ValidatableTest < ActiveSupport::TestCase
assert user.invalid?
assert_not_equal 'is invalid', user.errors[:email].join
%w(invalid_email_format 123 $$$ \(\) ).each do |email|
%w{invalid_email_format 123 $$$ () ☃ bla@bla.}.each do |email|
user.email = email
assert user.invalid?, 'should be invalid with email ' << email
assert_equal 'is invalid', user.errors[:email].join
@@ -39,7 +40,7 @@ class ValidatableTest < ActiveSupport::TestCase
end
test 'should accept valid emails' do
%w(a.b.c@example.com test_mail@gmail.com any@any.net email@test.br 123@mail.test).each do |email|
%w(a.b.c@example.com test_mail@gmail.com any@any.net email@test.br 123@mail.test 1☃3@mail.test).each do |email|
user = new_user(:email => email)
assert user.valid?, 'should be valid with email ' << email
assert_blank user.errors[:email]

View File

@@ -42,18 +42,16 @@ class ActiveRecordTest < ActiveSupport::TestCase
assert_include_modules Admin, :database_authenticatable, :registerable, :timeoutable, :recoverable, :lockable, :rememberable, :encryptable
end
if DEVISE_ORM == :active_record
test 'validations options are not applied to late' do
validators = WithValidation.validators_on :password
length = validators.find { |v| v.kind == :length }
assert_equal 2, length.options[:minimum]
assert_equal 6, length.options[:maximum]
end
test 'validations options are not applied too late' do
validators = WithValidation.validators_on :password
length = validators.find { |v| v.kind == :length }
assert_equal 2, length.options[:minimum]
assert_equal 6, length.options[:maximum]
end
test 'validations are applied just once' do
validators = Several.validators_on :password
assert_equal 1, validators.select{ |v| v.kind == :length }.length
end
test 'validations are applied just once' do
validators = Several.validators_on :password
assert_equal 1, validators.select{ |v| v.kind == :length }.length
end
test 'chosen modules are inheritable' do

View File

@@ -28,31 +28,31 @@ class OmniAuthRoutesTest < ActionController::TestCase
end
test 'should generate authorization path' do
assert_match "/users/auth/facebook", @controller.omniauth_authorize_path(:user, :facebook)
assert_match "/users/auth/facebook", @controller.send(:omniauth_authorize_path, :user, :facebook)
assert_raise ArgumentError do
@controller.omniauth_authorize_path(:user, :github)
@controller.send :omniauth_authorize_path, :user, :github
end
end
test 'should generate authorization path for named open_id omniauth' do
assert_match "/users/auth/google", @controller.omniauth_authorize_path(:user, :google)
assert_match "/users/auth/google", @controller.send(:omniauth_authorize_path, :user, :google)
end
test 'should generate authorization path with params' do
assert_match "/users/auth/open_id?openid_url=http%3A%2F%2Fyahoo.com",
@controller.omniauth_authorize_path(:user, :open_id, :openid_url => "http://yahoo.com")
@controller.send(:omniauth_authorize_path, :user, :open_id, :openid_url => "http://yahoo.com")
end
test 'should not add a "?" if no param was sent' do
assert_equal "/users/auth/open_id",
@controller.omniauth_authorize_path(:user, :open_id)
@controller.send(: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)
@controller.send(:omniauth_authorize_path, :user, :facebook)
end
end

View File

@@ -1,6 +1,9 @@
require 'mongoid/version'
Mongoid.configure do |config|
config.master = Mongo::Connection.new('127.0.0.1', 27017).db("devise-test-suite")
config.use_utc = true
config.include_root_in_json = true
end
class ActiveSupport::TestCase

View File

@@ -3,6 +3,4 @@ require 'shared_user'
class User < ActiveRecord::Base
include Shim
include SharedUser
attr_accessible :username, :email, :password, :password_confirmation, :remember_me
end

View File

@@ -1,5 +1,6 @@
class UsersController < ApplicationController
before_filter :authenticate_user!, :except => :accept
prepend_before_filter :current_user, :only => :exhibit
before_filter :authenticate_user!, :except => [:accept, :exhibit]
respond_to :html, :xml
def index
@@ -11,6 +12,10 @@ class UsersController < ApplicationController
@current_user = current_user
end
def exhibit
render :text => current_user ? "User is authenticated" : "User is not authenticated"
end
def expire
user_session['last_request_at'] = 31.minutes.ago.utc
render :text => 'User will be expired on next request'

View File

@@ -0,0 +1,3 @@
class Users::Mailer < Devise::Mailer
default :from => 'custom@example.com'
end

View File

@@ -21,9 +21,4 @@ module Shim
def ==(other)
other.is_a?(self.class) && _id == other._id
end
# Mongoid does not have this method in the current beta version (2.0.0.beta.20)
def update_attribute(attribute, value)
update_attributes(attribute => value)
end
end

View File

@@ -29,6 +29,7 @@ module RailsApp
# Configure sensitive parameters which will be filtered from the log file.
config.filter_parameters << :password
config.assets.enabled = false
config.action_mailer.default_url_options = { :host => "localhost:3000" }

View File

@@ -2,12 +2,7 @@ unless defined?(DEVISE_ORM)
DEVISE_ORM = (ENV["DEVISE_ORM"] || :active_record).to_sym
end
begin
require File.expand_path("../../../../.bundle/environment", __FILE__)
rescue LoadError
require 'rubygems'
require 'bundler'
Bundler.setup :default, :test, DEVISE_ORM
end
require 'rubygems'
require 'bundler/setup'
$:.unshift File.expand_path('../../../../lib', __FILE__)
$:.unshift File.expand_path('../../../../lib', __FILE__)

View File

@@ -2,7 +2,8 @@
# four configuration values can also be set straight in your models.
Devise.setup do |config|
# ==> Mailer Configuration
# Configure the e-mail address which will be shown in DeviseMailer.
# Configure the e-mail address which will be shown in Devise::Mailer,
# note that it will be overwritten if you use your own mailer class with default "from" parameter.
config.mailer_sender = "please-change-me@config-initializers-devise.com"
# Configure the class responsible to send e-mails.
@@ -35,7 +36,7 @@ Devise.setup do |config|
# 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 ]
# Configure which authentication keys should have whitespace stripped.
# These keys will have whitespace before and after removed upon creating or
# modifying a user and when used to authenticate or find a user. Default is :email.

View File

@@ -3,6 +3,10 @@ Rails.application.routes.draw do
resources :users, :only => [:index] do
get :expire, :on => :member
get :accept, :on => :member
authenticate do
post :exhibit, :on => :member
end
end
resources :admins, :only => [:index]
@@ -46,6 +50,12 @@ Rails.application.routes.draw do
constraints(:host => /192\.168\.1\.\d\d\d/) do
devise_for :homebase_admin, :class_name => "Admin", :path => "homebase"
end
devise_for :skip_admin, :class_name => "Admin", :skip => :all
# Routes for format=false testing
devise_for :htmlonly_admin, :class_name => "Admin", :skip => [:confirmations, :unlocks], :path => "htmlonly_admin", :format => false, :skip_helpers => [:confirmations, :unlocks]
devise_for :htmlonly_users, :class_name => "User", :only => [:confirmations, :unlocks], :path => "htmlonly_users", :format => false, :skip_helpers => true
# Other routes for routing_test.rb
devise_for :reader, :class_name => "User", :only => :passwords
@@ -72,5 +82,6 @@ Rails.application.routes.draw do
match "/set", :to => "home#set"
match "/unauthenticated", :to => "home#unauthenticated"
root :to => "home#index"
end
end

View File

@@ -7,6 +7,7 @@ module SharedUser
:trackable, :validatable, :omniauthable
attr_accessor :other_key
attr_accessible :username, :email, :password, :password_confirmation, :remember_me
# They need to be included after Devise is called.
extend ExtendMethods

View File

@@ -190,6 +190,41 @@ class CustomizedRoutingTest < ActionController::TestCase
assert_recognizes({:controller => 'devise/registrations', :action => 'new'}, {:path => 'http://10.0.0.100//homebase/sign_up', :method => :get})
end
end
test 'map with format false for sessions' do
assert_recognizes({:controller => 'devise/sessions', :action => 'new'}, {:path => '/htmlonly_admin/sign_in', :method => :get})
assert_raise ActionController::RoutingError do
assert_recognizes({:controller => 'devise/sessions', :action => 'new'}, {:path => '/htmlonly_admin/sign_in.xml', :method => :get})
end
end
test 'map with format false for passwords' do
assert_recognizes({:controller => 'devise/passwords', :action => 'create'}, {:path => '/htmlonly_admin/password', :method => :post})
assert_raise ActionController::RoutingError do
assert_recognizes({:controller => 'devise/passwords', :action => 'create'}, {:path => '/htmlonly_admin/password.xml', :method => :post})
end
end
test 'map with format false for registrations' do
assert_recognizes({:controller => 'devise/registrations', :action => 'new'}, {:path => '/htmlonly_admin/sign_up', :method => :get})
assert_raise ActionController::RoutingError do
assert_recognizes({:controller => 'devise/registrations', :action => 'new'}, {:path => '/htmlonly_admin/sign_up.xml', :method => :get})
end
end
test 'map with format false for confirmations' do
assert_recognizes({:controller => 'devise/confirmations', :action => 'show'}, {:path => '/htmlonly_users/confirmation', :method => :get})
assert_raise ActionController::RoutingError do
assert_recognizes({:controller => 'devise/confirmations', :action => 'show'}, {:path => '/htmlonly_users/confirmation.xml', :method => :get})
end
end
test 'map with format false for unlocks' do
assert_recognizes({:controller => 'devise/unlocks', :action => 'show'}, {:path => '/htmlonly_users/unlock', :method => :get})
assert_raise ActionController::RoutingError do
assert_recognizes({:controller => 'devise/unlocks', :action => 'show'}, {:path => '/htmlonly_users/unlock.xml', :method => :get})
end
end
end
class ScopedRoutingTest < ActionController::TestCase