devise-secure_password 1.0.7 → 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/Changelog.md +18 -4
  3. data/Gemfile.lock +8 -8
  4. data/README.md +17 -3
  5. data/app/controllers/devise/passwords_with_policy_controller.rb +52 -10
  6. data/app/views/devise/passwords_with_policy/edit.html.erb +5 -1
  7. data/config/locales/en.yml +40 -0
  8. data/coverage/assets/0.10.2/application.css +799 -0
  9. data/coverage/assets/0.10.2/application.js +1707 -0
  10. data/coverage/assets/0.10.2/colorbox/border.png +0 -0
  11. data/coverage/assets/0.10.2/colorbox/controls.png +0 -0
  12. data/coverage/assets/0.10.2/colorbox/loading.gif +0 -0
  13. data/coverage/assets/0.10.2/colorbox/loading_background.png +0 -0
  14. data/coverage/assets/0.10.2/favicon_green.png +0 -0
  15. data/coverage/assets/0.10.2/favicon_red.png +0 -0
  16. data/coverage/assets/0.10.2/favicon_yellow.png +0 -0
  17. data/coverage/assets/0.10.2/loading.gif +0 -0
  18. data/coverage/assets/0.10.2/magnify.png +0 -0
  19. data/coverage/assets/0.10.2/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  20. data/coverage/assets/0.10.2/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  21. data/coverage/assets/0.10.2/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  22. data/coverage/assets/0.10.2/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  23. data/coverage/assets/0.10.2/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  24. data/coverage/assets/0.10.2/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  25. data/coverage/assets/0.10.2/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  26. data/coverage/assets/0.10.2/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  27. data/coverage/assets/0.10.2/smoothness/images/ui-icons_222222_256x240.png +0 -0
  28. data/coverage/assets/0.10.2/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  29. data/coverage/assets/0.10.2/smoothness/images/ui-icons_454545_256x240.png +0 -0
  30. data/coverage/assets/0.10.2/smoothness/images/ui-icons_888888_256x240.png +0 -0
  31. data/coverage/assets/0.10.2/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  32. data/coverage/index.html +4115 -0
  33. data/devise-secure_password-1.0.0.gem +0 -0
  34. data/gemfiles/rails-5_0.gemfile +2 -2
  35. data/gemfiles/rails-5_0.gemfile.lock +288 -0
  36. data/gemfiles/rails-5_0_6.gemfile.lock +286 -0
  37. data/gemfiles/rails-5_1.gemfile.lock +9 -7
  38. data/gemfiles/rails-5_1_4.gemfile.lock +282 -0
  39. data/lib/devise/secure_password.rb +1 -0
  40. data/lib/devise/secure_password/controllers/helpers.rb +3 -1
  41. data/lib/devise/secure_password/grammar.rb +13 -0
  42. data/lib/devise/secure_password/models/password_disallows_frequent_changes.rb +3 -1
  43. data/lib/devise/secure_password/models/password_has_required_content.rb +40 -4
  44. data/lib/devise/secure_password/version.rb +1 -1
  45. data/lib/support/string/character_counter.rb +2 -0
  46. metadata +32 -3
  47. data/pkg/devise-secure_password-1.0.7.gem +0 -0
