playbook_ui 11.12.0 → 11.12.1.pre.alpha.passphrase1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_button/_button.scss +1 -1
  3. data/app/pb_kits/playbook/pb_passphrase/_passphrase.jsx +56 -97
  4. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_breached.html.erb +145 -1
  5. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_breached.jsx +127 -3
  6. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_breached.md +11 -2
  7. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_common.html.erb +136 -0
  8. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_common.jsx +90 -8
  9. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_common.md +5 -0
  10. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_confirmation.html.erb +51 -0
  11. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_confirmation.jsx +39 -0
  12. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_default.html.erb +0 -2
  13. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_default.jsx +6 -20
  14. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_input_props.html.erb +2 -2
  15. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_input_props.jsx +1 -1
  16. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.html.erb +318 -5
  17. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.jsx +134 -48
  18. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.md +11 -5
  19. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_strength_change.html.erb +123 -0
  20. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_strength_change.jsx +96 -20
  21. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_strength_change.md +6 -2
  22. data/app/pb_kits/playbook/pb_passphrase/docs/example.yml +4 -0
  23. data/app/pb_kits/playbook/pb_passphrase/docs/index.js +1 -0
  24. data/app/pb_kits/playbook/pb_passphrase/passphrase.html.erb +1 -1
  25. data/app/pb_kits/playbook/pb_passphrase/passphrase.rb +5 -9
  26. data/app/pb_kits/playbook/pb_passphrase/passphrase.test.jsx +0 -47
  27. data/lib/playbook/version.rb +2 -2
  28. metadata +9 -8
  29. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_default.md +0 -1
  30. data/app/pb_kits/playbook/pb_passphrase/passwordStrength.js +0 -55
  31. data/app/pb_kits/playbook/pb_passphrase/useHaveIBeenPwned.js +0 -52
  32. data/app/pb_kits/playbook/pb_passphrase/useZxcvbn.js +0 -58
