clearance 0.12.0 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of clearance might be problematic. Click here for more details.
- data/Appraisals +2 -7
- data/CHANGELOG.md +9 -1
- data/CONTRIBUTING.md +38 -0
- data/Gemfile +2 -10
- data/Gemfile.lock +45 -49
- data/LICENSE +1 -1
- data/README.md +122 -13
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/app/views/sessions/_form.html.erb +13 -0
- data/app/views/sessions/new.html.erb +1 -13
- data/clearance.gemspec +7 -2
- data/features/engine/visitor_resets_password.feature +11 -23
- data/features/engine/visitor_signs_in.feature +6 -14
- data/features/engine/visitor_signs_out.feature +1 -1
- data/features/engine/visitor_signs_up.feature +6 -16
- data/features/integration.feature +0 -2
- data/features/step_definitions/engine/clearance_steps.rb +72 -62
- data/features/support/env.rb +2 -2
- data/gemfiles/3.0.9.gemfile +5 -10
- data/gemfiles/3.0.9.gemfile.lock +28 -33
- data/gemfiles/3.1.0.gemfile +13 -0
- data/gemfiles/3.1.0.gemfile.lock +187 -0
- data/lib/clearance.rb +1 -0
- data/lib/clearance/configuration.rb +2 -1
- data/lib/clearance/password_strategies.rb +5 -0
- data/lib/clearance/password_strategies/sha1.rb +46 -0
- data/lib/clearance/user.rb +10 -38
- data/lib/generators/clearance/features/features_generator.rb +0 -10
- data/spec/models/clearance_user_spec.rb +33 -0
- data/spec/models/sha1_spec.rb +43 -0
- data/spec/models/user_spec.rb +13 -21
- metadata +106 -85
- data/features/step_definitions/web_steps.rb +0 -211
- data/features/support/appraisal.rb +0 -18
- data/features/support/paths.rb +0 -22
- data/features/support/selectors.rb +0 -39
- data/gemfiles/3.1.0.rc4.gemfile +0 -23
- data/gemfiles/3.1.0.rc4.gemfile.lock +0 -216
@@ -0,0 +1,13 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "http://rubygems.org"
|
4
|
+
|
5
|
+
gem "capybara", "~> 1.0.0"
|
6
|
+
gem "factory_girl_rails"
|
7
|
+
gem "shoulda-matchers", :git=>"git://github.com/thoughtbot/shoulda-matchers.git"
|
8
|
+
gem "database_cleaner"
|
9
|
+
gem "launchy"
|
10
|
+
gem "aruba", "~> 0.4.2"
|
11
|
+
gem "rails", "3.1.0"
|
12
|
+
|
13
|
+
gemspec :path=>"../"
|
@@ -0,0 +1,187 @@
|
|
1
|
+
GIT
|
2
|
+
remote: git://github.com/thoughtbot/shoulda-matchers.git
|
3
|
+
revision: 5190a39bba699d4989c2500c98622b505e2de828
|
4
|
+
specs:
|
5
|
+
shoulda-matchers (1.0.0.beta3)
|
6
|
+
|
7
|
+
PATH
|
8
|
+
remote: /Users/croaky/dev/clearance
|
9
|
+
specs:
|
10
|
+
clearance (0.12.0)
|
11
|
+
diesel (~> 0.1.5)
|
12
|
+
rails (>= 3.0)
|
13
|
+
|
14
|
+
GEM
|
15
|
+
remote: http://rubygems.org/
|
16
|
+
specs:
|
17
|
+
actionmailer (3.1.0)
|
18
|
+
actionpack (= 3.1.0)
|
19
|
+
mail (~> 2.3.0)
|
20
|
+
actionpack (3.1.0)
|
21
|
+
activemodel (= 3.1.0)
|
22
|
+
activesupport (= 3.1.0)
|
23
|
+
builder (~> 3.0.0)
|
24
|
+
erubis (~> 2.7.0)
|
25
|
+
i18n (~> 0.6)
|
26
|
+
rack (~> 1.3.2)
|
27
|
+
rack-cache (~> 1.0.3)
|
28
|
+
rack-mount (~> 0.8.2)
|
29
|
+
rack-test (~> 0.6.1)
|
30
|
+
sprockets (~> 2.0.0)
|
31
|
+
activemodel (3.1.0)
|
32
|
+
activesupport (= 3.1.0)
|
33
|
+
bcrypt-ruby (~> 3.0.0)
|
34
|
+
builder (~> 3.0.0)
|
35
|
+
i18n (~> 0.6)
|
36
|
+
activerecord (3.1.0)
|
37
|
+
activemodel (= 3.1.0)
|
38
|
+
activesupport (= 3.1.0)
|
39
|
+
arel (~> 2.2.1)
|
40
|
+
tzinfo (~> 0.3.29)
|
41
|
+
activeresource (3.1.0)
|
42
|
+
activemodel (= 3.1.0)
|
43
|
+
activesupport (= 3.1.0)
|
44
|
+
activesupport (3.1.0)
|
45
|
+
multi_json (~> 1.0)
|
46
|
+
addressable (2.2.6)
|
47
|
+
appraisal (0.3.8)
|
48
|
+
bundler
|
49
|
+
rake
|
50
|
+
arel (2.2.1)
|
51
|
+
aruba (0.4.6)
|
52
|
+
bcat (>= 0.6.1)
|
53
|
+
childprocess (>= 0.2.0)
|
54
|
+
cucumber (>= 1.0.2)
|
55
|
+
rdiscount (>= 1.6.8)
|
56
|
+
rspec (>= 2.6.0)
|
57
|
+
bcat (0.6.1)
|
58
|
+
rack (~> 1.0)
|
59
|
+
bcrypt-ruby (3.0.0)
|
60
|
+
builder (3.0.0)
|
61
|
+
capybara (1.0.1)
|
62
|
+
mime-types (>= 1.16)
|
63
|
+
nokogiri (>= 1.3.3)
|
64
|
+
rack (>= 1.0.0)
|
65
|
+
rack-test (>= 0.5.4)
|
66
|
+
selenium-webdriver (~> 2.0)
|
67
|
+
xpath (~> 0.1.4)
|
68
|
+
childprocess (0.2.2)
|
69
|
+
ffi (~> 1.0.6)
|
70
|
+
cucumber (1.0.2)
|
71
|
+
builder (>= 2.1.2)
|
72
|
+
diff-lcs (>= 1.1.2)
|
73
|
+
gherkin (~> 2.4.5)
|
74
|
+
json (>= 1.4.6)
|
75
|
+
term-ansicolor (>= 1.0.5)
|
76
|
+
cucumber-rails (1.0.2)
|
77
|
+
capybara (>= 1.0.0)
|
78
|
+
cucumber (~> 1.0.0)
|
79
|
+
nokogiri (>= 1.4.6)
|
80
|
+
database_cleaner (0.6.7)
|
81
|
+
diesel (0.1.5)
|
82
|
+
railties
|
83
|
+
diff-lcs (1.1.3)
|
84
|
+
erubis (2.7.0)
|
85
|
+
factory_girl (2.0.5)
|
86
|
+
factory_girl_rails (1.1.0)
|
87
|
+
factory_girl (~> 2.0.0)
|
88
|
+
railties (>= 3.0.0)
|
89
|
+
ffi (1.0.9)
|
90
|
+
gherkin (2.4.16)
|
91
|
+
json (>= 1.4.6)
|
92
|
+
hike (1.2.1)
|
93
|
+
i18n (0.6.0)
|
94
|
+
json (1.5.4)
|
95
|
+
json_pure (1.5.4)
|
96
|
+
spruz (~> 0.2.8)
|
97
|
+
launchy (2.0.5)
|
98
|
+
addressable (~> 2.2.6)
|
99
|
+
mail (2.3.0)
|
100
|
+
i18n (>= 0.4.0)
|
101
|
+
mime-types (~> 1.16)
|
102
|
+
treetop (~> 1.4.8)
|
103
|
+
mime-types (1.16)
|
104
|
+
mocha (0.9.12)
|
105
|
+
multi_json (1.0.3)
|
106
|
+
nokogiri (1.5.0)
|
107
|
+
polyglot (0.3.2)
|
108
|
+
rack (1.3.2)
|
109
|
+
rack-cache (1.0.3)
|
110
|
+
rack (>= 0.4)
|
111
|
+
rack-mount (0.8.3)
|
112
|
+
rack (>= 1.0.0)
|
113
|
+
rack-ssl (1.3.2)
|
114
|
+
rack
|
115
|
+
rack-test (0.6.1)
|
116
|
+
rack (>= 1.0)
|
117
|
+
rails (3.1.0)
|
118
|
+
actionmailer (= 3.1.0)
|
119
|
+
actionpack (= 3.1.0)
|
120
|
+
activerecord (= 3.1.0)
|
121
|
+
activeresource (= 3.1.0)
|
122
|
+
activesupport (= 3.1.0)
|
123
|
+
bundler (~> 1.0)
|
124
|
+
railties (= 3.1.0)
|
125
|
+
railties (3.1.0)
|
126
|
+
actionpack (= 3.1.0)
|
127
|
+
activesupport (= 3.1.0)
|
128
|
+
rack-ssl (~> 1.3.2)
|
129
|
+
rake (>= 0.8.7)
|
130
|
+
rdoc (~> 3.4)
|
131
|
+
thor (~> 0.14.6)
|
132
|
+
rake (0.9.2)
|
133
|
+
rdiscount (1.6.8)
|
134
|
+
rdoc (3.9.4)
|
135
|
+
rspec (2.6.0)
|
136
|
+
rspec-core (~> 2.6.0)
|
137
|
+
rspec-expectations (~> 2.6.0)
|
138
|
+
rspec-mocks (~> 2.6.0)
|
139
|
+
rspec-core (2.6.4)
|
140
|
+
rspec-expectations (2.6.0)
|
141
|
+
diff-lcs (~> 1.1.2)
|
142
|
+
rspec-mocks (2.6.0)
|
143
|
+
rspec-rails (2.6.1)
|
144
|
+
actionpack (~> 3.0)
|
145
|
+
activesupport (~> 3.0)
|
146
|
+
railties (~> 3.0)
|
147
|
+
rspec (~> 2.6.0)
|
148
|
+
rubyzip (0.9.4)
|
149
|
+
selenium-webdriver (2.5.0)
|
150
|
+
childprocess (>= 0.2.1)
|
151
|
+
ffi (>= 1.0.7)
|
152
|
+
json_pure
|
153
|
+
rubyzip
|
154
|
+
sprockets (2.0.0)
|
155
|
+
hike (~> 1.2)
|
156
|
+
rack (~> 1.0)
|
157
|
+
tilt (!= 1.3.0, ~> 1.1)
|
158
|
+
spruz (0.2.13)
|
159
|
+
sqlite3 (1.3.4)
|
160
|
+
term-ansicolor (1.0.6)
|
161
|
+
thor (0.14.6)
|
162
|
+
tilt (1.3.3)
|
163
|
+
treetop (1.4.10)
|
164
|
+
polyglot
|
165
|
+
polyglot (>= 0.3.1)
|
166
|
+
tzinfo (0.3.29)
|
167
|
+
xpath (0.1.4)
|
168
|
+
nokogiri (~> 1.3)
|
169
|
+
|
170
|
+
PLATFORMS
|
171
|
+
ruby
|
172
|
+
|
173
|
+
DEPENDENCIES
|
174
|
+
appraisal (~> 0.3.8)
|
175
|
+
aruba (~> 0.4.2)
|
176
|
+
bundler (~> 1.0.0)
|
177
|
+
capybara (~> 1.0.0)
|
178
|
+
clearance!
|
179
|
+
cucumber-rails (~> 1.0.2)
|
180
|
+
database_cleaner
|
181
|
+
factory_girl_rails
|
182
|
+
launchy
|
183
|
+
mocha
|
184
|
+
rails (= 3.1.0)
|
185
|
+
rspec-rails (~> 2.6.0)
|
186
|
+
shoulda-matchers!
|
187
|
+
sqlite3
|
data/lib/clearance.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Clearance
|
2
2
|
class Configuration
|
3
|
-
attr_accessor :mailer_sender, :cookie_expiration
|
3
|
+
attr_accessor :mailer_sender, :cookie_expiration, :password_strategy
|
4
4
|
|
5
5
|
def initialize
|
6
6
|
@mailer_sender = 'donotreply@example.com'
|
@@ -24,6 +24,7 @@ module Clearance
|
|
24
24
|
# Clearance.configure do |config|
|
25
25
|
# config.mailer_sender = 'me@example.com'
|
26
26
|
# config.cookie_expiration = lambda { 2.weeks.from_now.utc }
|
27
|
+
# config.password_strategy = MyPasswordStrategy
|
27
28
|
# end
|
28
29
|
def self.configure
|
29
30
|
self.configuration ||= Configuration.new
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'digest/sha1'
|
2
|
+
|
3
|
+
module Clearance
|
4
|
+
module PasswordStrategies
|
5
|
+
module SHA1
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
# Am I authenticated with given password?
|
9
|
+
#
|
10
|
+
# @param [String] plain-text password
|
11
|
+
# @return [true, false]
|
12
|
+
# @example
|
13
|
+
# user.authenticated?('password')
|
14
|
+
def authenticated?(password)
|
15
|
+
encrypted_password == encrypt(password)
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
def encrypt_password
|
21
|
+
initialize_salt_if_necessary
|
22
|
+
if password.present?
|
23
|
+
self.encrypted_password = encrypt(password)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def generate_hash(string)
|
28
|
+
if RUBY_VERSION >= '1.9'
|
29
|
+
Digest::SHA1.hexdigest(string).encode('UTF-8')
|
30
|
+
else
|
31
|
+
Digest::SHA1.hexdigest(string)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def encrypt(string)
|
36
|
+
generate_hash("--#{salt}--#{string}--")
|
37
|
+
end
|
38
|
+
|
39
|
+
def initialize_salt_if_necessary
|
40
|
+
if salt.blank?
|
41
|
+
self.salt = generate_random_code
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/clearance/user.rb
CHANGED
@@ -10,15 +10,18 @@ module Clearance
|
|
10
10
|
# extend and include à la carte.
|
11
11
|
#
|
12
12
|
# @example
|
13
|
-
# include Callbacks
|
13
|
+
# include Clearance::User::Callbacks
|
14
14
|
#
|
15
15
|
# @see Validations
|
16
16
|
# @see Callbacks
|
17
17
|
included do
|
18
|
-
attr_accessor :
|
18
|
+
attr_accessor :password_changing
|
19
|
+
attr_reader :password
|
19
20
|
|
20
21
|
include Validations
|
21
22
|
include Callbacks
|
23
|
+
|
24
|
+
include (Clearance.configuration.password_strategy || Clearance::PasswordStrategies::SHA1)
|
22
25
|
end
|
23
26
|
|
24
27
|
module ClassMethods
|
@@ -60,22 +63,10 @@ module Clearance
|
|
60
63
|
# salt, token, password encryption are handled before_save.
|
61
64
|
included do
|
62
65
|
before_validation :downcase_email
|
63
|
-
before_save :initialize_salt,
|
64
|
-
:encrypt_password
|
65
66
|
before_create :generate_remember_token
|
66
67
|
end
|
67
68
|
end
|
68
69
|
|
69
|
-
# Am I authenticated with given password?
|
70
|
-
#
|
71
|
-
# @param [String] plain-text password
|
72
|
-
# @return [true, false]
|
73
|
-
# @example
|
74
|
-
# user.authenticated?('password')
|
75
|
-
def authenticated?(password)
|
76
|
-
encrypted_password == encrypt(password)
|
77
|
-
end
|
78
|
-
|
79
70
|
# Set the remember token.
|
80
71
|
#
|
81
72
|
# @deprecated Use {#reset_remember_token!} instead
|
@@ -117,16 +108,13 @@ module Clearance
|
|
117
108
|
save
|
118
109
|
end
|
119
110
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
if RUBY_VERSION >= '1.9'
|
124
|
-
Digest::SHA1.hexdigest(string).encode('UTF-8')
|
125
|
-
else
|
126
|
-
Digest::SHA1.hexdigest(string)
|
127
|
-
end
|
111
|
+
def password=(unencrypted_password)
|
112
|
+
@password = unencrypted_password
|
113
|
+
encrypt_password
|
128
114
|
end
|
129
115
|
|
116
|
+
protected
|
117
|
+
|
130
118
|
def generate_random_code(length = 20)
|
131
119
|
if RUBY_VERSION >= '1.9'
|
132
120
|
SecureRandom.hex(length).encode('UTF-8')
|
@@ -135,22 +123,6 @@ module Clearance
|
|
135
123
|
end
|
136
124
|
end
|
137
125
|
|
138
|
-
def encrypt(string)
|
139
|
-
generate_hash("--#{salt}--#{string}--")
|
140
|
-
end
|
141
|
-
|
142
|
-
def initialize_salt
|
143
|
-
if salt.blank?
|
144
|
-
self.salt = generate_random_code
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
def encrypt_password
|
149
|
-
if password.present?
|
150
|
-
self.encrypted_password = encrypt(password)
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
126
|
def generate_remember_token
|
155
127
|
self.remember_token = generate_random_code
|
156
128
|
end
|
@@ -3,16 +3,6 @@ require 'diesel/generators/features_base'
|
|
3
3
|
module Clearance
|
4
4
|
module Generators
|
5
5
|
class FeaturesGenerator < Diesel::Generators::FeaturesBase
|
6
|
-
def inject_paths
|
7
|
-
inject_into_file "features/support/paths.rb", :after => "# Add more mappings here.\n" do
|
8
|
-
" when /the sign up page/i
|
9
|
-
sign_up_path
|
10
|
-
when /the sign in page/i
|
11
|
-
sign_in_path
|
12
|
-
when /the password reset request page/i
|
13
|
-
new_password_path\n"
|
14
|
-
end
|
15
|
-
end
|
16
6
|
end
|
17
7
|
end
|
18
8
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Clearance::User do
|
4
|
+
subject do
|
5
|
+
Class.new do
|
6
|
+
def self.validates_presence_of(*args); end
|
7
|
+
def self.validates_uniqueness_of(*args); end
|
8
|
+
def self.validates_format_of(*args); end
|
9
|
+
def self.before_validation(*args); end
|
10
|
+
def self.before_create(*args); end
|
11
|
+
|
12
|
+
include Clearance::User
|
13
|
+
end.new
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "when Clearance.configuration.password_strategy is set" do
|
17
|
+
let(:mock_password_strategy) { Module.new }
|
18
|
+
|
19
|
+
before { Clearance.configuration.password_strategy = mock_password_strategy }
|
20
|
+
|
21
|
+
it "includes the value it is set to" do
|
22
|
+
subject.should be_kind_of(mock_password_strategy)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "when Clearance.configuration.password_strategy is not set" do
|
27
|
+
before { Clearance.configuration.password_strategy = nil }
|
28
|
+
|
29
|
+
it "includes Clearance::PasswordStrategies::SHA1" do
|
30
|
+
subject.should be_kind_of(Clearance::PasswordStrategies::SHA1)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Clearance::PasswordStrategies::SHA1 do
|
4
|
+
subject do
|
5
|
+
Class.new do
|
6
|
+
attr_accessor :salt, :password, :encrypted_password
|
7
|
+
include Clearance::PasswordStrategies::SHA1
|
8
|
+
|
9
|
+
def generate_random_code; "code"; end
|
10
|
+
end.new
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#encrypt_password" do
|
14
|
+
context "when the password is set" do
|
15
|
+
let(:salt) { "salt" }
|
16
|
+
let(:password) { "password" }
|
17
|
+
|
18
|
+
before do
|
19
|
+
subject.salt = salt
|
20
|
+
subject.password = password
|
21
|
+
subject.send(:encrypt_password)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should encrypt the password using SHA1 into encrypted_password" do
|
25
|
+
expected = Digest::SHA1.hexdigest("--#{salt}--#{password}--")
|
26
|
+
|
27
|
+
subject.encrypted_password.should == expected
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "when the salt is not set" do
|
32
|
+
before do
|
33
|
+
subject.salt = nil
|
34
|
+
|
35
|
+
subject.send(:encrypt_password)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should initialize the salt" do
|
39
|
+
subject.salt.should_not be_nil
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|