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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 888e341c90edf3af686821f3d64998da9fcdd5cb
4
- data.tar.gz: 5f50386e3657dce0c24b81465a2e54ad8c81221a
3
+ metadata.gz: f6c97c6e01c1026bf027fb99348421103909a668
4
+ data.tar.gz: 910777f85e599d240356aeb2eba4339db0c481c3
5
5
  SHA512:
6
- metadata.gz: 2315ff44b30666ac9291217ba2c9fa2ecb928b0b6ac0919d4a6debc70ec093c1b42f1866191024ee00f0d086c9103b996b173e36a092b84eb56ea9017a7baea0
7
- data.tar.gz: c432df2a344582f4aef84b7512fa4f5a5a72058dc9a8528ee315e95e21044bff3d46ac29052cc1a9968e5dd298370e447df31f31a19519880b5da200df680eb9
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
- doesn't use Roda:
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.
@@ -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 = {:locals=>{:value=>value, :opts=>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] = true
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] = true
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 :change_password_requires_password?
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, invalid_password_message)
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
@@ -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 json_request?
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(request.send(:convert_to_json, json_response))
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 json_request? && json_response_custom_error_status?
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 json_request? && !json_response_custom_error_status?
229
+ if use_jwt? && !json_response_custom_error_status?
224
230
  status = json_response_error_status
225
231
  end
226
232
 
@@ -1,7 +1,7 @@
1
1
  # frozen-string-literal: true
2
2
 
3
3
  module Rodauth
4
- VERSION = '1.12.0'.freeze
4
+ VERSION = '1.13.0'.freeze
5
5
 
6
6
  def self.version
7
7
  VERSION
@@ -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.12.0
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-10-03 00:00:00.000000000 Z
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