@@ -0,0 +1,136 @@
1
+ <%= pb_rails("body", props: {
2
+ margin_bottom: "md",
3
+ id: "body_common"
4
+ }) %>
5
+
6
+ <%= pb_rails("passphrase", props: { label: "Passphrase", classname: "passphrase_common" }) %>
7
+
8
+ <%= pb_rails("progress_simple", props: { percent: 0, id: "bar_common" }) %>
9
+
10
+ <%= pb_rails("caption", props: { size: 'xs', text: "hello", id: "caption_common" }) %>
11
+
12
+
13
+ <%= javascript_tag do %>
14
+ window.addEventListener("DOMContentLoaded", () => {
15
+
16
+ const commonText = document.querySelector("#body_common")
17
+
18
+ // variables for the kits you are targeting
19
+ const passphrase = document.querySelector(".passphrase_common").querySelector("input")
20
+ const barVariant = document.getElementById("bar_common")
21
+ const barPercent = document.getElementById("bar_common").querySelector("div")
22
+ const caption = document.getElementById("caption_common")
23
+
24
+ // hide the bar and captions
25
+ barVariant.style.display = 'none';
26
+ barPercent.style.display = 'none';
27
+ caption.style.display = 'none';
28
+
29
+
30
+ const handleStrengthCalculation = (settings) => {
31
+ const {
32
+ passphrase = "",
33
+ common = false,
34
+ isPwned = false,
35
+ averageThreshold = 2,
36
+ minLength = 12,
37
+ strongThreshold = 3,
38
+ } = settings
39
+
40
+ const resultByScore = {
41
+ 0: {
42
+ variant: 'negative',
43
+ label: '',
44
+ percent: 0,
45
+ },
46
+ 1: {
47
+ variant: 'negative',
48
+ label: 'This passphrase is too common',
49
+ percent: 25,
50
+ },
51
+ 2: {
52
+ variant: 'negative',
53
+ label: 'Too weak',
54
+ percent: 25,
55
+ },
56
+ 3: {
57
+ variant: 'warning',
58
+ label: 'Almost there, keep going!',
59
+ percent: 50,
60
+ },
61
+ 4: {
62
+ variant: 'positive',
63
+ label: 'Success! Strong passphrase',
64
+ percent: 100,
65
+ }
66
+ }
67
+
68
+ const { score } = zxcvbn(passphrase);
69
+
70
+ const noPassphrase = passphrase.length <= 0
71
+ const commonPassphrase = common || isPwned
72
+ const weakPassphrase = passphrase.length < minLength || score < averageThreshold
73
+ const averagePassphrase = score < strongThreshold
74
+ const strongPassphrase = score >= strongThreshold
75
+
76
+ if (noPassphrase) {
77
+ return {...resultByScore[0], score}
78
+ } else if (commonPassphrase) {
79
+ return {...resultByScore[1], score}
80
+ } else if (weakPassphrase) {
81
+ return {...resultByScore[2], score}
82
+ } else if (averagePassphrase){
83
+ return {...resultByScore[3], score}
84
+ } else if (strongPassphrase) {
85
+ return {...resultByScore[4], score}
86
+ }
87
+ }
88
+
89
+ // array that holds the common passwords you wish to target
90
+ const COMMON_PASSPHRASES = ['passphrase', 'apple', 'password', 'p@55w0rd']
91
+
92
+ commonText.textContent = `Try typing any of the following: ${COMMON_PASSPHRASES.join(', ')}`
93
+
94
+ // function that checks if the user password is in the common password list
95
+ const isCommon = (passphrase) => {
96
+ if (COMMON_PASSPHRASES.includes(passphrase))
97
+ return true
98
+ return false
99
+ }
100
+
101
+ // event listeners attached to the input field
102
+ passphrase.addEventListener('input', (e) => {
103
+ const passphrase = e.target.value;
104
+
105
+ // pass in passphrase to the handleStrengthCalculation and set that equal to result variable
106
+ const result = handleStrengthCalculation({ passphrase: passphrase, common: isCommon(passphrase) })
107
+
108
+ // conditional statment to show or hide progress_simple bar and caption if user has entered a password
109
+ if (passphrase) {
110
+ barVariant.style.display = 'block';
111
+
112
+ barPercent.style.display = 'block';
113
+
114
+ caption.style.display = 'block';
115
+ } else {
116
+ barVariant.style.display = 'none';
117
+
118
+ barPercent.style.display = 'none';
119
+
120
+ caption.style.display = 'none';
121
+ }
122
+
123
+ // set the width of the progress_simple kit
124
+ barPercent.style.width = result.percent.toString()+ "%"
125
+
126
+
127
+ // set the variant of the progress_simple kit
128
+ barVariant.setAttribute("class", "pb_progress_simple_kit_"+ result.variant +"_left");
129
+
130
+
131
+ // set the text of the caption kit
132
+ caption.textContent = result.label
133
+ });
134
+
135
+ })
136
+ <% end %>
@@ -1,32 +1,114 @@
1
- import React, { useState } from 'react'
1
+ import React, { useState, useEffect } from 'react'
2
2
 
3
- import Passphrase from '../_passphrase'
4
- import Body from '../../pb_body/_body'
3
+ import {Body, Caption, Passphrase, ProgressSimple} from '../..'
4
+ import zxcvbn from 'zxcvbn'
5
5
 
6
6
  const PassphraseCommon = (props) => {
7
7
  const [input, setInput] = useState('')
8
-
8
+ const [checkStrength, setCheckStrength] = useState({
9
+ label: '',
10
+ percent: 0,
11
+ score: 0,
12
+ variant: ''
13
+ })
9
14
  const handleChange = (e) => setInput(e.target.value)
10
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
+
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
+ }
74
+
11
75
  const COMMON_PASSPHRASES = ['passphrase', 'apple', 'password', 'p@55w0rd']
12
76
 
13
- const commonCheck = (passphrase) => {
77
+ const isCommon = (passphrase) => {
14
78
  if (COMMON_PASSPHRASES.includes(passphrase))
15
79
  return true
16
80
  return false
17
81
  }
18
82
 
83
+ useEffect(() => {
84
+ const result = handleStrengthCalculation({ passphrase: input, common: isCommon(input) });
85
+ setCheckStrength({ ...result })
86
+ }, [input])
87
+
88
+
19
89
  return (
20
90
  <>
21
91
  <div>
22
- <Body text={`Try typing any of the following: ${COMMON_PASSPHRASES.join(' ')}`} />
23
- <br />
92
+ <Body
93
+ marginBottom='md'
94
+ text={`Try typing any of the following: ${COMMON_PASSPHRASES.join(', ')}`} />
24
95
  <Passphrase
25
- common={commonCheck(input)}
26
96
  onChange={handleChange}
27
97
  value={input}
28
98
  {...props}
29
99
  />
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
+ )}
30
112
  </div>
