mirror of
https://github.com/0rangebananaspy/authelia.git
synced 2024-09-14 22:47:21 +07:00
Replace material-UI by material-components-web.
This commit is contained in:
parent
7c6023fee4
commit
317611b099
2
client/.env.development
Normal file
2
client/.env.development
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
|
||||||
|
REACT_APP_CSP_CONTENT="default-src 'unsafe-inline'; script-src * 'unsafe-inline'; img-src * data:; style-src 'unsafe-inline'; connect-src * 'unsafe-inline' extensions:"
|
2
client/.env.production
Normal file
2
client/.env.production
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
|
||||||
|
REACT_APP_CSP_CONTENT="default-src 'self'; style-src 'self'; script-src 'self';"
|
|
@ -8,6 +8,7 @@ services:
|
||||||
- ./client/tsconfig.json:/usr/app/client/tsconfig.json
|
- ./client/tsconfig.json:/usr/app/client/tsconfig.json
|
||||||
- ./client/public:/usr/app/client/public
|
- ./client/public:/usr/app/client/public
|
||||||
- ./client/src:/usr/app/client/src
|
- ./client/src:/usr/app/client/src
|
||||||
|
- ./client/.env.development:/usr/app/client/.env.development
|
||||||
networks:
|
networks:
|
||||||
example-network:
|
example-network:
|
||||||
aliases:
|
aliases:
|
||||||
|
|
216
client/package-lock.json
generated
216
client/package-lock.json
generated
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "client-react",
|
"name": "authelia-portal",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
|
@ -890,6 +890,215 @@
|
||||||
"react-is": "^16.6.3"
|
"react-is": "^16.6.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@material/animation": {
|
||||||
|
"version": "0.41.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/animation/-/animation-0.41.0.tgz",
|
||||||
|
"integrity": "sha512-yYAwJbX3Q2AFd4dr6IYOsWLQy2HN8zWOFVl9AbUXunjzTfJCa/ecfXCriaT6qkmoNoHeTdJHRrsQJZC5GsPvzA=="
|
||||||
|
},
|
||||||
|
"@material/base": {
|
||||||
|
"version": "0.41.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/base/-/base-0.41.0.tgz",
|
||||||
|
"integrity": "sha512-tEyzwBRu3d1H120SfKsDVYZHcqT5lKohh/7cWKR93aAaPDkSvjpKJIjyu2yuSkjpDduVZGzVocYbOvhUKhhzXQ=="
|
||||||
|
},
|
||||||
|
"@material/button": {
|
||||||
|
"version": "0.41.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/button/-/button-0.41.0.tgz",
|
||||||
|
"integrity": "sha512-9mA/7P8yD3YPJ8ijwu0oOiT65OCa8Km3M9OF6VAsBE+XJS9Wo5hWDMgkv16raeOFeXj+1ALsjvuTz31JdcSkgQ==",
|
||||||
|
"requires": {
|
||||||
|
"@material/elevation": "^0.41.0",
|
||||||
|
"@material/ripple": "^0.41.0",
|
||||||
|
"@material/rtl": "^0.40.1",
|
||||||
|
"@material/shape": "^0.41.0",
|
||||||
|
"@material/theme": "^0.41.0",
|
||||||
|
"@material/typography": "^0.41.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@material/checkbox": {
|
||||||
|
"version": "0.41.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/checkbox/-/checkbox-0.41.0.tgz",
|
||||||
|
"integrity": "sha512-Zz6e5WRpziO7Z+4rbEs8GHNNBf1UuttniLp6/RvwPSQRaD8G04sdg4HcP/aDCY1KGMwivkuDPc2Bsgs6j+rD7Q==",
|
||||||
|
"requires": {
|
||||||
|
"@material/animation": "^0.41.0",
|
||||||
|
"@material/base": "^0.41.0",
|
||||||
|
"@material/ripple": "^0.41.0",
|
||||||
|
"@material/rtl": "^0.40.1",
|
||||||
|
"@material/selection-control": "^0.41.0",
|
||||||
|
"@material/theme": "^0.41.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@material/elevation": {
|
||||||
|
"version": "0.41.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/elevation/-/elevation-0.41.0.tgz",
|
||||||
|
"integrity": "sha512-ZtZS8z5ie9c7Cx5PVudgSorGYa0C3lu3dA+Nn6qJdhGUokl01msh54NfNuwk+EZsk65bNRRqw1Td/63TCbKIzg==",
|
||||||
|
"requires": {
|
||||||
|
"@material/animation": "^0.41.0",
|
||||||
|
"@material/theme": "^0.41.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@material/floating-label": {
|
||||||
|
"version": "0.41.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/floating-label/-/floating-label-0.41.0.tgz",
|
||||||
|
"integrity": "sha512-qI6f1nZU3crXxWAI9fw3U5fHw2qOzEor49EvskbcaV5KSRW5qO+jtfUQ3ib/Vhki7lqhgwNHB/0n7KYhvhjRHQ==",
|
||||||
|
"requires": {
|
||||||
|
"@material/animation": "^0.41.0",
|
||||||
|
"@material/base": "^0.41.0",
|
||||||
|
"@material/rtl": "^0.40.1",
|
||||||
|
"@material/theme": "^0.41.0",
|
||||||
|
"@material/typography": "^0.41.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@material/line-ripple": {
|
||||||
|
"version": "0.41.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/line-ripple/-/line-ripple-0.41.0.tgz",
|
||||||
|
"integrity": "sha512-5DDIoC3d78fCLhNgle7DRFojT3D2SF+XVpUd3g6yLZmybHB7832p4bgl/qGpbIXwk1wAQA1dkUgKH5foxorjNQ==",
|
||||||
|
"requires": {
|
||||||
|
"@material/animation": "^0.41.0",
|
||||||
|
"@material/base": "^0.41.0",
|
||||||
|
"@material/theme": "^0.41.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@material/notched-outline": {
|
||||||
|
"version": "0.41.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/notched-outline/-/notched-outline-0.41.0.tgz",
|
||||||
|
"integrity": "sha512-nQBkOXvkd5G9FeJ9UuecZh88WRgTsnGVvfj7UFJZEkvkzZwLBGUiJS6fF9FYraih3ZFgmphdbJxXEd9af3cqyQ==",
|
||||||
|
"requires": {
|
||||||
|
"@material/animation": "^0.41.0",
|
||||||
|
"@material/base": "^0.41.0",
|
||||||
|
"@material/rtl": "^0.40.1",
|
||||||
|
"@material/shape": "^0.41.0",
|
||||||
|
"@material/theme": "^0.41.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@material/react-button": {
|
||||||
|
"version": "0.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/react-button/-/react-button-0.8.0.tgz",
|
||||||
|
"integrity": "sha512-j/wk/HK2A3/mb+yFdYCbkWFi6hYvvq4fc4t1M3aRLgdeddMNn/+FHOu014dyKeFW93RrBn1WAdQTwCc31KivuQ==",
|
||||||
|
"requires": {
|
||||||
|
"@material/button": "^0.41.0",
|
||||||
|
"@material/react-ripple": "^0.8.0",
|
||||||
|
"classnames": "^2.2.5",
|
||||||
|
"react": "^16.4.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@material/react-checkbox": {
|
||||||
|
"version": "0.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/react-checkbox/-/react-checkbox-0.8.0.tgz",
|
||||||
|
"integrity": "sha512-/7wQcFovUa04/T0MnJOnrbGn21CgxSSWjqkbMPFh/RjET8vya/kqAjhkLw51Mk4q6si+nfHljM6YSFvvXbUBBw==",
|
||||||
|
"requires": {
|
||||||
|
"@material/checkbox": "^0.41.0",
|
||||||
|
"@material/react-ripple": "^0.8.0",
|
||||||
|
"classnames": "^2.2.5",
|
||||||
|
"react": "^16.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@material/react-floating-label": {
|
||||||
|
"version": "0.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/react-floating-label/-/react-floating-label-0.8.0.tgz",
|
||||||
|
"integrity": "sha512-Bfa+/4nLFu6YE0pAB1wG+vxwYiFvHcOKIq7uAB/IY0/N/ONKM2Jh74/KKqLvNJI608YpZqLAqmZu87R3K15rNQ==",
|
||||||
|
"requires": {
|
||||||
|
"@material/floating-label": "^0.41.0",
|
||||||
|
"classnames": "^2.2.5",
|
||||||
|
"react": "^16.4.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@material/react-line-ripple": {
|
||||||
|
"version": "0.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/react-line-ripple/-/react-line-ripple-0.8.0.tgz",
|
||||||
|
"integrity": "sha512-s921awUm8taB/kbETGN/vEEZV1WUwtTcsNkQ//HsK2fJW7lKuyVWrObc8ZhMFWljVEUj54ANmRvCke7M4/LSmA==",
|
||||||
|
"requires": {
|
||||||
|
"@material/line-ripple": "^0.41.0",
|
||||||
|
"classnames": "^2.2.5",
|
||||||
|
"react": "^16.4.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@material/react-notched-outline": {
|
||||||
|
"version": "0.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/react-notched-outline/-/react-notched-outline-0.8.0.tgz",
|
||||||
|
"integrity": "sha512-fQ8hHGOQ3dpk9AuuQqXbCAN2UTuRr5LCztkDxdCwvaPC+oR5meTd8RW7RkJgx/MeiSLe/1/2EMz+9lP+V0rx2w==",
|
||||||
|
"requires": {
|
||||||
|
"@material/notched-outline": "^0.41.0",
|
||||||
|
"classnames": "^2.2.5",
|
||||||
|
"react": "^16.4.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@material/react-ripple": {
|
||||||
|
"version": "0.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/react-ripple/-/react-ripple-0.8.0.tgz",
|
||||||
|
"integrity": "sha512-ThH9Px42poicRXgFBTfLjbAsVIUi6wmX4RszDPwiSTVMQYc785n240VAD8MfVCR27ykIxCrys/YibqxvREvjUQ==",
|
||||||
|
"requires": {
|
||||||
|
"@material/ripple": "^0.41.0",
|
||||||
|
"classnames": "^2.2.5",
|
||||||
|
"react": "^16.4.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@material/react-text-field": {
|
||||||
|
"version": "0.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/react-text-field/-/react-text-field-0.8.0.tgz",
|
||||||
|
"integrity": "sha512-eISr4YIBmsIarQQU/LhAPfB9M8srY8Tzagqw6E2z5JyHux8eHlsMWSuYD6eh4FiQekdZoIgoJjlFIGhOvNV59Q==",
|
||||||
|
"requires": {
|
||||||
|
"@material/react-floating-label": "^0.8.0",
|
||||||
|
"@material/react-line-ripple": "^0.8.0",
|
||||||
|
"@material/react-notched-outline": "^0.8.0",
|
||||||
|
"@material/textfield": "^0.41.0",
|
||||||
|
"classnames": "^2.2.5",
|
||||||
|
"react": "^16.4.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@material/ripple": {
|
||||||
|
"version": "0.41.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-0.41.0.tgz",
|
||||||
|
"integrity": "sha512-rxEUVWM4AByDlTCH0kkthZQmUuY6eeN0X6cOHBoioFN2vUDk0D0Nfzz/N9FF2AlAf8C2lDDLrTuqnJPVIn+NHA==",
|
||||||
|
"requires": {
|
||||||
|
"@material/animation": "^0.41.0",
|
||||||
|
"@material/base": "^0.41.0",
|
||||||
|
"@material/theme": "^0.41.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@material/rtl": {
|
||||||
|
"version": "0.40.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/rtl/-/rtl-0.40.1.tgz",
|
||||||
|
"integrity": "sha512-Pk6Iw1/KrhWZoZtkDsPMDUW0bm7Z1zeXb3MTQRCFmjf1wU5cRxgOTtuoZLcJqlcKGppLAzJL/TJV3E7KEiuL0A=="
|
||||||
|
},
|
||||||
|
"@material/selection-control": {
|
||||||
|
"version": "0.41.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/selection-control/-/selection-control-0.41.0.tgz",
|
||||||
|
"integrity": "sha512-rRHGiZVPoP4nxAAoeqsgTsxz9GwInGs7HIlEhPfMFygmSZVUHHsuOJXSTpOKYi8GCoKHpB0RKZsAtxM0BYAelw==",
|
||||||
|
"requires": {
|
||||||
|
"@material/ripple": "^0.41.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@material/shape": {
|
||||||
|
"version": "0.41.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/shape/-/shape-0.41.0.tgz",
|
||||||
|
"integrity": "sha512-k1K3CjOVxclfb/0r28cOa2oJpP7QMA2fP0SOS3Vh8ale5Q2jkaHTL60KX8VkHvV6rMqShpXW+60gPjoz5XRbDQ=="
|
||||||
|
},
|
||||||
|
"@material/textfield": {
|
||||||
|
"version": "0.41.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/textfield/-/textfield-0.41.0.tgz",
|
||||||
|
"integrity": "sha512-kJ52W2gxOS2xfpreVhvHQ1u3UkiDl58duw9HkhEkK5Oi1bSDOtbnlWy0pGTOiAma5ZQgetPNgoa+T0zMBptfnw==",
|
||||||
|
"requires": {
|
||||||
|
"@material/animation": "^0.41.0",
|
||||||
|
"@material/base": "^0.41.0",
|
||||||
|
"@material/floating-label": "^0.41.0",
|
||||||
|
"@material/line-ripple": "^0.41.0",
|
||||||
|
"@material/notched-outline": "^0.41.0",
|
||||||
|
"@material/ripple": "^0.41.0",
|
||||||
|
"@material/rtl": "^0.40.1",
|
||||||
|
"@material/shape": "^0.41.0",
|
||||||
|
"@material/theme": "^0.41.0",
|
||||||
|
"@material/typography": "^0.41.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@material/theme": {
|
||||||
|
"version": "0.41.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/theme/-/theme-0.41.0.tgz",
|
||||||
|
"integrity": "sha512-ohW2JxObKOWvP34EkIIcrEVtL3g0Gs/T3/MdOsM36euyshY8Jwl1f6fjVUQvVjSpixUtSb30/+ulblF8fTOwBg=="
|
||||||
|
},
|
||||||
|
"@material/typography": {
|
||||||
|
"version": "0.41.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/typography/-/typography-0.41.0.tgz",
|
||||||
|
"integrity": "sha512-15dlqSU+9uGcWdg4KXXcmDzTKJPb7/5Z9kmooONb2Laot1uiuntDXQS0yL+U2FYLW5Ros+WVMosDBKFruWx68A=="
|
||||||
|
},
|
||||||
"@mrmlnc/readdir-enhanced": {
|
"@mrmlnc/readdir-enhanced": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
|
||||||
|
@ -16990,6 +17199,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz",
|
||||||
"integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw="
|
"integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw="
|
||||||
},
|
},
|
||||||
|
"utility-types": {
|
||||||
|
"version": "3.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.4.1.tgz",
|
||||||
|
"integrity": "sha512-GyH068kJf7c4vhfqj4aCM5X+TeV8jG2iPFLimpGpnQ7dvKfogZOHfiYxMww/nGEfMm/bEmnVbeZGO1see1OVKg=="
|
||||||
|
},
|
||||||
"utils-merge": {
|
"utils-merge": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
{
|
{
|
||||||
"name": "client-react",
|
"name": "authelia-portal",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@material-ui/core": "3.7.1",
|
"@material/react-button": "^0.8.0",
|
||||||
"@material-ui/icons": "^3.0.1",
|
"@material/react-checkbox": "^0.8.0",
|
||||||
|
"@material/react-text-field": "^0.8.0",
|
||||||
"@types/classnames": "^2.2.7",
|
"@types/classnames": "^2.2.7",
|
||||||
"@types/jss": "^9.5.7",
|
"@types/jss": "^9.5.7",
|
||||||
"@types/node": "^10.12.2",
|
"@types/node": "^10.12.2",
|
||||||
|
@ -31,11 +32,12 @@
|
||||||
"redux-thunk": "^2.3.0",
|
"redux-thunk": "^2.3.0",
|
||||||
"typesafe-actions": "^3.0.0",
|
"typesafe-actions": "^3.0.0",
|
||||||
"typescript": "^3.1.6",
|
"typescript": "^3.1.6",
|
||||||
"u2f-api": "^1.0.10"
|
"u2f-api": "^1.0.10",
|
||||||
|
"utility-types": "^3.4.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-scripts start",
|
"start": "SASS_PATH=./node_modules react-scripts start",
|
||||||
"build": "react-scripts build",
|
"build": "SASS_PATH=./node_modules react-scripts build",
|
||||||
"test": "react-scripts test",
|
"test": "react-scripts test",
|
||||||
"eject": "react-scripts eject"
|
"eject": "react-scripts eject"
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
<meta name="robots" content="noindex, nofollow, nosnippet, noarchive">
|
<meta name="robots" content="noindex, nofollow, nosnippet, noarchive">
|
||||||
<meta name="theme-color" content="#000000">
|
|
||||||
|
<meta http-equiv="Content-Security-Policy" content="%REACT_APP_CSP_CONTENT%">
|
||||||
<!--
|
<!--
|
||||||
manifest.json provides metadata used when your web app is added to the
|
manifest.json provides metadata used when your web app is added to the
|
||||||
homescreen on Android. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
homescreen on Android. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||||
|
|
|
@ -9,7 +9,5 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"start_url": ".",
|
"start_url": ".",
|
||||||
"display": "standalone",
|
"display": "standalone"
|
||||||
"theme_color": "#000000",
|
|
||||||
"background_color": "#ffffff"
|
|
||||||
}
|
}
|
||||||
|
|
0
client/src/App.css → client/src/.env.development
Normal file → Executable file
0
client/src/App.css → client/src/.env.development
Normal file → Executable file
3
client/src/App.scss
Normal file
3
client/src/App.scss
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
@import "@material/react-button/index.scss";
|
||||||
|
@import "@material/react-checkbox/index.scss";
|
||||||
|
@import "@material/react-text-field/index.scss";
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import './App.css';
|
import './App.scss';
|
||||||
|
|
||||||
import { Router, Route, Switch } from "react-router-dom";
|
import { Route, Switch } from "react-router-dom";
|
||||||
import { routes } from './routes/index';
|
import { routes } from './routes/index';
|
||||||
import { createBrowserHistory } from 'history';
|
import { createBrowserHistory } from 'history';
|
||||||
import { createStore, applyMiddleware, compose } from 'redux';
|
import { createStore, applyMiddleware, compose } from 'redux';
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
import { createStyles, Theme } from "@material-ui/core";
|
|
||||||
|
|
||||||
const styles = createStyles((theme: Theme) => ({
|
|
||||||
container: {
|
|
||||||
textAlign: 'center',
|
|
||||||
},
|
|
||||||
messageContainer: {
|
|
||||||
fontSize: theme.typography.fontSize,
|
|
||||||
marginTop: theme.spacing.unit * 2,
|
|
||||||
marginBottom: theme.spacing.unit * 2,
|
|
||||||
color: 'green',
|
|
||||||
display: 'inline-block',
|
|
||||||
marginLeft: theme.spacing.unit * 2,
|
|
||||||
textAlign: 'left',
|
|
||||||
|
|
||||||
},
|
|
||||||
successContainer: {
|
|
||||||
verticalAlign: 'middle',
|
|
||||||
paddingTop: theme.spacing.unit * 2,
|
|
||||||
paddingBottom: theme.spacing.unit * 2,
|
|
||||||
marginTop: theme.spacing.unit * 2,
|
|
||||||
marginBottom: theme.spacing.unit * 3,
|
|
||||||
border: '1px solid #8ae48a',
|
|
||||||
borderRadius: '100px',
|
|
||||||
},
|
|
||||||
successLogoContainer: {
|
|
||||||
display: 'inline-block',
|
|
||||||
},
|
|
||||||
logoutButtonContainer: {
|
|
||||||
marginTop: theme.spacing.unit * 2,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
export default styles;
|
|
|
@ -1,36 +0,0 @@
|
||||||
import { createStyles, Theme } from "@material-ui/core";
|
|
||||||
|
|
||||||
const styles = createStyles((theme: Theme) => ({
|
|
||||||
fields: {
|
|
||||||
marginTop: theme.spacing.unit * 2,
|
|
||||||
},
|
|
||||||
field: {
|
|
||||||
paddingBottom: theme.spacing.unit * 2,
|
|
||||||
},
|
|
||||||
input: {
|
|
||||||
width: '100%',
|
|
||||||
},
|
|
||||||
buttons: {
|
|
||||||
'& button': {
|
|
||||||
width: '100%',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
controls: {
|
|
||||||
display: 'inline-block',
|
|
||||||
width: '100%',
|
|
||||||
fontSize: '0.875rem',
|
|
||||||
},
|
|
||||||
rememberMe: {
|
|
||||||
float: 'left',
|
|
||||||
fontSize: theme.typography.fontSize * 0.8,
|
|
||||||
},
|
|
||||||
resetPassword: {
|
|
||||||
padding: '12px 0px',
|
|
||||||
float: 'right',
|
|
||||||
'& a': {
|
|
||||||
color: 'black',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
export default styles;
|
|
|
@ -1,20 +0,0 @@
|
||||||
import { createStyles, Theme } from "@material-ui/core";
|
|
||||||
|
|
||||||
const styles = createStyles((theme: Theme) => ({
|
|
||||||
messageOuter: {
|
|
||||||
position: 'relative',
|
|
||||||
},
|
|
||||||
messageInner: {
|
|
||||||
width: '100%',
|
|
||||||
},
|
|
||||||
messageContainer: {
|
|
||||||
color: 'white',
|
|
||||||
fontSize: theme.typography.fontSize,
|
|
||||||
padding: theme.spacing.unit * 2,
|
|
||||||
border: '1px solid red',
|
|
||||||
borderRadius: '5px',
|
|
||||||
backgroundColor: '#ff8d8d',
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
export default styles;
|
|
|
@ -1,69 +0,0 @@
|
||||||
|
|
||||||
import { createStyles, Theme } from "@material-ui/core";
|
|
||||||
import { isAbsolute } from "path";
|
|
||||||
|
|
||||||
const styles = createStyles((theme: Theme) => ({
|
|
||||||
container: {
|
|
||||||
position: 'relative',
|
|
||||||
},
|
|
||||||
hello: {},
|
|
||||||
logout: {},
|
|
||||||
header: {
|
|
||||||
fontSize: theme.typography.fontSize * 1.5,
|
|
||||||
marginBottom: theme.spacing.unit,
|
|
||||||
position: 'relative',
|
|
||||||
'& $hello': {
|
|
||||||
display: 'inline-block',
|
|
||||||
},
|
|
||||||
'& $logout': {
|
|
||||||
position: 'absolute',
|
|
||||||
bottom: '0px',
|
|
||||||
right: '0px',
|
|
||||||
fontSize: theme.typography.fontSize * 0.9,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
body: {
|
|
||||||
paddingTop: theme.spacing.unit * 2,
|
|
||||||
paddingBottom: theme.spacing.unit * 2,
|
|
||||||
paddingLeft: theme.spacing.unit * 2,
|
|
||||||
paddingRight: theme.spacing.unit * 2,
|
|
||||||
border: '1px solid #e0e0e0',
|
|
||||||
borderRadius: '2px',
|
|
||||||
},
|
|
||||||
methodName: {
|
|
||||||
fontSize: theme.typography.fontSize * 1.2,
|
|
||||||
fontWeight: 'bold',
|
|
||||||
marginBottom: theme.spacing.unit,
|
|
||||||
},
|
|
||||||
methodU2f: {
|
|
||||||
borderBottom: '1px solid #e0e0e0',
|
|
||||||
padding: theme.spacing.unit,
|
|
||||||
},
|
|
||||||
methodTotp: {
|
|
||||||
padding: theme.spacing.unit,
|
|
||||||
paddingTop: theme.spacing.unit * 2,
|
|
||||||
},
|
|
||||||
image: {
|
|
||||||
width: '120px',
|
|
||||||
},
|
|
||||||
imageContainer: {
|
|
||||||
textAlign: 'center',
|
|
||||||
marginTop: theme.spacing.unit * 2,
|
|
||||||
marginBottom: theme.spacing.unit * 2,
|
|
||||||
},
|
|
||||||
registerDeviceContainer: {
|
|
||||||
textAlign: 'right',
|
|
||||||
fontSize: theme.typography.fontSize * 0.8,
|
|
||||||
},
|
|
||||||
registerDevice: {},
|
|
||||||
totpField: {
|
|
||||||
marginTop: theme.spacing.unit * 2,
|
|
||||||
width: '100%',
|
|
||||||
},
|
|
||||||
totpButton: {
|
|
||||||
marginTop: theme.spacing.unit * 2,
|
|
||||||
width: '100%',
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
export default styles;
|
|
|
@ -1,41 +0,0 @@
|
||||||
import { createStyles, Theme } from "@material-ui/core";
|
|
||||||
|
|
||||||
const styles = createStyles((theme: Theme) => ({
|
|
||||||
mainContent: {
|
|
||||||
width: '440px',
|
|
||||||
margin: '0 auto',
|
|
||||||
padding: '50px 0px',
|
|
||||||
},
|
|
||||||
frame: {
|
|
||||||
boxShadow: 'rgba(0,0,0,0.14902) 0px 1px 1px 0px,rgba(0,0,0,0.09804) 0px 1px 2px 0px',
|
|
||||||
backgroundColor: 'white',
|
|
||||||
borderRadius: '5px',
|
|
||||||
padding: '30px 40px',
|
|
||||||
},
|
|
||||||
innerFrame: {
|
|
||||||
width: '100%',
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
fontSize: '1.4em',
|
|
||||||
fontWeight: 'bold',
|
|
||||||
borderBottom: '5px solid ' + theme.palette.primary.main,
|
|
||||||
display: 'inline-block',
|
|
||||||
paddingRight: '10px',
|
|
||||||
paddingBottom: '5px',
|
|
||||||
},
|
|
||||||
content: {
|
|
||||||
paddingTop: theme.spacing.unit * 2,
|
|
||||||
paddingBottom: theme.spacing.unit,
|
|
||||||
},
|
|
||||||
footer: {
|
|
||||||
marginTop: '10px',
|
|
||||||
textAlign: 'center',
|
|
||||||
fontSize: '0.65em',
|
|
||||||
color: 'grey',
|
|
||||||
'& a': {
|
|
||||||
color: 'grey',
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
export default styles;
|
|
|
@ -1,33 +0,0 @@
|
||||||
import { createStyles, Theme } from "@material-ui/core";
|
|
||||||
|
|
||||||
const styles = createStyles((theme: Theme) => ({
|
|
||||||
form: {
|
|
||||||
paddingTop: theme.spacing.unit * 2,
|
|
||||||
},
|
|
||||||
field: {
|
|
||||||
width: '100%',
|
|
||||||
},
|
|
||||||
buttonsContainer: {
|
|
||||||
marginTop: theme.spacing.unit * 2,
|
|
||||||
width: '100%',
|
|
||||||
},
|
|
||||||
buttonContainer: {
|
|
||||||
width: '50%',
|
|
||||||
display: 'inline-block',
|
|
||||||
boxSizing: 'border-box',
|
|
||||||
},
|
|
||||||
buttonConfirmContainer: {
|
|
||||||
paddingRight: theme.spacing.unit / 2,
|
|
||||||
},
|
|
||||||
buttonConfirm: {
|
|
||||||
width: '100%',
|
|
||||||
},
|
|
||||||
buttonCancelContainer: {
|
|
||||||
paddingLeft: theme.spacing.unit / 2,
|
|
||||||
},
|
|
||||||
buttonCancel: {
|
|
||||||
width: '100%',
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
export default styles;
|
|
|
@ -1,55 +0,0 @@
|
||||||
import { createStyles, Theme } from "@material-ui/core";
|
|
||||||
|
|
||||||
const borderColor = '#e0e0e0';
|
|
||||||
|
|
||||||
const styles = createStyles((theme: Theme) => ({
|
|
||||||
secretContainer: {
|
|
||||||
width: '100%',
|
|
||||||
border: '1px solid ' + borderColor,
|
|
||||||
marginTop: theme.spacing.unit * 2,
|
|
||||||
marginBottom: theme.spacing.unit * 2,
|
|
||||||
},
|
|
||||||
qrcodeContainer: {
|
|
||||||
textAlign: 'center',
|
|
||||||
padding: theme.spacing.unit * 2,
|
|
||||||
},
|
|
||||||
base32Container: {
|
|
||||||
textAlign: 'center',
|
|
||||||
borderTop: '1px solid ' + borderColor,
|
|
||||||
padding: theme.spacing.unit,
|
|
||||||
wordWrap: 'break-word',
|
|
||||||
},
|
|
||||||
text: {
|
|
||||||
textAlign: 'center',
|
|
||||||
},
|
|
||||||
needGoogleAuthenticator: {
|
|
||||||
textAlign: 'center',
|
|
||||||
marginTop: theme.spacing.unit * 2,
|
|
||||||
},
|
|
||||||
needGoogleAuthenticatorText: {
|
|
||||||
fontSize: theme.typography.fontSize * 0.8,
|
|
||||||
},
|
|
||||||
store: {
|
|
||||||
width: '100px',
|
|
||||||
marginTop: theme.spacing.unit * 0.5,
|
|
||||||
marginLeft: theme.spacing.unit * 0.5,
|
|
||||||
marginRight: theme.spacing.unit * 0.5,
|
|
||||||
},
|
|
||||||
buttonContainer: {
|
|
||||||
textAlign: 'center',
|
|
||||||
paddingTop: theme.spacing.unit * 2,
|
|
||||||
},
|
|
||||||
progressContainer: {
|
|
||||||
textAlign: 'center',
|
|
||||||
paddingTop: theme.spacing.unit * 2,
|
|
||||||
},
|
|
||||||
button: {
|
|
||||||
marginLeft: theme.spacing.unit,
|
|
||||||
marginRight: theme.spacing.unit,
|
|
||||||
},
|
|
||||||
loginButtonContainer: {
|
|
||||||
textAlign: 'center',
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
export default styles;
|
|
|
@ -1,30 +0,0 @@
|
||||||
import { createStyles, Theme } from "@material-ui/core";
|
|
||||||
|
|
||||||
const styles = createStyles((theme: Theme) => ({
|
|
||||||
form: {
|
|
||||||
marginTop: theme.spacing.unit * 2,
|
|
||||||
},
|
|
||||||
field: {
|
|
||||||
width: '100%',
|
|
||||||
marginBottom: theme.spacing.unit * 2,
|
|
||||||
},
|
|
||||||
buttonsContainer: {
|
|
||||||
width: '100%',
|
|
||||||
},
|
|
||||||
buttonContainer: {
|
|
||||||
width: '50%',
|
|
||||||
boxSizing: 'border-box',
|
|
||||||
display: 'inline-block',
|
|
||||||
},
|
|
||||||
buttonResetContainer: {
|
|
||||||
paddingRight: theme.spacing.unit / 2,
|
|
||||||
},
|
|
||||||
buttonCancelContainer: {
|
|
||||||
paddingLeft: theme.spacing.unit / 2,
|
|
||||||
},
|
|
||||||
button: {
|
|
||||||
width: '100%',
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
export default styles;
|
|
|
@ -1,19 +0,0 @@
|
||||||
import { createStyles, Theme } from "@material-ui/core";
|
|
||||||
|
|
||||||
const styles = createStyles((theme: Theme) => ({
|
|
||||||
infoContainer: {
|
|
||||||
marginBottom: theme.spacing.unit * 2,
|
|
||||||
},
|
|
||||||
imageContainer: {
|
|
||||||
textAlign: 'center',
|
|
||||||
'& img': {
|
|
||||||
width: '120px',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
retryButtonContainer: {
|
|
||||||
textAlign: 'center',
|
|
||||||
paddingTop: theme.spacing.unit * 2,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
export default styles;
|
|
2
client/src/assets/scss/_variables.scss
Normal file
2
client/src/assets/scss/_variables.scss
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
|
||||||
|
$theme-spacing: 10px;
|
|
@ -0,0 +1,24 @@
|
||||||
|
@import '../../variables.scss';
|
||||||
|
|
||||||
|
.container {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.messageContainer {
|
||||||
|
color: green;
|
||||||
|
|
||||||
|
.username {
|
||||||
|
display: block;
|
||||||
|
font-size: 1.6em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.statusIcon {
|
||||||
|
margin-top: ($theme-spacing) * 2;
|
||||||
|
margin-bottom: ($theme-spacing) * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logoutButtonContainer {
|
||||||
|
margin-top: ($theme-spacing) * 2,
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
@import '../../variables.scss';
|
||||||
|
|
||||||
|
.notification {
|
||||||
|
margin-bottom: ($theme-spacing) * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field {
|
||||||
|
padding-bottom: ($theme-spacing) * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons button{
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.controls {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rememberMe {
|
||||||
|
float: left;
|
||||||
|
font-size: 0.8em;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-left: -11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resetPassword {
|
||||||
|
height: 40px;
|
||||||
|
float: right;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resetPassword a {
|
||||||
|
color: black;
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
@import '../../variables.scss';
|
||||||
|
|
||||||
|
.container {
|
||||||
|
color: white;
|
||||||
|
font-size: 0.8em;
|
||||||
|
padding: ($theme-spacing) * 2;
|
||||||
|
border: 1px solid red;
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: #ff8d8d;
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
@import '../../variables.scss';
|
||||||
|
|
||||||
|
.container {
|
||||||
|
position: relative,
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
font-size: 1.5em;
|
||||||
|
margin-bottom: ($theme-spacing);
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.hello {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0px;
|
||||||
|
right: 0px;
|
||||||
|
font-size: 0.6em,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.body {
|
||||||
|
padding-top: ($theme-spacing) * 2;
|
||||||
|
padding-bottom: ($theme-spacing) * 2;
|
||||||
|
padding-left: ($theme-spacing) * 2;
|
||||||
|
padding-right: ($theme-spacing) * 2;
|
||||||
|
border: 1px solid #e0e0e0;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.methodName {
|
||||||
|
font-size: 1.2em;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: ($theme-spacing);
|
||||||
|
}
|
||||||
|
|
||||||
|
.methodU2f {
|
||||||
|
border-bottom: 1px solid #e0e0e0;
|
||||||
|
padding: ($theme-spacing);
|
||||||
|
}
|
||||||
|
|
||||||
|
.methodTotp {
|
||||||
|
padding: ($theme-spacing);
|
||||||
|
padding-top: ($theme-spacing) * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image {
|
||||||
|
width: '120px';
|
||||||
|
}
|
||||||
|
|
||||||
|
.imageContainer {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: ($theme-spacing) * 2;
|
||||||
|
margin-bottom: ($theme-spacing) * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.registerDeviceContainer {
|
||||||
|
text-align: right;
|
||||||
|
font-size: 0.7em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.totpField {
|
||||||
|
margin-top: ($theme-spacing) * 2;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.totpButton {
|
||||||
|
margin-top: ($theme-spacing);
|
||||||
|
|
||||||
|
button {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
@import '../../variables.scss';
|
||||||
|
@import "@material/theme/mdc-theme";
|
||||||
|
|
||||||
|
.mainContent {
|
||||||
|
width: 440px;
|
||||||
|
margin: auto;
|
||||||
|
margin-top: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 1.4em;
|
||||||
|
font-weight: bold;
|
||||||
|
display: inline-block;
|
||||||
|
padding-bottom: ($theme-spacing);
|
||||||
|
}
|
||||||
|
|
||||||
|
.frame {
|
||||||
|
box-shadow:
|
||||||
|
rgba(0,0,0,0.14902) 0px 1px 1px 0px,
|
||||||
|
rgba(0,0,0,0.09804) 0px 1px 2px 0px;
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 40px;
|
||||||
|
border-top: 6px solid ($mdc-theme-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.innerFrame {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
margin-top: 10px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 0.65em;
|
||||||
|
color: grey;
|
||||||
|
|
||||||
|
a:visited {
|
||||||
|
color: grey;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
@import '../../variables.scss';
|
||||||
|
|
||||||
|
.form {
|
||||||
|
padding-top: ($theme-spacing) * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttonsContainer {
|
||||||
|
margin-top: ($theme-spacing) * 2;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttonContainer {
|
||||||
|
width: 50%;
|
||||||
|
display: inline-block;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttonConfirmContainer {
|
||||||
|
padding-right: ($theme-spacing) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttonConfirm {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttonCancelContainer {
|
||||||
|
padding-left: ($theme-spacing) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttonCancel {
|
||||||
|
width: 100%;
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
@import '../../variables.scss';
|
||||||
|
|
||||||
|
.secretContainer {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #dcdcdc;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin-top: ($theme-spacing) * 2;
|
||||||
|
margin-bottom: ($theme-spacing) * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qrcodeContainer {
|
||||||
|
text-align: center;
|
||||||
|
padding: ($theme-spacing) * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.base32Container {
|
||||||
|
text-align: center;
|
||||||
|
border-top: 1px solid #dcdcdc;
|
||||||
|
padding: ($theme-spacing);
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.needGoogleAuthenticator {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: ($theme-spacing) * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.needGoogleAuthenticatorText {
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store {
|
||||||
|
width: 100px;
|
||||||
|
margin-top: ($theme-spacing) * 0.5;
|
||||||
|
margin-left: ($theme-spacing) * 0.5;
|
||||||
|
margin-right: ($theme-spacing) * 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttonContainer {
|
||||||
|
text-align: center;
|
||||||
|
padding-top: ($theme-spacing) * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progressContainer {
|
||||||
|
text-align: center;
|
||||||
|
padding-top: ($theme-spacing) * 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
margin-left: ($theme-spacing);
|
||||||
|
margin-right: ($theme-spacing);
|
||||||
|
}
|
||||||
|
|
||||||
|
.loginButtonContainer {
|
||||||
|
text-align: center;
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
@import '../../variables.scss';
|
||||||
|
|
||||||
|
.form {
|
||||||
|
margin-top: ($theme-spacing) * 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
.field {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: ($theme-spacing) * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttonsContainer {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttonContainer {
|
||||||
|
width: 50%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttonResetContainer {
|
||||||
|
padding-right: ($theme-spacing) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttonCancelContainer {
|
||||||
|
padding-left: ($theme-spacing) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
width: 100%;
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
@import '../../variables.scss';
|
||||||
|
|
||||||
|
.infoContainer {
|
||||||
|
margin-bottom: ($theme-spacing) * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.imageContainer {
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.retryButtonContainer {
|
||||||
|
text-align: center;
|
||||||
|
padding-top: ($theme-spacing) * 2;
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
import styles from '../../assets/jss/components/AlreadyAuthenticated/AlreadyAuthenticated';
|
import styles from '../../assets/scss/components/AlreadyAuthenticated/AlreadyAuthenticated.module.scss';
|
||||||
import { WithStyles, withStyles, Button } from "@material-ui/core";
|
import Button from "@material/react-button";
|
||||||
import CircleLoader, { Status } from "../CircleLoader/CircleLoader";
|
import CircleLoader, { Status } from "../CircleLoader/CircleLoader";
|
||||||
|
|
||||||
export interface OwnProps {
|
export interface OwnProps {
|
||||||
|
@ -12,26 +12,23 @@ export interface DispatchProps {
|
||||||
onLogoutClicked: () => void;
|
onLogoutClicked: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Props = OwnProps & DispatchProps & WithStyles;
|
export type Props = OwnProps & DispatchProps;
|
||||||
|
|
||||||
class AlreadyAuthenticated extends Component<Props> {
|
class AlreadyAuthenticated extends Component<Props> {
|
||||||
render() {
|
render() {
|
||||||
const { classes } = this.props;
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.container}>
|
<div className={styles.container}>
|
||||||
<div className={classes.successContainer}>
|
<div className={styles.successContainer}>
|
||||||
<CircleLoader status={Status.SUCCESSFUL} />
|
<div className={styles.messageContainer}>
|
||||||
<span className={classes.messageContainer}>
|
<span className={styles.username}>{this.props.username}</span>
|
||||||
<b>{this.props.username}</b><br/>
|
|
||||||
you are authenticated
|
you are authenticated
|
||||||
</span>
|
</div>
|
||||||
|
<div className={styles.statusIcon}><CircleLoader status={Status.SUCCESSFUL} /></div>
|
||||||
</div>
|
</div>
|
||||||
<div>Close this tab or logout</div>
|
<div className={styles.logoutButtonContainer}>
|
||||||
<div className={classes.logoutButtonContainer}>
|
|
||||||
<Button
|
<Button
|
||||||
onClick={this.props.onLogoutClicked}
|
onClick={this.props.onLogoutClicked}
|
||||||
variant="contained"
|
color="red">
|
||||||
color="primary">
|
|
||||||
Logout
|
Logout
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -40,4 +37,4 @@ class AlreadyAuthenticated extends Component<Props> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withStyles(styles)(AlreadyAuthenticated);
|
export default AlreadyAuthenticated;
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
|
||||||
import styles from './CircleLoader.module.scss';
|
import styles from '../../assets/scss/components/CircleLoader/CircleLoader.module.scss';
|
||||||
|
|
||||||
export enum Status {
|
export enum Status {
|
||||||
LOADING,
|
LOADING,
|
||||||
|
|
|
@ -1,19 +1,14 @@
|
||||||
import React, { Component, KeyboardEvent, ChangeEvent } from "react";
|
import React, { Component, KeyboardEvent, FormEvent } from "react";
|
||||||
|
|
||||||
import TextField from '@material-ui/core/TextField';
|
import TextField, {Input} from '@material/react-text-field';
|
||||||
import Button from '@material-ui/core/Button';
|
import Button from '@material/react-button';
|
||||||
|
import Checkbox from '@material/react-checkbox';
|
||||||
import FormControlLabel from '@material-ui/core/FormControlLabel';
|
|
||||||
import Checkbox from '@material-ui/core/Checkbox';
|
|
||||||
|
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { WithStyles, withStyles } from "@material-ui/core";
|
|
||||||
|
|
||||||
import styles from '../../assets/jss/components/FirstFactorForm/FirstFactorForm';
|
import Notification from "../../components/Notification/Notification";
|
||||||
import FormNotification from "../../components/FormNotification/FormNotification";
|
|
||||||
|
|
||||||
import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank'
|
import styles from '../../assets/scss/components/FirstFactorForm/FirstFactorForm.module.scss';
|
||||||
import CheckBoxIcon from '@material-ui/icons/CheckBox';
|
|
||||||
|
|
||||||
export interface StateProps {
|
export interface StateProps {
|
||||||
formDisabled: boolean;
|
formDisabled: boolean;
|
||||||
|
@ -24,7 +19,7 @@ export interface DispatchProps {
|
||||||
onAuthenticationRequested(username: string, password: string): void;
|
onAuthenticationRequested(username: string, password: string): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Props = StateProps & DispatchProps & WithStyles;
|
export type Props = StateProps & DispatchProps;
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
username: string;
|
username: string;
|
||||||
|
@ -48,12 +43,14 @@ class FirstFactorForm extends Component<Props, State> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
onUsernameChanged = (e: ChangeEvent<HTMLInputElement>) => {
|
onUsernameChanged = (e: FormEvent<HTMLElement>) => {
|
||||||
this.setState({username: e.target.value});
|
const val = (e.target as HTMLInputElement).value;
|
||||||
|
this.setState({username: val});
|
||||||
}
|
}
|
||||||
|
|
||||||
onPasswordChanged = (e: ChangeEvent<HTMLInputElement>) => {
|
onPasswordChanged = (e: FormEvent<HTMLElement>) => {
|
||||||
this.setState({password: e.target.value});
|
const val = (e.target as HTMLInputElement).value;
|
||||||
|
this.setState({password: val});
|
||||||
}
|
}
|
||||||
|
|
||||||
onLoginClicked = () => {
|
onLoginClicked = () => {
|
||||||
|
@ -67,63 +64,61 @@ class FirstFactorForm extends Component<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { classes } = this.props;
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<FormNotification
|
<Notification
|
||||||
show={this.props.error != null}>
|
show={this.props.error != null}
|
||||||
|
className={styles.notification}>
|
||||||
{this.props.error || ''}
|
{this.props.error || ''}
|
||||||
</FormNotification>
|
</Notification>
|
||||||
<div className={classes.fields}>
|
<div className={styles.fields}>
|
||||||
<div className={classes.field}>
|
<div className={styles.field}>
|
||||||
<TextField
|
<TextField
|
||||||
className={classes.input}
|
className={styles.input}
|
||||||
variant="outlined"
|
|
||||||
id="username"
|
|
||||||
label="Username"
|
label="Username"
|
||||||
disabled={this.props.formDisabled}
|
outlined={true}>
|
||||||
onChange={this.onUsernameChanged}>
|
<Input
|
||||||
|
id="username"
|
||||||
|
onChange={this.onUsernameChanged}
|
||||||
|
disabled={this.props.formDisabled}
|
||||||
|
value={this.state.username}/>
|
||||||
</TextField>
|
</TextField>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.field}>
|
<div className={styles.field}>
|
||||||
<TextField
|
<TextField
|
||||||
className={classes.input}
|
className={styles.input}
|
||||||
id="password"
|
|
||||||
variant="outlined"
|
|
||||||
label="Password"
|
label="Password"
|
||||||
type="password"
|
outlined={true}>
|
||||||
disabled={this.props.formDisabled}
|
<Input
|
||||||
onChange={this.onPasswordChanged}
|
id="password"
|
||||||
onKeyPress={this.onPasswordKeyPressed}>
|
type="password"
|
||||||
|
disabled={this.props.formDisabled}
|
||||||
|
onChange={this.onPasswordChanged}
|
||||||
|
onKeyPress={this.onPasswordKeyPressed}
|
||||||
|
value={this.state.password} />
|
||||||
</TextField>
|
</TextField>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className={classes.buttons}>
|
<div className={styles.buttons}>
|
||||||
<Button
|
<Button
|
||||||
onClick={this.onLoginClicked}
|
onClick={this.onLoginClicked}
|
||||||
variant="contained"
|
|
||||||
color="primary"
|
color="primary"
|
||||||
|
raised={true}
|
||||||
disabled={this.props.formDisabled}>
|
disabled={this.props.formDisabled}>
|
||||||
Login
|
Login
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.controls}>
|
<div className={styles.controls}>
|
||||||
<div className={classes.rememberMe}>
|
<div className={styles.rememberMe}>
|
||||||
<FormControlLabel
|
<Checkbox
|
||||||
control={
|
nativeControlId='remember-checkbox'
|
||||||
<Checkbox
|
checked={this.state.rememberMe}
|
||||||
icon={<CheckBoxOutlineBlankIcon fontSize="small" />}
|
onChange={this.toggleRememberMe}
|
||||||
checkedIcon={<CheckBoxIcon fontSize="small" />}
|
|
||||||
checked={this.state.rememberMe}
|
|
||||||
onChange={this.toggleRememberMe}
|
|
||||||
color="primary"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label="Remember me"
|
|
||||||
/>
|
/>
|
||||||
|
<label htmlFor='remember-checkbox'>Remember me</label>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.resetPassword}>
|
<div className={styles.resetPassword}>
|
||||||
<Link to="/forgot-password">Forgot password?</Link>
|
<Link to="/forgot-password">Forgot password?</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -139,4 +134,4 @@ class FirstFactorForm extends Component<Props, State> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withStyles(styles)(FirstFactorForm);
|
export default FirstFactorForm;
|
|
@ -1,27 +0,0 @@
|
||||||
import React, { Component } from "react";
|
|
||||||
import { withStyles, WithStyles, Collapse } from "@material-ui/core";
|
|
||||||
|
|
||||||
import styles from '../../assets/jss/components/FormNotification/FormNotification';
|
|
||||||
|
|
||||||
interface Props extends WithStyles {
|
|
||||||
show: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
class FormNotification extends Component<Props> {
|
|
||||||
render() {
|
|
||||||
const { classes } = this.props;
|
|
||||||
return (
|
|
||||||
<Collapse in={this.props.show}>
|
|
||||||
<div className={classes.messageOuter}>
|
|
||||||
<div className={classes.messageInner}>
|
|
||||||
<div className={classes.messageContainer}>
|
|
||||||
{this.props.children}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Collapse>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default withStyles(styles)(FormNotification);
|
|
21
client/src/components/Notification/Notification.tsx
Normal file
21
client/src/components/Notification/Notification.tsx
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import React, { Component } from "react";
|
||||||
|
import classnames from 'classnames';
|
||||||
|
|
||||||
|
import styles from '../../assets/scss/components/Notification/Notification.module.scss';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
className?: string;
|
||||||
|
show: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Notification extends Component<Props> {
|
||||||
|
render() {
|
||||||
|
return (this.props.show)
|
||||||
|
? (<div className={classnames(styles.container, this.props.className)}>
|
||||||
|
{this.props.children}
|
||||||
|
</div>)
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Notification;
|
|
@ -1,10 +1,11 @@
|
||||||
import React, { Component, KeyboardEvent, ChangeEvent } from 'react';
|
import React, { Component, KeyboardEvent, ChangeEvent, FormEvent } from 'react';
|
||||||
|
|
||||||
import { WithStyles, withStyles, Button, TextField } from '@material-ui/core';
|
import TextField, { Input } from '@material/react-text-field';
|
||||||
|
import Button from '@material/react-button';
|
||||||
|
|
||||||
import styles from '../../assets/jss/components/SecondFactorForm/SecondFactorForm';
|
import styles from '../../assets/scss/components/SecondFactorForm/SecondFactorForm.module.scss';
|
||||||
import CircleLoader, { Status } from '../../components/CircleLoader/CircleLoader';
|
import CircleLoader, { Status } from '../../components/CircleLoader/CircleLoader';
|
||||||
import FormNotification from '../FormNotification/FormNotification';
|
import Notification from '../Notification/Notification';
|
||||||
|
|
||||||
export interface OwnProps {
|
export interface OwnProps {
|
||||||
username: string;
|
username: string;
|
||||||
|
@ -29,7 +30,7 @@ export interface DispatchProps {
|
||||||
onOneTimePasswordValidationRequested: (token: string) => void;
|
onOneTimePasswordValidationRequested: (token: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Props = OwnProps & StateProps & DispatchProps & WithStyles;
|
export type Props = OwnProps & StateProps & DispatchProps;
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
oneTimePassword: string;
|
oneTimePassword: string;
|
||||||
|
@ -48,7 +49,6 @@ class SecondFactorView extends Component<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderU2f(n: number) {
|
private renderU2f(n: number) {
|
||||||
const { classes } = this.props;
|
|
||||||
let u2fStatus = Status.LOADING;
|
let u2fStatus = Status.LOADING;
|
||||||
if (this.props.securityKeyVerified) {
|
if (this.props.securityKeyVerified) {
|
||||||
u2fStatus = Status.SUCCESSFUL;
|
u2fStatus = Status.SUCCESSFUL;
|
||||||
|
@ -56,14 +56,14 @@ class SecondFactorView extends Component<Props, State> {
|
||||||
u2fStatus = Status.FAILURE;
|
u2fStatus = Status.FAILURE;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className={classes.methodU2f} key='u2f-method'>
|
<div className={styles.methodU2f} key='u2f-method'>
|
||||||
<div className={classes.methodName}>Option {n} - Security Key</div>
|
<div className={styles.methodName}>Option {n} - Security Key</div>
|
||||||
<div>Insert your security key into a USB port and touch the gold disk.</div>
|
<div>Insert your security key into a USB port and touch the gold disk.</div>
|
||||||
<div className={classes.imageContainer}>
|
<div className={styles.imageContainer}>
|
||||||
<CircleLoader status={u2fStatus}></CircleLoader>
|
<CircleLoader status={u2fStatus}></CircleLoader>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.registerDeviceContainer}>
|
<div className={styles.registerDeviceContainer}>
|
||||||
<a className={classes.registerDevice} href="#"
|
<a className={styles.registerDevice} href="#"
|
||||||
onClick={this.props.onRegisterSecurityKeyClicked}>
|
onClick={this.props.onRegisterSecurityKeyClicked}>
|
||||||
Register device
|
Register device
|
||||||
</a>
|
</a>
|
||||||
|
@ -72,8 +72,8 @@ class SecondFactorView extends Component<Props, State> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private onOneTimePasswordChanged = (e: ChangeEvent<HTMLInputElement>) => {
|
private onOneTimePasswordChanged = (e: FormEvent<HTMLElement>) => {
|
||||||
this.setState({oneTimePassword: e.target.value});
|
this.setState({oneTimePassword: (e.target as HTMLInputElement).value});
|
||||||
}
|
}
|
||||||
|
|
||||||
private onTotpKeyPressed = (e: KeyboardEvent) => {
|
private onTotpKeyPressed = (e: KeyboardEvent) => {
|
||||||
|
@ -88,42 +88,43 @@ class SecondFactorView extends Component<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderTotp(n: number) {
|
private renderTotp(n: number) {
|
||||||
const { classes } = this.props;
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.methodTotp} key='totp-method'>
|
<div className={styles.methodTotp} key='totp-method'>
|
||||||
<div className={classes.methodName}>Option {n} - One-Time Password</div>
|
<div className={styles.methodName}>Option {n} - One-Time Password</div>
|
||||||
<FormNotification show={this.props.oneTimePasswordVerificationError !== null}>
|
<Notification show={this.props.oneTimePasswordVerificationError !== null}>
|
||||||
{this.props.oneTimePasswordVerificationError}
|
{this.props.oneTimePasswordVerificationError}
|
||||||
</FormNotification>
|
</Notification>
|
||||||
<TextField
|
<TextField
|
||||||
className={classes.totpField}
|
className={styles.totpField}
|
||||||
name="totp-token"
|
|
||||||
id="totp-token"
|
|
||||||
variant="outlined"
|
|
||||||
label="One-Time Password"
|
label="One-Time Password"
|
||||||
onChange={this.onOneTimePasswordChanged}
|
outlined={true}>
|
||||||
onKeyPress={this.onTotpKeyPressed}>
|
<Input
|
||||||
|
name="totp-token"
|
||||||
|
id="totp-token"
|
||||||
|
onChange={this.onOneTimePasswordChanged as any}
|
||||||
|
onKeyPress={this.onTotpKeyPressed}
|
||||||
|
value={this.state.oneTimePassword} />
|
||||||
</TextField>
|
</TextField>
|
||||||
<div className={classes.registerDeviceContainer}>
|
<div className={styles.registerDeviceContainer}>
|
||||||
<a className={classes.registerDevice} href="#"
|
<a className={styles.registerDevice} href="#"
|
||||||
onClick={this.props.onRegisterOneTimePasswordClicked}>
|
onClick={this.props.onRegisterOneTimePasswordClicked}>
|
||||||
Register device
|
Register device
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<div className={styles.totpButton}>
|
||||||
className={classes.totpButton}
|
<Button
|
||||||
variant="contained"
|
color="primary"
|
||||||
color="primary"
|
raised={true}
|
||||||
onClick={this.onOneTimePasswordValidationRequested}
|
onClick={this.onOneTimePasswordValidationRequested}
|
||||||
disabled={this.props.oneTimePasswordVerificationInProgress}>
|
disabled={this.props.oneTimePasswordVerificationInProgress}>
|
||||||
OK
|
OK
|
||||||
</Button>
|
</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderMode() {
|
private renderMode() {
|
||||||
const { classes } = this.props;
|
|
||||||
const methods = [];
|
const methods = [];
|
||||||
let n = 1;
|
let n = 1;
|
||||||
if (this.props.securityKeySupported) {
|
if (this.props.securityKeySupported) {
|
||||||
|
@ -133,23 +134,22 @@ class SecondFactorView extends Component<Props, State> {
|
||||||
methods.push(this.renderTotp(n));
|
methods.push(this.renderTotp(n));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.methodsContainer}>
|
<div className={styles.methodsContainer}>
|
||||||
{methods}
|
{methods}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { classes } = this.props;
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.container}>
|
<div className={styles.container}>
|
||||||
<div className={classes.header}>
|
<div className={styles.header}>
|
||||||
<div className={classes.hello}>Hello <b>{this.props.username}</b></div>
|
<div className={styles.hello}>Hello <b>{this.props.username}</b></div>
|
||||||
<div className={classes.logout}>
|
<div className={styles.logout}>
|
||||||
<a onClick={this.props.onLogoutClicked} href="#">Logout</a>
|
<a onClick={this.props.onLogoutClicked} href="#">Logout</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.body}>
|
<div className={styles.body}>
|
||||||
{this.renderMode()}
|
{this.renderMode()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -157,4 +157,4 @@ class SecondFactorView extends Component<Props, State> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withStyles(styles)(SecondFactorView);
|
export default SecondFactorView;
|
|
@ -32,11 +32,14 @@ function onAuthenticationRequested(dispatch: Dispatch) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const json = await res.json();
|
if (res.status !== 204) {
|
||||||
if ('error' in json) {
|
const json = await res.json();
|
||||||
await dispatch(authenticateFailure(json['error']));
|
if ('error' in json) {
|
||||||
return;
|
await dispatch(authenticateFailure(json['error']));
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(authenticateSuccess());
|
dispatch(authenticateSuccess());
|
||||||
|
|
||||||
// fetch state
|
// fetch state
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
|
||||||
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
|
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
|
||||||
sans-serif;
|
sans-serif;
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
background: #eee;
|
background: #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,10 @@ import { Route, Switch, Redirect, RouterProps, RouteProps } from "react-router";
|
||||||
|
|
||||||
import { routes } from '../../routes/routes';
|
import { routes } from '../../routes/routes';
|
||||||
import { AUTHELIA_GITHUB_URL } from "../../constants";
|
import { AUTHELIA_GITHUB_URL } from "../../constants";
|
||||||
import { WithStyles, withStyles } from "@material-ui/core";
|
|
||||||
|
|
||||||
import styles from '../../assets/jss/layouts/PortalLayout/PortalLayout';
|
import styles from '../../assets/scss/layouts/PortalLayout/PortalLayout.module.scss';
|
||||||
|
|
||||||
interface Props extends RouterProps, RouteProps, WithStyles {}
|
interface Props extends RouterProps, RouteProps {}
|
||||||
|
|
||||||
class PortalLayout extends Component<Props> {
|
class PortalLayout extends Component<Props> {
|
||||||
private renderTitle() {
|
private renderTitle() {
|
||||||
|
@ -25,15 +24,14 @@ class PortalLayout extends Component<Props> {
|
||||||
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { classes } = this.props;
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.mainContent}>
|
<div className={styles.main}>
|
||||||
<div className={classes.frame}>
|
<div className={styles.mainContent}>
|
||||||
<div className={classes.innerFrame}>
|
<div className={styles.title}>
|
||||||
<div className={classes.title}>
|
{this.renderTitle()}
|
||||||
{this.renderTitle()}
|
</div>
|
||||||
</div>
|
<div className={styles.frame}>
|
||||||
<div className={classes.content}>
|
<div className={styles.innerFrame}>
|
||||||
<Switch>
|
<Switch>
|
||||||
{routes.map((r, key) => {
|
{routes.map((r, key) => {
|
||||||
return <Route path={r.path} component={r.component} exact={true} key={key} />
|
return <Route path={r.path} component={r.component} exact={true} key={key} />
|
||||||
|
@ -42,13 +40,13 @@ class PortalLayout extends Component<Props> {
|
||||||
</Switch>
|
</Switch>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className={styles.footer}>
|
||||||
<div className={classes.footer}>
|
<div><a href={AUTHELIA_GITHUB_URL}>Powered by Authelia</a></div>
|
||||||
<div>Powered by <a href={AUTHELIA_GITHUB_URL}>Authelia</a></div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withStyles(styles)(PortalLayout);
|
export default PortalLayout;
|
|
@ -7,7 +7,7 @@ import AuthenticationView from "../containers/views/AuthenticationView/Authentic
|
||||||
|
|
||||||
export const routes = [{
|
export const routes = [{
|
||||||
path: '/',
|
path: '/',
|
||||||
title: 'Login',
|
title: 'Sign in',
|
||||||
component: AuthenticationView,
|
component: AuthenticationView,
|
||||||
}, {
|
}, {
|
||||||
path: '/confirmation-sent',
|
path: '/confirmation-sent',
|
||||||
|
@ -15,11 +15,11 @@ export const routes = [{
|
||||||
component: ConfirmationSentView
|
component: ConfirmationSentView
|
||||||
}, {
|
}, {
|
||||||
path: '/one-time-password-registration',
|
path: '/one-time-password-registration',
|
||||||
title: 'One-time password registration',
|
title: 'One-time password',
|
||||||
component: OneTimePasswordRegistrationView,
|
component: OneTimePasswordRegistrationView,
|
||||||
}, {
|
}, {
|
||||||
path: '/security-key-registration',
|
path: '/security-key-registration',
|
||||||
title: 'Security key registration',
|
title: 'Security key',
|
||||||
component: SecurityKeyRegistrationView,
|
component: SecurityKeyRegistrationView,
|
||||||
}, {
|
}, {
|
||||||
path: '/forgot-password',
|
path: '/forgot-password',
|
||||||
|
|
|
@ -3,7 +3,7 @@ import AlreadyAuthenticated from "../../containers/components/AlreadyAuthenticat
|
||||||
import FirstFactorForm from "../../containers/components/FirstFactorForm/FirstFactorForm";
|
import FirstFactorForm from "../../containers/components/FirstFactorForm/FirstFactorForm";
|
||||||
import SecondFactorForm from "../../containers/components/SecondFactorForm/SecondFactorForm";
|
import SecondFactorForm from "../../containers/components/SecondFactorForm/SecondFactorForm";
|
||||||
import RemoteState from "./RemoteState";
|
import RemoteState from "./RemoteState";
|
||||||
import { RouterProps, Redirect } from "react-router";
|
import { RouterProps } from "react-router";
|
||||||
import queryString from 'query-string';
|
import queryString from 'query-string';
|
||||||
|
|
||||||
export enum Stage {
|
export enum Stage {
|
||||||
|
|
|
@ -3,8 +3,8 @@ import classnames from 'classnames';
|
||||||
|
|
||||||
import mail from '../../assets/images/mail.png';
|
import mail from '../../assets/images/mail.png';
|
||||||
|
|
||||||
import styles from './ConfirmationSentView.module.css';
|
import styles from '../../assets/scss/views/ConfirmationSentView/ConfirmationSentView.module.scss';
|
||||||
import { Button } from "@material-ui/core";
|
import Button from "@material/react-button";
|
||||||
import { RouterProps } from "react-router";
|
import { RouterProps } from "react-router";
|
||||||
|
|
||||||
interface Props extends RouterProps {}
|
interface Props extends RouterProps {}
|
||||||
|
@ -22,7 +22,7 @@ class ConfirmationSentView extends Component<Props> {
|
||||||
<Button
|
<Button
|
||||||
onClick={() => this.props.history.goBack()}
|
onClick={() => this.props.history.goBack()}
|
||||||
className={styles.button}
|
className={styles.button}
|
||||||
variant="contained"
|
raised={true}
|
||||||
color="primary">
|
color="primary">
|
||||||
Back
|
Back
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import React, { Component, ChangeEvent, KeyboardEvent } from "react";
|
import React, { Component, KeyboardEvent, FormEvent } from "react";
|
||||||
import { TextField, WithStyles, withStyles, Button } from "@material-ui/core";
|
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
import Button from "@material/react-button";
|
||||||
|
import TextField, { Input } from "@material/react-text-field";
|
||||||
|
|
||||||
import styles from '../../assets/jss/views/ForgotPasswordView/ForgotPasswordView';
|
import styles from '../../assets/scss/views/ForgotPasswordView/ForgotPasswordView.module.scss';
|
||||||
|
|
||||||
export interface StateProps {
|
export interface StateProps {
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
|
@ -13,7 +14,7 @@ export interface DispatchProps {
|
||||||
onCancelClicked: () => void;
|
onCancelClicked: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Props = StateProps & DispatchProps & WithStyles;
|
export type Props = StateProps & DispatchProps;
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
username: string;
|
username: string;
|
||||||
|
@ -27,8 +28,8 @@ class ForgotPasswordView extends Component<Props, State> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private onUsernameChanged = (e: ChangeEvent<HTMLInputElement>) => {
|
private onUsernameChanged = (e: FormEvent<HTMLElement>) => {
|
||||||
this.setState({username: e.target.value});
|
this.setState({username: (e.target as HTMLInputElement).value});
|
||||||
}
|
}
|
||||||
|
|
||||||
private onKeyPressed = (e: KeyboardEvent) => {
|
private onKeyPressed = (e: KeyboardEvent) => {
|
||||||
|
@ -43,38 +44,38 @@ class ForgotPasswordView extends Component<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { classes } = this.props;
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div>What's your username?</div>
|
<div>What's your username?</div>
|
||||||
<div className={classes.form}>
|
<div className={styles.form}>
|
||||||
<TextField
|
<TextField
|
||||||
className={classes.field}
|
className={styles.field}
|
||||||
variant="outlined"
|
outlined={true}
|
||||||
id="username"
|
id="username"
|
||||||
label="Username"
|
label="Username">
|
||||||
onChange={this.onUsernameChanged}
|
<Input
|
||||||
onKeyPress={this.onKeyPressed}
|
onChange={this.onUsernameChanged}
|
||||||
value={this.state.username}
|
onKeyPress={this.onKeyPressed}
|
||||||
disabled={this.props.disabled}>
|
value={this.state.username}
|
||||||
|
disabled={this.props.disabled} />
|
||||||
</TextField>
|
</TextField>
|
||||||
<div className={classes.buttonsContainer}>
|
<div className={styles.buttonsContainer}>
|
||||||
<div className={classnames(classes.buttonContainer, classes.buttonConfirmContainer)}>
|
<div className={classnames(styles.buttonContainer, styles.buttonConfirmContainer)}>
|
||||||
<Button
|
<Button
|
||||||
onClick={this.onPasswordResetRequested}
|
onClick={this.onPasswordResetRequested}
|
||||||
variant="contained"
|
|
||||||
color="primary"
|
color="primary"
|
||||||
className={classes.buttonConfirm}
|
raised={true}
|
||||||
|
className={styles.buttonConfirm}
|
||||||
disabled={this.props.disabled}>
|
disabled={this.props.disabled}>
|
||||||
Next
|
Next
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className={classnames(classes.buttonContainer, classes.buttonCancelContainer)}>
|
<div className={classnames(styles.buttonContainer, styles.buttonCancelContainer)}>
|
||||||
<Button
|
<Button
|
||||||
onClick={this.props.onCancelClicked}
|
onClick={this.props.onCancelClicked}
|
||||||
variant="contained"
|
|
||||||
color="primary"
|
color="primary"
|
||||||
className={classes.buttonCancel}>
|
raised={true}
|
||||||
|
className={styles.buttonCancel}>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -85,4 +86,4 @@ class ForgotPasswordView extends Component<Props, State> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withStyles(styles)(ForgotPasswordView);
|
export default ForgotPasswordView;
|
|
@ -1,19 +1,20 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
import { WithStyles, withStyles, CircularProgress, Button } from "@material-ui/core";
|
import Button from "@material/react-button";
|
||||||
|
|
||||||
import styles from '../../assets/jss/views/OneTimePasswordRegistrationView/OneTimePasswordRegistrationView';
|
import styles from '../../assets/scss/views/OneTimePasswordRegistrationView/OneTimePasswordRegistrationView.module.scss';
|
||||||
import { RouteProps, RouterProps } from "react-router";
|
import { RouteProps, RouterProps } from "react-router";
|
||||||
import QueryString from 'query-string';
|
import QueryString from 'query-string';
|
||||||
|
|
||||||
import QRCode from 'qrcode.react';
|
import QRCode from 'qrcode.react';
|
||||||
import FormNotification from "../../components/FormNotification/FormNotification";
|
import Notification from "../../components/Notification/Notification";
|
||||||
|
|
||||||
import googleStoreImage from '../../assets/images/googleplay-badge.svg';
|
import googleStoreImage from '../../assets/images/googleplay-badge.svg';
|
||||||
import appleStoreImage from '../../assets/images/applestore-badge.svg';
|
import appleStoreImage from '../../assets/images/applestore-badge.svg';
|
||||||
import { Secret } from "./Secret";
|
import { Secret } from "./Secret";
|
||||||
|
import CircleLoader, { Status } from "../../components/CircleLoader/CircleLoader";
|
||||||
|
|
||||||
export interface Props extends WithStyles, RouteProps, RouterProps {
|
export interface Props extends RouteProps, RouterProps {
|
||||||
secret: Secret | null;
|
secret: Secret | null;
|
||||||
error: string | null;
|
error: string | null;
|
||||||
onInit: (token: string) => void;
|
onInit: (token: string) => void;
|
||||||
|
@ -47,54 +48,52 @@ class OneTimePasswordRegistrationView extends Component<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderWithSecret(secret: Secret) {
|
private renderWithSecret(secret: Secret) {
|
||||||
const { classes } = this.props;
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className={classes.text}>
|
<div className={styles.text}>
|
||||||
Register your device by scanning the barcode or adding the key.
|
Register your device by scanning the barcode or adding the key.
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.secretContainer}>
|
<div className={styles.secretContainer}>
|
||||||
<div className={classes.qrcodeContainer}>
|
<div className={styles.qrcodeContainer}>
|
||||||
<QRCode value={secret.otpauth_url} size={180} level="Q"></QRCode>
|
<QRCode value={secret.otpauth_url} size={180} level="Q"></QRCode>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.base32Container}>{secret.base32_secret}</div>
|
<div className={styles.base32Container}>{secret.base32_secret}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.loginButtonContainer}>
|
<div className={styles.loginButtonContainer}>
|
||||||
<Button
|
<Button
|
||||||
color="primary"
|
color="primary"
|
||||||
variant="contained"
|
raised={true}
|
||||||
onClick={this.props.onLoginClicked}>
|
onClick={this.props.onLoginClicked}>
|
||||||
Login
|
Login
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.needGoogleAuthenticator}>
|
<div className={styles.needGoogleAuthenticator}>
|
||||||
<div className={classes.needGoogleAuthenticatorText}>Need Google Authenticator?</div>
|
<div className={styles.needGoogleAuthenticatorText}>Need Google Authenticator?</div>
|
||||||
<img src={appleStoreImage} className={classes.store} alt='Google Authenticator on Apple Store'/>
|
<img src={appleStoreImage} className={styles.store} alt='Google Authenticator on Apple Store'/>
|
||||||
<img src={googleStoreImage} className={classes.store} alt='Google Authenticator on Google Store'/>
|
<img src={googleStoreImage} className={styles.store} alt='Google Authenticator on Google Store'/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderError() {
|
private renderError() {
|
||||||
const {classes} = this.props;
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<FormNotification show={true}>
|
<Notification show={true}>
|
||||||
<div>{this.props.error}</div>
|
<div>{this.props.error}</div>
|
||||||
</FormNotification>
|
</Notification>
|
||||||
<div className={classes.buttonContainer}>
|
<div className={styles.buttonContainer}>
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
|
||||||
color="primary"
|
color="primary"
|
||||||
className={classes.button}
|
raised={true}
|
||||||
|
className={styles.button}
|
||||||
onClick={this.props.onRetryClicked}>
|
onClick={this.props.onRetryClicked}>
|
||||||
Retry
|
Retry
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
|
||||||
color="primary"
|
color="primary"
|
||||||
className={classes.button}
|
raised={true}
|
||||||
|
className={styles.button}
|
||||||
onClick={this.props.onCancelClicked}>
|
onClick={this.props.onCancelClicked}>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -110,11 +109,10 @@ class OneTimePasswordRegistrationView extends Component<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderLoading() {
|
private renderLoading() {
|
||||||
const { classes } = this.props;
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div>One-Time password secret is being generated...</div>
|
<div>One-Time password secret is being generated...</div>
|
||||||
<div className={classes.progressContainer}><CircularProgress /></div>
|
<div className={styles.progressContainer}><CircleLoader status={Status.LOADING} /></div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -126,4 +124,4 @@ class OneTimePasswordRegistrationView extends Component<Props> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withStyles(styles)(OneTimePasswordRegistrationView);
|
export default OneTimePasswordRegistrationView;
|
|
@ -1,11 +1,13 @@
|
||||||
import React, { Component, KeyboardEvent, ChangeEvent } from "react";
|
import React, { Component, KeyboardEvent, FormEvent } from "react";
|
||||||
import { TextField, Button, WithStyles, withStyles } from "@material-ui/core";
|
|
||||||
import { RouterProps } from "react-router";
|
import { RouterProps } from "react-router";
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import QueryString from 'query-string';
|
import QueryString from 'query-string';
|
||||||
|
|
||||||
import styles from '../../assets/jss/views/ResetPasswordView/ResetPasswordView';
|
import Button from "@material/react-button";
|
||||||
import FormNotification from "../../components/FormNotification/FormNotification";
|
import TextField, { Input } from "@material/react-text-field";
|
||||||
|
|
||||||
|
import styles from '../../assets/scss/views/ResetPasswordView/ResetPasswordView.module.scss';
|
||||||
|
import Notification from "../../components/Notification/Notification";
|
||||||
|
|
||||||
export interface StateProps {
|
export interface StateProps {
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
|
@ -17,7 +19,7 @@ export interface DispatchProps {
|
||||||
onCancelClicked: () => void;
|
onCancelClicked: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Props = StateProps & DispatchProps & RouterProps & WithStyles;
|
export type Props = StateProps & DispatchProps & RouterProps;
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
password1: string;
|
password1: string;
|
||||||
|
@ -66,61 +68,64 @@ class ResetPasswordView extends Component<Props, State> {
|
||||||
this.onPasswordResetRequested();
|
this.onPasswordResetRequested();
|
||||||
}
|
}
|
||||||
|
|
||||||
private onPassword1Changed = (e: ChangeEvent<HTMLInputElement>) => {
|
private onPassword1Changed = (e: FormEvent<HTMLElement>) => {
|
||||||
this.setState({password1: e.target.value});
|
this.setState({password1: (e.target as HTMLInputElement).value});
|
||||||
}
|
}
|
||||||
|
|
||||||
private onPassword2Changed = (e: ChangeEvent<HTMLInputElement>) => {
|
private onPassword2Changed = (e: FormEvent<HTMLElement>) => {
|
||||||
this.setState({password2: e.target.value});
|
this.setState({password2: (e.target as HTMLInputElement).value});
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { classes } = this.props;
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<FormNotification show={this.state.error !== null}>
|
<Notification show={this.state.error !== null}>
|
||||||
{this.state.error}
|
{this.state.error}
|
||||||
</FormNotification>
|
</Notification>
|
||||||
<div>Enter your new password</div>
|
<div>Enter your new password</div>
|
||||||
<div className={classes.form}>
|
<div className={styles.form}>
|
||||||
<TextField
|
<TextField
|
||||||
className={classes.field}
|
className={styles.field}
|
||||||
variant="outlined"
|
outlined={true}
|
||||||
type="password"
|
|
||||||
id="password1"
|
id="password1"
|
||||||
value={this.state.password1}
|
|
||||||
onChange={this.onPassword1Changed}
|
|
||||||
disabled={this.props.disabled}
|
|
||||||
label="New password">
|
label="New password">
|
||||||
|
<Input
|
||||||
|
type="password"
|
||||||
|
key="password1"
|
||||||
|
value={this.state.password1}
|
||||||
|
onChange={this.onPassword1Changed}
|
||||||
|
disabled={this.props.disabled}/>
|
||||||
</TextField>
|
</TextField>
|
||||||
<TextField
|
<TextField
|
||||||
className={classes.field}
|
className={styles.field}
|
||||||
variant="outlined"
|
outlined={true}
|
||||||
type="password"
|
|
||||||
id="password2"
|
id="password2"
|
||||||
value={this.state.password2}
|
|
||||||
onKeyPress={this.onKeyPressed}
|
|
||||||
onChange={this.onPassword2Changed}
|
|
||||||
disabled={this.props.disabled}
|
|
||||||
label="Confirm password">
|
label="Confirm password">
|
||||||
|
<Input
|
||||||
|
type="password"
|
||||||
|
key="password2"
|
||||||
|
value={this.state.password2}
|
||||||
|
onKeyPress={this.onKeyPressed}
|
||||||
|
onChange={this.onPassword2Changed}
|
||||||
|
disabled={this.props.disabled} />
|
||||||
</TextField>
|
</TextField>
|
||||||
<div className={classes.buttonsContainer}>
|
<div className={styles.buttonsContainer}>
|
||||||
<div className={classnames(classes.buttonContainer, classes.buttonResetContainer)}>
|
<div className={classnames(styles.buttonContainer, styles.buttonResetContainer)}>
|
||||||
<Button
|
<Button
|
||||||
onClick={this.onResetClicked}
|
onClick={this.onResetClicked}
|
||||||
variant="contained"
|
|
||||||
color="primary"
|
color="primary"
|
||||||
|
raised={true}
|
||||||
disabled={this.props.disabled}
|
disabled={this.props.disabled}
|
||||||
className={classnames(classes.button, classes.buttonReset)}>
|
className={classnames(styles.button, styles.buttonReset)}>
|
||||||
Reset
|
Reset
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className={classnames(classes.buttonContainer, classes.buttonCancelContainer)}>
|
<div className={classnames(styles.buttonContainer, styles.buttonCancelContainer)}>
|
||||||
<Button
|
<Button
|
||||||
onClick={this.props.onCancelClicked}
|
onClick={this.props.onCancelClicked}
|
||||||
variant="contained"
|
|
||||||
color="primary"
|
color="primary"
|
||||||
className={classnames(classes.button, classes.buttonCancel)}>
|
raised={true}
|
||||||
|
className={classnames(styles.button, styles.buttonCancel)}>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -131,4 +136,4 @@ class ResetPasswordView extends Component<Props, State> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withStyles(styles)(ResetPasswordView);
|
export default ResetPasswordView;
|
|
@ -1,14 +1,14 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
import { WithStyles, withStyles, Button } from "@material-ui/core";
|
import Button from "@material/react-button";
|
||||||
|
|
||||||
import styles from '../../assets/jss/views/SecurityKeyRegistrationView/SecurityKeyRegistrationView';
|
import styles from '../../assets/scss/views/SecurityKeyRegistrationView/SecurityKeyRegistrationView.module.scss';
|
||||||
import { RouteProps, RouterProps } from "react-router";
|
import { RouteProps, RouterProps } from "react-router";
|
||||||
import QueryString from 'query-string';
|
import QueryString from 'query-string';
|
||||||
import FormNotification from "../../components/FormNotification/FormNotification";
|
import Notification from "../../components/Notification/Notification";
|
||||||
import CircleLoader, { Status } from "../../components/CircleLoader/CircleLoader";
|
import CircleLoader, { Status } from "../../components/CircleLoader/CircleLoader";
|
||||||
|
|
||||||
export interface Props extends WithStyles, RouteProps, RouterProps {
|
export interface Props extends RouteProps, RouterProps {
|
||||||
deviceRegistered: boolean | null;
|
deviceRegistered: boolean | null;
|
||||||
error: string | null;
|
error: string | null;
|
||||||
onInit: (token: string) => void;
|
onInit: (token: string) => void;
|
||||||
|
@ -32,16 +32,15 @@ class SecurityKeyRegistrationView extends Component<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderError() {
|
private renderError() {
|
||||||
const { classes } = this.props;
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<FormNotification show={true}>
|
<Notification show={true}>
|
||||||
{this.props.error}
|
{this.props.error}
|
||||||
</FormNotification>
|
</Notification>
|
||||||
<div className={classes.retryButtonContainer}>
|
<div className={styles.retryButtonContainer}>
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
|
||||||
color="primary"
|
color="primary"
|
||||||
|
raised={true}
|
||||||
onClick={this.props.onBackClicked}>
|
onClick={this.props.onBackClicked}>
|
||||||
Back
|
Back
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -51,7 +50,6 @@ class SecurityKeyRegistrationView extends Component<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderRegistering() {
|
private renderRegistering() {
|
||||||
const { classes } = this.props;
|
|
||||||
let status = Status.LOADING;
|
let status = Status.LOADING;
|
||||||
if (this.props.deviceRegistered === true) {
|
if (this.props.deviceRegistered === true) {
|
||||||
status = Status.SUCCESSFUL;
|
status = Status.SUCCESSFUL;
|
||||||
|
@ -60,8 +58,8 @@ class SecurityKeyRegistrationView extends Component<Props> {
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className={classes.infoContainer}>Press the gold disk to register your security key</div>
|
<div className={styles.infoContainer}>Press the gold disk to register your security key</div>
|
||||||
<div className={classes.imageContainer}>
|
<div className={styles.imageContainer}>
|
||||||
<CircleLoader status={status}></CircleLoader>
|
<CircleLoader status={status}></CircleLoader>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -77,4 +75,4 @@ class SecurityKeyRegistrationView extends Component<Props> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withStyles(styles)(SecurityKeyRegistrationView);
|
export default SecurityKeyRegistrationView;
|
68
package-lock.json
generated
68
package-lock.json
generated
|
@ -285,7 +285,7 @@
|
||||||
},
|
},
|
||||||
"@types/events": {
|
"@types/events": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "http://registry.npmjs.org/@types/events/-/events-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz",
|
||||||
"integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==",
|
"integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
@ -312,7 +312,7 @@
|
||||||
},
|
},
|
||||||
"@types/express-session": {
|
"@types/express-session": {
|
||||||
"version": "1.15.8",
|
"version": "1.15.8",
|
||||||
"resolved": "http://registry.npmjs.org/@types/express-session/-/express-session-1.15.8.tgz",
|
"resolved": "https://registry.npmjs.org/@types/express-session/-/express-session-1.15.8.tgz",
|
||||||
"integrity": "sha512-Be5N9zul4C/IH1UjRDaVJ46wkG1jsBgJlihBdWlqJWfCaiqvaVmxcyqcLey7omSFGCTIUDgdHqf0vwNjEZOSVA==",
|
"integrity": "sha512-Be5N9zul4C/IH1UjRDaVJ46wkG1jsBgJlihBdWlqJWfCaiqvaVmxcyqcLey7omSFGCTIUDgdHqf0vwNjEZOSVA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -358,7 +358,7 @@
|
||||||
},
|
},
|
||||||
"@types/ldapjs": {
|
"@types/ldapjs": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "http://registry.npmjs.org/@types/ldapjs/-/ldapjs-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/ldapjs/-/ldapjs-1.0.3.tgz",
|
||||||
"integrity": "sha512-FSj24s1WsFEfOy8taIKp2DokSZfFkjWYZb88AS5eDj3WTocZ+4DnHjhzrXEs048WQ5mfOLJXMOAnc0kSnHh5Lw==",
|
"integrity": "sha512-FSj24s1WsFEfOy8taIKp2DokSZfFkjWYZb88AS5eDj3WTocZ+4DnHjhzrXEs048WQ5mfOLJXMOAnc0kSnHh5Lw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -380,7 +380,7 @@
|
||||||
},
|
},
|
||||||
"@types/mockdate": {
|
"@types/mockdate": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "http://registry.npmjs.org/@types/mockdate/-/mockdate-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/mockdate/-/mockdate-2.0.0.tgz",
|
||||||
"integrity": "sha1-qvOIoerTsPXtbcFhGVbqe0ClfTw=",
|
"integrity": "sha1-qvOIoerTsPXtbcFhGVbqe0ClfTw=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
@ -598,7 +598,7 @@
|
||||||
},
|
},
|
||||||
"@types/yamljs": {
|
"@types/yamljs": {
|
||||||
"version": "0.2.30",
|
"version": "0.2.30",
|
||||||
"resolved": "http://registry.npmjs.org/@types/yamljs/-/yamljs-0.2.30.tgz",
|
"resolved": "https://registry.npmjs.org/@types/yamljs/-/yamljs-0.2.30.tgz",
|
||||||
"integrity": "sha1-0DTh0ynkbo0Pc3yajbl/aPgbU4I=",
|
"integrity": "sha1-0DTh0ynkbo0Pc3yajbl/aPgbU4I=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
@ -844,7 +844,7 @@
|
||||||
},
|
},
|
||||||
"array-equal": {
|
"array-equal": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "http://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz",
|
||||||
"integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=",
|
"integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
@ -1058,7 +1058,7 @@
|
||||||
},
|
},
|
||||||
"chalk": {
|
"chalk": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
"resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||||
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -1536,7 +1536,7 @@
|
||||||
},
|
},
|
||||||
"browserify-aes": {
|
"browserify-aes": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
|
||||||
"integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
|
"integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -1621,7 +1621,7 @@
|
||||||
},
|
},
|
||||||
"browserify-rsa": {
|
"browserify-rsa": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
"resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
|
||||||
"integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
|
"integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -1660,7 +1660,7 @@
|
||||||
},
|
},
|
||||||
"buffer": {
|
"buffer": {
|
||||||
"version": "4.9.1",
|
"version": "4.9.1",
|
||||||
"resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
|
||||||
"integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
|
"integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -1753,7 +1753,7 @@
|
||||||
},
|
},
|
||||||
"camelcase-keys": {
|
"camelcase-keys": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "http://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
|
||||||
"integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
|
"integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -2158,7 +2158,7 @@
|
||||||
},
|
},
|
||||||
"create-hash": {
|
"create-hash": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
|
||||||
"integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
|
"integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -2171,7 +2171,7 @@
|
||||||
},
|
},
|
||||||
"create-hmac": {
|
"create-hmac": {
|
||||||
"version": "1.1.7",
|
"version": "1.1.7",
|
||||||
"resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
|
||||||
"integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
|
"integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -2564,7 +2564,7 @@
|
||||||
},
|
},
|
||||||
"diffie-hellman": {
|
"diffie-hellman": {
|
||||||
"version": "5.0.3",
|
"version": "5.0.3",
|
||||||
"resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
|
||||||
"integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
|
"integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -2628,7 +2628,7 @@
|
||||||
},
|
},
|
||||||
"duplexer": {
|
"duplexer": {
|
||||||
"version": "0.1.1",
|
"version": "0.1.1",
|
||||||
"resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
|
||||||
"integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
|
"integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
@ -2892,7 +2892,7 @@
|
||||||
},
|
},
|
||||||
"events": {
|
"events": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "http://registry.npmjs.org/events/-/events-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
|
||||||
"integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=",
|
"integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
@ -3178,7 +3178,7 @@
|
||||||
},
|
},
|
||||||
"finalhandler": {
|
"finalhandler": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
|
||||||
"integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
|
"integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"debug": "2.6.9",
|
"debug": "2.6.9",
|
||||||
|
@ -3866,7 +3866,7 @@
|
||||||
},
|
},
|
||||||
"get-stream": {
|
"get-stream": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||||
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
|
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
@ -4744,7 +4744,7 @@
|
||||||
},
|
},
|
||||||
"http-errors": {
|
"http-errors": {
|
||||||
"version": "1.6.3",
|
"version": "1.6.3",
|
||||||
"resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
|
||||||
"integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
|
"integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"depd": "~1.1.2",
|
"depd": "~1.1.2",
|
||||||
|
@ -4936,7 +4936,7 @@
|
||||||
},
|
},
|
||||||
"is-builtin-module": {
|
"is-builtin-module": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
|
||||||
"integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
|
"integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -5740,7 +5740,7 @@
|
||||||
},
|
},
|
||||||
"load-json-file": {
|
"load-json-file": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
|
||||||
"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
|
"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -5986,7 +5986,7 @@
|
||||||
},
|
},
|
||||||
"media-typer": {
|
"media-typer": {
|
||||||
"version": "0.3.0",
|
"version": "0.3.0",
|
||||||
"resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||||
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
|
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
|
||||||
},
|
},
|
||||||
"mem": {
|
"mem": {
|
||||||
|
@ -6000,7 +6000,7 @@
|
||||||
},
|
},
|
||||||
"meow": {
|
"meow": {
|
||||||
"version": "3.7.0",
|
"version": "3.7.0",
|
||||||
"resolved": "http://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
|
||||||
"integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
|
"integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -6137,7 +6137,7 @@
|
||||||
},
|
},
|
||||||
"mkdirp": {
|
"mkdirp": {
|
||||||
"version": "0.5.1",
|
"version": "0.5.1",
|
||||||
"resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimist": "0.0.8"
|
"minimist": "0.0.8"
|
||||||
|
@ -6339,7 +6339,7 @@
|
||||||
},
|
},
|
||||||
"ncp": {
|
"ncp": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "http://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
|
||||||
"integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=",
|
"integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
@ -8222,7 +8222,7 @@
|
||||||
},
|
},
|
||||||
"os-tmpdir": {
|
"os-tmpdir": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
||||||
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
|
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
@ -8309,7 +8309,7 @@
|
||||||
},
|
},
|
||||||
"parse-asn1": {
|
"parse-asn1": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
"resolved": "http://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz",
|
||||||
"integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==",
|
"integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -8384,7 +8384,7 @@
|
||||||
},
|
},
|
||||||
"path-is-absolute": {
|
"path-is-absolute": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
|
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
|
||||||
},
|
},
|
||||||
"path-is-inside": {
|
"path-is-inside": {
|
||||||
|
@ -9062,7 +9062,7 @@
|
||||||
},
|
},
|
||||||
"readable-stream": {
|
"readable-stream": {
|
||||||
"version": "2.3.6",
|
"version": "2.3.6",
|
||||||
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
||||||
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
|
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -9581,7 +9581,7 @@
|
||||||
},
|
},
|
||||||
"sha.js": {
|
"sha.js": {
|
||||||
"version": "2.4.11",
|
"version": "2.4.11",
|
||||||
"resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
|
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
|
||||||
"integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
|
"integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -10160,7 +10160,7 @@
|
||||||
},
|
},
|
||||||
"strip-eof": {
|
"strip-eof": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
|
||||||
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
|
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
@ -10252,7 +10252,7 @@
|
||||||
},
|
},
|
||||||
"through": {
|
"through": {
|
||||||
"version": "2.3.8",
|
"version": "2.3.8",
|
||||||
"resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||||
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
|
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
@ -11312,7 +11312,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async": {
|
"async": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "http://registry.npmjs.org/async/-/async-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz",
|
||||||
"integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k="
|
"integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11333,7 +11333,7 @@
|
||||||
},
|
},
|
||||||
"wrap-ansi": {
|
"wrap-ansi": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
|
||||||
"integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
|
"integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
export const PRE_VALIDATION_TEMPLATE = "need-identity-validation";
|
|
|
@ -1,3 +1,3 @@
|
||||||
import { default as Level } from '../../../../shared/AuthenticationLevel';
|
import { default as Level } from "../../../../shared/AuthenticationLevel";
|
||||||
|
|
||||||
export {Level};
|
export { Level };
|
||||||
|
|
|
@ -8,7 +8,7 @@ import UserMessages = require("../../../../../shared/UserMessages");
|
||||||
import { ServerVariables } from "../../ServerVariables";
|
import { ServerVariables } from "../../ServerVariables";
|
||||||
import { AuthenticationSession } from "../../../../types/AuthenticationSession";
|
import { AuthenticationSession } from "../../../../types/AuthenticationSession";
|
||||||
import { GroupsAndEmails } from "../../authentication/backends/GroupsAndEmails";
|
import { GroupsAndEmails } from "../../authentication/backends/GroupsAndEmails";
|
||||||
import {Level} from "../../authentication/Level";
|
import { Level } from "../../authentication/Level";
|
||||||
|
|
||||||
export default function (vars: ServerVariables) {
|
export default function (vars: ServerVariables) {
|
||||||
return function (req: express.Request, res: express.Response)
|
return function (req: express.Request, res: express.Response)
|
||||||
|
@ -65,4 +65,4 @@ export default function (vars: ServerVariables) {
|
||||||
})
|
})
|
||||||
.catch(ErrorReplies.replyWithError200(req, res, vars.logger, UserMessages.AUTHENTICATION_FAILED));
|
.catch(ErrorReplies.replyWithError200(req, res, vars.logger, UserMessages.AUTHENTICATION_FAILED));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,13 +5,10 @@ import objectPath = require("object-path");
|
||||||
import exceptions = require("../../../Exceptions");
|
import exceptions = require("../../../Exceptions");
|
||||||
import { Identity } from "../../../../../types/Identity";
|
import { Identity } from "../../../../../types/Identity";
|
||||||
import { IdentityValidable } from "../../../IdentityValidable";
|
import { IdentityValidable } from "../../../IdentityValidable";
|
||||||
import { PRE_VALIDATION_TEMPLATE } from "../../../IdentityCheckPreValidationTemplate";
|
|
||||||
import Constants = require("../constants");
|
import Constants = require("../constants");
|
||||||
import { IRequestLogger } from "../../../logging/IRequestLogger";
|
import { IRequestLogger } from "../../../logging/IRequestLogger";
|
||||||
import { IUsersDatabase } from "../../../authentication/backends/IUsersDatabase";
|
import { IUsersDatabase } from "../../../authentication/backends/IUsersDatabase";
|
||||||
|
|
||||||
export const TEMPLATE_NAME = "password-reset-form";
|
|
||||||
|
|
||||||
export default class PasswordResetHandler implements IdentityValidable {
|
export default class PasswordResetHandler implements IdentityValidable {
|
||||||
private logger: IRequestLogger;
|
private logger: IRequestLogger;
|
||||||
private usersDatabase: IUsersDatabase;
|
private usersDatabase: IUsersDatabase;
|
||||||
|
@ -52,7 +49,8 @@ export default class PasswordResetHandler implements IdentityValidable {
|
||||||
}
|
}
|
||||||
|
|
||||||
preValidationResponse(req: express.Request, res: express.Response) {
|
preValidationResponse(req: express.Request, res: express.Response) {
|
||||||
res.render(PRE_VALIDATION_TEMPLATE);
|
res.status(204);
|
||||||
|
res.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
postValidationInit(req: express.Request) {
|
postValidationInit(req: express.Request) {
|
||||||
|
@ -60,7 +58,8 @@ export default class PasswordResetHandler implements IdentityValidable {
|
||||||
}
|
}
|
||||||
|
|
||||||
postValidationResponse(req: express.Request, res: express.Response) {
|
postValidationResponse(req: express.Request, res: express.Response) {
|
||||||
res.render(TEMPLATE_NAME);
|
res.status(204);
|
||||||
|
res.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
mailSubject(): string {
|
mailSubject(): string {
|
||||||
|
|
|
@ -4,7 +4,6 @@ import BluebirdPromise = require("bluebird");
|
||||||
|
|
||||||
import { Identity } from "../../../../../../types/Identity";
|
import { Identity } from "../../../../../../types/Identity";
|
||||||
import { IdentityValidable } from "../../../../IdentityValidable";
|
import { IdentityValidable } from "../../../../IdentityValidable";
|
||||||
import { PRE_VALIDATION_TEMPLATE } from "../../../../IdentityCheckPreValidationTemplate";
|
|
||||||
import Constants = require("../constants");
|
import Constants = require("../constants");
|
||||||
import ErrorReplies = require("../../../../ErrorReplies");
|
import ErrorReplies = require("../../../../ErrorReplies");
|
||||||
import { AuthenticationSessionHandler } from "../../../../AuthenticationSessionHandler";
|
import { AuthenticationSessionHandler } from "../../../../AuthenticationSessionHandler";
|
||||||
|
@ -64,7 +63,8 @@ export default class RegistrationHandler implements IdentityValidable {
|
||||||
}
|
}
|
||||||
|
|
||||||
preValidationResponse(req: express.Request, res: express.Response) {
|
preValidationResponse(req: express.Request, res: express.Response) {
|
||||||
res.render(PRE_VALIDATION_TEMPLATE);
|
res.status(204);
|
||||||
|
res.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
postValidationInit(req: express.Request) {
|
postValidationInit(req: express.Request) {
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
|
|
||||||
import BluebirdPromise = require("bluebird");
|
import BluebirdPromise = require("bluebird");
|
||||||
import express = require("express");
|
import express = require("express");
|
||||||
import objectPath = require("object-path");
|
|
||||||
|
|
||||||
import { IdentityValidable } from "../../../../IdentityValidable";
|
import { IdentityValidable } from "../../../../IdentityValidable";
|
||||||
import { Identity } from "../../../../../../types/Identity";
|
import { Identity } from "../../../../../../types/Identity";
|
||||||
import { PRE_VALIDATION_TEMPLATE } from "../../../../IdentityCheckPreValidationTemplate";
|
|
||||||
import FirstFactorValidator = require("../../../../FirstFactorValidator");
|
import FirstFactorValidator = require("../../../../FirstFactorValidator");
|
||||||
import { AuthenticationSessionHandler } from "../../../../AuthenticationSessionHandler";
|
import { AuthenticationSessionHandler } from "../../../../AuthenticationSessionHandler";
|
||||||
import { IRequestLogger } from "../../../../logging/IRequestLogger";
|
import { IRequestLogger } from "../../../../logging/IRequestLogger";
|
||||||
|
@ -13,8 +11,6 @@ import { IRequestLogger } from "../../../../logging/IRequestLogger";
|
||||||
const CHALLENGE = "u2f-register";
|
const CHALLENGE = "u2f-register";
|
||||||
const MAIL_SUBJECT = "Register your security key with Authelia";
|
const MAIL_SUBJECT = "Register your security key with Authelia";
|
||||||
|
|
||||||
const POST_VALIDATION_TEMPLATE_NAME = "u2f-register";
|
|
||||||
|
|
||||||
|
|
||||||
export default class RegistrationHandler implements IdentityValidable {
|
export default class RegistrationHandler implements IdentityValidable {
|
||||||
private logger: IRequestLogger;
|
private logger: IRequestLogger;
|
||||||
|
@ -55,7 +51,8 @@ export default class RegistrationHandler implements IdentityValidable {
|
||||||
}
|
}
|
||||||
|
|
||||||
preValidationResponse(req: express.Request, res: express.Response) {
|
preValidationResponse(req: express.Request, res: express.Response) {
|
||||||
res.render(PRE_VALIDATION_TEMPLATE);
|
res.status(204);
|
||||||
|
res.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
postValidationInit(req: express.Request) {
|
postValidationInit(req: express.Request) {
|
||||||
|
@ -63,7 +60,8 @@ export default class RegistrationHandler implements IdentityValidable {
|
||||||
}
|
}
|
||||||
|
|
||||||
postValidationResponse(req: express.Request, res: express.Response) {
|
postValidationResponse(req: express.Request, res: express.Response) {
|
||||||
res.render(POST_VALIDATION_TEMPLATE_NAME);
|
res.status(204);
|
||||||
|
res.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
mailSubject(): string {
|
mailSubject(): string {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as Express from 'express';
|
import * as Express from "express";
|
||||||
import * as Bluebird from 'bluebird';
|
import * as Bluebird from "bluebird";
|
||||||
import { ServerVariables } from "../../ServerVariables";
|
import { ServerVariables } from "../../ServerVariables";
|
||||||
import { AuthenticationSessionHandler } from '../../AuthenticationSessionHandler';
|
import { AuthenticationSessionHandler } from "../../AuthenticationSessionHandler";
|
||||||
|
|
||||||
export default function (vars: ServerVariables) {
|
export default function (vars: ServerVariables) {
|
||||||
return function (req: Express.Request, res: Express.Response): Bluebird<void> {
|
return function (req: Express.Request, res: Express.Response): Bluebird<void> {
|
||||||
|
@ -10,7 +10,7 @@ export default function (vars: ServerVariables) {
|
||||||
res.json({
|
res.json({
|
||||||
username: authSession.userid,
|
username: authSession.userid,
|
||||||
authentication_level: authSession.authentication_level
|
authentication_level: authSession.authentication_level
|
||||||
})
|
});
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,92 +0,0 @@
|
||||||
|
|
||||||
import BluebirdPromise = require("bluebird");
|
|
||||||
import request = require("request");
|
|
||||||
import assert = require("assert");
|
|
||||||
import Endpoints = require("../../shared/api");
|
|
||||||
|
|
||||||
declare module "request" {
|
|
||||||
export interface RequestAPI<TRequest extends Request,
|
|
||||||
TOptions extends CoreOptions,
|
|
||||||
TUriUrlOptions> {
|
|
||||||
getAsync(uri: string, options?: RequiredUriUrl): BluebirdPromise<RequestResponse>;
|
|
||||||
getAsync(uri: string): BluebirdPromise<RequestResponse>;
|
|
||||||
getAsync(options: RequiredUriUrl & CoreOptions): BluebirdPromise<RequestResponse>;
|
|
||||||
|
|
||||||
postAsync(uri: string, options?: CoreOptions): BluebirdPromise<RequestResponse>;
|
|
||||||
postAsync(uri: string): BluebirdPromise<RequestResponse>;
|
|
||||||
postAsync(options: RequiredUriUrl & CoreOptions): BluebirdPromise<RequestResponse>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const requestAsync: typeof request = BluebirdPromise.promisifyAll(request) as typeof request;
|
|
||||||
|
|
||||||
export = function (port: number) {
|
|
||||||
const PORT = port;
|
|
||||||
const BASE_URL = "http://localhost:" + PORT;
|
|
||||||
|
|
||||||
function execute_totp(jar: request.CookieJar, token: string) {
|
|
||||||
return requestAsync.postAsync({
|
|
||||||
url: BASE_URL + Endpoints.SECOND_FACTOR_TOTP_POST,
|
|
||||||
jar: jar,
|
|
||||||
form: {
|
|
||||||
token: token
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function execute_u2f_authentication(jar: request.CookieJar) {
|
|
||||||
return requestAsync.getAsync({
|
|
||||||
url: BASE_URL + Endpoints.SECOND_FACTOR_U2F_SIGN_REQUEST_GET,
|
|
||||||
jar: jar
|
|
||||||
})
|
|
||||||
.then(function (res: request.RequestResponse) {
|
|
||||||
assert.equal(res.statusCode, 200);
|
|
||||||
return requestAsync.postAsync({
|
|
||||||
url: BASE_URL + Endpoints.SECOND_FACTOR_U2F_SIGN_POST,
|
|
||||||
jar: jar,
|
|
||||||
form: {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function execute_verification(jar: request.CookieJar) {
|
|
||||||
return requestAsync.getAsync({ url: BASE_URL + Endpoints.VERIFY_GET, jar: jar });
|
|
||||||
}
|
|
||||||
|
|
||||||
function execute_login(jar: request.CookieJar) {
|
|
||||||
return requestAsync.getAsync({ url: BASE_URL + Endpoints.FIRST_FACTOR_GET, jar: jar });
|
|
||||||
}
|
|
||||||
|
|
||||||
function execute_first_factor(jar: request.CookieJar) {
|
|
||||||
return requestAsync.postAsync({
|
|
||||||
url: BASE_URL + Endpoints.FIRST_FACTOR_POST,
|
|
||||||
jar: jar,
|
|
||||||
form: {
|
|
||||||
username: "test_ok",
|
|
||||||
password: "password"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function execute_failing_first_factor(jar: request.CookieJar) {
|
|
||||||
return requestAsync.postAsync({
|
|
||||||
url: BASE_URL + Endpoints.FIRST_FACTOR_POST,
|
|
||||||
jar: jar,
|
|
||||||
form: {
|
|
||||||
username: "test_nok",
|
|
||||||
password: "password"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
login: execute_login,
|
|
||||||
verify: execute_verification,
|
|
||||||
u2f_authentication: execute_u2f_authentication,
|
|
||||||
first_factor: execute_first_factor,
|
|
||||||
failing_first_factor: execute_failing_first_factor,
|
|
||||||
totp: execute_totp,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
|
@ -2,6 +2,6 @@ enum Level {
|
||||||
NOT_AUTHENTICATED = 0,
|
NOT_AUTHENTICATED = 0,
|
||||||
ONE_FACTOR = 1,
|
ONE_FACTOR = 1,
|
||||||
TWO_FACTOR = 2
|
TWO_FACTOR = 2
|
||||||
};
|
}
|
||||||
|
|
||||||
export default Level;
|
export default Level;
|
||||||
|
|
|
@ -244,10 +244,10 @@ export const FIRST_FACTOR_POST = "/api/firstfactor";
|
||||||
* @apiName State
|
* @apiName State
|
||||||
* @apiGroup Authentication
|
* @apiGroup Authentication
|
||||||
* @apiVersion 1.0.0
|
* @apiVersion 1.0.0
|
||||||
*
|
*
|
||||||
* @apiSuccess (Success 200) A dict containing the username and the authentication
|
* @apiSuccess (Success 200) A dict containing the username and the authentication
|
||||||
* level
|
* level
|
||||||
*
|
*
|
||||||
* @apiDescription Get the authentication state of the user based on the cookie.
|
* @apiDescription Get the authentication state of the user based on the cookie.
|
||||||
*/
|
*/
|
||||||
export const STATE_GET = "/api/state";
|
export const STATE_GET = "/api/state";
|
||||||
|
|
Loading…
Reference in New Issue
Block a user