playbook_ui 11.12.1.pre.alpha.passphrase1 → 11.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_passphrase/_passphrase.jsx +97 -56
  3. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_breached.html.erb +1 -145
  4. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_breached.jsx +3 -127
  5. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_breached.md +2 -11
  6. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_common.jsx +8 -90
  7. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_default.html.erb +2 -0
  8. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_default.jsx +20 -6
  9. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_default.md +1 -0
  10. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_input_props.html.erb +2 -2
  11. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_input_props.jsx +1 -1
  12. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.html.erb +5 -318
  13. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.jsx +48 -134
  14. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.md +5 -11
  15. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_strength_change.jsx +20 -96
  16. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_strength_change.md +2 -6
  17. data/app/pb_kits/playbook/pb_passphrase/docs/example.yml +0 -4
  18. data/app/pb_kits/playbook/pb_passphrase/docs/index.js +0 -1
  19. data/app/pb_kits/playbook/pb_passphrase/passphrase.html.erb +1 -1
  20. data/app/pb_kits/playbook/pb_passphrase/passphrase.rb +9 -5
  21. data/app/pb_kits/playbook/pb_passphrase/passphrase.test.jsx +47 -0
  22. data/app/pb_kits/playbook/pb_passphrase/passwordStrength.js +55 -0
  23. data/app/pb_kits/playbook/pb_passphrase/useHaveIBeenPwned.js +52 -0
  24. data/app/pb_kits/playbook/pb_passphrase/useZxcvbn.js +58 -0
  25. data/lib/playbook/version.rb +2 -2
  26. metadata +8 -9
  27. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_common.html.erb +0 -136
  28. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_common.md +0 -5
  29. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_confirmation.html.erb +0 -51
  30. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_confirmation.jsx +0 -39
  31. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_strength_change.html.erb +0 -123
@@ -1,114 +1,32 @@
1
- import React, { useState, useEffect } from 'react'
1
+ import React, { useState } from 'react'
2
2
 
3
- import {Body, Caption, Passphrase, ProgressSimple} from '../..'
4
- import zxcvbn from 'zxcvbn'
3
+ import Passphrase from '../_passphrase'
4
+ import Body from '../../pb_body/_body'
5
5
 