31
113
  </>
32
114
  )
@@ -0,0 +1,5 @@
1
+ <div class="pb_pill_kit_warning"><div class="pb_title_kit_size_4 pb_pill_text">Disclaimer</div></div>
2
+
3
+ This example depends on the `zxcvbn` library.
4
+
5
+ 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.
@@ -0,0 +1,51 @@
1
+ <%= pb_rails("passphrase", props: { classname: "pass_input_1" }) %>
2
+
3
+ <%= pb_rails("passphrase", props: { confirmation: true, classname: "pass_input_2"}) %>
4
+
5
+ <div id="match"> </div>
6
+
7
+ <%= javascript_tag do %>
8
+ window.addEventListener("DOMContentLoaded", () => {
9
+
10
+ const useState = (defaultValue) => {
11
+ let value = defaultValue;
12
+ const getValue = () => value
13
+ const setValue = (newValue) => {
14
+ return value = newValue
15
+ }
16
+ return [getValue, setValue];
17
+ }
18
+
19
+ const [input, setInput] = useState('')
20
+ const [confirmationInput, setConfirmationInput] = useState('')
21
+
22
+ const match = document.querySelector("#match")
23
+
24
+ const input1 = document.querySelector(".pass_input_1").querySelector("input")
25
+ const input2 = document.querySelector(".pass_input_2").querySelector("input")
26
+
27
+ input1.addEventListener('input', (e) => {
28
+ setInput(e.target.value)
29
+ setMatchText()
30
+ });
31
+
32
+ input2.addEventListener('input', (e) => {
33
+ setConfirmationInput(e.target.value)
34
+ setMatchText()
35
+ });
36
+
37
+ const setMatchText = () => {
38
+
39
+ if (input() && confirmationInput()) {
40
+ if (input() === confirmationInput()) {
41
+ match.textContent = "They match!"
42
+ } else {
43
+ match.textContent = "They don't match!"
44
+ }
45
+ } else {
46
+ match.textContent = ""
47
+ }
48
+
49
+ }
50
+ })
51
+ <% end %>
@@ -0,0 +1,39 @@
1
+ import React, { useState } from 'react'
2
+
3
+ import {Body, Passphrase} from '../..'
4
+
5
+ const PassphraseConfirmation = (props) => {
6
+ const [input, setInput] = useState('')
7
+ const [confirmationInput, setConfirmationInput] = useState('')
8
+
9
+ const handleChange = (e) => setInput(e.target.value)
10
+ const handleConfirmationChange = (e) => setConfirmationInput(e.target.value)
11
+
12
+ return (
13
+ <>
14
+ <div>
15
+ <Passphrase
16
+ onChange={handleChange}
17
+ value={input}
18
+ {...props}
19
+ />
20
+ <Passphrase
21
+ confirmation
22
+ onChange={handleConfirmationChange}
23
+ value={confirmationInput}
24
+ {...props}
25
+ />
26
+ {input && confirmationInput && (
27
+ <Body
28
+ text={
29
+ input === confirmationInput ? "They match!" : "They don't match!"
30
+ }
31
+ {...props}
32
+ />
33
+ )}
34
+ </div>
35
+ </>
36
+ );
37
+ }
38
+
39
+ export default PassphraseConfirmation
@@ -1,3 +1 @@
1
1
  <%= pb_rails("passphrase") %>
2
-
3
- <%= pb_rails("passphrase", props: { confirmation: true}) %>
@@ -6,27 +6,13 @@ 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
-
12
9
  return (
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
- </>
10
+ <Passphrase
11
+ id="my-passphrase"
12
+ onChange={handleChange}
13
+ value={input}
14
+ {...props}
15
+ />
30
16
  )
31
17
  }
32
18
 
@@ -4,7 +4,7 @@
4
4
  id: "my-disabled-passphrase",
5
5
  name: "my-disabled-field",
6
6
  },
7
- label: "Input props passed directly to input kit"
7
+ label: "Pass props 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, id, etc for use in forms"
15
+ label: "Set name and ID for use in form libraries"
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' }}
39
+ inputProps={{ name: 'my-value-name', id: 'my-value-id-2' }}
40
40
  label="Set name and ID for use in form libraries"
41
41
  onChange={handleChange}
42
42
  value={input}