Binary file
Binary file
@@ -0,0 +1,4115 @@
1
+ <!DOCTYPE html>
2
+ <html xmlns='http://www.w3.org/1999/xhtml'>
3
+ <head>
4
+ <title>Code coverage for Devise-secure password</title>
5
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
6
+ <script src='./assets/0.10.2/application.js' type='text/javascript'></script>
7
+ <link href='./assets/0.10.2/application.css' media='screen, projection, print' rel='stylesheet' type='text/css'>
8
+ <link rel="shortcut icon" type="image/png" href="./assets/0.10.2/favicon_green.png" />
9
+ <link rel="icon" type="image/png" href="./assets/0.10.2/favicon.png" />
10
+ </head>
11
+
12
+ <body>
13
+ <div id="loading">
14
+ <img src="./assets/0.10.2/loading.gif" alt="loading"/>
15
+ </div>
16
+ <div id="wrapper" style="display:none;">
17
+ <div class="timestamp">Generated <abbr class="timeago" title="2018-04-29T19:21:42-07:00">2018-04-29T19:21:42-07:00</abbr></div>
18
+ <ul class="group_tabs"></ul>
19
+
20
+ <div id="content">
21
+ <div class="file_list_container" id="AllFiles">
22
+ <h2>
23
+ <span class="group_name">All Files</span>
24
+ (<span class="covered_percent"><span class="green">96.81%</span></span>
25
+ covered at
26
+ <span class="covered_strength">
27
+ <span class="green">
28
+ 96.45
29
+ </span>
30
+ </span> hits/line)
31
+ </h2>
32
+ <a name="AllFiles"></a>
33
+ <div>
34
+ <b>11</b> files in total.
35
+ <b>282</b> relevant lines.
36
+ <span class="green"><b>273</b> lines covered</span> and
37
+ <span class="red"><b>9</b> lines missed </span>
38
+ </div>
39
+ <table class="file_list">
40
+ <thead>
41
+ <tr>
42
+ <th>File</th>
43
+ <th>% covered</th>
44
+ <th>Lines</th>
45
+ <th>Relevant Lines</th>
46
+ <th>Lines covered</th>
47
+ <th>Lines missed</th>
48
+ <th>Avg. Hits / Line</th>
49
+ </tr>
50
+ </thead>
51
+ <tbody>
52
+
53
+ <tr>
54
+ <td class="strong"><a href="#bfa6cb8bd274fca7adb60a1e4aca51df703532e0" class="src_link" title="lib/devise/secure_password.rb">lib/devise/secure_password.rb</a></td>
55
+ <td class="green strong">100.0 %</td>
56
+ <td>70</td>
57
+ <td>42</td>
58
+ <td>42</td>
59
+ <td>0</td>
60
+ <td>1.0</td>
61
+ </tr>
62
+
63
+ <tr>
64
+ <td class="strong"><a href="#d293d1d7ca4a62df570f32a32e29bc1620da5946" class="src_link" title="lib/devise/secure_password/controllers/active_helpers.rb">lib/devise/secure_password/controllers/active_helpers.rb</a></td>
65
+ <td class="yellow strong">83.33 %</td>
66
+ <td>45</td>
67
+ <td>18</td>
68
+ <td>15</td>
69
+ <td>3</td>
70
+ <td>2.2</td>
71
+ </tr>
72
+
73
+ <tr>
74
+ <td class="strong"><a href="#9bf8b097105760cbd1fc5724ce787f72c57b574b" class="src_link" title="lib/devise/secure_password/controllers/devise_helpers.rb">lib/devise/secure_password/controllers/devise_helpers.rb</a></td>
75
+ <td class="green strong">100.0 %</td>
76
+ <td>67</td>
77
+ <td>28</td>
78
+ <td>28</td>
79
+ <td>0</td>
80
+ <td>1.8</td>
81
+ </tr>
82
+
83
+ <tr>
84
+ <td class="strong"><a href="#3eef7cc16f9ee559a604a48522ee19887f890bd9" class="src_link" title="lib/devise/secure_password/hooks/password_requires_regular_updates.rb">lib/devise/secure_password/hooks/password_requires_regular_updates.rb</a></td>
85
+ <td class="green strong">100.0 %</td>
86
+ <td>5</td>
87
+ <td>3</td>
88
+ <td>3</td>
89
+ <td>0</td>
90
+ <td>3.0</td>
91
+ </tr>
92
+
93
+ <tr>
94
+ <td class="strong"><a href="#96cdbb86efe2f2f9b0e36ed8c91f1a8c0cdcedd8" class="src_link" title="lib/devise/secure_password/models/password_disallows_frequent_changes.rb">lib/devise/secure_password/models/password_disallows_frequent_changes.rb</a></td>
95
+ <td class="green strong">96.3 %</td>
96
+ <td>60</td>
97
+ <td>27</td>
98
+ <td>26</td>
99
+ <td>1</td>
100
+ <td>5.2</td>
101
+ </tr>
102
+
103
+ <tr>
104
+ <td class="strong"><a href="#b2e3e1d1ac33418c11b262e1e2ff2a852214bd4e" class="src_link" title="lib/devise/secure_password/models/password_disallows_frequent_reuse.rb">lib/devise/secure_password/models/password_disallows_frequent_reuse.rb</a></td>
105
+ <td class="green strong">97.3 %</td>
106
+ <td>72</td>
107
+ <td>37</td>
108
+ <td>36</td>
109
+ <td>1</td>
110
+ <td>17.9</td>
111
+ </tr>
112
+
113
+ <tr>
114
+ <td class="strong"><a href="#4b69a1a797756cc5573d2387f77adfb89bd8ece4" class="src_link" title="lib/devise/secure_password/models/password_has_required_content.rb">lib/devise/secure_password/models/password_has_required_content.rb</a></td>
115
+ <td class="green strong">94.83 %</td>
116
+ <td>131</td>
117
+ <td>58</td>
118
+ <td>55</td>
119
+ <td>3</td>
120
+ <td>93.6</td>
121
+ </tr>
122
+
123
+ <tr>
124
+ <td class="strong"><a href="#ff5f47f049dfa920a69a4c9eee3ab6e03168a334" class="src_link" title="lib/devise/secure_password/models/password_requires_regular_updates.rb">lib/devise/secure_password/models/password_requires_regular_updates.rb</a></td>
125
+ <td class="green strong">100.0 %</td>
126
+ <td>56</td>
127
+ <td>23</td>
128
+ <td>23</td>
129
+ <td>0</td>
130
+ <td>3.6</td>
131
+ </tr>
132
+
133
+ <tr>
134
+ <td class="strong"><a href="#610c7e3624991293372156293eb507f0b5546b94" class="src_link" title="lib/devise/secure_password/models/previous_password.rb">lib/devise/secure_password/models/previous_password.rb</a></td>
135
+ <td class="green strong">100.0 %</td>
136
+ <td>20</td>
137
+ <td>13</td>
138
+ <td>13</td>
139
+ <td>0</td>
140
+ <td>19.4</td>
141
+ </tr>
142
+
143
+ <tr>
144
+ <td class="strong"><a href="#72db1cca418838b5594db9476581685e026a31a6" class="src_link" title="lib/devise/secure_password/routes.rb">lib/devise/secure_password/routes.rb</a></td>
145
+ <td class="green strong">100.0 %</td>
146
+ <td>11</td>
147
+ <td>6</td>
148
+ <td>6</td>
149
+ <td>0</td>
150
+ <td>1.0</td>
151
+ </tr>
152
+
153
+ <tr>
154
+ <td class="strong"><a href="#8089caa3c6348c0fa93f698fa861c92d2a256b6c" class="src_link" title="lib/support/string/character_counter.rb">lib/support/string/character_counter.rb</a></td>
155
+ <td class="green strong">96.3 %</td>
156
+ <td>53</td>
157
+ <td>27</td>
158
+ <td>26</td>
159
+ <td>1</td>
160
+ <td>758.7</td>
161
+ </tr>
162
+
163
+ </tbody>
164
+ </table>
165
+ </div>
166
+
167
+
168
+
169
+ <div class="file_list_container" id="secure_password">
170
+ <h2>
171
+ <span class="group_name">secure_password</span>
172
+ (<span class="covered_percent"><span class="green">96.86%</span></span>
173
+ covered at
174
+ <span class="covered_strength">
175
+ <span class="green">
176
+ 26.33
177
+ </span>
178
+ </span> hits/line)
179
+ </h2>
180
+ <a name="secure_password"></a>
181
+ <div>
182
+ <b>10</b> files in total.
183
+ <b>255</b> relevant lines.
184
+ <span class="green"><b>247</b> lines covered</span> and
185
+ <span class="red"><b>8</b> lines missed </span>
186
+ </div>
187
+ <table class="file_list">
188
+ <thead>
189
+ <tr>
190
+ <th>File</th>
191
+ <th>% covered</th>
192
+ <th>Lines</th>
193
+ <th>Relevant Lines</th>
194
+ <th>Lines covered</th>
195
+ <th>Lines missed</th>
196
+ <th>Avg. Hits / Line</th>
197
+ </tr>
198
+ </thead>
199
+ <tbody>
200
+
201
+ <tr>
202
+ <td class="strong"><a href="#bfa6cb8bd274fca7adb60a1e4aca51df703532e0" class="src_link" title="lib/devise/secure_password.rb">lib/devise/secure_password.rb</a></td>
203
+ <td class="green strong">100.0 %</td>
204
+ <td>70</td>
205
+ <td>42</td>
206
+ <td>42</td>
207
+ <td>0</td>
208
+ <td>1.0</td>
209
+ </tr>
210
+
211
+ <tr>
212
+ <td class="strong"><a href="#d293d1d7ca4a62df570f32a32e29bc1620da5946" class="src_link" title="lib/devise/secure_password/controllers/active_helpers.rb">lib/devise/secure_password/controllers/active_helpers.rb</a></td>
213
+ <td class="yellow strong">83.33 %</td>
214
+ <td>45</td>
215
+ <td>18</td>
216
+ <td>15</td>
217
+ <td>3</td>
218
+ <td>2.2</td>
219
+ </tr>
220
+
221
+ <tr>
222
+ <td class="strong"><a href="#9bf8b097105760cbd1fc5724ce787f72c57b574b" class="src_link" title="lib/devise/secure_password/controllers/devise_helpers.rb">lib/devise/secure_password/controllers/devise_helpers.rb</a></td>
223
+ <td class="green strong">100.0 %</td>
224
+ <td>67</td>
225
+ <td>28</td>
226
+ <td>28</td>
227
+ <td>0</td>
228
+ <td>1.8</td>
229
+ </tr>
230
+
231
+ <tr>
232
+ <td class="strong"><a href="#3eef7cc16f9ee559a604a48522ee19887f890bd9" class="src_link" title="lib/devise/secure_password/hooks/password_requires_regular_updates.rb">lib/devise/secure_password/hooks/password_requires_regular_updates.rb</a></td>
233
+ <td class="green strong">100.0 %</td>
234
+ <td>5</td>
235
+ <td>3</td>
236
+ <td>3</td>
237
+ <td>0</td>
238
+ <td>3.0</td>
239
+ </tr>
240
+
241
+ <tr>
242
+ <td class="strong"><a href="#96cdbb86efe2f2f9b0e36ed8c91f1a8c0cdcedd8" class="src_link" title="lib/devise/secure_password/models/password_disallows_frequent_changes.rb">lib/devise/secure_password/models/password_disallows_frequent_changes.rb</a></td>
243
+ <td class="green strong">96.3 %</td>
244
+ <td>60</td>
245
+ <td>27</td>
246
+ <td>26</td>
247
+ <td>1</td>
248
+ <td>5.2</td>
249
+ </tr>
250
+
251
+ <tr>
252
+ <td class="strong"><a href="#b2e3e1d1ac33418c11b262e1e2ff2a852214bd4e" class="src_link" title="lib/devise/secure_password/models/password_disallows_frequent_reuse.rb">lib/devise/secure_password/models/password_disallows_frequent_reuse.rb</a></td>
253
+ <td class="green strong">97.3 %</td>
254
+ <td>72</td>
255
+ <td>37</td>
256
+ <td>36</td>
257
+ <td>1</td>
258
+ <td>17.9</td>
259
+ </tr>
260
+
261
+ <tr>
262
+ <td class="strong"><a href="#4b69a1a797756cc5573d2387f77adfb89bd8ece4" class="src_link" title="lib/devise/secure_password/models/password_has_required_content.rb">lib/devise/secure_password/models/password_has_required_content.rb</a></td>
263
+ <td class="green strong">94.83 %</td>
264
+ <td>131</td>
265
+ <td>58</td>
266
+ <td>55</td>
267
+ <td>3</td>
268
+ <td>93.6</td>
269
+ </tr>
270
+
271
+ <tr>
272
+ <td class="strong"><a href="#ff5f47f049dfa920a69a4c9eee3ab6e03168a334" class="src_link" title="lib/devise/secure_password/models/password_requires_regular_updates.rb">lib/devise/secure_password/models/password_requires_regular_updates.rb</a></td>
273
+ <td class="green strong">100.0 %</td>
274
+ <td>56</td>
275
+ <td>23</td>
276
+ <td>23</td>
277
+ <td>0</td>
278
+ <td>3.6</td>
279
+ </tr>
280
+
281
+ <tr>
282
+ <td class="strong"><a href="#610c7e3624991293372156293eb507f0b5546b94" class="src_link" title="lib/devise/secure_password/models/previous_password.rb">lib/devise/secure_password/models/previous_password.rb</a></td>
283
+ <td class="green strong">100.0 %</td>
284
+ <td>20</td>
285
+ <td>13</td>
286
+ <td>13</td>
287
+ <td>0</td>
288
+ <td>19.4</td>
289
+ </tr>
290
+
291
+ <tr>
292
+ <td class="strong"><a href="#72db1cca418838b5594db9476581685e026a31a6" class="src_link" title="lib/devise/secure_password/routes.rb">lib/devise/secure_password/routes.rb</a></td>
293
+ <td class="green strong">100.0 %</td>
294
+ <td>11</td>
295
+ <td>6</td>
296
+ <td>6</td>
297
+ <td>0</td>
298
+ <td>1.0</td>
299
+ </tr>
300
+
301
+ </tbody>
302
+ </table>
303
+ </div>
304
+
305
+
306
+ <div class="file_list_container" id="support">
307
+ <h2>
308
+ <span class="group_name">support</span>
309
+ (<span class="covered_percent"><span class="green">96.3%</span></span>
310
+ covered at
311
+ <span class="covered_strength">
312
+ <span class="green">
313
+ 758.7
314
+ </span>
315
+ </span> hits/line)
316
+ </h2>
317
+ <a name="support"></a>
318
+ <div>
319
+ <b>1</b> files in total.
320
+ <b>27</b> relevant lines.
321
+ <span class="green"><b>26</b> lines covered</span> and
322
+ <span class="red"><b>1</b> lines missed </span>
323
+ </div>
324
+ <table class="file_list">
325
+ <thead>
326
+ <tr>
327
+ <th>File</th>
328
+ <th>% covered</th>
329
+ <th>Lines</th>
330
+ <th>Relevant Lines</th>
331
+ <th>Lines covered</th>
332
+ <th>Lines missed</th>
333
+ <th>Avg. Hits / Line</th>
334
+ </tr>
335
+ </thead>
336
+ <tbody>
337
+
338
+ <tr>
339
+ <td class="strong"><a href="#8089caa3c6348c0fa93f698fa861c92d2a256b6c" class="src_link" title="lib/support/string/character_counter.rb">lib/support/string/character_counter.rb</a></td>
340
+ <td class="green strong">96.3 %</td>
341
+ <td>53</td>
342
+ <td>27</td>
343
+ <td>26</td>
344
+ <td>1</td>
345
+ <td>758.7</td>
346
+ </tr>
347
+
348
+ </tbody>
349
+ </table>
350
+ </div>
351
+
352
+
353
+ </div>
354
+
355
+ <div id="footer">
356
+ Generated by <a href="http://github.com/colszowka/simplecov">simplecov</a> v0.15.1
357
+ and simplecov-html v0.10.2<br/>
358
+ using RSpec
359
+ </div>
360
+
361
+ <div class="source_files">
362
+
363
+ <div class="source_table" id="bfa6cb8bd274fca7adb60a1e4aca51df703532e0">
364
+ <div class="header">
365
+ <h3>lib/devise/secure_password.rb</h3>
366
+ <h4><span class="green">100.0 %</span> covered</h4>
367
+ <div>
368
+ <b>42</b> relevant lines.
369
+ <span class="green"><b>42</b> lines covered</span> and
370
+ <span class="red"><b>0</b> lines missed.</span>
371
+ </div>
372
+ </div>
373
+
374
+ <pre>
375
+ <ol>
376
+
377
+ <li class="never" data-hits="" data-linenumber="1">
378
+
379
+
380
+ <code class="ruby">#</code>
381
+ </li>
382
+
383
+ <li class="never" data-hits="" data-linenumber="2">
384
+
385
+
386
+ <code class="ruby"># lib/devise-secure_password.rb</code>
387
+ </li>
388
+
389
+ <li class="never" data-hits="" data-linenumber="3">
390
+
391
+
392
+ <code class="ruby">#</code>
393
+ </li>
394
+
395
+ <li class="covered" data-hits="1" data-linenumber="4">
396
+ <span class="hits">1</span>
397
+
398
+ <code class="ruby">require &#39;active_support/concern&#39;</code>
399
+ </li>
400
+
401
+ <li class="covered" data-hits="1" data-linenumber="5">
402
+ <span class="hits">1</span>
403
+
404
+ <code class="ruby">require &#39;devise&#39;</code>
405
+ </li>
406
+
407
+ <li class="covered" data-hits="1" data-linenumber="6">
408
+ <span class="hits">1</span>
409
+
410
+ <code class="ruby">require &#39;devise/secure_password/routes&#39;</code>
411
+ </li>
412
+
413
+ <li class="covered" data-hits="1" data-linenumber="7">
414
+ <span class="hits">1</span>
415
+
416
+ <code class="ruby">require &#39;devise/secure_password/version&#39;</code>
417
+ </li>
418
+
419
+ <li class="covered" data-hits="1" data-linenumber="8">
420
+ <span class="hits">1</span>
421
+
422
+ <code class="ruby">require &#39;devise/secure_password/models/password_has_required_content&#39;</code>
423
+ </li>
424
+
425
+ <li class="covered" data-hits="1" data-linenumber="9">
426
+ <span class="hits">1</span>
427
+
428
+ <code class="ruby">require &#39;devise/secure_password/models/password_disallows_frequent_reuse&#39;</code>
429
+ </li>
430
+
431
+ <li class="covered" data-hits="1" data-linenumber="10">
432
+ <span class="hits">1</span>
433
+
434
+ <code class="ruby">require &#39;devise/secure_password/models/password_disallows_frequent_changes&#39;</code>
435
+ </li>
436
+
437
+ <li class="covered" data-hits="1" data-linenumber="11">
438
+ <span class="hits">1</span>
439
+
440
+ <code class="ruby">require &#39;devise/secure_password/models/password_requires_regular_updates&#39;</code>
441
+ </li>
442
+
443
+ <li class="never" data-hits="" data-linenumber="12">
444
+
445
+
446
+ <code class="ruby"></code>
447
+ </li>
448
+
449
+ <li class="covered" data-hits="1" data-linenumber="13">
450
+ <span class="hits">1</span>
451
+
452
+ <code class="ruby">module Devise</code>
453
+ </li>
454
+
455
+ <li class="never" data-hits="" data-linenumber="14">
456
+
457
+
458
+ <code class="ruby"> # password_content_enforcement configuration parameters</code>
459
+ </li>
460
+
461
+ <li class="covered" data-hits="1" data-linenumber="15">
462
+ <span class="hits">1</span>
463
+
464
+ <code class="ruby"> @password_required_uppercase_count = 0</code>
465
+ </li>
466
+
467
+ <li class="covered" data-hits="1" data-linenumber="16">
468
+ <span class="hits">1</span>
469
+
470
+ <code class="ruby"> @password_required_lowercase_count = 0</code>
471
+ </li>
472
+
473
+ <li class="covered" data-hits="1" data-linenumber="17">
474
+ <span class="hits">1</span>
475
+
476
+ <code class="ruby"> @password_required_number_count = 0</code>
477
+ </li>
478
+
479
+ <li class="covered" data-hits="1" data-linenumber="18">
480
+ <span class="hits">1</span>
481
+
482
+ <code class="ruby"> @password_required_special_character_count = 0</code>
483
+ </li>
484
+
485
+ <li class="never" data-hits="" data-linenumber="19">
486
+
487
+
488
+ <code class="ruby"></code>
489
+ </li>
490
+
491
+ <li class="never" data-hits="" data-linenumber="20">
492
+
493
+
494
+ <code class="ruby"> # password_frequent_reuse_prevention configuration parameters</code>
495
+ </li>
496
+
497
+ <li class="covered" data-hits="1" data-linenumber="21">
498
+ <span class="hits">1</span>
499
+
500
+ <code class="ruby"> @password_previously_used_count = 1</code>
501
+ </li>
502
+
503
+ <li class="never" data-hits="" data-linenumber="22">
504
+
505
+
506
+ <code class="ruby"></code>
507
+ </li>
508
+
509
+ <li class="never" data-hits="" data-linenumber="23">
510
+
511
+
512
+ <code class="ruby"> # password_frequent_change_prevention configuration parameters</code>
513
+ </li>
514
+
515
+ <li class="covered" data-hits="1" data-linenumber="24">
516
+ <span class="hits">1</span>
517
+
518
+ <code class="ruby"> @password_minimum_age = 0.days</code>
519
+ </li>
520
+
521
+ <li class="never" data-hits="" data-linenumber="25">
522
+
523
+
524
+ <code class="ruby"></code>
525
+ </li>
526
+
527
+ <li class="never" data-hits="" data-linenumber="26">
528
+
529
+
530
+ <code class="ruby"> # password_regular_update_enforcement configuration parameters</code>
531
+ </li>
532
+
533
+ <li class="covered" data-hits="1" data-linenumber="27">
534
+ <span class="hits">1</span>
535
+
536
+ <code class="ruby"> @password_maximum_age = 365.days</code>
537
+ </li>
538
+
539
+ <li class="never" data-hits="" data-linenumber="28">
540
+
541
+
542
+ <code class="ruby"></code>
543
+ </li>
544
+
545
+ <li class="covered" data-hits="1" data-linenumber="29">
546
+ <span class="hits">1</span>
547
+
548
+ <code class="ruby"> class &lt;&lt; self</code>
549
+ </li>
550
+
551
+ <li class="covered" data-hits="1" data-linenumber="30">
552
+ <span class="hits">1</span>
553
+
554
+ <code class="ruby"> attr_accessor :password_required_uppercase_count</code>
555
+ </li>
556
+
557
+ <li class="covered" data-hits="1" data-linenumber="31">
558
+ <span class="hits">1</span>
559
+
560
+ <code class="ruby"> attr_accessor :password_required_lowercase_count</code>
561
+ </li>
562
+
563
+ <li class="covered" data-hits="1" data-linenumber="32">
564
+ <span class="hits">1</span>
565
+
566
+ <code class="ruby"> attr_accessor :password_required_number_count</code>
567
+ </li>
568
+
569
+ <li class="covered" data-hits="1" data-linenumber="33">
570
+ <span class="hits">1</span>
571
+
572
+ <code class="ruby"> attr_accessor :password_required_special_character_count</code>
573
+ </li>
574
+
575
+ <li class="covered" data-hits="1" data-linenumber="34">
576
+ <span class="hits">1</span>
577
+
578
+ <code class="ruby"> attr_accessor :password_previously_used_count</code>
579
+ </li>
580
+
581
+ <li class="covered" data-hits="1" data-linenumber="35">
582
+ <span class="hits">1</span>
583
+
584
+ <code class="ruby"> attr_accessor :password_minimum_age</code>
585
+ </li>
586
+
587
+ <li class="covered" data-hits="1" data-linenumber="36">
588
+ <span class="hits">1</span>
589
+
590
+ <code class="ruby"> attr_accessor :password_maximum_age</code>
591
+ </li>
592
+
593
+ <li class="never" data-hits="" data-linenumber="37">
594
+
595
+
596
+ <code class="ruby"> end</code>
597
+ </li>
598
+
599
+ <li class="never" data-hits="" data-linenumber="38">
600
+
601
+
602
+ <code class="ruby"></code>
603
+ </li>
604
+
605
+ <li class="covered" data-hits="1" data-linenumber="39">
606
+ <span class="hits">1</span>
607
+
608
+ <code class="ruby"> module SecurePassword</code>
609
+ </li>
610
+
611
+ <li class="covered" data-hits="1" data-linenumber="40">
612
+ <span class="hits">1</span>
613
+
614
+ <code class="ruby"> module Controllers</code>
615
+ </li>
616
+
617
+ <li class="covered" data-hits="1" data-linenumber="41">
618
+ <span class="hits">1</span>
619
+
620
+ <code class="ruby"> autoload :DeviseHelpers, &#39;devise/secure_password/controllers/devise_helpers&#39;</code>
621
+ </li>
622
+
623
+ <li class="covered" data-hits="1" data-linenumber="42">
624
+ <span class="hits">1</span>
625
+
626
+ <code class="ruby"> autoload :ActiveHelpers, &#39;devise/secure_password/controllers/active_helpers&#39;</code>
627
+ </li>
628
+
629
+ <li class="never" data-hits="" data-linenumber="43">
630
+
631
+
632
+ <code class="ruby"> end</code>
633
+ </li>
634
+
635
+ <li class="never" data-hits="" data-linenumber="44">
636
+
637
+
638
+ <code class="ruby"></code>
639
+ </li>
640
+
641
+ <li class="covered" data-hits="1" data-linenumber="45">
642
+ <span class="hits">1</span>
643
+
644
+ <code class="ruby"> class Engine &lt; ::Rails::Engine</code>
645
+ </li>
646
+
647
+ <li class="covered" data-hits="1" data-linenumber="46">
648
+ <span class="hits">1</span>
649
+
650
+ <code class="ruby"> ActiveSupport.on_load(:devise_controller) do</code>
651
+ </li>
652
+
653
+ <li class="covered" data-hits="1" data-linenumber="47">
654
+ <span class="hits">1</span>
655
+
656
+ <code class="ruby"> include ActionView::Helpers::DateHelper</code>
657
+ </li>
658
+
659
+ <li class="covered" data-hits="1" data-linenumber="48">
660
+ <span class="hits">1</span>
661
+
662
+ <code class="ruby"> include Devise::SecurePassword::Controllers::DeviseHelpers</code>
663
+ </li>
664
+
665
+ <li class="never" data-hits="" data-linenumber="49">
666
+
667
+
668
+ <code class="ruby"> end</code>
669
+ </li>
670
+
671
+ <li class="covered" data-hits="1" data-linenumber="50">
672
+ <span class="hits">1</span>
673
+
674
+ <code class="ruby"> ActiveSupport.on_load(:action_controller) do</code>
675
+ </li>
676
+
677
+ <li class="covered" data-hits="1" data-linenumber="51">
678
+ <span class="hits">1</span>
679
+
680
+ <code class="ruby"> include ActionView::Helpers::DateHelper</code>
681
+ </li>
682
+
683
+ <li class="covered" data-hits="1" data-linenumber="52">
684
+ <span class="hits">1</span>
685
+
686
+ <code class="ruby"> include Devise::SecurePassword::Controllers::ActiveHelpers</code>
687
+ </li>
688
+
689
+ <li class="never" data-hits="" data-linenumber="53">
690
+
691
+
692
+ <code class="ruby"> end</code>
693
+ </li>
694
+
695
+ <li class="never" data-hits="" data-linenumber="54">
696
+
697
+
698
+ <code class="ruby"></code>
699
+ </li>
700
+
701
+ <li class="never" data-hits="" data-linenumber="55">
702
+
703
+
704
+ <code class="ruby"> # add exceptions to the inflector so it doesn&#39;t get tripped up by our concerns that end in an &#39;s&#39;</code>
705
+ </li>
706
+
707
+ <li class="covered" data-hits="1" data-linenumber="56">
708
+ <span class="hits">1</span>
709
+
710
+ <code class="ruby"> ActiveSupport::Inflector.inflections do |inflect|</code>
711
+ </li>
712
+
713
+ <li class="covered" data-hits="1" data-linenumber="57">
714
+ <span class="hits">1</span>
715
+
716
+ <code class="ruby"> inflect.uncountable :password_disallows_frequent_changes</code>
717
+ </li>
718
+
719
+ <li class="covered" data-hits="1" data-linenumber="58">
720
+ <span class="hits">1</span>
721
+
722
+ <code class="ruby"> inflect.uncountable :password_requires_regular_updates</code>
723
+ </li>
724
+
725
+ <li class="never" data-hits="" data-linenumber="59">
726
+
727
+
728
+ <code class="ruby"> end</code>
729
+ </li>
730
+
731
+ <li class="never" data-hits="" data-linenumber="60">
732
+
733
+
734
+ <code class="ruby"> end</code>
735
+ </li>
736
+
737
+ <li class="never" data-hits="" data-linenumber="61">
738
+
739
+
740
+ <code class="ruby"> end</code>
741
+ </li>
742
+
743
+ <li class="never" data-hits="" data-linenumber="62">
744
+
745
+
746
+ <code class="ruby">end</code>
747
+ </li>
748
+
749
+ <li class="never" data-hits="" data-linenumber="63">
750
+
751
+
752
+ <code class="ruby"></code>
753
+ </li>
754
+
755
+ <li class="never" data-hits="" data-linenumber="64">
756
+
757
+
758
+ <code class="ruby"># modules</code>
759
+ </li>
760
+
761
+ <li class="covered" data-hits="1" data-linenumber="65">
762
+ <span class="hits">1</span>
763
+
764
+ <code class="ruby">Devise.add_module :password_has_required_content, model: &#39;devise/secure_password/models/password_has_required_content&#39;</code>
765
+ </li>
766
+
767
+ <li class="covered" data-hits="1" data-linenumber="66">
768
+ <span class="hits">1</span>
769
+
770
+ <code class="ruby">Devise.add_module :password_disallows_frequent_reuse, model: &#39;devise/secure_password/models/password_disallows_frequent_reuse&#39;</code>
771
+ </li>
772
+
773
+ <li class="covered" data-hits="1" data-linenumber="67">
774
+ <span class="hits">1</span>
775
+
776
+ <code class="ruby">Devise.add_module :password_disallows_frequent_changes, model: &#39;devise/secure_password/models/password_disallows_frequent_changes&#39;</code>
777
+ </li>
778
+
779
+ <li class="covered" data-hits="1" data-linenumber="68">
780
+ <span class="hits">1</span>
781
+
782
+ <code class="ruby">Devise.add_module :password_requires_regular_updates,</code>
783
+ </li>
784
+
785
+ <li class="never" data-hits="" data-linenumber="69">
786
+
787
+
788
+ <code class="ruby"> model: &#39;devise/secure_password/models/password_requires_regular_updates&#39;,</code>
789
+ </li>
790
+
791
+ <li class="never" data-hits="" data-linenumber="70">
792
+
793
+
794
+ <code class="ruby"> controller: :passwords_with_policy, route: :passwords_with_policy</code>
795
+ </li>
796
+
797
+ </ol>
798
+ </pre>
799
+ </div>
800
+
801
+
802
+ <div class="source_table" id="d293d1d7ca4a62df570f32a32e29bc1620da5946">
803
+ <div class="header">
804
+ <h3>lib/devise/secure_password/controllers/active_helpers.rb</h3>
805
+ <h4><span class="yellow">83.33 %</span> covered</h4>
806
+ <div>
807
+ <b>18</b> relevant lines.
808
+ <span class="green"><b>15</b> lines covered</span> and
809
+ <span class="red"><b>3</b> lines missed.</span>
810
+ </div>
811
+ </div>
812
+
813
+ <pre>
814
+ <ol>
815
+
816
+ <li class="covered" data-hits="1" data-linenumber="1">
817
+ <span class="hits">1</span>
818
+
819
+ <code class="ruby">module Devise</code>
820
+ </li>
821
+
822
+ <li class="covered" data-hits="1" data-linenumber="2">
823
+ <span class="hits">1</span>
824
+
825
+ <code class="ruby"> module SecurePassword</code>
826
+ </li>
827
+
828
+ <li class="covered" data-hits="1" data-linenumber="3">
829
+ <span class="hits">1</span>
830
+
831
+ <code class="ruby"> module Controllers</code>
832
+ </li>
833
+
834
+ <li class="covered" data-hits="1" data-linenumber="4">
835
+ <span class="hits">1</span>
836
+
837
+ <code class="ruby"> module ActiveHelpers</code>
838
+ </li>
839
+
840
+ <li class="covered" data-hits="1" data-linenumber="5">
841
+ <span class="hits">1</span>
842
+
843
+ <code class="ruby"> extend ActiveSupport::Concern</code>
844
+ </li>
845
+
846
+ <li class="never" data-hits="" data-linenumber="6">
847
+
848
+
849
+ <code class="ruby"></code>
850
+ </li>
851
+
852
+ <li class="covered" data-hits="1" data-linenumber="7">
853
+ <span class="hits">1</span>
854
+
855
+ <code class="ruby"> included do</code>
856
+ </li>
857
+
858
+ <li class="covered" data-hits="1" data-linenumber="8">
859
+ <span class="hits">1</span>
860
+
861
+ <code class="ruby"> before_action :pending_password_expired_redirect!, except: [:destroy]</code>
862
+ </li>
863
+
864
+ <li class="never" data-hits="" data-linenumber="9">
865
+
866
+
867
+ <code class="ruby"> end</code>
868
+ </li>
869
+
870
+ <li class="never" data-hits="" data-linenumber="10">
871
+
872
+
873
+ <code class="ruby"></code>
874
+ </li>
875
+
876
+ <li class="never" data-hits="" data-linenumber="11">
877
+
878
+
879
+ <code class="ruby"> # Redirect to password change page if password needs to be changed.</code>
880
+ </li>
881
+
882
+ <li class="covered" data-hits="1" data-linenumber="12">
883
+ <span class="hits">1</span>
884
+
885
+ <code class="ruby"> def pending_password_expired_redirect!</code>
886
+ </li>
887
+
888
+ <li class="covered" data-hits="9" data-linenumber="13">
889
+ <span class="hits">9</span>
890
+
891
+ <code class="ruby"> return unless skip_current_controller? &amp;&amp; redirected_in_session? &amp;&amp; warden.session &amp;&amp; warden.session[&#39;secure_password_expired&#39;]</code>
892
+ </li>
893
+
894
+ <li class="missed" data-hits="0" data-linenumber="14">
895
+
896
+
897
+ <code class="ruby"> redirect_to edit_user_password_with_policy_url, alert: &quot;#{error_string_for_password_expired}.&quot;</code>
898
+ </li>
899
+
900
+ <li class="never" data-hits="" data-linenumber="15">
901
+
902
+
903
+ <code class="ruby"> end</code>
904
+ </li>
905
+
906
+ <li class="never" data-hits="" data-linenumber="16">
907
+
908
+
909
+ <code class="ruby"></code>
910
+ </li>
911
+
912
+ <li class="covered" data-hits="1" data-linenumber="17">
913
+ <span class="hits">1</span>
914
+
915
+ <code class="ruby"> def redirected_in_session?</code>
916
+ </li>
917
+
918
+ <li class="covered" data-hits="2" data-linenumber="18">
919
+ <span class="hits">2</span>
920
+
921
+ <code class="ruby"> warden.authenticated? &amp;&amp; warden.session[&#39;secure_password_last_controller&#39;] == &#39;Devise::SessionsController&#39;</code>
922
+ </li>
923
+
924
+ <li class="never" data-hits="" data-linenumber="19">
925
+
926
+
927
+ <code class="ruby"> end</code>
928
+ </li>
929
+
930
+ <li class="never" data-hits="" data-linenumber="20">
931
+
932
+
933
+ <code class="ruby"></code>
934
+ </li>
935
+
936
+ <li class="never" data-hits="" data-linenumber="21">
937
+
938
+
939
+ <code class="ruby"> # Prevent infinite loops and allow specified controllers to bypass.</code>
940
+ </li>
941
+
942
+ <li class="never" data-hits="" data-linenumber="22">
943
+
944
+
945
+ <code class="ruby"> # @NOTE: The ability to extend this list may be made public, in the</code>
946
+ </li>
947
+
948
+ <li class="never" data-hits="" data-linenumber="23">
949
+
950
+
951
+ <code class="ruby"> # future if that functionality is needed.</code>
952
+ </li>
953
+
954
+ <li class="covered" data-hits="1" data-linenumber="24">
955
+ <span class="hits">1</span>
956
+
957
+ <code class="ruby"> def skip_current_controller?</code>
958
+ </li>
959
+
960
+ <li class="covered" data-hits="9" data-linenumber="25">
961
+ <span class="hits">9</span>
962
+
963
+ <code class="ruby"> exclusion_list = [</code>
964
+ </li>
965
+
966
+ <li class="never" data-hits="" data-linenumber="26">
967
+
968
+
969
+ <code class="ruby"> &#39;Devise::SessionsController&#39;,</code>
970
+ </li>
971
+
972
+ <li class="never" data-hits="" data-linenumber="27">
973
+
974
+
975
+ <code class="ruby"> &#39;Devise::PasswordsWithPolicyController#edit&#39;,</code>
976
+ </li>
977
+
978
+ <li class="never" data-hits="" data-linenumber="28">
979
+
980
+
981
+ <code class="ruby"> &#39;Devise::PasswordsWithPolicyController#update&#39;,</code>
982
+ </li>
983
+
984
+ <li class="never" data-hits="" data-linenumber="29">
985
+
986
+
987
+ <code class="ruby"> &#39;DeviseInvitable::RegistrationsController#edit&#39;,</code>
988
+ </li>
989
+
990
+ <li class="never" data-hits="" data-linenumber="30">
991
+
992
+
993
+ <code class="ruby"> &#39;DeviseInvitable::RegistrationsController#update&#39;</code>
994
+ </li>
995
+
996
+ <li class="never" data-hits="" data-linenumber="31">
997
+
998
+
999
+ <code class="ruby"> ]</code>
1000
+ </li>
1001
+
1002
+ <li class="covered" data-hits="9" data-linenumber="32">
1003
+ <span class="hits">9</span>
1004
+
1005
+ <code class="ruby"> !(exclusion_list.include?(&quot;#{self.class.name}#&quot; + action_name) || (exclusion_list &amp; self.class.ancestors.map(&amp;:to_s)).any?)</code>
1006
+ </li>
1007
+
1008
+ <li class="never" data-hits="" data-linenumber="33">
1009
+
1010
+
1011
+ <code class="ruby"> end</code>
1012
+ </li>
1013
+
1014
+ <li class="never" data-hits="" data-linenumber="34">
1015
+
1016
+
1017
+ <code class="ruby"></code>
1018
+ </li>
1019
+
1020
+ <li class="covered" data-hits="1" data-linenumber="35">
1021
+ <span class="hits">1</span>
1022
+
1023
+ <code class="ruby"> def error_string_for_password_expired</code>
1024
+ </li>
1025
+
1026
+ <li class="missed" data-hits="0" data-linenumber="36">
1027
+
1028
+
1029
+ <code class="ruby"> return &#39;password expired&#39; unless warden.user.class.respond_to?(:password_maximum_age)</code>
1030
+ </li>
1031
+
1032
+ <li class="missed" data-hits="0" data-linenumber="37">
1033
+
1034
+
1035
+ <code class="ruby"> I18n.t(</code>
1036
+ </li>
1037
+
1038
+ <li class="never" data-hits="" data-linenumber="38">
1039
+
1040
+
1041
+ <code class="ruby"> &#39;secure_password.password_requires_regular_updates.errors.messages.password_expired&#39;,</code>
1042
+ </li>
1043
+
1044
+ <li class="never" data-hits="" data-linenumber="39">
1045
+
1046
+
1047
+ <code class="ruby"> timeframe: distance_of_time_in_words(warden.user.class.password_maximum_age)</code>
1048
+ </li>
1049
+
1050
+ <li class="never" data-hits="" data-linenumber="40">
1051
+
1052
+
1053
+ <code class="ruby"> )</code>
1054
+ </li>
1055
+
1056
+ <li class="never" data-hits="" data-linenumber="41">
1057
+
1058
+
1059
+ <code class="ruby"> end</code>
1060
+ </li>
1061
+
1062
+ <li class="never" data-hits="" data-linenumber="42">
1063
+
1064
+
1065
+ <code class="ruby"> end</code>
1066
+ </li>
1067
+
1068
+ <li class="never" data-hits="" data-linenumber="43">
1069
+
1070
+
1071
+ <code class="ruby"> end</code>
1072
+ </li>
1073
+
1074
+ <li class="never" data-hits="" data-linenumber="44">
1075
+
1076
+
1077
+ <code class="ruby"> end</code>
1078
+ </li>
1079
+
1080
+ <li class="never" data-hits="" data-linenumber="45">
1081
+
1082
+
1083
+ <code class="ruby">end</code>
1084
+ </li>
1085
+
1086
+ </ol>
1087
+ </pre>
1088
+ </div>
1089
+
1090
+
1091
+ <div class="source_table" id="9bf8b097105760cbd1fc5724ce787f72c57b574b">
1092
+ <div class="header">
1093
+ <h3>lib/devise/secure_password/controllers/devise_helpers.rb</h3>
1094
+ <h4><span class="green">100.0 %</span> covered</h4>
1095
+ <div>
1096
+ <b>28</b> relevant lines.
1097
+ <span class="green"><b>28</b> lines covered</span> and
1098
+ <span class="red"><b>0</b> lines missed.</span>
1099
+ </div>
1100
+ </div>
1101
+
1102
+ <pre>
1103
+ <ol>
1104
+
1105
+ <li class="covered" data-hits="1" data-linenumber="1">
1106
+ <span class="hits">1</span>
1107
+
1108
+ <code class="ruby">module Devise</code>
1109
+ </li>
1110
+
1111
+ <li class="covered" data-hits="1" data-linenumber="2">
1112
+ <span class="hits">1</span>
1113
+
1114
+ <code class="ruby"> module SecurePassword</code>
1115
+ </li>
1116
+
1117
+ <li class="covered" data-hits="1" data-linenumber="3">
1118
+ <span class="hits">1</span>
1119
+
1120
+ <code class="ruby"> module Controllers</code>
1121
+ </li>
1122
+
1123
+ <li class="covered" data-hits="1" data-linenumber="4">
1124
+ <span class="hits">1</span>
1125
+
1126
+ <code class="ruby"> module DeviseHelpers</code>
1127
+ </li>
1128
+
1129
+ <li class="covered" data-hits="1" data-linenumber="5">
1130
+ <span class="hits">1</span>
1131
+
1132
+ <code class="ruby"> extend ActiveSupport::Concern</code>
1133
+ </li>
1134
+
1135
+ <li class="never" data-hits="" data-linenumber="6">
1136
+
1137
+
1138
+ <code class="ruby"></code>
1139
+ </li>
1140
+
1141
+ <li class="never" data-hits="" data-linenumber="7">
1142
+
1143
+
1144
+ <code class="ruby"> # rubocop:disable Style/ClassAndModuleChildren</code>
1145
+ </li>
1146
+
1147
+ <li class="covered" data-hits="1" data-linenumber="8">
1148
+ <span class="hits">1</span>
1149
+
1150
+ <code class="ruby"> class ::DeviseController</code>
1151
+ </li>
1152
+
1153
+ <li class="covered" data-hits="1" data-linenumber="9">
1154
+ <span class="hits">1</span>
1155
+
1156
+ <code class="ruby"> alias old_require_no_authentication require_no_authentication</code>
1157
+ </li>
1158
+
1159
+ <li class="never" data-hits="" data-linenumber="10">
1160
+
1161
+
1162
+ <code class="ruby"></code>
1163
+ </li>
1164
+
1165
+ <li class="covered" data-hits="1" data-linenumber="11">
1166
+ <span class="hits">1</span>
1167
+
1168
+ <code class="ruby"> protected</code>
1169
+ </li>
1170
+
1171
+ <li class="never" data-hits="" data-linenumber="12">
1172
+
1173
+
1174
+ <code class="ruby"></code>
1175
+ </li>
1176
+
1177
+ <li class="never" data-hits="" data-linenumber="13">
1178
+
1179
+
1180
+ <code class="ruby"> # Override the devise require_no_authentication before callback to</code>
1181
+ </li>
1182
+
1183
+ <li class="never" data-hits="" data-linenumber="14">
1184
+
1185
+
1186
+ <code class="ruby"> # prevent authenticated users with expired passwords from escaping to</code>
1187
+ </li>
1188
+
1189
+ <li class="never" data-hits="" data-linenumber="15">
1190
+
1191
+
1192
+ <code class="ruby"> # other pages without first updating their passwords.</code>
1193
+ </li>
1194
+
1195
+ <li class="covered" data-hits="1" data-linenumber="16">
1196
+ <span class="hits">1</span>
1197
+
1198
+ <code class="ruby"> def require_no_authentication</code>
1199
+ </li>
1200
+
1201
+ <li class="covered" data-hits="4" data-linenumber="17">
1202
+ <span class="hits">4</span>
1203
+
1204
+ <code class="ruby"> return if check_password_expired_and_redirect!</code>
1205
+ </li>
1206
+
1207
+ <li class="never" data-hits="" data-linenumber="18">
1208
+
1209
+
1210
+ <code class="ruby"></code>
1211
+ </li>
1212
+
1213
+ <li class="covered" data-hits="3" data-linenumber="19">
1214
+ <span class="hits">3</span>
1215
+
1216
+ <code class="ruby"> old_require_no_authentication</code>
1217
+ </li>
1218
+
1219
+ <li class="never" data-hits="" data-linenumber="20">
1220
+
1221
+
1222
+ <code class="ruby"> end</code>
1223
+ </li>
1224
+
1225
+ <li class="never" data-hits="" data-linenumber="21">
1226
+
1227
+
1228
+ <code class="ruby"></code>
1229
+ </li>
1230
+
1231
+ <li class="never" data-hits="" data-linenumber="22">
1232
+
1233
+
1234
+ <code class="ruby"> # Store the name of the current controller and action in the warden</code>
1235
+ </li>
1236
+
1237
+ <li class="never" data-hits="" data-linenumber="23">
1238
+
1239
+
1240
+ <code class="ruby"> # session store then redirect if signed in and password expired. The</code>
1241
+ </li>
1242
+
1243
+ <li class="never" data-hits="" data-linenumber="24">
1244
+
1245
+
1246
+ <code class="ruby"> # stored values will be used by non-devise controllers to prevent a</code>
1247
+ </li>
1248
+
1249
+ <li class="never" data-hits="" data-linenumber="25">
1250
+
1251
+
1252
+ <code class="ruby"> # user from escaping the change password process.</code>
1253
+ </li>
1254
+
1255
+ <li class="covered" data-hits="1" data-linenumber="26">
1256
+ <span class="hits">1</span>
1257
+
1258
+ <code class="ruby"> def check_password_expired_and_redirect!</code>
1259
+ </li>
1260
+
1261
+ <li class="covered" data-hits="4" data-linenumber="27">
1262
+ <span class="hits">4</span>
1263
+
1264
+ <code class="ruby"> assert_is_devise_resource!</code>
1265
+ </li>
1266
+
1267
+ <li class="never" data-hits="" data-linenumber="28">
1268
+
1269
+
1270
+ <code class="ruby"></code>
1271
+ </li>
1272
+
1273
+ <li class="covered" data-hits="4" data-linenumber="29">
1274
+ <span class="hits">4</span>
1275
+
1276
+ <code class="ruby"> return if skip_current_devise_controller?</code>
1277
+ </li>
1278
+
1279
+ <li class="never" data-hits="" data-linenumber="30">
1280
+
1281
+
1282
+ <code class="ruby"></code>
1283
+ </li>
1284
+
1285
+ <li class="covered" data-hits="4" data-linenumber="31">
1286
+ <span class="hits">4</span>
1287
+
1288
+ <code class="ruby"> if signed_in?(scope_name) &amp;&amp; warden.session(scope_name)[:secure_password_expired]</code>
1289
+ </li>
1290
+
1291
+ <li class="covered" data-hits="1" data-linenumber="32">
1292
+ <span class="hits">1</span>
1293
+
1294
+ <code class="ruby"> save_controller_state</code>
1295
+ </li>
1296
+
1297
+ <li class="covered" data-hits="1" data-linenumber="33">
1298
+ <span class="hits">1</span>
1299
+
1300
+ <code class="ruby"> redirect_to edit_user_password_with_policy_url, alert: &quot;#{error_string_for_password_expired}.&quot;</code>
1301
+ </li>
1302
+
1303
+ <li class="covered" data-hits="1" data-linenumber="34">
1304
+ <span class="hits">1</span>
1305
+
1306
+ <code class="ruby"> return true</code>
1307
+ </li>
1308
+
1309
+ <li class="never" data-hits="" data-linenumber="35">
1310
+
1311
+
1312
+ <code class="ruby"> end</code>
1313
+ </li>
1314
+
1315
+ <li class="never" data-hits="" data-linenumber="36">
1316
+
1317
+
1318
+ <code class="ruby"></code>
1319
+ </li>
1320
+
1321
+ <li class="covered" data-hits="3" data-linenumber="37">
1322
+ <span class="hits">3</span>
1323
+
1324
+ <code class="ruby"> false</code>
1325
+ </li>
1326
+
1327
+ <li class="never" data-hits="" data-linenumber="38">
1328
+
1329
+
1330
+ <code class="ruby"> end</code>
1331
+ </li>
1332
+
1333
+ <li class="never" data-hits="" data-linenumber="39">
1334
+
1335
+
1336
+ <code class="ruby"></code>
1337
+ </li>
1338
+
1339
+ <li class="covered" data-hits="1" data-linenumber="40">
1340
+ <span class="hits">1</span>
1341
+
1342
+ <code class="ruby"> def save_controller_state</code>
1343
+ </li>
1344
+
1345
+ <li class="covered" data-hits="1" data-linenumber="41">
1346
+ <span class="hits">1</span>
1347
+
1348
+ <code class="ruby"> warden.session(scope_name)[:secure_last_controller] = self.class.name</code>
1349
+ </li>
1350
+
1351
+ <li class="covered" data-hits="1" data-linenumber="42">
1352
+ <span class="hits">1</span>
1353
+
1354
+ <code class="ruby"> warden.session(scope_name)[:secure_last_action] = action_name</code>
1355
+ </li>
1356
+
1357
+ <li class="never" data-hits="" data-linenumber="43">
1358
+
1359
+
1360
+ <code class="ruby"> end</code>
1361
+ </li>
1362
+
1363
+ <li class="never" data-hits="" data-linenumber="44">
1364
+
1365
+
1366
+ <code class="ruby"></code>
1367
+ </li>
1368
+
1369
+ <li class="never" data-hits="" data-linenumber="45">
1370
+
1371
+
1372
+ <code class="ruby"> # Prevent infinite loops and allow specified controllers to bypass.</code>
1373
+ </li>
1374
+
1375
+ <li class="never" data-hits="" data-linenumber="46">
1376
+
1377
+
1378
+ <code class="ruby"> # @NOTE: The ability to extend this list may be made public, in the</code>
1379
+ </li>
1380
+
1381
+ <li class="never" data-hits="" data-linenumber="47">
1382
+
1383
+
1384
+ <code class="ruby"> # future if that functionality is needed.</code>
1385
+ </li>
1386
+
1387
+ <li class="covered" data-hits="1" data-linenumber="48">
1388
+ <span class="hits">1</span>
1389
+
1390
+ <code class="ruby"> def skip_current_devise_controller?</code>
1391
+ </li>
1392
+
1393
+ <li class="covered" data-hits="4" data-linenumber="49">
1394
+ <span class="hits">4</span>
1395
+
1396
+ <code class="ruby"> exclusion_list = [</code>
1397
+ </li>
1398
+
1399
+ <li class="never" data-hits="" data-linenumber="50">
1400
+
1401
+
1402
+ <code class="ruby"> &#39;Devise::SessionsController&#39;</code>
1403
+ </li>
1404
+
1405
+ <li class="never" data-hits="" data-linenumber="51">
1406
+
1407
+
1408
+ <code class="ruby"> ]</code>
1409
+ </li>
1410
+
1411
+ <li class="covered" data-hits="4" data-linenumber="52">
1412
+ <span class="hits">4</span>
1413
+
1414
+ <code class="ruby"> !(exclusion_list.include?(&quot;#{self.class.name}#&quot; + action_name) || (exclusion_list &amp; self.class.ancestors.map(&amp;:to_s)).any?)</code>
1415
+ </li>
1416
+
1417
+ <li class="never" data-hits="" data-linenumber="53">
1418
+
1419
+
1420
+ <code class="ruby"> end</code>
1421
+ </li>
1422
+
1423
+ <li class="never" data-hits="" data-linenumber="54">
1424
+
1425
+
1426
+ <code class="ruby"></code>
1427
+ </li>
1428
+
1429
+ <li class="covered" data-hits="1" data-linenumber="55">
1430
+ <span class="hits">1</span>
1431
+
1432
+ <code class="ruby"> def error_string_for_password_expired</code>
1433
+ </li>
1434
+
1435
+ <li class="covered" data-hits="1" data-linenumber="56">
1436
+ <span class="hits">1</span>
1437
+
1438
+ <code class="ruby"> class_obj = scope_name.to_s.camelize.constantize</code>
1439
+ </li>
1440
+
1441
+ <li class="covered" data-hits="1" data-linenumber="57">
1442
+ <span class="hits">1</span>
1443
+
1444
+ <code class="ruby"> I18n.t(</code>
1445
+ </li>
1446
+
1447
+ <li class="never" data-hits="" data-linenumber="58">
1448
+
1449
+
1450
+ <code class="ruby"> &#39;secure_password.password_requires_regular_updates.errors.messages.password_expired&#39;,</code>
1451
+ </li>
1452
+
1453
+ <li class="never" data-hits="" data-linenumber="59">
1454
+
1455
+
1456
+ <code class="ruby"> timeframe: distance_of_time_in_words(class_obj.password_maximum_age)</code>
1457
+ </li>
1458
+
1459
+ <li class="never" data-hits="" data-linenumber="60">
1460
+
1461
+
1462
+ <code class="ruby"> )</code>
1463
+ </li>
1464
+
1465
+ <li class="never" data-hits="" data-linenumber="61">
1466
+
1467
+
1468
+ <code class="ruby"> end</code>
1469
+ </li>
1470
+
1471
+ <li class="never" data-hits="" data-linenumber="62">
1472
+
1473
+
1474
+ <code class="ruby"> end</code>
1475
+ </li>
1476
+
1477
+ <li class="never" data-hits="" data-linenumber="63">
1478
+
1479
+
1480
+ <code class="ruby"> # rubocop:enable Style/ClassAndModuleChildren</code>
1481
+ </li>
1482
+
1483
+ <li class="never" data-hits="" data-linenumber="64">
1484
+
1485
+
1486
+ <code class="ruby"> end</code>
1487
+ </li>
1488
+
1489
+ <li class="never" data-hits="" data-linenumber="65">
1490
+
1491
+
1492
+ <code class="ruby"> end</code>
1493
+ </li>
1494
+
1495
+ <li class="never" data-hits="" data-linenumber="66">
1496
+
1497
+
1498
+ <code class="ruby"> end</code>
1499
+ </li>
1500
+
1501
+ <li class="never" data-hits="" data-linenumber="67">
1502
+
1503
+
1504
+ <code class="ruby">end</code>
1505
+ </li>
1506
+
1507
+ </ol>
1508
+ </pre>
1509
+ </div>
1510
+
1511
+
1512
+ <div class="source_table" id="3eef7cc16f9ee559a604a48522ee19887f890bd9">
1513
+ <div class="header">
1514
+ <h3>lib/devise/secure_password/hooks/password_requires_regular_updates.rb</h3>
1515
+ <h4><span class="green">100.0 %</span> covered</h4>
1516
+ <div>
1517
+ <b>3</b> relevant lines.
1518
+ <span class="green"><b>3</b> lines covered</span> and
1519
+ <span class="red"><b>0</b> lines missed.</span>
1520
+ </div>
1521
+ </div>
1522
+
1523
+ <pre>
1524
+ <ol>
1525
+
1526
+ <li class="covered" data-hits="1" data-linenumber="1">
1527
+ <span class="hits">1</span>
1528
+
1529
+ <code class="ruby">Warden::Manager.after_authentication do |user, warden, options|</code>
1530
+ </li>
1531
+
1532
+ <li class="covered" data-hits="4" data-linenumber="2">
1533
+ <span class="hits">4</span>
1534
+
1535
+ <code class="ruby"> if user.respond_to?(:password_expired?)</code>
1536
+ </li>
1537
+
1538
+ <li class="covered" data-hits="4" data-linenumber="3">
1539
+ <span class="hits">4</span>
1540
+
1541
+ <code class="ruby"> warden.session(options[:scope])[:secure_password_expired] = user.password_expired?</code>
1542
+ </li>
1543
+
1544
+ <li class="never" data-hits="" data-linenumber="4">
1545
+
1546
+
1547
+ <code class="ruby"> end</code>
1548
+ </li>
1549
+
1550
+ <li class="never" data-hits="" data-linenumber="5">
1551
+
1552
+
1553
+ <code class="ruby">end</code>
1554
+ </li>
1555
+
1556
+ </ol>
1557
+ </pre>
1558
+ </div>
1559
+
1560
+
1561
+ <div class="source_table" id="96cdbb86efe2f2f9b0e36ed8c91f1a8c0cdcedd8">
1562
+ <div class="header">
1563
+ <h3>lib/devise/secure_password/models/password_disallows_frequent_changes.rb</h3>
1564
+ <h4><span class="green">96.3 %</span> covered</h4>
1565
+ <div>
1566
+ <b>27</b> relevant lines.
1567
+ <span class="green"><b>26</b> lines covered</span> and
1568
+ <span class="red"><b>1</b> lines missed.</span>
1569
+ </div>
1570
+ </div>
1571
+
1572
+ <pre>
1573
+ <ol>
1574
+
1575
+ <li class="covered" data-hits="1" data-linenumber="1">
1576
+ <span class="hits">1</span>
1577
+
1578
+ <code class="ruby">module Devise</code>
1579
+ </li>
1580
+
1581
+ <li class="covered" data-hits="1" data-linenumber="2">
1582
+ <span class="hits">1</span>
1583
+
1584
+ <code class="ruby"> module Models</code>
1585
+ </li>
1586
+
1587
+ <li class="covered" data-hits="1" data-linenumber="3">
1588
+ <span class="hits">1</span>
1589
+
1590
+ <code class="ruby"> module PasswordDisallowsFrequentChanges</code>
1591
+ </li>
1592
+
1593
+ <li class="covered" data-hits="1" data-linenumber="4">
1594
+ <span class="hits">1</span>
1595
+
1596
+ <code class="ruby"> extend ActiveSupport::Concern</code>
1597
+ </li>
1598
+
1599
+ <li class="never" data-hits="" data-linenumber="5">
1600
+
1601
+
1602
+ <code class="ruby"></code>
1603
+ </li>
1604
+
1605
+ <li class="covered" data-hits="1" data-linenumber="6">
1606
+ <span class="hits">1</span>
1607
+
1608
+ <code class="ruby"> class ConfigurationError &lt; RuntimeError; end</code>
1609
+ </li>
1610
+
1611
+ <li class="never" data-hits="" data-linenumber="7">
1612
+
1613
+
1614
+ <code class="ruby"></code>
1615
+ </li>
1616
+
1617
+ <li class="covered" data-hits="1" data-linenumber="8">
1618
+ <span class="hits">1</span>
1619
+
1620
+ <code class="ruby"> included do</code>
1621
+ </li>
1622
+
1623
+ <li class="covered" data-hits="4" data-linenumber="9">
1624
+ <span class="hits">4</span>
1625
+
1626
+ <code class="ruby"> include ActionView::Helpers::DateHelper</code>
1627
+ </li>
1628
+
1629
+ <li class="covered" data-hits="4" data-linenumber="10">
1630
+ <span class="hits">4</span>
1631
+
1632
+ <code class="ruby"> validate :validate_password_frequent_change, if: :password_required?</code>
1633
+ </li>
1634
+
1635
+ <li class="never" data-hits="" data-linenumber="11">
1636
+
1637
+
1638
+ <code class="ruby"></code>
1639
+ </li>
1640
+
1641
+ <li class="covered" data-hits="4" data-linenumber="12">
1642
+ <span class="hits">4</span>
1643
+
1644
+ <code class="ruby"> set_callback(:initialize, :before, :before_resource_initialized)</code>
1645
+ </li>
1646
+
1647
+ <li class="covered" data-hits="4" data-linenumber="13">
1648
+ <span class="hits">4</span>
1649
+
1650
+ <code class="ruby"> set_callback(:initialize, :after, :after_resource_initialized)</code>
1651
+ </li>
1652
+
1653
+ <li class="never" data-hits="" data-linenumber="14">
1654
+
1655
+
1656
+ <code class="ruby"> end</code>
1657
+ </li>
1658
+
1659
+ <li class="never" data-hits="" data-linenumber="15">
1660
+
1661
+
1662
+ <code class="ruby"></code>
1663
+ </li>
1664
+
1665
+ <li class="covered" data-hits="1" data-linenumber="16">
1666
+ <span class="hits">1</span>
1667
+
1668
+ <code class="ruby"> def validate_password_frequent_change</code>
1669
+ </li>
1670
+
1671
+ <li class="covered" data-hits="13" data-linenumber="17">
1672
+ <span class="hits">13</span>
1673
+
1674
+ <code class="ruby"> if encrypted_password_changed? &amp;&amp; password_recent?</code>
1675
+ </li>
1676
+
1677
+ <li class="covered" data-hits="4" data-linenumber="18">
1678
+ <span class="hits">4</span>
1679
+
1680
+ <code class="ruby"> error_string = I18n.t(</code>
1681
+ </li>
1682
+
1683
+ <li class="never" data-hits="" data-linenumber="19">
1684
+
1685
+
1686
+ <code class="ruby"> &#39;secure_password.password_disallows_frequent_changes.errors.messages.password_is_recent&#39;,</code>
1687
+ </li>
1688
+
1689
+ <li class="never" data-hits="" data-linenumber="20">
1690
+
1691
+
1692
+ <code class="ruby"> timeframe: distance_of_time_in_words(self.class.password_minimum_age)</code>
1693
+ </li>
1694
+
1695
+ <li class="never" data-hits="" data-linenumber="21">
1696
+
1697
+
1698
+ <code class="ruby"> )</code>
1699
+ </li>
1700
+
1701
+ <li class="covered" data-hits="4" data-linenumber="22">
1702
+ <span class="hits">4</span>
1703
+
1704
+ <code class="ruby"> errors.add(:base, error_string)</code>
1705
+ </li>
1706
+
1707
+ <li class="never" data-hits="" data-linenumber="23">
1708
+
1709
+
1710
+ <code class="ruby"> end</code>
1711
+ </li>
1712
+
1713
+ <li class="never" data-hits="" data-linenumber="24">
1714
+
1715
+
1716
+ <code class="ruby"></code>
1717
+ </li>
1718
+
1719
+ <li class="covered" data-hits="13" data-linenumber="25">
1720
+ <span class="hits">13</span>
1721
+
1722
+ <code class="ruby"> errors.count.zero?</code>
1723
+ </li>
1724
+
1725
+ <li class="never" data-hits="" data-linenumber="26">
1726
+
1727
+
1728
+ <code class="ruby"> end</code>
1729
+ </li>
1730
+
1731
+ <li class="never" data-hits="" data-linenumber="27">
1732
+
1733
+
1734
+ <code class="ruby"></code>
1735
+ </li>
1736
+
1737
+ <li class="covered" data-hits="1" data-linenumber="28">
1738
+ <span class="hits">1</span>
1739
+
1740
+ <code class="ruby"> def password_recent?</code>
1741
+ </li>
1742
+
1743
+ <li class="covered" data-hits="15" data-linenumber="29">
1744
+ <span class="hits">15</span>
1745
+
1746
+ <code class="ruby"> last_password = previous_passwords.unscoped.last</code>
1747
+ </li>
1748
+
1749
+ <li class="covered" data-hits="15" data-linenumber="30">
1750
+ <span class="hits">15</span>
1751
+
1752
+ <code class="ruby"> last_password&amp;.fresh?(self.class.password_minimum_age)</code>
1753
+ </li>
1754
+
1755
+ <li class="never" data-hits="" data-linenumber="31">
1756
+
1757
+
1758
+ <code class="ruby"> end</code>
1759
+ </li>
1760
+
1761
+ <li class="never" data-hits="" data-linenumber="32">
1762
+
1763
+
1764
+ <code class="ruby"></code>
1765
+ </li>
1766
+
1767
+ <li class="covered" data-hits="1" data-linenumber="33">
1768
+ <span class="hits">1</span>
1769
+
1770
+ <code class="ruby"> protected</code>
1771
+ </li>
1772
+
1773
+ <li class="never" data-hits="" data-linenumber="34">
1774
+
1775
+
1776
+ <code class="ruby"></code>
1777
+ </li>
1778
+
1779
+ <li class="covered" data-hits="1" data-linenumber="35">
1780
+ <span class="hits">1</span>
1781
+
1782
+ <code class="ruby"> def before_resource_initialized</code>
1783
+ </li>
1784
+
1785
+ <li class="covered" data-hits="24" data-linenumber="36">
1786
+ <span class="hits">24</span>
1787
+
1788
+ <code class="ruby"> return if self.class.respond_to?(:password_previously_used_count)</code>
1789
+ </li>
1790
+
1791
+ <li class="never" data-hits="" data-linenumber="37">
1792
+
1793
+
1794
+ <code class="ruby"></code>
1795
+ </li>
1796
+
1797
+ <li class="covered" data-hits="2" data-linenumber="38">
1798
+ <span class="hits">2</span>
1799
+
1800
+ <code class="ruby"> raise ConfigurationError, &lt;&lt;-ERROR.strip_heredoc</code>
1801
+ </li>
1802
+
1803
+ <li class="never" data-hits="" data-linenumber="39">
1804
+
1805
+
1806
+ <code class="ruby"></code>
1807
+ </li>
1808
+
1809
+ <li class="never" data-hits="" data-linenumber="40">
1810
+
1811
+
1812
+ <code class="ruby"> The password_disallows_frequent_changes module depends on the</code>
1813
+ </li>
1814
+
1815
+ <li class="never" data-hits="" data-linenumber="41">
1816
+
1817
+
1818
+ <code class="ruby"> password_disallows_frequent_reuse module. Verify that you have</code>
1819
+ </li>
1820
+
1821
+ <li class="never" data-hits="" data-linenumber="42">
1822
+
1823
+
1824
+ <code class="ruby"> added both modules to your model, for example:</code>
1825
+ </li>
1826
+
1827
+ <li class="never" data-hits="" data-linenumber="43">
1828
+
1829
+
1830
+ <code class="ruby"></code>
1831
+ </li>
1832
+
1833
+ <li class="never" data-hits="" data-linenumber="44">
1834
+
1835
+
1836
+ <code class="ruby"> devise :database_authenticatable, :registerable,</code>
1837
+ </li>
1838
+
1839
+ <li class="never" data-hits="" data-linenumber="45">
1840
+
1841
+
1842
+ <code class="ruby"> :password_disallows_frequent_reuse,</code>
1843
+ </li>
1844
+
1845
+ <li class="never" data-hits="" data-linenumber="46">
1846
+
1847
+
1848
+ <code class="ruby"> :password_disallows_frequent_changes</code>
1849
+ </li>
1850
+
1851
+ <li class="never" data-hits="" data-linenumber="47">
1852
+
1853
+
1854
+ <code class="ruby"> ERROR</code>
1855
+ </li>
1856
+
1857
+ <li class="never" data-hits="" data-linenumber="48">
1858
+
1859
+
1860
+ <code class="ruby"> end</code>
1861
+ </li>
1862
+
1863
+ <li class="never" data-hits="" data-linenumber="49">
1864
+
1865
+
1866
+ <code class="ruby"></code>
1867
+ </li>
1868
+
1869
+ <li class="covered" data-hits="1" data-linenumber="50">
1870
+ <span class="hits">1</span>
1871
+
1872
+ <code class="ruby"> def after_resource_initialized</code>
1873
+ </li>
1874
+
1875
+ <li class="missed" data-hits="0" data-linenumber="51">
1876
+
1877
+
1878
+ <code class="ruby"> raise ConfigurationError, &#39;invalid type for password_minimum_age&#39; \</code>
1879
+ </li>
1880
+
1881
+ <li class="covered" data-hits="22" data-linenumber="52">
1882
+ <span class="hits">22</span>
1883
+
1884
+ <code class="ruby"> unless self.class.password_minimum_age.is_a?(::ActiveSupport::Duration)</code>
1885
+ </li>
1886
+
1887
+ <li class="never" data-hits="" data-linenumber="53">
1888
+
1889
+
1890
+ <code class="ruby"> end</code>
1891
+ </li>
1892
+
1893
+ <li class="never" data-hits="" data-linenumber="54">
1894
+
1895
+
1896
+ <code class="ruby"></code>
1897
+ </li>
1898
+
1899
+ <li class="covered" data-hits="1" data-linenumber="55">
1900
+ <span class="hits">1</span>
1901
+
1902
+ <code class="ruby"> module ClassMethods</code>
1903
+ </li>
1904
+
1905
+ <li class="covered" data-hits="1" data-linenumber="56">
1906
+ <span class="hits">1</span>
1907
+
1908
+ <code class="ruby"> ::Devise::Models.config(self, :password_minimum_age)</code>
1909
+ </li>
1910
+
1911
+ <li class="never" data-hits="" data-linenumber="57">
1912
+
1913
+
1914
+ <code class="ruby"> end</code>
1915
+ </li>
1916
+
1917
+ <li class="never" data-hits="" data-linenumber="58">
1918
+
1919
+
1920
+ <code class="ruby"> end</code>
1921
+ </li>
1922
+
1923
+ <li class="never" data-hits="" data-linenumber="59">
1924
+
1925
+
1926
+ <code class="ruby"> end</code>
1927
+ </li>
1928
+
1929
+ <li class="never" data-hits="" data-linenumber="60">
1930
+
1931
+
1932
+ <code class="ruby">end</code>
1933
+ </li>
1934
+
1935
+ </ol>
1936
+ </pre>
1937
+ </div>
1938
+
1939
+
1940
+ <div class="source_table" id="b2e3e1d1ac33418c11b262e1e2ff2a852214bd4e">
1941
+ <div class="header">
1942
+ <h3>lib/devise/secure_password/models/password_disallows_frequent_reuse.rb</h3>
1943
+ <h4><span class="green">97.3 %</span> covered</h4>
1944
+ <div>
1945
+ <b>37</b> relevant lines.
1946
+ <span class="green"><b>36</b> lines covered</span> and
1947
+ <span class="red"><b>1</b> lines missed.</span>
1948
+ </div>
1949
+ </div>
1950
+
1951
+ <pre>
1952
+ <ol>
1953
+
1954
+ <li class="covered" data-hits="1" data-linenumber="1">
1955
+ <span class="hits">1</span>
1956
+
1957
+ <code class="ruby">module Devise</code>
1958
+ </li>
1959
+
1960
+ <li class="covered" data-hits="1" data-linenumber="2">
1961
+ <span class="hits">1</span>
1962
+
1963
+ <code class="ruby"> module Models</code>
1964
+ </li>
1965
+
1966
+ <li class="covered" data-hits="1" data-linenumber="3">
1967
+ <span class="hits">1</span>
1968
+
1969
+ <code class="ruby"> module PasswordDisallowsFrequentReuse</code>
1970
+ </li>
1971
+
1972
+ <li class="covered" data-hits="1" data-linenumber="4">
1973
+ <span class="hits">1</span>
1974
+
1975
+ <code class="ruby"> extend ActiveSupport::Concern</code>
1976
+ </li>
1977
+
1978
+ <li class="never" data-hits="" data-linenumber="5">
1979
+
1980
+
1981
+ <code class="ruby"></code>
1982
+ </li>
1983
+
1984
+ <li class="covered" data-hits="1" data-linenumber="6">
1985
+ <span class="hits">1</span>
1986
+
1987
+ <code class="ruby"> require &#39;devise/secure_password/models/previous_password&#39;</code>
1988
+ </li>
1989
+
1990
+ <li class="never" data-hits="" data-linenumber="7">
1991
+
1992
+
1993
+ <code class="ruby"></code>
1994
+ </li>
1995
+
1996
+ <li class="covered" data-hits="1" data-linenumber="8">
1997
+ <span class="hits">1</span>
1998
+
1999
+ <code class="ruby"> included do</code>
2000
+ </li>
2001
+
2002
+ <li class="never" data-hits="" data-linenumber="9">
2003
+
2004
+
2005
+ <code class="ruby"> # we need to specify the foreign_key here to support the use of isolated subclasses in tests</code>
2006
+ </li>
2007
+
2008
+ <li class="covered" data-hits="5" data-linenumber="10">
2009
+ <span class="hits">5</span>
2010
+
2011
+ <code class="ruby"> has_many :previous_passwords,</code>
2012
+ </li>
2013
+
2014
+ <li class="covered" data-hits="101" data-linenumber="11">
2015
+ <span class="hits">101</span>
2016
+
2017
+ <code class="ruby"> -&gt; { limit(User.password_previously_used_count) },</code>
2018
+ </li>
2019
+
2020
+ <li class="never" data-hits="" data-linenumber="12">
2021
+
2022
+
2023
+ <code class="ruby"> class_name: &#39;Devise::Models::PreviousPassword&#39;,</code>
2024
+ </li>
2025
+
2026
+ <li class="never" data-hits="" data-linenumber="13">
2027
+
2028
+
2029
+ <code class="ruby"> foreign_key: &#39;user_id&#39;,</code>
2030
+ </li>
2031
+
2032
+ <li class="never" data-hits="" data-linenumber="14">
2033
+
2034
+
2035
+ <code class="ruby"> dependent: :destroy</code>
2036
+ </li>
2037
+
2038
+ <li class="covered" data-hits="5" data-linenumber="15">
2039
+ <span class="hits">5</span>
2040
+
2041
+ <code class="ruby"> validate :validate_password_frequent_reuse, if: :password_required?</code>
2042
+ </li>
2043
+
2044
+ <li class="never" data-hits="" data-linenumber="16">
2045
+
2046
+
2047
+ <code class="ruby"></code>
2048
+ </li>
2049
+
2050
+ <li class="covered" data-hits="5" data-linenumber="17">
2051
+ <span class="hits">5</span>
2052
+
2053
+ <code class="ruby"> set_callback(:save, :before, :before_resource_saved)</code>
2054
+ </li>
2055
+
2056
+ <li class="covered" data-hits="5" data-linenumber="18">
2057
+ <span class="hits">5</span>
2058
+
2059
+ <code class="ruby"> set_callback(:save, :after, :after_resource_saved, if: :dirty_password?)</code>
2060
+ </li>
2061
+
2062
+ <li class="never" data-hits="" data-linenumber="19">
2063
+
2064
+
2065
+ <code class="ruby"> end</code>
2066
+ </li>
2067
+
2068
+ <li class="never" data-hits="" data-linenumber="20">
2069
+
2070
+
2071
+ <code class="ruby"></code>
2072
+ </li>
2073
+
2074
+ <li class="covered" data-hits="1" data-linenumber="21">
2075
+ <span class="hits">1</span>
2076
+
2077
+ <code class="ruby"> def validate_password_frequent_reuse</code>
2078
+ </li>
2079
+
2080
+ <li class="covered" data-hits="41" data-linenumber="22">
2081
+ <span class="hits">41</span>
2082
+
2083
+ <code class="ruby"> if encrypted_password_changed? &amp;&amp; previous_password?(password)</code>
2084
+ </li>
2085
+
2086
+ <li class="covered" data-hits="6" data-linenumber="23">
2087
+ <span class="hits">6</span>
2088
+
2089
+ <code class="ruby"> error_string = I18n.t(</code>
2090
+ </li>
2091
+
2092
+ <li class="never" data-hits="" data-linenumber="24">
2093
+
2094
+
2095
+ <code class="ruby"> &#39;secure_password.password_disallows_frequent_reuse.errors.messages.password_is_recent&#39;,</code>
2096
+ </li>
2097
+
2098
+ <li class="never" data-hits="" data-linenumber="25">
2099
+
2100
+
2101
+ <code class="ruby"> count: self.class.password_previously_used_count</code>
2102
+ </li>
2103
+
2104
+ <li class="never" data-hits="" data-linenumber="26">
2105
+
2106
+
2107
+ <code class="ruby"> )</code>
2108
+ </li>
2109
+
2110
+ <li class="covered" data-hits="6" data-linenumber="27">
2111
+ <span class="hits">6</span>
2112
+
2113
+ <code class="ruby"> errors.add(:base, error_string)</code>
2114
+ </li>
2115
+
2116
+ <li class="never" data-hits="" data-linenumber="28">
2117
+
2118
+
2119
+ <code class="ruby"> end</code>
2120
+ </li>
2121
+
2122
+ <li class="never" data-hits="" data-linenumber="29">
2123
+
2124
+
2125
+ <code class="ruby"></code>
2126
+ </li>
2127
+
2128
+ <li class="covered" data-hits="41" data-linenumber="30">
2129
+ <span class="hits">41</span>
2130
+
2131
+ <code class="ruby"> errors.count.zero?</code>
2132
+ </li>
2133
+
2134
+ <li class="never" data-hits="" data-linenumber="31">
2135
+
2136
+
2137
+ <code class="ruby"> end</code>
2138
+ </li>
2139
+
2140
+ <li class="never" data-hits="" data-linenumber="32">
2141
+
2142
+
2143
+ <code class="ruby"></code>
2144
+ </li>
2145
+
2146
+ <li class="covered" data-hits="1" data-linenumber="33">
2147
+ <span class="hits">1</span>
2148
+
2149
+ <code class="ruby"> protected</code>
2150
+ </li>
2151
+
2152
+ <li class="never" data-hits="" data-linenumber="34">
2153
+
2154
+
2155
+ <code class="ruby"></code>
2156
+ </li>
2157
+
2158
+ <li class="covered" data-hits="1" data-linenumber="35">
2159
+ <span class="hits">1</span>
2160
+
2161
+ <code class="ruby"> def before_resource_saved; end</code>
2162
+ </li>
2163
+
2164
+ <li class="never" data-hits="" data-linenumber="36">
2165
+
2166
+
2167
+ <code class="ruby"></code>
2168
+ </li>
2169
+
2170
+ <li class="covered" data-hits="1" data-linenumber="37">
2171
+ <span class="hits">1</span>
2172
+
2173
+ <code class="ruby"> def after_resource_saved</code>
2174
+ </li>
2175
+
2176
+ <li class="covered" data-hits="39" data-linenumber="38">
2177
+ <span class="hits">39</span>
2178
+
2179
+ <code class="ruby"> salt = ::BCrypt::Password.new(encrypted_password).salt</code>
2180
+ </li>
2181
+
2182
+ <li class="covered" data-hits="39" data-linenumber="39">
2183
+ <span class="hits">39</span>
2184
+
2185
+ <code class="ruby"> previous_password = previous_passwords.build(user_id: id, salt: salt, encrypted_password: encrypted_password)</code>
2186
+ </li>
2187
+
2188
+ <li class="covered" data-hits="39" data-linenumber="40">
2189
+ <span class="hits">39</span>
2190
+
2191
+ <code class="ruby"> previous_password.save!</code>
2192
+ </li>
2193
+
2194
+ <li class="never" data-hits="" data-linenumber="41">
2195
+
2196
+
2197
+ <code class="ruby"> end</code>
2198
+ </li>
2199
+
2200
+ <li class="never" data-hits="" data-linenumber="42">
2201
+
2202
+
2203
+ <code class="ruby"></code>
2204
+ </li>
2205
+
2206
+ <li class="covered" data-hits="1" data-linenumber="43">
2207
+ <span class="hits">1</span>
2208
+
2209
+ <code class="ruby"> def previous_password?(password)</code>
2210
+ </li>
2211
+
2212
+ <li class="covered" data-hits="41" data-linenumber="44">
2213
+ <span class="hits">41</span>
2214
+
2215
+ <code class="ruby"> salts = previous_passwords.select(:salt).map(&amp;:salt)</code>
2216
+ </li>
2217
+
2218
+ <li class="covered" data-hits="41" data-linenumber="45">
2219
+ <span class="hits">41</span>
2220
+
2221
+ <code class="ruby"> pepper = self.class.pepper.presence || &#39;&#39;</code>
2222
+ </li>
2223
+
2224
+ <li class="never" data-hits="" data-linenumber="46">
2225
+
2226
+
2227
+ <code class="ruby"></code>
2228
+ </li>
2229
+
2230
+ <li class="covered" data-hits="41" data-linenumber="47">
2231
+ <span class="hits">41</span>
2232
+
2233
+ <code class="ruby"> salts.each do |salt|</code>
2234
+ </li>
2235
+
2236
+ <li class="covered" data-hits="17" data-linenumber="48">
2237
+ <span class="hits">17</span>
2238
+
2239
+ <code class="ruby"> candidate = ::BCrypt::Engine.hash_secret(&quot;#{password}#{pepper}&quot;, salt)</code>
2240
+ </li>
2241
+
2242
+ <li class="covered" data-hits="17" data-linenumber="49">
2243
+ <span class="hits">17</span>
2244
+
2245
+ <code class="ruby"> return true unless previous_passwords.find_by(encrypted_password: candidate).nil?</code>
2246
+ </li>
2247
+
2248
+ <li class="never" data-hits="" data-linenumber="50">
2249
+
2250
+
2251
+ <code class="ruby"> end</code>
2252
+ </li>
2253
+
2254
+ <li class="never" data-hits="" data-linenumber="51">
2255
+
2256
+
2257
+ <code class="ruby"></code>
2258
+ </li>
2259
+
2260
+ <li class="covered" data-hits="35" data-linenumber="52">
2261
+ <span class="hits">35</span>
2262
+
2263
+ <code class="ruby"> false</code>
2264
+ </li>
2265
+
2266
+ <li class="never" data-hits="" data-linenumber="53">
2267
+
2268
+
2269
+ <code class="ruby"> end</code>
2270
+ </li>
2271
+
2272
+ <li class="never" data-hits="" data-linenumber="54">
2273
+
2274
+
2275
+ <code class="ruby"></code>
2276
+ </li>
2277
+
2278
+ <li class="covered" data-hits="1" data-linenumber="55">
2279
+ <span class="hits">1</span>
2280
+
2281
+ <code class="ruby"> def dirty_password?</code>
2282
+ </li>
2283
+
2284
+ <li class="covered" data-hits="43" data-linenumber="56">
2285
+ <span class="hits">43</span>
2286
+
2287
+ <code class="ruby"> return false unless password_required?</code>
2288
+ </li>
2289
+
2290
+ <li class="covered" data-hits="41" data-linenumber="57">
2291
+ <span class="hits">41</span>
2292
+
2293
+ <code class="ruby"> if Rails.version &gt; &#39;5.1&#39;</code>
2294
+ </li>
2295
+
2296
+ <li class="covered" data-hits="41" data-linenumber="58">
2297
+ <span class="hits">41</span>
2298
+
2299
+ <code class="ruby"> saved_change_to_encrypted_password?</code>
2300
+ </li>
2301
+
2302
+ <li class="never" data-hits="" data-linenumber="59">
2303
+
2304
+
2305
+ <code class="ruby"> else</code>
2306
+ </li>
2307
+
2308
+ <li class="missed" data-hits="0" data-linenumber="60">
2309
+
2310
+
2311
+ <code class="ruby"> encrypted_password_changed?</code>
2312
+ </li>
2313
+
2314
+ <li class="never" data-hits="" data-linenumber="61">
2315
+
2316
+
2317
+ <code class="ruby"> end</code>
2318
+ </li>
2319
+
2320
+ <li class="never" data-hits="" data-linenumber="62">
2321
+
2322
+
2323
+ <code class="ruby"> end</code>
2324
+ </li>
2325
+
2326
+ <li class="never" data-hits="" data-linenumber="63">
2327
+
2328
+
2329
+ <code class="ruby"></code>
2330
+ </li>
2331
+
2332
+ <li class="covered" data-hits="1" data-linenumber="64">
2333
+ <span class="hits">1</span>
2334
+
2335
+ <code class="ruby"> module ClassMethods</code>
2336
+ </li>
2337
+
2338
+ <li class="covered" data-hits="1" data-linenumber="65">
2339
+ <span class="hits">1</span>
2340
+
2341
+ <code class="ruby"> config_params = %i(</code>
2342
+ </li>
2343
+
2344
+ <li class="never" data-hits="" data-linenumber="66">
2345
+
2346
+
2347
+ <code class="ruby"> password_previously_used_count</code>
2348
+ </li>
2349
+
2350
+ <li class="never" data-hits="" data-linenumber="67">
2351
+
2352
+
2353
+ <code class="ruby"> )</code>
2354
+ </li>
2355
+
2356
+ <li class="covered" data-hits="1" data-linenumber="68">
2357
+ <span class="hits">1</span>
2358
+
2359
+ <code class="ruby"> ::Devise::Models.config(self, *config_params)</code>
2360
+ </li>
2361
+
2362
+ <li class="never" data-hits="" data-linenumber="69">
2363
+
2364
+
2365
+ <code class="ruby"> end</code>
2366
+ </li>
2367
+
2368
+ <li class="never" data-hits="" data-linenumber="70">
2369
+
2370
+
2371
+ <code class="ruby"> end</code>
2372
+ </li>
2373
+
2374
+ <li class="never" data-hits="" data-linenumber="71">
2375
+
2376
+
2377
+ <code class="ruby"> end</code>
2378
+ </li>
2379
+
2380
+ <li class="never" data-hits="" data-linenumber="72">
2381
+
2382
+
2383
+ <code class="ruby">end</code>
2384
+ </li>
2385
+
2386
+ </ol>
2387
+ </pre>
2388
+ </div>
2389
+
2390
+
2391
+ <div class="source_table" id="4b69a1a797756cc5573d2387f77adfb89bd8ece4">
2392
+ <div class="header">
2393
+ <h3>lib/devise/secure_password/models/password_has_required_content.rb</h3>
2394
+ <h4><span class="green">94.83 %</span> covered</h4>
2395
+ <div>
2396
+ <b>58</b> relevant lines.
2397
+ <span class="green"><b>55</b> lines covered</span> and
2398
+ <span class="red"><b>3</b> lines missed.</span>
2399
+ </div>
2400
+ </div>
2401
+
2402
+ <pre>
2403
+ <ol>
2404
+
2405
+ <li class="covered" data-hits="1" data-linenumber="1">
2406
+ <span class="hits">1</span>
2407
+
2408
+ <code class="ruby">module Devise</code>
2409
+ </li>
2410
+
2411
+ <li class="covered" data-hits="1" data-linenumber="2">
2412
+ <span class="hits">1</span>
2413
+
2414
+ <code class="ruby"> module Models</code>
2415
+ </li>
2416
+
2417
+ <li class="covered" data-hits="1" data-linenumber="3">
2418
+ <span class="hits">1</span>
2419
+
2420
+ <code class="ruby"> module PasswordHasRequiredContent</code>
2421
+ </li>
2422
+
2423
+ <li class="covered" data-hits="1" data-linenumber="4">
2424
+ <span class="hits">1</span>
2425
+
2426
+ <code class="ruby"> extend ActiveSupport::Concern</code>
2427
+ </li>
2428
+
2429
+ <li class="never" data-hits="" data-linenumber="5">
2430
+
2431
+
2432
+ <code class="ruby"></code>
2433
+ </li>
2434
+
2435
+ <li class="covered" data-hits="1" data-linenumber="6">
2436
+ <span class="hits">1</span>
2437
+
2438
+ <code class="ruby"> require &#39;support/string/character_counter&#39;</code>
2439
+ </li>
2440
+
2441
+ <li class="never" data-hits="" data-linenumber="7">
2442
+
2443
+
2444
+ <code class="ruby"></code>
2445
+ </li>
2446
+
2447
+ <li class="covered" data-hits="1" data-linenumber="8">
2448
+ <span class="hits">1</span>
2449
+
2450
+ <code class="ruby"> LENGTH_MAX = 255</code>
2451
+ </li>
2452
+
2453
+ <li class="never" data-hits="" data-linenumber="9">
2454
+
2455
+
2456
+ <code class="ruby"></code>
2457
+ </li>
2458
+
2459
+ <li class="covered" data-hits="1" data-linenumber="10">
2460
+ <span class="hits">1</span>
2461
+
2462
+ <code class="ruby"> included do</code>
2463
+ </li>
2464
+
2465
+ <li class="covered" data-hits="6" data-linenumber="11">
2466
+ <span class="hits">6</span>
2467
+
2468
+ <code class="ruby"> validate :validate_password_content, if: :password_required?</code>
2469
+ </li>
2470
+
2471
+ <li class="covered" data-hits="6" data-linenumber="12">
2472
+ <span class="hits">6</span>
2473
+
2474
+ <code class="ruby"> validate :validate_password_confirmation_content, if: :password_required?</code>
2475
+ </li>
2476
+
2477
+ <li class="never" data-hits="" data-linenumber="13">
2478
+
2479
+
2480
+ <code class="ruby"> end</code>
2481
+ </li>
2482
+
2483
+ <li class="never" data-hits="" data-linenumber="14">
2484
+
2485
+
2486
+ <code class="ruby"></code>
2487
+ </li>
2488
+
2489
+ <li class="covered" data-hits="1" data-linenumber="15">
2490
+ <span class="hits">1</span>
2491
+
2492
+ <code class="ruby"> def validate_password_content</code>
2493
+ </li>
2494
+
2495
+ <li class="covered" data-hits="47" data-linenumber="16">
2496
+ <span class="hits">47</span>
2497
+
2498
+ <code class="ruby"> self.password ||= &#39;&#39;</code>
2499
+ </li>
2500
+
2501
+ <li class="covered" data-hits="47" data-linenumber="17">
2502
+ <span class="hits">47</span>
2503
+
2504
+ <code class="ruby"> validate_password_content_for(:password)</code>
2505
+ </li>
2506
+
2507
+ <li class="covered" data-hits="47" data-linenumber="18">
2508
+ <span class="hits">47</span>
2509
+
2510
+ <code class="ruby"> errors[:password].count.zero?</code>
2511
+ </li>
2512
+
2513
+ <li class="never" data-hits="" data-linenumber="19">
2514
+
2515
+
2516
+ <code class="ruby"> end</code>
2517
+ </li>
2518
+
2519
+ <li class="never" data-hits="" data-linenumber="20">
2520
+
2521
+
2522
+ <code class="ruby"></code>
2523
+ </li>
2524
+
2525
+ <li class="covered" data-hits="1" data-linenumber="21">
2526
+ <span class="hits">1</span>
2527
+
2528
+ <code class="ruby"> def validate_password_confirmation_content</code>
2529
+ </li>
2530
+
2531
+ <li class="covered" data-hits="47" data-linenumber="22">
2532
+ <span class="hits">47</span>
2533
+
2534
+ <code class="ruby"> self.password_confirmation ||= &#39;&#39;</code>
2535
+ </li>
2536
+
2537
+ <li class="covered" data-hits="47" data-linenumber="23">
2538
+ <span class="hits">47</span>
2539
+
2540
+ <code class="ruby"> validate_password_content_for(:password_confirmation)</code>
2541
+ </li>
2542
+
2543
+ <li class="covered" data-hits="47" data-linenumber="24">
2544
+ <span class="hits">47</span>
2545
+
2546
+ <code class="ruby"> errors[:password_confirmation].count.zero?</code>
2547
+ </li>
2548
+
2549
+ <li class="never" data-hits="" data-linenumber="25">
2550
+
2551
+
2552
+ <code class="ruby"> end</code>
2553
+ </li>
2554
+
2555
+ <li class="never" data-hits="" data-linenumber="26">
2556
+
2557
+
2558
+ <code class="ruby"></code>
2559
+ </li>
2560
+
2561
+ <li class="covered" data-hits="1" data-linenumber="27">
2562
+ <span class="hits">1</span>
2563
+
2564
+ <code class="ruby"> def validate_password_content_for(attr)</code>
2565
+ </li>
2566
+
2567
+ <li class="covered" data-hits="94" data-linenumber="28">
2568
+ <span class="hits">94</span>
2569
+
2570
+ <code class="ruby"> return unless respond_to?(attr) &amp;&amp; !(password_obj = send(attr)).nil?</code>
2571
+ </li>
2572
+
2573
+ <li class="covered" data-hits="94" data-linenumber="29">
2574
+ <span class="hits">94</span>
2575
+
2576
+ <code class="ruby"> ::Support::String::CharacterCounter.new.count(password_obj).each do |type, dict|</code>
2577
+ </li>
2578
+
2579
+ <li class="covered" data-hits="470" data-linenumber="30">
2580
+ <span class="hits">470</span>
2581
+
2582
+ <code class="ruby"> error_string = case type</code>
2583
+ </li>
2584
+
2585
+ <li class="covered" data-hits="94" data-linenumber="31">
2586
+ <span class="hits">94</span>
2587
+
2588
+ <code class="ruby"> when :unknown then validate_unknown(dict)</code>
2589
+ </li>
2590
+
2591
+ <li class="covered" data-hits="376" data-linenumber="32">
2592
+ <span class="hits">376</span>
2593
+
2594
+ <code class="ruby"> else validate_type(type, dict)</code>
2595
+ </li>
2596
+
2597
+ <li class="never" data-hits="" data-linenumber="33">
2598
+
2599
+
2600
+ <code class="ruby"> end</code>
2601
+ </li>
2602
+
2603
+ <li class="covered" data-hits="470" data-linenumber="34">
2604
+ <span class="hits">470</span>
2605
+
2606
+ <code class="ruby"> errors.add(attr, error_string) if error_string.present?</code>
2607
+ </li>
2608
+
2609
+ <li class="never" data-hits="" data-linenumber="35">
2610
+
2611
+
2612
+ <code class="ruby"> end</code>
2613
+ </li>
2614
+
2615
+ <li class="never" data-hits="" data-linenumber="36">
2616
+
2617
+
2618
+ <code class="ruby"> end</code>
2619
+ </li>
2620
+
2621
+ <li class="never" data-hits="" data-linenumber="37">
2622
+
2623
+
2624
+ <code class="ruby"></code>
2625
+ </li>
2626
+
2627
+ <li class="covered" data-hits="1" data-linenumber="38">
2628
+ <span class="hits">1</span>
2629
+
2630
+ <code class="ruby"> protected</code>
2631
+ </li>
2632
+
2633
+ <li class="never" data-hits="" data-linenumber="39">
2634
+
2635
+
2636
+ <code class="ruby"></code>
2637
+ </li>
2638
+
2639
+ <li class="covered" data-hits="1" data-linenumber="40">
2640
+ <span class="hits">1</span>
2641
+
2642
+ <code class="ruby"> def validate_unknown(dict)</code>
2643
+ </li>
2644
+
2645
+ <li class="covered" data-hits="94" data-linenumber="41">
2646
+ <span class="hits">94</span>
2647
+
2648
+ <code class="ruby"> type_total = dict.values.reduce(0, :+)</code>
2649
+ </li>
2650
+
2651
+ <li class="covered" data-hits="94" data-linenumber="42">
2652
+ <span class="hits">94</span>
2653
+
2654
+ <code class="ruby"> return if type_total &lt;= required_char_counts_for_type(:unknown)[:max]</code>
2655
+ </li>
2656
+
2657
+ <li class="never" data-hits="" data-linenumber="43">
2658
+
2659
+
2660
+ <code class="ruby"></code>
2661
+ </li>
2662
+
2663
+ <li class="covered" data-hits="2" data-linenumber="44">
2664
+ <span class="hits">2</span>
2665
+
2666
+ <code class="ruby"> error_string_for_unknown_chars(type_total, dict.keys)</code>
2667
+ </li>
2668
+
2669
+ <li class="never" data-hits="" data-linenumber="45">
2670
+
2671
+
2672
+ <code class="ruby"> end</code>
2673
+ </li>
2674
+
2675
+ <li class="never" data-hits="" data-linenumber="46">
2676
+
2677
+
2678
+ <code class="ruby"></code>
2679
+ </li>
2680
+
2681
+ <li class="covered" data-hits="1" data-linenumber="47">
2682
+ <span class="hits">1</span>
2683
+
2684
+ <code class="ruby"> def validate_type(type, dict)</code>
2685
+ </li>
2686
+
2687
+ <li class="covered" data-hits="376" data-linenumber="48">
2688
+ <span class="hits">376</span>
2689
+
2690
+ <code class="ruby"> type_total = dict.values.reduce(0, :+)</code>
2691
+ </li>
2692
+
2693
+ <li class="covered" data-hits="376" data-linenumber="49">
2694
+ <span class="hits">376</span>
2695
+
2696
+ <code class="ruby"> error_string = if type_total &lt; required_char_counts_for_type(type)[:min]</code>
2697
+ </li>
2698
+
2699
+ <li class="covered" data-hits="16" data-linenumber="50">
2700
+ <span class="hits">16</span>
2701
+
2702
+ <code class="ruby"> error_string_for_length(type, :min)</code>
2703
+ </li>
2704
+
2705
+ <li class="covered" data-hits="360" data-linenumber="51">
2706
+ <span class="hits">360</span>
2707
+
2708
+ <code class="ruby"> elsif type_total &gt; required_char_counts_for_type(type)[:max]</code>
2709
+ </li>
2710
+
2711
+ <li class="missed" data-hits="0" data-linenumber="52">
2712
+
2713
+
2714
+ <code class="ruby"> error_string_for_length(type, :max)</code>
2715
+ </li>
2716
+
2717
+ <li class="never" data-hits="" data-linenumber="53">
2718
+
2719
+
2720
+ <code class="ruby"> end</code>
2721
+ </li>
2722
+
2723
+ <li class="covered" data-hits="376" data-linenumber="54">
2724
+ <span class="hits">376</span>
2725
+
2726
+ <code class="ruby"> error_string</code>
2727
+ </li>
2728
+
2729
+ <li class="never" data-hits="" data-linenumber="55">
2730
+
2731
+
2732
+ <code class="ruby"> end</code>
2733
+ </li>
2734
+
2735
+ <li class="never" data-hits="" data-linenumber="56">
2736
+
2737
+
2738
+ <code class="ruby"></code>
2739
+ </li>
2740
+
2741
+ <li class="covered" data-hits="1" data-linenumber="57">
2742
+ <span class="hits">1</span>
2743
+
2744
+ <code class="ruby"> def error_string_for_length(type, threshold = :min)</code>
2745
+ </li>
2746
+
2747
+ <li class="covered" data-hits="16" data-linenumber="58">
2748
+ <span class="hits">16</span>
2749
+
2750
+ <code class="ruby"> lang_key = case threshold</code>
2751
+ </li>
2752
+
2753
+ <li class="covered" data-hits="16" data-linenumber="59">
2754
+ <span class="hits">16</span>
2755
+
2756
+ <code class="ruby"> when :min then &#39;secure_password.password_has_required_content.errors.messages.minimum_characters&#39;</code>
2757
+ </li>
2758
+
2759
+ <li class="missed" data-hits="0" data-linenumber="60">
2760
+
2761
+
2762
+ <code class="ruby"> when :max then &#39;secure_password.password_has_required_content.errors.messages.maximum_characters&#39;</code>
2763
+ </li>
2764
+
2765
+ <li class="missed" data-hits="0" data-linenumber="61">
2766
+
2767
+
2768
+ <code class="ruby"> else return &#39;&#39;</code>
2769
+ </li>
2770
+
2771
+ <li class="never" data-hits="" data-linenumber="62">
2772
+
2773
+
2774
+ <code class="ruby"> end</code>
2775
+ </li>
2776
+
2777
+ <li class="never" data-hits="" data-linenumber="63">
2778
+
2779
+
2780
+ <code class="ruby"></code>
2781
+ </li>
2782
+
2783
+ <li class="covered" data-hits="16" data-linenumber="64">
2784
+ <span class="hits">16</span>
2785
+
2786
+ <code class="ruby"> count = required_char_counts_for_type(type)[threshold]</code>
2787
+ </li>
2788
+
2789
+ <li class="covered" data-hits="16" data-linenumber="65">
2790
+ <span class="hits">16</span>
2791
+
2792
+ <code class="ruby"> error_string = I18n.t(lang_key, count: count, type: type.to_s, subject: &#39;character&#39;.pluralize(count))</code>
2793
+ </li>
2794
+
2795
+ <li class="covered" data-hits="16" data-linenumber="66">
2796
+ <span class="hits">16</span>
2797
+
2798
+ <code class="ruby"> error_string + &#39; &#39; + dict_for_type(type)</code>
2799
+ </li>
2800
+
2801
+ <li class="never" data-hits="" data-linenumber="67">
2802
+
2803
+
2804
+ <code class="ruby"> end</code>
2805
+ </li>
2806
+
2807
+ <li class="never" data-hits="" data-linenumber="68">
2808
+
2809
+
2810
+ <code class="ruby"></code>
2811
+ </li>
2812
+
2813
+ <li class="covered" data-hits="1" data-linenumber="69">
2814
+ <span class="hits">1</span>
2815
+
2816
+ <code class="ruby"> def error_string_for_unknown_chars(total, chars = [])</code>
2817
+ </li>
2818
+
2819
+ <li class="never" data-hits="" data-linenumber="70">
2820
+
2821
+
2822
+ <code class="ruby"> I18n.t(</code>
2823
+ </li>
2824
+
2825
+ <li class="never" data-hits="" data-linenumber="71">
2826
+
2827
+
2828
+ <code class="ruby"> &#39;secure_password.password_has_required_content.errors.messages.unknown_characters&#39;,</code>
2829
+ </li>
2830
+
2831
+ <li class="never" data-hits="" data-linenumber="72">
2832
+
2833
+
2834
+ <code class="ruby"> count: total,</code>
2835
+ </li>
2836
+
2837
+ <li class="never" data-hits="" data-linenumber="73">
2838
+
2839
+
2840
+ <code class="ruby"> subject: &#39;character&#39;.pluralize(total)</code>
2841
+ </li>
2842
+
2843
+ <li class="covered" data-hits="2" data-linenumber="74">
2844
+ <span class="hits">2</span>
2845
+
2846
+ <code class="ruby"> ) + &quot; (#{chars.join(&#39;&#39;)})&quot;</code>
2847
+ </li>
2848
+
2849
+ <li class="never" data-hits="" data-linenumber="75">
2850
+
2851
+
2852
+ <code class="ruby"> end</code>
2853
+ </li>
2854
+
2855
+ <li class="never" data-hits="" data-linenumber="76">
2856
+
2857
+
2858
+ <code class="ruby"></code>
2859
+ </li>
2860
+
2861
+ <li class="covered" data-hits="1" data-linenumber="77">
2862
+ <span class="hits">1</span>
2863
+
2864
+ <code class="ruby"> def dict_for_type(type)</code>
2865
+ </li>
2866
+
2867
+ <li class="covered" data-hits="16" data-linenumber="78">
2868
+ <span class="hits">16</span>
2869
+
2870
+ <code class="ruby"> character_counter = ::Support::String::CharacterCounter.new</code>
2871
+ </li>
2872
+
2873
+ <li class="never" data-hits="" data-linenumber="79">
2874
+
2875
+
2876
+ <code class="ruby"></code>
2877
+ </li>
2878
+
2879
+ <li class="covered" data-hits="16" data-linenumber="80">
2880
+ <span class="hits">16</span>
2881
+
2882
+ <code class="ruby"> case type</code>
2883
+ </li>
2884
+
2885
+ <li class="covered" data-hits="4" data-linenumber="81">
2886
+ <span class="hits">4</span>
2887
+
2888
+ <code class="ruby"> when :special, :unknown then &quot;(#{character_counter.count_hash[type].keys.join(&#39;&#39;)})&quot;</code>
2889
+ </li>
2890
+
2891
+ <li class="never" data-hits="" data-linenumber="82">
2892
+
2893
+
2894
+ <code class="ruby"> else</code>
2895
+ </li>
2896
+
2897
+ <li class="covered" data-hits="12" data-linenumber="83">
2898
+ <span class="hits">12</span>
2899
+
2900
+ <code class="ruby"> &quot;(#{character_counter.count_hash[type].keys.first}..#{character_counter.count_hash[type].keys.last})&quot;</code>
2901
+ </li>
2902
+
2903
+ <li class="never" data-hits="" data-linenumber="84">
2904
+
2905
+
2906
+ <code class="ruby"> end</code>
2907
+ </li>
2908
+
2909
+ <li class="never" data-hits="" data-linenumber="85">
2910
+
2911
+
2912
+ <code class="ruby"> end</code>
2913
+ </li>
2914
+
2915
+ <li class="never" data-hits="" data-linenumber="86">
2916
+
2917
+
2918
+ <code class="ruby"></code>
2919
+ </li>
2920
+
2921
+ <li class="covered" data-hits="1" data-linenumber="87">
2922
+ <span class="hits">1</span>
2923
+
2924
+ <code class="ruby"> def required_char_counts_for_type(type)</code>
2925
+ </li>
2926
+
2927
+ <li class="covered" data-hits="846" data-linenumber="88">
2928
+ <span class="hits">846</span>
2929
+
2930
+ <code class="ruby"> self.class.config[:REQUIRED_CHAR_COUNTS][type]</code>
2931
+ </li>
2932
+
2933
+ <li class="never" data-hits="" data-linenumber="89">
2934
+
2935
+
2936
+ <code class="ruby"> end</code>
2937
+ </li>
2938
+
2939
+ <li class="never" data-hits="" data-linenumber="90">
2940
+
2941
+
2942
+ <code class="ruby"></code>
2943
+ </li>
2944
+
2945
+ <li class="covered" data-hits="1" data-linenumber="91">
2946
+ <span class="hits">1</span>
2947
+
2948
+ <code class="ruby"> module ClassMethods</code>
2949
+ </li>
2950
+
2951
+ <li class="covered" data-hits="1" data-linenumber="92">
2952
+ <span class="hits">1</span>
2953
+
2954
+ <code class="ruby"> config_params = %i(</code>
2955
+ </li>
2956
+
2957
+ <li class="never" data-hits="" data-linenumber="93">
2958
+
2959
+
2960
+ <code class="ruby"> password_required_uppercase_count</code>
2961
+ </li>
2962
+
2963
+ <li class="never" data-hits="" data-linenumber="94">
2964
+
2965
+
2966
+ <code class="ruby"> password_required_lowercase_count</code>
2967
+ </li>
2968
+
2969
+ <li class="never" data-hits="" data-linenumber="95">
2970
+
2971
+
2972
+ <code class="ruby"> password_required_number_count</code>
2973
+ </li>
2974
+
2975
+ <li class="never" data-hits="" data-linenumber="96">
2976
+
2977
+
2978
+ <code class="ruby"> password_required_special_character_count</code>
2979
+ </li>
2980
+
2981
+ <li class="never" data-hits="" data-linenumber="97">
2982
+
2983
+
2984
+ <code class="ruby"> )</code>
2985
+ </li>
2986
+
2987
+ <li class="covered" data-hits="1" data-linenumber="98">
2988
+ <span class="hits">1</span>
2989
+
2990
+ <code class="ruby"> ::Devise::Models.config(self, *config_params)</code>
2991
+ </li>
2992
+
2993
+ <li class="never" data-hits="" data-linenumber="99">
2994
+
2995
+
2996
+ <code class="ruby"></code>
2997
+ </li>
2998
+
2999
+ <li class="never" data-hits="" data-linenumber="100">
3000
+
3001
+
3002
+ <code class="ruby"> # rubocop:disable Metrics/MethodLength</code>
3003
+ </li>
3004
+
3005
+ <li class="covered" data-hits="1" data-linenumber="101">
3006
+ <span class="hits">1</span>
3007
+
3008
+ <code class="ruby"> def config</code>
3009
+ </li>
3010
+
3011
+ <li class="never" data-hits="" data-linenumber="102">
3012
+
3013
+
3014
+ <code class="ruby"> {</code>
3015
+ </li>
3016
+
3017
+ <li class="never" data-hits="" data-linenumber="103">
3018
+
3019
+
3020
+ <code class="ruby"> REQUIRED_CHAR_COUNTS: {</code>
3021
+ </li>
3022
+
3023
+ <li class="never" data-hits="" data-linenumber="104">
3024
+
3025
+
3026
+ <code class="ruby"> uppercase: {</code>
3027
+ </li>
3028
+
3029
+ <li class="never" data-hits="" data-linenumber="105">
3030
+
3031
+
3032
+ <code class="ruby"> min: password_required_uppercase_count,</code>
3033
+ </li>
3034
+
3035
+ <li class="never" data-hits="" data-linenumber="106">
3036
+
3037
+
3038
+ <code class="ruby"> max: LENGTH_MAX</code>
3039
+ </li>
3040
+
3041
+ <li class="never" data-hits="" data-linenumber="107">
3042
+
3043
+
3044
+ <code class="ruby"> },</code>
3045
+ </li>
3046
+
3047
+ <li class="never" data-hits="" data-linenumber="108">
3048
+
3049
+
3050
+ <code class="ruby"> lowercase: {</code>
3051
+ </li>
3052
+
3053
+ <li class="never" data-hits="" data-linenumber="109">
3054
+
3055
+
3056
+ <code class="ruby"> min: password_required_lowercase_count,</code>
3057
+ </li>
3058
+
3059
+ <li class="never" data-hits="" data-linenumber="110">
3060
+
3061
+
3062
+ <code class="ruby"> max: LENGTH_MAX</code>
3063
+ </li>
3064
+
3065
+ <li class="never" data-hits="" data-linenumber="111">
3066
+
3067
+
3068
+ <code class="ruby"> },</code>
3069
+ </li>
3070
+
3071
+ <li class="never" data-hits="" data-linenumber="112">
3072
+
3073
+
3074
+ <code class="ruby"> number: {</code>
3075
+ </li>
3076
+
3077
+ <li class="never" data-hits="" data-linenumber="113">
3078
+
3079
+
3080
+ <code class="ruby"> min: password_required_number_count,</code>
3081
+ </li>
3082
+
3083
+ <li class="never" data-hits="" data-linenumber="114">
3084
+
3085
+
3086
+ <code class="ruby"> max: LENGTH_MAX</code>
3087
+ </li>
3088
+
3089
+ <li class="never" data-hits="" data-linenumber="115">
3090
+
3091
+
3092
+ <code class="ruby"> },</code>
3093
+ </li>
3094
+
3095
+ <li class="never" data-hits="" data-linenumber="116">
3096
+
3097
+
3098
+ <code class="ruby"> special: {</code>
3099
+ </li>
3100
+
3101
+ <li class="never" data-hits="" data-linenumber="117">
3102
+
3103
+
3104
+ <code class="ruby"> min: password_required_special_character_count,</code>
3105
+ </li>
3106
+
3107
+ <li class="never" data-hits="" data-linenumber="118">
3108
+
3109
+
3110
+ <code class="ruby"> max: LENGTH_MAX</code>
3111
+ </li>
3112
+
3113
+ <li class="never" data-hits="" data-linenumber="119">
3114
+
3115
+
3116
+ <code class="ruby"> },</code>
3117
+ </li>
3118
+
3119
+ <li class="never" data-hits="" data-linenumber="120">
3120
+
3121
+
3122
+ <code class="ruby"> unknown: {</code>
3123
+ </li>
3124
+
3125
+ <li class="never" data-hits="" data-linenumber="121">
3126
+
3127
+
3128
+ <code class="ruby"> min: 0,</code>
3129
+ </li>
3130
+
3131
+ <li class="never" data-hits="" data-linenumber="122">
3132
+
3133
+
3134
+ <code class="ruby"> max: 0</code>
3135
+ </li>
3136
+
3137
+ <li class="never" data-hits="" data-linenumber="123">
3138
+
3139
+
3140
+ <code class="ruby"> }</code>
3141
+ </li>
3142
+
3143
+ <li class="never" data-hits="" data-linenumber="124">
3144
+
3145
+
3146
+ <code class="ruby"> }</code>
3147
+ </li>
3148
+
3149
+ <li class="covered" data-hits="846" data-linenumber="125">
3150
+ <span class="hits">846</span>
3151
+
3152
+ <code class="ruby"> }</code>
3153
+ </li>
3154
+
3155
+ <li class="never" data-hits="" data-linenumber="126">
3156
+
3157
+
3158
+ <code class="ruby"> end</code>
3159
+ </li>
3160
+
3161
+ <li class="never" data-hits="" data-linenumber="127">
3162
+
3163
+
3164
+ <code class="ruby"> # rubocop:enable Metrics/MethodLength</code>
3165
+ </li>
3166
+
3167
+ <li class="never" data-hits="" data-linenumber="128">
3168
+
3169
+
3170
+ <code class="ruby"> end</code>
3171
+ </li>
3172
+
3173
+ <li class="never" data-hits="" data-linenumber="129">
3174
+
3175
+
3176
+ <code class="ruby"> end</code>
3177
+ </li>
3178
+
3179
+ <li class="never" data-hits="" data-linenumber="130">
3180
+
3181
+
3182
+ <code class="ruby"> end</code>
3183
+ </li>
3184
+
3185
+ <li class="never" data-hits="" data-linenumber="131">
3186
+
3187
+
3188
+ <code class="ruby">end</code>
3189
+ </li>
3190
+
3191
+ </ol>
3192
+ </pre>
3193
+ </div>
3194
+
3195
+
3196
+ <div class="source_table" id="ff5f47f049dfa920a69a4c9eee3ab6e03168a334">
3197
+ <div class="header">
3198
+ <h3>lib/devise/secure_password/models/password_requires_regular_updates.rb</h3>
3199
+ <h4><span class="green">100.0 %</span> covered</h4>
3200
+ <div>
3201
+ <b>23</b> relevant lines.
3202
+ <span class="green"><b>23</b> lines covered</span> and
3203
+ <span class="red"><b>0</b> lines missed.</span>
3204
+ </div>
3205
+ </div>
3206
+
3207
+ <pre>
3208
+ <ol>
3209
+
3210
+ <li class="covered" data-hits="1" data-linenumber="1">
3211
+ <span class="hits">1</span>
3212
+
3213
+ <code class="ruby">module Devise</code>
3214
+ </li>
3215
+
3216
+ <li class="covered" data-hits="1" data-linenumber="2">
3217
+ <span class="hits">1</span>
3218
+
3219
+ <code class="ruby"> module Models</code>
3220
+ </li>
3221
+
3222
+ <li class="covered" data-hits="1" data-linenumber="3">
3223
+ <span class="hits">1</span>
3224
+
3225
+ <code class="ruby"> module PasswordRequiresRegularUpdates</code>
3226
+ </li>
3227
+
3228
+ <li class="covered" data-hits="1" data-linenumber="4">
3229
+ <span class="hits">1</span>
3230
+
3231
+ <code class="ruby"> extend ActiveSupport::Concern</code>
3232
+ </li>
3233
+
3234
+ <li class="never" data-hits="" data-linenumber="5">
3235
+
3236
+
3237
+ <code class="ruby"></code>
3238
+ </li>
3239
+
3240
+ <li class="covered" data-hits="1" data-linenumber="6">
3241
+ <span class="hits">1</span>
3242
+
3243
+ <code class="ruby"> require &#39;devise/secure_password/hooks/password_requires_regular_updates&#39;</code>
3244
+ </li>
3245
+
3246
+ <li class="never" data-hits="" data-linenumber="7">
3247
+
3248
+
3249
+ <code class="ruby"></code>
3250
+ </li>
3251
+
3252
+ <li class="covered" data-hits="1" data-linenumber="8">
3253
+ <span class="hits">1</span>
3254
+
3255
+ <code class="ruby"> class ConfigurationError &lt; RuntimeError; end</code>
3256
+ </li>
3257
+
3258
+ <li class="never" data-hits="" data-linenumber="9">
3259
+
3260
+
3261
+ <code class="ruby"></code>
3262
+ </li>
3263
+
3264
+ <li class="covered" data-hits="1" data-linenumber="10">
3265
+ <span class="hits">1</span>
3266
+
3267
+ <code class="ruby"> included do</code>
3268
+ </li>
3269
+
3270
+ <li class="covered" data-hits="4" data-linenumber="11">
3271
+ <span class="hits">4</span>
3272
+
3273
+ <code class="ruby"> set_callback(:initialize, :before, :before_regular_update_initialized)</code>
3274
+ </li>
3275
+
3276
+ <li class="covered" data-hits="4" data-linenumber="12">
3277
+ <span class="hits">4</span>
3278
+
3279
+ <code class="ruby"> set_callback(:initialize, :after, :after_regular_update_initialized)</code>
3280
+ </li>
3281
+
3282
+ <li class="never" data-hits="" data-linenumber="13">
3283
+
3284
+
3285
+ <code class="ruby"> end</code>
3286
+ </li>
3287
+
3288
+ <li class="never" data-hits="" data-linenumber="14">
3289
+
3290
+
3291
+ <code class="ruby"></code>
3292
+ </li>
3293
+
3294
+ <li class="covered" data-hits="1" data-linenumber="15">
3295
+ <span class="hits">1</span>
3296
+
3297
+ <code class="ruby"> def password_expired?</code>
3298
+ </li>
3299
+
3300
+ <li class="covered" data-hits="6" data-linenumber="16">
3301
+ <span class="hits">6</span>
3302
+
3303
+ <code class="ruby"> last_password = previous_passwords.unscoped.last</code>
3304
+ </li>
3305
+
3306
+ <li class="covered" data-hits="6" data-linenumber="17">
3307
+ <span class="hits">6</span>
3308
+
3309
+ <code class="ruby"> inconsistent_password?(last_password) || last_password.stale?(self.class.password_maximum_age)</code>
3310
+ </li>
3311
+
3312
+ <li class="never" data-hits="" data-linenumber="18">
3313
+
3314
+
3315
+ <code class="ruby"> end</code>
3316
+ </li>
3317
+
3318
+ <li class="never" data-hits="" data-linenumber="19">
3319
+
3320
+
3321
+ <code class="ruby"></code>
3322
+ </li>
3323
+
3324
+ <li class="covered" data-hits="1" data-linenumber="20">
3325
+ <span class="hits">1</span>
3326
+
3327
+ <code class="ruby"> protected</code>
3328
+ </li>
3329
+
3330
+ <li class="never" data-hits="" data-linenumber="21">
3331
+
3332
+
3333
+ <code class="ruby"></code>
3334
+ </li>
3335
+
3336
+ <li class="covered" data-hits="1" data-linenumber="22">
3337
+ <span class="hits">1</span>
3338
+
3339
+ <code class="ruby"> def before_regular_update_initialized</code>
3340
+ </li>
3341
+
3342
+ <li class="covered" data-hits="21" data-linenumber="23">
3343
+ <span class="hits">21</span>
3344
+
3345
+ <code class="ruby"> return if self.class.respond_to?(:password_previously_used_count)</code>
3346
+ </li>
3347
+
3348
+ <li class="never" data-hits="" data-linenumber="24">
3349
+
3350
+
3351
+ <code class="ruby"></code>
3352
+ </li>
3353
+
3354
+ <li class="covered" data-hits="1" data-linenumber="25">
3355
+ <span class="hits">1</span>
3356
+
3357
+ <code class="ruby"> raise ConfigurationError, &lt;&lt;-ERROR.strip_heredoc</code>
3358
+ </li>
3359
+
3360
+ <li class="never" data-hits="" data-linenumber="26">
3361
+
3362
+
3363
+ <code class="ruby"></code>
3364
+ </li>
3365
+
3366
+ <li class="never" data-hits="" data-linenumber="27">
3367
+
3368
+
3369
+ <code class="ruby"> The password_requires_regular_updates module depends on the</code>
3370
+ </li>
3371
+
3372
+ <li class="never" data-hits="" data-linenumber="28">
3373
+
3374
+
3375
+ <code class="ruby"> password_disallows_frequent_reuse module. Verify that you have</code>
3376
+ </li>
3377
+
3378
+ <li class="never" data-hits="" data-linenumber="29">
3379
+
3380
+
3381
+ <code class="ruby"> added both modules to your model, for example:</code>
3382
+ </li>
3383
+
3384
+ <li class="never" data-hits="" data-linenumber="30">
3385
+
3386
+
3387
+ <code class="ruby"></code>
3388
+ </li>
3389
+
3390
+ <li class="never" data-hits="" data-linenumber="31">
3391
+
3392
+
3393
+ <code class="ruby"> devise :database_authenticatable, :registerable,</code>
3394
+ </li>
3395
+
3396
+ <li class="never" data-hits="" data-linenumber="32">
3397
+
3398
+
3399
+ <code class="ruby"> :password_disallows_frequent_reuse,</code>
3400
+ </li>
3401
+
3402
+ <li class="never" data-hits="" data-linenumber="33">
3403
+
3404
+
3405
+ <code class="ruby"> :password_requires_regular_updates</code>
3406
+ </li>
3407
+
3408
+ <li class="never" data-hits="" data-linenumber="34">
3409
+
3410
+
3411
+ <code class="ruby"> ERROR</code>
3412
+ </li>
3413
+
3414
+ <li class="never" data-hits="" data-linenumber="35">
3415
+
3416
+
3417
+ <code class="ruby"> end</code>
3418
+ </li>
3419
+
3420
+ <li class="never" data-hits="" data-linenumber="36">
3421
+
3422
+
3423
+ <code class="ruby"></code>
3424
+ </li>
3425
+
3426
+ <li class="covered" data-hits="1" data-linenumber="37">
3427
+ <span class="hits">1</span>
3428
+
3429
+ <code class="ruby"> def after_regular_update_initialized</code>
3430
+ </li>
3431
+
3432
+ <li class="covered" data-hits="1" data-linenumber="38">
3433
+ <span class="hits">1</span>
3434
+
3435
+ <code class="ruby"> raise ConfigurationError, &#39;invalid type for password_maximum_age&#39; \</code>
3436
+ </li>
3437
+
3438
+ <li class="covered" data-hits="20" data-linenumber="39">
3439
+ <span class="hits">20</span>
3440
+
3441
+ <code class="ruby"> unless self.class.password_maximum_age.is_a?(::ActiveSupport::Duration)</code>
3442
+ </li>
3443
+
3444
+ <li class="never" data-hits="" data-linenumber="40">
3445
+
3446
+
3447
+ <code class="ruby"> end</code>
3448
+ </li>
3449
+
3450
+ <li class="never" data-hits="" data-linenumber="41">
3451
+
3452
+
3453
+ <code class="ruby"></code>
3454
+ </li>
3455
+
3456
+ <li class="never" data-hits="" data-linenumber="42">
3457
+
3458
+
3459
+ <code class="ruby"> # Check if current password is out of sync with last_password</code>
3460
+ </li>
3461
+
3462
+ <li class="never" data-hits="" data-linenumber="43">
3463
+
3464
+
3465
+ <code class="ruby"> #</code>
3466
+ </li>
3467
+
3468
+ <li class="never" data-hits="" data-linenumber="44">
3469
+
3470
+
3471
+ <code class="ruby"> # @param last_password [PreviousPassword] Password to compare with current password</code>
3472
+ </li>
3473
+
3474
+ <li class="never" data-hits="" data-linenumber="45">
3475
+
3476
+
3477
+ <code class="ruby"> # @return [Boolean] True if password is nil or out of sync, otherwise false</code>
3478
+ </li>
3479
+
3480
+ <li class="never" data-hits="" data-linenumber="46">
3481
+
3482
+
3483
+ <code class="ruby"> #</code>
3484
+ </li>
3485
+
3486
+ <li class="covered" data-hits="1" data-linenumber="47">
3487
+ <span class="hits">1</span>
3488
+
3489
+ <code class="ruby"> def inconsistent_password?(last_password = nil)</code>
3490
+ </li>
3491
+
3492
+ <li class="covered" data-hits="6" data-linenumber="48">
3493
+ <span class="hits">6</span>
3494
+
3495
+ <code class="ruby"> last_password.nil? || (encrypted_password != last_password.encrypted_password)</code>
3496
+ </li>
3497
+
3498
+ <li class="never" data-hits="" data-linenumber="49">
3499
+
3500
+
3501
+ <code class="ruby"> end</code>
3502
+ </li>
3503
+
3504
+ <li class="never" data-hits="" data-linenumber="50">
3505
+
3506
+
3507
+ <code class="ruby"></code>
3508
+ </li>
3509
+
3510
+ <li class="covered" data-hits="1" data-linenumber="51">
3511
+ <span class="hits">1</span>
3512
+
3513
+ <code class="ruby"> module ClassMethods</code>
3514
+ </li>
3515
+
3516
+ <li class="covered" data-hits="1" data-linenumber="52">
3517
+ <span class="hits">1</span>
3518
+
3519
+ <code class="ruby"> ::Devise::Models.config(self, :password_maximum_age)</code>
3520
+ </li>
3521
+
3522
+ <li class="never" data-hits="" data-linenumber="53">
3523
+
3524
+
3525
+ <code class="ruby"> end</code>
3526
+ </li>
3527
+
3528
+ <li class="never" data-hits="" data-linenumber="54">
3529
+
3530
+
3531
+ <code class="ruby"> end</code>
3532
+ </li>
3533
+
3534
+ <li class="never" data-hits="" data-linenumber="55">
3535
+
3536
+
3537
+ <code class="ruby"> end</code>
3538
+ </li>
3539
+
3540
+ <li class="never" data-hits="" data-linenumber="56">
3541
+
3542
+
3543
+ <code class="ruby">end</code>
3544
+ </li>
3545
+
3546
+ </ol>
3547
+ </pre>
3548
+ </div>
3549
+
3550
+
3551
+ <div class="source_table" id="610c7e3624991293372156293eb507f0b5546b94">
3552
+ <div class="header">
3553
+ <h3>lib/devise/secure_password/models/previous_password.rb</h3>
3554
+ <h4><span class="green">100.0 %</span> covered</h4>
3555
+ <div>
3556
+ <b>13</b> relevant lines.
3557
+ <span class="green"><b>13</b> lines covered</span> and
3558
+ <span class="red"><b>0</b> lines missed.</span>
3559
+ </div>
3560
+ </div>
3561
+
3562
+ <pre>
3563
+ <ol>
3564
+
3565
+ <li class="covered" data-hits="1" data-linenumber="1">
3566
+ <span class="hits">1</span>
3567
+
3568
+ <code class="ruby">module Devise</code>
3569
+ </li>
3570
+
3571
+ <li class="covered" data-hits="1" data-linenumber="2">
3572
+ <span class="hits">1</span>
3573
+
3574
+ <code class="ruby"> module Models</code>
3575
+ </li>
3576
+
3577
+ <li class="covered" data-hits="1" data-linenumber="3">
3578
+ <span class="hits">1</span>
3579
+
3580
+ <code class="ruby"> class PreviousPassword &lt; ::ActiveRecord::Base</code>
3581
+ </li>
3582
+
3583
+ <li class="covered" data-hits="1" data-linenumber="4">
3584
+ <span class="hits">1</span>
3585
+
3586
+ <code class="ruby"> self.table_name = &#39;previous_passwords&#39;</code>
3587
+ </li>
3588
+
3589
+ <li class="covered" data-hits="1" data-linenumber="5">
3590
+ <span class="hits">1</span>
3591
+
3592
+ <code class="ruby"> belongs_to :user</code>
3593
+ </li>
3594
+
3595
+ <li class="covered" data-hits="224" data-linenumber="6">
3596
+ <span class="hits">224</span>
3597
+
3598
+ <code class="ruby"> default_scope -&gt; { order(created_at: :desc) }</code>
3599
+ </li>
3600
+
3601
+ <li class="covered" data-hits="1" data-linenumber="7">
3602
+ <span class="hits">1</span>
3603
+
3604
+ <code class="ruby"> validates :user_id, presence: true</code>
3605
+ </li>
3606
+
3607
+ <li class="covered" data-hits="1" data-linenumber="8">
3608
+ <span class="hits">1</span>
3609
+
3610
+ <code class="ruby"> validates :salt, presence: true</code>
3611
+ </li>
3612
+
3613
+ <li class="covered" data-hits="1" data-linenumber="9">
3614
+ <span class="hits">1</span>
3615
+
3616
+ <code class="ruby"> validates :encrypted_password, presence: true</code>
3617
+ </li>
3618
+
3619
+ <li class="never" data-hits="" data-linenumber="10">
3620
+
3621
+
3622
+ <code class="ruby"></code>
3623
+ </li>
3624
+
3625
+ <li class="covered" data-hits="1" data-linenumber="11">
3626
+ <span class="hits">1</span>
3627
+
3628
+ <code class="ruby"> def fresh?(minimum_age_duration, now = ::Time.zone.now)</code>
3629
+ </li>
3630
+
3631
+ <li class="covered" data-hits="10" data-linenumber="12">
3632
+ <span class="hits">10</span>
3633
+
3634
+ <code class="ruby"> now &lt;= (created_at + minimum_age_duration)</code>
3635
+ </li>
3636
+
3637
+ <li class="never" data-hits="" data-linenumber="13">
3638
+
3639
+
3640
+ <code class="ruby"> end</code>
3641
+ </li>
3642
+
3643
+ <li class="never" data-hits="" data-linenumber="14">
3644
+
3645
+
3646
+ <code class="ruby"></code>
3647
+ </li>
3648
+
3649
+ <li class="covered" data-hits="1" data-linenumber="15">
3650
+ <span class="hits">1</span>
3651
+
3652
+ <code class="ruby"> def stale?(maximum_age_duration, now = ::Time.zone.now)</code>
3653
+ </li>
3654
+
3655
+ <li class="covered" data-hits="8" data-linenumber="16">
3656
+ <span class="hits">8</span>
3657
+
3658
+ <code class="ruby"> now &gt; (created_at + maximum_age_duration)</code>
3659
+ </li>
3660
+
3661
+ <li class="never" data-hits="" data-linenumber="17">
3662
+
3663
+
3664
+ <code class="ruby"> end</code>
3665
+ </li>
3666
+
3667
+ <li class="never" data-hits="" data-linenumber="18">
3668
+
3669
+
3670
+ <code class="ruby"> end</code>
3671
+ </li>
3672
+
3673
+ <li class="never" data-hits="" data-linenumber="19">
3674
+
3675
+
3676
+ <code class="ruby"> end</code>
3677
+ </li>
3678
+
3679
+ <li class="never" data-hits="" data-linenumber="20">
3680
+
3681
+
3682
+ <code class="ruby">end</code>
3683
+ </li>
3684
+
3685
+ </ol>
3686
+ </pre>
3687
+ </div>
3688
+
3689
+
3690
+ <div class="source_table" id="72db1cca418838b5594db9476581685e026a31a6">
3691
+ <div class="header">
3692
+ <h3>lib/devise/secure_password/routes.rb</h3>
3693
+ <h4><span class="green">100.0 %</span> covered</h4>
3694
+ <div>
3695
+ <b>6</b> relevant lines.
3696
+ <span class="green"><b>6</b> lines covered</span> and
3697
+ <span class="red"><b>0</b> lines missed.</span>
3698
+ </div>
3699
+ </div>
3700
+
3701
+ <pre>
3702
+ <ol>
3703
+
3704
+ <li class="covered" data-hits="1" data-linenumber="1">
3705
+ <span class="hits">1</span>
3706
+
3707
+ <code class="ruby">module ActionDispatch</code>
3708
+ </li>
3709
+
3710
+ <li class="covered" data-hits="1" data-linenumber="2">
3711
+ <span class="hits">1</span>
3712
+
3713
+ <code class="ruby"> module Routing</code>
3714
+ </li>
3715
+
3716
+ <li class="covered" data-hits="1" data-linenumber="3">
3717
+ <span class="hits">1</span>
3718
+
3719
+ <code class="ruby"> class Mapper</code>
3720
+ </li>
3721
+
3722
+ <li class="covered" data-hits="1" data-linenumber="4">
3723
+ <span class="hits">1</span>
3724
+
3725
+ <code class="ruby"> protected</code>
3726
+ </li>
3727
+
3728
+ <li class="never" data-hits="" data-linenumber="5">
3729
+
3730
+
3731
+ <code class="ruby"></code>
3732
+ </li>
3733
+
3734
+ <li class="covered" data-hits="1" data-linenumber="6">
3735
+ <span class="hits">1</span>
3736
+
3737
+ <code class="ruby"> def devise_passwords_with_policy(mapping, controllers)</code>
3738
+ </li>
3739
+
3740
+ <li class="covered" data-hits="1" data-linenumber="7">
3741
+ <span class="hits">1</span>
3742
+
3743
+ <code class="ruby"> resource :password_with_policy, only: %i(edit update), path: mapping.path_names[:change_password], controller: controllers[:passwords_with_policy]</code>
3744
+ </li>
3745
+
3746
+ <li class="never" data-hits="" data-linenumber="8">
3747
+
3748
+
3749
+ <code class="ruby"> end</code>
3750
+ </li>
3751
+
3752
+ <li class="never" data-hits="" data-linenumber="9">
3753
+
3754
+
3755
+ <code class="ruby"> end</code>
3756
+ </li>
3757
+
3758
+ <li class="never" data-hits="" data-linenumber="10">
3759
+
3760
+
3761
+ <code class="ruby"> end</code>
3762
+ </li>
3763
+
3764
+ <li class="never" data-hits="" data-linenumber="11">
3765
+
3766
+
3767
+ <code class="ruby">end</code>
3768
+ </li>
3769
+
3770
+ </ol>
3771
+ </pre>
3772
+ </div>
3773
+
3774
+
3775
+ <div class="source_table" id="8089caa3c6348c0fa93f698fa861c92d2a256b6c">
3776
+ <div class="header">
3777
+ <h3>lib/support/string/character_counter.rb</h3>
3778
+ <h4><span class="green">96.3 %</span> covered</h4>
3779
+ <div>
3780
+ <b>27</b> relevant lines.
3781
+ <span class="green"><b>26</b> lines covered</span> and
3782
+ <span class="red"><b>1</b> lines missed.</span>
3783
+ </div>
3784
+ </div>
3785
+
3786
+ <pre>
3787
+ <ol>
3788
+
3789
+ <li class="never" data-hits="" data-linenumber="1">
3790
+
3791
+
3792
+ <code class="ruby"># lib/support/character_counter.rb</code>
3793
+ </li>
3794
+
3795
+ <li class="never" data-hits="" data-linenumber="2">
3796
+
3797
+
3798
+ <code class="ruby">#</code>
3799
+ </li>
3800
+
3801
+ <li class="covered" data-hits="1" data-linenumber="3">
3802
+ <span class="hits">1</span>
3803
+
3804
+ <code class="ruby">module Support</code>
3805
+ </li>
3806
+
3807
+ <li class="covered" data-hits="1" data-linenumber="4">
3808
+ <span class="hits">1</span>
3809
+
3810
+ <code class="ruby"> module String</code>
3811
+ </li>
3812
+
3813
+ <li class="covered" data-hits="1" data-linenumber="5">
3814
+ <span class="hits">1</span>
3815
+
3816
+ <code class="ruby"> class CharacterCounter</code>
3817
+ </li>
3818
+
3819
+ <li class="covered" data-hits="1" data-linenumber="6">
3820
+ <span class="hits">1</span>
3821
+
3822
+ <code class="ruby"> attr_reader :count_hash</code>
3823
+ </li>
3824
+
3825
+ <li class="never" data-hits="" data-linenumber="7">
3826
+
3827
+
3828
+ <code class="ruby"></code>
3829
+ </li>
3830
+
3831
+ <li class="covered" data-hits="1" data-linenumber="8">
3832
+ <span class="hits">1</span>
3833
+
3834
+ <code class="ruby"> def initialize</code>
3835
+ </li>
3836
+
3837
+ <li class="covered" data-hits="119" data-linenumber="9">
3838
+ <span class="hits">119</span>
3839
+
3840
+ <code class="ruby"> @count_hash = {</code>
3841
+ </li>
3842
+
3843
+ <li class="covered" data-hits="119" data-linenumber="10">
3844
+ <span class="hits">119</span>
3845
+
3846
+ <code class="ruby"> uppercase: characters_to_dictionary((&#39;A&#39;..&#39;Z&#39;).to_a),</code>
3847
+ </li>
3848
+
3849
+ <li class="covered" data-hits="119" data-linenumber="11">
3850
+ <span class="hits">119</span>
3851
+
3852
+ <code class="ruby"> lowercase: characters_to_dictionary((&#39;a&#39;..&#39;z&#39;).to_a),</code>
3853
+ </li>
3854
+
3855
+ <li class="covered" data-hits="119" data-linenumber="12">
3856
+ <span class="hits">119</span>
3857
+
3858
+ <code class="ruby"> number: characters_to_dictionary((&#39;0&#39;..&#39;9&#39;).to_a),</code>
3859
+ </li>
3860
+
3861
+ <li class="never" data-hits="" data-linenumber="13">
3862
+
3863
+
3864
+ <code class="ruby"> special: characters_to_dictionary(%w(! @ # $ % ^ &amp; * ( ) _ + - = [ ] { } | &#39;)),</code>
3865
+ </li>
3866
+
3867
+ <li class="never" data-hits="" data-linenumber="14">
3868
+
3869
+
3870
+ <code class="ruby"> unknown: {}</code>
3871
+ </li>
3872
+
3873
+ <li class="never" data-hits="" data-linenumber="15">
3874
+
3875
+
3876
+ <code class="ruby"> }</code>
3877
+ </li>
3878
+
3879
+ <li class="never" data-hits="" data-linenumber="16">
3880
+
3881
+
3882
+ <code class="ruby"> end</code>
3883
+ </li>
3884
+
3885
+ <li class="never" data-hits="" data-linenumber="17">
3886
+
3887
+
3888
+ <code class="ruby"></code>
3889
+ </li>
3890
+
3891
+ <li class="covered" data-hits="1" data-linenumber="18">
3892
+ <span class="hits">1</span>
3893
+
3894
+ <code class="ruby"> def count(string)</code>
3895
+ </li>
3896
+
3897
+ <li class="covered" data-hits="101" data-linenumber="19">
3898
+ <span class="hits">101</span>
3899
+
3900
+ <code class="ruby"> raise ArgumentError, &quot;Invalid value for string: #{string}&quot; if string.nil?</code>
3901
+ </li>
3902
+
3903
+ <li class="never" data-hits="" data-linenumber="20">
3904
+
3905
+
3906
+ <code class="ruby"></code>
3907
+ </li>
3908
+
3909
+ <li class="covered" data-hits="1350" data-linenumber="21">
3910
+ <span class="hits">1350</span>
3911
+
3912
+ <code class="ruby"> string.split(&#39;&#39;).each { |c| tally_character(c) }</code>
3913
+ </li>
3914
+
3915
+ <li class="never" data-hits="" data-linenumber="22">
3916
+
3917
+
3918
+ <code class="ruby"></code>
3919
+ </li>
3920
+
3921
+ <li class="covered" data-hits="100" data-linenumber="23">
3922
+ <span class="hits">100</span>
3923
+
3924
+ <code class="ruby"> @count_hash</code>
3925
+ </li>
3926
+
3927
+ <li class="never" data-hits="" data-linenumber="24">
3928
+
3929
+
3930
+ <code class="ruby"> end</code>
3931
+ </li>
3932
+
3933
+ <li class="never" data-hits="" data-linenumber="25">
3934
+
3935
+
3936
+ <code class="ruby"></code>
3937
+ </li>
3938
+
3939
+ <li class="covered" data-hits="1" data-linenumber="26">
3940
+ <span class="hits">1</span>
3941
+
3942
+ <code class="ruby"> private</code>
3943
+ </li>
3944
+
3945
+ <li class="never" data-hits="" data-linenumber="27">
3946
+
3947
+
3948
+ <code class="ruby"></code>
3949
+ </li>
3950
+
3951
+ <li class="covered" data-hits="1" data-linenumber="28">
3952
+ <span class="hits">1</span>
3953
+
3954
+ <code class="ruby"> def characters_to_dictionary(array)</code>
3955
+ </li>
3956
+
3957
+ <li class="covered" data-hits="476" data-linenumber="29">
3958
+ <span class="hits">476</span>
3959
+
3960
+ <code class="ruby"> dictionary = {}</code>
3961
+ </li>
3962
+
3963
+ <li class="covered" data-hits="10234" data-linenumber="30">
3964
+ <span class="hits">10234</span>
3965
+
3966
+ <code class="ruby"> array.each { |c| dictionary.store(c, 0) }</code>
3967
+ </li>
3968
+
3969
+ <li class="never" data-hits="" data-linenumber="31">
3970
+
3971
+
3972
+ <code class="ruby"></code>
3973
+ </li>
3974
+
3975
+ <li class="covered" data-hits="476" data-linenumber="32">
3976
+ <span class="hits">476</span>
3977
+
3978
+ <code class="ruby"> dictionary</code>
3979
+ </li>
3980
+
3981
+ <li class="never" data-hits="" data-linenumber="33">
3982
+
3983
+
3984
+ <code class="ruby"> end</code>
3985
+ </li>
3986
+
3987
+ <li class="never" data-hits="" data-linenumber="34">
3988
+
3989
+
3990
+ <code class="ruby"></code>
3991
+ </li>
3992
+
3993
+ <li class="covered" data-hits="1" data-linenumber="35">
3994
+ <span class="hits">1</span>
3995
+
3996
+ <code class="ruby"> def tally_character(character)</code>
3997
+ </li>
3998
+
3999
+ <li class="covered" data-hits="1250" data-linenumber="36">
4000
+ <span class="hits">1250</span>
4001
+
4002
+ <code class="ruby"> %i(uppercase lowercase number special unknown).each do |type|</code>
4003
+ </li>
4004
+
4005
+ <li class="covered" data-hits="3513" data-linenumber="37">
4006
+ <span class="hits">3513</span>
4007
+
4008
+ <code class="ruby"> if @count_hash[type].key?(character)</code>
4009
+ </li>
4010
+
4011
+ <li class="covered" data-hits="1247" data-linenumber="38">
4012
+ <span class="hits">1247</span>
4013
+
4014
+ <code class="ruby"> @count_hash[type][character] += 1</code>
4015
+ </li>
4016
+
4017
+ <li class="covered" data-hits="1247" data-linenumber="39">
4018
+ <span class="hits">1247</span>
4019
+
4020
+ <code class="ruby"> return @count_hash[type][character]</code>
4021
+ </li>
4022
+
4023
+ <li class="never" data-hits="" data-linenumber="40">
4024
+
4025
+
4026
+ <code class="ruby"> end</code>
4027
+ </li>
4028
+
4029
+ <li class="never" data-hits="" data-linenumber="41">
4030
+
4031
+
4032
+ <code class="ruby"> end</code>
4033
+ </li>
4034
+
4035
+ <li class="never" data-hits="" data-linenumber="42">
4036
+
4037
+
4038
+ <code class="ruby"></code>
4039
+ </li>
4040
+
4041
+ <li class="never" data-hits="" data-linenumber="43">
4042
+
4043
+
4044
+ <code class="ruby"> # must be new unknown char</code>
4045
+ </li>
4046
+
4047
+ <li class="covered" data-hits="3" data-linenumber="44">
4048
+ <span class="hits">3</span>
4049
+
4050
+ <code class="ruby"> @count_hash[:unknown][character] = 1</code>
4051
+ </li>
4052
+
4053
+ <li class="covered" data-hits="3" data-linenumber="45">
4054
+ <span class="hits">3</span>
4055
+
4056
+ <code class="ruby"> @count_hash[:unknown][character]</code>
4057
+ </li>
4058
+
4059
+ <li class="never" data-hits="" data-linenumber="46">
4060
+
4061
+
4062
+ <code class="ruby"> end</code>
4063
+ </li>
4064
+
4065
+ <li class="never" data-hits="" data-linenumber="47">
4066
+
4067
+
4068
+ <code class="ruby"></code>
4069
+ </li>
4070
+
4071
+ <li class="covered" data-hits="1" data-linenumber="48">
4072
+ <span class="hits">1</span>
4073
+
4074
+ <code class="ruby"> def character_in_dictionary?(character, dictionary)</code>
4075
+ </li>
4076
+
4077
+ <li class="missed" data-hits="0" data-linenumber="49">
4078
+
4079
+
4080
+ <code class="ruby"> dictionary.key?(character)</code>
4081
+ </li>
4082
+
4083
+ <li class="never" data-hits="" data-linenumber="50">
4084
+
4085
+
4086
+ <code class="ruby"> end</code>
4087
+ </li>
4088
+
4089
+ <li class="never" data-hits="" data-linenumber="51">
4090
+
4091
+
4092
+ <code class="ruby"> end</code>
4093
+ </li>
4094
+
4095
+ <li class="never" data-hits="" data-linenumber="52">
4096
+
4097
+
4098
+ <code class="ruby"> end</code>
4099
+ </li>
4100
+
4101
+ <li class="never" data-hits="" data-linenumber="53">
4102
+
4103
+
4104
+ <code class="ruby">end</code>
4105
+ </li>
4106
+
4107
+ </ol>
4108
+ </pre>
4109
+ </div>
4110
+
4111
+
4112
+ </div>
4113
+ </div>
4114
+ </body>
4115
+ </html>