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,157 +1,71 @@
1
1
  import React, { useState } from 'react'
2
2
 
3
- import { Body, Caption, Passphrase, ProgressSimple, TextInput } from '../..'
4
- import zxcvbn from 'zxcvbn'
5
-
3
+ import Body from '../../pb_body/_body'
4
+ import Passphrase from '../../pb_passphrase/_passphrase'
5
+ import TextInput from '../../pb_text_input/_text_input'
6
6
 
7
7
  const PassphraseMeterSettings = (props) => {
8
8
  const [input, setInput] = useState('')
9
- const [result, setResult] = useState({})
10
- const [calculatedStrength, setCalculatedStrength] = useState(0)
11
-
12
- const meterSettings = [
13
- {
14
- label: "Default settings"
15
- },
16
- {
17
- minLength: 5,
18
- label: "Min length = 5",
19
- },
20
- {
21
- minLength: 30,
22
- label: "Min length = 30",
23
- },
24
- {
25
- label: "Average threshold = 1",
26
- averageThreshold: 1,
27
- },
28
- {
29
- label: "Strong Threshold = 4",
30
- strongThreshold: 4,
31
- },
32
- ]
33
-
34
- const handleStrengthCalculation = (settings) => {
35
- const {
36
- passphrase = "",
37
- common = false,
38
- isPwned = false,
39
- averageThreshold = 2,
40
- minLength = 12,
41
- strongThreshold = 3,
42
- } = settings
43
-
44
- const resultByScore = {
45
- 0: {
46
- variant: 'negative',
47
- label: '',
48
- percent: 0,
49
- },
50
- 1: {
51
- variant: 'negative',
52
- label: 'This passphrase is too common',
53
- percent: 25,
54
- },
55
- 2: {
56
- variant: 'negative',
57
- label: 'Too weak',
58
- percent: 25,
59
- },
60
- 3: {
61
- variant: 'warning',
62
- label: 'Almost there, keep going!',
63
- percent: 50,
64
- },
65
- 4: {
66
- variant: 'positive',
67
- label: 'Success! Strong passphrase',
68
- percent: 100,
69
- }
70
- }
71
-
72
- const { score } = zxcvbn(passphrase);
73
-
74
- const noPassphrase = passphrase.length <= 0
75
- const commonPassphrase = common || isPwned
76
- const weakPassphrase = passphrase.length < minLength || score < averageThreshold
77
- const averagePassphrase = score < strongThreshold
78
- const strongPassphrase = score >= strongThreshold
79
-
80
- if (noPassphrase) {
81
- return {...resultByScore[0], score}
82
- } else if (commonPassphrase) {
83
- return {...resultByScore[1], score}
84
- } else if (weakPassphrase) {
85
- return {...resultByScore[2], score}
86
- } else if (averagePassphrase){
87
- return {...resultByScore[3], score}
88
- } else if (strongPassphrase) {
89
- return {...resultByScore[4], score}
90
- }
91
- }
92
9
 
93
-
94
- const handleChange = (e) => {
95
- const passphrase = e.target.value;
96
-
97
- setInput(passphrase)
98
-
99
- const calculated = []
100
-
101
- meterSettings.forEach((setting, index) => {
102
- const results = handleStrengthCalculation({passphrase, ...setting})
103
- if (index == 0) setCalculatedStrength(results.score)
104
- calculated.push(results)
105
- })
106
-
107
- setResult(calculated)
108
- }
10
+ const handleChange = (e) => setInput(e.target.value)
109
11
 
12
+ const [strength, setStrength] = useState(0)
13
+ const handleStrengthChange = (str) => setStrength(str)
110
14
  return (
111
15
  <>
112
16
  <div>
113
17
  <Body>
114
- {
115
- "These examples will all share the same input value. Type in any of the inputs to see how the strength meter changes in response to different settings."
116
- }
18
+ {'These examples will all share the same input value. Type in any of the inputs to see how the strength meter changes in response to different settings.'}
117
19
  </Body>
20
+ <br />
21
+ <TextInput
22
+ disabled
23
+ label="Calculated Strength"
24
+ readOnly
25
+ value={strength}
26
+ />
27
+
118
28
  <Passphrase
119
- label={"Type your passphrase"}
29
+ label="Default settings"
120
30
  onChange={handleChange}
31
+ onStrengthChange={handleStrengthChange}
121
32
  value={input}
122
33
  {...props}
123
34
  />
124
- <TextInput
125
- disabled
126
- label="Calculated Strength"
127
- readOnly
128
- value={calculatedStrength}
35
+
36
+ <Passphrase
37
+ label="Min length = 5"
38
+ minLength={5}
39
+ onChange={handleChange}
40
+ value={input}
41
+ {...props}
42
+ />
43
+ <Passphrase
44
+ label="Min length = 30"
45
+ minLength={30}
46
+ onChange={handleChange}
47
+ value={input}
48
+ {...props}
49
+ />
50
+
51
+ <Passphrase
52
+ averageThreshold={1}
53
+ label="Average threshold = 1"
54
+ onChange={handleChange}
55
+ value={input}
56
+ {...props}
57
+ />
58
+
59
+ <Passphrase
60
+ label="Strong Threshold = 4"
61
+ onChange={handleChange}
62
+ strongThreshold={4}
63
+ value={input}
64
+ {...props}
129
65
  />
130
- {meterSettings.map((settings, index) => (
131
- <div key={index}>
132
- <Passphrase
133
- label={settings.label}
134
- onChange={handleChange}
135
- value={input}
136
- {...props}
137
- />
138
- {input.length > 0 && (
139
- <>
140
- <ProgressSimple
141
- percent={result[index].percent}
142
- variant={result[index].variant}
143
- />
144
- <Caption size='xs'
145
- text={result[index].label}
146
- />
147
- </>
148
- )}
149
- </div>
150
- ))}
151
-
152
66
  </div>
153
67
  </>
154
- );
68
+ )
155
69
  }
