rodauth 1.12.0 → 1.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +10 -0
- data/README.rdoc +1 -1
- data/doc/base.rdoc +3 -0
- data/doc/change_password.rdoc +2 -0
- data/doc/jwt.rdoc +1 -0
- data/doc/release_notes/1.13.0.txt +34 -0
- data/lib/rodauth/features/base.rb +5 -3
- data/lib/rodauth/features/change_password.rb +9 -2
- data/lib/rodauth/features/jwt.rb +10 -4
- data/lib/rodauth/version.rb +1 -1
- data/spec/change_password_spec.rb +26 -0
- data/spec/jwt_spec.rb +31 -0
- data/spec/login_spec.rb +24 -0
- data/spec/rodauth_spec.rb +34 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f6c97c6e01c1026bf027fb99348421103909a668
|
4
|
+
data.tar.gz: 910777f85e599d240356aeb2eba4339db0c481c3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c2a571d6eac5c96a458da39020a074edb561c2f71ef32a93382177fcdfe67d73d0ad5dd548255d7c8a09e9f9d67166becd616ec1d8c650d30d766a42b24990ae
|
7
|
+
data.tar.gz: '070838b8388668fa6c7ac73145c82dd0e825d61c83ea43e603789f1efd0383d3c57b147345f55b47d709f6a3786f475fc78fa2e1f5fd30213d6e691fcb6ba5ba'
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
=== 1.13.0 (2017-11-21)
|
2
|
+
|
3
|
+
* Add json_response_body(hash) configuration method to jwt feature (jeremyevans)
|
4
|
+
|
5
|
+
* Support invalid_previous_password_message configuration method in change_password feature (jeremyevans)
|
6
|
+
|
7
|
+
* Use custom error statuses if only_json? and json_response_custom_error_status? are true even if request isn't in json format (jeremyevans)
|
8
|
+
|
9
|
+
* Add cache_templates configuration method for disabling caching of templates (adam12, jeremyevans) (#46)
|
10
|
+
|
1
11
|
=== 1.12.0 (2017-10-03)
|
2
12
|
|
3
13
|
* [SECURITY] Clear expired password reset key for account before retrieving password reset key (chanks, jeremyevans) (#43)
|
data/README.rdoc
CHANGED
@@ -940,7 +940,7 @@ inside the middleware, you can easily provide a way for your
|
|
940
940
|
application to call Rodauth methods.
|
941
941
|
|
942
942
|
Here are some examples of integrating Rodauth into applications that
|
943
|
-
|
943
|
+
don't use Roda:
|
944
944
|
|
945
945
|
* {Ginatra, a Sinatra-based git repository viewer}[https://github.com/jeremyevans/ginatra/commit/28108ebec96e8d42596ee55b01c3f7b50c155dd1]
|
946
946
|
* {Rodauth's demo site as a Rails application}[https://github.com/jeremyevans/rodauth-demo-rails] (
|
data/doc/base.rdoc
CHANGED
@@ -37,6 +37,9 @@ account_select :: An array of columns to select from +accounts_table+. By
|
|
37
37
|
default, selects all columns in the table.
|
38
38
|
account_status_column :: The status id column in the account model.
|
39
39
|
account_unverified_status_value :: The representating unverified accounts.
|
40
|
+
cache_templates :: Whether to cache templates. True by default. It may be worth
|
41
|
+
switching this to false in development if you are using your
|
42
|
+
own templates instead of the templates provided by Rodauth.
|
40
43
|
default_redirect :: Where to redirect after most successful actions.
|
41
44
|
invalid_field_error_status :: The response status to use for invalid field
|
42
45
|
value errors, 422 by default.
|
data/doc/change_password.rdoc
CHANGED
@@ -25,3 +25,5 @@ after_change_password :: Run arbitrary code after successful password change.
|
|
25
25
|
before_change_password :: Run arbitrary code before changing the password for an account.
|
26
26
|
before_change_password_route :: Run arbitrary code before handling a change password route.
|
27
27
|
change_password_view :: The HTML to use for the change password form.
|
28
|
+
invalid_previous_password_message :: The message to use when the previous password was
|
29
|
+
incorrect. Defaults to invalid_password_message.
|
data/doc/jwt.rdoc
CHANGED
@@ -66,6 +66,7 @@ use_jwt? :: Whether to use the JWT in the Authorization header for authenticatio
|
|
66
66
|
== Auth Methods
|
67
67
|
|
68
68
|
json_request? :: Whether the current request is a JSON request, looks at the Content-Type request header by default.
|
69
|
+
json_response_body(hash) :: The body to use for JSON response. By default just converts hash to JSON. Can be used to reformat JSON output in arbitrary ways.
|
69
70
|
jwt_session_hash :: The session hash used to create the session_jwt. Can be used to set JWT claims.
|
70
71
|
jwt_token :: Retrieve the JWT token from the request, by default taking it from the Authorization header.
|
71
72
|
session_jwt :: An encoded JWT for the current session.
|
@@ -0,0 +1,34 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* A cache_templates configuration method has been added, which can be
|
4
|
+
set to false to disable the default caching of templates. The main
|
5
|
+
time you would want to use this is if you were overriding Rodauth's
|
6
|
+
templates with your own templates and modifying such templates in
|
7
|
+
development mode. If that is the case, you may want to use
|
8
|
+
something like:
|
9
|
+
|
10
|
+
cache_templates(ENV['RACK_ENV'] != 'development')
|
11
|
+
|
12
|
+
* An invalid_previous_password_message configuration method has been
|
13
|
+
added to the change_password feature, which overrides the default
|
14
|
+
invalid_password_message configuration method if the incorrect
|
15
|
+
previous password is used when changing the password. This is
|
16
|
+
designed for use when invalid_password_message has been overridden
|
17
|
+
and the message doesn't make sense in the change password case.
|
18
|
+
|
19
|
+
* A json_response_body(hash) configuration method has been added to
|
20
|
+
the jwt feature, allowing for custom formatting of the JSON
|
21
|
+
response body. This is called with the hash to use in the
|
22
|
+
response, and should return a JSON-formatted string. Example:
|
23
|
+
|
24
|
+
json_response_body do |hash|
|
25
|
+
super('status'=>response.status, 'detail'=>hash)
|
26
|
+
end
|
27
|
+
|
28
|
+
= Other Improvements
|
29
|
+
|
30
|
+
* In the jwt feature, if json_response_custom_error_status? is set to
|
31
|
+
true, custom error statuses will be used if only_json? is set to
|
32
|
+
true, even if the request is not in JSON format. Previously,
|
33
|
+
custom error statuses were only used if the request was in JSON
|
34
|
+
format.
|
@@ -17,6 +17,7 @@ module Rodauth
|
|
17
17
|
auth_value_method :account_status_column, :status_id
|
18
18
|
auth_value_method :account_unverified_status_value, 1
|
19
19
|
auth_value_method :accounts_table, :accounts
|
20
|
+
auth_value_method :cache_templates, true
|
20
21
|
auth_value_method :default_redirect, '/'
|
21
22
|
auth_value_method :invalid_field_error_status, 422
|
22
23
|
auth_value_method :invalid_key_error_status, 401
|
@@ -235,9 +236,10 @@ module Rodauth
|
|
235
236
|
end
|
236
237
|
|
237
238
|
def button_opts(value, opts)
|
238
|
-
opts =
|
239
|
+
opts = Hash[template_opts].merge!(opts)
|
240
|
+
opts[:locals] = {:value=>value, :opts=>opts}
|
239
241
|
opts[:path] = template_path('button')
|
240
|
-
opts[:cache] =
|
242
|
+
opts[:cache] = cache_templates
|
241
243
|
opts[:cache_key] = :rodauth_button
|
242
244
|
opts
|
243
245
|
end
|
@@ -516,7 +518,7 @@ module Rodauth
|
|
516
518
|
opts = template_opts.dup
|
517
519
|
opts[:locals] = opts[:locals] ? opts[:locals].dup : {}
|
518
520
|
opts[:locals][:rodauth] = self
|
519
|
-
opts[:cache] =
|
521
|
+
opts[:cache] = cache_templates
|
520
522
|
opts[:cache_key] = :"rodauth_#{page}"
|
521
523
|
|
522
524
|
scope.instance_exec do
|
@@ -17,7 +17,10 @@ module Rodauth
|
|
17
17
|
auth_value_method :new_password_label, 'New Password'
|
18
18
|
auth_value_method :new_password_param, 'new-password'
|
19
19
|
|
20
|
-
auth_value_methods
|
20
|
+
auth_value_methods(
|
21
|
+
:change_password_requires_password?,
|
22
|
+
:invalid_previous_password_message
|
23
|
+
)
|
21
24
|
|
22
25
|
route do |r|
|
23
26
|
require_account
|
@@ -30,7 +33,7 @@ module Rodauth
|
|
30
33
|
r.post do
|
31
34
|
catch_error do
|
32
35
|
if change_password_requires_password? && !password_match?(param(password_param))
|
33
|
-
throw_error_status(invalid_password_error_status, password_param,
|
36
|
+
throw_error_status(invalid_password_error_status, password_param, invalid_previous_password_message)
|
34
37
|
end
|
35
38
|
|
36
39
|
password = param(new_password_param)
|
@@ -63,5 +66,9 @@ module Rodauth
|
|
63
66
|
def change_password_requires_password?
|
64
67
|
modifications_require_password?
|
65
68
|
end
|
69
|
+
|
70
|
+
def invalid_previous_password_message
|
71
|
+
invalid_password_message
|
72
|
+
end
|
66
73
|
end
|
67
74
|
end
|
data/lib/rodauth/features/jwt.rb
CHANGED
@@ -38,6 +38,8 @@ module Rodauth
|
|
38
38
|
:set_jwt_token
|
39
39
|
)
|
40
40
|
|
41
|
+
auth_private_methods :json_response_body
|
42
|
+
|
41
43
|
def session
|
42
44
|
return @session if defined?(@session)
|
43
45
|
return super unless use_jwt?
|
@@ -163,7 +165,7 @@ module Rodauth
|
|
163
165
|
|
164
166
|
def before_view_recovery_codes
|
165
167
|
super if defined?(super)
|
166
|
-
if
|
168
|
+
if use_jwt?
|
167
169
|
json_response[:codes] = recovery_codes
|
168
170
|
json_response[json_response_success_key] ||= "" if include_success_messages?
|
169
171
|
end
|
@@ -201,11 +203,15 @@ module Rodauth
|
|
201
203
|
return_json_response
|
202
204
|
end
|
203
205
|
|
206
|
+
def _json_response_body(hash)
|
207
|
+
request.send(:convert_to_json, hash)
|
208
|
+
end
|
209
|
+
|
204
210
|
def return_json_response
|
205
211
|
response.status ||= json_response_error_status if json_response[json_response_error_key]
|
206
212
|
set_jwt
|
207
213
|
response['Content-Type'] ||= json_response_content_type
|
208
|
-
response.write(
|
214
|
+
response.write(_json_response_body(json_response))
|
209
215
|
request.halt
|
210
216
|
end
|
211
217
|
|
@@ -214,13 +220,13 @@ module Rodauth
|
|
214
220
|
end
|
215
221
|
|
216
222
|
def set_redirect_error_status(status)
|
217
|
-
if
|
223
|
+
if use_jwt? && json_response_custom_error_status?
|
218
224
|
response.status = status
|
219
225
|
end
|
220
226
|
end
|
221
227
|
|
222
228
|
def set_response_error_status(status)
|
223
|
-
if
|
229
|
+
if use_jwt? && !json_response_custom_error_status?
|
224
230
|
status = json_response_error_status
|
225
231
|
end
|
226
232
|
|
data/lib/rodauth/version.rb
CHANGED
@@ -91,6 +91,32 @@ describe 'Rodauth change_password feature' do
|
|
91
91
|
page.find('#notice_flash').text.must_equal "Your password has been changed"
|
92
92
|
end
|
93
93
|
|
94
|
+
it "should support invalid_previous_password_message" do
|
95
|
+
require_password = true
|
96
|
+
rodauth do
|
97
|
+
enable :login, :logout, :change_password
|
98
|
+
invalid_previous_password_message "Previous password not correct"
|
99
|
+
end
|
100
|
+
roda do |r|
|
101
|
+
r.rodauth
|
102
|
+
r.root{view :content=>""}
|
103
|
+
end
|
104
|
+
|
105
|
+
login
|
106
|
+
page.current_path.must_equal '/'
|
107
|
+
|
108
|
+
visit '/change-password'
|
109
|
+
page.title.must_equal 'Change Password'
|
110
|
+
|
111
|
+
fill_in 'Password', :with=>'0123456'
|
112
|
+
fill_in 'New Password', :with=>'0123456'
|
113
|
+
fill_in 'Confirm Password', :with=>'0123456'
|
114
|
+
click_button 'Change Password'
|
115
|
+
page.find('#error_flash').text.must_equal "There was an error changing your password"
|
116
|
+
page.body.must_include 'Previous password not correct'
|
117
|
+
page.current_path.must_equal '/change-password'
|
118
|
+
end
|
119
|
+
|
94
120
|
it "should support setting requirements for passwords" do
|
95
121
|
rodauth do
|
96
122
|
enable :login, :create_account, :change_password
|
data/spec/jwt_spec.rb
CHANGED
@@ -33,6 +33,22 @@ describe 'Rodauth login feature' do
|
|
33
33
|
res.must_equal [400, {'error'=>'invalid JWT format or claim in Authorization header'}]
|
34
34
|
end
|
35
35
|
|
36
|
+
it "should use custom JSON error statuses even if the request isn't in JSON format if a JWT is in use" do
|
37
|
+
rodauth do
|
38
|
+
only_json? true
|
39
|
+
end
|
40
|
+
roda(:jwt) do |r|
|
41
|
+
r.rodauth
|
42
|
+
rodauth.require_authentication
|
43
|
+
'1'
|
44
|
+
end
|
45
|
+
|
46
|
+
status, headers, body = json_request("/", :headers=>{'CONTENT_TYPE'=>'text/html'}, :include_headers=>true)
|
47
|
+
status.must_equal 401
|
48
|
+
headers['Content-Type'].must_equal 'application/json'
|
49
|
+
JSON.parse(body.join).must_equal("error"=>"Please login to continue")
|
50
|
+
end
|
51
|
+
|
36
52
|
it "should require json request content type in only json mode for rodauth endpoints only" do
|
37
53
|
oj = false
|
38
54
|
rodauth do
|
@@ -103,6 +119,21 @@ describe 'Rodauth login feature' do
|
|
103
119
|
res.must_equal [405, {'error'=>'non-POST method used in JSON API'}]
|
104
120
|
end
|
105
121
|
|
122
|
+
it "should allow customizing JSON response bodies" do
|
123
|
+
rodauth do
|
124
|
+
enable :login, :logout, :jwt
|
125
|
+
json_response_body do |hash|
|
126
|
+
super('status'=>response.status, 'detail'=>hash)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
roda(:jwt) do |r|
|
130
|
+
r.rodauth
|
131
|
+
end
|
132
|
+
|
133
|
+
res = json_request("/login", :method=>'GET')
|
134
|
+
res.must_equal [405, {'status'=>405, 'detail'=>{'error'=>'non-POST method used in JSON API'}}]
|
135
|
+
end
|
136
|
+
|
106
137
|
it "should support valid_jwt? method for checking for valid JWT tokens" do
|
107
138
|
rodauth do
|
108
139
|
enable :login, :logout, :jwt
|
data/spec/login_spec.rb
CHANGED
@@ -154,6 +154,30 @@ describe 'Rodauth login feature' do
|
|
154
154
|
page.current_path.must_equal '/auth/lin'
|
155
155
|
end
|
156
156
|
|
157
|
+
it "should use correct redirect paths when using prefix" do
|
158
|
+
rodauth do
|
159
|
+
enable :login, :logout
|
160
|
+
prefix '/auth'
|
161
|
+
end
|
162
|
+
roda do |r|
|
163
|
+
r.on 'auth' do
|
164
|
+
r.rodauth
|
165
|
+
rodauth.require_login
|
166
|
+
end
|
167
|
+
rodauth.send("#{r.remaining_path[1..-1]}_redirect")
|
168
|
+
end
|
169
|
+
|
170
|
+
visit '/login'
|
171
|
+
page.html.must_equal '/'
|
172
|
+
visit '/logout'
|
173
|
+
page.html.must_equal '/auth/login'
|
174
|
+
visit '/require_login'
|
175
|
+
page.html.must_equal '/auth/login'
|
176
|
+
|
177
|
+
visit '/auth'
|
178
|
+
page.current_path.must_equal '/auth/login'
|
179
|
+
end
|
180
|
+
|
157
181
|
it "should login and logout via jwt" do
|
158
182
|
rodauth do
|
159
183
|
enable :login, :logout
|
data/spec/rodauth_spec.rb
CHANGED
@@ -38,6 +38,40 @@ describe 'Rodauth' do
|
|
38
38
|
page.title.must_equal 'Login'
|
39
39
|
end
|
40
40
|
|
41
|
+
it "should pick up template changes if not caching templates" do
|
42
|
+
begin
|
43
|
+
@no_freeze = true
|
44
|
+
cache = true
|
45
|
+
rodauth do
|
46
|
+
enable :login
|
47
|
+
cache_templates{cache}
|
48
|
+
end
|
49
|
+
roda do |r|
|
50
|
+
r.rodauth
|
51
|
+
end
|
52
|
+
dir = 'spec/views2'
|
53
|
+
file = "#{dir}/login.str"
|
54
|
+
app.plugin :render, :views=>dir, :engine=>'str'
|
55
|
+
Dir.mkdir(dir) unless File.directory?(dir)
|
56
|
+
|
57
|
+
text = File.read('spec/views/login.str')
|
58
|
+
File.open(file, 'wb'){|f| f.write text}
|
59
|
+
visit '/login'
|
60
|
+
page.all('label').first.text.must_equal 'Login'
|
61
|
+
|
62
|
+
File.open(file, 'wb'){|f| f.write text.gsub('Login', 'Banana')}
|
63
|
+
visit '/login'
|
64
|
+
page.all('label').first.text.must_equal 'Login'
|
65
|
+
|
66
|
+
cache = false
|
67
|
+
visit '/login'
|
68
|
+
page.all('label').first.text.must_equal 'Banana'
|
69
|
+
ensure
|
70
|
+
File.delete(file) if File.file?(file)
|
71
|
+
Dir.rmdir(dir) if File.directory?(dir)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
41
75
|
it "should require login to perform certain actions" do
|
42
76
|
rodauth do
|
43
77
|
enable :login, :change_password, :change_login, :close_account
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rodauth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Evans
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-11-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sequel
|
@@ -241,6 +241,7 @@ extra_rdoc_files:
|
|
241
241
|
- doc/release_notes/1.10.0.txt
|
242
242
|
- doc/release_notes/1.11.0.txt
|
243
243
|
- doc/release_notes/1.12.0.txt
|
244
|
+
- doc/release_notes/1.13.0.txt
|
244
245
|
files:
|
245
246
|
- CHANGELOG
|
246
247
|
- MIT-LICENSE
|
@@ -272,6 +273,7 @@ files:
|
|
272
273
|
- doc/release_notes/1.10.0.txt
|
273
274
|
- doc/release_notes/1.11.0.txt
|
274
275
|
- doc/release_notes/1.12.0.txt
|
276
|
+
- doc/release_notes/1.13.0.txt
|
275
277
|
- doc/release_notes/1.2.0.txt
|
276
278
|
- doc/release_notes/1.3.0.txt
|
277
279
|
- doc/release_notes/1.4.0.txt
|