6
6
  const PassphraseCommon = (props) => {
7
7
  const [input, setInput] = useState('')
8
- const [checkStrength, setCheckStrength] = useState({
9
- label: '',
10
- percent: 0,
11
- score: 0,
12
- variant: ''
13
- })
14
- const handleChange = (e) => setInput(e.target.value)
15
-
16
- const handleStrengthCalculation = (settings) => {
17
- const {
18
- passphrase = "",
19
- common = false,
20
- isPwned = false,
21
- averageThreshold = 2,
22
- minLength = 12,
23
- strongThreshold = 3,
24
- } = settings
25
-
26
- const resultByScore = {
27
- 0: {
28
- variant: 'negative',
29
- label: '',
30
- percent: 0,
31
- },
32
- 1: {
33
- variant: 'negative',
34
- label: 'This passphrase is too common',
35
- percent: 25,
36
- },
37
- 2: {
38
- variant: 'negative',
39
- label: 'Too weak',
40
- percent: 25,
41
- },
42
- 3: {
43
- variant: 'warning',
44
- label: 'Almost there, keep going!',
45
- percent: 50,
46
- },
47
- 4: {
48
- variant: 'positive',
49
- label: 'Success! Strong passphrase',
50
- percent: 100,
51
- }
52
- }
53
-
54
- const { score } = zxcvbn(passphrase);
55
-
56
- const noPassphrase = passphrase.length <= 0
57
- const commonPassphrase = common || isPwned
58
- const weakPassphrase = passphrase.length < minLength || score < averageThreshold
59
- const averagePassphrase = score < strongThreshold
60
- const strongPassphrase = score >= strongThreshold
61
8
 
62
- if (noPassphrase) {
63
- return {...resultByScore[0], score}
64
- } else if (commonPassphrase) {
65
- return {...resultByScore[1], score}
66
- } else if (weakPassphrase) {
67
- return {...resultByScore[2], score}
68
- } else if (averagePassphrase){
69
- return {...resultByScore[3], score}
70
- } else if (strongPassphrase) {
71
- return {...resultByScore[4], score}
72
- }
73
- }
9
+ const handleChange = (e) => setInput(e.target.value)
74
10
 
75
11
  const COMMON_PASSPHRASES = ['passphrase', 'apple', 'password', 'p@55w0rd']
76
12
 
77
- const isCommon = (passphrase) => {
13
+ const commonCheck = (passphrase) => {
78
14
  if (COMMON_PASSPHRASES.includes(passphrase))
79
15
  return true
80
16
  return false
81
17
  }
82
18
 
83
- useEffect(() => {
84
- const result = handleStrengthCalculation({ passphrase: input, common: isCommon(input) });
85
- setCheckStrength({ ...result })
86
- }, [input])
87
-
88
-
89
19
  return (
90
20
  <>
91
21
  <div>
92
- <Body
93
- marginBottom='md'
94
- text={`Try typing any of the following: ${COMMON_PASSPHRASES.join(', ')}`} />
22
+ <Body text={`Try typing any of the following: ${COMMON_PASSPHRASES.join(' ')}`} />
23
+ <br />
95
24
  <Passphrase
25
+ common={commonCheck(input)}
96
26
  onChange={handleChange}
97
27
  value={input}
98
28
  {...props}
99
29
  />
100
- {input.length > 0 && (
101
- <>
102
- <ProgressSimple
103
- className={input.length === 0 ? "progress-empty-input" : null}
104
- percent={checkStrength.percent}
105
- variant={checkStrength.variant}
106
- />
107
- <Caption size='xs'
108
- text={checkStrength.label}
109
- />
110
- </>
111
- )}
112
30
  </div>
113
31
  </>
114
32
  )
@@ -1 +1,3 @@
1
1
  <%= pb_rails("passphrase") %>
2
+
3
+ <%= pb_rails("passphrase", props: { confirmation: true}) %>
@@ -6,13 +6,27 @@ const PassphraseDefault = (props) => {
6
6
  const [input, setInput] = useState('')
7
7
  const handleChange = (e) => setInput(e.target.value)
8
8
 
9
+ const [confoInput, setConfoInput] = useState('')
10
+ const handleConfoChange = (e) => setConfoInput(e.target.value)
11
+
9
12
  return (
10
- <Passphrase
11
- id="my-passphrase"
12
- onChange={handleChange}
13
- value={input}
14
- {...props}
15
- />
13
+ <>
14
+ <div>
15
+ <Passphrase
16
+ id="my-passphrase"
17
+ onChange={handleChange}
18
+ value={input}
19
+ {...props}
20
+ />
21
+ <Passphrase
22
+ confirmation
23
+ onChange={handleConfoChange}
24
+ value={confoInput}
25
+ {...props}
26
+ />
27
+ <span>{input === confoInput ? 'They match!' : 'They don\'t match!'}</span>
28
+ </div>
29
+ </>
16
30
  )
17
31
  }
18
32
 
@@ -0,0 +1 @@
1
+ Use the `confirmation` prop to only include the label and show/hide icon.
@@ -4,7 +4,7 @@
4
4
  id: "my-disabled-passphrase",
5
5
  name: "my-disabled-field",
6
6
  },
7
- label: "Pass props directly to input kit"
7
+ label: "Input props passed directly to input kit"
8
8
  }) %>
9
9
 
10
10
  <%= pb_rails("passphrase", props: {
@@ -12,5 +12,5 @@
12
12
  id: "my-custome-id",
13
13
  name: "my-value-name",
14
14
  },
15
- label: "Set name and ID for use in form libraries"
15
+ label: "Set name, id, etc for use in forms"
16
16
  }) %>
