mirror of
https://github.com/heartcombo/devise.git
synced 2026-01-09 23:58:06 -05:00
Compare commits
538 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0efcba3627 | ||
|
|
07e77eb4b3 | ||
|
|
e3d0a2ba45 | ||
|
|
08edcc10fe | ||
|
|
2d919fba32 | ||
|
|
843168d5c7 | ||
|
|
095572b6fd | ||
|
|
b9112d4308 | ||
|
|
23c5517009 | ||
|
|
32e60fade5 | ||
|
|
fc251c306c | ||
|
|
f6a74e90e5 | ||
|
|
91f2bce08e | ||
|
|
5e81210400 | ||
|
|
4b7fcac23a | ||
|
|
213ed81641 | ||
|
|
3232d14b20 | ||
|
|
949c9e5ded | ||
|
|
66c829eef4 | ||
|
|
6a22e88dfa | ||
|
|
605924a921 | ||
|
|
72c3472fe1 | ||
|
|
ea870e0636 | ||
|
|
3f00d735a4 | ||
|
|
1437ae2ce3 | ||
|
|
052cbef205 | ||
|
|
b1754074e5 | ||
|
|
e8b70bb04d | ||
|
|
58cbd91512 | ||
|
|
177ed8a356 | ||
|
|
a5e63d7a28 | ||
|
|
5ecbbdf260 | ||
|
|
efe34219a9 | ||
|
|
bc0cab8d60 | ||
|
|
7e855eddef | ||
|
|
8541c465d7 | ||
|
|
4e318b5167 | ||
|
|
5e7caffc9e | ||
|
|
87edf0fbcf | ||
|
|
e7de0d4c4c | ||
|
|
2a8d0f9bee | ||
|
|
4681f81ce6 | ||
|
|
86f2696b84 | ||
|
|
20cf73facf | ||
|
|
d0219d914f | ||
|
|
50d17bbb8e | ||
|
|
3dccf3c6ff | ||
|
|
acd33174fc | ||
|
|
d56641f514 | ||
|
|
354e5022bf | ||
|
|
3cdbf15fe9 | ||
|
|
143794d701 | ||
|
|
4048545151 | ||
|
|
32648027e2 | ||
|
|
7e96bac6a4 | ||
|
|
f5a77ac598 | ||
|
|
591f4a97f7 | ||
|
|
cf1989e1da | ||
|
|
7c8c0f8dba | ||
|
|
66afa2a2bf | ||
|
|
747751a20f | ||
|
|
8e0327e203 | ||
|
|
d88b3cedfb | ||
|
|
9a60415e2e | ||
|
|
b861a65e72 | ||
|
|
1ab7792beb | ||
|
|
c4d5a3fdaa | ||
|
|
11a77055f1 | ||
|
|
9bc8e1211b | ||
|
|
cd1bc53947 | ||
|
|
fffbeb5cc7 | ||
|
|
7539d31a05 | ||
|
|
78fedd6c10 | ||
|
|
14a0cfefaa | ||
|
|
b7e67115fc | ||
|
|
b7bc8dec12 | ||
|
|
b8ed2f3160 | ||
|
|
b46b7e3736 | ||
|
|
c5ef39f087 | ||
|
|
cfb8228de9 | ||
|
|
4e0c598de1 | ||
|
|
fed6a92d55 | ||
|
|
2c1ca126f4 | ||
|
|
36fb1ecf4d | ||
|
|
08986dbd4b | ||
|
|
b69d2c412f | ||
|
|
6f5d176e8e | ||
|
|
57515de5ad | ||
|
|
49aebde435 | ||
|
|
bc598b9da3 | ||
|
|
da0323e591 | ||
|
|
061e9d7404 | ||
|
|
3c519b13ff | ||
|
|
aeec6138c2 | ||
|
|
75ad4ee87b | ||
|
|
e029ad7b0c | ||
|
|
225afe6813 | ||
|
|
8487637b2f | ||
|
|
8978bd4fe0 | ||
|
|
5926898cf4 | ||
|
|
df2995ce19 | ||
|
|
5717c6f082 | ||
|
|
72cf2481b5 | ||
|
|
5c39a0c6d1 | ||
|
|
56a26bd280 | ||
|
|
b194882b23 | ||
|
|
b5909f9b93 | ||
|
|
3c9cfa50c0 | ||
|
|
e632240aee | ||
|
|
176158a309 | ||
|
|
2503f2d0a8 | ||
|
|
85897b4fe2 | ||
|
|
fdd47d74db | ||
|
|
ae4448403c | ||
|
|
2ead747be6 | ||
|
|
10aadee637 | ||
|
|
7670eb8e98 | ||
|
|
486dc65884 | ||
|
|
17e85aa79d | ||
|
|
10c9a492ab | ||
|
|
b7079c7cf2 | ||
|
|
55e69b18a4 | ||
|
|
020341176c | ||
|
|
a79846730e | ||
|
|
48eea9d325 | ||
|
|
dd7c3ee91f | ||
|
|
4e2cdc2d5b | ||
|
|
545a5cec3b | ||
|
|
ab77e08690 | ||
|
|
39c1a2c7d0 | ||
|
|
270e2ece19 | ||
|
|
6b5988d756 | ||
|
|
a4efbb9ad6 | ||
|
|
eb0ad1c21a | ||
|
|
f5e33089a0 | ||
|
|
e499fadf52 | ||
|
|
70199ed039 | ||
|
|
fb07558082 | ||
|
|
5ad122b928 | ||
|
|
c78b4b40c1 | ||
|
|
ef2a2280a3 | ||
|
|
42fca4dbe5 | ||
|
|
03f2a6a5e4 | ||
|
|
cc2fea8276 | ||
|
|
bb4cc2428f | ||
|
|
43f7cf0f12 | ||
|
|
bb5d65209a | ||
|
|
69f79ad446 | ||
|
|
75fdd2944d | ||
|
|
ae48fc8419 | ||
|
|
d6d61fc5be | ||
|
|
19c8f0c0ad | ||
|
|
63627d1439 | ||
|
|
662f0e76d8 | ||
|
|
eadce2fef6 | ||
|
|
0fe0373144 | ||
|
|
1f9ebbd9f4 | ||
|
|
a0058d5fbf | ||
|
|
e8d1c9ca23 | ||
|
|
d9d5ae3d58 | ||
|
|
b51c7fe59b | ||
|
|
a6b754b697 | ||
|
|
92218e9ecc | ||
|
|
60e933df73 | ||
|
|
b451fc0aad | ||
|
|
2f28e48f54 | ||
|
|
76e4967ca1 | ||
|
|
dceb788c6b | ||
|
|
fae8e977e8 | ||
|
|
0a588fab3a | ||
|
|
bbf57214ac | ||
|
|
804fbdf6d5 | ||
|
|
e4987e8bb7 | ||
|
|
9d5a9c8a61 | ||
|
|
c8aa5f3e62 | ||
|
|
df4b282566 | ||
|
|
b8c5d76c5a | ||
|
|
b871bd5036 | ||
|
|
c439b80524 | ||
|
|
704221d48f | ||
|
|
da70348662 | ||
|
|
2e6457006e | ||
|
|
1f68309c47 | ||
|
|
c618969677 | ||
|
|
93013c2e89 | ||
|
|
8ec89bf659 | ||
|
|
b3edfeab73 | ||
|
|
c63483ae24 | ||
|
|
3ed0dc5d9f | ||
|
|
8a93c34080 | ||
|
|
2dfa7e1761 | ||
|
|
5bf4f57fcf | ||
|
|
1b8fd7c2ff | ||
|
|
f75352a373 | ||
|
|
fa5ae57ce4 | ||
|
|
ac2ebdfb11 | ||
|
|
ea94e199ce | ||
|
|
d89dad5728 | ||
|
|
32a141d2a9 | ||
|
|
36557ef641 | ||
|
|
aa24335656 | ||
|
|
1acd3d1790 | ||
|
|
d20fdf87b6 | ||
|
|
95f56258d7 | ||
|
|
8e9ad4626e | ||
|
|
2de7cbae25 | ||
|
|
37473cdaf7 | ||
|
|
bf30d79aca | ||
|
|
148fa99dce | ||
|
|
77203e3d97 | ||
|
|
b151d2cfe2 | ||
|
|
e0ffe8f85f | ||
|
|
78f137368c | ||
|
|
af4a582300 | ||
|
|
2f88f7c0ed | ||
|
|
ce37c301ff | ||
|
|
bd14589fe4 | ||
|
|
c07bc69fad | ||
|
|
9a8cb011d7 | ||
|
|
335a6af861 | ||
|
|
72cbafa322 | ||
|
|
4549d8c65f | ||
|
|
6c566c1ca4 | ||
|
|
41aed807fc | ||
|
|
ddea9359a6 | ||
|
|
5d87e150f7 | ||
|
|
d90e365636 | ||
|
|
22442907af | ||
|
|
10f58b636f | ||
|
|
2d14bd2826 | ||
|
|
f4ceecece4 | ||
|
|
359fdd840c | ||
|
|
c6578250d2 | ||
|
|
dc14c76ff6 | ||
|
|
5e74fd406b | ||
|
|
ebeee33429 | ||
|
|
e449c3b6d2 | ||
|
|
58871172ab | ||
|
|
41a2d65ade | ||
|
|
e6dc425abb | ||
|
|
d29b744d92 | ||
|
|
e79ebe8aec | ||
|
|
10f93129c3 | ||
|
|
04d9512f30 | ||
|
|
135c8da390 | ||
|
|
aca7e5d162 | ||
|
|
02298117a0 | ||
|
|
7998d6f878 | ||
|
|
ed6e232756 | ||
|
|
567fabbbc6 | ||
|
|
d77a956276 | ||
|
|
3c885e043d | ||
|
|
9ae013ae3c | ||
|
|
1bae64d8c4 | ||
|
|
f8792c8cf0 | ||
|
|
198bfff2de | ||
|
|
d3f0665105 | ||
|
|
77b960f14a | ||
|
|
b388aae473 | ||
|
|
81c6d70b7c | ||
|
|
f3928d8462 | ||
|
|
c22d755cf4 | ||
|
|
72cfaad618 | ||
|
|
22897150d8 | ||
|
|
395a69b4ef | ||
|
|
547439d94c | ||
|
|
84f743c4ef | ||
|
|
22a8cfe6d3 | ||
|
|
3025b7e2f7 | ||
|
|
1b2460171e | ||
|
|
f822f92321 | ||
|
|
042ba76480 | ||
|
|
3458e12274 | ||
|
|
d9364f7a4a | ||
|
|
fd0db0b188 | ||
|
|
c9c1e13743 | ||
|
|
25296d8c6f | ||
|
|
34c7981f69 | ||
|
|
f7a658e13d | ||
|
|
1d639bd0c5 | ||
|
|
5ee07390b7 | ||
|
|
83ad67bd51 | ||
|
|
72be1f1289 | ||
|
|
0285565322 | ||
|
|
acc3adb2c1 | ||
|
|
af37800c1d | ||
|
|
86eecc6606 | ||
|
|
349aab72f0 | ||
|
|
bfa65dde70 | ||
|
|
d099d8f0ac | ||
|
|
5190f52857 | ||
|
|
5790107f49 | ||
|
|
6fd21ae37e | ||
|
|
b95c321660 | ||
|
|
0061f113db | ||
|
|
1fb3fbbd88 | ||
|
|
d3f8bd6cae | ||
|
|
0642e2fc9b | ||
|
|
cc017b1f0d | ||
|
|
6c2f51e35e | ||
|
|
47db984f52 | ||
|
|
0c4615e337 | ||
|
|
85e46f0163 | ||
|
|
9913fde749 | ||
|
|
1f940f61c6 | ||
|
|
70e38fe66d | ||
|
|
872ef2b97f | ||
|
|
33fb89340a | ||
|
|
bd9bf326c0 | ||
|
|
d48414b0a5 | ||
|
|
b6a7d11e5a | ||
|
|
75ce916be9 | ||
|
|
c768366240 | ||
|
|
ca7d479e90 | ||
|
|
5bfbc264b7 | ||
|
|
9f8d3db2b4 | ||
|
|
4b0d161f95 | ||
|
|
b2b8b5bf9a | ||
|
|
beda0fe9bd | ||
|
|
8fa3951bea | ||
|
|
9724e386c3 | ||
|
|
f2de7bf84c | ||
|
|
84b8188db9 | ||
|
|
19b5bcbe0f | ||
|
|
7c8f636b98 | ||
|
|
5745d97232 | ||
|
|
86f0bff332 | ||
|
|
30ab6f923d | ||
|
|
839e8fc8ac | ||
|
|
4c83743263 | ||
|
|
e1fde192f2 | ||
|
|
73389ea491 | ||
|
|
eeb6a30752 | ||
|
|
01669c7374 | ||
|
|
ac3a25bf2e | ||
|
|
0652117c79 | ||
|
|
2261005ed5 | ||
|
|
e80e0c9a89 | ||
|
|
79e9d6e564 | ||
|
|
0c6f2adf14 | ||
|
|
77ec1b08cd | ||
|
|
2be9fb292e | ||
|
|
88dba417ef | ||
|
|
b98f021d0f | ||
|
|
c026b5a3f6 | ||
|
|
3696cbf33e | ||
|
|
cbfdcbeaed | ||
|
|
130d684198 | ||
|
|
f0f3e15c08 | ||
|
|
19a1ea5211 | ||
|
|
6c2c808478 | ||
|
|
adc9a45f05 | ||
|
|
50186474d4 | ||
|
|
ffab77c35e | ||
|
|
cde2229e59 | ||
|
|
397fce1f9d | ||
|
|
f044916f94 | ||
|
|
0415564a7d | ||
|
|
ed6f2abc23 | ||
|
|
96a0477555 | ||
|
|
da5464acf6 | ||
|
|
1c8fc18fad | ||
|
|
fbf667e009 | ||
|
|
071ba358a9 | ||
|
|
ef4db2e93d | ||
|
|
6a2ef52aa0 | ||
|
|
d821275588 | ||
|
|
59966e817c | ||
|
|
b1df686a2e | ||
|
|
ae426dcc1c | ||
|
|
1646684af9 | ||
|
|
ac58c28617 | ||
|
|
7d72121bd7 | ||
|
|
10235f9d72 | ||
|
|
5d311e7557 | ||
|
|
5d86327e4d | ||
|
|
61903b534a | ||
|
|
ee61d86546 | ||
|
|
06a2cff140 | ||
|
|
2f36d0dd32 | ||
|
|
d5a2a9b2da | ||
|
|
8ee1591868 | ||
|
|
18c377e0d7 | ||
|
|
00a01c2bc4 | ||
|
|
00e8841e93 | ||
|
|
f79bb31ee6 | ||
|
|
d6449d014e | ||
|
|
b853871667 | ||
|
|
f796439cf2 | ||
|
|
692175b897 | ||
|
|
68dc20cba2 | ||
|
|
90dbae4c7a | ||
|
|
564e588f5e | ||
|
|
8f4b06542e | ||
|
|
7513512000 | ||
|
|
7b04ecdddb | ||
|
|
50338b34f9 | ||
|
|
75268bed5c | ||
|
|
e873e2aeed | ||
|
|
b27491061e | ||
|
|
9e096a4113 | ||
|
|
8c7bf7dd15 | ||
|
|
f7dd59839c | ||
|
|
84c4759f58 | ||
|
|
e345d3940c | ||
|
|
d59301ed2a | ||
|
|
48751783a7 | ||
|
|
691172d01f | ||
|
|
eb51d0365f | ||
|
|
422bf89182 | ||
|
|
4962fbcb51 | ||
|
|
be2b481385 | ||
|
|
d169ef3641 | ||
|
|
2a64972321 | ||
|
|
33fac7f765 | ||
|
|
5c2e3e1a12 | ||
|
|
4a24667e80 | ||
|
|
c3d9dc3007 | ||
|
|
df0a9401b1 | ||
|
|
f7f086faae | ||
|
|
6ae64b1723 | ||
|
|
7d41072c0e | ||
|
|
2f75b12add | ||
|
|
352dd1f2fc | ||
|
|
bdf0bc7b1e | ||
|
|
b1f490a2f8 | ||
|
|
73f617db7b | ||
|
|
1da8490dbc | ||
|
|
6e79c5c242 | ||
|
|
f4db03d31c | ||
|
|
8bc1096099 | ||
|
|
a23247d431 | ||
|
|
6a37945025 | ||
|
|
dcada8fe75 | ||
|
|
f80cecc864 | ||
|
|
1d6ee13aae | ||
|
|
01d3ed7172 | ||
|
|
a1411c885f | ||
|
|
6e48fcee76 | ||
|
|
42a0c30139 | ||
|
|
87f2fa9767 | ||
|
|
8463c6dce4 | ||
|
|
9b77ac0cab | ||
|
|
0afae74386 | ||
|
|
56c1ab0824 | ||
|
|
1ec23994f2 | ||
|
|
2950434ed3 | ||
|
|
1aca139c65 | ||
|
|
fa451306fc | ||
|
|
c179cef365 | ||
|
|
3511f8ac00 | ||
|
|
1579ec9a87 | ||
|
|
cbc6926e3d | ||
|
|
9678b422ff | ||
|
|
d1bf31729d | ||
|
|
a89a2052b8 | ||
|
|
6c80839e7b | ||
|
|
972ac3b5f0 | ||
|
|
caa8961938 | ||
|
|
619826fbc8 | ||
|
|
fe62d1bf6a | ||
|
|
95f20587ef | ||
|
|
8171ad39e0 | ||
|
|
0c9b79947d | ||
|
|
4c9680787d | ||
|
|
6eeb9e4b7d | ||
|
|
80b2240ef0 | ||
|
|
2f142724c5 | ||
|
|
174c2903d7 | ||
|
|
1f4c8e39f8 | ||
|
|
3caab6d2ea | ||
|
|
4e5a9bd600 | ||
|
|
fef34d360b | ||
|
|
05ddd9c204 | ||
|
|
ba2e44c6a4 | ||
|
|
4f07ed42e3 | ||
|
|
66716023e4 | ||
|
|
4bc2ff997a | ||
|
|
b1633f2454 | ||
|
|
41a91188f5 | ||
|
|
4def600076 | ||
|
|
18a18e4c72 | ||
|
|
85c90671bc | ||
|
|
16b688eced | ||
|
|
37c55eb192 | ||
|
|
2d7dc3e82d | ||
|
|
e7a8a7247c | ||
|
|
c4818a9fb2 | ||
|
|
8c2a7146df | ||
|
|
311e3206c9 | ||
|
|
6ad6b3d2a6 | ||
|
|
471a05fd59 | ||
|
|
7a12655111 | ||
|
|
1b26869b74 | ||
|
|
13f35d80a9 | ||
|
|
1c4faa7d8a | ||
|
|
c26ed53927 | ||
|
|
fe0f6e96b3 | ||
|
|
6dd7ccee68 | ||
|
|
9327cf8af5 | ||
|
|
512b52e23a | ||
|
|
5df7105301 | ||
|
|
a84fdb771f | ||
|
|
ff75341c75 | ||
|
|
f0d48a96ca | ||
|
|
215fdf119e | ||
|
|
985b646ee1 | ||
|
|
622e480c4b | ||
|
|
2e78a46c52 | ||
|
|
b1b6e53d6f | ||
|
|
65325f7f81 | ||
|
|
9bd82e5a24 | ||
|
|
0689b4558e | ||
|
|
dbea934701 | ||
|
|
8e4d5fb38f | ||
|
|
e324ee9823 | ||
|
|
54e9cabf5d | ||
|
|
7a3f6fb53d | ||
|
|
59a9576498 | ||
|
|
57eb3886ba | ||
|
|
fe9e6db0e2 | ||
|
|
db8eeb6c6e | ||
|
|
2b7328535d | ||
|
|
d4e5424360 | ||
|
|
d67d992749 | ||
|
|
b6c7aafe55 | ||
|
|
9829384829 | ||
|
|
1d79c1982a | ||
|
|
f6259531c3 | ||
|
|
ed03039d19 | ||
|
|
b6abc4623b | ||
|
|
d1949b7b42 | ||
|
|
b6e30427a3 | ||
|
|
96e0dcf5d5 | ||
|
|
ab48435211 | ||
|
|
8bcb05d6c0 | ||
|
|
6b363d6af9 | ||
|
|
2fd2a8662d |
23
.travis.yml
23
.travis.yml
@@ -1,15 +1,20 @@
|
||||
language: ruby
|
||||
script: "bundle exec rake test"
|
||||
rvm:
|
||||
- 1.8.7
|
||||
- 1.9.2
|
||||
- 1.9.3
|
||||
- ree
|
||||
- 2.0.0
|
||||
env:
|
||||
- DEVISE_ORM=mongoid
|
||||
- DEVISE_ORM=active_record
|
||||
gemfile:
|
||||
- gemfiles/Gemfile.rails-3.1.x
|
||||
- gemfiles/Gemfile.rails-3.2.x
|
||||
- Gemfile
|
||||
services:
|
||||
- mongodb
|
||||
notifications:
|
||||
recipients:
|
||||
- jose.valim@plataformatec.com.br
|
||||
- carlos@plataformatec.com.br
|
||||
- rodrigo.flores@plataformatec.com.br
|
||||
- rafael.franca@plataformatec.com.br
|
||||
email: false
|
||||
campfire:
|
||||
on_success: change
|
||||
on_failure: always
|
||||
rooms:
|
||||
- secure: "TRiqvuM4i/QmRDWjUSNitE5/P91BOzDkNl53+bZjjtxcISCswZtmECWBR7n9\n3xwqCOU1o2lfohxZ32OHOj/Nj7o+90zWJfWxcv+if0hIXRiil62M5pg0lZUd\nyJ4M5VQ0lSWo5he1OUrXhSabPJeaK3B8yT/tdh+qO5yzR+vb/jc="
|
||||
|
||||
9
.yardopts
Normal file
9
.yardopts
Normal file
@@ -0,0 +1,9 @@
|
||||
--protected
|
||||
--no-private
|
||||
--embed-mixin ClassMethods
|
||||
-
|
||||
README.md
|
||||
CHANGELOG.rdoc
|
||||
CONTRIBUTING.md
|
||||
MIT-LICENSE
|
||||
|
||||
@@ -1,15 +1,169 @@
|
||||
== trunk (2.1.0.rc2)
|
||||
== 3.1.1
|
||||
|
||||
* bug fix
|
||||
* Improve default message which asked users to sign in even when they were already signed (by @gregates)
|
||||
* Improve error message for when the `config.secret_key` is missing
|
||||
|
||||
== 3.1.0
|
||||
|
||||
Security announcement: http://blog.plataformatec.com.br/2013/08/devise-3-1-now-with-more-secure-defaults/
|
||||
|
||||
* backwards incompatible changes
|
||||
* Do not store confirmation, unlock and reset password tokens directly in the database. This means tokens previously stored in the database are no longer valid. You can reenable this temporarily by setting `config.allow_insecure_tokens_lookup = true` in your configuration file. It is recommended to keep this configuration set to true just temporarily in your production servers only to aid migration
|
||||
* The Devise mailer and its views were changed to explicitly receive a token argument as `@token`. You will need to update your mailers and re-copy the views to your application with `rails g devise:views`
|
||||
* Sanitization of parameters should be done by calling `devise_parameter_sanitizer.sanitize(:action)` instead of `devise_parameter_sanitizer.for(:action)`
|
||||
|
||||
* deprecations
|
||||
* Token authentication is deprecated
|
||||
|
||||
* enhancements
|
||||
* Better security defaults
|
||||
* Allow easier customization of parameter sanitizer (by @alexpeattie)
|
||||
|
||||
* bug fix
|
||||
* Do not confirm e-mail after password reset (by @moll)
|
||||
* Do not sign in after confirmation
|
||||
* Do not store confirmation, unlock and reset password tokens directly in the database
|
||||
* Do not compare directly against confirmation, unlock and reset password tokens
|
||||
* Skip storage for cookies on unverified requests
|
||||
|
||||
== 3.0.2
|
||||
|
||||
* bug fix
|
||||
* Skip storage for cookies on unverified requests
|
||||
|
||||
== 3.0.1
|
||||
|
||||
Security announcement: http://blog.plataformatec.com.br/2013/08/csrf-token-fixation-attacks-in-devise/
|
||||
|
||||
* enhancements
|
||||
* Add after_confirmation callback
|
||||
|
||||
* bug fix
|
||||
* When using rails 3.2, the generator adds 'attr_accessible' to the model (by @jcoyne)
|
||||
* Clean up CSRF token after authentication (by @homakov). Notice this change will clean up the CSRF Token after authentication (sign in, sign up, etc). So if you are using AJAX for such features, you will need to fetch a new CSRF token from the server.
|
||||
|
||||
== 3.0.0
|
||||
|
||||
* enhancements
|
||||
* Rails 4 and Strong Parameters compatibility (by @carlosantoniodasilva, @josevalim, @latortuga, @lucasmazza, @nashby, @rafaelfranca, @spastorino)
|
||||
* Drop support for Rails < 3.2 and Ruby < 1.9.3
|
||||
* Enable to skip sending reconfirmation email when reconfirmable is on and `skip_confirmation_notification!` is invoked (by @tkhr)
|
||||
|
||||
* bug fix
|
||||
* Errors on unlock are now properly reflected on the first `unlock_keys`
|
||||
|
||||
* backwards incompatible changes
|
||||
* Changes on session storage will expire all existing sessions on upgrade
|
||||
|
||||
== 2.2.4
|
||||
|
||||
* enhancements
|
||||
* Add `destroy_with_password` to `DatabaseAuthenticatable`. Allows destroying a record when `:current_password` matches, similarly to how `update_with_password` works. (by @michiel3)
|
||||
* Allow to override path after password resetting (by @worker8)
|
||||
* Add `#skip_confirmation_notification!` method to `Confirmable`. Allows skipping confirmation email without auto-confirming. (by @gregates)
|
||||
* allow_unconfirmed_access_for config from `:confirmable` module can be set to `nil` that means unconfirmed access for unlimited time. (by @nashby)
|
||||
* Support Rails' token strategy on authentication (by @robhurring)
|
||||
* Support explicitly setting the http authentication key via `config.http_authentication_key` (by @neo)
|
||||
|
||||
* bug fix
|
||||
* Do not redirect when accessing devise API via JSON. (by @sebastianwr)
|
||||
* Generating scoped devise views now uses the correct scoped shared links partial instead of the default devise one (by @nashby)
|
||||
* Fix inheriting mailer templates from `Devise::Mailer`
|
||||
* Fix a bug when procs are used as default mailer in Devise (by @tomasv)
|
||||
|
||||
== 2.2.3
|
||||
|
||||
Security announcement: http://blog.plataformatec.com.br/2013/01/security-announcement-devise-v2-2-3-v2-1-3-v2-0-5-and-v1-5-3-released/
|
||||
|
||||
* bug fix
|
||||
* Require string conversion for all values
|
||||
|
||||
== 2.2.2
|
||||
|
||||
* bug fix
|
||||
* Fix bug when checking for reconfirmable in templates
|
||||
|
||||
== 2.2.1
|
||||
|
||||
* bug fix
|
||||
* Fix regression with case_insensitive_keys
|
||||
* Fix regression when password is blank when it is invalid
|
||||
|
||||
== 2.2.0
|
||||
|
||||
* backwards incompatible changes
|
||||
* `headers_for` is deprecated, customize the mailer directly instead
|
||||
* All mailer methods now expect a second argument with delivery options
|
||||
* Default minimum password length is now 8 (by @carlosgaldino)
|
||||
* Support alternate sign in error message when email record does not exist (this adds a new I18n key to the locale file) (by @gabetax)
|
||||
* DeviseController responds only to HTML requests by default (call `DeviseController.respond_to` or `ApplicationController.respond_to` to add new formats)
|
||||
* Support Mongoid 3 onwards (by @durran)
|
||||
|
||||
* enhancements
|
||||
* Fix unlockable which could leak account existence on paranoid mode (by @latortuga)
|
||||
* Confirmable now has a confirm_within option to set a period while the confirmation token is still valid (by @promisedlandt)
|
||||
* Flash messages in controller now respects `resource_name` (by @latortuga)
|
||||
* Separate `sign_in` and `sign_up` on RegistrationsController (by @rubynortheast)
|
||||
* Add autofocus to default views (by @Radagaisus)
|
||||
* Unlock user on password reset (by @marcinb)
|
||||
* Allow validation callbacks to apply to virtual attributes (by @latortuga)
|
||||
|
||||
* bug fix
|
||||
* unconfirmed_email now uses the proper e-mail on salutation
|
||||
* Fix default email_regexp config to not allow spaces (by @kukula)
|
||||
* Fix a regression introduced on warden 1.2.1 (by @ejfinneran)
|
||||
* Properly camelize omniauth strategies (by @saizai)
|
||||
* Do not set flash messages for non navigational requests on session sign out (by @mathieul)
|
||||
* Set the proper fields as required on the lockable module (by @nickhoffman)
|
||||
* Respects Devise mailer default's reply_to (by @mrchrisadams)
|
||||
* Properly assign resource on `sign_in` related action (by @adammcnamara)
|
||||
* `update_with_password` doesn't change encrypted password when it is invalid (by @nashby)
|
||||
* Properly handle namespaced models on Active Record generator (by @nashby)
|
||||
|
||||
== 2.1.2
|
||||
|
||||
* enhancements
|
||||
* Handle backwards incompatibility between Rails 3.2.6 and Thor 0.15.x
|
||||
|
||||
* bug fix
|
||||
* Fix regression on strategy validation on previous release
|
||||
|
||||
== 2.1.1 (yanked)
|
||||
|
||||
* enhancements
|
||||
* `sign_out_all_scopes` now locks warden and does not allow new logins in the same action
|
||||
* `Devise.omniauth_path_prefix` is available to configure omniauth path prefix
|
||||
* Redirect to sign in page when trying to access password#edit without a token (by @gbataille)
|
||||
* Allow a lambda in authenticate(d) routes helpers to further select the scope
|
||||
* Removed warnings on Rails 3.2.6 (by @nashby)
|
||||
|
||||
* bug fix
|
||||
* `update_with_password` now relies on assign_attributes and forwards the :as option (by @wtn)
|
||||
* Do not trigger timeout on sign in related actions
|
||||
* Timeout does not explode when reset_authentication_token! is accidentally defined by Active Model (by @remomueller)
|
||||
|
||||
* deprecations
|
||||
* Strategy#validate() no longer validates nil resources
|
||||
|
||||
== 2.1.0
|
||||
|
||||
* enhancements
|
||||
* Add `check_fields!(model_class)` method on Devise::Models to check if the model includes the fields that Devise uses
|
||||
* Add `skip_reconfirmation!` to skip reconfirmation
|
||||
* Devise model generator now works with engines
|
||||
* Devise encryptable was moved to its new gem (http://github.com/plataformatec/devise-encryptable)
|
||||
|
||||
* deprecations
|
||||
* Deprecations warnings added on Devise 2.0 are now removed with their features
|
||||
* use_salt_as_remember_token and apply_schema does not have any effect since 2.0 and are now deprecated
|
||||
* valid_for_authentication? must now return a boolean
|
||||
* All devise modules should now have a `required_fields(klass)` module method to help gathering missing attributes
|
||||
* `use_salt_as_remember_token` and `apply_schema` does not have any effect since 2.0 and are now deprecated
|
||||
* `valid_for_authentication?` must now return a boolean
|
||||
|
||||
* bug fix
|
||||
* Ensure after sign in hook is not called without a resource
|
||||
* Fix a term: now on Omniauth related flash messages, we say that we're authenticating from an omniauth provider instead of authorizing
|
||||
* Fixed redirect when authenticated mounted apps (by @hakanensari)
|
||||
* Ensure the failure app still respects config.relative_url_root
|
||||
* `/users/sign_in` doesn't choke on protected attributes used to select sign in scope (by @Paymium)
|
||||
* `failed_attempts` is set to zero after any sign in (including via reset password) (by @rodrigoflores)
|
||||
@@ -17,20 +171,7 @@
|
||||
* Do not accidentally mark `_prefixes` as private
|
||||
* Better support for custom strategies on test helpers (by @mattconnolly)
|
||||
* Return `head :no_content` in SessionsController now that most JS libraries handle it (by @julianvargasalvarez)
|
||||
|
||||
== 2.1.0.rc
|
||||
|
||||
* enhancements
|
||||
* Add check_fields! method on Devise::Models to check if the model includes the fields that Devise uses
|
||||
* Add `skip_reconfirmation!` to skip reconfirmation
|
||||
|
||||
* bug fix
|
||||
* Ensure after sign in hook is not called without a resource
|
||||
* Fix a term: now on Omniauth related flash messages, we say that we're authenticating from an omniauth provider instead of authorizing
|
||||
* Fixed redirect when authenticated mounted apps (by @hakanensari)
|
||||
|
||||
* deprecation
|
||||
* All devise modules should have a required_fields(klass) module method to help gathering missing attributes
|
||||
* Reverted moving devise/shared/_links.erb to devise/_links.erb
|
||||
|
||||
== 2.0.4
|
||||
|
||||
@@ -531,7 +672,7 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
|
||||
* Added Registerable
|
||||
* Added Http Basic Authentication support
|
||||
* Allow scoped_views to be customized per controller/mailer class
|
||||
* [#99] Allow authenticatable to used in change_table statements
|
||||
* Allow authenticatable to used in change_table statements
|
||||
|
||||
== 0.9.2
|
||||
|
||||
@@ -671,19 +812,19 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
|
||||
* Added DataMapper support
|
||||
* Remove store_location from authenticatable strategy and add it to failure app
|
||||
* Allow a strategy to be placed after authenticatable
|
||||
* [#45] Do not rely attribute? methods, since they are not added on Datamapper
|
||||
* Do not rely attribute? methods, since they are not added on Datamapper
|
||||
|
||||
== 0.5.6
|
||||
|
||||
* enhancements
|
||||
* [#42] Do not send nil to build (DataMapper compatibility)
|
||||
* [#44] Allow to have scoped views
|
||||
* Do not send nil to build (DataMapper compatibility)
|
||||
* Allow to have scoped views
|
||||
|
||||
== 0.5.5
|
||||
|
||||
* enhancements
|
||||
* Allow overwriting find for authentication method
|
||||
* [#38] Remove Ruby 1.8.7 dependency
|
||||
* Remove Ruby 1.8.7 dependency
|
||||
|
||||
== 0.5.4
|
||||
|
||||
@@ -691,7 +832,7 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
|
||||
* Deprecate :singular in devise_for and use :scope instead
|
||||
|
||||
* enhancements
|
||||
* [#37] Create after_sign_in_path_for and after_sign_out_path_for hooks to be
|
||||
* Create after_sign_in_path_for and after_sign_out_path_for hooks to be
|
||||
overwriten in ApplicationController
|
||||
* Create sign_in_and_redirect and sign_out_and_redirect helpers
|
||||
* Warden::Manager.default_scope is automatically configured to the first given scope
|
||||
@@ -703,7 +844,7 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
|
||||
* Ensure all controllers are unloadable
|
||||
|
||||
* enhancements
|
||||
* [#35] Moved friendly_token to Devise
|
||||
* Moved friendly_token to Devise
|
||||
* Added Devise.all, so you can freeze your app strategies
|
||||
* Added Devise.apply_schema, so you can turn it to false in Datamapper or MongoMapper
|
||||
in cases you don't want it be handlded automatically
|
||||
@@ -711,9 +852,9 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
|
||||
== 0.5.2
|
||||
|
||||
* enhancements
|
||||
* [#28] Improved sign_in and sign_out helpers to accepts resources
|
||||
* [#28] Added stored_location_for as a helper
|
||||
* [#20] Added test helpers
|
||||
* Improved sign_in and sign_out helpers to accepts resources
|
||||
* Added stored_location_for as a helper
|
||||
* Added test helpers
|
||||
|
||||
== 0.5.1
|
||||
|
||||
@@ -734,7 +875,7 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
|
||||
== 0.4.3
|
||||
|
||||
* bug fix
|
||||
* [#29] Authentication just fails if user cannot be serialized from session, without raising errors;
|
||||
* Authentication just fails if user cannot be serialized from session, without raising errors;
|
||||
* Default configuration values should not overwrite user values;
|
||||
|
||||
== 0.4.2
|
||||
@@ -752,7 +893,7 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
|
||||
== 0.4.1
|
||||
|
||||
* bug fix
|
||||
* [#21] Ensure options can be set even if models were not loaded
|
||||
* Ensure options can be set even if models were not loaded
|
||||
|
||||
== 0.4.0
|
||||
|
||||
@@ -763,25 +904,25 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
|
||||
* :authenticable calls are deprecated, use :authenticatable instead
|
||||
|
||||
* enhancements
|
||||
* [#16] Allow devise to be more agnostic and do not require ActiveRecord to be loaded
|
||||
* Allow devise to be more agnostic and do not require ActiveRecord to be loaded
|
||||
* Allow Warden::Manager to be configured through Devise
|
||||
* Created a generator which creates an initializer
|
||||
|
||||
== 0.3.0
|
||||
|
||||
* bug fix
|
||||
* [#15] Allow yml messages to be configured by not using engine locales
|
||||
* Allow yml messages to be configured by not using engine locales
|
||||
|
||||
* deprecations
|
||||
* Renamed confirm_in to confirm_within
|
||||
* [#14] Do not send confirmation messages when user changes his e-mail
|
||||
* [#13] Renamed authenticable to authenticatable and added deprecation warnings
|
||||
* Do not send confirmation messages when user changes his e-mail
|
||||
* Renamed authenticable to authenticatable and added deprecation warnings
|
||||
|
||||
== 0.2.3
|
||||
|
||||
* enhancements
|
||||
* Ensure fail! works inside strategies
|
||||
* [#12] Make unauthenticated message (when you haven't signed in) different from invalid message
|
||||
* Make unauthenticated message (when you haven't signed in) different from invalid message
|
||||
|
||||
* bug fix
|
||||
* Do not redirect on invalid authenticate
|
||||
@@ -790,7 +931,7 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
|
||||
== 0.2.2
|
||||
|
||||
* bug fix
|
||||
* [#9] Fix a bug when using customized resources
|
||||
* Fix a bug when using customized resources
|
||||
|
||||
== 0.2.1
|
||||
|
||||
@@ -798,17 +939,17 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
|
||||
* Clean devise_views generator to use devise existing views
|
||||
|
||||
* enhancements
|
||||
* [#7] Create instance variables (like @user) for each devise controller
|
||||
* Create instance variables (like @user) for each devise controller
|
||||
* Use Devise::Controller::Helpers only internally
|
||||
|
||||
* bug fix
|
||||
* [#6] Fix a bug with Mongrel and Ruby 1.8.6
|
||||
* Fix a bug with Mongrel and Ruby 1.8.6
|
||||
|
||||
== 0.2.0
|
||||
|
||||
* enhancements
|
||||
* [#4] Allow option :null => true in authenticable migration
|
||||
* [#3] Remove attr_accessible calls from devise modules
|
||||
* Allow option :null => true in authenticable migration
|
||||
* Remove attr_accessible calls from devise modules
|
||||
* Customizable time frame for rememberable with :remember_for config
|
||||
* Customizable time frame for confirmable with :confirm_in config
|
||||
* Generators for creating a resource and copy views
|
||||
@@ -817,12 +958,12 @@ Notes: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.
|
||||
* Do not load hooks or strategies if they are not used
|
||||
|
||||
* bug fixes
|
||||
* [#2] Fixed requiring devise strategies
|
||||
* Fixed requiring devise strategies
|
||||
|
||||
== 0.1.1
|
||||
|
||||
* bug fixes
|
||||
* [#1] Fixed requiring devise mapping
|
||||
* Fixed requiring devise mapping
|
||||
|
||||
== 0.1.0
|
||||
|
||||
14
CONTRIBUTING.md
Normal file
14
CONTRIBUTING.md
Normal file
@@ -0,0 +1,14 @@
|
||||
### Please read before contributing
|
||||
|
||||
1) Do not post questions in the issues tracker. If you have any questions about Devise, search the [Wiki](https://github.com/plataformatec/devise/wiki) or use the [Mailing List](https://groups.google.com/group/plataformatec-devise) or [Stack Overflow](http://stackoverflow.com/questions/tagged/devise).
|
||||
|
||||
2) If you find a security bug, **DO NOT** submit an issue here. Please send an e-mail to [developers@plataformatec.com.br](mailto:developers@plataformatec.com.br) instead.
|
||||
|
||||
3) Do a small search on the issues tracker before submitting your issue to see if it was already reported / fixed.
|
||||
|
||||
4) When reporting an issue, include Rails, Devise and Warden versions. If you are getting exceptions, please include the full backtrace.
|
||||
|
||||
That's it! The more information you give, the easier it becomes for us to track it down and fix it.
|
||||
Ideally, you should provide an application that reproduces the error or a test case to Devise's suite.
|
||||
|
||||
Thanks!
|
||||
18
Gemfile
18
Gemfile
@@ -1,8 +1,8 @@
|
||||
source "http://rubygems.org"
|
||||
source "https://rubygems.org"
|
||||
|
||||
gemspec
|
||||
|
||||
gem "rails", "~> 3.2.0"
|
||||
gem "rails", "~> 4.0.0"
|
||||
gem "omniauth", "~> 1.0.0"
|
||||
gem "omniauth-oauth2", "~> 1.0.0"
|
||||
gem "rdoc"
|
||||
@@ -10,12 +10,8 @@ gem "rdoc"
|
||||
group :test do
|
||||
gem "omniauth-facebook"
|
||||
gem "omniauth-openid", "~> 1.0.1"
|
||||
gem "webrat", "0.7.2", :require => false
|
||||
gem "mocha", :require => false
|
||||
|
||||
platforms :mri_18 do
|
||||
gem "ruby-debug", ">= 0.10.3"
|
||||
end
|
||||
gem "webrat", "0.7.3", :require => false
|
||||
gem "mocha", "~> 0.13.1", :require => false
|
||||
end
|
||||
|
||||
platforms :jruby do
|
||||
@@ -26,10 +22,10 @@ end
|
||||
|
||||
platforms :ruby do
|
||||
gem "sqlite3"
|
||||
end
|
||||
|
||||
platforms :mri_19, :mri_20 do
|
||||
group :mongoid do
|
||||
gem "mongo", "~> 1.3.0"
|
||||
gem "mongoid", "~> 2.0"
|
||||
gem "bson_ext", "~> 1.3.0"
|
||||
gem "mongoid", github: "mongoid/mongoid", branch: "master"
|
||||
end
|
||||
end
|
||||
|
||||
223
Gemfile.lock
223
Gemfile.lock
@@ -1,143 +1,141 @@
|
||||
GIT
|
||||
remote: git://github.com/mongoid/mongoid.git
|
||||
revision: 346a79a7d01aa194de80e649916239a18d38ce13
|
||||
branch: master
|
||||
specs:
|
||||
mongoid (4.0.0)
|
||||
activemodel (~> 4.0.0)
|
||||
moped (~> 1.5)
|
||||
origin (~> 1.0)
|
||||
tzinfo (~> 0.3.22)
|
||||
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
devise (2.1.0)
|
||||
devise (3.1.1)
|
||||
bcrypt-ruby (~> 3.0)
|
||||
orm_adapter (~> 0.0.7)
|
||||
railties (~> 3.1)
|
||||
warden (~> 1.1.1)
|
||||
orm_adapter (~> 0.1)
|
||||
railties (>= 3.2.6, < 5)
|
||||
thread_safe (~> 0.1)
|
||||
warden (~> 1.2.3)
|
||||
|
||||
GEM
|
||||
remote: http://rubygems.org/
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actionmailer (3.2.0)
|
||||
actionpack (= 3.2.0)
|
||||
mail (~> 2.4.0)
|
||||
actionpack (3.2.0)
|
||||
activemodel (= 3.2.0)
|
||||
activesupport (= 3.2.0)
|
||||
builder (~> 3.0.0)
|
||||
actionmailer (4.0.0)
|
||||
actionpack (= 4.0.0)
|
||||
mail (~> 2.5.3)
|
||||
actionpack (4.0.0)
|
||||
activesupport (= 4.0.0)
|
||||
builder (~> 3.1.0)
|
||||
erubis (~> 2.7.0)
|
||||
journey (~> 1.0.0)
|
||||
rack (~> 1.4.0)
|
||||
rack-cache (~> 1.1)
|
||||
rack-test (~> 0.6.1)
|
||||
sprockets (~> 2.1.2)
|
||||
activemodel (3.2.0)
|
||||
activesupport (= 3.2.0)
|
||||
builder (~> 3.0.0)
|
||||
activerecord (3.2.0)
|
||||
activemodel (= 3.2.0)
|
||||
activesupport (= 3.2.0)
|
||||
arel (~> 3.0.0)
|
||||
tzinfo (~> 0.3.29)
|
||||
activeresource (3.2.0)
|
||||
activemodel (= 3.2.0)
|
||||
activesupport (= 3.2.0)
|
||||
activesupport (3.2.0)
|
||||
i18n (~> 0.6)
|
||||
multi_json (~> 1.0)
|
||||
addressable (2.2.6)
|
||||
arel (3.0.0)
|
||||
bcrypt-ruby (3.0.1)
|
||||
bson (1.5.1)
|
||||
bson_ext (1.3.1)
|
||||
builder (3.0.0)
|
||||
columnize (0.3.5)
|
||||
rack (~> 1.5.2)
|
||||
rack-test (~> 0.6.2)
|
||||
activemodel (4.0.0)
|
||||
activesupport (= 4.0.0)
|
||||
builder (~> 3.1.0)
|
||||
activerecord (4.0.0)
|
||||
activemodel (= 4.0.0)
|
||||
activerecord-deprecated_finders (~> 1.0.2)
|
||||
activesupport (= 4.0.0)
|
||||
arel (~> 4.0.0)
|
||||
activerecord-deprecated_finders (1.0.3)
|
||||
activesupport (4.0.0)
|
||||
i18n (~> 0.6, >= 0.6.4)
|
||||
minitest (~> 4.2)
|
||||
multi_json (~> 1.3)
|
||||
thread_safe (~> 0.1)
|
||||
tzinfo (~> 0.3.37)
|
||||
arel (4.0.0)
|
||||
atomic (1.1.12)
|
||||
bcrypt-ruby (3.1.2)
|
||||
builder (3.1.4)
|
||||
erubis (2.7.0)
|
||||
faraday (0.7.5)
|
||||
addressable (~> 2.2.6)
|
||||
multipart-post (~> 1.1.3)
|
||||
rack (>= 1.1.0, < 2)
|
||||
faraday (0.8.8)
|
||||
multipart-post (~> 1.2.0)
|
||||
hashie (1.2.0)
|
||||
hike (1.2.1)
|
||||
i18n (0.6.0)
|
||||
journey (1.0.0)
|
||||
json (1.6.5)
|
||||
linecache (0.46)
|
||||
rbx-require-relative (> 0.0.4)
|
||||
mail (2.4.1)
|
||||
i18n (>= 0.4.0)
|
||||
hike (1.2.3)
|
||||
httpauth (0.2.0)
|
||||
i18n (0.6.5)
|
||||
json (1.8.0)
|
||||
jwt (0.1.8)
|
||||
multi_json (>= 1.5)
|
||||
mail (2.5.4)
|
||||
mime-types (~> 1.16)
|
||||
treetop (~> 1.4.8)
|
||||
metaclass (0.0.1)
|
||||
mime-types (1.17.2)
|
||||
mocha (0.10.0)
|
||||
mime-types (1.23)
|
||||
minitest (4.7.5)
|
||||
mocha (0.13.3)
|
||||
metaclass (~> 0.0.1)
|
||||
mongo (1.3.1)
|
||||
bson (>= 1.3.1)
|
||||
mongoid (2.3.4)
|
||||
activemodel (~> 3.1)
|
||||
mongo (~> 1.3)
|
||||
tzinfo (~> 0.3.22)
|
||||
multi_json (1.0.4)
|
||||
multipart-post (1.1.4)
|
||||
nokogiri (1.5.0)
|
||||
oauth2 (0.5.1)
|
||||
faraday (~> 0.7.4)
|
||||
multi_json (~> 1.0.3)
|
||||
omniauth (1.0.1)
|
||||
moped (1.5.1)
|
||||
multi_json (1.7.9)
|
||||
multipart-post (1.2.0)
|
||||
nokogiri (1.5.9)
|
||||
oauth2 (0.8.1)
|
||||
faraday (~> 0.8)
|
||||
httpauth (~> 0.1)
|
||||
jwt (~> 0.1.4)
|
||||
multi_json (~> 1.0)
|
||||
rack (~> 1.2)
|
||||
omniauth (1.0.3)
|
||||
hashie (~> 1.2)
|
||||
rack
|
||||
omniauth-facebook (1.0.0)
|
||||
omniauth-oauth2 (~> 1.0.0)
|
||||
omniauth-oauth2 (1.0.0)
|
||||
oauth2 (~> 0.5.0)
|
||||
omniauth-facebook (1.4.0)
|
||||
omniauth-oauth2 (~> 1.0.2)
|
||||
omniauth-oauth2 (1.0.3)
|
||||
oauth2 (~> 0.8.0)
|
||||
omniauth (~> 1.0)
|
||||
omniauth-openid (1.0.1)
|
||||
omniauth (~> 1.0)
|
||||
rack-openid (~> 1.3.1)
|
||||
orm_adapter (0.0.7)
|
||||
origin (1.1.0)
|
||||
orm_adapter (0.4.0)
|
||||
polyglot (0.3.3)
|
||||
rack (1.4.1)
|
||||
rack-cache (1.1)
|
||||
rack (>= 0.4)
|
||||
rack (1.5.2)
|
||||
rack-openid (1.3.1)
|
||||
rack (>= 1.1.0)
|
||||
ruby-openid (>= 2.1.8)
|
||||
rack-ssl (1.3.2)
|
||||
rack
|
||||
rack-test (0.6.1)
|
||||
rack-test (0.6.2)
|
||||
rack (>= 1.0)
|
||||
rails (3.2.0)
|
||||
actionmailer (= 3.2.0)
|
||||
actionpack (= 3.2.0)
|
||||
activerecord (= 3.2.0)
|
||||
activeresource (= 3.2.0)
|
||||
activesupport (= 3.2.0)
|
||||
bundler (~> 1.0)
|
||||
railties (= 3.2.0)
|
||||
railties (3.2.0)
|
||||
actionpack (= 3.2.0)
|
||||
activesupport (= 3.2.0)
|
||||
rack-ssl (~> 1.3.2)
|
||||
rails (4.0.0)
|
||||
actionmailer (= 4.0.0)
|
||||
actionpack (= 4.0.0)
|
||||
activerecord (= 4.0.0)
|
||||
activesupport (= 4.0.0)
|
||||
bundler (>= 1.3.0, < 2.0)
|
||||
railties (= 4.0.0)
|
||||
sprockets-rails (~> 2.0.0)
|
||||
railties (4.0.0)
|
||||
actionpack (= 4.0.0)
|
||||
activesupport (= 4.0.0)
|
||||
rake (>= 0.8.7)
|
||||
rdoc (~> 3.4)
|
||||
thor (~> 0.14.6)
|
||||
rake (0.9.2.2)
|
||||
rbx-require-relative (0.0.5)
|
||||
rdoc (3.12)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
rake (10.1.0)
|
||||
rdoc (4.0.1)
|
||||
json (~> 1.4)
|
||||
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)
|
||||
sprockets (2.1.2)
|
||||
ruby-openid (2.2.3)
|
||||
sprockets (2.10.0)
|
||||
hike (~> 1.2)
|
||||
multi_json (~> 1.0)
|
||||
rack (~> 1.0)
|
||||
tilt (~> 1.1, != 1.3.0)
|
||||
sqlite3 (1.3.5)
|
||||
thor (0.14.6)
|
||||
tilt (1.3.3)
|
||||
treetop (1.4.10)
|
||||
sprockets-rails (2.0.0)
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
sprockets (~> 2.8)
|
||||
sqlite3 (1.3.7)
|
||||
thor (0.18.1)
|
||||
thread_safe (0.1.2)
|
||||
atomic
|
||||
tilt (1.4.1)
|
||||
treetop (1.4.14)
|
||||
polyglot
|
||||
polyglot (>= 0.3.1)
|
||||
tzinfo (0.3.31)
|
||||
warden (1.1.1)
|
||||
tzinfo (0.3.37)
|
||||
warden (1.2.3)
|
||||
rack (>= 1.0)
|
||||
webrat (0.7.2)
|
||||
webrat (0.7.3)
|
||||
nokogiri (>= 1.2.0)
|
||||
rack (>= 1.0)
|
||||
rack-test (>= 0.5.3)
|
||||
@@ -148,18 +146,15 @@ PLATFORMS
|
||||
DEPENDENCIES
|
||||
activerecord-jdbc-adapter
|
||||
activerecord-jdbcsqlite3-adapter
|
||||
bson_ext (~> 1.3.0)
|
||||
devise!
|
||||
jruby-openssl
|
||||
mocha
|
||||
mongo (~> 1.3.0)
|
||||
mongoid (~> 2.0)
|
||||
mocha (~> 0.13.1)
|
||||
mongoid!
|
||||
omniauth (~> 1.0.0)
|
||||
omniauth-facebook
|
||||
omniauth-oauth2 (~> 1.0.0)
|
||||
omniauth-openid (~> 1.0.1)
|
||||
rails (~> 3.2.0)
|
||||
rails (~> 4.0.0)
|
||||
rdoc
|
||||
ruby-debug (>= 0.10.3)
|
||||
sqlite3
|
||||
webrat (= 0.7.2)
|
||||
webrat (= 0.7.3)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright 2009-2012 Plataformatec. http://plataformatec.com.br
|
||||
Copyright 2009-2013 Plataformatec. http://plataformatec.com.br
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
227
README.md
227
README.md
@@ -1,25 +1,23 @@
|
||||
*IMPORTANT:* Devise 2.1 is out. If you are upgrading, please read: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.1
|
||||

|
||||
|
||||
*IMPORTANT:* Devise 2.0 is out. If you are upgrading, please read: https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.0
|
||||
By [Plataformatec](http://plataformatec.com.br/).
|
||||
|
||||
## Devise
|
||||
[](http://travis-ci.org/plataformatec/devise)
|
||||
[](https://codeclimate.com/github/plataformatec/devise)
|
||||
|
||||
INFO: This README is [also available in a friendly navigable format](http://devise.plataformatec.com.br/).
|
||||
|
||||
[](http://travis-ci.org/plataformatec/devise)
|
||||
This README is [also available in a friendly navigable format](http://devise.plataformatec.com.br/).
|
||||
|
||||
Devise is a flexible authentication solution for Rails based on Warden. It:
|
||||
|
||||
* Is Rack based;
|
||||
* Is a complete MVC solution based on Rails engines;
|
||||
* Allows you to have multiple roles (or models/scopes) signed in at the same time;
|
||||
* Allows you to have multiple models signed in at the same time;
|
||||
* Is based on a modularity concept: use just what you really need.
|
||||
|
||||
It's comprised of 12 modules:
|
||||
It's composed of 10 modules:
|
||||
|
||||
* [Database Authenticatable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/DatabaseAuthenticatable): encrypts and stores a password in the database to validate the authenticity of a user while signing in. The authentication can be done both through POST requests or HTTP Basic Authentication.
|
||||
* [Token Authenticatable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/TokenAuthenticatable): signs in a user based on an authentication token (also known as "single access token"). The token can be given both through query string or HTTP Basic Authentication.
|
||||
* [Omniauthable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Omniauthable): adds Omniauth (github.com/intridea/omniauth) support;
|
||||
* [Omniauthable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Omniauthable): adds Omniauth (https://github.com/intridea/omniauth) support;
|
||||
* [Confirmable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Confirmable): sends emails with confirmation instructions and verifies whether an account is already confirmed during sign in.
|
||||
* [Recoverable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Recoverable): resets the user password and sends reset instructions.
|
||||
* [Registerable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Registerable): handles signing up users through a registration process, also allowing them to edit and destroy their account.
|
||||
@@ -29,6 +27,8 @@ It's comprised of 12 modules:
|
||||
* [Validatable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Validatable): provides validations of email and password. It's optional and can be customized, so you're able to define your own validations.
|
||||
* [Lockable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Lockable): locks an account after a specified number of failed sign-in attempts. Can unlock via email or after a specified time period.
|
||||
|
||||
Devise is guaranteed to be thread-safe on YARV. Thread-safety support on JRuby is on progress.
|
||||
|
||||
## Information
|
||||
|
||||
### The Devise wiki
|
||||
@@ -57,7 +57,7 @@ You can view the Devise documentation in RDoc format here:
|
||||
|
||||
http://rubydoc.info/github/plataformatec/devise/master/frames
|
||||
|
||||
If you need to use Devise with Rails 2.3, you can always run "gem server" from the command line after you install the gem to access the old documentation.
|
||||
If you need to use Devise with previous versions of Rails, you can always run "gem server" from the command line after you install the gem to access the old documentation.
|
||||
|
||||
### Example applications
|
||||
|
||||
@@ -90,7 +90,7 @@ Once you have solidified your understanding of Rails and authentication mechanis
|
||||
|
||||
## Getting started
|
||||
|
||||
Devise 2.0 works with Rails 3.1 onwards. You can add it to your Gemfile with:
|
||||
Devise 3.0 works with Rails 3.2 onwards. You can add it to your Gemfile with:
|
||||
|
||||
```ruby
|
||||
gem 'devise'
|
||||
@@ -110,7 +110,7 @@ The generator will install an initializer which describes ALL Devise's configura
|
||||
rails generate devise MODEL
|
||||
```
|
||||
|
||||
Replace MODEL by the class name used for the applications users, it's frequently 'User' but could also be 'Admin'. This will create a model (if one does not exist) and configure it with default Devise modules. Next, you'll usually run "rake db:migrate" as the generator will have created a migration file (if your ORM supports them). This generator also configures your config/routes.rb file to point to Devise controller.
|
||||
Replace MODEL by the class name used for the applications users, it's frequently `User` but could also be `Admin`. This will create a model (if one does not exist) and configure it with default Devise modules. Next, you'll usually run `rake db:migrate` as the generator will have created a migration file (if your ORM supports them). This generator also configures your config/routes.rb file to point to the Devise controller.
|
||||
|
||||
Note that you should re-start your app here if you've already started it. Otherwise you'll run into strange errors like users being unable to login and the route helpers being undefined.
|
||||
|
||||
@@ -143,7 +143,7 @@ user_session
|
||||
After signing in a user, confirming the account or updating the password, Devise will look for a scoped root path to redirect. Example: For a :user resource, it will use `user_root_path` if it exists, otherwise default `root_path` will be used. This means that you need to set the root inside your routes:
|
||||
|
||||
```ruby
|
||||
root :to => "home#index"
|
||||
root to: "home#index"
|
||||
```
|
||||
|
||||
You can also overwrite `after_sign_in_path_for` and `after_sign_out_path_for` to customize your redirect hooks.
|
||||
@@ -176,34 +176,65 @@ devise :database_authenticatable, :registerable, :confirmable, :recoverable, :st
|
||||
|
||||
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.
|
||||
|
||||
### Configuring multiple models
|
||||
### Strong Parameters
|
||||
|
||||
Devise allows you to set up as many roles as you want. For example, you may have a User model and also want an Admin model with just authentication and timeoutable features. If so, just follow these steps:
|
||||
When you customize your own views, you may end up adding new attributes to forms. Rails 4 moved the parameter sanitization from the model to the controller, causing Devise to handle this concern at the controller as well.
|
||||
|
||||
There are just three actions in Devise that allows any set of parameters to be passed down to the model, therefore requiring sanitization. Their names and the permited parameters by default are:
|
||||
|
||||
* `sign_in` (`Devise::SessionsController#new`) - Permits only the authentication keys (like `email`)
|
||||
* `sign_up` (`Devise::RegistrationsController#create`) - Permits authentication keys plus `password` and `password_confirmation`
|
||||
* `account_update` (`Devise::RegistrationsController#update`) - Permits authentication keys plus `password`, `password_confirmation` and `current_password`
|
||||
|
||||
In case you want to permit additional parameters (the lazy way™) you can do with a simple before filter in your `ApplicationController`:
|
||||
|
||||
```ruby
|
||||
# Create a migration with the required fields
|
||||
create_table :admins do |t|
|
||||
t.string :email
|
||||
t.string :encrypted_password
|
||||
t.timestamps
|
||||
class ApplicationController < ActionController::Base
|
||||
before_filter :configure_permitted_parameters, if: :devise_controller?
|
||||
|
||||
protected
|
||||
|
||||
def configure_permitted_parameters
|
||||
devise_parameter_sanitizer.for(:sign_up) << :username
|
||||
end
|
||||
end
|
||||
|
||||
# Inside your Admin model
|
||||
devise :database_authenticatable, :timeoutable
|
||||
|
||||
# Inside your routes
|
||||
devise_for :admins
|
||||
|
||||
# Inside your protected controller
|
||||
before_filter :authenticate_admin!
|
||||
|
||||
# Inside your controllers and views
|
||||
admin_signed_in?
|
||||
current_admin
|
||||
admin_session
|
||||
```
|
||||
|
||||
On the other hand, you can simply run the generator!
|
||||
To completely change Devise defaults or invoke custom behaviour, you can also pass a block:
|
||||
|
||||
```ruby
|
||||
def configure_permitted_parameters
|
||||
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username, :email) }
|
||||
end
|
||||
```
|
||||
|
||||
If you have multiple Devise models, you may want to set up different parameter sanitizer per model. In this case, we recommend inheriting from `Devise::ParameterSanitizer` and add your own logic:
|
||||
|
||||
```ruby
|
||||
class User::ParameterSanitizer < Devise::ParameterSanitizer
|
||||
def sign_in
|
||||
default_params.permit(:username, :email)
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
And then configure your controllers to use it:
|
||||
|
||||
```ruby
|
||||
class ApplicationController < ActionController::Base
|
||||
protected
|
||||
|
||||
def devise_parameter_sanitizer
|
||||
if resource_class == User
|
||||
User::ParameterSanitizer.new(User, :user, params)
|
||||
else
|
||||
super # Use the default one
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
The example above overrides the permitted parameters for the user to be both `:username` and `:email`. The non-lazy way to configure parameters would be by defining the before filter above in a custom controller. We detail how to configure and customize controllers in some sections below.
|
||||
|
||||
### Configuring views
|
||||
|
||||
@@ -215,7 +246,7 @@ Since Devise is an engine, all its views are packaged inside the gem. These view
|
||||
rails generate devise:views
|
||||
```
|
||||
|
||||
If you have more than one role in your application (such as "User" and "Admin"), you will notice that Devise uses the same views for all roles. Fortunately, Devise offers an easy way to customize views. All you need to do is set "config.scoped_views = true" inside "config/initializers/devise.rb".
|
||||
If you have more than one Devise model in your application (such as "User" and "Admin"), you will notice that Devise uses the same views for all models. Fortunately, Devise offers an easy way to customize views. All you need to do is set "config.scoped_views = true" inside "config/initializers/devise.rb".
|
||||
|
||||
After doing so, you will be able to have views based on the role like "users/sessions/new" and "admins/sessions/new". If no view is found within the scope, Devise will use the default view at "devise/sessions/new". You can also use the generator to generate scoped views:
|
||||
|
||||
@@ -227,29 +258,31 @@ rails generate devise:views users
|
||||
|
||||
If the customization at the views level is not enough, you can customize each controller by following these steps:
|
||||
|
||||
1) Create your custom controller, for example a Admins::SessionsController:
|
||||
1. Create your custom controller, for example a `Admins::SessionsController`:
|
||||
|
||||
```ruby
|
||||
class Admins::SessionsController < Devise::SessionsController
|
||||
end
|
||||
```
|
||||
```ruby
|
||||
class Admins::SessionsController < Devise::SessionsController
|
||||
end
|
||||
```
|
||||
|
||||
2) Tell the router to use this controller:
|
||||
Note that in the above example, the controller needs to be created in the `app/controller/admins/` directory.
|
||||
|
||||
```ruby
|
||||
devise_for :admins, :controllers => { :sessions => "admins/sessions" }
|
||||
```
|
||||
2. Tell the router to use this controller:
|
||||
|
||||
3) And since we changed the controller, it won't use the "devise/sessions" views, so remember to copy "devise/sessions" to "admin/sessions".
|
||||
```ruby
|
||||
devise_for :admins, :controllers => { :sessions => "admins/sessions" }
|
||||
```
|
||||
|
||||
Remember that Devise uses flash messages to let users know if sign in was successful or failed. Devise expects your application to call "flash[:notice]" and "flash[:alert]" as appropriate.
|
||||
3. And since we changed the controller, it won't use the `"devise/sessions"` views, so remember to copy `"devise/sessions"` to `"admin/sessions"`.
|
||||
|
||||
Remember that Devise uses flash messages to let users know if sign in was successful or failed. Devise expects your application to call `"flash[:notice]"` and `"flash[:alert]"` as appropriate. Do not print the entire flash hash, print specific keys or at least remove the `:timedout` key from the hash as Devise adds this key in some circumstances, this key is not meant for display.
|
||||
|
||||
### Configuring routes
|
||||
|
||||
Devise also ships with default routes. If you need to customize them, you should probably be able to do it through the devise_for method. It accepts several options like :class_name, :path_prefix and so on, including the possibility to change path names for I18n:
|
||||
|
||||
```ruby
|
||||
devise_for :users, :path => "usuarios", :path_names => { :sign_in => 'login', :sign_out => 'logout', :password => 'secret', :confirmation => 'verification', :unlock => 'unblock', :registration => 'register', :sign_up => 'cmon_let_me_in' }
|
||||
devise_for :users, :path => "auth", :path_names => { :sign_in => 'login', :sign_out => 'logout', :password => 'secret', :confirmation => 'verification', :unlock => 'unblock', :registration => 'register', :sign_up => 'cmon_let_me_in' }
|
||||
```
|
||||
|
||||
Be sure to check `devise_for` documentation for details.
|
||||
@@ -306,7 +339,23 @@ https://github.com/plataformatec/devise/wiki/I18n
|
||||
|
||||
### Test helpers
|
||||
|
||||
Devise includes some tests helpers for functional specs. To use them, you just need to include Devise::TestHelpers in your test class and use the sign_in and sign_out method. Such methods have the same signature as in controllers:
|
||||
Devise includes some tests helpers for functional specs. In order to use them, you need to include Devise in your functional tests by adding the following to the bottom of your `test/test_helper.rb` file:
|
||||
|
||||
```ruby
|
||||
class ActionController::TestCase
|
||||
include Devise::TestHelpers
|
||||
end
|
||||
```
|
||||
|
||||
If you're using RSpec, you can put the following inside a file named `spec/support/devise.rb`:
|
||||
|
||||
```ruby
|
||||
RSpec.configure do |config|
|
||||
config.include Devise::TestHelpers, :type => :controller
|
||||
end
|
||||
```
|
||||
|
||||
Now you are ready to use the `sign_in` and `sign_out` methods. Such methods have the same signature as in controllers:
|
||||
|
||||
```ruby
|
||||
sign_in :user, @user # sign_in(scope, resource)
|
||||
@@ -316,39 +365,65 @@ sign_out :user # sign_out(scope)
|
||||
sign_out @user # sign_out(resource)
|
||||
```
|
||||
|
||||
You can include the Devise Test Helpers in all of your tests by adding the following to the bottom of your test/test_helper.rb file:
|
||||
There are two things that is important to keep in mind:
|
||||
|
||||
```ruby
|
||||
class ActionController::TestCase
|
||||
include Devise::TestHelpers
|
||||
end
|
||||
```
|
||||
1. These helpers are not going to work for integration tests driven by Capybara or Webrat. They are meant to be used with functional tests only. Instead, fill in the form or explicitly set the user in session;
|
||||
|
||||
If you're using RSpec and want the helpers automatically included within all `describe` blocks, add a file called spec/support/devise.rb with the following contents:
|
||||
2. If you are testing Devise internal controllers or a controller that inherits from Devise's, you need to tell Devise which mapping should be used before a request. This is necessary because Devise gets this information from router, but since functional tests do not pass through the router, it needs to be told explicitly. For example, if you are testing the user scope, simply do:
|
||||
|
||||
```ruby
|
||||
RSpec.configure do |config|
|
||||
config.include Devise::TestHelpers, :type => :controller
|
||||
end
|
||||
```
|
||||
|
||||
Do not use such helpers for integration tests such as Cucumber or Webrat. Instead, fill in the form or explicitly set the user in session. For more tips, check the wiki (https://wiki.github.com/plataformatec/devise).
|
||||
```ruby
|
||||
@request.env["devise.mapping"] = Devise.mappings[:user]
|
||||
get :new
|
||||
```
|
||||
|
||||
### Omniauth
|
||||
|
||||
Devise comes with Omniauth support out of the box to authenticate from other providers. You can read more about Omniauth support in the wiki:
|
||||
Devise comes with Omniauth support out of the box to authenticate with other providers. To use it, just specify your omniauth configuration in `config/initializers/devise.rb`:
|
||||
|
||||
```ruby
|
||||
config.omniauth :github, 'APP_ID', 'APP_SECRET', :scope => 'user,public_repo'
|
||||
```
|
||||
|
||||
You can read more about Omniauth support in the wiki:
|
||||
|
||||
* https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
|
||||
|
||||
### Configuring multiple models
|
||||
|
||||
Devise allows you to set up as many Devise models as you want. If you want to have an Admin model with just authentication and timeout features, in addition to the User model above, just run:
|
||||
|
||||
```ruby
|
||||
# Create a migration with the required fields
|
||||
create_table :admins do |t|
|
||||
t.string :email
|
||||
t.string :encrypted_password
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
# Inside your Admin model
|
||||
devise :database_authenticatable, :timeoutable
|
||||
|
||||
# Inside your routes
|
||||
devise_for :admins
|
||||
|
||||
# Inside your protected controller
|
||||
before_filter :authenticate_admin!
|
||||
|
||||
# Inside your controllers and views
|
||||
admin_signed_in?
|
||||
current_admin
|
||||
admin_session
|
||||
```
|
||||
|
||||
Alternatively, you can simply run the Devise generator.
|
||||
|
||||
Keep in mind that those models will have completely different routes. They **do not** and **cannot** share the same controller for sign in, sign out and so on. In case you want to have different roles sharing the same actions, we recommend you to use a role-based approach, by either providing a role column or using [CanCan](https://github.com/ryanb/cancan).
|
||||
|
||||
### Other ORMs
|
||||
|
||||
Devise supports ActiveRecord (default) and Mongoid. To choose other ORM, you just need to require it in the initializer file.
|
||||
|
||||
### Migrating from other solutions
|
||||
|
||||
Devise implements encryption strategies for Clearance, Authlogic and Restful-Authentication. To make use of these strategies, you need set the desired encryptor in the encryptor initializer config option and add :encryptable to your model. You might also need to rename your encrypted password and salt columns to match Devise's fields (encrypted_password and password_salt).
|
||||
|
||||
## Troubleshooting
|
||||
## Additional information
|
||||
|
||||
### Heroku
|
||||
|
||||
@@ -360,8 +435,6 @@ config.assets.initialize_on_precompile = false
|
||||
|
||||
Read more about the potential issues at http://guides.rubyonrails.org/asset_pipeline.html
|
||||
|
||||
## Additional information
|
||||
|
||||
### Warden
|
||||
|
||||
Devise is based on Warden, which is a general Rack authentication framework created by Daniel Neighman. We encourage you to read more about Warden here:
|
||||
@@ -374,12 +447,8 @@ We have a long list of valued contributors. Check them all at:
|
||||
|
||||
https://github.com/plataformatec/devise/contributors
|
||||
|
||||
### Maintainers
|
||||
|
||||
* José Valim (https://github.com/josevalim)
|
||||
* Carlos Antônio da Silva (https://github.com/carlosantoniodasilva)
|
||||
* Rodrigo Flores (https://github.com/rodrigoflores)
|
||||
|
||||
## License
|
||||
|
||||
MIT License. Copyright 2012 Plataformatec. http://plataformatec.com.br
|
||||
MIT License. Copyright 2009-2013 Plataformatec. http://plataformatec.com.br
|
||||
|
||||
You are not granted rights or licenses to the trademarks of the Plataformatec, including without limitation the Devise name or logo.
|
||||
|
||||
3
Rakefile
3
Rakefile
@@ -22,6 +22,7 @@ Rake::TestTask.new(:test) do |t|
|
||||
t.libs << 'test'
|
||||
t.pattern = 'test/**/*_test.rb'
|
||||
t.verbose = true
|
||||
t.warning = false
|
||||
end
|
||||
|
||||
desc 'Generate documentation for Devise.'
|
||||
@@ -29,6 +30,6 @@ Rake::RDocTask.new(:rdoc) do |rdoc|
|
||||
rdoc.rdoc_dir = 'rdoc'
|
||||
rdoc.title = 'Devise'
|
||||
rdoc.options << '--line-numbers' << '--inline-source'
|
||||
rdoc.rdoc_files.include('README.rdoc')
|
||||
rdoc.rdoc_files.include('README.md')
|
||||
rdoc.rdoc_files.include('lib/**/*.rb')
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
class Devise::ConfirmationsController < DeviseController
|
||||
# GET /resource/confirmation/new
|
||||
def new
|
||||
build_resource({})
|
||||
self.resource = resource_class.new
|
||||
end
|
||||
|
||||
# POST /resource/confirmation
|
||||
@@ -20,8 +20,12 @@ class Devise::ConfirmationsController < DeviseController
|
||||
self.resource = resource_class.confirm_by_token(params[:confirmation_token])
|
||||
|
||||
if resource.errors.empty?
|
||||
set_flash_message(:notice, :confirmed) if is_navigational_format?
|
||||
sign_in(resource_name, resource)
|
||||
if Devise.allow_insecure_sign_in_after_confirmation
|
||||
set_flash_message(:notice, :confirmed_and_signed_in) if is_navigational_format?
|
||||
sign_in(resource_name, resource)
|
||||
else
|
||||
set_flash_message(:notice, :confirmed) if is_navigational_format?
|
||||
end
|
||||
respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource) }
|
||||
else
|
||||
respond_with_navigational(resource.errors, :status => :unprocessable_entity){ render :new }
|
||||
@@ -32,12 +36,17 @@ class Devise::ConfirmationsController < DeviseController
|
||||
|
||||
# The path used after resending confirmation instructions.
|
||||
def after_resending_confirmation_instructions_path_for(resource_name)
|
||||
new_session_path(resource_name)
|
||||
new_session_path(resource_name) if is_navigational_format?
|
||||
end
|
||||
|
||||
# The path used after confirmation.
|
||||
def after_confirmation_path_for(resource_name, resource)
|
||||
after_sign_in_path_for(resource)
|
||||
if Devise.allow_insecure_sign_in_after_confirmation
|
||||
after_sign_in_path_for(resource)
|
||||
elsif signed_in?
|
||||
signed_in_root_path(resource)
|
||||
else
|
||||
new_session_path(resource_name)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
class Devise::OmniauthCallbacksController < DeviseController
|
||||
prepend_before_filter { request.env["devise.skip_timeout"] = true }
|
||||
|
||||
def passthru
|
||||
render :status => 404, :text => "Not found. Authentication passthru."
|
||||
end
|
||||
|
||||
def failure
|
||||
set_flash_message :alert, :failure, :kind => failed_strategy.name.to_s.humanize, :reason => failure_message
|
||||
set_flash_message :alert, :failure, :kind => OmniAuth::Utils.camelize(failed_strategy.name), :reason => failure_message
|
||||
redirect_to after_omniauth_failure_path_for(resource_name)
|
||||
end
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
class Devise::PasswordsController < DeviseController
|
||||
prepend_before_filter :require_no_authentication
|
||||
# Render the #edit only if coming from a reset password email link
|
||||
append_before_filter :assert_reset_token_passed, :only => :edit
|
||||
|
||||
# GET /resource/password/new
|
||||
def new
|
||||
build_resource({})
|
||||
self.resource = resource_class.new
|
||||
end
|
||||
|
||||
# POST /resource/password
|
||||
@@ -28,20 +30,39 @@ class Devise::PasswordsController < DeviseController
|
||||
self.resource = resource_class.reset_password_by_token(resource_params)
|
||||
|
||||
if resource.errors.empty?
|
||||
resource.unlock_access! if unlockable?(resource)
|
||||
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 => after_sign_in_path_for(resource)
|
||||
respond_with resource, :location => after_resetting_password_path_for(resource)
|
||||
else
|
||||
respond_with resource
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
def after_resetting_password_path_for(resource)
|
||||
after_sign_in_path_for(resource)
|
||||
end
|
||||
|
||||
# The path used after sending reset password instructions
|
||||
def after_sending_reset_password_instructions_path_for(resource_name)
|
||||
new_session_path(resource_name)
|
||||
new_session_path(resource_name) if is_navigational_format?
|
||||
end
|
||||
|
||||
# Check if a reset_password_token is provided in the request
|
||||
def assert_reset_token_passed
|
||||
if params[:reset_password_token].blank?
|
||||
set_flash_message(:alert, :no_token)
|
||||
redirect_to new_session_path(resource_name)
|
||||
end
|
||||
end
|
||||
|
||||
# Check if proper Lockable module methods are present & unlock strategy
|
||||
# allows to unlock resource on password reset
|
||||
def unlockable?(resource)
|
||||
resource.respond_to?(:unlock_access!) &&
|
||||
resource.respond_to?(:unlock_strategy_enabled?) &&
|
||||
resource.unlock_strategy_enabled?(:email)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,18 +4,18 @@ class Devise::RegistrationsController < DeviseController
|
||||
|
||||
# GET /resource/sign_up
|
||||
def new
|
||||
resource = build_resource({})
|
||||
respond_with resource
|
||||
build_resource({})
|
||||
respond_with self.resource
|
||||
end
|
||||
|
||||
# POST /resource
|
||||
def create
|
||||
build_resource
|
||||
build_resource(sign_up_params)
|
||||
|
||||
if resource.save
|
||||
if resource.active_for_authentication?
|
||||
set_flash_message :notice, :signed_up if is_navigational_format?
|
||||
sign_in(resource_name, resource)
|
||||
sign_up(resource_name, resource)
|
||||
respond_with resource, :location => after_sign_up_path_for(resource)
|
||||
else
|
||||
set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format?
|
||||
@@ -38,13 +38,13 @@ class Devise::RegistrationsController < DeviseController
|
||||
# the current user in place.
|
||||
def update
|
||||
self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
|
||||
prev_unconfirmed_email = resource.unconfirmed_email if resource.respond_to?(:unconfirmed_email)
|
||||
|
||||
if resource.update_with_password(resource_params)
|
||||
if update_resource(resource, account_update_params)
|
||||
if is_navigational_format?
|
||||
if resource.respond_to?(:pending_reconfirmation?) && resource.pending_reconfirmation?
|
||||
flash_key = :update_needs_confirmation
|
||||
end
|
||||
set_flash_message :notice, flash_key || :updated
|
||||
flash_key = update_needs_confirmation?(resource, prev_unconfirmed_email) ?
|
||||
:update_needs_confirmation : :updated
|
||||
set_flash_message :notice, flash_key
|
||||
end
|
||||
sign_in resource_name, resource, :bypass => true
|
||||
respond_with resource, :location => after_update_path_for(resource)
|
||||
@@ -74,11 +74,28 @@ class Devise::RegistrationsController < DeviseController
|
||||
|
||||
protected
|
||||
|
||||
def update_needs_confirmation?(resource, previous)
|
||||
resource.respond_to?(:pending_reconfirmation?) &&
|
||||
resource.pending_reconfirmation? &&
|
||||
previous != resource.unconfirmed_email
|
||||
end
|
||||
|
||||
# By default we want to require a password checks on update.
|
||||
# You can overwrite this method in your own RegistrationsController.
|
||||
def update_resource(resource, params)
|
||||
resource.update_with_password(params)
|
||||
end
|
||||
|
||||
# Build a devise resource passing in the session. Useful to move
|
||||
# temporary session data to the newly created user.
|
||||
def build_resource(hash=nil)
|
||||
hash ||= resource_params || {}
|
||||
self.resource = resource_class.new_with_session(hash, session)
|
||||
self.resource = resource_class.new_with_session(hash || {}, session)
|
||||
end
|
||||
|
||||
# Signs in a user on sign up. You can overwrite this method in your own
|
||||
# RegistrationsController.
|
||||
def sign_up(resource_name, resource)
|
||||
sign_in(resource_name, resource)
|
||||
end
|
||||
|
||||
# The path used after sign up. You need to overwrite this method
|
||||
@@ -104,4 +121,12 @@ class Devise::RegistrationsController < DeviseController
|
||||
send(:"authenticate_#{resource_name}!", :force => true)
|
||||
self.resource = send(:"current_#{resource_name}")
|
||||
end
|
||||
|
||||
def sign_up_params
|
||||
devise_parameter_sanitizer.sanitize(:sign_up)
|
||||
end
|
||||
|
||||
def account_update_params
|
||||
devise_parameter_sanitizer.sanitize(:account_update)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
class Devise::SessionsController < DeviseController
|
||||
prepend_before_filter :require_no_authentication, :only => [ :new, :create ]
|
||||
prepend_before_filter :allow_params_authentication!, :only => :create
|
||||
prepend_before_filter { request.env["devise.skip_timeout"] = true }
|
||||
|
||||
# GET /resource/sign_in
|
||||
def new
|
||||
resource = build_resource(nil, :unsafe => true)
|
||||
self.resource = resource_class.new(sign_in_params)
|
||||
clean_up_passwords(resource)
|
||||
respond_with(resource, serialize_options(resource))
|
||||
end
|
||||
|
||||
# POST /resource/sign_in
|
||||
def create
|
||||
resource = warden.authenticate!(auth_options)
|
||||
self.resource = warden.authenticate!(auth_options)
|
||||
set_flash_message(:notice, :signed_in) if is_navigational_format?
|
||||
sign_in(resource_name, resource)
|
||||
respond_with resource, :location => after_sign_in_path_for(resource)
|
||||
@@ -21,20 +22,22 @@ class Devise::SessionsController < DeviseController
|
||||
def destroy
|
||||
redirect_path = after_sign_out_path_for(resource_name)
|
||||
signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
|
||||
set_flash_message :notice, :signed_out if signed_out
|
||||
set_flash_message :notice, :signed_out if signed_out && is_navigational_format?
|
||||
|
||||
# We actually need to hardcode this as Rails default responder doesn't
|
||||
# support returning empty response on GET request
|
||||
respond_to do |format|
|
||||
format.all { head :no_content }
|
||||
format.any(*navigational_formats) { redirect_to redirect_path }
|
||||
format.all do
|
||||
head :no_content
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def sign_in_params
|
||||
devise_parameter_sanitizer.sanitize(:sign_in)
|
||||
end
|
||||
|
||||
def serialize_options(resource)
|
||||
methods = resource_class.authentication_keys.dup
|
||||
methods = methods.keys if methods.is_a?(Hash)
|
||||
@@ -46,4 +49,3 @@ class Devise::SessionsController < DeviseController
|
||||
{ :scope => resource_name, :recall => "#{controller_path}#new" }
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ class Devise::UnlocksController < DeviseController
|
||||
|
||||
# GET /resource/unlock/new
|
||||
def new
|
||||
build_resource({})
|
||||
self.resource = resource_class.new
|
||||
end
|
||||
|
||||
# POST /resource/unlock
|
||||
@@ -33,12 +33,12 @@ class Devise::UnlocksController < DeviseController
|
||||
|
||||
# The path used after sending unlock password instructions
|
||||
def after_sending_unlock_instructions_path_for(resource)
|
||||
new_session_path(resource)
|
||||
new_session_path(resource) if is_navigational_format?
|
||||
end
|
||||
|
||||
# The path used after unlocking the resource
|
||||
def after_unlock_path_for(resource)
|
||||
new_session_path(resource)
|
||||
new_session_path(resource) if is_navigational_format?
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -10,7 +10,7 @@ class DeviseController < Devise.parent_controller.constantize
|
||||
helper_method *helpers
|
||||
|
||||
prepend_before_filter :assert_is_devise_resource!
|
||||
respond_to *Mime::SET.map(&:to_sym) if mimes_for_respond_to.empty?
|
||||
respond_to :html if mimes_for_respond_to.empty?
|
||||
|
||||
# Gets the actual resource stored in the instance variable
|
||||
def resource
|
||||
@@ -28,10 +28,6 @@ class DeviseController < Devise.parent_controller.constantize
|
||||
devise_mapping.to
|
||||
end
|
||||
|
||||
def resource_params
|
||||
params[resource_name]
|
||||
end
|
||||
|
||||
# Returns a signed in resource from session (if one exists)
|
||||
def signed_in_resource
|
||||
warden.authenticate(:scope => resource_name)
|
||||
@@ -43,8 +39,11 @@ class DeviseController < Devise.parent_controller.constantize
|
||||
end
|
||||
|
||||
# Override prefixes to consider the scoped view.
|
||||
# Notice we need to check for the request due to a bug in
|
||||
# Action Controller tests that forces _prefixes to be
|
||||
# loaded before even having a request object.
|
||||
def _prefixes #:nodoc:
|
||||
@_prefixes ||= if self.class.scoped_views? && devise_mapping
|
||||
@_prefixes ||= if self.class.scoped_views? && request && devise_mapping
|
||||
super.unshift("#{devise_mapping.scoped_path}/#{controller_name}")
|
||||
else
|
||||
super
|
||||
@@ -59,11 +58,19 @@ class DeviseController < Devise.parent_controller.constantize
|
||||
def assert_is_devise_resource! #:nodoc:
|
||||
unknown_action! <<-MESSAGE unless devise_mapping
|
||||
Could not find devise mapping for path #{request.fullpath.inspect}.
|
||||
Maybe you forgot to wrap your route inside the scope block? For example:
|
||||
This may happen for two reasons:
|
||||
|
||||
1) You forgot to wrap your route inside the scope block. For example:
|
||||
|
||||
devise_scope :user do
|
||||
get "/some/route" => "some_devise_controller"
|
||||
end
|
||||
|
||||
2) You are testing a Devise controller bypassing the router.
|
||||
If so, you can explicitly tell Devise which mapping to use:
|
||||
|
||||
@request.env["devise.mapping"] = Devise.mappings[:user]
|
||||
|
||||
devise_scope :user do
|
||||
match "/some/route" => "some_devise_controller"
|
||||
end
|
||||
MESSAGE
|
||||
end
|
||||
|
||||
@@ -82,23 +89,6 @@ MESSAGE
|
||||
instance_variable_set(:"@#{resource_name}", new_resource)
|
||||
end
|
||||
|
||||
# Build a devise resource.
|
||||
# Assignment bypasses attribute protection when :unsafe option is passed
|
||||
def build_resource(hash = nil, options = {})
|
||||
hash ||= resource_params || {}
|
||||
|
||||
if options[:unsafe]
|
||||
self.resource = resource_class.new.tap do |resource|
|
||||
hash.each do |key, value|
|
||||
setter = :"#{key}="
|
||||
resource.send(setter, value) if resource.respond_to?(setter)
|
||||
end
|
||||
end
|
||||
else
|
||||
self.resource = resource_class.new(hash)
|
||||
end
|
||||
end
|
||||
|
||||
# Helper for use in before_filters where no authentication is required.
|
||||
#
|
||||
# Example:
|
||||
@@ -152,13 +142,18 @@ MESSAGE
|
||||
#
|
||||
# Please refer to README or en.yml locale file to check what messages are
|
||||
# available.
|
||||
def set_flash_message(key, kind, options={})
|
||||
def set_flash_message(key, kind, options = {})
|
||||
message = find_message(kind, options)
|
||||
flash[key] = message if message.present?
|
||||
end
|
||||
|
||||
# Get message for given
|
||||
def find_message(kind, options = {})
|
||||
options[:scope] = "devise.#{controller_name}"
|
||||
options[:default] = Array(options[:default]).unshift(kind.to_sym)
|
||||
options[:resource_name] = resource_name
|
||||
options = devise_i18n_options(options) if respond_to?(:devise_i18n_options, true)
|
||||
message = I18n.t("#{resource_name}.#{kind}", options)
|
||||
flash[key] = message if message.present?
|
||||
I18n.t("#{options[:resource_name]}.#{kind}", options)
|
||||
end
|
||||
|
||||
def clean_up_passwords(object)
|
||||
@@ -171,11 +166,7 @@ MESSAGE
|
||||
end
|
||||
end
|
||||
|
||||
def request_format
|
||||
@request_format ||= request.format.try(:ref)
|
||||
end
|
||||
|
||||
def is_navigational_format?
|
||||
Devise.navigational_formats.include?(request.format.try(:ref))
|
||||
def resource_params
|
||||
params.fetch(resource_name, {})
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
class Devise::Mailer < ::ActionMailer::Base
|
||||
class Devise::Mailer < Devise.parent_mailer.constantize
|
||||
include Devise::Mailers::Helpers
|
||||
|
||||
def confirmation_instructions(record)
|
||||
devise_mail(record, :confirmation_instructions)
|
||||
def confirmation_instructions(record, token, opts={})
|
||||
@token = token
|
||||
devise_mail(record, :confirmation_instructions, opts)
|
||||
end
|
||||
|
||||
def reset_password_instructions(record)
|
||||
devise_mail(record, :reset_password_instructions)
|
||||
def reset_password_instructions(record, token, opts={})
|
||||
@token = token
|
||||
devise_mail(record, :reset_password_instructions, opts)
|
||||
end
|
||||
|
||||
def unlock_instructions(record)
|
||||
devise_mail(record, :unlock_instructions)
|
||||
def unlock_instructions(record, token, opts={})
|
||||
@token = token
|
||||
devise_mail(record, :unlock_instructions, opts)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
<% ActiveSupport::Deprecation.warn "Rendering partials devise/_links.erb is deprecated" \
|
||||
"please use devise/shared/_links.erb instead."%>
|
||||
<%= render "shared/links" %>
|
||||
@@ -4,9 +4,9 @@
|
||||
<%= devise_error_messages! %>
|
||||
|
||||
<div><%= f.label :email %><br />
|
||||
<%= f.email_field :email %></div>
|
||||
<%= f.email_field :email, :autofocus => true %></div>
|
||||
|
||||
<div><%= f.submit "Resend confirmation instructions" %></div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
<%= render "devise/shared/links" %>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<p>Welcome <%= @resource.email %>!</p>
|
||||
<p>Welcome <%= @email %>!</p>
|
||||
|
||||
<p>You can confirm your account email through the link below:</p>
|
||||
|
||||
<p><%= link_to 'Confirm my account', confirmation_url(@resource, :confirmation_token => @resource.confirmation_token) %></p>
|
||||
<p><%= link_to 'Confirm my account', confirmation_url(@resource, :confirmation_token => @token) %></p>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<p>Hello <%= @resource.email %>!</p>
|
||||
|
||||
<p>Someone has requested a link to change your password, and you can do this through the link below.</p>
|
||||
<p>Someone has requested a link to change your password. You can do this through the link below.</p>
|
||||
|
||||
<p><%= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @resource.reset_password_token) %></p>
|
||||
<p><%= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @token) %></p>
|
||||
|
||||
<p>If you didn't request this, please ignore this email.</p>
|
||||
<p>Your password won't change until you access the link above and create a new one.</p>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<p>Hello <%= @resource.email %>!</p>
|
||||
|
||||
<p>Your account has been locked due to an excessive amount of unsuccessful sign in attempts.</p>
|
||||
<p>Your account has been locked due to an excessive number of unsuccessful sign in attempts.</p>
|
||||
|
||||
<p>Click the link below to unlock your account:</p>
|
||||
|
||||
<p><%= link_to 'Unlock my account', unlock_url(@resource, :unlock_token => @resource.unlock_token) %></p>
|
||||
<p><%= link_to 'Unlock my account', unlock_url(@resource, :unlock_token => @token) %></p>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<%= f.hidden_field :reset_password_token %>
|
||||
|
||||
<div><%= f.label :password, "New password" %><br />
|
||||
<%= f.password_field :password %></div>
|
||||
<%= f.password_field :password, :autofocus => true %></div>
|
||||
|
||||
<div><%= f.label :password_confirmation, "Confirm new password" %><br />
|
||||
<%= f.password_field :password_confirmation %></div>
|
||||
@@ -13,4 +13,4 @@
|
||||
<div><%= f.submit "Change my password" %></div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
<%= render "devise/shared/links" %>
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
<%= devise_error_messages! %>
|
||||
|
||||
<div><%= f.label :email %><br />
|
||||
<%= f.email_field :email %></div>
|
||||
<%= f.email_field :email, :autofocus => true %></div>
|
||||
|
||||
<div><%= f.submit "Send me reset password instructions" %></div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
<%= render "devise/shared/links" %>
|
||||
|
||||
@@ -4,7 +4,11 @@
|
||||
<%= devise_error_messages! %>
|
||||
|
||||
<div><%= f.label :email %><br />
|
||||
<%= f.email_field :email %></div>
|
||||
<%= f.email_field :email, :autofocus => true %></div>
|
||||
|
||||
<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
|
||||
<div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
|
||||
<% end %>
|
||||
|
||||
<div><%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
|
||||
<%= f.password_field :password, :autocomplete => "off" %></div>
|
||||
@@ -20,6 +24,6 @@
|
||||
|
||||
<h3>Cancel my account</h3>
|
||||
|
||||
<p>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), :confirm => "Are you sure?", :method => :delete %>.</p>
|
||||
<p>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), :data => { :confirm => "Are you sure?" }, :method => :delete %></p>
|
||||
|
||||
<%= link_to "Back", :back %>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<%= devise_error_messages! %>
|
||||
|
||||
<div><%= f.label :email %><br />
|
||||
<%= f.email_field :email %></div>
|
||||
<%= f.email_field :email, :autofocus => true %></div>
|
||||
|
||||
<div><%= f.label :password %><br />
|
||||
<%= f.password_field :password %></div>
|
||||
@@ -15,4 +15,4 @@
|
||||
<div><%= f.submit "Sign up" %></div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
<%= render "devise/shared/links" %>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
|
||||
<div><%= f.label :email %><br />
|
||||
<%= f.email_field :email %></div>
|
||||
<%= f.email_field :email, :autofocus => true %></div>
|
||||
|
||||
<div><%= f.label :password %><br />
|
||||
<%= f.password_field :password %></div>
|
||||
@@ -14,4 +14,4 @@
|
||||
<div><%= f.submit "Sign in" %></div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
<%= render "devise/shared/links" %>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<%= link_to "Sign up", new_registration_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.recoverable? && controller_name != 'passwords' %>
|
||||
<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
|
||||
<%= link_to "Forgot your password?", new_password_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
@@ -22,4 +22,4 @@
|
||||
<%- resource_class.omniauth_providers.each do |provider| %>
|
||||
<%= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider) %><br />
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
<%= devise_error_messages! %>
|
||||
|
||||
<div><%= f.label :email %><br />
|
||||
<%= f.email_field :email %></div>
|
||||
<%= f.email_field :email, :autofocus => true %></div>
|
||||
|
||||
<div><%= f.submit "Resend unlock instructions" %></div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
<%= render "devise/shared/links" %>
|
||||
|
||||
@@ -1,57 +1,60 @@
|
||||
# Additional translations at https://github.com/plataformatec/devise/wiki/I18n
|
||||
|
||||
en:
|
||||
devise:
|
||||
confirmations:
|
||||
confirmed: "Your account was successfully confirmed."
|
||||
confirmed_and_signed_in: "Your account was successfully confirmed. You are now signed in."
|
||||
send_instructions: "You will receive an email with instructions about how to confirm your account in a few minutes."
|
||||
send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions about how to confirm your account in a few minutes."
|
||||
failure:
|
||||
already_authenticated: "You are already signed in."
|
||||
inactive: "Your account is not activated yet."
|
||||
invalid: "Invalid email or password."
|
||||
invalid_token: "Invalid authentication token."
|
||||
locked: "Your account is locked."
|
||||
not_found_in_database: "Invalid email or password."
|
||||
timeout: "Your session expired. Please sign in again to continue."
|
||||
unauthenticated: "You need to sign in or sign up before continuing."
|
||||
unconfirmed: "You have to confirm your account before continuing."
|
||||
mailer:
|
||||
confirmation_instructions:
|
||||
subject: "Confirmation instructions"
|
||||
reset_password_instructions:
|
||||
subject: "Reset password instructions"
|
||||
unlock_instructions:
|
||||
subject: "Unlock Instructions"
|
||||
omniauth_callbacks:
|
||||
failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
|
||||
success: "Successfully authenticated from %{kind} account."
|
||||
passwords:
|
||||
no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
|
||||
send_instructions: "You will receive an email with instructions about how to reset your password in a few minutes."
|
||||
send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
|
||||
updated: "Your password was changed successfully. You are now signed in."
|
||||
updated_not_active: "Your password was changed successfully."
|
||||
registrations:
|
||||
destroyed: "Bye! Your account was successfully cancelled. We hope to see you again soon."
|
||||
signed_up: "Welcome! You have signed up successfully."
|
||||
signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
|
||||
signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
|
||||
signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please open the link to activate your account."
|
||||
update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and click on the confirm link to finalize confirming your new email address."
|
||||
updated: "You updated your account successfully."
|
||||
sessions:
|
||||
signed_in: "Signed in successfully."
|
||||
signed_out: "Signed out successfully."
|
||||
unlocks:
|
||||
send_instructions: "You will receive an email with instructions about how to unlock your account in a few minutes."
|
||||
send_paranoid_instructions: "If your account exists, you will receive an email with instructions about how to unlock it in a few minutes."
|
||||
unlocked: "Your account has been unlocked successfully. Please sign in to continue."
|
||||
errors:
|
||||
messages:
|
||||
already_confirmed: "was already confirmed, please try signing in"
|
||||
confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
|
||||
expired: "has expired, please request a new one"
|
||||
not_found: "not found"
|
||||
already_confirmed: "was already confirmed, please try signing in"
|
||||
not_locked: "was not locked"
|
||||
not_saved:
|
||||
one: "1 error prohibited this %{resource} from being saved:"
|
||||
other: "%{count} errors prohibited this %{resource} from being saved:"
|
||||
|
||||
devise:
|
||||
failure:
|
||||
already_authenticated: 'You are already signed in.'
|
||||
unauthenticated: 'You need to sign in or sign up before continuing.'
|
||||
unconfirmed: 'You have to confirm your account before continuing.'
|
||||
locked: 'Your account is locked.'
|
||||
invalid: 'Invalid email or password.'
|
||||
invalid_token: 'Invalid authentication token.'
|
||||
timeout: 'Your session expired, please sign in again to continue.'
|
||||
inactive: 'Your account was not activated yet.'
|
||||
sessions:
|
||||
signed_in: 'Signed in successfully.'
|
||||
signed_out: 'Signed out successfully.'
|
||||
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 email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
|
||||
confirmations:
|
||||
send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.'
|
||||
send_paranoid_instructions: 'If your email address exists in our database, you will receive an email with instructions about how to confirm your account in a few minutes.'
|
||||
confirmed: 'Your account was successfully confirmed. You are now signed in.'
|
||||
registrations:
|
||||
signed_up: 'Welcome! You have signed up successfully.'
|
||||
signed_up_but_unconfirmed: 'A message with a confirmation link has been sent to your email address. Please open the link to activate your account.'
|
||||
signed_up_but_inactive: 'You have signed up successfully. However, we could not sign you in because your account is not yet activated.'
|
||||
signed_up_but_locked: 'You have signed up successfully. However, we could not sign you in because your account is locked.'
|
||||
updated: 'You updated your account successfully.'
|
||||
update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and click on the confirm link to finalize confirming your new email address."
|
||||
destroyed: 'Bye! Your account was successfully cancelled. We hope to see you again soon.'
|
||||
unlocks:
|
||||
send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.'
|
||||
unlocked: 'Your account has been unlocked successfully. Please sign in to continue.'
|
||||
send_paranoid_instructions: 'If your account exists, you will receive an email with instructions about how to unlock it in a few minutes.'
|
||||
omniauth_callbacks:
|
||||
success: 'Successfully authenticated from %{kind} account.'
|
||||
failure: 'Could not authenticate you from %{kind} because "%{reason}".'
|
||||
mailer:
|
||||
confirmation_instructions:
|
||||
subject: 'Confirmation instructions'
|
||||
reset_password_instructions:
|
||||
subject: 'Reset password instructions'
|
||||
unlock_instructions:
|
||||
subject: 'Unlock Instructions'
|
||||
|
||||
@@ -6,6 +6,7 @@ Gem::Specification.new do |s|
|
||||
s.name = "devise"
|
||||
s.version = Devise::VERSION.dup
|
||||
s.platform = Gem::Platform::RUBY
|
||||
s.licenses = ["MIT"]
|
||||
s.summary = "Flexible authentication solution for Rails with Warden"
|
||||
s.email = "contact@plataformatec.com.br"
|
||||
s.homepage = "http://github.com/plataformatec/devise"
|
||||
@@ -18,8 +19,9 @@ Gem::Specification.new do |s|
|
||||
s.test_files = `git ls-files -- test/*`.split("\n")
|
||||
s.require_paths = ["lib"]
|
||||
|
||||
s.add_dependency("warden", "~> 1.1.1")
|
||||
s.add_dependency("orm_adapter", "~> 0.0.7")
|
||||
s.add_dependency("warden", "~> 1.2.3")
|
||||
s.add_dependency("orm_adapter", "~> 0.1")
|
||||
s.add_dependency("bcrypt-ruby", "~> 3.0")
|
||||
s.add_dependency("railties", "~> 3.1")
|
||||
s.add_dependency("thread_safe", "~> 0.1")
|
||||
s.add_dependency("railties", ">= 3.2.6", "< 5")
|
||||
end
|
||||
|
||||
BIN
devise.png
Normal file
BIN
devise.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
@@ -1,167 +0,0 @@
|
||||
PATH
|
||||
remote: ..
|
||||
specs:
|
||||
devise (2.1.0.rc2)
|
||||
bcrypt-ruby (~> 3.0)
|
||||
orm_adapter (~> 0.0.7)
|
||||
railties (~> 3.1)
|
||||
warden (~> 1.1.1)
|
||||
|
||||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
actionmailer (3.1.4)
|
||||
actionpack (= 3.1.4)
|
||||
mail (~> 2.3.0)
|
||||
actionpack (3.1.4)
|
||||
activemodel (= 3.1.4)
|
||||
activesupport (= 3.1.4)
|
||||
builder (~> 3.0.0)
|
||||
erubis (~> 2.7.0)
|
||||
i18n (~> 0.6)
|
||||
rack (~> 1.3.6)
|
||||
rack-cache (~> 1.1)
|
||||
rack-mount (~> 0.8.2)
|
||||
rack-test (~> 0.6.1)
|
||||
sprockets (~> 2.0.3)
|
||||
activemodel (3.1.4)
|
||||
activesupport (= 3.1.4)
|
||||
builder (~> 3.0.0)
|
||||
i18n (~> 0.6)
|
||||
activerecord (3.1.4)
|
||||
activemodel (= 3.1.4)
|
||||
activesupport (= 3.1.4)
|
||||
arel (~> 2.2.3)
|
||||
tzinfo (~> 0.3.29)
|
||||
activeresource (3.1.4)
|
||||
activemodel (= 3.1.4)
|
||||
activesupport (= 3.1.4)
|
||||
activesupport (3.1.4)
|
||||
multi_json (~> 1.0)
|
||||
addressable (2.2.7)
|
||||
arel (2.2.3)
|
||||
bcrypt-ruby (3.0.1)
|
||||
bson (1.5.2)
|
||||
bson_ext (1.3.1)
|
||||
builder (3.0.0)
|
||||
columnize (0.3.6)
|
||||
erubis (2.7.0)
|
||||
faraday (0.7.6)
|
||||
addressable (~> 2.2)
|
||||
multipart-post (~> 1.1)
|
||||
rack (~> 1.1)
|
||||
hashie (1.2.0)
|
||||
hike (1.2.1)
|
||||
i18n (0.6.0)
|
||||
json (1.7.0)
|
||||
linecache (0.46)
|
||||
rbx-require-relative (> 0.0.4)
|
||||
mail (2.3.3)
|
||||
i18n (>= 0.4.0)
|
||||
mime-types (~> 1.16)
|
||||
treetop (~> 1.4.8)
|
||||
metaclass (0.0.1)
|
||||
mime-types (1.18)
|
||||
mocha (0.10.4)
|
||||
metaclass (~> 0.0.1)
|
||||
mongo (1.3.1)
|
||||
bson (>= 1.3.1)
|
||||
mongoid (2.4.4)
|
||||
activemodel (~> 3.1)
|
||||
mongo (~> 1.3)
|
||||
tzinfo (~> 0.3.22)
|
||||
multi_json (1.3.4)
|
||||
multipart-post (1.1.5)
|
||||
nokogiri (1.5.0)
|
||||
oauth2 (0.5.2)
|
||||
faraday (~> 0.7)
|
||||
multi_json (~> 1.0)
|
||||
omniauth (1.0.2)
|
||||
hashie (~> 1.2)
|
||||
rack
|
||||
omniauth-facebook (1.2.0)
|
||||
omniauth-oauth2 (~> 1.0.0)
|
||||
omniauth-oauth2 (1.0.0)
|
||||
oauth2 (~> 0.5.0)
|
||||
omniauth (~> 1.0)
|
||||
omniauth-openid (1.0.1)
|
||||
omniauth (~> 1.0)
|
||||
rack-openid (~> 1.3.1)
|
||||
orm_adapter (0.0.7)
|
||||
polyglot (0.3.3)
|
||||
rack (1.3.6)
|
||||
rack-cache (1.2)
|
||||
rack (>= 0.4)
|
||||
rack-mount (0.8.3)
|
||||
rack (>= 1.0.0)
|
||||
rack-openid (1.3.1)
|
||||
rack (>= 1.1.0)
|
||||
ruby-openid (>= 2.1.8)
|
||||
rack-ssl (1.3.2)
|
||||
rack
|
||||
rack-test (0.6.1)
|
||||
rack (>= 1.0)
|
||||
rails (3.1.4)
|
||||
actionmailer (= 3.1.4)
|
||||
actionpack (= 3.1.4)
|
||||
activerecord (= 3.1.4)
|
||||
activeresource (= 3.1.4)
|
||||
activesupport (= 3.1.4)
|
||||
bundler (~> 1.0)
|
||||
railties (= 3.1.4)
|
||||
railties (3.1.4)
|
||||
actionpack (= 3.1.4)
|
||||
activesupport (= 3.1.4)
|
||||
rack-ssl (~> 1.3.2)
|
||||
rake (>= 0.8.7)
|
||||
rdoc (~> 3.4)
|
||||
thor (~> 0.14.6)
|
||||
rake (0.9.2.2)
|
||||
rbx-require-relative (0.0.5)
|
||||
rdoc (3.12)
|
||||
json (~> 1.4)
|
||||
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)
|
||||
sprockets (2.0.4)
|
||||
hike (~> 1.2)
|
||||
rack (~> 1.0)
|
||||
tilt (~> 1.1, != 1.3.0)
|
||||
sqlite3 (1.3.5)
|
||||
thor (0.14.6)
|
||||
tilt (1.3.3)
|
||||
treetop (1.4.10)
|
||||
polyglot
|
||||
polyglot (>= 0.3.1)
|
||||
tzinfo (0.3.33)
|
||||
warden (1.1.1)
|
||||
rack (>= 1.0)
|
||||
webrat (0.7.2)
|
||||
nokogiri (>= 1.2.0)
|
||||
rack (>= 1.0)
|
||||
rack-test (>= 0.5.3)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
activerecord-jdbc-adapter
|
||||
activerecord-jdbcsqlite3-adapter
|
||||
bson_ext (~> 1.3.0)
|
||||
devise!
|
||||
jruby-openssl
|
||||
mocha
|
||||
mongo (~> 1.3.0)
|
||||
mongoid (~> 2.0)
|
||||
omniauth (~> 1.0.0)
|
||||
omniauth-facebook
|
||||
omniauth-oauth2 (~> 1.0.0)
|
||||
omniauth-openid (~> 1.0.1)
|
||||
rails (~> 3.1.0)
|
||||
rdoc
|
||||
ruby-debug (>= 0.10.3)
|
||||
sqlite3
|
||||
webrat (= 0.7.2)
|
||||
@@ -1,8 +1,8 @@
|
||||
source "http://rubygems.org"
|
||||
source "https://rubygems.org"
|
||||
|
||||
gem "devise", :path => ".."
|
||||
gemspec :path => '..'
|
||||
|
||||
gem "rails", "~> 3.1.0"
|
||||
gem "rails", "~> 3.2.6"
|
||||
gem "omniauth", "~> 1.0.0"
|
||||
gem "omniauth-oauth2", "~> 1.0.0"
|
||||
gem "rdoc"
|
||||
@@ -10,12 +10,8 @@ gem "rdoc"
|
||||
group :test do
|
||||
gem "omniauth-facebook"
|
||||
gem "omniauth-openid", "~> 1.0.1"
|
||||
gem "webrat", "0.7.2", :require => false
|
||||
gem "mocha", :require => false
|
||||
|
||||
platforms :mri_18 do
|
||||
gem "ruby-debug", ">= 0.10.3"
|
||||
end
|
||||
gem "webrat", "0.7.3", :require => false
|
||||
gem "mocha", "~> 0.13.1", :require => false
|
||||
end
|
||||
|
||||
platforms :jruby do
|
||||
@@ -26,10 +22,10 @@ end
|
||||
|
||||
platforms :ruby do
|
||||
gem "sqlite3"
|
||||
end
|
||||
|
||||
platforms :mri_19, :mri_20 do
|
||||
group :mongoid do
|
||||
gem "mongo", "~> 1.3.0"
|
||||
gem "mongoid", "~> 2.0"
|
||||
gem "bson_ext", "~> 1.3.0"
|
||||
gem "mongoid", "~> 3.0"
|
||||
end
|
||||
end
|
||||
159
gemfiles/Gemfile.rails-3.2.x.lock
Normal file
159
gemfiles/Gemfile.rails-3.2.x.lock
Normal file
@@ -0,0 +1,159 @@
|
||||
PATH
|
||||
remote: ..
|
||||
specs:
|
||||
devise (3.1.1)
|
||||
bcrypt-ruby (~> 3.0)
|
||||
orm_adapter (~> 0.1)
|
||||
railties (>= 3.2.6, < 5)
|
||||
thread_safe (~> 0.1)
|
||||
warden (~> 1.2.3)
|
||||
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actionmailer (3.2.14)
|
||||
actionpack (= 3.2.14)
|
||||
mail (~> 2.5.4)
|
||||
actionpack (3.2.14)
|
||||
activemodel (= 3.2.14)
|
||||
activesupport (= 3.2.14)
|
||||
builder (~> 3.0.0)
|
||||
erubis (~> 2.7.0)
|
||||
journey (~> 1.0.4)
|
||||
rack (~> 1.4.5)
|
||||
rack-cache (~> 1.2)
|
||||
rack-test (~> 0.6.1)
|
||||
sprockets (~> 2.2.1)
|
||||
activemodel (3.2.14)
|
||||
activesupport (= 3.2.14)
|
||||
builder (~> 3.0.0)
|
||||
activerecord (3.2.14)
|
||||
activemodel (= 3.2.14)
|
||||
activesupport (= 3.2.14)
|
||||
arel (~> 3.0.2)
|
||||
tzinfo (~> 0.3.29)
|
||||
activeresource (3.2.14)
|
||||
activemodel (= 3.2.14)
|
||||
activesupport (= 3.2.14)
|
||||
activesupport (3.2.14)
|
||||
i18n (~> 0.6, >= 0.6.4)
|
||||
multi_json (~> 1.0)
|
||||
arel (3.0.2)
|
||||
atomic (1.1.13)
|
||||
bcrypt-ruby (3.1.2)
|
||||
builder (3.0.4)
|
||||
erubis (2.7.0)
|
||||
faraday (0.8.8)
|
||||
multipart-post (~> 1.2.0)
|
||||
hashie (1.2.0)
|
||||
hike (1.2.3)
|
||||
httpauth (0.2.0)
|
||||
i18n (0.6.5)
|
||||
journey (1.0.4)
|
||||
json (1.8.0)
|
||||
jwt (0.1.8)
|
||||
multi_json (>= 1.5)
|
||||
mail (2.5.4)
|
||||
mime-types (~> 1.16)
|
||||
treetop (~> 1.4.8)
|
||||
metaclass (0.0.1)
|
||||
mime-types (1.23)
|
||||
mocha (0.13.3)
|
||||
metaclass (~> 0.0.1)
|
||||
mongoid (3.1.4)
|
||||
activemodel (~> 3.2)
|
||||
moped (~> 1.4)
|
||||
origin (~> 1.0)
|
||||
tzinfo (~> 0.3.22)
|
||||
moped (1.5.1)
|
||||
multi_json (1.7.9)
|
||||
multipart-post (1.2.0)
|
||||
nokogiri (1.5.9)
|
||||
oauth2 (0.8.1)
|
||||
faraday (~> 0.8)
|
||||
httpauth (~> 0.1)
|
||||
jwt (~> 0.1.4)
|
||||
multi_json (~> 1.0)
|
||||
rack (~> 1.2)
|
||||
omniauth (1.0.3)
|
||||
hashie (~> 1.2)
|
||||
rack
|
||||
omniauth-facebook (1.4.0)
|
||||
omniauth-oauth2 (~> 1.0.2)
|
||||
omniauth-oauth2 (1.0.3)
|
||||
oauth2 (~> 0.8.0)
|
||||
omniauth (~> 1.0)
|
||||
omniauth-openid (1.0.1)
|
||||
omniauth (~> 1.0)
|
||||
rack-openid (~> 1.3.1)
|
||||
origin (1.1.0)
|
||||
orm_adapter (0.4.0)
|
||||
polyglot (0.3.3)
|
||||
rack (1.4.5)
|
||||
rack-cache (1.2)
|
||||
rack (>= 0.4)
|
||||
rack-openid (1.3.1)
|
||||
rack (>= 1.1.0)
|
||||
ruby-openid (>= 2.1.8)
|
||||
rack-ssl (1.3.3)
|
||||
rack
|
||||
rack-test (0.6.2)
|
||||
rack (>= 1.0)
|
||||
rails (3.2.14)
|
||||
actionmailer (= 3.2.14)
|
||||
actionpack (= 3.2.14)
|
||||
activerecord (= 3.2.14)
|
||||
activeresource (= 3.2.14)
|
||||
activesupport (= 3.2.14)
|
||||
bundler (~> 1.0)
|
||||
railties (= 3.2.14)
|
||||
railties (3.2.14)
|
||||
actionpack (= 3.2.14)
|
||||
activesupport (= 3.2.14)
|
||||
rack-ssl (~> 1.3.2)
|
||||
rake (>= 0.8.7)
|
||||
rdoc (~> 3.4)
|
||||
thor (>= 0.14.6, < 2.0)
|
||||
rake (10.1.0)
|
||||
rdoc (3.12.2)
|
||||
json (~> 1.4)
|
||||
ruby-openid (2.2.3)
|
||||
sprockets (2.2.2)
|
||||
hike (~> 1.2)
|
||||
multi_json (~> 1.0)
|
||||
rack (~> 1.0)
|
||||
tilt (~> 1.1, != 1.3.0)
|
||||
sqlite3 (1.3.7)
|
||||
thor (0.18.1)
|
||||
thread_safe (0.1.2)
|
||||
atomic
|
||||
tilt (1.4.1)
|
||||
treetop (1.4.14)
|
||||
polyglot
|
||||
polyglot (>= 0.3.1)
|
||||
tzinfo (0.3.37)
|
||||
warden (1.2.3)
|
||||
rack (>= 1.0)
|
||||
webrat (0.7.3)
|
||||
nokogiri (>= 1.2.0)
|
||||
rack (>= 1.0)
|
||||
rack-test (>= 0.5.3)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
activerecord-jdbc-adapter
|
||||
activerecord-jdbcsqlite3-adapter
|
||||
devise!
|
||||
jruby-openssl
|
||||
mocha (~> 0.13.1)
|
||||
mongoid (~> 3.0)
|
||||
omniauth (~> 1.0.0)
|
||||
omniauth-facebook
|
||||
omniauth-oauth2 (~> 1.0.0)
|
||||
omniauth-openid (~> 1.0.1)
|
||||
rails (~> 3.2.6)
|
||||
rdoc
|
||||
sqlite3
|
||||
webrat (= 0.7.3)
|
||||
@@ -6,12 +6,15 @@ require 'set'
|
||||
require 'securerandom'
|
||||
|
||||
module Devise
|
||||
autoload :Delegator, 'devise/delegator'
|
||||
autoload :FailureApp, 'devise/failure_app'
|
||||
autoload :OmniAuth, 'devise/omniauth'
|
||||
autoload :ParamFilter, 'devise/param_filter'
|
||||
autoload :Schema, 'devise/schema'
|
||||
autoload :TestHelpers, 'devise/test_helpers'
|
||||
autoload :Delegator, 'devise/delegator'
|
||||
autoload :FailureApp, 'devise/failure_app'
|
||||
autoload :OmniAuth, 'devise/omniauth'
|
||||
autoload :ParameterFilter, 'devise/parameter_filter'
|
||||
autoload :BaseSanitizer, 'devise/parameter_sanitizer'
|
||||
autoload :ParameterSanitizer, 'devise/parameter_sanitizer'
|
||||
autoload :TestHelpers, 'devise/test_helpers'
|
||||
autoload :TimeInflector, 'devise/time_inflector'
|
||||
autoload :TokenGenerator, 'devise/token_generator'
|
||||
|
||||
module Controllers
|
||||
autoload :Helpers, 'devise/controllers/helpers'
|
||||
@@ -43,7 +46,21 @@ module Devise
|
||||
# True values used to check params
|
||||
TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE']
|
||||
|
||||
# Custom domain for cookies. Not set by default
|
||||
# Secret key used by the key generator
|
||||
mattr_accessor :secret_key
|
||||
@@secret_key = nil
|
||||
|
||||
# Allow insecure token lookup. Must be used
|
||||
# temporarily just for migration.
|
||||
mattr_accessor :allow_insecure_token_lookup
|
||||
@@allow_insecure_tokens_lookup = false
|
||||
|
||||
# Allow insecure sign in after confirmation. Must be used
|
||||
# temporarily just for migration.
|
||||
mattr_accessor :allow_insecure_sign_in_after_confirmation
|
||||
@@allow_insecure_sign_in_after_confirmation = false
|
||||
|
||||
# Custom domain or key for cookies. Not set by default
|
||||
mattr_accessor :rememberable_options
|
||||
@@rememberable_options = {}
|
||||
|
||||
@@ -51,6 +68,10 @@ module Devise
|
||||
mattr_accessor :stretches
|
||||
@@stretches = 10
|
||||
|
||||
# The default key used when authenticating over http auth.
|
||||
mattr_accessor :http_authentication_key
|
||||
@@http_authentication_key = nil
|
||||
|
||||
# Keys used when authenticating a user.
|
||||
mattr_accessor :authentication_keys
|
||||
@@authentication_keys = [ :email ]
|
||||
@@ -87,7 +108,7 @@ module Devise
|
||||
# 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 = /\A[^@]+@([^@\.]+\.)+[^@\.]+\z/
|
||||
@@email_regexp = /\A[^@\s]+@([^@\s]+\.)+[^@\s]+\z/
|
||||
|
||||
# Range validation for password length
|
||||
mattr_accessor :password_length
|
||||
@@ -102,9 +123,14 @@ module Devise
|
||||
@@extend_remember_period = false
|
||||
|
||||
# Time interval you can access your account before confirming your account.
|
||||
# nil - allows unconfirmed access for unlimited time
|
||||
mattr_accessor :allow_unconfirmed_access_for
|
||||
@@allow_unconfirmed_access_for = 0.days
|
||||
|
||||
# Time interval the confirmation token is valid. nil = unlimited
|
||||
mattr_accessor :confirm_within
|
||||
@@confirm_within = nil
|
||||
|
||||
# Defines which key will be used when confirming an account.
|
||||
mattr_accessor :confirmation_keys
|
||||
@@confirmation_keys = [ :email ]
|
||||
@@ -195,23 +221,26 @@ module Devise
|
||||
mattr_accessor :parent_controller
|
||||
@@parent_controller = "ApplicationController"
|
||||
|
||||
# The parent mailer all Devise mailers inherit from.
|
||||
# Defaults to ActionMailer::Base. This should be set early
|
||||
# in the initialization process and should be set to a string.
|
||||
mattr_accessor :parent_mailer
|
||||
@@parent_mailer = "ActionMailer::Base"
|
||||
|
||||
# The router Devise should use to generate routes. Defaults
|
||||
# to :main_app. Should be overriden by engines in order
|
||||
# to provide custom routes.
|
||||
mattr_accessor :router_name
|
||||
@@router_name = nil
|
||||
|
||||
def self.encryptor=(value)
|
||||
warn "\n[DEVISE] To select a encryption which isn't bcrypt, you should use devise-encryptable gem.\n"
|
||||
end
|
||||
# Set the omniauth path prefix so it can be overriden when
|
||||
# Devise is used in a mountable engine
|
||||
mattr_accessor :omniauth_path_prefix
|
||||
@@omniauth_path_prefix = nil
|
||||
|
||||
def self.use_salt_as_remember_token=(value)
|
||||
warn "\n[DEVISE] Devise.use_salt_as_remember_token is deprecated and has no effect. Please remove it.\n"
|
||||
end
|
||||
|
||||
def self.apply_schema=(value)
|
||||
warn "\n[DEVISE] Devise.apply_schema is deprecated and has no effect. Please remove it.\n"
|
||||
end
|
||||
# Set if we should clean up the CSRF Token on authentication
|
||||
mattr_accessor :clean_up_csrf_token_on_authentication
|
||||
@@clean_up_csrf_token_on_authentication = true
|
||||
|
||||
# PRIVATE CONFIGURATION
|
||||
|
||||
@@ -237,6 +266,10 @@ module Devise
|
||||
mattr_accessor :paranoid
|
||||
@@paranoid = false
|
||||
|
||||
# Stores the token generator
|
||||
mattr_accessor :token_generator
|
||||
@@token_generator = nil
|
||||
|
||||
# Default way to setup Devise. Run rails generate devise_install to create
|
||||
# a fresh initializer with all configuration values.
|
||||
def self.setup
|
||||
@@ -295,7 +328,7 @@ module Devise
|
||||
# == Options:
|
||||
#
|
||||
# +model+ - String representing the load path to a custom *model* for this module (to autoload.)
|
||||
# +controller+ - Symbol representing the name of an exisiting or custom *controller* for this module.
|
||||
# +controller+ - Symbol representing the name of an existing or custom *controller* for this module.
|
||||
# +route+ - Symbol representing the named *route* helper for this module.
|
||||
# +strategy+ - Symbol representing if this module got a custom *strategy*.
|
||||
#
|
||||
@@ -405,6 +438,17 @@ module Devise
|
||||
|
||||
Devise.mappings.each_value do |mapping|
|
||||
warden_config.scope_defaults mapping.name, :strategies => mapping.strategies
|
||||
|
||||
warden_config.serialize_into_session(mapping.name) do |record|
|
||||
mapping.to.serialize_into_session(record)
|
||||
end
|
||||
|
||||
warden_config.serialize_from_session(mapping.name) do |key|
|
||||
# Previous versions contained an additional entry at the beginning of
|
||||
# key with the record's class name.
|
||||
args = key[-2, 2]
|
||||
mapping.to.serialize_from_session(*args)
|
||||
end
|
||||
end
|
||||
|
||||
@@warden_config_block.try :call, Devise.warden_config
|
||||
@@ -412,9 +456,9 @@ module Devise
|
||||
end
|
||||
end
|
||||
|
||||
# Generate a friendly string randomically to be used as token.
|
||||
# Generate a friendly string randomly to be used as token.
|
||||
def self.friendly_token
|
||||
SecureRandom.base64(15).tr('+/=lIO0', 'pqrsxyz')
|
||||
SecureRandom.urlsafe_base64(15).tr('lIO0', 'sxyz')
|
||||
end
|
||||
|
||||
# constant-time comparison algorithm to prevent timing attacks
|
||||
|
||||
@@ -80,6 +80,17 @@ module Devise
|
||||
is_a?(DeviseController)
|
||||
end
|
||||
|
||||
# Setup a param sanitizer to filter parameters using strong_parameters. See
|
||||
# lib/devise/parameter_sanitizer.rb for more info. Override this
|
||||
# method in your application controller to use your own parameter sanitizer.
|
||||
def devise_parameter_sanitizer
|
||||
@devise_parameter_sanitizer ||= if defined?(ActionController::StrongParameters)
|
||||
Devise::ParameterSanitizer.new(resource_class, resource_name, params)
|
||||
else
|
||||
Devise::BaseSanitizer.new(resource_class, resource_name, params)
|
||||
end
|
||||
end
|
||||
|
||||
# Tell warden that params authentication is allowed for that specific page.
|
||||
def allow_params_authentication!
|
||||
request.env["devise.allow_params_authentication"] = true
|
||||
@@ -88,8 +99,8 @@ module Devise
|
||||
# Return true if the given scope is signed in session. If no scope given, return
|
||||
# true if any scope is signed in. Does not run authentication hooks.
|
||||
def signed_in?(scope=nil)
|
||||
[ scope || Devise.mappings.keys ].flatten.any? do |scope|
|
||||
warden.authenticate?(:scope => scope)
|
||||
[ scope || Devise.mappings.keys ].flatten.any? do |_scope|
|
||||
warden.authenticate?(:scope => _scope)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -106,6 +117,7 @@ module Devise
|
||||
# sign_in :user, @user # sign_in(scope, resource)
|
||||
# sign_in @user # sign_in(resource)
|
||||
# sign_in @user, :event => :authentication # sign_in(resource, options)
|
||||
# sign_in @user, :store => false # sign_in(resource, options)
|
||||
# sign_in @user, :bypass => true # sign_in(resource, options)
|
||||
#
|
||||
def sign_in(resource_or_scope, *args)
|
||||
@@ -126,8 +138,8 @@ module Devise
|
||||
end
|
||||
|
||||
# Sign out a given user or scope. This helper is useful for signing out a user
|
||||
# after deleting accounts. Returns true if there was a logout and false if there is no user logged in
|
||||
# on the referred scope
|
||||
# after deleting accounts. Returns true if there was a logout and false if there
|
||||
# is no user logged in on the referred scope
|
||||
#
|
||||
# Examples:
|
||||
#
|
||||
@@ -141,6 +153,7 @@ module Devise
|
||||
|
||||
warden.raw_session.inspect # Without this inspect here. The session does not clear.
|
||||
warden.logout(scope)
|
||||
warden.clear_strategies_cache!(:scope => scope)
|
||||
instance_variable_set(:"@current_#{scope}", nil)
|
||||
|
||||
!!user
|
||||
@@ -149,18 +162,20 @@ module Devise
|
||||
# Sign out all active users or scopes. This helper is useful for signing out all roles
|
||||
# in one click. This signs out ALL scopes in warden. Returns true if there was at least one logout
|
||||
# and false if there was no user logged in on all scopes.
|
||||
def sign_out_all_scopes
|
||||
def sign_out_all_scopes(lock=true)
|
||||
users = Devise.mappings.keys.map { |s| warden.user(:scope => s, :run_callbacks => false) }
|
||||
|
||||
warden.raw_session.inspect
|
||||
warden.logout
|
||||
expire_devise_cached_variables!
|
||||
|
||||
warden.clear_strategies_cache!
|
||||
warden.lock! if lock
|
||||
|
||||
users.any?
|
||||
end
|
||||
|
||||
# Returns and delete the url stored in the session for the given scope. Useful
|
||||
# for giving redirect backs after sign up:
|
||||
# Returns and delete (if it's navigational format) the url stored in the session for
|
||||
# the given scope. Useful for giving redirect backs after sign up:
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
@@ -168,7 +183,12 @@ module Devise
|
||||
#
|
||||
def stored_location_for(resource_or_scope)
|
||||
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
||||
session.delete("#{scope}_return_to")
|
||||
|
||||
if is_navigational_format?
|
||||
session.delete("#{scope}_return_to")
|
||||
else
|
||||
session["#{scope}_return_to"]
|
||||
end
|
||||
end
|
||||
|
||||
# The scope root url to be used when he's signed in. By default, it first
|
||||
@@ -253,12 +273,20 @@ module Devise
|
||||
# Overwrite Rails' handle unverified request to sign out all scopes,
|
||||
# clear run strategies and remove cached variables.
|
||||
def handle_unverified_request
|
||||
sign_out_all_scopes
|
||||
warden.clear_strategies_cache!
|
||||
sign_out_all_scopes(false)
|
||||
request.env["devise.skip_storage"] = true
|
||||
expire_devise_cached_variables!
|
||||
super # call the default behaviour which resets the session
|
||||
end
|
||||
|
||||
def request_format
|
||||
@request_format ||= request.format.try(:ref)
|
||||
end
|
||||
|
||||
def is_navigational_format?
|
||||
Devise.navigational_formats.include?(request_format)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def expire_devise_cached_variables!
|
||||
|
||||
@@ -21,16 +21,17 @@ module Devise
|
||||
|
||||
# Remembers the given resource by setting up a cookie
|
||||
def remember_me(resource)
|
||||
return if env["devise.skip_storage"]
|
||||
scope = Devise::Mapping.find_scope!(resource)
|
||||
resource.remember_me!(resource.extend_remember_period)
|
||||
cookies.signed["remember_#{scope}_token"] = remember_cookie_values(resource)
|
||||
cookies.signed[remember_key(resource, scope)] = remember_cookie_values(resource)
|
||||
end
|
||||
|
||||
# Forgets the given resource by deleting a cookie
|
||||
def forget_me(resource)
|
||||
scope = Devise::Mapping.find_scope!(resource)
|
||||
resource.forget_me!
|
||||
cookies.delete("remember_#{scope}_token", forget_cookie_values(resource))
|
||||
cookies.delete(remember_key(resource, scope), forget_cookie_values(resource))
|
||||
end
|
||||
|
||||
protected
|
||||
@@ -47,6 +48,10 @@ module Devise
|
||||
:expires => resource.remember_expires_at
|
||||
)
|
||||
end
|
||||
|
||||
def remember_key(resource, scope)
|
||||
resource.rememberable_options.fetch(:key, "remember_#{scope}_token")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -78,7 +78,14 @@ module Devise
|
||||
def redirect_url
|
||||
if warden_message == :timeout
|
||||
flash[:timedout] = true
|
||||
attempted_path || scope_path
|
||||
|
||||
path = if request.get?
|
||||
attempted_path
|
||||
else
|
||||
request.referrer
|
||||
end
|
||||
|
||||
path || scope_path
|
||||
else
|
||||
scope_path
|
||||
end
|
||||
|
||||
5
lib/devise/hooks/csrf_cleaner.rb
Normal file
5
lib/devise/hooks/csrf_cleaner.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
Warden::Manager.after_authentication do |record, warden, options|
|
||||
if Devise.clean_up_csrf_token_on_authentication
|
||||
warden.request.session.try(:delete, :_csrf_token)
|
||||
end
|
||||
end
|
||||
@@ -2,6 +2,6 @@
|
||||
# This is only triggered when the user is explicitly set (with set_user)
|
||||
Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
|
||||
if record.respond_to?(:failed_attempts) && warden.authenticated?(options[:scope])
|
||||
record.update_attribute(:failed_attempts, 0)
|
||||
record.update_attribute(:failed_attempts, 0) unless record.failed_attempts.to_i.zero?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
|
||||
scope = options[:scope]
|
||||
if record.respond_to?(:remember_me) && record.remember_me && warden.authenticated?(scope)
|
||||
if record.respond_to?(:remember_me) && options[:store] != false &&
|
||||
record.remember_me && warden.authenticated?(scope)
|
||||
Devise::Controllers::Rememberable::Proxy.new(warden).remember_me(record)
|
||||
end
|
||||
end
|
||||
@@ -5,17 +5,20 @@
|
||||
# verify timeout in the following request.
|
||||
Warden::Manager.after_set_user do |record, warden, options|
|
||||
scope = options[:scope]
|
||||
env = warden.request.env
|
||||
|
||||
if record && record.respond_to?(:timedout?) && warden.authenticated?(scope) && options[:store] != false
|
||||
last_request_at = warden.session(scope)['last_request_at']
|
||||
|
||||
if record.timedout?(last_request_at)
|
||||
if record.timedout?(last_request_at) && !env['devise.skip_timeout']
|
||||
warden.logout(scope)
|
||||
record.reset_authentication_token! if record.respond_to?(:reset_authentication_token!) && record.expire_auth_token_on_timeout
|
||||
if record.respond_to?(:expire_auth_token_on_timeout) && record.expire_auth_token_on_timeout
|
||||
record.reset_authentication_token!
|
||||
end
|
||||
throw :warden, :scope => scope, :message => :timeout
|
||||
end
|
||||
|
||||
unless warden.request.env['devise.skip_trackable']
|
||||
unless env['devise.skip_trackable']
|
||||
warden.session(scope)['last_request_at'] = Time.now.utc
|
||||
end
|
||||
end
|
||||
|
||||
@@ -11,9 +11,9 @@ module Devise
|
||||
protected
|
||||
|
||||
# Configure default email options
|
||||
def devise_mail(record, action)
|
||||
def devise_mail(record, action, opts={})
|
||||
initialize_from_record(record)
|
||||
mail headers_for(action)
|
||||
mail headers_for(action, opts)
|
||||
end
|
||||
|
||||
def initialize_from_record(record)
|
||||
@@ -25,28 +25,32 @@ module Devise
|
||||
@devise_mapping ||= Devise.mappings[scope_name]
|
||||
end
|
||||
|
||||
def headers_for(action)
|
||||
def headers_for(action, opts)
|
||||
headers = {
|
||||
:subject => translate(devise_mapping, action),
|
||||
:from => mailer_sender(devise_mapping),
|
||||
:subject => subject_for(action),
|
||||
: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
|
||||
:from => mailer_sender(devise_mapping),
|
||||
:reply_to => mailer_reply_to(devise_mapping),
|
||||
:template_path => template_paths,
|
||||
:template_name => action
|
||||
}.merge(opts)
|
||||
|
||||
@email = headers[:to]
|
||||
headers
|
||||
end
|
||||
|
||||
def mailer_sender(mapping)
|
||||
if default_params[:from].present?
|
||||
default_params[:from]
|
||||
def mailer_reply_to(mapping)
|
||||
mailer_sender(mapping, :reply_to)
|
||||
end
|
||||
|
||||
def mailer_from(mapping)
|
||||
mailer_sender(mapping, :from)
|
||||
end
|
||||
|
||||
def mailer_sender(mapping, sender = :from)
|
||||
default_sender = default_params[sender]
|
||||
if default_sender.present?
|
||||
default_sender.respond_to?(:to_proc) ? instance_eval(&default_sender) : default_sender
|
||||
elsif Devise.mailer_sender.is_a?(Proc)
|
||||
Devise.mailer_sender.call(mapping.name)
|
||||
else
|
||||
@@ -55,12 +59,12 @@ module Devise
|
||||
end
|
||||
|
||||
def template_paths
|
||||
template_path = [self.class.mailer_name]
|
||||
template_path = _prefixes.dup
|
||||
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
|
||||
# Setup a subject doing an I18n lookup. At first, it attempts to set a subject
|
||||
# based on the current mapping:
|
||||
#
|
||||
# en:
|
||||
@@ -77,8 +81,8 @@ module Devise
|
||||
# confirmation_instructions:
|
||||
# subject: '...'
|
||||
#
|
||||
def translate(mapping, key)
|
||||
I18n.t(:"#{mapping.name}_subject", :scope => [:devise, :mailer, key],
|
||||
def subject_for(key)
|
||||
I18n.t(:"#{devise_mapping.name}_subject", :scope => [:devise, :mailer, key],
|
||||
:default => [:subject, key.to_s.humanize])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -29,17 +29,17 @@ module Devise
|
||||
|
||||
# Receives an object and find a scope for it. If a scope cannot be found,
|
||||
# raises an error. If a symbol is given, it's considered to be the scope.
|
||||
def self.find_scope!(duck)
|
||||
case duck
|
||||
def self.find_scope!(obj)
|
||||
case obj
|
||||
when String, Symbol
|
||||
return duck
|
||||
return obj
|
||||
when Class
|
||||
Devise.mappings.each_value { |m| return m.name if duck <= m.to }
|
||||
Devise.mappings.each_value { |m| return m.name if obj <= m.to }
|
||||
else
|
||||
Devise.mappings.each_value { |m| return m.name if duck.is_a?(m.to) }
|
||||
Devise.mappings.each_value { |m| return m.name if obj.is_a?(m.to) }
|
||||
end
|
||||
|
||||
raise "Could not find a valid mapping for #{duck.inspect}"
|
||||
raise "Could not find a valid mapping for #{obj.inspect}"
|
||||
end
|
||||
|
||||
def self.find_by_path!(path, path_type=:fullpath)
|
||||
|
||||
@@ -27,7 +27,7 @@ module Devise
|
||||
# inside the given class.
|
||||
#
|
||||
def self.config(mod, *accessors) #:nodoc:
|
||||
(class << mod; self; end).send :attr_accessor, :available_configs
|
||||
class << mod; attr_accessor :available_configs; end
|
||||
mod.available_configs = accessors
|
||||
|
||||
accessors.each do |accessor|
|
||||
@@ -51,18 +51,13 @@ module Devise
|
||||
|
||||
def self.check_fields!(klass)
|
||||
failed_attributes = []
|
||||
instance = klass.new
|
||||
|
||||
klass.devise_modules.each do |mod|
|
||||
instance = klass.new
|
||||
constant = const_get(mod.to_s.classify)
|
||||
|
||||
if const_get(mod.to_s.classify).respond_to?(:required_fields)
|
||||
const_get(mod.to_s.classify).required_fields(klass).each do |field|
|
||||
failed_attributes << field unless instance.respond_to?(field)
|
||||
end
|
||||
else
|
||||
ActiveSupport::Deprecation.warn "The module #{mod} doesn't implement self.required_fields(klass). " \
|
||||
"Devise uses required_fields to warn developers of any missing fields in their models. " \
|
||||
"Please implement #{mod}.required_fields(klass) that returns an array of symbols with the required fields."
|
||||
constant.required_fields(klass).each do |field|
|
||||
failed_attributes << field unless instance.respond_to?(field)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -88,11 +83,13 @@ module Devise
|
||||
|
||||
devise_modules_hook! do
|
||||
include Devise::Models::Authenticatable
|
||||
selected_modules.each do |m|
|
||||
if m == :encryptable && !(defined?(Devise::Models::Encryptable))
|
||||
warn "[DEVISE] You're trying to include :encryptable in your model but it is not bundled with the Devise gem anymore. Please add `devise-encryptable` to your Gemfile to proceed.\n"
|
||||
end
|
||||
|
||||
if selected_modules.include?(:token_authenticatable)
|
||||
ActiveSupport::Deprecation.warn "devise :token_authenticatable is deprecated. " \
|
||||
"Please check Devise 3.1 release notes for more information on how to upgrade."
|
||||
end
|
||||
|
||||
selected_modules.each do |m|
|
||||
mod = Devise::Models.const_get(m.to_s.classify)
|
||||
|
||||
if mod.const_defined?("ClassMethods")
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
require 'devise/hooks/activatable'
|
||||
require 'devise/hooks/csrf_cleaner'
|
||||
|
||||
module Devise
|
||||
module Models
|
||||
@@ -10,15 +11,18 @@ module Devise
|
||||
#
|
||||
# * +authentication_keys+: parameters used for authentication. By default [:email].
|
||||
#
|
||||
# * +http_authentication_key+: map the username passed via HTTP Auth to this parameter. Defaults to
|
||||
# the first element in +authentication_keys+.
|
||||
#
|
||||
# * +request_keys+: parameters from the request object used for authentication.
|
||||
# By specifying a symbol (which should be a request method), it will automatically be
|
||||
# passed to find_for_authentication method and considered in your model lookup.
|
||||
#
|
||||
# For instance, if you set :request_keys to [:subdomain], :subdomain will be considered
|
||||
# as key on authentication. This can also be a hash where the value is a boolean expliciting
|
||||
# as key on authentication. This can also be a hash where the value is a boolean specifying
|
||||
# if the value is required or not.
|
||||
#
|
||||
# * +http_authenticatable+: if this model allows http authentication. By default true.
|
||||
# * +http_authenticatable+: if this model allows http authentication. By default false.
|
||||
# It also accepts an array specifying the strategies that should allow http.
|
||||
#
|
||||
# * +params_authenticatable+: if this model allows authentication through request params. By default true.
|
||||
@@ -32,7 +36,7 @@ module Devise
|
||||
# == active_for_authentication?
|
||||
#
|
||||
# After authenticating a user and in each request, Devise checks if your model is active by
|
||||
# calling model.active_for_authentication?. This method is overwriten by other devise modules. For instance,
|
||||
# calling model.active_for_authentication?. This method is overwritten by other devise modules. For instance,
|
||||
# :confirmable overwrites .active_for_authentication? to only return true if your model was confirmed.
|
||||
#
|
||||
# You overwrite this method yourself, but if you do, don't forget to call super:
|
||||
@@ -93,22 +97,6 @@ module Devise
|
||||
def authenticatable_salt
|
||||
end
|
||||
|
||||
def devise_mailer
|
||||
Devise.mailer
|
||||
end
|
||||
|
||||
def headers_for(name)
|
||||
{}
|
||||
end
|
||||
|
||||
def downcase_keys
|
||||
self.class.case_insensitive_keys.each { |k| self[k].try(:downcase!) }
|
||||
end
|
||||
|
||||
def strip_whitespace
|
||||
self.class.strip_whitespace_keys.each { |k| self[k].try(:strip!) }
|
||||
end
|
||||
|
||||
array = %w(serializable_hash)
|
||||
# to_xml does not call serializable_hash on 3.1
|
||||
array << "to_xml" if Rails::VERSION::STRING[0,3] == "3.1"
|
||||
@@ -134,9 +122,84 @@ module Devise
|
||||
RUBY
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def devise_mailer
|
||||
Devise.mailer
|
||||
end
|
||||
|
||||
# This is an internal method called every time Devise needs
|
||||
# to send a notification/mail. This can be overriden if you
|
||||
# need to customize the e-mail delivery logic. For instance,
|
||||
# if you are using a queue to deliver e-mails (delayed job,
|
||||
# sidekiq, resque, etc), you must add the delivery to the queue
|
||||
# just after the transaction was committed. To achieve this,
|
||||
# you can override send_devise_notification to store the
|
||||
# deliveries until the after_commit callback is triggered:
|
||||
#
|
||||
# class User
|
||||
# devise :database_authenticatable, :confirmable
|
||||
#
|
||||
# after_commit :send_pending_notifications
|
||||
#
|
||||
# protected
|
||||
#
|
||||
# def send_devise_notification(notification, *args)
|
||||
# # If the record is new or changed then delay the
|
||||
# # delivery until the after_commit callback otherwise
|
||||
# # send now because after_commit will not be called.
|
||||
# if new_record? || changed?
|
||||
# pending_notifications << [notification, args]
|
||||
# else
|
||||
# devise_mailer.send(notification, self, *args).deliver
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# def send_pending_notifications
|
||||
# pending_notifications.each do |notification, args|
|
||||
# devise_mailer.send(notification, self, *args).deliver
|
||||
# end
|
||||
#
|
||||
# # Empty the pending notifications array because the
|
||||
# # after_commit hook can be called multiple times which
|
||||
# # could cause multiple emails to be sent.
|
||||
# pending_notifications.clear
|
||||
# end
|
||||
#
|
||||
# def pending_notifications
|
||||
# @pending_notifications ||= []
|
||||
# end
|
||||
# end
|
||||
#
|
||||
def send_devise_notification(notification, *args)
|
||||
devise_mailer.send(notification, self, *args).deliver
|
||||
end
|
||||
|
||||
def downcase_keys
|
||||
self.class.case_insensitive_keys.each { |k| apply_to_attribute_or_variable(k, :downcase!) }
|
||||
end
|
||||
|
||||
def strip_whitespace
|
||||
self.class.strip_whitespace_keys.each { |k| apply_to_attribute_or_variable(k, :strip!) }
|
||||
end
|
||||
|
||||
def apply_to_attribute_or_variable(attr, method)
|
||||
if self[attr]
|
||||
self[attr].try(method)
|
||||
|
||||
# Use respond_to? here to avoid a regression where globally
|
||||
# configured strip_whitespace_keys or case_insensitive_keys were
|
||||
# attempting to strip! or downcase! when a model didn't have the
|
||||
# globally configured key.
|
||||
elsif respond_to?(attr)
|
||||
send(attr).try(method)
|
||||
end
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
Devise::Models.config(self, :authentication_keys, :request_keys, :strip_whitespace_keys,
|
||||
:case_insensitive_keys, :http_authenticatable, :params_authenticatable, :skip_session_storage)
|
||||
:case_insensitive_keys, :http_authenticatable, :params_authenticatable, :skip_session_storage,
|
||||
:http_authentication_key)
|
||||
|
||||
def serialize_into_session(record)
|
||||
[record.to_key, record.authenticatable_salt]
|
||||
@@ -162,27 +225,26 @@ module Devise
|
||||
# it may be wrapped as well. For instance, database authenticatable
|
||||
# provides a `find_for_database_authentication` that wraps a call to
|
||||
# this method. This allows you to customize both database authenticatable
|
||||
# or the whole authenticate stack by customize `find_for_authentication.`
|
||||
# or the whole authenticate stack by customize `find_for_authentication.`
|
||||
#
|
||||
# Overwrite to add customized conditions, create a join, or maybe use a
|
||||
# namedscope to filter records while authenticating.
|
||||
# Example:
|
||||
#
|
||||
# def self.find_for_authentication(conditions={})
|
||||
# conditions[:active] = true
|
||||
# super
|
||||
# def self.find_for_authentication(tainted_conditions)
|
||||
# find_first_by_auth_conditions(tainted_conditions, :active => true)
|
||||
# end
|
||||
#
|
||||
# Finally, notice that Devise also queries for users in other scenarios
|
||||
# besides authentication, for example when retrieving an user to send
|
||||
# an e-mail for password reset. In such cases, find_for_authentication
|
||||
# is not called.
|
||||
def find_for_authentication(conditions)
|
||||
find_first_by_auth_conditions(conditions)
|
||||
def find_for_authentication(tainted_conditions)
|
||||
find_first_by_auth_conditions(tainted_conditions)
|
||||
end
|
||||
|
||||
def find_first_by_auth_conditions(conditions)
|
||||
to_adapter.find_first devise_param_filter.filter(conditions)
|
||||
def find_first_by_auth_conditions(tainted_conditions, opts={})
|
||||
to_adapter.find_first(devise_parameter_filter.filter(tainted_conditions).merge(opts))
|
||||
end
|
||||
|
||||
# Find an initialize a record setting an error if it can't be found.
|
||||
@@ -214,16 +276,8 @@ module Devise
|
||||
|
||||
protected
|
||||
|
||||
def devise_param_filter
|
||||
@devise_param_filter ||= Devise::ParamFilter.new(case_insensitive_keys, strip_whitespace_keys)
|
||||
end
|
||||
|
||||
# Generate a token by looping and ensuring does not already exist.
|
||||
def generate_token(column)
|
||||
loop do
|
||||
token = Devise.friendly_token
|
||||
break token unless to_adapter.find_first({ column => token })
|
||||
end
|
||||
def devise_parameter_filter
|
||||
@devise_parameter_filter ||= Devise::ParameterFilter.new(case_insensitive_keys, strip_whitespace_keys)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,7 +7,7 @@ module Devise
|
||||
#
|
||||
# == Options
|
||||
#
|
||||
# Confirmable adds the following options to devise_for:
|
||||
# Confirmable adds the following options to +devise+:
|
||||
#
|
||||
# * +allow_unconfirmed_access_for+: the time you want to allow the user to access his account
|
||||
# before confirming it. After this period, the user access is denied. You can
|
||||
@@ -19,6 +19,8 @@ module Devise
|
||||
# db field to be setup (t.reconfirmable in migrations). Until confirmed new email is
|
||||
# stored in unconfirmed email column, and copied to email column on successful
|
||||
# confirmation.
|
||||
# * +confirm_within+: the time before a sent confirmation token becomes invalid.
|
||||
# You can use this to force the user to confirm within a set period of time.
|
||||
#
|
||||
# == Examples
|
||||
#
|
||||
@@ -28,12 +30,21 @@ module Devise
|
||||
#
|
||||
module Confirmable
|
||||
extend ActiveSupport::Concern
|
||||
include ActionView::Helpers::DateHelper
|
||||
|
||||
included do
|
||||
before_create :generate_confirmation_token, :if => :confirmation_required?
|
||||
after_create :send_on_create_confirmation_instructions, :if => :confirmation_required?
|
||||
before_update :postpone_email_change_until_confirmation, :if => :postpone_email_change?
|
||||
after_update :send_confirmation_instructions, :if => :reconfirmation_required?
|
||||
after_create :send_on_create_confirmation_instructions, :if => :send_confirmation_notification?
|
||||
before_update :postpone_email_change_until_confirmation_and_regenerate_confirmation_token, :if => :postpone_email_change?
|
||||
after_update :send_reconfirmation_instructions, :if => :reconfirmation_required?
|
||||
end
|
||||
|
||||
def initialize(*args, &block)
|
||||
@bypass_confirmation_postpone = false
|
||||
@reconfirmation_required = false
|
||||
@skip_confirmation_notification = false
|
||||
@raw_confirmation_token = nil
|
||||
super
|
||||
end
|
||||
|
||||
def self.required_fields(klass)
|
||||
@@ -47,10 +58,16 @@ module Devise
|
||||
# add errors
|
||||
def confirm!
|
||||
pending_any_confirmation do
|
||||
if confirmation_period_expired?
|
||||
self.errors.add(:email, :confirmation_period_expired,
|
||||
:period => Devise::TimeInflector.time_ago_in_words(self.class.confirm_within.ago))
|
||||
return false
|
||||
end
|
||||
|
||||
self.confirmation_token = nil
|
||||
self.confirmed_at = Time.now.utc
|
||||
|
||||
if self.class.reconfirmable && unconfirmed_email.present?
|
||||
saved = if self.class.reconfirmable && unconfirmed_email.present?
|
||||
skip_reconfirmation!
|
||||
self.email = unconfirmed_email
|
||||
self.unconfirmed_email = nil
|
||||
@@ -60,6 +77,9 @@ module Devise
|
||||
else
|
||||
save(:validate => false)
|
||||
end
|
||||
|
||||
after_confirmation if saved
|
||||
saved
|
||||
end
|
||||
end
|
||||
|
||||
@@ -74,16 +94,28 @@ module Devise
|
||||
|
||||
# Send confirmation instructions by email
|
||||
def send_confirmation_instructions
|
||||
self.confirmation_token = nil if reconfirmation_required?
|
||||
@reconfirmation_required = false
|
||||
unless @raw_confirmation_token
|
||||
generate_confirmation_token!
|
||||
end
|
||||
|
||||
generate_confirmation_token! if self.confirmation_token.blank?
|
||||
self.devise_mailer.confirmation_instructions(self).deliver
|
||||
opts = pending_reconfirmation? ? { :to => unconfirmed_email } : { }
|
||||
send_devise_notification(:confirmation_instructions, @raw_confirmation_token, opts)
|
||||
end
|
||||
|
||||
# Resend confirmation token. This method does not need to generate a new token.
|
||||
def resend_confirmation_token
|
||||
pending_any_confirmation { send_confirmation_instructions }
|
||||
def send_reconfirmation_instructions
|
||||
@reconfirmation_required = false
|
||||
|
||||
unless @skip_confirmation_notification
|
||||
send_confirmation_instructions
|
||||
end
|
||||
end
|
||||
|
||||
# Resend confirmation token.
|
||||
# Regenerates the token if the period is expired.
|
||||
def resend_confirmation_instructions
|
||||
pending_any_confirmation do
|
||||
send_confirmation_instructions
|
||||
end
|
||||
end
|
||||
|
||||
# Overwrites active_for_authentication? for confirmation
|
||||
@@ -105,18 +137,16 @@ module Devise
|
||||
self.confirmed_at = Time.now.utc
|
||||
end
|
||||
|
||||
# Skips sending the confirmation/reconfirmation notification email after_create/after_update. Unlike
|
||||
# #skip_confirmation!, record still requires confirmation.
|
||||
def skip_confirmation_notification!
|
||||
@skip_confirmation_notification = true
|
||||
end
|
||||
|
||||
# If you don't want reconfirmation to be sent, neither a code
|
||||
# to be generated, call skip_reconfirmation!
|
||||
def skip_reconfirmation!
|
||||
@bypass_postpone = true
|
||||
end
|
||||
|
||||
def headers_for(action)
|
||||
headers = super
|
||||
if action == :confirmation_instructions && pending_reconfirmation?
|
||||
headers[:to] = unconfirmed_email
|
||||
end
|
||||
headers
|
||||
@bypass_confirmation_postpone = true
|
||||
end
|
||||
|
||||
protected
|
||||
@@ -125,7 +155,7 @@ module Devise
|
||||
# instructions on creation. This can be overriden
|
||||
# in models to map to a nice sign up e-mail.
|
||||
def send_on_create_confirmation_instructions
|
||||
self.devise_mailer.confirmation_instructions(self).deliver
|
||||
send_confirmation_instructions
|
||||
end
|
||||
|
||||
# Callback to overwrite if confirmation is required or not.
|
||||
@@ -152,13 +182,32 @@ module Devise
|
||||
# # allow_unconfirmed_access_for = 0.days
|
||||
# confirmation_period_valid? # will always return false
|
||||
#
|
||||
# # allow_unconfirmed_access_for = nil
|
||||
# confirmation_period_valid? # will always return true
|
||||
#
|
||||
def confirmation_period_valid?
|
||||
confirmation_sent_at && confirmation_sent_at.utc >= self.class.allow_unconfirmed_access_for.ago
|
||||
self.class.allow_unconfirmed_access_for.nil? || (confirmation_sent_at && confirmation_sent_at.utc >= self.class.allow_unconfirmed_access_for.ago)
|
||||
end
|
||||
|
||||
# Checks if the user confirmation happens before the token becomes invalid
|
||||
# Examples:
|
||||
#
|
||||
# # confirm_within = 3.days and confirmation_sent_at = 2.days.ago
|
||||
# confirmation_period_expired? # returns false
|
||||
#
|
||||
# # confirm_within = 3.days and confirmation_sent_at = 4.days.ago
|
||||
# confirmation_period_expired? # returns true
|
||||
#
|
||||
# # confirm_within = nil
|
||||
# confirmation_period_expired? # will always return false
|
||||
#
|
||||
def confirmation_period_expired?
|
||||
self.class.confirm_within && (Time.now > self.confirmation_sent_at + self.class.confirm_within )
|
||||
end
|
||||
|
||||
# Checks whether the record requires any confirmation.
|
||||
def pending_any_confirmation
|
||||
if !confirmed? || pending_reconfirmation?
|
||||
if (!confirmed? || pending_reconfirmation?)
|
||||
yield
|
||||
else
|
||||
self.errors.add(:email, :already_confirmed)
|
||||
@@ -166,10 +215,12 @@ module Devise
|
||||
end
|
||||
end
|
||||
|
||||
# Generates a new random token for confirmation, and stores the time
|
||||
# this token is being generated
|
||||
# Generates a new random token for confirmation, and stores
|
||||
# the time this token is being generated
|
||||
def generate_confirmation_token
|
||||
self.confirmation_token = self.class.confirmation_token
|
||||
raw, enc = Devise.token_generator.generate(self.class, :confirmation_token)
|
||||
@raw_confirmation_token = raw
|
||||
self.confirmation_token = enc
|
||||
self.confirmation_sent_at = Time.now.utc
|
||||
end
|
||||
|
||||
@@ -177,25 +228,28 @@ module Devise
|
||||
generate_confirmation_token && save(:validate => false)
|
||||
end
|
||||
|
||||
def after_password_reset
|
||||
super
|
||||
confirm! unless confirmed?
|
||||
end
|
||||
|
||||
def postpone_email_change_until_confirmation
|
||||
def postpone_email_change_until_confirmation_and_regenerate_confirmation_token
|
||||
@reconfirmation_required = true
|
||||
self.unconfirmed_email = self.email
|
||||
self.email = self.email_was
|
||||
generate_confirmation_token
|
||||
end
|
||||
|
||||
def postpone_email_change?
|
||||
postpone = self.class.reconfirmable && email_changed? && !@bypass_postpone
|
||||
@bypass_postpone = nil
|
||||
postpone = self.class.reconfirmable && email_changed? && !@bypass_confirmation_postpone && !self.email.blank?
|
||||
@bypass_confirmation_postpone = false
|
||||
postpone
|
||||
end
|
||||
|
||||
def reconfirmation_required?
|
||||
self.class.reconfirmable && @reconfirmation_required
|
||||
self.class.reconfirmable && @reconfirmation_required && !self.email.blank?
|
||||
end
|
||||
|
||||
def send_confirmation_notification?
|
||||
confirmation_required? && !@skip_confirmation_notification && !self.email.blank?
|
||||
end
|
||||
|
||||
def after_confirmation
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
@@ -208,7 +262,7 @@ module Devise
|
||||
unless confirmable.try(:persisted?)
|
||||
confirmable = find_or_initialize_with_errors(confirmation_keys, attributes, :not_found)
|
||||
end
|
||||
confirmable.resend_confirmation_token if confirmable.persisted?
|
||||
confirmable.resend_confirmation_instructions if confirmable.persisted?
|
||||
confirmable
|
||||
end
|
||||
|
||||
@@ -217,14 +271,17 @@ module Devise
|
||||
# If the user is already confirmed, create an error for the user
|
||||
# Options must have the confirmation_token
|
||||
def confirm_by_token(confirmation_token)
|
||||
confirmable = find_or_initialize_with_error_by(:confirmation_token, confirmation_token)
|
||||
confirmable.confirm! if confirmable.persisted?
|
||||
confirmable
|
||||
end
|
||||
original_token = confirmation_token
|
||||
confirmation_token = Devise.token_generator.digest(self, :confirmation_token, confirmation_token)
|
||||
|
||||
# Generate a token checking if one does not already exist in the database.
|
||||
def confirmation_token
|
||||
generate_token(:confirmation_token)
|
||||
confirmable = find_or_initialize_with_error_by(:confirmation_token, confirmation_token)
|
||||
if !confirmable.persisted? && Devise.allow_insecure_token_lookup
|
||||
confirmable = find_or_initialize_with_error_by(:confirmation_token, original_token)
|
||||
end
|
||||
|
||||
confirmable.confirm! if confirmable.persisted?
|
||||
confirmable.confirmation_token = original_token
|
||||
confirmable
|
||||
end
|
||||
|
||||
# Find a record for confirmation by unconfirmed email field
|
||||
@@ -235,7 +292,7 @@ module Devise
|
||||
find_or_initialize_with_errors(unconfirmed_required_attributes, unconfirmed_attributes, :not_found)
|
||||
end
|
||||
|
||||
Devise::Models.config(self, :allow_unconfirmed_access_for, :confirmation_keys, :reconfirmable)
|
||||
Devise::Models.config(self, :allow_unconfirmed_access_for, :confirmation_keys, :reconfirmable, :confirm_within)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -64,7 +64,7 @@ module Devise
|
||||
result = if valid_password?(current_password)
|
||||
update_attributes(params, *options)
|
||||
else
|
||||
self.attributes = params
|
||||
self.assign_attributes(params, *options)
|
||||
self.valid?
|
||||
self.errors.add(:current_password, current_password.blank? ? :blank : :invalid)
|
||||
false
|
||||
@@ -75,13 +75,13 @@ module Devise
|
||||
end
|
||||
|
||||
# Updates record attributes without asking for the current password.
|
||||
# Never allows to change the current password. If you are using this
|
||||
# Never allows a change to the current password. If you are using this
|
||||
# method, you should probably override this method to protect other
|
||||
# attributes you would not like to be updated without a password.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# def update_without_password(params={})
|
||||
# def update_without_password(params, *options)
|
||||
# params.delete(:email)
|
||||
# super(params)
|
||||
# end
|
||||
@@ -95,6 +95,21 @@ module Devise
|
||||
result
|
||||
end
|
||||
|
||||
# Destroy record when :current_password matches, otherwise returns
|
||||
# error on :current_password. It also automatically rejects
|
||||
# :current_password if it is blank.
|
||||
def destroy_with_password(current_password)
|
||||
result = if valid_password?(current_password)
|
||||
destroy
|
||||
else
|
||||
self.valid?
|
||||
self.errors.add(:current_password, current_password.blank? ? :blank : :invalid)
|
||||
false
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
def after_database_authentication
|
||||
end
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ module Devise
|
||||
def self.required_fields(klass)
|
||||
attributes = []
|
||||
attributes << :failed_attempts if klass.lock_strategy_enabled?(:failed_attempts)
|
||||
attributes << :unlock_at if klass.unlock_strategy_enabled?(:time)
|
||||
attributes << :locked_at if klass.unlock_strategy_enabled?(:time)
|
||||
attributes << :unlock_token if klass.unlock_strategy_enabled?(:email)
|
||||
|
||||
attributes
|
||||
@@ -38,11 +38,10 @@ module Devise
|
||||
self.locked_at = Time.now.utc
|
||||
|
||||
if unlock_strategy_enabled?(:email)
|
||||
generate_unlock_token
|
||||
send_unlock_instructions
|
||||
else
|
||||
save(:validate => false)
|
||||
end
|
||||
|
||||
save(:validate => false)
|
||||
end
|
||||
|
||||
# Unlock a user by cleaning locked_at and failed_attempts.
|
||||
@@ -55,16 +54,20 @@ module Devise
|
||||
|
||||
# Verifies whether a user is locked or not.
|
||||
def access_locked?
|
||||
locked_at && !lock_expired?
|
||||
!!locked_at && !lock_expired?
|
||||
end
|
||||
|
||||
# Send unlock instructions by email
|
||||
def send_unlock_instructions
|
||||
self.devise_mailer.unlock_instructions(self).deliver
|
||||
raw, enc = Devise.token_generator.generate(self.class, :unlock_token)
|
||||
self.unlock_token = enc
|
||||
self.save(:validate => false)
|
||||
send_devise_notification(:unlock_instructions, raw, {})
|
||||
raw
|
||||
end
|
||||
|
||||
# Resend the unlock instructions if the user is locked.
|
||||
def resend_unlock_token
|
||||
def resend_unlock_instructions
|
||||
if_access_locked { send_unlock_instructions }
|
||||
end
|
||||
|
||||
@@ -105,7 +108,11 @@ module Devise
|
||||
end
|
||||
|
||||
def unauthenticated_message
|
||||
if lock_strategy_enabled?(:failed_attempts) && attempts_exceeded?
|
||||
# If set to paranoid mode, do not show the locked message because it
|
||||
# leaks the existence of an account.
|
||||
if Devise.paranoid
|
||||
super
|
||||
elsif lock_strategy_enabled?(:failed_attempts) && attempts_exceeded?
|
||||
:locked
|
||||
else
|
||||
super
|
||||
@@ -118,11 +125,6 @@ module Devise
|
||||
self.failed_attempts > self.class.maximum_attempts
|
||||
end
|
||||
|
||||
# Generates unlock token
|
||||
def generate_unlock_token
|
||||
self.unlock_token = self.class.unlock_token
|
||||
end
|
||||
|
||||
# Tells if the lock is expired if :time unlock strategy is active
|
||||
def lock_expired?
|
||||
if unlock_strategy_enabled?(:time)
|
||||
@@ -138,19 +140,19 @@ module Devise
|
||||
if access_locked?
|
||||
yield
|
||||
else
|
||||
self.errors.add(:email, :not_locked)
|
||||
self.errors.add(Devise.unlock_keys.first, :not_locked)
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
# Attempt to find a user by its email. If a record is found, send new
|
||||
# Attempt to find a user by its unlock keys. 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
|
||||
# Options must contain the user's unlock keys
|
||||
def send_unlock_instructions(attributes={})
|
||||
lockable = find_or_initialize_with_errors(unlock_keys, attributes, :not_found)
|
||||
lockable.resend_unlock_token if lockable.persisted?
|
||||
lockable.resend_unlock_instructions if lockable.persisted?
|
||||
lockable
|
||||
end
|
||||
|
||||
@@ -159,8 +161,16 @@ module Devise
|
||||
# If the user is not locked, creates an error for the user
|
||||
# Options must have the unlock_token
|
||||
def unlock_access_by_token(unlock_token)
|
||||
original_token = unlock_token
|
||||
unlock_token = Devise.token_generator.digest(self, :unlock_token, unlock_token)
|
||||
|
||||
lockable = find_or_initialize_with_error_by(:unlock_token, unlock_token)
|
||||
if !lockable.persisted? && Devise.allow_insecure_token_lookup
|
||||
lockable = find_or_initialize_with_error_by(:unlock_token, original_token)
|
||||
end
|
||||
|
||||
lockable.unlock_access! if lockable.persisted?
|
||||
lockable.unlock_token = original_token
|
||||
lockable
|
||||
end
|
||||
|
||||
@@ -174,10 +184,6 @@ module Devise
|
||||
self.lock_strategy == strategy
|
||||
end
|
||||
|
||||
def unlock_token
|
||||
Devise.friendly_token
|
||||
end
|
||||
|
||||
Devise::Models.config(self, :maximum_attempts, :lock_strategy, :unlock_strategy, :unlock_in, :unlock_keys)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,7 +8,7 @@ module Devise
|
||||
#
|
||||
# Oauthable adds the following options to devise_for:
|
||||
#
|
||||
# * +omniauth_providers+: Which providers are avaialble to this model. It expects an array:
|
||||
# * +omniauth_providers+: Which providers are available to this model. It expects an array:
|
||||
#
|
||||
# devise_for :database_authenticatable, :omniauthable, :omniauth_providers => [:twitter]
|
||||
#
|
||||
@@ -24,4 +24,4 @@ module Devise
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
module Devise
|
||||
module Models
|
||||
|
||||
# Recoverable takes care of reseting the user password and send reset instructions.
|
||||
# Recoverable takes care of resetting the user password and send reset instructions.
|
||||
#
|
||||
# ==Options
|
||||
#
|
||||
@@ -42,10 +42,17 @@ module Devise
|
||||
save
|
||||
end
|
||||
|
||||
# Resets reset password token and send reset password instructions by email
|
||||
# Resets reset password token and send reset password instructions by email.
|
||||
# Returns the token sent in the e-mail.
|
||||
def send_reset_password_instructions
|
||||
generate_reset_password_token! if should_generate_reset_token?
|
||||
self.devise_mailer.reset_password_instructions(self).deliver
|
||||
raw, enc = Devise.token_generator.generate(self.class, :reset_password_token)
|
||||
|
||||
self.reset_password_token = enc
|
||||
self.reset_password_sent_at = Time.now.utc
|
||||
self.save(:validate => false)
|
||||
|
||||
send_devise_notification(:reset_password_instructions, raw, {})
|
||||
raw
|
||||
end
|
||||
|
||||
# Checks if the reset password token sent is within the limit time.
|
||||
@@ -74,23 +81,6 @@ module Devise
|
||||
|
||||
protected
|
||||
|
||||
def should_generate_reset_token?
|
||||
reset_password_token.nil? || !reset_password_period_valid?
|
||||
end
|
||||
|
||||
# Generates a new random token for reset password
|
||||
def generate_reset_password_token
|
||||
self.reset_password_token = self.class.reset_password_token
|
||||
self.reset_password_sent_at = Time.now.utc
|
||||
self.reset_password_token
|
||||
end
|
||||
|
||||
# Resets the reset password token with and save the record without
|
||||
# validating
|
||||
def generate_reset_password_token!
|
||||
generate_reset_password_token && save(:validate => false)
|
||||
end
|
||||
|
||||
# Removes reset_password token
|
||||
def clear_reset_password_token
|
||||
self.reset_password_token = nil
|
||||
@@ -102,9 +92,9 @@ module Devise
|
||||
|
||||
module ClassMethods
|
||||
# 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
|
||||
# password instructions to it. If user is not found, returns a new user
|
||||
# with an email not found error.
|
||||
# Attributes must contain the user email
|
||||
# Attributes must contain the user's email
|
||||
def send_reset_password_instructions(attributes={})
|
||||
recoverable = find_or_initialize_with_errors(reset_password_keys, attributes, :not_found)
|
||||
recoverable.send_reset_password_instructions if recoverable.persisted?
|
||||
@@ -122,7 +112,14 @@ module Devise
|
||||
# containing an error in reset_password_token attribute.
|
||||
# Attributes must contain reset_password_token, password and confirmation
|
||||
def reset_password_by_token(attributes={})
|
||||
recoverable = find_or_initialize_with_error_by(:reset_password_token, attributes[:reset_password_token])
|
||||
original_token = attributes[:reset_password_token]
|
||||
reset_password_token = Devise.token_generator.digest(self, :reset_password_token, original_token)
|
||||
|
||||
recoverable = find_or_initialize_with_error_by(:reset_password_token, reset_password_token)
|
||||
if !recoverable.persisted? && Devise.allow_insecure_token_lookup
|
||||
recoverable = find_or_initialize_with_error_by(:reset_password_token, original_token)
|
||||
end
|
||||
|
||||
if recoverable.persisted?
|
||||
if recoverable.reset_password_period_valid?
|
||||
recoverable.reset_password!(attributes[:password], attributes[:password_confirmation])
|
||||
@@ -130,6 +127,8 @@ module Devise
|
||||
recoverable.errors.add(:reset_password_token, :expired)
|
||||
end
|
||||
end
|
||||
|
||||
recoverable.reset_password_token = original_token
|
||||
recoverable
|
||||
end
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ module Devise
|
||||
def remember_me!(extend_period=false)
|
||||
self.remember_token = self.class.remember_token if generate_remember_token?
|
||||
self.remember_created_at = Time.now.utc if generate_remember_timestamp?(extend_period)
|
||||
save(:validate => false)
|
||||
save(:validate => false) if self.changed?
|
||||
end
|
||||
|
||||
# If the record is persisted, remove the remember token (but only if
|
||||
@@ -110,12 +110,16 @@ module Devise
|
||||
# Recreate the user based on the stored cookie
|
||||
def serialize_from_cookie(id, remember_token)
|
||||
record = to_adapter.get(id)
|
||||
record if record && record.rememberable_value == remember_token && !record.remember_expired?
|
||||
record if record && !record.remember_expired? &&
|
||||
Devise.secure_compare(record.rememberable_value, remember_token)
|
||||
end
|
||||
|
||||
# Generate a token checking if one does not already exist in the database.
|
||||
def remember_token #:nodoc:
|
||||
generate_token(:remember_token)
|
||||
loop do
|
||||
token = Devise.friendly_token
|
||||
break token unless to_adapter.find_first({ :remember_token => token })
|
||||
end
|
||||
end
|
||||
|
||||
Devise::Models.config(self, :remember_for, :extend_remember_period, :rememberable_options)
|
||||
|
||||
@@ -2,7 +2,7 @@ require 'devise/hooks/timeoutable'
|
||||
|
||||
module Devise
|
||||
module Models
|
||||
# Timeoutable takes care of veryfing whether a user session has already
|
||||
# Timeoutable takes care of verifyng whether a user session has already
|
||||
# expired or not. When a session expires after the configured time, the user
|
||||
# will be asked for credentials again, it means, he/she will be redirected
|
||||
# to the sign in page.
|
||||
@@ -37,7 +37,7 @@ module Devise
|
||||
private
|
||||
|
||||
def remember_exists_and_not_expired?
|
||||
return false unless respond_to?(:remember_created_at)
|
||||
return false unless respond_to?(:remember_created_at) && respond_to?(:remember_expired?)
|
||||
remember_created_at && !remember_expired?
|
||||
end
|
||||
|
||||
|
||||
@@ -18,6 +18,18 @@ module Devise
|
||||
# If you want to delete the token after it is used, you can do so in the
|
||||
# after_token_authentication callback.
|
||||
#
|
||||
# == APIs
|
||||
#
|
||||
# If you are using token authentication with APIs and using trackable. Every
|
||||
# request will be considered as a new sign in (since there is no session in
|
||||
# APIs). You can disable this by creating a before filter as follow:
|
||||
#
|
||||
# before_filter :skip_trackable
|
||||
#
|
||||
# def skip_trackable
|
||||
# request.env['devise.skip_trackable'] = true
|
||||
# end
|
||||
#
|
||||
# == Options
|
||||
#
|
||||
# TokenAuthenticatable adds the following options to devise_for:
|
||||
@@ -67,7 +79,10 @@ module Devise
|
||||
|
||||
# Generate a token checking if one does not already exist in the database.
|
||||
def authentication_token
|
||||
generate_token(:authentication_token)
|
||||
loop do
|
||||
token = Devise.friendly_token
|
||||
break token unless to_adapter.find_first({ :authentication_token => token })
|
||||
end
|
||||
end
|
||||
|
||||
Devise::Models.config(self, :token_authentication_key, :expire_auth_token_on_timeout)
|
||||
|
||||
@@ -20,7 +20,7 @@ module Devise
|
||||
self.last_sign_in_at = old_current || new_current
|
||||
self.current_sign_in_at = new_current
|
||||
|
||||
old_current, new_current = self.current_sign_in_ip, request.ip
|
||||
old_current, new_current = self.current_sign_in_ip, request.remote_ip
|
||||
self.last_sign_in_ip = old_current || new_current
|
||||
self.current_sign_in_ip = new_current
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ module Devise
|
||||
# Validatable adds the following options to devise_for:
|
||||
#
|
||||
# * +email_regexp+: the regular expression used to validate e-mails;
|
||||
# * +password_length+: a range expressing password length. Defaults to 6..128.
|
||||
# * +password_length+: a range expressing password length. Defaults to 8..128.
|
||||
#
|
||||
module Validatable
|
||||
# All validations used by this module.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
begin
|
||||
require "omniauth"
|
||||
require "omniauth/version"
|
||||
rescue LoadError => e
|
||||
rescue LoadError
|
||||
warn "Could not load 'omniauth'. Please ensure you have the omniauth gem >= 1.0.0 installed and listed in your Gemfile."
|
||||
raise
|
||||
end
|
||||
|
||||
@@ -2,21 +2,6 @@ module Devise
|
||||
module OmniAuth
|
||||
module UrlHelpers
|
||||
def self.define_helpers(mapping)
|
||||
return unless mapping.omniauthable?
|
||||
|
||||
class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1
|
||||
def #{mapping.name}_omniauth_authorize_path(provider, params = {})
|
||||
if Devise.omniauth_configs[provider.to_sym]
|
||||
script_name = request.env["SCRIPT_NAME"]
|
||||
|
||||
path = "\#{script_name}/#{mapping.path}/auth/\#{provider}\".squeeze("/")
|
||||
path << '?' + params.to_param if params.present?
|
||||
path
|
||||
else
|
||||
raise ArgumentError, "Could not find omniauth provider \#{provider.inspect}"
|
||||
end
|
||||
end
|
||||
URL_HELPERS
|
||||
end
|
||||
|
||||
def omniauth_authorize_path(resource_or_scope, *args)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
module Devise
|
||||
class ParamFilter
|
||||
class ParameterFilter
|
||||
def initialize(case_insensitive_keys, strip_whitespace_keys)
|
||||
@case_insensitive_keys = case_insensitive_keys || []
|
||||
@strip_whitespace_keys = strip_whitespace_keys || []
|
||||
@@ -8,16 +8,16 @@ module Devise
|
||||
def filter(conditions)
|
||||
conditions = stringify_params(conditions.dup)
|
||||
|
||||
@case_insensitive_keys.each do |k|
|
||||
value = conditions[k]
|
||||
next unless value.respond_to?(:downcase)
|
||||
conditions[k] = value.downcase
|
||||
end
|
||||
conditions.merge!(filtered_hash_by_method_for_given_keys(conditions.dup, :downcase, @case_insensitive_keys))
|
||||
conditions.merge!(filtered_hash_by_method_for_given_keys(conditions.dup, :strip, @strip_whitespace_keys))
|
||||
|
||||
@strip_whitespace_keys.each do |k|
|
||||
conditions
|
||||
end
|
||||
|
||||
def filtered_hash_by_method_for_given_keys(conditions, method, condition_keys)
|
||||
condition_keys.each do |k|
|
||||
value = conditions[k]
|
||||
next unless value.respond_to?(:strip)
|
||||
conditions[k] = value.strip
|
||||
conditions[k] = value.send(method) if value.respond_to?(method)
|
||||
end
|
||||
|
||||
conditions
|
||||
@@ -33,9 +33,8 @@ module Devise
|
||||
|
||||
private
|
||||
|
||||
# Determine which values should be transformed to string or passed as-is to the query builder underneath
|
||||
def param_requires_string_conversion?(value)
|
||||
[Fixnum, TrueClass, FalseClass, Regexp].none? {|clz| value.is_a? clz }
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
93
lib/devise/parameter_sanitizer.rb
Normal file
93
lib/devise/parameter_sanitizer.rb
Normal file
@@ -0,0 +1,93 @@
|
||||
module Devise
|
||||
class BaseSanitizer
|
||||
attr_reader :params, :resource_name, :resource_class
|
||||
|
||||
def initialize(resource_class, resource_name, params)
|
||||
@resource_class = resource_class
|
||||
@resource_name = resource_name
|
||||
@params = params
|
||||
@blocks = Hash.new
|
||||
end
|
||||
|
||||
def for(kind, &block)
|
||||
if block_given?
|
||||
@blocks[kind] = block
|
||||
else
|
||||
default_for(kind)
|
||||
end
|
||||
end
|
||||
|
||||
def sanitize(kind)
|
||||
if block = @blocks[kind]
|
||||
block.call(default_params)
|
||||
else
|
||||
default_sanitize(kind)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def default_for(kind)
|
||||
raise ArgumentError, "a block is expected in Devise base sanitizer"
|
||||
end
|
||||
|
||||
def default_sanitize(kind)
|
||||
default_params
|
||||
end
|
||||
|
||||
def default_params
|
||||
params.fetch(resource_name, {})
|
||||
end
|
||||
end
|
||||
|
||||
class ParameterSanitizer < BaseSanitizer
|
||||
def initialize(*)
|
||||
super
|
||||
@permitted = Hash.new { |h,k| h[k] = attributes_for(k) }
|
||||
end
|
||||
|
||||
def sign_in
|
||||
default_params.permit self.for(:sign_in)
|
||||
end
|
||||
|
||||
def sign_up
|
||||
default_params.permit self.for(:sign_up)
|
||||
end
|
||||
|
||||
def account_update
|
||||
default_params.permit self.for(:account_update)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Change for(kind) to return the values in the @permitted
|
||||
# hash, allowing the developer to customize at runtime.
|
||||
def default_for(kind)
|
||||
@permitted[kind] || raise("No sanitizer provided for #{kind}")
|
||||
end
|
||||
|
||||
def default_sanitize(kind)
|
||||
if respond_to?(kind, true)
|
||||
send(kind)
|
||||
else
|
||||
raise NotImplementedError, "Devise doesn't know how to sanitize parameters for #{kind}"
|
||||
end
|
||||
end
|
||||
|
||||
def attributes_for(kind)
|
||||
case kind
|
||||
when :sign_in
|
||||
auth_keys + [:password, :remember_me]
|
||||
when :sign_up
|
||||
auth_keys + [:password, :password_confirmation]
|
||||
when :account_update
|
||||
auth_keys + [:password, :password_confirmation, :current_password]
|
||||
end
|
||||
end
|
||||
|
||||
def auth_keys
|
||||
@auth_keys ||= @resource_class.authentication_keys.respond_to?(:keys) ?
|
||||
@resource_class.authentication_keys.keys : @resource_class.authentication_keys
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -29,21 +29,17 @@ module Devise
|
||||
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"
|
||||
initializer "devise.secret_key" do
|
||||
Devise.token_generator ||=
|
||||
if secret_key = Devise.secret_key
|
||||
Devise::TokenGenerator.new(
|
||||
Devise::CachingKeyGenerator.new(Devise::KeyGenerator.new(secret_key))
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
initializer "devise.fix_routes_proxy_missing_respond_to_bug" do
|
||||
# We can get rid of this once we support only Rails > 3.2
|
||||
# Deprecate: Remove once we move to Rails 4 only.
|
||||
ActionDispatch::Routing::RoutesProxy.class_eval do
|
||||
def respond_to?(method, include_private = false)
|
||||
super || routes.url_helpers.respond_to?(method)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
require "active_support/core_ext/object/try"
|
||||
require "active_support/core_ext/hash/slice"
|
||||
|
||||
module ActionDispatch::Routing
|
||||
class RouteSet #:nodoc:
|
||||
@@ -42,20 +43,20 @@ module ActionDispatch::Routing
|
||||
# needed routes:
|
||||
#
|
||||
# # Session routes for Authenticatable (default)
|
||||
# new_user_session GET /users/sign_in {:controller=>"devise/sessions", :action=>"new"}
|
||||
# user_session POST /users/sign_in {:controller=>"devise/sessions", :action=>"create"}
|
||||
# destroy_user_session GET /users/sign_out {:controller=>"devise/sessions", :action=>"destroy"}
|
||||
# new_user_session GET /users/sign_in {:controller=>"devise/sessions", :action=>"new"}
|
||||
# user_session POST /users/sign_in {:controller=>"devise/sessions", :action=>"create"}
|
||||
# destroy_user_session DELETE /users/sign_out {:controller=>"devise/sessions", :action=>"destroy"}
|
||||
#
|
||||
# # Password routes for Recoverable, if User model has :recoverable configured
|
||||
# new_user_password GET /users/password/new(.:format) {:controller=>"devise/passwords", :action=>"new"}
|
||||
# edit_user_password GET /users/password/edit(.:format) {:controller=>"devise/passwords", :action=>"edit"}
|
||||
# user_password PUT /users/password(.:format) {:controller=>"devise/passwords", :action=>"update"}
|
||||
# POST /users/password(.:format) {:controller=>"devise/passwords", :action=>"create"}
|
||||
# new_user_password GET /users/password/new(.:format) {:controller=>"devise/passwords", :action=>"new"}
|
||||
# edit_user_password GET /users/password/edit(.:format) {:controller=>"devise/passwords", :action=>"edit"}
|
||||
# user_password PUT /users/password(.:format) {:controller=>"devise/passwords", :action=>"update"}
|
||||
# POST /users/password(.:format) {:controller=>"devise/passwords", :action=>"create"}
|
||||
#
|
||||
# # Confirmation routes for Confirmable, if User model has :confirmable configured
|
||||
# new_user_confirmation GET /users/confirmation/new(.:format) {:controller=>"devise/confirmations", :action=>"new"}
|
||||
# user_confirmation GET /users/confirmation(.:format) {:controller=>"devise/confirmations", :action=>"show"}
|
||||
# POST /users/confirmation(.:format) {:controller=>"devise/confirmations", :action=>"create"}
|
||||
# new_user_confirmation GET /users/confirmation/new(.:format) {:controller=>"devise/confirmations", :action=>"new"}
|
||||
# user_confirmation GET /users/confirmation(.:format) {:controller=>"devise/confirmations", :action=>"show"}
|
||||
# POST /users/confirmation(.:format) {:controller=>"devise/confirmations", :action=>"create"}
|
||||
#
|
||||
# ==== Options
|
||||
#
|
||||
@@ -79,7 +80,8 @@ module ActionDispatch::Routing
|
||||
# * :path_names => configure different path names to overwrite defaults :sign_in, :sign_out, :sign_up,
|
||||
# :password, :confirmation, :unlock.
|
||||
#
|
||||
# devise_for :users, :path_names => { :sign_in => 'login', :sign_out => 'logout', :password => 'secret', :confirmation => 'verification' }
|
||||
# devise_for :users, :path_names => { :sign_in => 'login', :sign_out => 'logout',
|
||||
# :password => 'secret', :confirmation => 'verification', registration: 'register }
|
||||
#
|
||||
# * :controllers => the controller which should be used. All routes by default points to Devise controllers.
|
||||
# However, if you want them to point to custom controller, you should do:
|
||||
@@ -182,7 +184,7 @@ module ActionDispatch::Routing
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# In order to get Devise to recognize the deactivate action, your devise_for entry should look like this,
|
||||
# In order to get Devise to recognize the deactivate action, your devise_scope entry should look like this:
|
||||
#
|
||||
# devise_scope :owner do
|
||||
# post "deactivate", :to => "registrations#deactivate", :as => "deactivate_registration"
|
||||
@@ -190,6 +192,7 @@ module ActionDispatch::Routing
|
||||
#
|
||||
def devise_for(*resources)
|
||||
@devise_finalized = false
|
||||
raise_no_secret_key unless Devise.secret_key
|
||||
options = resources.extract_options!
|
||||
|
||||
options[:as] ||= @scope[:as] if @scope[:as].present?
|
||||
@@ -221,14 +224,6 @@ module ActionDispatch::Routing
|
||||
routes = mapping.used_routes
|
||||
|
||||
devise_scope mapping.name do
|
||||
if block_given?
|
||||
ActiveSupport::Deprecation.warn "Passing a block to devise_for is deprecated. " \
|
||||
"Please remove the block from devise_for (only the block, the call to " \
|
||||
"devise_for must still exist) and call devise_scope :#{mapping.name} do ... end " \
|
||||
"with the block instead", caller
|
||||
yield
|
||||
end
|
||||
|
||||
with_devise_exclusive_scope mapping.fullpath, mapping.name, options do
|
||||
routes.each { |mod| send("devise_#{mod}", mapping, mapping.controllers) }
|
||||
end
|
||||
@@ -236,7 +231,9 @@ module ActionDispatch::Routing
|
||||
end
|
||||
end
|
||||
|
||||
# Allow you to add authentication request from the router:
|
||||
# Allow you to add authentication request from the router.
|
||||
# Takes an optional scope and block to provide constraints
|
||||
# on the model instance itself.
|
||||
#
|
||||
# authenticate do
|
||||
# resources :post
|
||||
@@ -246,35 +243,36 @@ module ActionDispatch::Routing
|
||||
# resources :users
|
||||
# end
|
||||
#
|
||||
def authenticate(scope=nil)
|
||||
constraint = lambda do |request|
|
||||
request.env["warden"].authenticate!(:scope => scope)
|
||||
end
|
||||
|
||||
constraints(constraint) do
|
||||
# authenticate :user, lambda {|u| u.role == "admin"} do
|
||||
# root :to => "admin/dashboard#show", :as => :user_root
|
||||
# end
|
||||
#
|
||||
def authenticate(scope=nil, block=nil)
|
||||
constraints_for(:authenticate!, scope, block) do
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
# Allow you to route based on whether a scope is authenticated. You
|
||||
# can optionally specify which scope.
|
||||
# can optionally specify which scope and a block. The block accepts
|
||||
# a model and allows extra constraints to be done on the instance.
|
||||
#
|
||||
# authenticated :admin do
|
||||
# root :to => 'admin/dashboard#show'
|
||||
# root :to => 'admin/dashboard#show', :as => :admin_root
|
||||
# end
|
||||
#
|
||||
# authenticated do
|
||||
# root :to => 'dashboard#show'
|
||||
# root :to => 'dashboard#show', :as => :authenticated_root
|
||||
# end
|
||||
#
|
||||
# authenticated :user, lambda {|u| u.role == "admin"} do
|
||||
# root :to => "admin/dashboard#show", :as => :user_root
|
||||
# end
|
||||
#
|
||||
# root :to => 'landing#show'
|
||||
#
|
||||
def authenticated(scope=nil)
|
||||
constraint = lambda do |request|
|
||||
request.env["warden"].authenticate? :scope => scope
|
||||
end
|
||||
|
||||
constraints(constraint) do
|
||||
def authenticated(scope=nil, block=nil)
|
||||
constraints_for(:authenticate?, scope, block) do
|
||||
yield
|
||||
end
|
||||
end
|
||||
@@ -317,7 +315,7 @@ module ActionDispatch::Routing
|
||||
# good and working example.
|
||||
#
|
||||
# devise_scope :user do
|
||||
# match "/some/route" => "some_devise_controller"
|
||||
# get "/some/route" => "some_devise_controller"
|
||||
# end
|
||||
# devise_for :users
|
||||
#
|
||||
@@ -367,16 +365,67 @@ module ActionDispatch::Routing
|
||||
:cancel => mapping.path_names[:cancel]
|
||||
}
|
||||
|
||||
resource :registration, :only => [:new, :create, :edit, :update, :destroy], :path => mapping.path_names[:registration],
|
||||
:path_names => path_names, :controller => controllers[:registrations] do
|
||||
options = {
|
||||
:only => [:new, :create, :edit, :update, :destroy],
|
||||
:path => mapping.path_names[:registration],
|
||||
:path_names => path_names,
|
||||
:controller => controllers[:registrations]
|
||||
}
|
||||
|
||||
resource :registration, options do
|
||||
get :cancel
|
||||
end
|
||||
end
|
||||
|
||||
def devise_omniauth_callback(mapping, controllers) #:nodoc:
|
||||
path, @scope[:path] = @scope[:path], nil
|
||||
path_prefix = "/#{mapping.path}/auth".squeeze("/")
|
||||
path_prefix = Devise.omniauth_path_prefix || "/#{mapping.path}/auth".squeeze("/")
|
||||
set_omniauth_path_prefix!(path_prefix)
|
||||
|
||||
providers = Regexp.union(mapping.to.omniauth_providers.map(&:to_s))
|
||||
|
||||
match "#{path_prefix}/:provider",
|
||||
:constraints => { :provider => providers },
|
||||
:to => "#{controllers[:omniauth_callbacks]}#passthru",
|
||||
:as => :omniauth_authorize,
|
||||
:via => [:get, :post]
|
||||
|
||||
match "#{path_prefix}/:action/callback",
|
||||
:constraints => { :action => providers },
|
||||
:to => controllers[:omniauth_callbacks],
|
||||
:as => :omniauth_callback,
|
||||
:via => [:get, :post]
|
||||
ensure
|
||||
@scope[:path] = path
|
||||
end
|
||||
|
||||
DEVISE_SCOPE_KEYS = [:as, :path, :module, :constraints, :defaults, :options]
|
||||
|
||||
def with_devise_exclusive_scope(new_path, new_as, options) #:nodoc:
|
||||
old = {}
|
||||
DEVISE_SCOPE_KEYS.each { |k| old[k] = @scope[k] }
|
||||
|
||||
new = { :as => new_as, :path => new_path, :module => nil }
|
||||
new.merge!(options.slice(:constraints, :defaults, :options))
|
||||
|
||||
@scope.merge!(new)
|
||||
yield
|
||||
ensure
|
||||
@scope.merge!(old)
|
||||
end
|
||||
|
||||
def constraints_for(method_to_apply, scope=nil, block=nil)
|
||||
constraint = lambda do |request|
|
||||
request.env['warden'].send(method_to_apply, :scope => scope) &&
|
||||
(block.nil? || block.call(request.env["warden"].user(scope)))
|
||||
end
|
||||
|
||||
constraints(constraint) do
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
def set_omniauth_path_prefix!(path_prefix) #:nodoc:
|
||||
if ::OmniAuth.config.path_prefix && ::OmniAuth.config.path_prefix != path_prefix
|
||||
raise "Wrong OmniAuth configuration. If you are getting this exception, it means that either:\n\n" \
|
||||
"1) You are manually setting OmniAuth.config.path_prefix and it doesn't match the Devise one\n" \
|
||||
@@ -385,22 +434,16 @@ module ActionDispatch::Routing
|
||||
else
|
||||
::OmniAuth.config.path_prefix = path_prefix
|
||||
end
|
||||
|
||||
match "#{path_prefix}/:action/callback", :constraints => { :action => Regexp.union(mapping.to.omniauth_providers.map(&:to_s)) },
|
||||
:to => controllers[:omniauth_callbacks], :as => :omniauth_callback
|
||||
ensure
|
||||
@scope[:path] = path
|
||||
end
|
||||
|
||||
def with_devise_exclusive_scope(new_path, new_as, options) #:nodoc:
|
||||
old_as, old_path, old_module, old_constraints, old_defaults, old_options =
|
||||
*@scope.values_at(:as, :path, :module, :constraints, :defaults, :options)
|
||||
@scope[:as], @scope[:path], @scope[:module], @scope[:constraints], @scope[:defaults], @scope[:options] =
|
||||
new_as, new_path, nil, *options.values_at(:constraints, :defaults, :options)
|
||||
yield
|
||||
ensure
|
||||
@scope[:as], @scope[:path], @scope[:module], @scope[:constraints], @scope[:defaults], @scope[:options] =
|
||||
old_as, old_path, old_module, old_constraints, old_defaults, old_options
|
||||
def raise_no_secret_key #:nodoc:
|
||||
raise <<-ERROR
|
||||
Devise.secret_key was not set. Please add the following to your Devise initializer:
|
||||
|
||||
config.secret_key = '#{SecureRandom.hex(64)}'
|
||||
|
||||
Please ensure you restarted your application after installing Devise or setting the key.
|
||||
ERROR
|
||||
end
|
||||
|
||||
def raise_no_devise_method_error!(klass) #:nodoc:
|
||||
|
||||
@@ -3,41 +3,20 @@ module Warden::Mixins::Common
|
||||
@request ||= ActionDispatch::Request.new(env)
|
||||
end
|
||||
|
||||
# This is called internally by Warden on logout
|
||||
# Deprecate: Remove this check once we move to Rails 4 only.
|
||||
NULL_STORE =
|
||||
defined?(ActionController::RequestForgeryProtection::ProtectionMethods::NullSession::NullSessionHash) ?
|
||||
ActionController::RequestForgeryProtection::ProtectionMethods::NullSession::NullSessionHash : nil
|
||||
|
||||
def reset_session!
|
||||
request.reset_session
|
||||
# Calling reset_session on NULL_STORE causes it fail.
|
||||
# This is a bug that needs to be fixed in Rails.
|
||||
unless NULL_STORE && request.session.is_a?(NULL_STORE)
|
||||
request.reset_session
|
||||
end
|
||||
end
|
||||
|
||||
def cookies
|
||||
request.cookie_jar
|
||||
end
|
||||
end
|
||||
|
||||
class Warden::SessionSerializer
|
||||
def serialize(record)
|
||||
klass = record.class
|
||||
array = klass.serialize_into_session(record)
|
||||
array.unshift(klass.name)
|
||||
end
|
||||
|
||||
def deserialize(keys)
|
||||
klass_name, *args = keys
|
||||
|
||||
begin
|
||||
klass = ActiveSupport::Inflector.constantize(klass_name)
|
||||
if klass.respond_to? :serialize_from_session
|
||||
klass.serialize_from_session(*args)
|
||||
else
|
||||
Rails.logger.warn "[Devise] Stored serialized class #{klass_name} seems not to be Devise enabled anymore. Did you do that on purpose?"
|
||||
nil
|
||||
end
|
||||
rescue NameError => e
|
||||
if e.message =~ /uninitialized constant/
|
||||
Rails.logger.debug "[Devise] Trying to deserialize invalid class #{klass_name}"
|
||||
nil
|
||||
else
|
||||
raise
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,7 +9,7 @@ module Devise
|
||||
attr_accessor :authentication_hash, :authentication_type, :password
|
||||
|
||||
def store?
|
||||
!mapping.to.skip_session_storage.include?(authentication_type)
|
||||
super && !mapping.to.skip_session_storage.include?(authentication_type)
|
||||
end
|
||||
|
||||
def valid?
|
||||
@@ -18,17 +18,16 @@ module Devise
|
||||
|
||||
private
|
||||
|
||||
# Simply invokes valid_for_authentication? with the given block and deal with the result.
|
||||
# Receives a resource and check if it is valid by calling valid_for_authentication?
|
||||
# An optional block that will be triggered while validating can be optionally
|
||||
# given as parameter. Check Devise::Models::Authenticable.valid_for_authentication?
|
||||
# for more information.
|
||||
#
|
||||
# In case the resource can't be validated, it will fail with the given
|
||||
# unauthenticated_message.
|
||||
def validate(resource, &block)
|
||||
result = resource && resource.valid_for_authentication?(&block)
|
||||
|
||||
case result
|
||||
when Symbol, String
|
||||
ActiveSupport::Deprecation.warn "valid_for_authentication should return a boolean value"
|
||||
fail!(result)
|
||||
return false
|
||||
end
|
||||
|
||||
if result
|
||||
decorate(resource)
|
||||
true
|
||||
@@ -84,12 +83,12 @@ module Devise
|
||||
|
||||
# Extract the appropriate subhash for authentication from params.
|
||||
def params_auth_hash
|
||||
params[scope]
|
||||
end
|
||||
params[scope]
|
||||
end
|
||||
|
||||
# Extract a hash with attributes:values from the http params.
|
||||
def http_auth_hash
|
||||
keys = [authentication_keys.first, :password]
|
||||
keys = [http_authentication_key, :password]
|
||||
Hash[*keys.zip(decode_credentials).flatten]
|
||||
end
|
||||
|
||||
@@ -123,24 +122,27 @@ module Devise
|
||||
parse_authentication_key_values(request_values, request_keys)
|
||||
end
|
||||
|
||||
# Holds the authentication keys.
|
||||
def authentication_keys
|
||||
@authentication_keys ||= mapping.to.authentication_keys
|
||||
end
|
||||
|
||||
# Holds request keys.
|
||||
def http_authentication_key
|
||||
@http_authentication_key ||= mapping.to.http_authentication_key || case authentication_keys
|
||||
when Array then authentication_keys.first
|
||||
when Hash then authentication_keys.keys.first
|
||||
end
|
||||
end
|
||||
|
||||
def request_keys
|
||||
@request_keys ||= mapping.to.request_keys
|
||||
end
|
||||
|
||||
# Returns values from the request object.
|
||||
def request_values
|
||||
keys = request_keys.respond_to?(:keys) ? request_keys.keys : request_keys
|
||||
values = keys.map { |k| self.request.send(k) }
|
||||
Hash[keys.zip(values)]
|
||||
end
|
||||
|
||||
# Parse authentication keys considering if they should be enforced or not.
|
||||
def parse_authentication_key_values(hash, keys)
|
||||
keys.each do |key, enforce|
|
||||
value = hash[key].presence
|
||||
|
||||
@@ -2,6 +2,11 @@ module Devise
|
||||
module Strategies
|
||||
# Base strategy for Devise. Responsible for verifying correct scope and mapping.
|
||||
class Base < ::Warden::Strategies::Base
|
||||
# Whenever CSRF cannot be verified, we turn off any kind of storage
|
||||
def store?
|
||||
!env["devise.skip_storage"]
|
||||
end
|
||||
|
||||
# Checks if a valid scope was given for devise and find mapping based on this scope.
|
||||
def mapping
|
||||
@mapping ||= begin
|
||||
|
||||
@@ -6,12 +6,11 @@ module Devise
|
||||
class DatabaseAuthenticatable < Authenticatable
|
||||
def authenticate!
|
||||
resource = valid_password? && mapping.to.find_for_database_authentication(authentication_hash)
|
||||
return fail(:not_found_in_database) unless resource
|
||||
|
||||
if validate(resource){ resource.valid_password?(password) }
|
||||
resource.after_database_authentication
|
||||
success!(resource)
|
||||
elsif !halted?
|
||||
fail(:invalid)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -19,11 +19,13 @@ module Devise
|
||||
def authenticate!
|
||||
resource = mapping.to.serialize_from_cookie(*remember_cookie)
|
||||
|
||||
unless resource
|
||||
cookies.delete(remember_key)
|
||||
return pass
|
||||
end
|
||||
|
||||
if validate(resource)
|
||||
success!(resource)
|
||||
elsif !halted?
|
||||
cookies.delete(remember_key)
|
||||
pass
|
||||
end
|
||||
end
|
||||
|
||||
@@ -39,7 +41,7 @@ module Devise
|
||||
end
|
||||
|
||||
def remember_key
|
||||
"remember_#{scope}_token"
|
||||
mapping.to.rememberable_options.fetch(:key, "remember_#{scope}_token")
|
||||
end
|
||||
|
||||
def remember_cookie
|
||||
@@ -50,4 +52,4 @@ module Devise
|
||||
end
|
||||
end
|
||||
|
||||
Warden::Strategies.add(:rememberable, Devise::Strategies::Rememberable)
|
||||
Warden::Strategies.add(:rememberable, Devise::Strategies::Rememberable)
|
||||
|
||||
@@ -7,21 +7,29 @@ module Devise
|
||||
#
|
||||
# http://myapp.example.com/?user_token=SECRET
|
||||
#
|
||||
# For HTTP, you can pass the token as username and blank password. Since some clients may require
|
||||
# a password, you can pass "X" as password and it will simply be ignored.
|
||||
# For headers, you can use basic authentication passing the token as username and
|
||||
# blank password. Since some clients may require a password, you can pass "X" as
|
||||
# password and it will simply be ignored.
|
||||
#
|
||||
# You may also pass the token using the Token authentication mechanism provided
|
||||
# by Rails: http://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Token.html
|
||||
# The token options are stored in request.env['devise.token_options']
|
||||
class TokenAuthenticatable < Authenticatable
|
||||
def store?
|
||||
super && !mapping.to.skip_session_storage.include?(:token_auth)
|
||||
end
|
||||
|
||||
def valid?
|
||||
super || valid_for_token_auth?
|
||||
end
|
||||
|
||||
def authenticate!
|
||||
resource = mapping.to.find_for_token_authentication(authentication_hash)
|
||||
return fail(:invalid_token) unless resource
|
||||
|
||||
if validate(resource)
|
||||
resource.after_token_authentication
|
||||
success!(resource)
|
||||
elsif !halted?
|
||||
fail(:invalid_token)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -37,7 +45,33 @@ module Devise
|
||||
false
|
||||
end
|
||||
|
||||
# Try both scoped and non scoped keys.
|
||||
# Check if the model accepts this strategy as token authenticatable.
|
||||
def token_authenticatable?
|
||||
mapping.to.http_authenticatable?(:token_options)
|
||||
end
|
||||
|
||||
# Check if this is strategy is valid for token authentication by:
|
||||
#
|
||||
# * Validating if the model allows http token authentication;
|
||||
# * If the http auth token exists;
|
||||
# * If all authentication keys are present;
|
||||
#
|
||||
def valid_for_token_auth?
|
||||
token_authenticatable? && auth_token.present? && with_authentication_hash(:token_auth, token_auth_hash)
|
||||
end
|
||||
|
||||
# Extract the auth token from the request
|
||||
def auth_token
|
||||
@auth_token ||= ActionController::HttpAuthentication::Token.token_and_options(request)
|
||||
end
|
||||
|
||||
# Extract a hash with attributes:values from the auth_token
|
||||
def token_auth_hash
|
||||
request.env['devise.token_options'] = auth_token.last
|
||||
{ authentication_keys.first => auth_token.first }
|
||||
end
|
||||
|
||||
# Try both scoped and non scoped keys
|
||||
def params_auth_hash
|
||||
if params[scope].kind_of?(Hash) && params[scope].has_key?(authentication_keys.first)
|
||||
params[scope]
|
||||
|
||||
@@ -45,6 +45,7 @@ module Devise
|
||||
def sign_in(resource_or_scope, resource=nil)
|
||||
scope ||= Devise::Mapping.find_scope!(resource_or_scope)
|
||||
resource ||= resource_or_scope
|
||||
warden.instance_variable_get(:@users).delete(scope)
|
||||
warden.session_serializer.store(resource, scope)
|
||||
end
|
||||
|
||||
@@ -106,8 +107,8 @@ module Devise
|
||||
env["warden.options"] = options
|
||||
Warden::Manager._run_callbacks(:before_failure, env, options)
|
||||
|
||||
status, headers, body = Devise.warden_config[:failure_app].call(env).to_a
|
||||
@controller.send :render, :status => status, :text => body,
|
||||
status, headers, response = Devise.warden_config[:failure_app].call(env).to_a
|
||||
@controller.send :render, :status => status, :text => response.body,
|
||||
:content_type => headers["Content-Type"], :location => headers["Location"]
|
||||
nil # causes process return @response
|
||||
end
|
||||
|
||||
14
lib/devise/time_inflector.rb
Normal file
14
lib/devise/time_inflector.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
require "active_support/core_ext/module/delegation"
|
||||
|
||||
module Devise
|
||||
class TimeInflector
|
||||
include ActionView::Helpers::DateHelper
|
||||
|
||||
class << self
|
||||
attr_reader :instance
|
||||
delegate :time_ago_in_words, :to => :instance
|
||||
end
|
||||
|
||||
@instance = new
|
||||
end
|
||||
end
|
||||
70
lib/devise/token_generator.rb
Normal file
70
lib/devise/token_generator.rb
Normal file
@@ -0,0 +1,70 @@
|
||||
# Deprecate: Copied verbatim from Rails source, remove once we move to Rails 4 only.
|
||||
require 'thread_safe'
|
||||
require 'openssl'
|
||||
require 'securerandom'
|
||||
|
||||
module Devise
|
||||
class TokenGenerator
|
||||
def initialize(key_generator, digest="SHA256")
|
||||
@key_generator = key_generator
|
||||
@digest = digest
|
||||
end
|
||||
|
||||
def digest(klass, column, value)
|
||||
value.present? && OpenSSL::HMAC.hexdigest(@digest, key_for(column), value.to_s)
|
||||
end
|
||||
|
||||
def generate(klass, column)
|
||||
key = key_for(column)
|
||||
|
||||
loop do
|
||||
raw = Devise.friendly_token
|
||||
enc = OpenSSL::HMAC.hexdigest(@digest, key, raw)
|
||||
break [raw, enc] unless klass.to_adapter.find_first({ column => enc })
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def key_for(column)
|
||||
@key_generator.generate_key("Devise #{column}")
|
||||
end
|
||||
end
|
||||
|
||||
# KeyGenerator is a simple wrapper around OpenSSL's implementation of PBKDF2
|
||||
# It can be used to derive a number of keys for various purposes from a given secret.
|
||||
# This lets Rails applications have a single secure secret, but avoid reusing that
|
||||
# key in multiple incompatible contexts.
|
||||
class KeyGenerator
|
||||
def initialize(secret, options = {})
|
||||
@secret = secret
|
||||
# The default iterations are higher than required for our key derivation uses
|
||||
# on the off chance someone uses this for password storage
|
||||
@iterations = options[:iterations] || 2**16
|
||||
end
|
||||
|
||||
# Returns a derived key suitable for use. The default key_size is chosen
|
||||
# to be compatible with the default settings of ActiveSupport::MessageVerifier.
|
||||
# i.e. OpenSSL::Digest::SHA1#block_length
|
||||
def generate_key(salt, key_size=64)
|
||||
OpenSSL::PKCS5.pbkdf2_hmac_sha1(@secret, salt, @iterations, key_size)
|
||||
end
|
||||
end
|
||||
|
||||
# CachingKeyGenerator is a wrapper around KeyGenerator which allows users to avoid
|
||||
# re-executing the key generation process when it's called using the same salt and
|
||||
# key_size
|
||||
class CachingKeyGenerator
|
||||
def initialize(key_generator)
|
||||
@key_generator = key_generator
|
||||
@cache_keys = ThreadSafe::Cache.new
|
||||
end
|
||||
|
||||
# Returns a derived key suitable for use. The default key_size is chosen
|
||||
# to be compatible with the default settings of ActiveSupport::MessageVerifier.
|
||||
# i.e. OpenSSL::Digest::SHA1#block_length
|
||||
def generate_key(salt, key_size=64)
|
||||
@cache_keys["#{salt}#{key_size}"] ||= @key_generator.generate_key(salt, key_size)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,3 +1,3 @@
|
||||
module Devise
|
||||
VERSION = "2.1.0".freeze
|
||||
VERSION = "3.1.1".freeze
|
||||
end
|
||||
|
||||
@@ -22,12 +22,13 @@ module ActiveRecord
|
||||
end
|
||||
|
||||
def inject_devise_content
|
||||
content = model_contents + <<CONTENT
|
||||
# Setup accessible (or protected) attributes for your model
|
||||
attr_accessible :email, :password, :password_confirmation, :remember_me
|
||||
CONTENT
|
||||
content = model_contents
|
||||
|
||||
class_path = class_name.to_s.split("::")
|
||||
class_path = if namespaced?
|
||||
class_name.to_s.split("::")
|
||||
else
|
||||
[class_name]
|
||||
end
|
||||
|
||||
indent_depth = class_path.size - 1
|
||||
content = content.split("\n").map { |line| " " * indent_depth + line } .join("\n") << "\n"
|
||||
@@ -49,7 +50,7 @@ CONTENT
|
||||
t.datetime :remember_created_at
|
||||
|
||||
## Trackable
|
||||
t.integer :sign_in_count, :default => 0
|
||||
t.integer :sign_in_count, :default => 0, :null => false
|
||||
t.datetime :current_sign_in_at
|
||||
t.datetime :last_sign_in_at
|
||||
t.string :current_sign_in_ip
|
||||
@@ -62,12 +63,9 @@ CONTENT
|
||||
# t.string :unconfirmed_email # Only if using reconfirmable
|
||||
|
||||
## Lockable
|
||||
# t.integer :failed_attempts, :default => 0 # Only if lock strategy is :failed_attempts
|
||||
# t.integer :failed_attempts, :default => 0, :null => false # Only if lock strategy is :failed_attempts
|
||||
# t.string :unlock_token # Only if unlock strategy is :email or :both
|
||||
# t.datetime :locked_at
|
||||
|
||||
## Token authenticatable
|
||||
# t.string :authentication_token
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
@@ -14,6 +14,5 @@ class DeviseCreate<%= table_name.camelize %> < ActiveRecord::Migration
|
||||
add_index :<%= table_name %>, :reset_password_token, :unique => true
|
||||
# add_index :<%= table_name %>, :confirmation_token, :unique => true
|
||||
# add_index :<%= table_name %>, :unlock_token, :unique => true
|
||||
# add_index :<%= table_name %>, :authentication_token, :unique => true
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,7 +15,6 @@ class AddDeviseTo<%= table_name.camelize %> < ActiveRecord::Migration
|
||||
add_index :<%= table_name %>, :reset_password_token, :unique => true
|
||||
# add_index :<%= table_name %>, :confirmation_token, :unique => true
|
||||
# add_index :<%= table_name %>, :unlock_token, :unique => true
|
||||
# add_index :<%= table_name %>, :authentication_token, :unique => true
|
||||
end
|
||||
|
||||
def self.down
|
||||
|
||||
@@ -2,24 +2,43 @@ module Devise
|
||||
module Generators
|
||||
module OrmHelpers
|
||||
def model_contents
|
||||
<<-CONTENT
|
||||
buffer = <<-CONTENT
|
||||
# Include default devise modules. Others available are:
|
||||
# :token_authenticatable, :confirmable,
|
||||
# :lockable, :timeoutable and :omniauthable
|
||||
# :confirmable, :lockable, :timeoutable and :omniauthable
|
||||
devise :database_authenticatable, :registerable,
|
||||
:recoverable, :rememberable, :trackable, :validatable
|
||||
|
||||
CONTENT
|
||||
buffer += <<-CONTENT if needs_attr_accessible?
|
||||
# Setup accessible (or protected) attributes for your model
|
||||
attr_accessible :email, :password, :password_confirmation, :remember_me
|
||||
|
||||
CONTENT
|
||||
buffer
|
||||
end
|
||||
|
||||
def needs_attr_accessible?
|
||||
rails_3? && !strong_parameters_enabled?
|
||||
end
|
||||
|
||||
def rails_3?
|
||||
Rails::VERSION::MAJOR == 3
|
||||
end
|
||||
|
||||
def strong_parameters_enabled?
|
||||
defined?(ActionController::StrongParameters)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
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
|
||||
@@ -29,4 +48,4 @@ CONTENT
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,10 +10,15 @@ module Devise
|
||||
argument :scope, :required => false, :default => nil,
|
||||
:desc => "The scope to copy views to"
|
||||
|
||||
# Le sigh, ensure Thor won't handle opts as args
|
||||
# It should be fixed in future Rails releases
|
||||
class_option :form_builder, :aliases => "-b"
|
||||
class_option :markerb
|
||||
|
||||
public_task :copy_views
|
||||
end
|
||||
|
||||
# TODO: Add this to Rails itslef
|
||||
# TODO: Add this to Rails itself
|
||||
module ClassMethods
|
||||
def hide!
|
||||
Rails::Generators.hide_namespace self.namespace
|
||||
@@ -31,7 +36,13 @@ module Devise
|
||||
protected
|
||||
|
||||
def view_directory(name, _target_path = nil)
|
||||
directory name.to_s, _target_path || "#{target_path}/#{name}"
|
||||
directory name.to_s, _target_path || "#{target_path}/#{name}" do |content|
|
||||
if scope
|
||||
content.gsub "devise/shared/links", "#{scope}/shared/links"
|
||||
else
|
||||
content
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def target_path
|
||||
@@ -98,6 +109,7 @@ module Devise
|
||||
:desc => "The scope to copy views to"
|
||||
|
||||
invoke SharedViewsGenerator
|
||||
|
||||
hook_for :form_builder, :aliases => "-b",
|
||||
:desc => "Form builder to be used",
|
||||
:default => defined?(SimpleForm) ? "simple_form_for" : "form_for"
|
||||
|
||||
@@ -20,8 +20,8 @@ module Mongoid
|
||||
def migration_data
|
||||
<<RUBY
|
||||
## Database authenticatable
|
||||
field :email, :type => String, :null => false, :default => ""
|
||||
field :encrypted_password, :type => String, :null => false, :default => ""
|
||||
field :email, :type => String, :default => ""
|
||||
field :encrypted_password, :type => String, :default => ""
|
||||
|
||||
## Recoverable
|
||||
field :reset_password_token, :type => String
|
||||
@@ -54,4 +54,4 @@ RUBY
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -21,11 +21,15 @@ 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:
|
||||
4. If you are deploying on Heroku with Rails 3.2 only, 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.
|
||||
|
||||
5. You can copy Devise views (for customization) to your app by running:
|
||||
|
||||
rails g devise:views
|
||||
|
||||
===============================================================================
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
# Use this hook to configure devise mailer, warden hooks and so forth.
|
||||
# Many of these configuration options can be set straight in your model.
|
||||
Devise.setup do |config|
|
||||
# The secret key used by Devise. Devise uses this key to generate
|
||||
# random tokens. Changing this key will render invalid all existing
|
||||
# confirmation, reset password and unlock tokens in the database.
|
||||
config.secret_key = '<%= SecureRandom.hex(64) %>'
|
||||
|
||||
# ==> Mailer Configuration
|
||||
# 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"
|
||||
# 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.
|
||||
# config.mailer = "Devise::Mailer"
|
||||
# config.mailer = 'Devise::Mailer'
|
||||
|
||||
# ==> ORM configuration
|
||||
# Load and configure the ORM. Supports :active_record (default) and
|
||||
@@ -48,17 +54,21 @@ Devise.setup do |config|
|
||||
# enable it only for database (email + password) authentication.
|
||||
# config.params_authenticatable = true
|
||||
|
||||
# Tell if authentication through HTTP Basic Auth is enabled. False by default.
|
||||
# Tell if authentication through HTTP Auth is enabled. False by default.
|
||||
# It can be set to an array that will enable http authentication only for the
|
||||
# given strategies, for example, `config.http_authenticatable = [:token]` will
|
||||
# enable it only for token authentication.
|
||||
# enable it only for token authentication. The supported strategies are:
|
||||
# :database = Support basic authentication with authentication key + password
|
||||
# :token = Support basic authentication with token authentication key
|
||||
# :token_options = Support token authentication with options as defined in
|
||||
# http://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Token.html
|
||||
# config.http_authenticatable = false
|
||||
|
||||
# If http headers should be returned for AJAX requests. True by default.
|
||||
# config.http_authenticatable_on_xhr = true
|
||||
|
||||
# The realm used in Http Basic Authentication. "Application" by default.
|
||||
# config.http_authentication_realm = "Application"
|
||||
# The realm used in Http Basic Authentication. 'Application' by default.
|
||||
# config.http_authentication_realm = 'Application'
|
||||
|
||||
# It will change confirmation, password recovery and other workflows
|
||||
# to behave the same regardless if the e-mail provided was right or wrong.
|
||||
@@ -72,6 +82,12 @@ Devise.setup do |config|
|
||||
# passing :skip => :sessions to `devise_for` in your config/routes.rb
|
||||
config.skip_session_storage = [:http_auth]
|
||||
|
||||
# By default, Devise cleans up the CSRF token on authentication to
|
||||
# avoid CSRF token fixation attacks. This means that, when using AJAX
|
||||
# requests for sign in and sign up, you need to get a new CSRF token
|
||||
# from the server. You can disable this option at your own risk.
|
||||
# config.clean_up_csrf_token_on_authentication = true
|
||||
|
||||
# ==> 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.
|
||||
@@ -82,7 +98,7 @@ Devise.setup do |config|
|
||||
config.stretches = Rails.env.test? ? 1 : 10
|
||||
|
||||
# Setup a pepper to generate the encrypted password.
|
||||
# config.pepper = <%= SecureRandom.hex(64).inspect %>
|
||||
# config.pepper = '<%= SecureRandom.hex(64) %>'
|
||||
|
||||
# ==> Configuration for :confirmable
|
||||
# A period that the user is allowed to access the website even without
|
||||
@@ -92,6 +108,14 @@ Devise.setup do |config|
|
||||
# the user cannot access the website without confirming his account.
|
||||
# config.allow_unconfirmed_access_for = 2.days
|
||||
|
||||
# A period that the user is allowed to confirm their account before their
|
||||
# token becomes invalid. For example, if set to 3.days, the user can confirm
|
||||
# their account within 3 days after the mail was sent, but on the fourth day
|
||||
# their account can't be confirmed with the token any more.
|
||||
# Default is nil, meaning there is no restriction on how long a user can take
|
||||
# before confirming their account.
|
||||
# config.confirm_within = 3.days
|
||||
|
||||
# If true, requires any email changes to be confirmed (exactly the same way as
|
||||
# initial account confirmation) to be applied. Requires additional unconfirmed_email
|
||||
# db field (see migrations). Until confirmed new email is stored in
|
||||
@@ -113,11 +137,11 @@ Devise.setup do |config|
|
||||
# config.rememberable_options = {}
|
||||
|
||||
# ==> Configuration for :validatable
|
||||
# Range for password length. Default is 6..128.
|
||||
# config.password_length = 6..128
|
||||
# Range for password length. Default is 8..128.
|
||||
config.password_length = 8..128
|
||||
|
||||
# Email regex used to validate email formats. It simply asserts that
|
||||
# an one (and only one) @ exists in the given string. This is mainly
|
||||
# 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/
|
||||
|
||||
@@ -126,6 +150,9 @@ Devise.setup do |config|
|
||||
# time the user will be asked for credentials again. Default is 30 minutes.
|
||||
# config.timeout_in = 30.minutes
|
||||
|
||||
# If true, expires auth token on session timeout.
|
||||
# config.expire_auth_token_on_timeout = false
|
||||
|
||||
# ==> Configuration for :lockable
|
||||
# Defines which strategy will be used to lock an account.
|
||||
# :failed_attempts = Locks an account after a number of failed attempts to sign in.
|
||||
@@ -164,7 +191,9 @@ Devise.setup do |config|
|
||||
# :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1,
|
||||
# :authlogic_sha512 (then you should set stretches above to 20 for default behavior)
|
||||
# and :restful_authentication_sha1 (then you should set stretches to 10, and copy
|
||||
# REST_AUTH_SITE_KEY to pepper)
|
||||
# REST_AUTH_SITE_KEY to pepper).
|
||||
#
|
||||
# Require the `devise-encryptable` gem when using anything other than bcrypt
|
||||
# config.encryptor = :sha512
|
||||
|
||||
# ==> Configuration for :token_authenticatable
|
||||
@@ -181,9 +210,8 @@ Devise.setup do |config|
|
||||
# devise role declared in your routes (usually :user).
|
||||
# config.default_scope = :user
|
||||
|
||||
# Configure sign_out behavior.
|
||||
# Sign_out action can be scoped (i.e. /users/sign_out affects only :user scope).
|
||||
# The default is true, which means any logout action will sign out all active scopes.
|
||||
# Set this configuration to false if you want /users/sign_out to sign out
|
||||
# only the current scope. By default, Devise signs out all scopes.
|
||||
# config.sign_out_all_scopes = true
|
||||
|
||||
# ==> Navigation configuration
|
||||
@@ -195,7 +223,7 @@ Devise.setup do |config|
|
||||
# should add them to the navigational formats lists.
|
||||
#
|
||||
# The "*/*" below is required to match Internet Explorer requests.
|
||||
# config.navigational_formats = ["*/*", :html]
|
||||
# config.navigational_formats = ['*/*', :html]
|
||||
|
||||
# The default HTTP method used to sign out a resource. Default is :delete.
|
||||
config.sign_out_via = :delete
|
||||
@@ -213,4 +241,18 @@ Devise.setup do |config|
|
||||
# manager.intercept_401 = false
|
||||
# manager.default_strategies(:scope => :user).unshift :some_external_strategy
|
||||
# end
|
||||
|
||||
# ==> Mountable engine configurations
|
||||
# When using Devise inside an engine, let's call it `MyEngine`, and this engine
|
||||
# is mountable, there are some extra configurations to be taken into account.
|
||||
# The following options are available, assuming the engine is mounted as:
|
||||
#
|
||||
# mount MyEngine, at: '/my_engine'
|
||||
#
|
||||
# The router that invoked `devise_for`, in the example above, would be:
|
||||
# config.router_name = :my_engine
|
||||
#
|
||||
# When using omniauth, Devise cannot automatically set Omniauth path,
|
||||
# so you need to do it manually. For the users scope, it would be:
|
||||
# config.omniauth_path_prefix = '/my_engine/users/auth'
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Welcome <%= @resource.email %>!
|
||||
Welcome <%= @email %>!
|
||||
|
||||
You can confirm your account through the link below:
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Hello <%= @resource.email %>!
|
||||
|
||||
Your account has been locked due to an excessive amount of unsuccessful sign in attempts.
|
||||
Your account has been locked due to an excessive number of unsuccessful sign in attempts.
|
||||
|
||||
Click the link below to unlock your account:
|
||||
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
|
||||
<%= simple_form_for(resource, :as => resource_name, :url => confirmation_path(resource_name), :html => { :method => :post }) do |f| %>
|
||||
<%= f.error_notification %>
|
||||
<%= f.full_error :confirmation_token %>
|
||||
|
||||
<div class="inputs">
|
||||
<%= f.input :email, :required => true %>
|
||||
<div class="form-inputs">
|
||||
<%= f.input :email, :required => true, :autofocus => true %>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<div class="form-actions">
|
||||
<%= f.button :submit, "Resend confirmation instructions" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
<%= render "devise/shared/links" %>
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
<%= f.input :reset_password_token, :as => :hidden %>
|
||||
<%= f.full_error :reset_password_token %>
|
||||
|
||||
<div class="inputs">
|
||||
<%= f.input :password, :label => "New password", :required => true %>
|
||||
<div class="form-inputs">
|
||||
<%= f.input :password, :label => "New password", :required => true, :autofocus => true %>
|
||||
<%= f.input :password_confirmation, :label => "Confirm your new password", :required => true %>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<div class="form-actions">
|
||||
<%= f.button :submit, "Change my password" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
<%= render "devise/shared/links" %>
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
<%= simple_form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :post }) do |f| %>
|
||||
<%= f.error_notification %>
|
||||
|
||||
<div class="inputs">
|
||||
<%= f.input :email, :required => true %>
|
||||
<div class="form-inputs">
|
||||
<%= f.input :email, :required => true, :autofocus => true %>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<div class="form-actions">
|
||||
<%= f.button :submit, "Send me reset password instructions" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
<%= render "devise/shared/links" %>
|
||||
|
||||
@@ -3,20 +3,25 @@
|
||||
<%= simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
|
||||
<%= f.error_notification %>
|
||||
|
||||
<div class="inputs">
|
||||
<div class="form-inputs">
|
||||
<%= f.input :email, :required => true, :autofocus => true %>
|
||||
|
||||
<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
|
||||
<p>Currently waiting confirmation for: <%= resource.unconfirmed_email %></p>
|
||||
<% end %>
|
||||
|
||||
<%= f.input :password, :autocomplete => "off", :hint => "leave it blank if you don't want to change it", :required => false %>
|
||||
<%= f.input :password_confirmation, :required => false %>
|
||||
<%= f.input :current_password, :hint => "we need your current password to confirm your changes", :required => true %>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<div class="form-actions">
|
||||
<%= f.button :submit, "Update" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<h3>Cancel my account</h3>
|
||||
|
||||
<p>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), :confirm => "Are you sure?", :method => :delete %>.</p>
|
||||
<p>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), :data => { :confirm => "Are you sure?" }, :method => :delete %></p>
|
||||
|
||||
<%= link_to "Back", :back %>
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
<%= simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
|
||||
<%= f.error_notification %>
|
||||
|
||||
<div class="inputs">
|
||||
<div class="form-inputs">
|
||||
<%= f.input :email, :required => true, :autofocus => true %>
|
||||
<%= f.input :password, :required => true %>
|
||||
<%= f.input :password_confirmation, :required => true %>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<div class="form-actions">
|
||||
<%= f.button :submit, "Sign up" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
<%= render "devise/shared/links" %>
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
<h2>Sign in</h2>
|
||||
|
||||
<%= simple_form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
|
||||
<div class="inputs">
|
||||
<div class="form-inputs">
|
||||
<%= f.input :email, :required => false, :autofocus => true %>
|
||||
<%= f.input :password, :required => false %>
|
||||
<%= f.input :remember_me, :as => :boolean if devise_mapping.rememberable? %>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<div class="form-actions">
|
||||
<%= f.button :submit, "Sign in" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
<%= render "devise/shared/links" %>
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
|
||||
<%= simple_form_for(resource, :as => resource_name, :url => unlock_path(resource_name), :html => { :method => :post }) do |f| %>
|
||||
<%= f.error_notification %>
|
||||
<%= f.full_error :unlock_token %>
|
||||
|
||||
<div class="inputs">
|
||||
<%= f.input :email, :required => true %>
|
||||
<div class="form-inputs">
|
||||
<%= f.input :email, :required => true, :autofocus => true %>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<div class="form-actions">
|
||||
<%= f.button :submit, "Resend unlock instructions" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "devise/shared/links" %>
|
||||
<%= render "devise/shared/links" %>
|
||||
|
||||
@@ -139,30 +139,27 @@ class ControllerAuthenticatableTest < ActionController::TestCase
|
||||
assert_equal nil, @controller.instance_variable_get(:@current_admin)
|
||||
end
|
||||
|
||||
test 'sign out clears up any signed in user by scope' do
|
||||
test 'sign out logs out and clears up any signed in user by scope' do
|
||||
user = User.new
|
||||
@mock_warden.expects(:user).with(:scope => :user, :run_callbacks => false).returns(user)
|
||||
@mock_warden.expects(:logout).with(:user).returns(true)
|
||||
@mock_warden.expects(:clear_strategies_cache!).with(:scope => :user).returns(true)
|
||||
@controller.instance_variable_set(:@current_user, user)
|
||||
@controller.sign_out(:user)
|
||||
assert_equal nil, @controller.instance_variable_get(:@current_user)
|
||||
end
|
||||
|
||||
test 'sign out proxy to logout on warden' do
|
||||
@mock_warden.expects(:user).with(:scope => :user, :run_callbacks => false).returns(true)
|
||||
@mock_warden.expects(:logout).with(:user).returns(true)
|
||||
@controller.sign_out(:user)
|
||||
end
|
||||
|
||||
test 'sign out accepts a resource as argument' do
|
||||
@mock_warden.expects(:user).with(:scope => :user, :run_callbacks => false).returns(true)
|
||||
@mock_warden.expects(:logout).with(:user).returns(true)
|
||||
@mock_warden.expects(:clear_strategies_cache!).with(:scope => :user).returns(true)
|
||||
@controller.sign_out(User.new)
|
||||
end
|
||||
|
||||
test 'sign out without args proxy to sign out all scopes' do
|
||||
@mock_warden.expects(:user).times(Devise.mappings.size)
|
||||
@mock_warden.expects(:logout).with().returns(true)
|
||||
@mock_warden.expects(:clear_strategies_cache!).with().returns(true)
|
||||
@controller.sign_out
|
||||
end
|
||||
|
||||
@@ -205,7 +202,7 @@ class ControllerAuthenticatableTest < ActionController::TestCase
|
||||
|
||||
test 'sign in and redirect uses the stored location' do
|
||||
user = User.new
|
||||
@controller.session[:"user_return_to"] = "/foo.bar"
|
||||
@controller.session[:user_return_to] = "/foo.bar"
|
||||
@mock_warden.expects(:user).with(:user).returns(nil)
|
||||
@mock_warden.expects(:set_user).with(user, :scope => :user).returns(true)
|
||||
@controller.expects(:redirect_to).with("/foo.bar")
|
||||
@@ -232,6 +229,7 @@ class ControllerAuthenticatableTest < ActionController::TestCase
|
||||
swap Devise, :sign_out_all_scopes => false do
|
||||
@mock_warden.expects(:user).with(:scope => :admin, :run_callbacks => false).returns(true)
|
||||
@mock_warden.expects(:logout).with(:admin).returns(true)
|
||||
@mock_warden.expects(:clear_strategies_cache!).with(:scope => :admin).returns(true)
|
||||
@controller.expects(:redirect_to).with(admin_root_path)
|
||||
@controller.instance_eval "def after_sign_out_path_for(resource); admin_root_path; end"
|
||||
@controller.sign_out_and_redirect(:admin)
|
||||
@@ -242,6 +240,7 @@ class ControllerAuthenticatableTest < ActionController::TestCase
|
||||
swap Devise, :sign_out_all_scopes => true do
|
||||
@mock_warden.expects(:user).times(Devise.mappings.size)
|
||||
@mock_warden.expects(:logout).with().returns(true)
|
||||
@mock_warden.expects(:clear_strategies_cache!).with().returns(true)
|
||||
@controller.expects(:redirect_to).with(admin_root_path)
|
||||
@controller.instance_eval "def after_sign_out_path_for(resource); admin_root_path; end"
|
||||
@controller.sign_out_and_redirect(:admin)
|
||||
|
||||
@@ -34,10 +34,20 @@ class HelpersTest < ActionController::TestCase
|
||||
end
|
||||
|
||||
test 'get resource params from request params using resource name as key' do
|
||||
user_params = {'name' => 'Shirley Templar'}
|
||||
@controller.stubs(:params).returns(HashWithIndifferentAccess.new({'user' => user_params}))
|
||||
user_params = {'email' => 'shirley@templar.com'}
|
||||
|
||||
assert_equal user_params, @controller.resource_params
|
||||
params = if Devise.rails4?
|
||||
# Stub controller name so strong parameters can filter properly.
|
||||
# DeviseController does not allow any parameters by default.
|
||||
@controller.stubs(:controller_name).returns(:sessions_controller)
|
||||
|
||||
ActionController::Parameters.new({'user' => user_params})
|
||||
else
|
||||
HashWithIndifferentAccess.new({'user' => user_params})
|
||||
end
|
||||
@controller.stubs(:params).returns(params)
|
||||
|
||||
assert_equal user_params, @controller.send(:resource_params)
|
||||
end
|
||||
|
||||
test 'resources methods are not controller actions' do
|
||||
@@ -95,6 +105,12 @@ class HelpersTest < ActionController::TestCase
|
||||
assert_equal 'devise custom options', flash[:notice]
|
||||
end
|
||||
|
||||
test 'allows custom i18n options to override resource_name' do
|
||||
I18n.expects(:t).with("custom_resource_name.confirmed", anything)
|
||||
@controller.stubs(:devise_i18n_options).returns(:resource_name => "custom_resource_name")
|
||||
@controller.send :set_flash_message, :notice, :confirmed
|
||||
end
|
||||
|
||||
test 'navigational_formats not returning a wild card' do
|
||||
MyController.send(:public, :navigational_formats)
|
||||
Devise.navigational_formats = [:"*/*", :html]
|
||||
|
||||
31
test/controllers/passwords_controller_test.rb
Normal file
31
test/controllers/passwords_controller_test.rb
Normal file
@@ -0,0 +1,31 @@
|
||||
require 'test_helper'
|
||||
|
||||
class PasswordsControllerTest < ActionController::TestCase
|
||||
tests Devise::PasswordsController
|
||||
include Devise::TestHelpers
|
||||
|
||||
setup do
|
||||
request.env["devise.mapping"] = Devise.mappings[:user]
|
||||
@user = create_user.tap(&:confirm!)
|
||||
@raw = @user.send_reset_password_instructions
|
||||
end
|
||||
|
||||
def put_update_with_params
|
||||
put :update, "user" => {
|
||||
"reset_password_token" => @raw, "password" => "123456", "password_confirmation" => "123456"
|
||||
}
|
||||
end
|
||||
|
||||
test 'redirect to after_sign_in_path_for if after_resetting_password_path_for is not overridden' do
|
||||
put_update_with_params
|
||||
assert_redirected_to "http://test.host/"
|
||||
end
|
||||
|
||||
test 'redirect accordingly if after_resetting_password_path_for is overridden' do
|
||||
custom_path = "http://custom.path/"
|
||||
Devise::PasswordsController.any_instance.stubs(:after_resetting_password_path_for).with(@user).returns(custom_path)
|
||||
|
||||
put_update_with_params
|
||||
assert_redirected_to custom_path
|
||||
end
|
||||
end
|
||||
@@ -4,6 +4,57 @@ class SessionsControllerTest < ActionController::TestCase
|
||||
tests Devise::SessionsController
|
||||
include Devise::TestHelpers
|
||||
|
||||
test "#create doesn't raise unpermitted params when sign in fails" do
|
||||
ActiveSupport::Notifications.subscribe /unpermitted_parameters/ do |name, start, finish, id, payload|
|
||||
flunk "Unpermitted params: #{payload}"
|
||||
end
|
||||
request.env["devise.mapping"] = Devise.mappings[:user]
|
||||
request.session["user_return_to"] = 'foo.bar'
|
||||
user = create_user
|
||||
post :create, :user => {
|
||||
:email => "wrong@email.com",
|
||||
:password => "wrongpassword"
|
||||
}
|
||||
assert_equal 200, @response.status
|
||||
end
|
||||
|
||||
test "#create works even with scoped views" do
|
||||
swap Devise, :scoped_views => true do
|
||||
request.env["devise.mapping"] = Devise.mappings[:user]
|
||||
post :create
|
||||
assert_equal 200, @response.status
|
||||
assert_template "users/sessions/new"
|
||||
end
|
||||
end
|
||||
|
||||
test "#create delete the url stored in the session if the requested format is navigational" do
|
||||
request.env["devise.mapping"] = Devise.mappings[:user]
|
||||
request.session["user_return_to"] = 'foo.bar'
|
||||
|
||||
user = create_user
|
||||
user.confirm!
|
||||
post :create, :user => {
|
||||
:email => user.email,
|
||||
:password => user.password
|
||||
}
|
||||
|
||||
assert_nil request.session["user_return_to"]
|
||||
end
|
||||
|
||||
test "#create doesn't delete the url stored in the session if the requested format is not navigational" do
|
||||
request.env["devise.mapping"] = Devise.mappings[:user]
|
||||
request.session["user_return_to"] = 'foo.bar'
|
||||
|
||||
user = create_user
|
||||
user.confirm!
|
||||
post :create, :format => 'json', :user => {
|
||||
:email => user.email,
|
||||
:password => user.password
|
||||
}
|
||||
|
||||
assert_equal 'foo.bar', request.session["user_return_to"]
|
||||
end
|
||||
|
||||
test "#create doesn't raise exception after Warden authentication fails when TestHelpers included" do
|
||||
request.env["devise.mapping"] = Devise.mappings[:user]
|
||||
post :create, :user => {
|
||||
@@ -13,24 +64,36 @@ class SessionsControllerTest < ActionController::TestCase
|
||||
assert_equal 200, @response.status
|
||||
assert_template "devise/sessions/new"
|
||||
end
|
||||
|
||||
if defined?(ActiveRecord)
|
||||
if ActiveRecord::Base.respond_to?(:mass_assignment_sanitizer)
|
||||
test "#new doesn't raise mass-assignment exception even if sign-in key is attr_protected" do
|
||||
request.env["devise.mapping"] = Devise.mappings[:user]
|
||||
|
||||
ActiveRecord::Base.mass_assignment_sanitizer = :strict
|
||||
User.class_eval { attr_protected :email }
|
||||
|
||||
begin
|
||||
assert_nothing_raised ActiveModel::MassAssignmentSecurity::Error do
|
||||
get :new, :user => { :email => "allez viens!" }
|
||||
end
|
||||
ensure
|
||||
ActiveRecord::Base.mass_assignment_sanitizer = :logger
|
||||
User.class_eval { attr_accessible :email }
|
||||
test "#destroy doesn't set the flash if the requested format is not navigational" do
|
||||
request.env["devise.mapping"] = Devise.mappings[:user]
|
||||
user = create_user
|
||||
user.confirm!
|
||||
post :create, :format => 'json', :user => {
|
||||
:email => user.email,
|
||||
:password => user.password
|
||||
}
|
||||
|
||||
delete :destroy, :format => 'json'
|
||||
assert flash[:notice].blank?, "flash[:notice] should be blank, not #{flash[:notice].inspect}"
|
||||
assert_equal 204, @response.status
|
||||
end
|
||||
|
||||
if defined?(ActiveRecord) && ActiveRecord::Base.respond_to?(:mass_assignment_sanitizer)
|
||||
test "#new doesn't raise mass-assignment exception even if sign-in key is attr_protected" do
|
||||
request.env["devise.mapping"] = Devise.mappings[:user]
|
||||
|
||||
ActiveRecord::Base.mass_assignment_sanitizer = :strict
|
||||
User.class_eval { attr_protected :email }
|
||||
|
||||
begin
|
||||
assert_nothing_raised ActiveModel::MassAssignmentSecurity::Error do
|
||||
get :new, :user => { :email => "allez viens!" }
|
||||
end
|
||||
ensure
|
||||
ActiveRecord::Base.mass_assignment_sanitizer = :logger
|
||||
User.class_eval { attr_accessible :email }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -68,5 +68,16 @@ class DeviseTest < ActiveSupport::TestCase
|
||||
end
|
||||
assert_not Devise.secure_compare("size_1", "size_four")
|
||||
end
|
||||
|
||||
|
||||
test 'Devise.email_regexp should match valid email addresses' do
|
||||
valid_emails = ["test@example.com", "jo@jo.co", "f4$_m@you.com", "testing.example@example.com.ua"]
|
||||
non_valid_emails = ["rex", "test@go,com", "test user@example.com", "test_user@example server.com"]
|
||||
|
||||
valid_emails.each do |email|
|
||||
assert_match Devise.email_regexp, email
|
||||
end
|
||||
non_valid_emails.each do |email|
|
||||
assert_no_match Devise.email_regexp, email
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -80,9 +80,9 @@ class FailureTest < ActiveSupport::TestCase
|
||||
|
||||
test 'setup a default message' do
|
||||
call_failure
|
||||
assert_match /You are being/, @response.last.body
|
||||
assert_match /redirected/, @response.last.body
|
||||
assert_match /users\/sign_in/, @response.last.body
|
||||
assert_match(/You are being/, @response.last.body)
|
||||
assert_match(/redirected/, @response.last.body)
|
||||
assert_match(/users\/sign_in/, @response.last.body)
|
||||
end
|
||||
|
||||
test 'works for any navigational format' do
|
||||
@@ -215,7 +215,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 is not activated yet.')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,10 +10,14 @@ if DEVISE_ORM == :active_record
|
||||
|
||||
test "all files are properly created with rails31 migration syntax" do
|
||||
run_generator %w(monster)
|
||||
assert_file "app/models/monster.rb", /devise/, /attr_accessible (:[a-z_]+(, )?)+/
|
||||
assert_migration "db/migrate/devise_create_monsters.rb", /def change/
|
||||
end
|
||||
|
||||
test "all files for namespaced model are properly created" do
|
||||
run_generator %w(admin/monster)
|
||||
assert_migration "db/migrate/devise_create_admin_monsters.rb", /def change/
|
||||
end
|
||||
|
||||
test "update model migration when model exists" do
|
||||
run_generator %w(monster)
|
||||
assert_file "app/models/monster.rb"
|
||||
@@ -58,12 +62,42 @@ if DEVISE_ORM == :active_record
|
||||
destination File.expand_path("../../tmp", __FILE__)
|
||||
setup :prepare_destination
|
||||
|
||||
test "all files are properly created" do
|
||||
test "all files are properly created in rails 4.0" do
|
||||
ActiveRecord::Generators::DeviseGenerator.any_instance.stubs(:rails_3?).returns(false)
|
||||
simulate_inside_engine(RailsEngine::Engine, RailsEngine) do
|
||||
run_generator ["monster"]
|
||||
|
||||
assert_file "app/models/rails_engine/monster.rb", /devise/,/attr_accessible (:[a-z_]+(, )?)+/
|
||||
assert_file "app/models/rails_engine/monster.rb", /devise/
|
||||
assert_file "app/models/rails_engine/monster.rb" do |content|
|
||||
assert_no_match /attr_accessible :email/, content
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test "all files are properly created in rails 3.2 when strong_parameters gem is not installed" do
|
||||
ActiveRecord::Generators::DeviseGenerator.any_instance.stubs(:rails_3?).returns(true)
|
||||
ActiveRecord::Generators::DeviseGenerator.any_instance.stubs(:strong_parameters_enabled?).returns(false)
|
||||
simulate_inside_engine(RailsEngine::Engine, RailsEngine) do
|
||||
run_generator ["monster"]
|
||||
|
||||
assert_file "app/models/rails_engine/monster.rb", /devise/
|
||||
assert_file "app/models/rails_engine/monster.rb" do |content|
|
||||
assert_match /attr_accessible :email/, content
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test "all files are properly created in rails 3.2 when strong_parameters gem is installed" do
|
||||
ActiveRecord::Generators::DeviseGenerator.any_instance.stubs(:rails_3?).returns(true)
|
||||
ActiveRecord::Generators::DeviseGenerator.any_instance.stubs(:strong_parameters_enabled?).returns(true)
|
||||
simulate_inside_engine(RailsEngine::Engine, RailsEngine) do
|
||||
run_generator ["monster"]
|
||||
|
||||
assert_file "app/models/rails_engine/monster.rb", /devise/
|
||||
assert_file "app/models/rails_engine/monster.rb" do |content|
|
||||
assert_no_match /attr_accessible :email/, content
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,14 +8,17 @@ class ViewsGeneratorTest < Rails::Generators::TestCase
|
||||
test "Assert all views are properly created with no params" do
|
||||
run_generator
|
||||
assert_files
|
||||
assert_shared_links
|
||||
end
|
||||
|
||||
test "Assert all views are properly created with scope param param" do
|
||||
test "Assert all views are properly created with scope param" do
|
||||
run_generator %w(users)
|
||||
assert_files "users"
|
||||
assert_shared_links "users"
|
||||
|
||||
run_generator %w(admins)
|
||||
assert_files "admins"
|
||||
assert_shared_links "admins"
|
||||
end
|
||||
|
||||
test "Assert views with simple form" do
|
||||
@@ -49,4 +52,16 @@ class ViewsGeneratorTest < Rails::Generators::TestCase
|
||||
assert_file "app/views/#{scope}/shared/_links.erb"
|
||||
assert_file "app/views/#{scope}/unlocks/new.html.erb"
|
||||
end
|
||||
|
||||
def assert_shared_links(scope = nil)
|
||||
scope = "devise" if scope.nil?
|
||||
link = /<%= render \"#{scope}\/shared\/links\" %>/
|
||||
|
||||
assert_file "app/views/#{scope}/passwords/edit.html.erb", link
|
||||
assert_file "app/views/#{scope}/passwords/new.html.erb", link
|
||||
assert_file "app/views/#{scope}/confirmations/new.html.erb", link
|
||||
assert_file "app/views/#{scope}/registrations/new.html.erb", link
|
||||
assert_file "app/views/#{scope}/sessions/new.html.erb", link
|
||||
assert_file "app/views/#{scope}/unlocks/new.html.erb", link
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
require 'test_helper'
|
||||
|
||||
class DeviseHelperTest < ActionController::IntegrationTest
|
||||
class DeviseHelperTest < ActionDispatch::IntegrationTest
|
||||
setup do
|
||||
model_labels = { :models => { :user => "utilisateur" } }
|
||||
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
require 'test_helper'
|
||||
|
||||
class IndifferentHashTest < ActiveSupport::TestCase
|
||||
setup do
|
||||
@hash = Devise::IndifferentHash.new
|
||||
end
|
||||
|
||||
test "it overwrites getter and setter" do
|
||||
@hash[:foo] = "bar"
|
||||
assert_equal "bar", @hash["foo"]
|
||||
assert_equal "bar", @hash[:foo]
|
||||
|
||||
@hash["foo"] = "baz"
|
||||
assert_equal "baz", @hash["foo"]
|
||||
assert_equal "baz", @hash[:foo]
|
||||
end
|
||||
|
||||
test "it overwrites update" do
|
||||
@hash.update :foo => "bar"
|
||||
assert_equal "bar", @hash["foo"]
|
||||
assert_equal "bar", @hash[:foo]
|
||||
|
||||
@hash.update "foo" => "baz"
|
||||
assert_equal "baz", @hash["foo"]
|
||||
assert_equal "baz", @hash[:foo]
|
||||
end
|
||||
|
||||
test "it returns a Hash on to_hash" do
|
||||
@hash[:foo] = "bar"
|
||||
assert_equal Hash["foo", "bar"], @hash.to_hash
|
||||
assert_kind_of Hash, @hash.to_hash
|
||||
end
|
||||
end if defined?(Devise::IndifferentHash)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user