156
70
 
157
71
  export default PassphraseMeterSettings
@@ -1,15 +1,9 @@
1
- This example shows how to enhance the passphrase strenght by setting diferent thresholds and lengths.
1
+ By default, the minimum length is 12 and the strength meter will show a strength of 1 if not met. Notice the bar won't change from red until the minimum is met
2
+ Use the `minLength` prop to adjust.
2
3
 
3
- The `meterSettings` array contains different settings for each rendered input. The `handleStrengthCalculation` handles the strength calculation using those settings, showing different results for the same `passphrase` input.
4
4
 
5
- By default, `minLength` is 12. Try typing any value in the `Default Example` input. Notice that the bar won't change from red until the minimum is met.
5
+ The meter also response to `averageThreshold` and `strongTreshold` props. `averageThresold` defaults to 2, and `strongThreshold` defaults to 3.
6
+ This means that the bar will turn yellow when the strength of the passphrase is calculated to be 2 on a 0-4 scale, and green when 3.
6
7
 
7
8
  Adjust these props to tune the sensitivity of the bar.
8
-
9
- Note: minimum length trumps strength and will set the bar to a red color, despite whatever strength is calculated.
10
-
11
- <div class="pb_pill_kit_warning"><div class="pb_title_kit_size_4 pb_pill_text">Disclaimer</div></div>
12
-
13
- This example depends on the `zxcvbn` library.
14
-
15
- You can use any library to achieve the same result, this example only intends to show how to add more features to the `Passphrase` kit.
9
+ Note: minimum length trumps strength and will set the bar to a red color, despite whatever strength is calculated.
@@ -1,110 +1,34 @@
1
1
  import React, { useState } from 'react'
2
- import { useEffect } from 'react'
3
2
 
4
- import { Caption, Passphrase, ProgressSimple, TextInput} from '../..'
5
- import zxcvbn from 'zxcvbn'
3
+ import Passphrase from '../_passphrase'
4
+
5
+ import TextInput from '../../pb_text_input/_text_input'
6
6
 
