@standardnotes/authenticator 2.3.5
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.
- package/.babelrc +21 -0
- package/.browserlistrc +2 -0
- package/.eslintignore +3 -0
- package/.eslintrc +30 -0
- package/CHANGELOG.md +136 -0
- package/README.md +7 -0
- package/app/assets/svg/drag-indicator.svg +14 -0
- package/app/assets/svg/palette.svg +3 -0
- package/app/assets/svg/reorder-icon.svg +37 -0
- package/app/components/AuthEntry.jsx +202 -0
- package/app/components/AuthMenu.jsx +63 -0
- package/app/components/ConfirmDialog.jsx +37 -0
- package/app/components/CopyNotification.jsx +15 -0
- package/app/components/CountdownPie.jsx +131 -0
- package/app/components/DataErrorAlert.jsx +21 -0
- package/app/components/EditEntry.jsx +283 -0
- package/app/components/Home.jsx +365 -0
- package/app/components/QRCodeReader.jsx +91 -0
- package/app/components/ViewEntries.jsx +82 -0
- package/app/index.js +4 -0
- package/app/lib/otp.js +184 -0
- package/app/lib/utils.js +185 -0
- package/app/stylesheets/main.scss +443 -0
- package/editor.index.ejs +10 -0
- package/ext.json.sample +8 -0
- package/package.json +68 -0
- package/webpack.config.js +74 -0
- package/webpack.dev.js +23 -0
- package/webpack.prod.js +11 -0
package/.babelrc
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"presets": [
|
|
3
|
+
[
|
|
4
|
+
"@babel/preset-env",
|
|
5
|
+
{
|
|
6
|
+
"modules": false,
|
|
7
|
+
"targets": "defaults"
|
|
8
|
+
}
|
|
9
|
+
],
|
|
10
|
+
[
|
|
11
|
+
"@babel/preset-react",
|
|
12
|
+
{
|
|
13
|
+
"runtime": "automatic"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
],
|
|
17
|
+
"plugins": [
|
|
18
|
+
"@babel/plugin-proposal-class-properties",
|
|
19
|
+
"@babel/plugin-transform-runtime"
|
|
20
|
+
]
|
|
21
|
+
}
|
package/.browserlistrc
ADDED
package/.eslintignore
ADDED
package/.eslintrc
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"env": {
|
|
3
|
+
"browser": true,
|
|
4
|
+
"es6": true
|
|
5
|
+
},
|
|
6
|
+
"extends": [
|
|
7
|
+
"@standardnotes/eslint-config-extensions",
|
|
8
|
+
"plugin:react/recommended"
|
|
9
|
+
],
|
|
10
|
+
"parser": "@babel/eslint-parser",
|
|
11
|
+
"parserOptions": {
|
|
12
|
+
"ecmaVersion": 11,
|
|
13
|
+
"ecmaFeatures": {
|
|
14
|
+
"jsx": true
|
|
15
|
+
},
|
|
16
|
+
"sourceType": "module"
|
|
17
|
+
},
|
|
18
|
+
"plugins": [
|
|
19
|
+
"react"
|
|
20
|
+
],
|
|
21
|
+
"settings": {
|
|
22
|
+
"react": {
|
|
23
|
+
"version": "detect"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"rules": {
|
|
27
|
+
"react/jsx-uses-react": "off",
|
|
28
|
+
"react/react-in-jsx-scope": "off"
|
|
29
|
+
}
|
|
30
|
+
}
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
|
+
|
|
6
|
+
## [2.3.5](https://github.com/standardnotes/plugins/compare/@standardnotes/authenticator@2.3.4...@standardnotes/authenticator@2.3.5) (2022-11-04)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @standardnotes/authenticator
|
|
9
|
+
|
|
10
|
+
## [2.3.4](https://github.com/standardnotes/plugins/compare/@standardnotes/authenticator@2.3.3...@standardnotes/authenticator@2.3.4) (2022-11-04)
|
|
11
|
+
|
|
12
|
+
**Note:** Version bump only for package @standardnotes/authenticator
|
|
13
|
+
|
|
14
|
+
## [2.3.3](https://github.com/standardnotes/plugins/compare/@standardnotes/authenticator@2.3.2...@standardnotes/authenticator@2.3.3) (2022-11-04)
|
|
15
|
+
|
|
16
|
+
**Note:** Version bump only for package @standardnotes/authenticator
|
|
17
|
+
|
|
18
|
+
## [2.3.2](https://github.com/standardnotes/plugins/compare/@standardnotes/authenticator@2.3.1...@standardnotes/authenticator@2.3.2) (2022-11-04)
|
|
19
|
+
|
|
20
|
+
**Note:** Version bump only for package @standardnotes/authenticator
|
|
21
|
+
|
|
22
|
+
## [2.3.1](https://github.com/standardnotes/plugins/compare/@standardnotes/authenticator@2.3.0...@standardnotes/authenticator@2.3.1) (2022-11-04)
|
|
23
|
+
|
|
24
|
+
**Note:** Version bump only for package @standardnotes/authenticator
|
|
25
|
+
|
|
26
|
+
# 2.3.0 (2022-11-04)
|
|
27
|
+
|
|
28
|
+
### Features
|
|
29
|
+
|
|
30
|
+
* add core plugins ([b607787](https://github.com/standardnotes/plugins/commit/b60778762306f5647cb715102eab23083b266718))
|
|
31
|
+
|
|
32
|
+
## [2.2.7](https://github.com/standardnotes/app/compare/@standardnotes/authenticator@2.2.6...@standardnotes/authenticator@2.2.7) (2022-11-01)
|
|
33
|
+
|
|
34
|
+
**Note:** Version bump only for package @standardnotes/authenticator
|
|
35
|
+
|
|
36
|
+
## [2.2.6](https://github.com/standardnotes/app/compare/@standardnotes/authenticator@2.2.5...@standardnotes/authenticator@2.2.6) (2022-10-27)
|
|
37
|
+
|
|
38
|
+
**Note:** Version bump only for package @standardnotes/authenticator
|
|
39
|
+
|
|
40
|
+
## [2.2.5](https://github.com/standardnotes/app/compare/@standardnotes/authenticator@2.2.4...@standardnotes/authenticator@2.2.5) (2022-10-05)
|
|
41
|
+
|
|
42
|
+
**Note:** Version bump only for package @standardnotes/authenticator
|
|
43
|
+
|
|
44
|
+
## [2.2.4](https://github.com/standardnotes/app/compare/@standardnotes/authenticator@2.2.3...@standardnotes/authenticator@2.2.4) (2022-08-22)
|
|
45
|
+
|
|
46
|
+
### Bug Fixes
|
|
47
|
+
|
|
48
|
+
* trigger the `onChange` event of qr code uploading input when clicking on the button ([#1421](https://github.com/standardnotes/app/issues/1421)) ([2a976a0](https://github.com/standardnotes/app/commit/2a976a0de499ba33186a52a6bd2c10a709b86fee))
|
|
49
|
+
|
|
50
|
+
## [2.2.3](https://github.com/standardnotes/app/compare/@standardnotes/authenticator@2.2.2...@standardnotes/authenticator@2.2.3) (2022-07-13)
|
|
51
|
+
|
|
52
|
+
**Note:** Version bump only for package @standardnotes/authenticator
|
|
53
|
+
|
|
54
|
+
## [2.2.2](https://github.com/standardnotes/app/compare/@standardnotes/authenticator@2.2.1...@standardnotes/authenticator@2.2.2) (2022-07-06)
|
|
55
|
+
|
|
56
|
+
**Note:** Version bump only for package @standardnotes/authenticator
|
|
57
|
+
|
|
58
|
+
## [2.2.1](https://github.com/standardnotes/app/compare/@standardnotes/authenticator@2.2.0...@standardnotes/authenticator@2.2.1) (2022-06-30)
|
|
59
|
+
|
|
60
|
+
**Note:** Version bump only for package @standardnotes/authenticator
|
|
61
|
+
|
|
62
|
+
# [2.2.0](https://github.com/standardnotes/app/compare/@standardnotes/authenticator@2.1.2...@standardnotes/authenticator@2.2.0) (2022-06-29)
|
|
63
|
+
|
|
64
|
+
### Features
|
|
65
|
+
|
|
66
|
+
* deprecated editors ([#1166](https://github.com/standardnotes/app/issues/1166)) ([60ca415](https://github.com/standardnotes/app/commit/60ca4150446f9a14bb6a31416686c6d07a7d0cd9))
|
|
67
|
+
|
|
68
|
+
## [2.1.2](https://github.com/standardnotes/app/compare/@standardnotes/authenticator@2.1.2-alpha.0...@standardnotes/authenticator@2.1.2) (2022-06-23)
|
|
69
|
+
|
|
70
|
+
**Note:** Version bump only for package @standardnotes/authenticator
|
|
71
|
+
|
|
72
|
+
## [2.1.2-alpha.0](https://github.com/standardnotes/app/compare/@standardnotes/authenticator@2.1.1...@standardnotes/authenticator@2.1.2-alpha.0) (2022-06-23)
|
|
73
|
+
|
|
74
|
+
### Bug Fixes
|
|
75
|
+
|
|
76
|
+
* **components:** disable minification in themes build due to limitations in mobile css parser ([#1143](https://github.com/standardnotes/app/issues/1143)) ([2d069fd](https://github.com/standardnotes/app/commit/2d069fd4bdca95d857ba20b5f3c946db1ae1735a))
|
|
77
|
+
|
|
78
|
+
## [2.1.1](https://github.com/standardnotes/app/compare/@standardnotes/authenticator@2.1.1-alpha.0...@standardnotes/authenticator@2.1.1) (2022-06-23)
|
|
79
|
+
|
|
80
|
+
**Note:** Version bump only for package @standardnotes/authenticator
|
|
81
|
+
|
|
82
|
+
## [2.1.1-alpha.0](https://github.com/standardnotes/app/compare/@standardnotes/authenticator@2.1.0...@standardnotes/authenticator@2.1.1-alpha.0) (2022-06-23)
|
|
83
|
+
|
|
84
|
+
**Note:** Version bump only for package @standardnotes/authenticator
|
|
85
|
+
|
|
86
|
+
# [2.1.0](https://github.com/standardnotes/app/compare/@standardnotes/authenticator@2.1.0-alpha.0...@standardnotes/authenticator@2.1.0) (2022-06-22)
|
|
87
|
+
|
|
88
|
+
**Note:** Version bump only for package @standardnotes/authenticator
|
|
89
|
+
|
|
90
|
+
# [2.1.0-alpha.0](https://github.com/standardnotes/app/compare/@standardnotes/authenticator@2.0.14...@standardnotes/authenticator@2.1.0-alpha.0) (2022-06-22)
|
|
91
|
+
|
|
92
|
+
### Bug Fixes
|
|
93
|
+
|
|
94
|
+
* components scripts ([#1136](https://github.com/standardnotes/app/issues/1136)) ([e80b4d0](https://github.com/standardnotes/app/commit/e80b4d0ffad495c758b593c30e1c4c754dda9b7e))
|
|
95
|
+
|
|
96
|
+
### Features
|
|
97
|
+
|
|
98
|
+
* optional secret field ([#1115](https://github.com/standardnotes/app/issues/1115)) ([7c0938b](https://github.com/standardnotes/app/commit/7c0938b877f21787dd53fbf46e591487ef02a1c8))
|
|
99
|
+
|
|
100
|
+
## [2.0.14](https://github.com/standardnotes/app/compare/@standardnotes/authenticator@2.0.14-alpha.0...@standardnotes/authenticator@2.0.14) (2022-06-18)
|
|
101
|
+
|
|
102
|
+
**Note:** Version bump only for package @standardnotes/authenticator
|
|
103
|
+
|
|
104
|
+
## [2.0.14-alpha.0](https://github.com/standardnotes/app/compare/@standardnotes/authenticator@2.0.13...@standardnotes/authenticator@2.0.14-alpha.0) (2022-06-18)
|
|
105
|
+
|
|
106
|
+
### Bug Fixes
|
|
107
|
+
|
|
108
|
+
* plus editor icons ([#1120](https://github.com/standardnotes/app/issues/1120)) ([ba65948](https://github.com/standardnotes/app/commit/ba65948364a3fca7bfa5005c56802102c73ccd99))
|
|
109
|
+
|
|
110
|
+
## 2.0.13 (2022-06-16)
|
|
111
|
+
|
|
112
|
+
**Note:** Version bump only for package @standardnotes/authenticator
|
|
113
|
+
|
|
114
|
+
## 2.0.12 (2022-06-16)
|
|
115
|
+
|
|
116
|
+
**Note:** Version bump only for package @standardnotes/authenticator
|
|
117
|
+
|
|
118
|
+
## [2.0.11](https://github.com/standardnotes/app/compare/@standardnotes/authenticator@2.0.11-alpha.3...@standardnotes/authenticator@2.0.11) (2022-06-16)
|
|
119
|
+
|
|
120
|
+
**Note:** Version bump only for package @standardnotes/authenticator
|
|
121
|
+
|
|
122
|
+
## [2.0.11-alpha.3](https://github.com/standardnotes/app/compare/@standardnotes/authenticator@2.0.11-alpha.2...@standardnotes/authenticator@2.0.11-alpha.3) (2022-06-16)
|
|
123
|
+
|
|
124
|
+
**Note:** Version bump only for package @standardnotes/authenticator
|
|
125
|
+
|
|
126
|
+
## 2.0.11-alpha.2 (2022-06-16)
|
|
127
|
+
|
|
128
|
+
**Note:** Version bump only for package @standardnotes/authenticator
|
|
129
|
+
|
|
130
|
+
## 2.0.11-alpha.1 (2022-06-16)
|
|
131
|
+
|
|
132
|
+
**Note:** Version bump only for package @standardnotes/authenticator
|
|
133
|
+
|
|
134
|
+
## 2.0.11-alpha.0 (2022-06-15)
|
|
135
|
+
|
|
136
|
+
**Note:** Version bump only for package @standardnotes/authenticator
|
package/README.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
## LICENSE
|
|
2
|
+
|
|
3
|
+
As of version 2.0, TokenVault houses a public-source, but not open-source presence. This means you are free to browse the code and even use the code _privately_, but you may not redistribute, repackage, or otherwise use its public distributable/release assets on GitHub, for free or for profit.
|
|
4
|
+
|
|
5
|
+
For more information, read [this blog post](https://blog.standardnotes.com/why-tokenvault-is-going-public-source/).
|
|
6
|
+
|
|
7
|
+
Previous versions of TokenVault retain the license they were released with.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<svg width="10px" height="16px" viewBox="0 0 10 16" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<g stroke="none" strokeWidth="1" fill="none" fillRule="evenodd">
|
|
3
|
+
<g transform="translate(-617.000000, -246.000000)">
|
|
4
|
+
<g transform="translate(100.000000, 100.000000)">
|
|
5
|
+
<g transform="translate(510.000000, 142.000000)">
|
|
6
|
+
<g>
|
|
7
|
+
<polygon points="0 0 24 0 24 24 0 24"></polygon>
|
|
8
|
+
<path d="M11,18 C11,19.1 10.1,20 9,20 C7.9,20 7,19.1 7,18 C7,16.9 7.9,16 9,16 C10.1,16 11,16.9 11,18 Z M9,10 C7.9,10 7,10.9 7,12 C7,13.1 7.9,14 9,14 C10.1,14 11,13.1 11,12 C11,10.9 10.1,10 9,10 Z M9,4 C7.9,4 7,4.9 7,6 C7,7.1 7.9,8 9,8 C10.1,8 11,7.1 11,6 C11,4.9 10.1,4 9,4 Z M15,8 C16.1,8 17,7.1 17,6 C17,4.9 16.1,4 15,4 C13.9,4 13,4.9 13,6 C13,7.1 13.9,8 15,8 Z M15,10 C13.9,10 13,10.9 13,12 C13,13.1 13.9,14 15,14 C16.1,14 17,13.1 17,12 C17,10.9 16.1,10 15,10 Z M15,16 C13.9,16 13,16.9 13,18 C13,19.1 13.9,20 15,20 C16.1,20 17,19.1 17,18 C17,16.9 16.1,16 15,16 Z" fill="currentColor"></path>
|
|
9
|
+
</g>
|
|
10
|
+
</g>
|
|
11
|
+
</g>
|
|
12
|
+
</g>
|
|
13
|
+
</g>
|
|
14
|
+
</svg>
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M12.5833 8C12.2518 8 11.9339 7.8683 11.6995 7.63388C11.465 7.39946 11.3333 7.08152 11.3333 6.75C11.3333 6.41848 11.465 6.10054 11.6995 5.86612C11.9339 5.6317 12.2518 5.5 12.5833 5.5C12.9149 5.5 13.2328 5.6317 13.4672 5.86612C13.7016 6.10054 13.8333 6.41848 13.8333 6.75C13.8333 7.08152 13.7016 7.39946 13.4672 7.63388C13.2328 7.8683 12.9149 8 12.5833 8ZM10.0833 4.66667C9.75181 4.66667 9.43387 4.53497 9.19945 4.30055C8.96503 4.06613 8.83333 3.74819 8.83333 3.41667C8.83333 3.08515 8.96503 2.7672 9.19945 2.53278C9.43387 2.29836 9.75181 2.16667 10.0833 2.16667C10.4149 2.16667 10.7328 2.29836 10.9672 2.53278C11.2016 2.7672 11.3333 3.08515 11.3333 3.41667C11.3333 3.74819 11.2016 4.06613 10.9672 4.30055C10.7328 4.53497 10.4149 4.66667 10.0833 4.66667ZM5.91667 4.66667C5.58515 4.66667 5.2672 4.53497 5.03278 4.30055C4.79836 4.06613 4.66667 3.74819 4.66667 3.41667C4.66667 3.08515 4.79836 2.7672 5.03278 2.53278C5.2672 2.29836 5.58515 2.16667 5.91667 2.16667C6.24819 2.16667 6.56613 2.29836 6.80055 2.53278C7.03497 2.7672 7.16667 3.08515 7.16667 3.41667C7.16667 3.74819 7.03497 4.06613 6.80055 4.30055C6.56613 4.53497 6.24819 4.66667 5.91667 4.66667ZM3.41667 8C3.08515 8 2.7672 7.8683 2.53278 7.63388C2.29836 7.39946 2.16667 7.08152 2.16667 6.75C2.16667 6.41848 2.29836 6.10054 2.53278 5.86612C2.7672 5.6317 3.08515 5.5 3.41667 5.5C3.74819 5.5 4.06613 5.6317 4.30055 5.86612C4.53497 6.10054 4.66667 6.41848 4.66667 6.75C4.66667 7.08152 4.53497 7.39946 4.30055 7.63388C4.06613 7.8683 3.74819 8 3.41667 8ZM8 0.5C6.01088 0.5 4.10322 1.29018 2.6967 2.6967C1.29018 4.10322 0.5 6.01088 0.5 8C0.5 9.98912 1.29018 11.8968 2.6967 13.3033C4.10322 14.7098 6.01088 15.5 8 15.5C8.33152 15.5 8.64946 15.3683 8.88388 15.1339C9.1183 14.8995 9.25 14.5815 9.25 14.25C9.25 13.925 9.125 13.6333 8.925 13.4167C8.73333 13.1917 8.60833 12.9 8.60833 12.5833C8.60833 12.2518 8.74003 11.9339 8.97445 11.6995C9.20887 11.465 9.52681 11.3333 9.85833 11.3333H11.3333C12.4384 11.3333 13.4982 10.8943 14.2796 10.1129C15.061 9.33154 15.5 8.27174 15.5 7.16667C15.5 3.48333 12.1417 0.5 8 0.5Z" fill="#FFF"/>
|
|
3
|
+
</svg>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<svg
|
|
2
|
+
version="1.1"
|
|
3
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
4
|
+
width="12px" height="10px"
|
|
5
|
+
viewBox="0 0 300 300"
|
|
6
|
+
xmlSpace="preserve"
|
|
7
|
+
>
|
|
8
|
+
<g fill="currentColor">
|
|
9
|
+
<path
|
|
10
|
+
d="M159.365,23.736v-10c0-5.523-4.477-10-10-10H10c-5.523,0-10,4.477-10,10v10c0,5.523,4.477,10,10,10h139.365
|
|
11
|
+
C154.888,33.736,159.365,29.259,159.365,23.736z"
|
|
12
|
+
/>
|
|
13
|
+
<path
|
|
14
|
+
d="M130.586,66.736H10c-5.523,0-10,4.477-10,10v10c0,5.523,4.477,10,10,10h120.586c5.523,0,10-4.477,10-10v-10
|
|
15
|
+
C140.586,71.213,136.109,66.736,130.586,66.736z"
|
|
16
|
+
/>
|
|
17
|
+
<path
|
|
18
|
+
d="M111.805,129.736H10c-5.523,0-10,4.477-10,10v10c0,5.523,4.477,10,10,10h101.805c5.523,0,10-4.477,10-10v-10
|
|
19
|
+
C121.805,134.213,117.328,129.736,111.805,129.736z"
|
|
20
|
+
/>
|
|
21
|
+
<path
|
|
22
|
+
d="M93.025,199.736H10c-5.523,0-10,4.477-10,10v10c0,5.523,4.477,10,10,10h83.025c5.522,0,10-4.477,10-10v-10
|
|
23
|
+
C103.025,204.213,98.548,199.736,93.025,199.736z"
|
|
24
|
+
/>
|
|
25
|
+
<path
|
|
26
|
+
d="M74.244,262.736H10c-5.523,0-10,4.477-10,10v10c0,5.523,4.477,10,10,10h64.244c5.522,0,10-4.477,10-10v-10
|
|
27
|
+
C84.244,267.213,79.767,262.736,74.244,262.736z"
|
|
28
|
+
/>
|
|
29
|
+
<path
|
|
30
|
+
d="M298.29,216.877l-7.071-7.071c-1.875-1.875-4.419-2.929-7.071-2.929c-2.652,0-5.196,1.054-7.072,2.929l-34.393,34.393
|
|
31
|
+
V18.736c0-5.523-4.477-10-10-10h-10c-5.523,0-10,4.477-10,10v225.462l-34.393-34.393c-1.876-1.875-4.419-2.929-7.071-2.929
|
|
32
|
+
c-2.652,0-5.196,1.054-7.071,2.929l-7.072,7.071c-3.904,3.905-3.904,10.237,0,14.142l63.536,63.536
|
|
33
|
+
c1.953,1.953,4.512,2.929,7.071,2.929c2.559,0,5.119-0.976,7.071-2.929l63.536-63.536
|
|
34
|
+
C302.195,227.113,302.195,220.781,298.29,216.877z"
|
|
35
|
+
/>
|
|
36
|
+
</g>
|
|
37
|
+
</svg>
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import AuthMenu from '@Components/AuthMenu'
|
|
2
|
+
import CountdownPie from '@Components/CountdownPie'
|
|
3
|
+
import { totp } from '@Lib/otp'
|
|
4
|
+
import { getEntryColor, getVarColorForContrast, hexColorToRGB } from '@Lib/utils'
|
|
5
|
+
import PropTypes from 'prop-types'
|
|
6
|
+
import React from 'react'
|
|
7
|
+
import DragIndicator from '../assets/svg/drag-indicator.svg'
|
|
8
|
+
|
|
9
|
+
export default class AuthEntry extends React.Component {
|
|
10
|
+
constructor(props) {
|
|
11
|
+
super(props)
|
|
12
|
+
|
|
13
|
+
this.state = {
|
|
14
|
+
token: '',
|
|
15
|
+
timeLeft: 0,
|
|
16
|
+
entryStyle: {
|
|
17
|
+
color: '',
|
|
18
|
+
backgroundColor: '',
|
|
19
|
+
},
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
this.updateToken()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
getTimeLeft() {
|
|
26
|
+
const seconds = new Date().getSeconds()
|
|
27
|
+
return seconds > 29 ? 60 - seconds : 30 - seconds
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
updateToken = async () => {
|
|
31
|
+
const { secret } = this.props.entry
|
|
32
|
+
if (!secret) {
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const token = await totp.gen(secret)
|
|
37
|
+
const timeLeft = this.getTimeLeft()
|
|
38
|
+
this.setState({
|
|
39
|
+
token,
|
|
40
|
+
timeLeft,
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
this.timer = setTimeout(this.updateToken, timeLeft * 1000)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
componentDidMount() {
|
|
47
|
+
this.updateEntryStyle()
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
componentDidUpdate(prevProps) {
|
|
51
|
+
// If the secret changed make sure to recalculate token
|
|
52
|
+
if (prevProps.entry.secret !== this.props.entry.secret) {
|
|
53
|
+
clearTimeout(this.timer)
|
|
54
|
+
this.timer = setTimeout(this.updateToken, 0)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (prevProps.lastUpdated !== this.props.lastUpdated) {
|
|
58
|
+
this.updateEntryStyle(true)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
componentWillUnmount() {
|
|
63
|
+
clearTimeout(this.timer)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
handleInputChange = (event) => {
|
|
67
|
+
const target = event.target
|
|
68
|
+
const name = target.name
|
|
69
|
+
|
|
70
|
+
this.props.onEntryChange({
|
|
71
|
+
id: this.props.id,
|
|
72
|
+
name,
|
|
73
|
+
value: target.value,
|
|
74
|
+
})
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
copyToClipboard = (value) => {
|
|
78
|
+
const textField = document.createElement('textarea')
|
|
79
|
+
textField.innerText = value
|
|
80
|
+
document.body.appendChild(textField)
|
|
81
|
+
textField.select()
|
|
82
|
+
document.execCommand('copy')
|
|
83
|
+
textField.remove()
|
|
84
|
+
this.props.onCopyValue()
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
updateEntryStyle = (useDelay = false) => {
|
|
88
|
+
/**
|
|
89
|
+
* A short amount of time to wait in order to prevent reading
|
|
90
|
+
* stale information from the DOM after a theme is activated.
|
|
91
|
+
*/
|
|
92
|
+
const DELAY_BEFORE_READING_PROPERTIES = useDelay ? 0 : 50
|
|
93
|
+
|
|
94
|
+
setTimeout(() => {
|
|
95
|
+
const { entryStyle } = this.state
|
|
96
|
+
const entryColor = getEntryColor(document, this.props.entry)
|
|
97
|
+
|
|
98
|
+
if (entryColor) {
|
|
99
|
+
// The background color for the entry.
|
|
100
|
+
entryStyle.backgroundColor = entryColor
|
|
101
|
+
|
|
102
|
+
const rgbColor = hexColorToRGB(entryColor)
|
|
103
|
+
const varColor = getVarColorForContrast(rgbColor)
|
|
104
|
+
|
|
105
|
+
// The foreground color for the entry.
|
|
106
|
+
entryStyle.color = `var(${varColor})`
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
this.setState({
|
|
110
|
+
entryStyle,
|
|
111
|
+
})
|
|
112
|
+
}, DELAY_BEFORE_READING_PROPERTIES)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
render() {
|
|
116
|
+
const { service, account, notes, password, secret } = this.props.entry
|
|
117
|
+
const { id, onEdit, onRemove, canEdit, style, innerRef, ...divProps } = this.props
|
|
118
|
+
const { token, timeLeft, entryStyle } = this.state
|
|
119
|
+
|
|
120
|
+
delete divProps.onCopyValue
|
|
121
|
+
delete divProps.lastUpdated
|
|
122
|
+
|
|
123
|
+
return (
|
|
124
|
+
<div
|
|
125
|
+
{...divProps}
|
|
126
|
+
className="sk-notification sk-base-custom"
|
|
127
|
+
style={{
|
|
128
|
+
...entryStyle,
|
|
129
|
+
...style,
|
|
130
|
+
}}
|
|
131
|
+
ref={innerRef}
|
|
132
|
+
>
|
|
133
|
+
<div className="auth-entry">
|
|
134
|
+
{canEdit && (
|
|
135
|
+
<div className="auth-drag-indicator-container">
|
|
136
|
+
<DragIndicator className="grab-cursor" />
|
|
137
|
+
</div>
|
|
138
|
+
)}
|
|
139
|
+
<div className="auth-details">
|
|
140
|
+
<div className="auth-info">
|
|
141
|
+
<div className="auth-service">{service}</div>
|
|
142
|
+
<div className="auth-account">{account}</div>
|
|
143
|
+
<div className="auth-optional">
|
|
144
|
+
{notes && (
|
|
145
|
+
<div className="auth-notes-row">
|
|
146
|
+
<div className="auth-notes">{notes}</div>
|
|
147
|
+
</div>
|
|
148
|
+
)}
|
|
149
|
+
{password && (
|
|
150
|
+
<div className="auth-password-row">
|
|
151
|
+
<div className="auth-password" onClick={() => this.copyToClipboard(password)}>
|
|
152
|
+
{'•'.repeat(password.length)}
|
|
153
|
+
</div>
|
|
154
|
+
</div>
|
|
155
|
+
)}
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
{secret && (
|
|
159
|
+
<div className="auth-token-info">
|
|
160
|
+
<div className="auth-token" onClick={() => this.copyToClipboard(token)}>
|
|
161
|
+
<div>{token.slice(0, 3)}</div>
|
|
162
|
+
<div>{token.slice(3, 6)}</div>
|
|
163
|
+
</div>
|
|
164
|
+
<div className="auth-countdown">
|
|
165
|
+
<CountdownPie
|
|
166
|
+
token={token}
|
|
167
|
+
timeLeft={timeLeft}
|
|
168
|
+
total={30}
|
|
169
|
+
bgColor={entryStyle.backgroundColor}
|
|
170
|
+
fgColor={entryStyle.color}
|
|
171
|
+
/>
|
|
172
|
+
</div>
|
|
173
|
+
</div>
|
|
174
|
+
)}
|
|
175
|
+
</div>
|
|
176
|
+
{canEdit && (
|
|
177
|
+
<div className="auth-options">
|
|
178
|
+
<AuthMenu
|
|
179
|
+
onEdit={onEdit.bind(this, id)}
|
|
180
|
+
onRemove={onRemove.bind(this, id)}
|
|
181
|
+
buttonColor={entryStyle.color}
|
|
182
|
+
/>
|
|
183
|
+
</div>
|
|
184
|
+
)}
|
|
185
|
+
</div>
|
|
186
|
+
</div>
|
|
187
|
+
)
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
AuthEntry.propTypes = {
|
|
192
|
+
id: PropTypes.any.isRequired,
|
|
193
|
+
entry: PropTypes.object.isRequired,
|
|
194
|
+
onEdit: PropTypes.func.isRequired,
|
|
195
|
+
onRemove: PropTypes.func.isRequired,
|
|
196
|
+
onEntryChange: PropTypes.func,
|
|
197
|
+
onCopyValue: PropTypes.func.isRequired,
|
|
198
|
+
canEdit: PropTypes.bool.isRequired,
|
|
199
|
+
innerRef: PropTypes.func.isRequired,
|
|
200
|
+
lastUpdated: PropTypes.number.isRequired,
|
|
201
|
+
style: PropTypes.object.isRequired,
|
|
202
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import PropTypes from 'prop-types'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
|
|
4
|
+
export default class AuthMenu extends React.Component {
|
|
5
|
+
constructor(props) {
|
|
6
|
+
super(props)
|
|
7
|
+
|
|
8
|
+
this.state = {
|
|
9
|
+
show: false,
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
onToggle = () => {
|
|
14
|
+
this.setState({
|
|
15
|
+
show: !this.state.show,
|
|
16
|
+
})
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
onEdit = () => {
|
|
20
|
+
this.onToggle()
|
|
21
|
+
this.props.onEdit()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
onRemove = () => {
|
|
25
|
+
this.onToggle()
|
|
26
|
+
this.props.onRemove()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
render() {
|
|
30
|
+
const { buttonColor } = this.props
|
|
31
|
+
|
|
32
|
+
const buttonStyle = {}
|
|
33
|
+
if (buttonColor) {
|
|
34
|
+
buttonStyle.color = buttonColor
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<div className="auth-menu">
|
|
39
|
+
<div className="sk-button" onClick={this.onToggle} style={buttonStyle}>
|
|
40
|
+
<div className="sk-label">•••</div>
|
|
41
|
+
</div>
|
|
42
|
+
{this.state.show &&
|
|
43
|
+
((<div className="auth-overlay" onClick={this.onToggle} />),
|
|
44
|
+
(
|
|
45
|
+
<div className="sk-menu-panel">
|
|
46
|
+
<div className="sk-menu-panel-row" onClick={this.onEdit}>
|
|
47
|
+
<div className="sk-label">Edit</div>
|
|
48
|
+
</div>
|
|
49
|
+
<div className="sk-menu-panel-row" onClick={this.onRemove}>
|
|
50
|
+
<div className="sk-label">Remove</div>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
))}
|
|
54
|
+
</div>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
AuthMenu.propTypes = {
|
|
60
|
+
onEdit: PropTypes.func.isRequired,
|
|
61
|
+
onRemove: PropTypes.func.isRequired,
|
|
62
|
+
buttonColor: PropTypes.string,
|
|
63
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import PropTypes from 'prop-types'
|
|
2
|
+
|
|
3
|
+
const ConfirmDialog = ({ title, message, onConfirm, onCancel }) => (
|
|
4
|
+
<div className="auth-overlay">
|
|
5
|
+
<div className="auth-dialog sk-panel">
|
|
6
|
+
<div className="sk-panel-header">
|
|
7
|
+
<div className="sk-panel-header-title">{title}</div>
|
|
8
|
+
</div>
|
|
9
|
+
<div className="sk-panel-content">
|
|
10
|
+
<div className="sk-panel-section sk-panel-hero">
|
|
11
|
+
<div className="sk-panel-row">
|
|
12
|
+
<div className="sk-h1">{message}</div>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
<div className="sk-panel-footer">
|
|
17
|
+
<div className="sk-button-group stretch">
|
|
18
|
+
<div className="sk-button neutral" onClick={onCancel}>
|
|
19
|
+
<div className="sk-label">Cancel</div>
|
|
20
|
+
</div>
|
|
21
|
+
<div className="sk-button info" onClick={onConfirm}>
|
|
22
|
+
<div className="sk-label">Confirm</div>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
ConfirmDialog.propTypes = {
|
|
31
|
+
title: PropTypes.string.isRequired,
|
|
32
|
+
message: PropTypes.string.isRequired,
|
|
33
|
+
onConfirm: PropTypes.func.isRequired,
|
|
34
|
+
onCancel: PropTypes.func.isRequired,
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default ConfirmDialog
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import PropTypes from 'prop-types'
|
|
2
|
+
|
|
3
|
+
const CopyNotification = ({ isVisible }) => (
|
|
4
|
+
<div className={`auth-copy-notification ${isVisible ? 'visible' : 'hidden'}`}>
|
|
5
|
+
<div className="sk-panel">
|
|
6
|
+
<div className="sk-font-small sk-bold">Copied value to clipboard.</div>
|
|
7
|
+
</div>
|
|
8
|
+
</div>
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
CopyNotification.propTypes = {
|
|
12
|
+
isVisible: PropTypes.bool.isRequired,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default CopyNotification
|