@@ -36,7 +36,7 @@ const PassphraseInputProps = (props) => {
36
36
  {...props}
37
37
  />
38
38
  <Passphrase
39
- inputProps={{ name: 'my-value-name', id: 'my-value-id-2' }}
39
+ inputProps={{ name: 'my-value-name', id: 'my-value-id' }}
40
40
  label="Set name and ID for use in form libraries"
41
41
  onChange={handleChange}
42
42
  value={input}
@@ -1,323 +1,10 @@
1
- <%= pb_rails("passphrase", props: { label: "Default Settings", classname: "def_passphrase" }) %>
2
1
 
3
- <%= pb_rails("progress_simple", props: { percent: 0, id: "def_bar" }) %>
2
+ <%= pb_rails("passphrase", props: { label: "Default Settings"}) %>
4
3
 
5
- <%= pb_rails("caption", props: { size: 'xs', text: "hello", id: "def_caption" }) %>
4
+ <%= pb_rails("passphrase", props: { label: "Min length = 5", min_length: 5}) %>
6
5
 
7
- <%= pb_rails("text_input", props: { label: "Calculated Strength", value: "0", disabled: true, id: "calc_strength" }) %>
6
+ <%= pb_rails("passphrase", props: { label: "Min length = 30", min_length: 30}) %>
8
7
 
9
- <%= pb_rails("passphrase", props: { label: "Min length = 5", classname: "min_5" }) %>
8
+ <%= pb_rails("passphrase", props: { average_threshold: 1, label: "Average Threshold = 1"}) %>
10
9
 
11
- <%= pb_rails("progress_simple", props: { percent: 0, id: "min_5_bar" }) %>
12
-
13
- <%= pb_rails("caption", props: { size: 'xs', text: "hello", id: "min_5_caption" }) %>
14
-
15
- <%= pb_rails("passphrase", props: { label: "Min length = 30", classname: "min_30" }) %>
16
-
17
- <%= pb_rails("progress_simple", props: { percent: 0, id: "min_30_bar" }) %>
18
-
19
- <%= pb_rails("caption", props: { size: 'xs', text: "hello", id: "min_30_caption" }) %>
20
-
21
- <%= pb_rails("passphrase", props: { label: "Average Threshold = 1", classname: "avg_1" }) %>
22
-
23
- <%= pb_rails("progress_simple", props: { percent: 0, id: "avg_1_bar" }) %>
24
-
25
- <%= pb_rails("caption", props: { size: 'xs', text: "hello", id: "avg_1_caption" }) %>
26
-
27
- <%= pb_rails("passphrase", props: { label: "Strong Threshold = 4", classname: "strong_4" }) %>
28
-
29
- <%= pb_rails("progress_simple", props: { percent: 0, id: "strong_4_bar" }) %>
30
-
31
- <%= pb_rails("caption", props: { size: 'xs', text: "hello", id: "strong_4_caption" }) %>
32
-
33
-
34
-
35
- <%= javascript_tag do %>
36
- window.addEventListener("DOMContentLoaded", () => {
37
-
38
-
39
- // variables for the passphrase kits you are targeting
40
- const defPassphrase = document.querySelector(".def_passphrase").querySelector("input")
41
- const min5 = document.querySelector(".min_5").querySelector("input")
42
- const min30 = document.querySelector(".min_30").querySelector("input")
43
- const avg1 = document.querySelector(".avg_1").querySelector("input")
44
- const strong4 = document.querySelector(".strong_4").querySelector("input")
45
-
46
- // variable for the text_input kit you are targeting
47
- const calcStrength = document.querySelector("#calc_strength")
48
-
49
- // variables for the progress_simple kits you are targeting
50
- const defBarVariant = document.getElementById("def_bar")
51
- const defBarPercent = document.getElementById("def_bar").querySelector("div")
52
- const min5BarVariant = document.getElementById("min_5_bar")
53
- const min5BarPercent = document.getElementById("min_5_bar").querySelector("div")
54
- const min30BarVariant = document.getElementById("min_30_bar")
55
- const min30BarPercent = document.getElementById("min_30_bar").querySelector("div")
56
- const avg1BarVariant = document.getElementById("avg_1_bar")
57
- const avg1BarPercent = document.getElementById("avg_1_bar").querySelector("div")
58
- const strong4BarVariant = document.getElementById("strong_4_bar")
59
- const strong4BarPercent = document.getElementById("strong_4_bar").querySelector("div")
60
-
61
- // hide all the progress_simple bars
62
- defBarVariant.style.display = 'none';
63
- defBarPercent.style.display = 'none';
64
- min5BarVariant.style.display = 'none';
65
- min5BarPercent.style.display = 'none';
66
- min30BarVariant.style.display = 'none';
67
- min30BarPercent.style.display = 'none';
68
- avg1BarVariant.style.display = 'none';
69
- avg1BarPercent.style.display = 'none';
70
- strong4BarVariant.style.display = 'none';
71
- strong4BarPercent.style.display = 'none';
72
-
73
- // variables for the caption kits you are targeting
74
- const defCaption = document.getElementById("def_caption")
75
- const min5Caption = document.getElementById("min_5_caption")
76
- const min30Caption = document.getElementById("min_30_caption")
77
- const avg1Caption = document.getElementById("avg_1_caption")
78
- const strong4Caption = document.getElementById("strong_4_caption")
79
-
80
- // hide all the captions
81
- defCaption.style.display = 'none';
82
- min5Caption.style.display = 'none';
83
- min30Caption.style.display = 'none';
84
- avg1Caption.style.display = 'none';
85
- strong4Caption.style.display = 'none';
86
-
87
- // funtion that determines strenght of user passowrd using zxcvbn
88
- const handleStrengthCalculation = (settings) => {
89
-
90
- // define the settings object with its defaults
91
- const {
92
- passphrase = "",
93
- common = false,
94
- isPwned = false,
95
- averageThreshold = 2,
96
- minLength = 12,
97
- strongThreshold = 3,
98
- } = settings
99
-
100
- // define the resultsByScore objects, these return an object with a variant and percentage,
101
- // depending on the score of the password
102
- const resultByScore = {
103
- 0: {
104
- variant: 'negative',
105
- label: '',
106
- percent: 0,
107
- },
108
- 1: {
109
- variant: 'negative',
110
- label: 'This passphrase is too common',
111
- percent: 25,
112
- },
113
- 2: {
114
- variant: 'negative',
115
- label: 'Too weak',
116
- percent: 25,
117
- },
118
- 3: {
119
- variant: 'warning',
120
- label: 'Almost there, keep going!',
121
- percent: 50,
122
- },
123
- 4: {
124
- variant: 'positive',
125
- label: 'Success! Strong passphrase',
126
- percent: 100,
127
- }
128
- }
129
-
130
- const { score } = zxcvbn(passphrase);
131
-
132
- const noPassphrase = passphrase.length <= 0
133
- const commonPassphrase = common || isPwned
134
- const weakPassphrase = passphrase.length < minLength || score < averageThreshold
135
- const averagePassphrase = score < strongThreshold
136
- const strongPassphrase = score >= strongThreshold
137
-
138
- // conditional that returns the score of the password, along with the resultByScore object
139
- // so we can change the percantage and variant of the progress_simple kit
140
- if (noPassphrase) {
141
- return {...resultByScore[0], score}
142
- } else if (commonPassphrase) {
143
- return {...resultByScore[1], score}
144
- } else if (weakPassphrase) {
145
- return {...resultByScore[2], score}
146
- } else if (averagePassphrase){
147
- return {...resultByScore[3], score}
148
- } else if (strongPassphrase) {
149
- return {...resultByScore[4], score}
150
- }
151
- }
152
-
153
-
154
- // event listeners attached to the input field
155
- min5.addEventListener('input', (e) => {
156
- const passphrase = e.target.value;
157
-
158
- // defining setting object to spread into handleStrengthCalculation
159
- setting = {
160
- minLength: 5,
161
- }
162
-
163
- // pass in passphrase and setting object to handleStrengthCalculation and set that equal to result variable
164
- const result = handleStrengthCalculation({passphrase, ...setting})
165
-
166
- // set the value of the text_input to the score
167
- calcStrength.value = result.score
168
-
169
- // conditional statment to show or hide progress_simple bar and caption if user has entered a password
170
- if (passphrase) {
171
- min5BarVariant.style.display = 'block';
172
-
173
- min5BarPercent.style.display = 'block';
174
-
175
- min5Caption.style.display = 'block';
176
- } else {
177
- min5BarVariant.style.display = 'none';
178
-
179
- min5BarPercent.style.display = 'none';
180
-
181
- min5Caption.style.display = 'none';
182
- }
183
-
184
- // set the width of the progress_simple kit
185
- min5BarPercent.style.width = result.percent.toString()+ "%"
186
-
187
-
188
- // set the variant of the progress_simple kit
189
- min5BarVariant.setAttribute("class", "pb_progress_simple_kit_"+ result.variant +"_left");
190
-
191
-
192
- // set the text of the caption kit
193
- min5Caption.textContent = result.label
194
- });
195
-
196
- defPassphrase.addEventListener('input', (e) => {
197
- const passphrase = e.target.value;
198
-
199
- const result = handleStrengthCalculation({passphrase})
200
-
201
- calcStrength.value = result.score
202
-
203
- if (passphrase) {
204
- defBarVariant.style.display = 'block';
205
-
206
- defBarPercent.style.display = 'block';
207
-
208
- defCaption.style.display = 'block';
209
- } else {
210
- defBarVariant.style.display = 'none';
211
-
212
- defBarPercent.style.display = 'none';
213
-
214
- defCaption.style.display = 'none';
215
- }
216
-
217
- defBarPercent.style.width = result.percent.toString()+ "%"
218
-
219
- defBarVariant.setAttribute("class", "pb_progress_simple_kit_"+ result.variant +"_left");
220
-
221
- defCaption.textContent = result.label
222
-
223
- });
224
-
225
- min30.addEventListener('input', (e) => {
226
- const passphrase = e.target.value;
227
-
228
- setting = {
229
- minLength: 30,
230
- }
231
-
232
- const result = handleStrengthCalculation({passphrase, ...setting})
233
-
234
- calcStrength.value = result.score
235
-
236
- if (passphrase) {
237
- min30BarVariant.style.display = 'block';
238
-
239
- min30BarPercent.style.display = 'block';
240
-
241
- min30Caption.style.display = 'block';
242
- } else {
243
- min30BarVariant.style.display = 'none';
244
-
245
- min30BarPercent.style.display = 'none';
246
-
247
- min30Caption.style.display = 'none';
248
- }
249
-
250
- min30BarPercent.style.width = result.percent.toString()+ "%"
251
-
252
- min30BarVariant.setAttribute("class", "pb_progress_simple_kit_"+ result.variant +"_left");
253
-
254
- min30Caption.textContent = result.label
255
- });
256
-
257
- avg1.addEventListener('input', (e) => {
258
- const passphrase = e.target.value;
259
-
260
- setting = {
261
- averageThreshold: 1,
262
- }
263
-
264
- const result = handleStrengthCalculation({passphrase, ...setting})
265
-
266
- calcStrength.value = result.score
267
-
268
- if (passphrase) {
269
- avg1BarVariant.style.display = 'block';
270
-
271
- avg1BarPercent.style.display = 'block';
272
-
273
- avg1Caption.style.display = 'block';
274
- } else {
275
- avg1BarVariant.style.display = 'none';
276
-
277
- avg1BarPercent.style.display = 'none';
278
-
279
- avg1Caption.style.display = 'none';
280
- }
281
-
282
- avg1BarPercent.style.width = result.percent.toString()+ "%"
283
-
284
- avg1BarVariant.setAttribute("class", "pb_progress_simple_kit_"+ result.variant +"_left");
285
-
286
- avg1Caption.textContent = result.label
287
- });
288
-
289
- strong4.addEventListener('input', (e) => {
290
- const passphrase = e.target.value;
291
-
292
- setting = {
293
- strongThreshold: 4,
294
- }
295
-
296
- const result = handleStrengthCalculation({passphrase, ...setting})
297
-
298
- calcStrength.value = result.score
299
-
300
- if (passphrase) {
301
- strong4BarVariant.style.display = 'block';
302
-
303
- strong4BarPercent.style.display = 'block';
304
-
305
- strong4Caption.style.display = 'block';
306
- } else {
307
- strong4BarVariant.style.display = 'none';
308
-
309
- strong4BarPercent.style.display = 'none';
310
-
311
- strong4Caption.style.display = 'none';
312
- }
313
-
314
- strong4BarPercent.style.width = result.percent.toString()+ "%"
315
-
316
- strong4BarVariant.setAttribute("class", "pb_progress_simple_kit_"+ result.variant +"_left");
317
-
318
- strong4Caption.textContent = result.label
319
- });
320
-
321
-
322
- })
323
- <% end %>
10
+ <%= pb_rails("passphrase", props: { label: "Strong Threshold = 4", strong_threshold: 4}) %>