7
7
  const PassphraseStrengthChange = (props) => {
8
8
  const [input, setInput] = useState('')
9
- const [checkStrength, setCheckStrength] = useState({
10
- label: '',
11
- percent: 0,
12
- score: 0,
13
- variant: ''
14
- })
15
9
 
16
10
  const handleChange = (e) => setInput(e.target.value)
17
11
 
18
- const handleStrengthCalculation = (settings) => {
19
- const {
20
- passphrase = "",
21
- common = false,
22
- isPwned = false,
23
- averageThreshold = 2,
24
- minLength = 12,
25
- strongThreshold = 3,
26
- } = settings
27
-
28
- const resultByScore = {
29
- 0: {
30
- variant: 'negative',
31
- label: '',
32
- percent: 0,
33
- },
34
- 1: {
35
- variant: 'negative',
36
- label: 'This passphrase is too common',
37
- percent: 25,
38
- },
39
- 2: {
40
- variant: 'negative',
41
- label: 'Too weak',
42
- percent: 25,
43
- },
44
- 3: {
45
- variant: 'warning',
46
- label: 'Almost there, keep going!',
47
- percent: 50,
48
- },
49
- 4: {
50
- variant: 'positive',
51
- label: 'Success! Strong passphrase',
52
- percent: 100,
53
- }
54
- }
55
-
56
- const { score } = zxcvbn(passphrase);
57
-
58
- const noPassphrase = passphrase.length <= 0
59
- const commonPassphrase = common || isPwned
60
- const weakPassphrase = passphrase.length < minLength || score < averageThreshold
61
- const averagePassphrase = score < strongThreshold
62
- const strongPassphrase = score >= strongThreshold
63
-
64
- if (noPassphrase) {
65
- return {...resultByScore[0], score}
66
- } else if (commonPassphrase) {
67
- return {...resultByScore[1], score}
68
- } else if (weakPassphrase) {
69
- return {...resultByScore[2], score}
70
- } else if (averagePassphrase){
71
- return {...resultByScore[3], score}
72
- } else if (strongPassphrase) {
73
- return {...resultByScore[4], score}
74
- }
75
- }
76
-
77
- useEffect(() => {
78
- const result = handleStrengthCalculation({ passphrase: input })
79
- setCheckStrength({...result})
80
- },[input])
12
+ const [strength, setStrength] = useState(0)
13
+ const handleStrengthChange = (str) => setStrength(str)
81
14
 
82
15
  return (
83
16
  <>
84
- <Passphrase
85
- label="Passphrase"
86
- onChange={handleChange}
87
- value={input}
88
- {...props}
89
- />
90
- {input.length > 0 && (
91
- <>
92
- <ProgressSimple
93
- percent={checkStrength.percent}
94
- variant={checkStrength.variant}
95
- />
96
- <Caption size='xs'
97
- text={checkStrength.label}
98
- />
99
- </>
100
- )}
101
- <TextInput
102
- disabled
103
- label="Passphrase Strength"
104
- marginTop="xl"
105
- readOnly
106
- value={checkStrength.score}
107
- />
17
+ <div>
18
+ <Passphrase
19
+ label="Passphrase"
20
+ onChange={handleChange}
21
+ onStrengthChange={handleStrengthChange}
22
+ value={input}
23
+ {...props}
24
+ />
25
+ <TextInput
26
+ disabled
27
+ label="Passphrase Strength"
28
+ readOnly
29
+ value={strength}
30
+ />
31
+ </div>
108
32
  </>
109
33
  )
110
34
  }
@@ -1,7 +1,3 @@
1
- Strength is calculated on a 0-4 scale by the <a href="https://github.com/dropbox/zxcvbn" target="_blank"> Zxcvbn package</a>.
1
+ As the strength of the entered passphrase changes, the optional `onStrengthChange` callback is called with the new strength value. This exposes the calculated strength.
2
2
 
3
- <div class="pb_pill_kit_warning"><div class="pb_title_kit_size_4 pb_pill_text">Disclaimer</div></div>
4
-
5
- This example depends on the `zxcvbn` library.
6
-
7
- You can use any library to achieve the same result, this example only intends to show how to add more features to the `Passphrase` kit.
3
+ Strength is calculated on a 0-4 scale by the <a href="https://github.com/dropbox/zxcvbn" target="_blank"> Zxcvbn package</a>
@@ -2,17 +2,13 @@ examples:
2
2
 
3
3
  rails:
4
4
  - passphrase_default: Default
5
- - passphrase_confirmation: Confirmation
6
5
  - passphrase_meter_settings: Meter Settings
7
6
  - passphrase_input_props: Input Props
8
7
  - passphrase_tips: Tips
9
- - passphrase_strength_change: Strength Change
10
- - passphrase_common: Common Passphrases
11
8
  - passphrase_breached: Breached Passphrases
12
9
 
13
10
  react:
14
11
  - passphrase_default: Default
15
- - passphrase_confirmation: Confirmation
16
12
  - passphrase_meter_settings: Meter Settings
17
13
  - passphrase_input_props: Input Props
18
14
  - passphrase_tips: Tips
@@ -1,5 +1,4 @@
1
1
  export { default as PassphraseDefault } from './_passphrase_default.jsx'
2
- export { default as PassphraseConfirmation } from './_passphrase_confirmation.jsx'
3
2
  export { default as PassphraseMeterSettings } from './_passphrase_meter_settings'
4
3
  export { default as PassphraseInputProps } from './_passphrase_input_props'
5
4
  export { default as PassphraseTips } from './_passphrase_tips'
@@ -1 +1 @@
1
- <%= react_component('Passphrase', object.passphrase_options, class: object.classname,) %>
1
+ <%= react_component('Passphrase', object.passphrase_options) %>
@@ -3,14 +3,15 @@
3
3
  module Playbook
4
4
  module PbPassphrase
5
5
  class Passphrase < Playbook::KitBase
6
+ prop :average_threshold
7
+ prop :check_pwned
6
8
  prop :confirmation, type: Playbook::Props::Boolean, default: false
7
9
  prop :input_props, type: Playbook::Props::Hash, default: {}
8
10
  prop :label
9
- prop :show_tips_below, type: Playbook::Props::Enum,
10
- values: %w[always xs sm md lg xl],
11
- default: "always"
11
+ prop :min_length
12
+ prop :show_tips_below
13
+ prop :strong_threshold
12
14
  prop :tips, type: Playbook::Props::Array, default: []
13
- prop :value, type: Playbook::Props::String
14
15
 
15
16
  def classname
16
17
  generate_classname("pb_passphrase")
@@ -18,15 +19,18 @@ module Playbook
18
19
 
19
20
  def passphrase_options
20
21
  {
22
+ checkPwned: check_pwned,
21
23
  dark: dark,
22
24
  id: id,
25
+ averageThreshold: average_threshold,
23
26
  confirmation: confirmation,
24
27
  inputProps: input_props,
25
28
  label: label,
29
+ minLength: min_length,
26
30
  showTipsBelow: show_tips_below,
31
+ strongThreshold: strong_threshold,
27
32
  tips: tips,
28
33
  uncontrolled: true,
29
- value: value,
30
34
  }.compact
31
35
  end
32
36
  end
@@ -64,6 +64,41 @@ test('passes input props to input element', () => {
64
64
  expect(input).toBeDisabled()
65
65
  })
66
66
 
67
+ test('progress bar is invisible when value is empty', () => {
68
+ render(
69
+ <Passphrase
70
+ data={{ testid: testId }}
71
+ />
72
+ )
73
+
74
+ const kit = screen.getByTestId(testId)
75
+ expect(kit.querySelector('[class^=pb_progress_simple_wrapper]')).toHaveClass('progress-empty-input')
76
+ })
77
+
78
+ test('progress bar is visible when value is not empty', () => {
79
+ render(
80
+ <Passphrase
81
+ data={{ testid: testId }}
82
+ value="test_password_input"
83
+ />
84
+ )
85
+
86
+ const kit = screen.getByTestId(testId)
87
+ expect(kit.querySelector('[class^=pb_progress_simple_wrapper]')).not.toHaveClass('progress-empty-input')
88
+ })
89
+
90
+ test('no progress bar is show when confirmation is true', () => {
91
+ render(
92
+ <Passphrase
93
+ confirmation
94
+ data={{ testid: testId }}
95
+ />
96
+ )
97
+
98
+ const kit = screen.getByTestId(testId)
99
+ expect(kit.querySelector('[class^=pb_progress_simple_wrapper]')).toBeNull()
100
+ })
101
+
67
102
  test('popover target shows when tips are given', () => {
68
103
  render(
69
104
  <Passphrase
@@ -86,3 +121,15 @@ test('popover target does not show when tips are not given', () => {
86
121
  const kit = screen.getByTestId(testId)
87
122
  expect(kit.querySelector('[class^=pb_popover_reference_wrapper]')).toBeNull()
88
123
  })
124
+
125
+ test('data-strength attribute exposes strength of password', () => {
126
+ render(
127
+ <Passphrase
128
+ data={{ testid: testId }}
129
+ value="correct horse battery staple"
130
+ />
131
+ )
132
+
133
+ const kit = screen.getByTestId(testId)
134
+ expect(parseInt(kit.getAttribute('data-strength'))).toBeGreaterThan(0)
135
+ })
@@ -0,0 +1,55 @@
1
+ import zxcvbn from 'zxcvbn'
2
+
3
+ export const zxcvbnPasswordScore = (options) => {
4
+ const {
5
+ calculate = zxcvbn,
6
+ averageThreshold = 2,
7
+ strongThreshold = 3,
8
+ minLength = 12,
9
+ } = options
10
+
11
+ return {
12
+ minLength,
13
+ averageThreshold,
14
+ strongThreshold,
15
+ test: function (password = '', common = false) {
16
+ const feedbackValues = (str) => {
17
+ let percent, variant, text
18
+
19
+ if (password.length <= 0) {
20
+ percent = '0'
21
+ variant = 'negative'
22
+ text = '\u00A0' //nbsp to keep form from jumping when typing beings
23
+ } else if (common) {
24
+ percent = '25'
25
+ variant = 'negative'
26
+ text = 'This passphrase is too common'
27
+ } else if (password.length < this.minLength || str < this.averageThreshold) {
28
+ percent = '25'
29
+ variant = 'negative'
30
+ text = 'Too weak'
31
+ } else if (str < this.strongThreshold){
32
+ percent = '50'
33
+ variant = 'warning'
34
+ text = 'Almost there, keep going!'
35
+ } else if (str >= this.strongThreshold) {
36
+ percent = '100'
37
+ variant = 'positive'
38
+ text = 'Success! Strong passphrase'
39
+ }
40
+ return { percent, variant, text }
41
+ }
42
+
43
+ const result = calculate(password)
44
+
45
+ return (
46
+ {
47
+ suggestions: result.feedback.suggestions,
48
+ warning: result.feedback.warning,
49
+ strength: result.score,
50
+ ...feedbackValues(result.score),
51
+ }
52
+ )
53
+ },
54
+ }
55
+ }
@@ -0,0 +1,52 @@
1
+
2
+ import { useEffect, useState } from 'react'
3
+
4
+ const checkHaveIBeenPwned = async function (passphrase) {
5
+ const buffer = new TextEncoder('utf-8').encode(passphrase)
6
+ const digest = await crypto.subtle.digest('SHA-1', buffer)
7
+ const hashArray = Array.from(new Uint8Array(digest))
8
+ const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('')
9
+
10
+ const firstFive = hashHex.slice(0, 5)
11
+ const endOfHash = hashHex.slice(5)
12
+
13
+ const resp = await fetch(`https://api.pwnedpasswords.com/range/${firstFive}`)
14
+ const text = await resp.text()
15
+
16
+ const match = text.split('\n').some((line) => {
17
+ //Each line is <sha-1-hash-suffix>:<count of incidents>
18
+ return line.split(':')[0] === endOfHash.toUpperCase()
19
+ })
20
+ return match
21
+ }
22
+
23
+ /**
24
+ * If the input hasn't changed in <delay> ms,
25
+ * hit the haveibeenpwned api and check if the given passphrase is compromised
26
+ */
27
+ export default function useHaveIBeenPwned(passphrase, minLength, delay = 400) {
28
+ const [isPwned, setIsPwned] = useState(false)
29
+
30
+ useEffect(
31
+ () => {
32
+ // only check the API for passphrases above the minimum size
33
+ if (passphrase.length < minLength) {
34
+ setIsPwned(false)
35
+ return
36
+ }
37
+
38
+ const handler = setTimeout(() => {
39
+ checkHaveIBeenPwned(passphrase)
40
+ .then((pwned) => setIsPwned(pwned))
41
+ .catch(() => setIsPwned(false))
42
+ }, delay)
43
+
44
+ return () => {
45
+ clearTimeout(handler)
46
+ }
47
+ },
48
+ [passphrase, minLength, delay]
49
+ )
50
+
51
+ return isPwned
52
+ }
@@ -0,0 +1,58 @@
1
+ import { useEffect, useMemo, useState } from 'react'
2
+ import zxcvbn from 'zxcvbn'
3
+
4
+ export default function useZxcvbn(options) {
5
+ const { passphrase = '', common, isPwned, confirmation, averageThreshold, minLength, strongThreshold } = options
6
+ const calculator = useMemo(
7
+ () => confirmation ? () => ({ score: 0 }) : zxcvbn,
8
+ [confirmation]
9
+ )
10
+
11
+ const [percent, setPercent] = useState('0')
12
+ const [variant, setVariant] = useState('negative')
13
+ const [text, setText] = useState('\u00A0') //nbsp to keep height constant
14
+ const [result, setResult] = useState({})
15
+
16
+ useEffect(() => {
17
+ if (confirmation) return
18
+ const newResult = calculator(passphrase)
19
+ setResult(newResult)
20
+ const str = newResult.score
21
+
22
+ const noPassphrase = passphrase.length <= 0
23
+ const commonPassphrase = common || isPwned
24
+ const weakPassphrase = passphrase.length < minLength || str < averageThreshold
25
+ const averagePassphrase = str < strongThreshold
26
+ const strongPassphrase = str >= strongThreshold
27
+
28
+ if (noPassphrase) {
29
+ setPercent('0')
30
+ setVariant('negative')
31
+ setText('\u00A0') //nbsp to keep height constant
32
+ } else if (commonPassphrase) {
33
+ setPercent('25')
34
+ setVariant('negative')
35
+ setText('This passphrase is too common')
36
+ } else if (weakPassphrase) {
37
+ setPercent('25')
38
+ setVariant('negative')
39
+ setText('Too weak')
40
+ } else if (averagePassphrase){
41
+ setPercent('50')
42
+ setVariant('warning')
43
+ setText('Almost there, keep going!')
44
+ } else if (strongPassphrase) {
45
+ setPercent('100')
46
+ setVariant('positive')
47
+ setText('Success! Strong passphrase')
48
+ }
49
+ }, [passphrase, common, isPwned, averageThreshold, minLength, strongThreshold]
50
+ )
51
+
52
+ return {
53
+ strength: common || isPwned ? 0 : result.score,
54
+ percent,
55
+ variant,
56
+ text,
57
+ }
58
+ }
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Playbook
4
- PREVIOUS_VERSION = "11.12.1"
5
- VERSION = "11.12.1.pre.alpha.passphrase1"
4
+ PREVIOUS_VERSION = "11.12.0"
5
+ VERSION = "11.12.1"
6
6
  end